8000 Added a ClientOption to determine whetehr to use Fstat or Stat when F… · etherscan-io/sftp@09f03e7 · GitHub
[go: up one dir, main page]

Skip to content
8000

Commit 09f03e7

Browse files
committed
Added a ClientOption to determine whetehr to use Fstat or Stat when File.WriteTo is being called to support strange behaviour on some servers
1 parent f3d1308 commit 09f03e7

File tree

1 file changed

+34
-4
lines changed

1 file changed

+34
-4
lines changed

client.go

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,23 @@ func MaxPacketChecked(size int) ClientOption {
5151
}
5252
}
5353

54+
// UseFstat sets whether to use Fstat or Stat when File.WriteTo is called (usually when copying files).
55+
// Some servers limit the amount of open files and calling Stat after opening the file will throw an error
56+
// From the server. Setting this flag will call Fstat instead of Stat which is suppose to be called on an
57+
// open file handle.
58+
//
59+
// From our experience it happens often with IBM Sterling SFTP servers that have "extractability" level
60+
// set to 1 which means only 1 file can be open at any given time.
61+
//
62+
// If the server you are working with still has an issue with both Stat and Fstat calls you can always
63+
// open a file and just loop through multiple Read calls until the file is completely read.
64+
func UseFstat(value bool) ClientOption {
65+
return func(c *Client) error {
66+
c.useFstat = value
67+
return nil
68+
}
69+
}
70+
5471
// MaxPacketUnchecked sets the maximum size of the payload, measured in bytes.
5572
// It accepts sizes larger than the 32768 bytes all servers should support.
5673
// Only use a setting higher than 32768 if your application always connects to
@@ -161,6 +178,7 @@ type Client struct {
161178
maxPacket int // max packet size read or written.
162179
nextid uint32
163180
maxConcurrentRequests int
181+
useFstat bool
164182
}
165183

166184
// Create creates the named file mode 0666 (before umask), truncating it if it
@@ -913,15 +931,27 @@ func (f *File) Read(b []byte) (int, error) {
913931
// maximise throughput for transferring the entire file (especially
914932
// over high latency links).
915933
func (f *File) WriteTo(w io.Writer) (int64, error) {
916-
fi, err := f.c.Stat(f.path)
917-
if err != nil {
918-
return 0, err
934+
var err error
935+
fileSize := uint64(0)
936+
if f.c.useFstat {
937+
var fileStat *FileStat
938+
if fileStat, err = f.c.fstat(f.handle); err != nil {
939+
return 0, err
940+
}
941+
fileSize = uint64(fileStat.Size)
942+
943+
} else {
944+
var fi os.FileInfo
945+
if fi, err = f.c.Stat(f.path); err != nil {
946+
return 0, err
947+
}
948+
fileSize = uint64(fi.Size())
919949
}
950+
920951
inFlight := 0
921952
desiredInFlight := 1
922953
offset := f.offset
923954
writeOffset := offset
924-
fileSize := uint64(fi.Size())
925955
// see comment on same line in Read() above
926956
ch := make(chan result, f.c.maxConcurrentRequests+1)
927957
type inflightRead struct {

0 commit comments

Comments
 (0)
0