github.com/rclone/rclone@v1.66.1-0.20240517100346-7b89735ae726/cmd/mount/fs.go (about) 1 // FUSE main Fs 2 3 //go:build linux 4 5 package mount 6 7 import ( 8 "context" 9 "syscall" 10 11 "bazil.org/fuse" 12 fusefs "bazil.org/fuse/fs" 13 "github.com/rclone/rclone/cmd/mountlib" 14 "github.com/rclone/rclone/fs" 15 "github.com/rclone/rclone/fs/fserrors" 16 "github.com/rclone/rclone/fs/log" 17 "github.com/rclone/rclone/vfs" 18 ) 19 20 // FS represents the top level filing system 21 type FS struct { 22 *vfs.VFS 23 f fs.Fs 24 opt *mountlib.Options 25 server *fusefs.Server 26 } 27 28 // Check interface satisfied 29 var _ fusefs.FS = (*FS)(nil) 30 31 // NewFS makes a new FS 32 func NewFS(VFS *vfs.VFS, opt *mountlib.Options) *FS { 33 fsys := &FS{ 34 VFS: VFS, 35 f: VFS.Fs(), 36 opt: opt, 37 } 38 return fsys 39 } 40 41 // Root returns the root node 42 func (f *FS) Root() (node fusefs.Node, err error) { 43 defer log.Trace("", "")("node=%+v, err=%v", &node, &err) 44 root, err := f.VFS.Root() 45 if err != nil { 46 return nil, translateError(err) 47 } 48 return &Dir{root, f}, nil 49 } 50 51 // Check interface satisfied 52 var _ fusefs.FSStatfser = (*FS)(nil) 53 54 // Statfs is called to obtain file system metadata. 55 // It should write that data to resp. 56 func (f *FS) Statfs(ctx context.Context, req *fuse.StatfsRequest, resp *fuse.StatfsResponse) (err error) { 57 defer log.Trace("", "")("stat=%+v, err=%v", resp, &err) 58 const blockSize = 4096 59 total, _, free := f.VFS.Statfs() 60 resp.Blocks = uint64(total) / blockSize // Total data blocks in file system. 61 resp.Bfree = uint64(free) / blockSize // Free blocks in file system. 62 resp.Bavail = resp.Bfree // Free blocks in file system if you're not root. 63 resp.Files = 1e9 // Total files in file system. 64 resp.Ffree = 1e9 // Free files in file system. 65 resp.Bsize = blockSize // Block size 66 resp.Namelen = 255 // Maximum file name length? 67 resp.Frsize = blockSize // Fragment size, smallest addressable data size in the file system. 68 mountlib.ClipBlocks(&resp.Blocks) 69 mountlib.ClipBlocks(&resp.Bfree) 70 mountlib.ClipBlocks(&resp.Bavail) 71 return nil 72 } 73 74 // Translate errors from mountlib 75 func translateError(err error) error { 76 if err == nil { 77 return nil 78 } 79 _, uErr := fserrors.Cause(err) 80 switch uErr { 81 case vfs.OK: 82 return nil 83 case vfs.ENOENT, fs.ErrorDirNotFound, fs.ErrorObjectNotFound: 84 return fuse.Errno(syscall.ENOENT) 85 case vfs.EEXIST, fs.ErrorDirExists: 86 return fuse.Errno(syscall.EEXIST) 87 case vfs.EPERM, fs.ErrorPermissionDenied: 88 return fuse.Errno(syscall.EPERM) 89 case vfs.ECLOSED: 90 return fuse.Errno(syscall.EBADF) 91 case vfs.ENOTEMPTY: 92 return fuse.Errno(syscall.ENOTEMPTY) 93 case vfs.ESPIPE: 94 return fuse.Errno(syscall.ESPIPE) 95 case vfs.EBADF: 96 return fuse.Errno(syscall.EBADF) 97 case vfs.EROFS: 98 return fuse.Errno(syscall.EROFS) 99 case vfs.ENOSYS, fs.ErrorNotImplemented: 100 return syscall.ENOSYS 101 case vfs.EINVAL: 102 return fuse.Errno(syscall.EINVAL) 103 } 104 fs.Errorf(nil, "IO error: %v", err) 105 return err 106 }