2016-07-18 00:03:23 +02:00
|
|
|
// FUSE main Fs
|
|
|
|
|
2021-02-03 18:46:08 +01:00
|
|
|
// +build linux freebsd
|
2016-07-18 00:03:23 +02:00
|
|
|
|
|
|
|
package mount
|
|
|
|
|
|
|
|
import (
|
2019-05-07 14:53:16 +02:00
|
|
|
"context"
|
2017-05-11 14:15:51 +02:00
|
|
|
"syscall"
|
|
|
|
|
2016-07-18 00:03:23 +02:00
|
|
|
"bazil.org/fuse"
|
|
|
|
fusefs "bazil.org/fuse/fs"
|
2017-05-02 23:35:07 +02:00
|
|
|
"github.com/pkg/errors"
|
2019-07-28 19:47:38 +02:00
|
|
|
"github.com/rclone/rclone/cmd/mountlib"
|
|
|
|
"github.com/rclone/rclone/fs"
|
|
|
|
"github.com/rclone/rclone/fs/log"
|
|
|
|
"github.com/rclone/rclone/vfs"
|
2016-07-18 00:03:23 +02:00
|
|
|
)
|
|
|
|
|
|
|
|
// FS represents the top level filing system
|
|
|
|
type FS struct {
|
2017-10-28 21:01:34 +02:00
|
|
|
*vfs.VFS
|
2020-07-23 18:17:01 +02:00
|
|
|
f fs.Fs
|
|
|
|
opt *mountlib.Options
|
2016-07-18 00:03:23 +02:00
|
|
|
}
|
|
|
|
|
2019-04-30 14:06:24 +02:00
|
|
|
// Check interface satisfied
|
2016-07-18 00:03:23 +02:00
|
|
|
var _ fusefs.FS = (*FS)(nil)
|
|
|
|
|
2017-05-02 23:35:07 +02:00
|
|
|
// NewFS makes a new FS
|
2020-07-23 18:17:01 +02:00
|
|
|
func NewFS(VFS *vfs.VFS, opt *mountlib.Options) *FS {
|
2017-05-02 23:35:07 +02:00
|
|
|
fsys := &FS{
|
2020-07-22 18:58:49 +02:00
|
|
|
VFS: VFS,
|
|
|
|
f: VFS.Fs(),
|
2020-07-23 18:17:01 +02:00
|
|
|
opt: opt,
|
2016-09-09 09:39:19 +02:00
|
|
|
}
|
2017-05-02 23:35:07 +02:00
|
|
|
return fsys
|
2016-09-09 09:39:19 +02:00
|
|
|
}
|
|
|
|
|
2017-05-02 23:35:07 +02:00
|
|
|
// Root returns the root node
|
2017-05-09 12:39:33 +02:00
|
|
|
func (f *FS) Root() (node fusefs.Node, err error) {
|
2018-01-12 17:30:54 +01:00
|
|
|
defer log.Trace("", "")("node=%+v, err=%v", &node, &err)
|
2017-10-28 21:01:34 +02:00
|
|
|
root, err := f.VFS.Root()
|
2017-05-04 22:49:06 +02:00
|
|
|
if err != nil {
|
2017-05-02 23:35:07 +02:00
|
|
|
return nil, translateError(err)
|
2016-07-18 00:03:23 +02:00
|
|
|
}
|
2020-07-23 18:17:01 +02:00
|
|
|
return &Dir{root, f}, nil
|
2016-07-18 00:03:23 +02:00
|
|
|
}
|
2016-11-20 23:54:03 +01:00
|
|
|
|
2019-04-30 14:06:24 +02:00
|
|
|
// Check interface satisfied
|
2016-11-20 23:54:03 +01:00
|
|
|
var _ fusefs.FSStatfser = (*FS)(nil)
|
|
|
|
|
|
|
|
// Statfs is called to obtain file system metadata.
|
|
|
|
// It should write that data to resp.
|
2017-05-09 12:39:33 +02:00
|
|
|
func (f *FS) Statfs(ctx context.Context, req *fuse.StatfsRequest, resp *fuse.StatfsResponse) (err error) {
|
2018-01-12 17:30:54 +01:00
|
|
|
defer log.Trace("", "")("stat=%+v, err=%v", resp, &err)
|
2016-11-20 23:54:03 +01:00
|
|
|
const blockSize = 4096
|
2020-04-08 19:29:50 +02:00
|
|
|
total, _, free := f.VFS.Statfs()
|
|
|
|
resp.Blocks = uint64(total) / blockSize // Total data blocks in file system.
|
|
|
|
resp.Bfree = uint64(free) / blockSize // Free blocks in file system.
|
|
|
|
resp.Bavail = resp.Bfree // Free blocks in file system if you're not root.
|
|
|
|
resp.Files = 1e9 // Total files in file system.
|
|
|
|
resp.Ffree = 1e9 // Free files in file system.
|
|
|
|
resp.Bsize = blockSize // Block size
|
|
|
|
resp.Namelen = 255 // Maximum file name length?
|
|
|
|
resp.Frsize = blockSize // Fragment size, smallest addressable data size in the file system.
|
2018-06-26 10:26:34 +02:00
|
|
|
mountlib.ClipBlocks(&resp.Blocks)
|
|
|
|
mountlib.ClipBlocks(&resp.Bfree)
|
|
|
|
mountlib.ClipBlocks(&resp.Bavail)
|
2016-11-20 23:54:03 +01:00
|
|
|
return nil
|
|
|
|
}
|
2017-05-04 22:49:06 +02:00
|
|
|
|
2017-05-02 23:35:07 +02:00
|
|
|
// Translate errors from mountlib
|
|
|
|
func translateError(err error) error {
|
|
|
|
if err == nil {
|
|
|
|
return nil
|
|
|
|
}
|
2017-10-28 21:16:03 +02:00
|
|
|
switch errors.Cause(err) {
|
|
|
|
case vfs.OK:
|
|
|
|
return nil
|
2020-04-21 17:31:43 +02:00
|
|
|
case vfs.ENOENT, fs.ErrorDirNotFound, fs.ErrorObjectNotFound:
|
2017-10-28 21:16:03 +02:00
|
|
|
return fuse.ENOENT
|
2020-04-21 17:31:43 +02:00
|
|
|
case vfs.EEXIST, fs.ErrorDirExists:
|
2017-10-28 21:16:03 +02:00
|
|
|
return fuse.EEXIST
|
2020-04-21 17:31:43 +02:00
|
|
|
case vfs.EPERM, fs.ErrorPermissionDenied:
|
2017-11-03 12:35:36 +01:00
|
|
|
return fuse.EPERM
|
|
|
|
case vfs.ECLOSED:
|
|
|
|
return fuse.Errno(syscall.EBADF)
|
|
|
|
case vfs.ENOTEMPTY:
|
|
|
|
return fuse.Errno(syscall.ENOTEMPTY)
|
2017-10-28 21:16:03 +02:00
|
|
|
case vfs.ESPIPE:
|
|
|
|
return fuse.Errno(syscall.ESPIPE)
|
|
|
|
case vfs.EBADF:
|
|
|
|
return fuse.Errno(syscall.EBADF)
|
|
|
|
case vfs.EROFS:
|
|
|
|
return fuse.Errno(syscall.EROFS)
|
2020-04-21 17:31:43 +02:00
|
|
|
case vfs.ENOSYS, fs.ErrorNotImplemented:
|
2017-10-31 16:33:08 +01:00
|
|
|
return fuse.ENOSYS
|
2018-02-23 23:39:28 +01:00
|
|
|
case vfs.EINVAL:
|
|
|
|
return fuse.Errno(syscall.EINVAL)
|
2017-05-02 23:35:07 +02:00
|
|
|
}
|
|
|
|
return err
|
2017-05-04 22:49:06 +02:00
|
|
|
}
|