github.com/ncw/rclone@v1.48.1-0.20190724201158-a35aa1360e3e/cmd/mount/fs.go (about) 1 // FUSE main Fs 2 3 // +build linux darwin freebsd 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/ncw/rclone/cmd/mountlib" 14 "github.com/ncw/rclone/fs" 15 "github.com/ncw/rclone/fs/log" 16 "github.com/ncw/rclone/vfs" 17 "github.com/ncw/rclone/vfs/vfsflags" 18 "github.com/pkg/errors" 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 const fsBlocks = (1 << 50) / blockSize 58 resp.Blocks = fsBlocks // Total data blocks in file system. 59 resp.Bfree = fsBlocks // Free blocks in file system. 60 resp.Bavail = fsBlocks // 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 total, used, free := f.VFS.Statfs() 67 if total >= 0 { 68 resp.Blocks = uint64(total) / blockSize 69 } 70 if used >= 0 { 71 resp.Bfree = resp.Blocks - uint64(used)/blockSize 72 } 73 if free >= 0 { 74 resp.Bavail = uint64(free) / blockSize 75 } 76 mountlib.ClipBlocks(&resp.Blocks) 77 mountlib.ClipBlocks(&resp.Bfree) 78 mountlib.ClipBlocks(&resp.Bavail) 79 return nil 80 } 81 82 // Translate errors from mountlib 83 func translateError(err error) error { 84 if err == nil { 85 return nil 86 } 87 switch errors.Cause(err) { 88 case vfs.OK: 89 return nil 90 case vfs.ENOENT: 91 return fuse.ENOENT 92 case vfs.EEXIST: 93 return fuse.EEXIST 94 case vfs.EPERM: 95 return fuse.EPERM 96 case vfs.ECLOSED: 97 return fuse.Errno(syscall.EBADF) 98 case vfs.ENOTEMPTY: 99 return fuse.Errno(syscall.ENOTEMPTY) 100 case vfs.ESPIPE: 101 return fuse.Errno(syscall.ESPIPE) 102 case vfs.EBADF: 103 return fuse.Errno(syscall.EBADF) 104 case vfs.EROFS: 105 return fuse.Errno(syscall.EROFS) 106 case vfs.ENOSYS: 107 return fuse.ENOSYS 108 case vfs.EINVAL: 109 return fuse.Errno(syscall.EINVAL) 110 } 111 return err 112 }