github.com/rclone/rclone@v1.66.1-0.20240517100346-7b89735ae726/cmd/mount/handle.go (about) 1 //go:build linux 2 3 package mount 4 5 import ( 6 "context" 7 "io" 8 9 "bazil.org/fuse" 10 fusefs "bazil.org/fuse/fs" 11 "github.com/rclone/rclone/fs/log" 12 "github.com/rclone/rclone/vfs" 13 ) 14 15 // FileHandle is an open for read file handle on a File 16 type FileHandle struct { 17 vfs.Handle 18 } 19 20 // Check interface satisfied 21 var _ fusefs.HandleReader = (*FileHandle)(nil) 22 23 // Read from the file handle 24 func (fh *FileHandle) Read(ctx context.Context, req *fuse.ReadRequest, resp *fuse.ReadResponse) (err error) { 25 var n int 26 defer log.Trace(fh, "len=%d, offset=%d", req.Size, req.Offset)("read=%d, err=%v", &n, &err) 27 data := resp.Data[:req.Size] 28 n, err = fh.Handle.ReadAt(data, req.Offset) 29 resp.Data = data[:n] 30 if err == io.EOF { 31 err = nil 32 } 33 return translateError(err) 34 } 35 36 // Check interface satisfied 37 var _ fusefs.HandleWriter = (*FileHandle)(nil) 38 39 // Write data to the file handle 40 func (fh *FileHandle) Write(ctx context.Context, req *fuse.WriteRequest, resp *fuse.WriteResponse) (err error) { 41 defer log.Trace(fh, "len=%d, offset=%d", len(req.Data), req.Offset)("written=%d, err=%v", &resp.Size, &err) 42 n, err := fh.Handle.WriteAt(req.Data, req.Offset) 43 if err != nil { 44 return translateError(err) 45 } 46 resp.Size = n 47 return nil 48 } 49 50 // Check interface satisfied 51 var _ fusefs.HandleFlusher = (*FileHandle)(nil) 52 53 // Flush is called on each close() of a file descriptor. So if a 54 // filesystem wants to return write errors in close() and the file has 55 // cached dirty data, this is a good place to write back data and 56 // return any errors. Since many applications ignore close() errors 57 // this is not always useful. 58 // 59 // NOTE: The flush() method may be called more than once for each 60 // open(). This happens if more than one file descriptor refers to an 61 // opened file due to dup(), dup2() or fork() calls. It is not 62 // possible to determine if a flush is final, so each flush should be 63 // treated equally. Multiple write-flush sequences are relatively 64 // rare, so this shouldn't be a problem. 65 // 66 // Filesystems shouldn't assume that flush will always be called after 67 // some writes, or that if will be called at all. 68 func (fh *FileHandle) Flush(ctx context.Context, req *fuse.FlushRequest) (err error) { 69 defer log.Trace(fh, "")("err=%v", &err) 70 return translateError(fh.Handle.Flush()) 71 } 72 73 var _ fusefs.HandleReleaser = (*FileHandle)(nil) 74 75 // Release is called when we are finished with the file handle 76 // 77 // It isn't called directly from userspace so the error is ignored by 78 // the kernel 79 func (fh *FileHandle) Release(ctx context.Context, req *fuse.ReleaseRequest) (err error) { 80 defer log.Trace(fh, "")("err=%v", &err) 81 return translateError(fh.Handle.Release()) 82 }