mirror of
https://github.com/rclone/rclone.git
synced 2024-11-22 09:11:11 +08:00
mount,vfs: unify Read and Write handles in preparation for ReadWrite handles
This commit is contained in:
parent
e18122e88b
commit
5634659ea3
|
@ -126,7 +126,7 @@ func (d *Dir) Create(ctx context.Context, req *fuse.CreateRequest, resp *fuse.Cr
|
|||
if err != nil {
|
||||
return nil, nil, translateError(err)
|
||||
}
|
||||
return &File{file}, &WriteFileHandle{fh}, err
|
||||
return &File{file}, &FileHandle{fh}, err
|
||||
}
|
||||
|
||||
var _ fusefs.NodeMkdirer = (*Dir)(nil)
|
||||
|
|
|
@ -69,20 +69,12 @@ func (f *File) Open(ctx context.Context, req *fuse.OpenRequest, resp *fuse.OpenR
|
|||
return nil, translateError(err)
|
||||
}
|
||||
|
||||
switch h := handle.(type) {
|
||||
case *vfs.ReadFileHandle:
|
||||
if f.VFS().Opt.NoSeek {
|
||||
resp.Flags |= fuse.OpenNonSeekable
|
||||
}
|
||||
fh = &ReadFileHandle{h}
|
||||
case *vfs.WriteFileHandle:
|
||||
// See if seeking is supported and set FUSE hint accordingly
|
||||
if _, err = handle.Seek(0, 1); err != nil {
|
||||
resp.Flags |= fuse.OpenNonSeekable
|
||||
fh = &WriteFileHandle{h}
|
||||
default:
|
||||
panic("unknown file handle type")
|
||||
}
|
||||
|
||||
return fh, nil
|
||||
return &FileHandle{handle}, nil
|
||||
}
|
||||
|
||||
// Check interface satisfied
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
package mount
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"io"
|
||||
|
||||
"bazil.org/fuse"
|
||||
|
@ -13,11 +12,9 @@ import (
|
|||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
var errClosedFileHandle = errors.New("Attempt to use closed file handle")
|
||||
|
||||
// WriteFileHandle is an open for write handle on a File
|
||||
type WriteFileHandle struct {
|
||||
*vfs.WriteFileHandle
|
||||
// FileHandle is an open for read file handle on a File
|
||||
type FileHandle struct {
|
||||
vfs.Handle
|
||||
}
|
||||
|
||||
// Check interface satisfied
|
||||
|
@ -39,12 +36,12 @@ func (fh *FileHandle) Read(ctx context.Context, req *fuse.ReadRequest, resp *fus
|
|||
}
|
||||
|
||||
// Check interface satisfied
|
||||
var _ fusefs.HandleWriter = (*WriteFileHandle)(nil)
|
||||
var _ fusefs.HandleWriter = (*FileHandle)(nil)
|
||||
|
||||
// Write data to the file handle
|
||||
func (fh *WriteFileHandle) Write(ctx context.Context, req *fuse.WriteRequest, resp *fuse.WriteResponse) (err error) {
|
||||
func (fh *FileHandle) Write(ctx context.Context, req *fuse.WriteRequest, resp *fuse.WriteResponse) (err error) {
|
||||
defer fs.Trace(fh, "len=%d, offset=%d", len(req.Data), req.Offset)("written=%d, err=%v", &resp.Size, &err)
|
||||
n, err := fh.WriteFileHandle.WriteAt(req.Data, req.Offset)
|
||||
n, err := fh.Handle.WriteAt(req.Data, req.Offset)
|
||||
if err != nil {
|
||||
return translateError(err)
|
||||
}
|
||||
|
@ -52,6 +49,9 @@ func (fh *WriteFileHandle) Write(ctx context.Context, req *fuse.WriteRequest, re
|
|||
return nil
|
||||
}
|
||||
|
||||
// Check interface satisfied
|
||||
var _ fusefs.HandleFlusher = (*FileHandle)(nil)
|
||||
|
||||
// Flush is called on each close() of a file descriptor. So if a
|
||||
// filesystem wants to return write errors in close() and the file has
|
||||
// cached dirty data, this is a good place to write back data and
|
||||
|
@ -67,18 +67,18 @@ func (fh *WriteFileHandle) Write(ctx context.Context, req *fuse.WriteRequest, re
|
|||
//
|
||||
// Filesystems shouldn't assume that flush will always be called after
|
||||
// some writes, or that if will be called at all.
|
||||
func (fh *WriteFileHandle) Flush(ctx context.Context, req *fuse.FlushRequest) (err error) {
|
||||
func (fh *FileHandle) Flush(ctx context.Context, req *fuse.FlushRequest) (err error) {
|
||||
defer fs.Trace(fh, "")("err=%v", &err)
|
||||
return translateError(fh.WriteFileHandle.Flush())
|
||||
return translateError(fh.Handle.Flush())
|
||||
}
|
||||
|
||||
var _ fusefs.HandleReleaser = (*WriteFileHandle)(nil)
|
||||
var _ fusefs.HandleReleaser = (*FileHandle)(nil)
|
||||
|
||||
// Release is called when we are finished with the file handle
|
||||
//
|
||||
// It isn't called directly from userspace so the error is ignored by
|
||||
// the kernel
|
||||
func (fh *WriteFileHandle) Release(ctx context.Context, req *fuse.ReleaseRequest) (err error) {
|
||||
func (fh *FileHandle) Release(ctx context.Context, req *fuse.ReleaseRequest) (err error) {
|
||||
defer fs.Trace(fh, "")("err=%v", &err)
|
||||
return translateError(fh.WriteFileHandle.Release())
|
||||
return translateError(fh.Handle.Release())
|
||||
}
|
|
@ -1,57 +0,0 @@
|
|||
// +build linux darwin freebsd
|
||||
|
||||
package mount
|
||||
|
||||
import (
|
||||
"bazil.org/fuse"
|
||||
fusefs "bazil.org/fuse/fs"
|
||||
"github.com/ncw/rclone/fs"
|
||||
"github.com/ncw/rclone/vfs"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
// ReadFileHandle is an open for read file handle on a File
|
||||
type ReadFileHandle struct {
|
||||
*vfs.ReadFileHandle
|
||||
}
|
||||
|
||||
// Check interface satisfied
|
||||
var _ fusefs.Handle = (*ReadFileHandle)(nil)
|
||||
|
||||
// Check interface satisfied
|
||||
var _ fusefs.HandleReader = (*ReadFileHandle)(nil)
|
||||
|
||||
// Read from the file handle
|
||||
func (fh *ReadFileHandle) Read(ctx context.Context, req *fuse.ReadRequest, resp *fuse.ReadResponse) (err error) {
|
||||
var n int
|
||||
defer fs.Trace(fh, "len=%d, offset=%d", req.Size, req.Offset)("read=%d, err=%v", &n, &err)
|
||||
data := make([]byte, req.Size)
|
||||
n, err = fh.ReadFileHandle.ReadAt(data, req.Offset)
|
||||
if err != nil {
|
||||
return translateError(err)
|
||||
}
|
||||
resp.Data = data[:n]
|
||||
return nil
|
||||
}
|
||||
|
||||
// Check interface satisfied
|
||||
var _ fusefs.HandleFlusher = (*ReadFileHandle)(nil)
|
||||
|
||||
// Flush is called each time the file or directory is closed.
|
||||
// Because there can be multiple file descriptors referring to a
|
||||
// single opened file, Flush can be called multiple times.
|
||||
func (fh *ReadFileHandle) Flush(ctx context.Context, req *fuse.FlushRequest) (err error) {
|
||||
defer fs.Trace(fh, "")("err=%v", &err)
|
||||
return translateError(fh.ReadFileHandle.Flush())
|
||||
}
|
||||
|
||||
var _ fusefs.HandleReleaser = (*ReadFileHandle)(nil)
|
||||
|
||||
// Release is called when we are finished with the file handle
|
||||
//
|
||||
// It isn't called directly from userspace so the error is ignored by
|
||||
// the kernel
|
||||
func (fh *ReadFileHandle) Release(ctx context.Context, req *fuse.ReleaseRequest) (err error) {
|
||||
defer fs.Trace(fh, "")("err=%v", &err)
|
||||
return translateError(fh.ReadFileHandle.Release())
|
||||
}
|
|
@ -124,8 +124,11 @@ func (fh *ReadFileHandle) seek(offset int64, reopen bool) (err error) {
|
|||
return nil
|
||||
}
|
||||
|
||||
// Seek the file
|
||||
// Seek the file - returns ESPIPE if seeking isn't possible
|
||||
func (fh *ReadFileHandle) Seek(offset int64, whence int) (n int64, err error) {
|
||||
if fh.noSeek {
|
||||
return 0, ESPIPE
|
||||
}
|
||||
size := fh.o.Size()
|
||||
switch whence {
|
||||
case 0:
|
||||
|
|
|
@ -102,6 +102,9 @@ type Handle interface {
|
|||
Write(b []byte) (n int, err error)
|
||||
WriteAt(b []byte, off int64) (n int, err error)
|
||||
WriteString(s string) (n int, err error)
|
||||
// Additional methods useful for FUSE filesystems
|
||||
Flush() error
|
||||
Release() error
|
||||
}
|
||||
|
||||
// baseHandle implements all the missing methods
|
||||
|
@ -124,6 +127,8 @@ func (h baseHandle) Truncate(size int64) error { retu
|
|||
func (h baseHandle) Write(b []byte) (n int, err error) { return 0, ENOSYS }
|
||||
func (h baseHandle) WriteAt(b []byte, off int64) (n int, err error) { return 0, ENOSYS }
|
||||
func (h baseHandle) WriteString(s string) (n int, err error) { return 0, ENOSYS }
|
||||
func (h baseHandle) Flush() (err error) { return ENOSYS }
|
||||
func (h baseHandle) Release() (err error) { return ENOSYS }
|
||||
|
||||
// Check interfaces
|
||||
var (
|
||||
|
@ -131,7 +136,6 @@ var (
|
|||
_ Handle = (*ReadFileHandle)(nil)
|
||||
_ Handle = (*WriteFileHandle)(nil)
|
||||
_ Handle = (*DirHandle)(nil)
|
||||
_ Handle = (*os.File)(nil)
|
||||
)
|
||||
|
||||
// VFS represents the top level filing system
|
||||
|
|
Loading…
Reference in New Issue
Block a user