diff --git a/backend/cache/object.go b/backend/cache/object.go index 9de7b3b7d..87395db8a 100644 --- a/backend/cache/object.go +++ b/backend/cache/object.go @@ -14,6 +14,7 @@ import ( "github.com/ncw/rclone/fs" "github.com/ncw/rclone/fs/hash" + "github.com/ncw/rclone/lib/readers" ) // Object is a generic file like object that stores basic information about it @@ -219,19 +220,21 @@ func (o *Object) Open(options ...fs.OpenOption) (io.ReadCloser, error) { var err error cacheReader := NewObjectHandle(o) + var offset, limit int64 for _, option := range options { switch x := option.(type) { case *fs.SeekOption: - _, err = cacheReader.Seek(x.Offset, os.SEEK_SET) + offset, limit = x.Offset, 0 case *fs.RangeOption: - _, err = cacheReader.Seek(x.Start, os.SEEK_SET) + offset, limit = x.Decode(o.Size()) } + _, err = cacheReader.Seek(offset, os.SEEK_SET) if err != nil { - return cacheReader, err + return nil, err } } - return cacheReader, nil + return readers.NewLimitedReadCloser(cacheReader, limit), nil } // Update will change the object data diff --git a/lib/readers/limited.go b/lib/readers/limited.go new file mode 100644 index 000000000..ad28763ed --- /dev/null +++ b/lib/readers/limited.go @@ -0,0 +1,22 @@ +package readers + +import "io" + +// LimitedReadCloser adds io.Closer to io.LimitedReader. Create one with NewLimitedReadCloser +type LimitedReadCloser struct { + *io.LimitedReader + io.Closer +} + +// NewLimitedReadCloser returns a LimitedReadCloser wrapping rc to +// limit it to reading limit bytes. If limit == 0 then it does not +// wrap rc, it just returns it. +func NewLimitedReadCloser(rc io.ReadCloser, limit int64) (lrc io.ReadCloser) { + if limit == 0 { + return rc + } + return &LimitedReadCloser{ + LimitedReader: &io.LimitedReader{R: rc, N: limit}, + Closer: rc, + } +}