mount: Implement FUSE mount options - fixes #653

This commit is contained in:
Nick Craig-Wood 2016-09-09 08:39:19 +01:00
parent 5b913884cf
commit 5c91623148
4 changed files with 79 additions and 11 deletions

View file

@ -130,6 +130,8 @@ var _ fusefs.Node = (*Dir)(nil)
// Attr updates the attribes of a directory
func (d *Dir) Attr(ctx context.Context, a *fuse.Attr) error {
fs.Debug(d.path, "Dir.Attr")
a.Gid = gid
a.Uid = uid
a.Mode = os.ModeDir | dirPerms
// FIXME include Valid so get some caching? Also mtime
return nil

View file

@ -46,6 +46,8 @@ func (f *File) Attr(ctx context.Context, a *fuse.Attr) error {
f.mu.Lock()
defer f.mu.Unlock()
fs.Debug(f.o, "File.Attr")
a.Gid = gid
a.Uid = uid
a.Mode = filePerms
// if o is nil it isn't valid yet, so return the size so far
if f.o == nil {

View file

@ -10,12 +10,6 @@ import (
"github.com/ncw/rclone/fs"
)
// Default permissions
const (
dirPerms = 0755
filePerms = 0644
)
// FS represents the top level filing system
type FS struct {
f fs.Fs
@ -30,6 +24,36 @@ func (f *FS) Root() (fusefs.Node, error) {
return newDir(f.f, ""), nil
}
// mountOptions configures the options from the command line flags
func mountOptions(device string) (options []fuse.MountOption) {
options = []fuse.MountOption{
fuse.MaxReadahead(uint32(maxReadAhead)),
fuse.Subtype("rclone"),
fuse.FSName(device), fuse.VolumeName(device),
fuse.NoAppleDouble(),
fuse.NoAppleXattr(),
}
if allowNonEmpty {
options = append(options, fuse.AllowNonEmptyMount())
}
if allowOther {
options = append(options, fuse.AllowOther())
}
if allowRoot {
options = append(options, fuse.AllowRoot())
}
if defaultPermissions {
options = append(options, fuse.DefaultPermissions())
}
if readOnly {
options = append(options, fuse.ReadOnly())
}
if writebackCache {
options = append(options, fuse.WritebackCache())
}
return options
}
// mount the file system
//
// The mount point will be ready when this returns.
@ -37,7 +61,7 @@ func (f *FS) Root() (fusefs.Node, error) {
// returns an error, and an error channel for the serve process to
// report an error when fusermount is called.
func mount(f fs.Fs, mountpoint string) (<-chan error, error) {
c, err := fuse.Mount(mountpoint)
c, err := fuse.Mount(mountpoint, mountOptions(f.Name()+":"+f.Root())...)
if err != nil {
return nil, err
}

View file

@ -5,23 +5,56 @@
package mount
import (
"log"
"os"
"bazil.org/fuse"
"github.com/ncw/rclone/cmd"
"github.com/ncw/rclone/fs"
"github.com/pkg/errors"
"github.com/spf13/cobra"
"golang.org/x/sys/unix"
)
// Globals
var (
noModTime = false
debugFUSE = false
// mount options
readOnly = false
allowNonEmpty = false
allowRoot = false
allowOther = false
defaultPermissions = false
writebackCache = false
maxReadAhead fs.SizeSuffix = 128 * 1024
umask = 0
uid = uint32(unix.Geteuid())
gid = uint32(unix.Getegid())
// foreground = false
// default permissions for directories - modified by umask in Mount
dirPerms = os.FileMode(0777)
filePerms = os.FileMode(0666)
)
func init() {
umask = unix.Umask(0) // read the umask
unix.Umask(umask) // set it back to what it was
cmd.Root.AddCommand(mountCmd)
mountCmd.Flags().BoolVarP(&noModTime, "no-modtime", "", false, "Don't read the modification time (can speed things up).")
mountCmd.Flags().BoolVarP(&debugFUSE, "debug-fuse", "", false, "Debug the FUSE internals - needs -v.")
mountCmd.Flags().BoolVarP(&noModTime, "no-modtime", "", noModTime, "Don't read the modification time (can speed things up).")
mountCmd.Flags().BoolVarP(&debugFUSE, "debug-fuse", "", debugFUSE, "Debug the FUSE internals - needs -v.")
// mount options
mountCmd.Flags().BoolVarP(&readOnly, "read-only", "", readOnly, "Mount read-only.")
mountCmd.Flags().BoolVarP(&allowNonEmpty, "allow-non-empty", "", allowNonEmpty, "Allow mounting over a non-empty directory.")
mountCmd.Flags().BoolVarP(&allowRoot, "allow-root", "", allowRoot, "Allow access to root user.")
mountCmd.Flags().BoolVarP(&allowOther, "allow-other", "", allowOther, "Allow access to other users.")
mountCmd.Flags().BoolVarP(&defaultPermissions, "default-permissions", "", defaultPermissions, "Makes kernel enforce access control based on the file mode.")
mountCmd.Flags().BoolVarP(&writebackCache, "write-back-cache", "", writebackCache, "Makes kernel buffer writes before sending them to rclone. Without this, writethrough caching is used.")
mountCmd.Flags().VarP(&maxReadAhead, "max-read-ahead", "", "The number of bytes that can be prefetched for sequential reads.")
mountCmd.Flags().IntVarP(&umask, "umask", "", umask, "Override the permission bits set by the filesystem.")
mountCmd.Flags().Uint32VarP(&uid, "uid", "", uid, "Override the uid field set by the filesystem.")
mountCmd.Flags().Uint32VarP(&gid, "gid", "", gid, "Override the gid field set by the filesystem.")
//mountCmd.Flags().BoolVarP(&foreground, "foreground", "", foreground, "Do not detach.")
}
var mountCmd = &cobra.Command{
@ -85,10 +118,13 @@ mount won't do that, so will be less reliable than the rclone command.
* Preserve timestamps
* Move directories
`,
RunE: func(command *cobra.Command, args []string) error {
Run: func(command *cobra.Command, args []string) {
cmd.CheckArgs(2, 2, command, args)
fdst := cmd.NewFsDst(args)
return Mount(fdst, args[1])
err := Mount(fdst, args[1])
if err != nil {
log.Fatalf("Fatal error: %v", err)
}
},
}
@ -102,6 +138,10 @@ func Mount(f fs.Fs, mountpoint string) error {
}
}
// Set permissions
dirPerms = 0777 &^ os.FileMode(umask)
filePerms = 0666 &^ os.FileMode(umask)
// Mount it
errChan, err := mount(f, mountpoint)
if err != nil {