rclone/cmd/mount/fs.go
Nick Craig-Wood af8ba18580 mount: disable mount for freebsd
The upstream library rclone uses for rclone mount no longer supports
freebsd. Not only is it broken, but it no longer compiles.

This patch disables rclone mount for freebsd.

However all is not lost for freebsd users - compiling rclone with the
`cmount` tag, so `go install -tags cmount` will install a working
`rclone mount` command which uses cgofuse and the libfuse C library
directly.

Note that the binaries from rclone.org will not have mount support as
we don't have a freebsd build machine in CI and it is very hard to
cross compile cmount.

See: https://github.com/bazil/fuse/issues/280
Fixes #5843
2023-10-29 15:46:41 +00:00

108 lines
2.9 KiB
Go

// FUSE main Fs
//go:build linux
// +build linux
package mount
import (
"context"
"syscall"
"bazil.org/fuse"
fusefs "bazil.org/fuse/fs"
"github.com/rclone/rclone/cmd/mountlib"
"github.com/rclone/rclone/fs"
"github.com/rclone/rclone/fs/fserrors"
"github.com/rclone/rclone/fs/log"
"github.com/rclone/rclone/vfs"
)
// FS represents the top level filing system
type FS struct {
*vfs.VFS
f fs.Fs
opt *mountlib.Options
server *fusefs.Server
}
// Check interface satisfied
var _ fusefs.FS = (*FS)(nil)
// NewFS makes a new FS
func NewFS(VFS *vfs.VFS, opt *mountlib.Options) *FS {
fsys := &FS{
VFS: VFS,
f: VFS.Fs(),
opt: opt,
}
return fsys
}
// Root returns the root node
func (f *FS) Root() (node fusefs.Node, err error) {
defer log.Trace("", "")("node=%+v, err=%v", &node, &err)
root, err := f.VFS.Root()
if err != nil {
return nil, translateError(err)
}
return &Dir{root, f}, nil
}
// Check interface satisfied
var _ fusefs.FSStatfser = (*FS)(nil)
// Statfs is called to obtain file system metadata.
// It should write that data to resp.
func (f *FS) Statfs(ctx context.Context, req *fuse.StatfsRequest, resp *fuse.StatfsResponse) (err error) {
defer log.Trace("", "")("stat=%+v, err=%v", resp, &err)
const blockSize = 4096
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.
mountlib.ClipBlocks(&resp.Blocks)
mountlib.ClipBlocks(&resp.Bfree)
mountlib.ClipBlocks(&resp.Bavail)
return nil
}
// Translate errors from mountlib
func translateError(err error) error {
if err == nil {
return nil
}
_, uErr := fserrors.Cause(err)
switch uErr {
case vfs.OK:
return nil
case vfs.ENOENT, fs.ErrorDirNotFound, fs.ErrorObjectNotFound:
return fuse.Errno(syscall.ENOENT)
case vfs.EEXIST, fs.ErrorDirExists:
return fuse.Errno(syscall.EEXIST)
case vfs.EPERM, fs.ErrorPermissionDenied:
return fuse.Errno(syscall.EPERM)
case vfs.ECLOSED:
return fuse.Errno(syscall.EBADF)
case vfs.ENOTEMPTY:
return fuse.Errno(syscall.ENOTEMPTY)
case vfs.ESPIPE:
return fuse.Errno(syscall.ESPIPE)
case vfs.EBADF:
return fuse.Errno(syscall.EBADF)
case vfs.EROFS:
return fuse.Errno(syscall.EROFS)
case vfs.ENOSYS, fs.ErrorNotImplemented:
return syscall.ENOSYS
case vfs.EINVAL:
return fuse.Errno(syscall.EINVAL)
}
fs.Errorf(nil, "IO error: %v", err)
return err
}