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  }