Skip to content
This repository has been archived by the owner on Mar 19, 2021. It is now read-only.

Commit

Permalink
Support OSXFUSE 3.x, fall back to 2.x if needed
Browse files Browse the repository at this point in the history
Also supports custom bundled OSXFUSE installs.

OSXFUSE 3.x is still currently in beta, approach with caution.

All tests here pass on Yosemite with what should become OSXFUSE 3.0.6,
as discussed in
macfuse/macfuse#232 (comment)
  • Loading branch information
tv42 committed Sep 8, 2015
1 parent 5b16e66 commit 3c03e2f
Show file tree
Hide file tree
Showing 2 changed files with 84 additions and 20 deletions.
50 changes: 33 additions & 17 deletions mount_darwin.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,11 @@ import (
"syscall"
)

var errNoAvail = errors.New("no available fuse devices")

var errNotLoaded = errors.New("osxfuse is not loaded")
var (
errNoAvail = errors.New("no available fuse devices")
errNotLoaded = errors.New("osxfuse is not loaded")
errOSXFUSENotFound = errors.New("cannot locate OSXFUSE")
)

func loadOSXFUSE(bin string) error {
cmd := exec.Command(bin)
Expand Down Expand Up @@ -170,22 +172,36 @@ func callMount(bin string, dir string, conf *mountConfig, f *os.File, ready chan
}

func mount(dir string, conf *mountConfig, ready chan<- struct{}, errp *error) (*os.File, error) {
f, err := openOSXFUSEDev("/dev/osxfuse")
if err == errNotLoaded {
err = loadOSXFUSE("/Library/Filesystems/osxfusefs.fs/Support/load_osxfusefs")
locations := conf.osxfuseLocations
if locations == nil {
locations = []OSXFUSEPaths{
OSXFUSELocationV3,
OSXFUSELocationV2,
}
}
for _, loc := range locations {
f, err := openOSXFUSEDev(loc.DevicePrefix)
if err == errNotLoaded {
err = loadOSXFUSE(loc.Load)
if err != nil {
if os.IsNotExist(err) {
// try the other locations
continue
}
return nil, err
}
// try again
f, err = openOSXFUSEDev(loc.DevicePrefix)
}
if err != nil {
return nil, err
}
// try again
f, err = openOSXFUSEDev("/dev/osxfuse")
}
if err != nil {
return nil, err
}
err = callMount("/Library/Filesystems/osxfusefs.fs/Support/mount_osxfusefs", dir, conf, f, ready, errp)
if err != nil {
f.Close()
return nil, err
err = callMount(loc.Mount, dir, conf, f, ready, errp)
if err != nil {
f.Close()
return nil, err
}
return f, nil
}
return f, nil
return nil, errOSXFUSENotFound
}
54 changes: 51 additions & 3 deletions options.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,10 @@ func dummyOption(conf *mountConfig) error {
// mountConfig holds the configuration for a mount operation.
// Use it by passing MountOption values to Mount.
type mountConfig struct {
options map[string]string
maxReadahead uint32
initFlags InitFlags
options map[string]string
maxReadahead uint32
initFlags InitFlags
osxfuseLocations []OSXFUSEPaths
}

func escapeComma(s string) string {
Expand Down Expand Up @@ -168,3 +169,50 @@ func WritebackCache() MountOption {
return nil
}
}

// OSXFUSEPaths describes the paths used by an installed OSXFUSE
// version. See OSXFUSELocationV3 for typical values.
type OSXFUSEPaths struct {
// Prefix for the device file. At mount time, an incrementing
// number is suffixed until a free FUSE device is found.
DevicePrefix string
// Path of the load helper, used to load the kernel extension if
// no device files are found.
Load string
// Path of the mount helper, used for the actual mount operation.
Mount string
}

// Default paths for OSXFUSE. See OSXFUSELocations.
var (
OSXFUSELocationV3 = OSXFUSEPaths{
DevicePrefix: "/dev/osxfuse",
Load: "/Library/Filesystems/osxfuse.fs/Contents/Resources/load_osxfuse",
Mount: "/Library/Filesystems/osxfuse.fs/Contents/Resources/mount_osxfuse",
}
OSXFUSELocationV2 = OSXFUSEPaths{
DevicePrefix: "/dev/osxfuse",
Load: "/Library/Filesystems/osxfusefs.fs/Support/load_osxfusefs",
Mount: "/Library/Filesystems/osxfusefs.fs/Support/mount_osxfusefs",
}
)

// OSXFUSELocations sets where to look for OSXFUSE files. The
// arguments are all the possible locations. The previous locations
// are replaced.
//
// Without this option, OSXFUSELocationV3 and OSXFUSELocationV2 are
// used.
//
// OS X only. Others ignore this option.
func OSXFUSELocations(paths ...OSXFUSEPaths) MountOption {
return func(conf *mountConfig) error {
if len(paths) == 0 {
return errors.New("must specify at least one location for OSXFUSELocations")
}
// replace previous values, but make a copy so there's no
// worries about caller mutating their slice
conf.osxfuseLocations = append(conf.osxfuseLocations[:0], paths...)
return nil
}
}

0 comments on commit 3c03e2f

Please sign in to comment.