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