Support OSXFUSE 3.x, fall back to 2.x if needed
Also supports custom bundled OSXFUSE installs.geesefs-0-30-9
parent
0b9db0a706
commit
eadfaa0742
|
@ -135,6 +135,14 @@ type MountConfig struct {
|
||||||
// default name involving the string 'osxfuse' is used.
|
// default name involving the string 'osxfuse' is used.
|
||||||
VolumeName string
|
VolumeName string
|
||||||
|
|
||||||
|
// OS X only.
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
OSXFUSELocations []OSXFUSEPaths
|
||||||
|
|
||||||
// Additional key=value options to pass unadulterated to the underlying mount
|
// Additional key=value options to pass unadulterated to the underlying mount
|
||||||
// command. See `man 8 mount`, the fuse documentation, etc. for
|
// command. See `man 8 mount`, the fuse documentation, etc. for
|
||||||
// system-specific information.
|
// system-specific information.
|
||||||
|
@ -230,3 +238,38 @@ func (c *MountConfig) toOptionsString() string {
|
||||||
|
|
||||||
return strings.Join(components, ",")
|
return strings.Join(components, ",")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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
|
||||||
|
|
||||||
|
// Environment variable used to pass the path to the executable calling the
|
||||||
|
// mount helper.
|
||||||
|
DaemonVar 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",
|
||||||
|
DaemonVar: "MOUNT_OSXFUSE_DAEMON_PATH",
|
||||||
|
}
|
||||||
|
OSXFUSELocationV2 = OSXFUSEPaths{
|
||||||
|
DevicePrefix: "/dev/osxfuse",
|
||||||
|
Load: "/Library/Filesystems/osxfusefs.fs/Support/load_osxfusefs",
|
||||||
|
Mount: "/Library/Filesystems/osxfusefs.fs/Support/mount_osxfusefs",
|
||||||
|
DaemonVar: "MOUNT_FUSEFS_DAEMON_PATH",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
|
@ -14,10 +14,16 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
var errNoAvail = errors.New("no available fuse devices")
|
var errNoAvail = errors.New("no available fuse devices")
|
||||||
var errNotLoaded = errors.New("osxfusefs is not loaded")
|
var errNotLoaded = errors.New("osxfuse is not loaded")
|
||||||
|
|
||||||
func loadOSXFUSE() error {
|
// errOSXFUSENotFound is returned from Mount when the OSXFUSE installation is
|
||||||
cmd := exec.Command("/Library/Filesystems/osxfusefs.fs/Support/load_osxfusefs")
|
// not detected.
|
||||||
|
//
|
||||||
|
// Make sure OSXFUSE is installed, or see OSXFUSELocations for customization.
|
||||||
|
var errOSXFUSENotFound = errors.New("cannot locate OSXFUSE")
|
||||||
|
|
||||||
|
func loadOSXFUSE(bin string) error {
|
||||||
|
cmd := exec.Command(bin)
|
||||||
cmd.Dir = "/"
|
cmd.Dir = "/"
|
||||||
cmd.Stdout = os.Stdout
|
cmd.Stdout = os.Stdout
|
||||||
cmd.Stderr = os.Stderr
|
cmd.Stderr = os.Stderr
|
||||||
|
@ -25,10 +31,10 @@ func loadOSXFUSE() error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func openOSXFUSEDev() (dev *os.File, err error) {
|
func openOSXFUSEDev(devPrefix string) (dev *os.File, err error) {
|
||||||
// Try each device name.
|
// Try each device name.
|
||||||
for i := uint64(0); ; i++ {
|
for i := uint64(0); ; i++ {
|
||||||
path := fmt.Sprintf("/dev/osxfuse%d", i)
|
path := devPrefix + strconv.FormatUint(i, 10)
|
||||||
dev, err = os.OpenFile(path, os.O_RDWR, 0000)
|
dev, err = os.OpenFile(path, os.O_RDWR, 0000)
|
||||||
if os.IsNotExist(err) {
|
if os.IsNotExist(err) {
|
||||||
if i == 0 {
|
if i == 0 {
|
||||||
|
@ -52,11 +58,12 @@ func openOSXFUSEDev() (dev *os.File, err error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func callMount(
|
func callMount(
|
||||||
|
bin string,
|
||||||
|
daemonVar string,
|
||||||
dir string,
|
dir string,
|
||||||
cfg *MountConfig,
|
cfg *MountConfig,
|
||||||
dev *os.File,
|
dev *os.File,
|
||||||
ready chan<- error) (err error) {
|
ready chan<- error) (err error) {
|
||||||
const bin = "/Library/Filesystems/osxfusefs.fs/Support/mount_osxfusefs"
|
|
||||||
|
|
||||||
// The mount helper doesn't understand any escaping.
|
// The mount helper doesn't understand any escaping.
|
||||||
for k, v := range cfg.toMap() {
|
for k, v := range cfg.toMap() {
|
||||||
|
@ -85,8 +92,15 @@ func callMount(
|
||||||
)
|
)
|
||||||
cmd.ExtraFiles = []*os.File{dev}
|
cmd.ExtraFiles = []*os.File{dev}
|
||||||
cmd.Env = os.Environ()
|
cmd.Env = os.Environ()
|
||||||
|
// OSXFUSE <3.3.0
|
||||||
cmd.Env = append(cmd.Env, "MOUNT_FUSEFS_CALL_BY_LIB=")
|
cmd.Env = append(cmd.Env, "MOUNT_FUSEFS_CALL_BY_LIB=")
|
||||||
cmd.Env = append(cmd.Env, "MOUNT_FUSEFS_DAEMON_PATH="+bin)
|
// OSXFUSE >=3.3.0
|
||||||
|
cmd.Env = append(cmd.Env, "MOUNT_OSXFUSE_CALL_BY_LIB=")
|
||||||
|
|
||||||
|
daemon := os.Args[0]
|
||||||
|
if daemonVar != "" {
|
||||||
|
cmd.Env = append(cmd.Env, daemonVar+"="+daemon)
|
||||||
|
}
|
||||||
|
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
cmd.Stdout = &buf
|
cmd.Stdout = &buf
|
||||||
|
@ -122,34 +136,53 @@ func mount(
|
||||||
dir string,
|
dir string,
|
||||||
cfg *MountConfig,
|
cfg *MountConfig,
|
||||||
ready chan<- error) (dev *os.File, err error) {
|
ready chan<- error) (dev *os.File, err error) {
|
||||||
// Open the device.
|
// get OSXFUSE locations
|
||||||
dev, err = openOSXFUSEDev()
|
locations := cfg.OSXFUSELocations
|
||||||
|
if locations == nil {
|
||||||
|
locations = []OSXFUSEPaths{
|
||||||
|
OSXFUSELocationV3,
|
||||||
|
OSXFUSELocationV2,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Special case: we may need to explicitly load osxfuse. Load it, then try
|
for _, loc := range locations {
|
||||||
// again.
|
if _, err := os.Stat(loc.Mount); os.IsNotExist(err) {
|
||||||
if err == errNotLoaded {
|
// try the other locations
|
||||||
err = loadOSXFUSE()
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// Open the device.
|
||||||
|
dev, err = openOSXFUSEDev(loc.DevicePrefix)
|
||||||
|
|
||||||
|
// Special case: we may need to explicitly load osxfuse. Load it, then
|
||||||
|
// try again.
|
||||||
|
if err == errNotLoaded {
|
||||||
|
err = loadOSXFUSE(loc.Load)
|
||||||
|
if err != nil {
|
||||||
|
err = fmt.Errorf("loadOSXFUSE: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
dev, err = openOSXFUSEDev(loc.DevicePrefix)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Propagate errors.
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = fmt.Errorf("loadOSXFUSE: %v", err)
|
err = fmt.Errorf("openOSXFUSEDev: %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
dev, err = openOSXFUSEDev()
|
// Call the mount binary with the device.
|
||||||
}
|
err = callMount(loc.Mount, loc.DaemonVar, dir, cfg, dev, ready)
|
||||||
|
if err != nil {
|
||||||
|
dev.Close()
|
||||||
|
err = fmt.Errorf("callMount: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// Propagate errors.
|
|
||||||
if err != nil {
|
|
||||||
err = fmt.Errorf("openOSXFUSEDev: %v", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Call the mount binary with the device.
|
|
||||||
err = callMount(dir, cfg, dev, ready)
|
|
||||||
if err != nil {
|
|
||||||
dev.Close()
|
|
||||||
err = fmt.Errorf("callMount: %v", err)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
err = errOSXFUSENotFound
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue