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 }