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  }