sftp: check for truncated files without an extra backend request

This commit is contained in:
Michael Eischer 2024-05-11 22:08:12 +02:00
parent c6d74458ee
commit eaa3f81d6b

View file

@ -425,7 +425,24 @@ func (r *SFTP) checkNoSpace(dir string, size int64, origErr error) error {
// Load runs fn with a reader that yields the contents of the file at h at the
// given offset.
func (r *SFTP) Load(ctx context.Context, h backend.Handle, length int, offset int64, fn func(rd io.Reader) error) error {
return util.DefaultLoad(ctx, h, length, offset, r.openReader, fn)
return util.DefaultLoad(ctx, h, length, offset, r.openReader, func(rd io.Reader) error {
if length == 0 {
return fn(rd)
}
// there is no direct way to efficiently check whether the file is too short
// rd is already a LimitedReader which can be used to track the number of bytes read
err := fn(rd)
// check the underlying reader to be agnostic to however fn() handles the returned error
_, rderr := rd.Read([]byte{0})
if rderr == io.EOF && rd.(*backend.LimitedReadCloser).N != 0 {
// file is too short
return fmt.Errorf("%w: %v", errTooShort, err)
}
return err
})
}
func (r *SFTP) openReader(_ context.Context, h backend.Handle, length int, offset int64) (io.ReadCloser, error) {
@ -434,18 +451,6 @@ func (r *SFTP) openReader(_ context.Context, h backend.Handle, length int, offse
return nil, err
}
fi, err := f.Stat()
if err != nil {
_ = f.Close()
return nil, err
}
size := fi.Size()
if size < offset+int64(length) {
_ = f.Close()
return nil, errTooShort
}
if offset > 0 {
_, err = f.Seek(offset, 0)
if err != nil {