mirror of
https://github.com/rclone/rclone.git
synced 2026-01-04 09:33:36 +00:00
Add options for Open and implement Range for all remotes
This commit is contained in:
@@ -4,6 +4,7 @@ package crypt
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"path"
|
||||
"sync"
|
||||
|
||||
@@ -297,12 +298,59 @@ func (o *Object) Hash(hash fs.HashType) (string, error) {
|
||||
}
|
||||
|
||||
// Open opens the file for read. Call Close() on the returned io.ReadCloser
|
||||
func (o *Object) Open() (io.ReadCloser, error) {
|
||||
func (o *Object) Open(options ...fs.OpenOption) (io.ReadCloser, error) {
|
||||
var offset int64
|
||||
for _, option := range options {
|
||||
switch x := option.(type) {
|
||||
case *fs.SeekOption:
|
||||
offset = x.Offset
|
||||
default:
|
||||
if option.Mandatory() {
|
||||
fs.Log(o, "Unsupported mandatory option: %v", option)
|
||||
}
|
||||
}
|
||||
}
|
||||
in, err := o.Object.Open()
|
||||
if err != nil {
|
||||
return in, err
|
||||
return nil, err
|
||||
}
|
||||
return o.f.cipher.DecryptData(in)
|
||||
|
||||
// This reads the header and checks it is OK
|
||||
rc, err := o.f.cipher.DecryptData(in)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// If seeking required, then...
|
||||
if offset != 0 {
|
||||
// FIXME could cache the unseeked decrypter as we re-read the header on every seek
|
||||
decrypter := rc.(*decrypter)
|
||||
|
||||
// Seek the decrypter and work out where to seek the
|
||||
// underlying file and how many bytes to discard
|
||||
underlyingOffset, discard := decrypter.seek(offset)
|
||||
|
||||
// Re-open stream with a seek of underlyingOffset
|
||||
err = in.Close()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
in, err := o.Object.Open(&fs.SeekOption{Offset: underlyingOffset})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Update the stream
|
||||
decrypter.rc = in
|
||||
|
||||
// Discard the bytes
|
||||
_, err = io.CopyN(ioutil.Discard, decrypter, discard)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return rc, err
|
||||
}
|
||||
|
||||
// Update in to the object with the modTime given of the given size
|
||||
|
||||
Reference in New Issue
Block a user