Repository: C2FO/vfs (go)
Issue: read from 13 for 32768 from 32785 not supported. (SSH_FX_FAILURE) using sftp backend
Getting
sftp: "read from 13 for 32768 from 32785 not supported." (SSH_FX_FAILURE)
when doing file.CopyTO or file.MoveTo on some servers (works fine on openssh sftp server).

Problems stems of cached file handle when calling Seek which use RW mode.  Then later Reads end up failing on some servers.

Should roll back seek validation on CopyTo and MoveTo funcs until a more robust solution is found.


Pull request description: Rollback Seek validation on copy/move
Getting
sftp: "read from 13 for 32768 from 32785 not supported." (SSH_FX_FAILURE)
when doing file.CopyTO or file.MoveTo on some servers (works fine on openssh sftp server).

Problems stems of cached file handle when calling Seek which use RW mode. Then later Reads end up failing on some servers.

Should roll back seek validation on CopyTo and MoveTo funcs until a more robust solution is found.

fixes #100 

Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index a1d7cd7..6d9ef10 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
 ### Changed
 - Modified S3 file.go so that on the initial read when the remote file is downloaded, a temporary file is locally created
 using concurrent go routines to download parts of the file vs. a single request to download the whole object
+### Fixed
+- Fixed #100 Rolled back Seek validation before Copy or Move in SFTP backend due to bug on some SFTP servers and how we cache open "file handles"
 
 ## [5.9.0] - 2021-09-07
 ### Added
diff --git a/backend/sftp/file.go b/backend/sftp/file.go
index 63c7089..554c71b 100644
--- a/backend/sftp/file.go
+++ b/backend/sftp/file.go
@@ -7,7 +7,6 @@ import (
 	"time"
 
 	"github.com/c2fo/vfs/v5"
-	"github.com/c2fo/vfs/v5/backend"
 	"github.com/c2fo/vfs/v5/utils"
 )
 
@@ -137,9 +136,10 @@ func (f *File) Location() vfs.Location {
 // we'll do a an io.Copy to the destination file then delete source file.
 func (f *File) MoveToFile(t vfs.File) error {
 	// validate seek is at 0,0 before doing copy
-	if err := backend.ValidateCopySeekPosition(f); err != nil {
-		return err
-	}
+	// TODO: Fix this later
+	// if err := backend.ValidateCopySeekPosition(f); err != nil {
+	//	  return err
+	// }
 	// sftp rename if vfs is sftp and for the same user/host
 	if f.fileSystem.Scheme() == t.Location().FileSystem().Scheme() &&
 		f.Authority.User == t.(*File).Authority.User &&
@@ -187,9 +187,10 @@ func (f *File) MoveToLocation(location vfs.Location) (vfs.File, error) {
 // CopyToFile puts the contents of File into the targetFile passed.
 func (f *File) CopyToFile(file vfs.File) error {
 	// validate seek is at 0,0 before doing copy
-	if err := backend.ValidateCopySeekPosition(f); err != nil {
-		return err
-	}
+	// TODO: Fix this later
+	// if err := backend.ValidateCopySeekPosition(f); err != nil {
+	//  	return err
+	// }
 
 	fileBufferSize := 0
 


Test patch:
diff --git a/backend/sftp/file_test.go b/backend/sftp/file_test.go
index 955278f..f9cdbaf 100644
--- a/backend/sftp/file_test.go
+++ b/backend/sftp/file_test.go
@@ -222,7 +222,6 @@ func (ts *fileTestSuite) TestCopyToFile() {
 
 	sourceSftpFile := &mocks.SFTPFile{}
 
-	sourceSftpFile.On("Seek", int64(0), 1).Return(int64(0), nil)
 	sourceSftpFile.On("Read", mock.Anything).Return(len(content), nil).Once()
 	sourceSftpFile.On("Read", mock.Anything).Return(0, io.EOF).Once()
 	sourceSftpFile.On("Close").Return(nil).Once()
@@ -278,7 +277,6 @@ func (ts *fileTestSuite) TestCopyToFileBuffered() {
 
 	sourceSftpFile := &mocks.SFTPFile{}
 
-	sourceSftpFile.On("Seek", int64(0), 1).Return(int64(0), nil)
 	sourceSftpFile.On("Read", mock.Anything).Return(len(content), nil).Once()
 	sourceSftpFile.On("Read", mock.Anything).Return(0, io.EOF).Once()
 	sourceSftpFile.On("Close").Return(nil).Once()
@@ -336,7 +334,6 @@ func (ts *fileTestSuite) TestCopyToFileEmpty() {
 	sourceClient := &mocks.Client{}
 
 	sourceSftpFile := &mocks.SFTPFile{}
-	sourceSftpFile.On("Seek", int64(0), 1).Return(int64(0), nil)
 	sourceSftpFile.On("Read", mock.Anything).Return(0, io.EOF).Once()
 	sourceSftpFile.On("Close").Return(nil).Once()
 
@@ -393,7 +390,6 @@ func (ts *fileTestSuite) TestCopyToFileEmptyBuffered() {
 	sourceClient := &mocks.Client{}
 
 	sourceSftpFile := &mocks.SFTPFile{}
-	sourceSftpFile.On("Seek", int64(0), 1).Return(int64(0), nil)
 	sourceSftpFile.On("Read", mock.Anything).Return(0, io.EOF).Once()
 	sourceSftpFile.On("Close").Return(nil).Once()
 
@@ -450,7 +446,6 @@ func (ts *fileTestSuite) TestCopyToLocation() {
 	sourceClient := &mocks.Client{}
 
 	sourceSftpFile := &mocks.SFTPFile{}
-	sourceSftpFile.On("Seek", int64(0), 1).Return(int64(0), nil)
 	sourceSftpFile.On("Read", mock.Anything).Return(len(content), nil).Once()
 	sourceSftpFile.On("Read", mock.Anything).Return(0, io.EOF).Once()
 	sourceSftpFile.On("Close").Return(nil).Once()
@@ -511,7 +506,6 @@ func (ts *fileTestSuite) TestMoveToFile_differentAuthority() {
 	sourceClient.On("Remove", mock.Anything).Return(nil).Once()
 
 	sourceSftpFile := &mocks.SFTPFile{}
-	sourceSftpFile.On("Seek", int64(0), 1).Return(int64(0), nil)
 	sourceSftpFile.On("Read", mock.Anything).Return(len(content), nil).Once()
 	sourceSftpFile.On("Read", mock.Anything).Return(0, io.EOF).Once()
 	sourceSftpFile.On("Close").Return(nil).Once()
@@ -616,7 +610,6 @@ func (ts *fileTestSuite) TestMoveToLocation() {
 	sourceClient.On("Remove", mock.Anything).Return(nil).Once()
 
 	sourceSftpFile := &mocks.SFTPFile{}
-	sourceSftpFile.On("Seek", int64(0), 1).Return(int64(0), nil)
 	sourceSftpFile.On("Read", mock.Anything).Return(len(content), nil).Once()
 	sourceSftpFile.On("Read", mock.Anything).Return(0, io.EOF).Once()
 	sourceSftpFile.On("Close").Return(nil).Once()