forked from TrueCloudLab/restic
sftp: check for truncated files without an extra backend request
This commit is contained in:
parent
c6d74458ee
commit
eaa3f81d6b
1 changed files with 18 additions and 13 deletions
|
@ -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
|
// Load runs fn with a reader that yields the contents of the file at h at the
|
||||||
// given offset.
|
// given offset.
|
||||||
func (r *SFTP) Load(ctx context.Context, h backend.Handle, length int, offset int64, fn func(rd io.Reader) error) error {
|
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) {
|
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
|
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 {
|
if offset > 0 {
|
||||||
_, err = f.Seek(offset, 0)
|
_, err = f.Seek(offset, 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
Loading…
Reference in a new issue