github.com/ncw/rclone@v1.48.1-0.20190724201158-a35aa1360e3e/cmd/mount/handle.go (about) 1 // +build linux darwin freebsd 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/ncw/rclone/fs/log" 12 "github.com/ncw/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 := make([]byte, req.Size) 28 n, err = fh.Handle.ReadAt(data, req.Offset) 29 if err == io.EOF { 30 err = nil 31 } else if err != nil { 32 return translateError(err) 33 } 34 resp.Data = data[:n] 35 return nil 36 } 37 38 // Check interface satisfied 39 var _ fusefs.HandleWriter = (*FileHandle)(nil) 40 41 // Write data to the file handle 42 func (fh *FileHandle) Write(ctx context.Context, req *fuse.WriteRequest, resp *fuse.WriteResponse) (err error) { 43 defer log.Trace(fh, "len=%d, offset=%d", len(req.Data), req.Offset)("written=%d, err=%v", &resp.Size, &err) 44 n, err := fh.Handle.WriteAt(req.Data, req.Offset) 45 if err != nil { 46 return translateError(err) 47 } 48 resp.Size = n 49 return nil 50 } 51 52 // Check interface satisfied 53 var _ fusefs.HandleFlusher = (*FileHandle)(nil) 54 55 // Flush is called on each close() of a file descriptor. So if a 56 // filesystem wants to return write errors in close() and the file has 57 // cached dirty data, this is a good place to write back data and 58 // return any errors. Since many applications ignore close() errors 59 // this is not always useful. 60 // 61 // NOTE: The flush() method may be called more than once for each 62 // open(). This happens if more than one file descriptor refers to an 63 // opened file due to dup(), dup2() or fork() calls. It is not 64 // possible to determine if a flush is final, so each flush should be 65 // treated equally. Multiple write-flush sequences are relatively 66 // rare, so this shouldn't be a problem. 67 // 68 // Filesystems shouldn't assume that flush will always be called after 69 // some writes, or that if will be called at all. 70 func (fh *FileHandle) Flush(ctx context.Context, req *fuse.FlushRequest) (err error) { 71 defer log.Trace(fh, "")("err=%v", &err) 72 return translateError(fh.Handle.Flush()) 73 } 74 75 var _ fusefs.HandleReleaser = (*FileHandle)(nil) 76 77 // Release is called when we are finished with the file handle 78 // 79 // It isn't called directly from userspace so the error is ignored by 80 // the kernel 81 func (fh *FileHandle) Release(ctx context.Context, req *fuse.ReleaseRequest) (err error) { 82 defer log.Trace(fh, "")("err=%v", &err) 83 return translateError(fh.Handle.Release()) 84 }