8000 Merge pull request #332 from peachfinance/Fstat-stat-options · etherscan-io/sftp@5616182 · GitHub
[go: up one dir, main page]

Skip to content {"props":{"docsUrl":"https://docs.github.com/get-started/accessibility/keyboard-shortcuts"}}

Commit 5616182

Browse files
authored
Merge pull request pkg#332 from peachfinance/Fstat-stat-options
Added a ClientOption to determine whetehr to use Fstat or Stat when File.WriteTo is being called to support strange behaviour on some servers
2 parents a5f5a4c + 77a4076 commit 5616182

File tree

2 files changed

+54
-4
lines changed

2 files changed

+54
-4
lines changed

client.go

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

54+
// UseFstat sets whether to use Fstat or Stat when File.WriteTo is called
55+
// (usually when copying files).
56+
// Some servers limit the amount of open files and calling Stat after opening
57+
// the file will throw an error From the server. Setting this flag will call
58+
// Fstat instead of Stat which is suppose to be called on an open file handle.
59+
//
60+
// It has been found that that with IBM Sterling SFTP servers which have
61+
// "extractability" level set to 1 which means only 1 file can be opened at
62+
// any given time.
63+
//
64+
// If the server you are working with still has an issue with both Stat and
65+
// Fstat calls you can always open a file and read it until the end.
66+
//
67+
// Another reason to read the file until its end and Fstat doesn't work is
68+
// that in some servers, reading a full file will automatically delete the
69+
// file as some of these mainframes map the file to a message in a queue.
70+
// Once the file has been read it will get deleted.
71+
func UseFstat(value bool) ClientOption {
72+
return func(c *Client) error {
73+
c.useFstat = value
74+
return nil
75+
}
76+
}
77+
5478
// MaxPacketUnchecked sets the maximum size of the payload, measured in bytes.
5579
// It accepts sizes larger than the 32768 bytes all servers should support.
5680
// Only use a setting higher than 32768 if your application always connects to
@@ -161,6 +185,7 @@ type Client struct {
161185
maxPacket int // max packet size read or written.
162186
nextid uint32
163187
maxConcurrentRequests int
188+
useFstat bool
164189
}
165190

166191
// Create creates the named file mode 0666 (before umask), truncating it if it
@@ -913,15 +938,26 @@ func (f *File) Read(b []byte) (int, error) {
913938
// maximise throughput for transferring the entire file (especially
914939
// over high latency links).
915940
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
941+
var fileSize uint64
942+
if f.c.useFstat {
943+
fileStat, err := f.c.fstat(f.handle)
944+
if err != nil {
945+
return 0, err
946+
}
947+
fileSize = fileStat.Size
948+
949+
} else {
950+
fi, err := f.c.Stat(f.path)
951+
if err != nil {
952+
return 0, err
953+
}
954+
fileSize = uint64(fi.Size())
919955
}
956+
920957
inFlight := 0
921958
desiredInFlight := 1
922959
offset := f.offset
923960
writeOffset := offset
924-
fileSize := uint64(fi.Size())
925961
// see comment on same line in Read() above
926962
ch := make(chan result, f.c.maxConcurrentRequests+1)
927963
type inflightRead struct {

client_test.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,3 +194,17 @@ func testMaxPacketOption(t *testing.T, o ClientOption, tt packetSizeTest) {
194194
t.Errorf("MaxPacketChecked(%v)\n- want: %v\n- got: %v", tt.size, tt.size, c.maxPacket)
195195
}
196196
}
197+
198+
func testFstatOption(t *testing.T, o ClientOption, value bool) {
199+
var c Client
200+
201+
err := o(&c)
202+
if err == nil && c.useFstat != value {
203+
t.Errorf("UseFStat(%v)\n- want: %v\n- got: %v", value, value, c.useFstat)
204+
}
205+
}
206+
207+
func TestUseFstatChecked(t *testing.T) {
208+
testFstatOption(t, UseFstat(true), true)
209+
testFstatOption(t, UseFstat(false), false)
210+
}

0 commit comments

Comments
 (0)
0