github.com/artpar/rclone@v1.67.3/cmd/mount2/fs.go (about)

     1  // FUSE main Fs
     2  
     3  //go:build linux || (darwin && amd64)
     4  
     5  package mount2
     6  
     7  import (
     8  	"os"
     9  	"syscall"
    10  
    11  	"github.com/artpar/rclone/cmd/mountlib"
    12  	"github.com/artpar/rclone/fs"
    13  	"github.com/artpar/rclone/fs/fserrors"
    14  	"github.com/artpar/rclone/fs/log"
    15  	"github.com/artpar/rclone/vfs"
    16  	"github.com/hanwen/go-fuse/v2/fuse"
    17  )
    18  
    19  // FS represents the top level filing system
    20  type FS struct {
    21  	VFS *vfs.VFS
    22  	f   fs.Fs
    23  	opt *mountlib.Options
    24  }
    25  
    26  // NewFS creates a pathfs.FileSystem from the fs.Fs passed in
    27  func NewFS(VFS *vfs.VFS, opt *mountlib.Options) *FS {
    28  	fsys := &FS{
    29  		VFS: VFS,
    30  		f:   VFS.Fs(),
    31  		opt: opt,
    32  	}
    33  	return fsys
    34  }
    35  
    36  // Root returns the root node
    37  func (f *FS) Root() (node *Node, err error) {
    38  	defer log.Trace("", "")("node=%+v, err=%v", &node, &err)
    39  	root, err := f.VFS.Root()
    40  	if err != nil {
    41  		return nil, err
    42  	}
    43  	return newNode(f, root), nil
    44  }
    45  
    46  // SetDebug if called, provide debug output through the log package.
    47  func (f *FS) SetDebug(debug bool) {
    48  	fs.Debugf(f.f, "SetDebug %v", debug)
    49  }
    50  
    51  // get the Mode from a vfs Node
    52  func getMode(node os.FileInfo) uint32 {
    53  	Mode := node.Mode().Perm()
    54  	if node.IsDir() {
    55  		Mode |= fuse.S_IFDIR
    56  	} else {
    57  		Mode |= fuse.S_IFREG
    58  	}
    59  	return uint32(Mode)
    60  }
    61  
    62  // fill in attr from node
    63  func setAttr(node vfs.Node, attr *fuse.Attr) {
    64  	Size := uint64(node.Size())
    65  	const BlockSize = 512
    66  	Blocks := (Size + BlockSize - 1) / BlockSize
    67  	modTime := node.ModTime()
    68  	// set attributes
    69  	vfs := node.VFS()
    70  	attr.Owner.Gid = vfs.Opt.GID
    71  	attr.Owner.Uid = vfs.Opt.UID
    72  	attr.Mode = getMode(node)
    73  	attr.Size = Size
    74  	attr.Nlink = 1
    75  	attr.Blocks = Blocks
    76  	// attr.Blksize = BlockSize // not supported in freebsd/darwin, defaults to 4k if not set
    77  	s := uint64(modTime.Unix())
    78  	ns := uint32(modTime.Nanosecond())
    79  	attr.Atime = s
    80  	attr.Atimensec = ns
    81  	attr.Mtime = s
    82  	attr.Mtimensec = ns
    83  	attr.Ctime = s
    84  	attr.Ctimensec = ns
    85  	//attr.Rdev
    86  }
    87  
    88  // fill in AttrOut from node
    89  func (f *FS) setAttrOut(node vfs.Node, out *fuse.AttrOut) {
    90  	setAttr(node, &out.Attr)
    91  	out.SetTimeout(f.opt.AttrTimeout)
    92  }
    93  
    94  // fill in EntryOut from node
    95  func (f *FS) setEntryOut(node vfs.Node, out *fuse.EntryOut) {
    96  	setAttr(node, &out.Attr)
    97  	out.SetEntryTimeout(f.opt.AttrTimeout)
    98  	out.SetAttrTimeout(f.opt.AttrTimeout)
    99  }
   100  
   101  // Translate errors from mountlib into Syscall error numbers
   102  func translateError(err error) syscall.Errno {
   103  	if err == nil {
   104  		return 0
   105  	}
   106  	_, uErr := fserrors.Cause(err)
   107  	switch uErr {
   108  	case vfs.OK:
   109  		return 0
   110  	case vfs.ENOENT, fs.ErrorDirNotFound, fs.ErrorObjectNotFound:
   111  		return syscall.ENOENT
   112  	case vfs.EEXIST, fs.ErrorDirExists:
   113  		return syscall.EEXIST
   114  	case vfs.EPERM, fs.ErrorPermissionDenied:
   115  		return syscall.EPERM
   116  	case vfs.ECLOSED:
   117  		return syscall.EBADF
   118  	case vfs.ENOTEMPTY:
   119  		return syscall.ENOTEMPTY
   120  	case vfs.ESPIPE:
   121  		return syscall.ESPIPE
   122  	case vfs.EBADF:
   123  		return syscall.EBADF
   124  	case vfs.EROFS:
   125  		return syscall.EROFS
   126  	case vfs.ENOSYS, fs.ErrorNotImplemented:
   127  		return syscall.ENOSYS
   128  	case vfs.EINVAL:
   129  		return syscall.EINVAL
   130  	}
   131  	fs.Errorf(nil, "IO error: %v", err)
   132  	return syscall.EIO
   133  }