0

I'm trying to read a file from an SMB server using .net7 api and SMBLibrary, but the read fail with null data and the status :"STATUS_END_OF_FILE". I want to get the stream data to upload it to an s3 aws bucket.

My code is as following(not completed/optimized yet..):

client = new SMB2Client();
bool isConnected = client.Connect("xxxxxxxxxxx", SMBTransportType.DirectTCPTransport);
if (isConnected)
{
   NTStatus status = client.Login(string. Empty, "xxxxxxxxxx", "xxxxxxxx");
   if (status == NTStatus.STATUS_SUCCESS)
   {
     //List<string> shares = client.ListShares(out status);
     var folderPath = "folder1\\folder2\\folder3";
     var shareName = "share";

     ISMBFileStore fileStore = client.TreeConnect(shareName: shareName, out status);
     if (status == NTStatus.STATUS_SUCCESS)
     {
       object directoryHandle;
       FileStatus fileStatus;
       status = fileStore.CreateFile(out directoryHandle, out fileStatus, "", AccessMask.GENERIC_READ, 0, ShareAccess.Read | ShareAccess.Write | ShareAccess.Delete, CreateDisposition.FILE_OPEN, CreateOptions.FILE_DIRECTORY_FILE, null);
       status = fileStore.CreateFile(out directoryHandle, out fileStatus, folderPath, AccessMask.GENERIC_READ, 0, ShareAccess.Read, CreateDisposition.FILE_OPEN, CreateOptions.FILE_DIRECTORY_FILE, null);
        status = fileStore.CreateFile(out directoryHandle, out fileStatus, "file1.pdf", AccessMask.GENERIC_READ | AccessMask.SYNCHRONIZE, FileAttributes.Normal, ShareAccess.Read, CreateDisposition.FILE_OPEN, CreateOptions.FILE_NON_DIRECTORY_FILE | CreateOptions.FILE_SYNCHRONOUS_IO_ALERT, null);

        if (status == NTStatus.STATUS_SUCCESS)
        {
           MemoryStream stream = new MemoryStream();
           byte[] data;
           long bytesRead = 0;
           while (true)
           {
              status = fileStore.ReadFile(out data, directoryHandle, bytesRead, (int) client.MaxReadSize);
              //returned status :  STATUS_END_OF_FILE
2
  • What do you mean by SMB Server and why are you using SMB2Client ? All Windows versions since 2012 use SMB v3. As long as your application runs on Windows or a correctly configured Linux box, you can use File methods to read remote files, the same way you would with local files. There's no need for usernames and passwords that could leak because access uses the current process's account. Commented Nov 27, 2023 at 11:58
  • thank Kanavos you for your comment, my application is executed on a docker container inside an aws ec2 Linux, and I have to access a Windows share and an FSX server from this Linux machine, something which is not native for Linux therefore the use of the SMBLibrary library or mount the share on Linux and giving rights to docker (this second solution is not recommended by those responsible for the infrastructure) Commented Nov 27, 2023 at 13:11

2 Answers 2

-1

In the official repository has an example of reading file. And do not forget when you write a stream in a file, set stream position in 0. Because of this, I spent a lot of time looking for a problem

client = new SMB2Client();
bool isConnected = client.Connect("xxxxxxxxxxx", SMBTransportType.DirectTCPTransport);
if (isConnected)
{
  NTStatus status = client.Login(string.Empty, "xxxxxxxxxx", "xxxxxxxx");
  if (status == NTStatus.STATUS_SUCCESS)
  {
    //List<string> shares = client.ListShares(out status);
    var folderPath = "folder1\\folder2\\folder3";
    var shareName = "share";

    ISMBFileStore fileStore = client.TreeConnect(shareName: shareName, out status);
    if (status == NTStatus.STATUS_SUCCESS)
    {
      object directoryHandle;
      FileStatus fileStatus;
      status = fileStore.CreateFile(out directoryHandle, out fileStatus, "", AccessMask.GENERIC_READ, 0, ShareAccess.Read | ShareAccess.Write | ShareAccess.Delete, CreateDisposition.FILE_OPEN, CreateOptions.FILE_DIRECTORY_FILE, null);
      status = fileStore.CreateFile(out directoryHandle, out fileStatus, folderPath, AccessMask.GENERIC_READ, 0, ShareAccess.Read, CreateDisposition.FILE_OPEN, CreateOptions.FILE_DIRECTORY_FILE, null);
      status = fileStore.CreateFile(out directoryHandle, out fileStatus, "file1.pdf", AccessMask.GENERIC_READ | AccessMask.SYNCHRONIZE, FileAttributes.Normal, ShareAccess.Read, CreateDisposition.FILE_OPEN, CreateOptions.FILE_NON_DIRECTORY_FILE | CreateOptions.FILE_SYNCHRONOUS_IO_ALERT, null);

      if (status == NTStatus.STATUS_SUCCESS)
      {
        MemoryStream stream = new MemoryStream();
        byte[] data;
        long bytesRead = 0;
        while (true)
        {
          status = fileStore.ReadFile(out data, directoryHandle, bytesRead, (int)client.MaxReadSize);
          if (status != NTStatus.STATUS_SUCCESS && status != NTStatus.STATUS_END_OF_FILE)
          {
            throw new Exception("Failed to read from file");
          }

          if (status == NTStatus.STATUS_END_OF_FILE || data.Length == 0)
          {
            break;
          }
          bytesRead += data.Length;
          stream.Write(data, 0, data.Length);
        }

        stream.Position = 0;
        //create file code
      }

      status = fileStore.CloseFile(fileHandle);
      status = fileStore.Disconnect();
    }
  }
  
  client.Disconnect();
}
Sign up to request clarification or add additional context in comments.

2 Comments

Please include the relevant code in your answer, instead of just linking to an external repo. See this meta post.
That's not an example at all. It's an incomplete Github issue caused by programmer error. The call to ReadFile is identical to the question's code. The repo does have examples here.
-1

Looks like your server does not deal well with (int)client.MaxReadSize as minimum read size,

you may want to obtain the file size in advance, set remainingFileLength to it, and then use Math.Max((int)client.MaxReadSize, remainingFileLength)

for each read.

Edit: My understanding from the GitHub issue was that everything was working correctly and that the stream was not read correctly by the user (The stream position was set to the end of the stream)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.