Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 9 additions & 4 deletions fuse.go
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ func (e *MountpointDoesNotExistError) Error() string {
// After a successful return, caller must call Close to free
// resources.
func Mount(dir string, options ...MountOption) (*Conn, error) {
conf := mountConfig{
conf := MountConfig{
options: make(map[string]string),
initFlags: InitAsyncDIO | InitSetxattrExt,
}
Expand All @@ -154,7 +154,12 @@ func Mount(dir string, options ...MountOption) (*Conn, error) {
}

c := &Conn{}
f, err := mount(dir, &conf)
m := mount
if conf.mountFunc != nil {
m = conf.mountFunc
}

f, err := m(dir, &conf)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -182,7 +187,7 @@ var (
ErrClosedWithoutInit = errors.New("fuse connection closed without init")
)

func initMount(c *Conn, conf *mountConfig) error {
func initMount(c *Conn, conf *MountConfig) error {
req, err := c.ReadRequest()
if err != nil {
if err == io.EOF {
Expand Down Expand Up @@ -215,7 +220,7 @@ func initMount(c *Conn, conf *mountConfig) error {
c.flags = r.Flags & (InitBigWrites | InitParallelDirOps | conf.initFlags)
s := &initResponse{
Library: proto,
MaxReadahead: conf.maxReadahead,
MaxReadahead: conf.MaxReadahead,
Flags: c.flags,
MaxBackground: conf.maxBackground,
CongestionThreshold: conf.congestionThreshold,
Expand Down
4 changes: 2 additions & 2 deletions mount_freebsd.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ func isBoringMountFusefsError(err error) bool {
return false
}

func mount(dir string, conf *mountConfig) (*os.File, error) {
func mount(dir string, conf *MountConfig) (*os.File, error) {
for k, v := range conf.options {
if strings.Contains(k, ",") || strings.Contains(v, ",") {
// Silly limitation but the mount helper does not
Expand All @@ -64,7 +64,7 @@ func mount(dir string, conf *mountConfig) (*os.File, error) {
cmd := exec.Command(
"/sbin/mount_fusefs",
"--safe",
"-o", conf.getOptions(),
"-o", conf.GetOptions(),
"3",
dir,
)
Expand Down
4 changes: 2 additions & 2 deletions mount_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ func isBoringFusermountError(err error) bool {
return false
}

func mount(dir string, conf *mountConfig) (fusefd *os.File, err error) {
func mount(dir string, conf *MountConfig) (fusefd *os.File, err error) {
fds, err := syscall.Socketpair(syscall.AF_UNIX, syscall.SOCK_STREAM, 0)
if err != nil {
return nil, fmt.Errorf("socketpair error: %v", err)
Expand All @@ -69,7 +69,7 @@ func mount(dir string, conf *mountConfig) (fusefd *os.File, err error) {

cmd := exec.Command(
"fusermount3",
"-o", conf.getOptions(),
"-o", conf.GetOptions(),
"--",
dir,
)
Expand Down
78 changes: 52 additions & 26 deletions options.go
Original file line number Diff line number Diff line change
@@ -1,21 +1,25 @@
package fuse

import (
"os"
"strings"
)

func dummyOption(conf *mountConfig) error {
func dummyOption(conf *MountConfig) error {
return nil
}

// mountConfig holds the configuration for a mount operation.
// MountConfig holds the configuration for a mount operation.
// Use it by passing MountOption values to Mount.
type mountConfig struct {
type MountConfig struct {
options map[string]string
maxReadahead uint32
MaxReadahead uint32
initFlags InitFlags
maxBackground uint16
congestionThreshold uint16

mountFunc MFunc
umountFunc UMFunc
}

func escapeComma(s string) string {
Expand All @@ -24,10 +28,10 @@ func escapeComma(s string) string {
return s
}

// getOptions makes a string of options suitable for passing to FUSE
// GetOptions makes a string of options suitable for passing to FUSE
// mount flag `-o`. Returns an empty string if no options were set.
// Any platform specific adjustments should happen before the call.
func (m *mountConfig) getOptions() string {
func (m *MountConfig) GetOptions() string {
var opts []string
for k, v := range m.options {
k = escapeComma(k)
Expand All @@ -39,17 +43,23 @@ func (m *mountConfig) getOptions() string {
return strings.Join(opts, ",")
}

type mountOption func(*mountConfig) error
type mountOption func(*MountConfig) error

// MountOption is passed to Mount to change the behavior of the mount.
type MountOption mountOption

// MFunc is a user-specified mount function.
type MFunc func(string, *MountConfig) (*os.File, error)

// UMFunc is a user-specified umount function.
type UMFunc func(string) error

// FSName sets the file system name (also called source) that is
// visible in the list of mounted file systems.
//
// FreeBSD ignores this option.
func FSName(name string) MountOption {
return func(conf *mountConfig) error {
return func(conf *MountConfig) error {
conf.options["fsname"] = name
return nil
}
Expand All @@ -61,7 +71,7 @@ func FSName(name string) MountOption {
//
// FreeBSD ignores this option.
func Subtype(fstype string) MountOption {
return func(conf *mountConfig) error {
return func(conf *MountConfig) error {
conf.options["subtype"] = fstype
return nil
}
Expand All @@ -77,7 +87,7 @@ func DaemonTimeout(name string) MountOption {

// AllowOther allows other users to access the file system.
func AllowOther() MountOption {
return func(conf *mountConfig) error {
return func(conf *MountConfig) error {
conf.options["allow_other"] = ""
return nil
}
Expand All @@ -86,7 +96,7 @@ func AllowOther() MountOption {
// AllowDev enables interpreting character or block special devices on the
// filesystem.
func AllowDev() MountOption {
return func(conf *mountConfig) error {
return func(conf *MountConfig) error {
conf.options["dev"] = ""
return nil
}
Expand All @@ -95,7 +105,7 @@ func AllowDev() MountOption {
// AllowSUID allows set-user-identifier or set-group-identifier bits to take
// effect.
func AllowSUID() MountOption {
return func(conf *mountConfig) error {
return func(conf *MountConfig) error {
conf.options["suid"] = ""
return nil
}
Expand All @@ -110,15 +120,15 @@ func AllowSUID() MountOption {
//
// FreeBSD ignores this option.
func DefaultPermissions() MountOption {
return func(conf *mountConfig) error {
return func(conf *MountConfig) error {
conf.options["default_permissions"] = ""
return nil
}
}

// ReadOnly makes the mount read-only.
func ReadOnly() MountOption {
return func(conf *mountConfig) error {
return func(conf *MountConfig) error {
conf.options["ro"] = ""
return nil
}
Expand All @@ -132,8 +142,24 @@ func ReadOnly() MountOption {
// originate from any client process. This usually tremendously
// improves read performance.
func MaxReadahead(n uint32) MountOption {
return func(conf *mountConfig) error {
conf.maxReadahead = n
return func(conf *MountConfig) error {
conf.MaxReadahead = n
return nil
}
}

// MountFunc allows the user to specify their own mount function.
func MountFunc(f MFunc) MountOption {
return func(conf *MountConfig) error {
conf.mountFunc = f
return nil
}
}

// UMountFunc allow the user to specify their own umount function.
func UMountFunc(f UMFunc) MountOption {
return func(conf *MountConfig) error {
conf.umountFunc = f
return nil
}
}
Expand All @@ -142,7 +168,7 @@ func MaxReadahead(n uint32) MountOption {
// handle. Without this, there is at most one request in flight at a
// time.
func AsyncRead() MountOption {
return func(conf *mountConfig) error {
return func(conf *MountConfig) error {
conf.initFlags |= InitAsyncRead
return nil
}
Expand All @@ -152,15 +178,15 @@ func AsyncRead() MountOption {
// them to the FUSE server. Without this, writethrough caching is
// used.
func WritebackCache() MountOption {
return func(conf *mountConfig) error {
return func(conf *MountConfig) error {
conf.initFlags |= InitWritebackCache
return nil
}
}

// CacheSymlinks enables the kernel to cache symlink contents.
func CacheSymlinks() MountOption {
return func(conf *mountConfig) error {
return func(conf *MountConfig) error {
conf.initFlags |= InitCacheSymlinks
return nil
}
Expand All @@ -169,7 +195,7 @@ func CacheSymlinks() MountOption {
// ExplicitInvalidateData stops the kernel from invalidating cached file data automatically.
// Use e.g. `InvalidateNodeData` to invalidate cached data as needed.
func ExplicitInvalidateData() MountOption {
return func(conf *mountConfig) error {
return func(conf *MountConfig) error {
conf.initFlags |= InitExplicitInvalidateData
return nil
}
Expand All @@ -181,7 +207,7 @@ func ExplicitInvalidateData() MountOption {
// default these mounts are rejected to prevent accidental covering up
// of data, which could for example prevent automatic backup.
func AllowNonEmptyMount() MountOption {
return func(conf *mountConfig) error {
return func(conf *MountConfig) error {
conf.options["nonempty"] = ""
return nil
}
Expand All @@ -194,7 +220,7 @@ func AllowNonEmptyMount() MountOption {
// On Linux, this can be adjusted on the fly with
// /sys/fs/fuse/connections/CONN/max_background
func MaxBackground(n uint16) MountOption {
return func(conf *mountConfig) error {
return func(conf *MountConfig) error {
conf.maxBackground = n
return nil
}
Expand All @@ -209,7 +235,7 @@ func MaxBackground(n uint16) MountOption {
func CongestionThreshold(n uint16) MountOption {
// TODO to test this, we'd have to figure out our connection id
// and read /sys
return func(conf *mountConfig) error {
return func(conf *MountConfig) error {
conf.congestionThreshold = n
return nil
}
Expand All @@ -219,7 +245,7 @@ func CongestionThreshold(n uint16) MountOption {
// useful for distributed filesystems with global locking. Without
// this, kernel manages local locking automatically.
func LockingFlock() MountOption {
return func(conf *mountConfig) error {
return func(conf *MountConfig) error {
conf.initFlags |= InitFlockLocks
return nil
}
Expand All @@ -232,7 +258,7 @@ func LockingFlock() MountOption {
// Beware POSIX locks are a broken API with unintuitive behavior for
// callers.
func LockingPOSIX() MountOption {
return func(conf *mountConfig) error {
return func(conf *MountConfig) error {
conf.initFlags |= InitPOSIXLocks
return nil
}
Expand All @@ -242,7 +268,7 @@ func LockingPOSIX() MountOption {
//
// This is the newer `InitHandleKillPrivV2` interface from FUSE protocol 7.33, not the deprecated one from 7.26.
func HandleKillPriv() MountOption {
return func(conf *mountConfig) error {
return func(conf *MountConfig) error {
conf.initFlags |= InitHandleKillPrivV2
return nil
}
Expand Down
2 changes: 1 addition & 1 deletion options_freebsd.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package fuse

func daemonTimeout(name string) MountOption {
return func(conf *mountConfig) error {
return func(conf *MountConfig) error {
conf.options["timeout"] = name
return nil
}
Expand Down
2 changes: 1 addition & 1 deletion options_helper_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ package fuse

// for TestMountOptionCommaError
func ForTestSetMountOption(k, v string) MountOption {
fn := func(conf *mountConfig) error {
fn := func(conf *MountConfig) error {
conf.options[k] = v
return nil
}
Expand Down
15 changes: 14 additions & 1 deletion unmount.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,19 @@
package fuse

// Unmount tries to unmount the filesystem mounted at dir.
func Unmount(dir string) error {
func Unmount(dir string, options ...MountOption) error {
conf := MountConfig{
options: make(map[string]string),
}
for _, option := range options {
if err := option(&conf); err != nil {
return err
}
}

if conf.umountFunc != nil {
return conf.umountFunc(dir)
}

return unmount(dir)
}