2023-10-29 14:15:34 +00:00
|
|
|
//go:build linux
|
|
|
|
// +build linux
|
2016-07-17 22:03:23 +00:00
|
|
|
|
|
|
|
package mount
|
|
|
|
|
|
|
|
import (
|
2019-05-07 12:53:16 +00:00
|
|
|
"context"
|
2017-10-29 21:14:05 +00:00
|
|
|
"io"
|
2016-07-17 22:03:23 +00:00
|
|
|
|
|
|
|
"bazil.org/fuse"
|
|
|
|
fusefs "bazil.org/fuse/fs"
|
2019-07-28 17:47:38 +00:00
|
|
|
"github.com/rclone/rclone/fs/log"
|
|
|
|
"github.com/rclone/rclone/vfs"
|
2016-07-17 22:03:23 +00:00
|
|
|
)
|
|
|
|
|
2017-11-02 18:22:26 +00:00
|
|
|
// FileHandle is an open for read file handle on a File
|
|
|
|
type FileHandle struct {
|
|
|
|
vfs.Handle
|
2016-07-17 22:03:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Check interface satisfied
|
2017-10-29 21:14:05 +00:00
|
|
|
var _ fusefs.HandleReader = (*FileHandle)(nil)
|
|
|
|
|
|
|
|
// Read from the file handle
|
|
|
|
func (fh *FileHandle) Read(ctx context.Context, req *fuse.ReadRequest, resp *fuse.ReadResponse) (err error) {
|
|
|
|
var n int
|
2018-01-12 16:30:54 +00:00
|
|
|
defer log.Trace(fh, "len=%d, offset=%d", req.Size, req.Offset)("read=%d, err=%v", &n, &err)
|
2023-04-29 12:48:21 +00:00
|
|
|
data := resp.Data[:req.Size]
|
2017-10-29 21:14:05 +00:00
|
|
|
n, err = fh.Handle.ReadAt(data, req.Offset)
|
2023-04-29 12:48:21 +00:00
|
|
|
resp.Data = data[:n]
|
2017-10-29 21:14:05 +00:00
|
|
|
if err == io.EOF {
|
|
|
|
err = nil
|
|
|
|
}
|
2023-04-29 12:48:21 +00:00
|
|
|
return translateError(err)
|
2017-10-29 21:14:05 +00:00
|
|
|
}
|
2016-07-17 22:03:23 +00:00
|
|
|
|
|
|
|
// Check interface satisfied
|
2017-11-02 18:22:26 +00:00
|
|
|
var _ fusefs.HandleWriter = (*FileHandle)(nil)
|
2016-07-17 22:03:23 +00:00
|
|
|
|
|
|
|
// Write data to the file handle
|
2017-11-02 18:22:26 +00:00
|
|
|
func (fh *FileHandle) Write(ctx context.Context, req *fuse.WriteRequest, resp *fuse.WriteResponse) (err error) {
|
2018-01-12 16:30:54 +00:00
|
|
|
defer log.Trace(fh, "len=%d, offset=%d", len(req.Data), req.Offset)("written=%d, err=%v", &resp.Size, &err)
|
2020-02-28 14:44:15 +00:00
|
|
|
n, err := fh.Handle.WriteAt(req.Data, req.Offset)
|
2016-07-17 22:03:23 +00:00
|
|
|
if err != nil {
|
2017-05-02 21:35:07 +00:00
|
|
|
return translateError(err)
|
2017-05-01 12:38:41 +00:00
|
|
|
}
|
2019-01-11 17:17:46 +00:00
|
|
|
resp.Size = n
|
2016-07-17 22:03:23 +00:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2017-11-02 18:22:26 +00:00
|
|
|
// Check interface satisfied
|
|
|
|
var _ fusefs.HandleFlusher = (*FileHandle)(nil)
|
|
|
|
|
2016-07-17 22:03:23 +00:00
|
|
|
// 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
|
|
|
|
// return any errors. Since many applications ignore close() errors
|
|
|
|
// this is not always useful.
|
|
|
|
//
|
|
|
|
// NOTE: The flush() method may be called more than once for each
|
|
|
|
// open(). This happens if more than one file descriptor refers to an
|
|
|
|
// opened file due to dup(), dup2() or fork() calls. It is not
|
|
|
|
// possible to determine if a flush is final, so each flush should be
|
|
|
|
// treated equally. Multiple write-flush sequences are relatively
|
|
|
|
// rare, so this shouldn't be a problem.
|
|
|
|
//
|
|
|
|
// Filesystems shouldn't assume that flush will always be called after
|
|
|
|
// some writes, or that if will be called at all.
|
2017-11-02 18:22:26 +00:00
|
|
|
func (fh *FileHandle) Flush(ctx context.Context, req *fuse.FlushRequest) (err error) {
|
2018-01-12 16:30:54 +00:00
|
|
|
defer log.Trace(fh, "")("err=%v", &err)
|
2017-11-02 18:22:26 +00:00
|
|
|
return translateError(fh.Handle.Flush())
|
2016-07-17 22:03:23 +00:00
|
|
|
}
|
|
|
|
|
2017-11-02 18:22:26 +00:00
|
|
|
var _ fusefs.HandleReleaser = (*FileHandle)(nil)
|
2016-07-17 22:03:23 +00:00
|
|
|
|
|
|
|
// 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
|
2017-11-02 18:22:26 +00:00
|
|
|
func (fh *FileHandle) Release(ctx context.Context, req *fuse.ReleaseRequest) (err error) {
|
2018-01-12 16:30:54 +00:00
|
|
|
defer log.Trace(fh, "")("err=%v", &err)
|
2017-11-02 18:22:26 +00:00
|
|
|
return translateError(fh.Handle.Release())
|
2016-07-17 22:03:23 +00:00
|
|
|
}
|