Rebex FileServer calls Seek whilst CanSeek is false

0 votes
asked Oct 5 by MarcelVanDerHeijden (120 points)

Hi,

I'm using the Rebex File Server Component and I implemented my own file-system-provider with custom file-streams (which push or pull the data from another service).
This used to work, but since a couple of Rebex versions (not sure exactly since what version) this stopped working.

I do not supported seeking in the file (CanSeek is set to false. I can't support this, since the used services also do not support this).
But, when a file is begin uploaded, the Seek function is being called anyway. For now, all calls to Seek don't really have a purpose (i.e. seeking to the current position). The current implementation I have seems to handle these cases.

Unfortunately, there is no way for me to verify that this handles all calls to Seek correctly and definitely have no way to ensure that will handles all situations correctly when I update Rebex to a new version.

public override bool CanSeek => false;

public override long Seek(long offset, SeekOrigin origin)
{
if (Length == 0)
    return 0;
if (origin == SeekOrigin.End && offset == 0)
    return Length;
throw new NotSupportedException();
}

Can you respect the CanSeek property and not call this function with this is not supported by the stream?

Applies to: Rebex SFTP
commented Oct 5 by Lukas Pokorny (124,610 points)
edited Oct 5 by Lukas Pokorny
Hi, which version of Rebex File Server do you use? Does this still occur with the latest version? We fixed one issue related to non-seekable streams earlier this year: https://www.rebex.net/file-server/history.aspx#R5.3
commented Oct 5 by MarcelVanDerHeijden (120 points)
I currently use the latest version of Rebex.
In the history, it says:

File System: Tweaked handling of non-seekable streams supplied to NodeContent.CreateReadOnlyContent method.

The issue I face is with stream supplied to NodeContent.CreateImmediateWriteContent.
commented Oct 5 by Lukas Pokorny (124,610 points)
Oh, thanks, you are right. We'll look into this!

1 Answer

0 votes
answered Oct 5 by renestein (3,950 points)

Hi,
I am trying to reproduce the problem, but the following code works and does not call Seek on the SFTP server.

Do you see any difference?

FileSystemProvider returns ImmediateWriteContent.

 var provider = new ImplicitProtocolFileSystemReadWriteProviderMock()
                   {
                       ReturnContentType = FileSystemRwProviderMockBase.ImplementorContentType.ImmediateWriteContent
                   };


//ImplicitProtocolFileSystemReadWriteProviderMock
 protected override NodeContent GetContent(NodeBase node, NodeContentParameters contentParameters)
            {

                switch (ReturnContentType)
                {

                    case ImplementorContentType.ImmediateWriteContent:
                        {
                            return NodeContent.CreateImmediateWriteContent(Storage[node].Content.GetStream());
                        }
               }
             }

Rebex SFTP client uploads file.

sftp.PutFile(TestUtils.CreateReadOnlyStream(DataGenerator.GetRandomData(256)), fileName);

This code does not call Seek method on the Stream.
I have wrapped "immediate stream", and as you can see, an exception is raised when the Seek method is called.

var wrapperStream = DelegateStream.FromExistingStream(stream, mapping =>
            {
                mapping.SeekFunc = (l, origin) => { throw new ApplicationException("Seek called"); };

                return mapping;
            });
commented Oct 5 by MarcelVanDerHeijden (120 points)
It's hard to compare the code, the test-case seems to be the same.

I did do a bit more analysis on my side. I don't have a reproduction case in c#, I'm only testing it using sftp-clients. What I can tell you:
- I do not have this issue using FileZilla.
- I do not have this issue using Rebex SFTP Client
- I do have this issue with WinSCP.

The call to seek is always as follows: Offet = 0, SeekOrigin.End
I get this call before the first byte is send to the stream followed by a call after every 32768 bytes (so at a total amount of bytes written to the stream of 0, 32768, 65536, 98304, ...)

If it helps, below is the stack-trace when the Seek is called.

   at Empirion.FileServer.Sftp.Models.SftpWriteStream.Seek(Int64 offset, SeekOrigin origin)
   at mwksu.kqmgx.iislt.dvmxq(riwhi p0, Int64 p1)
   at mwksu.xtjrq.hvury.kswzo(riwhi p0, Int64 p1)
   at mwksu.xepcn.ljmpl(dszdt p0, Int32 p1)
   at mwksu.xepcn.mynxn(dszdt p0)
   at mwksu.hnlwy.omgui(Object p0)
   at mwksu.xatng.pwrda.mqfxr(Object p0)
   at System.Threading.QueueUserWorkItemCallback.WaitCallback_Context(Object state)
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem()
   at System.Threading.ThreadPoolWorkQueue.Dispatch()
   at System.Threading._ThreadPoolWaitCallback.PerformWaitCallback()
commented Oct 5 by renestein (3,950 points)
Thanks for the additional information. I will try the WinSCP client tomorrow.
commented Oct 6 by Lukas Pokorny (124,610 points)
Please try lowering maximum supported SFTP version to 4. Does the issue still persist then?

    var server = new FileServer();
    server.Settings.SftpMaxVersion = 4;

(It looks like the cause of the issue is that WinSCP opens the file with SSH_FXF_ACCESS_APPEND_DATA or ACE4_APPEND_DATA flags when SFTP v5 is enabled, which results in Rebex File Server calling Seek(FileSeekOrigin.End, 0) before each Write call. We'll see what we can do about this.)
commented Oct 6 by MarcelVanDerHeijden (120 points)
This does resolve the issue.

I look forward to the actual fix, as I would prefer to use the latest SFTP version
commented Oct 7 by Lukas Pokorny (124,610 points)
I sent a link to a hotfix to your e-mail address. Please give it a try and let us know whether it resolves the issue.
commented Oct 7 by MarcelVanDerHeijden (120 points)
This hotfix has resolved the issue
...