github.com/hanwen/go-fuse@v1.0.0/fuse/mount_darwin.go (about) 1 // Copyright 2016 the Go-FUSE Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package fuse 6 7 import ( 8 "bytes" 9 "fmt" 10 "os" 11 "os/exec" 12 "path/filepath" 13 "strings" 14 "syscall" 15 ) 16 17 func openFUSEDevice() (*os.File, error) { 18 fs, err := filepath.Glob("/dev/osxfuse*") 19 if err != nil { 20 return nil, err 21 } 22 if len(fs) == 0 { 23 bin := oldLoadBin 24 if _, err := os.Stat(newLoadBin); err == nil { 25 bin = newLoadBin 26 } 27 28 cmd := exec.Command(bin) 29 if err := cmd.Run(); err != nil { 30 return nil, err 31 } 32 fs, err = filepath.Glob("/dev/osxfuse*") 33 if err != nil { 34 return nil, err 35 } 36 } 37 38 for _, fn := range fs { 39 f, err := os.OpenFile(fn, os.O_RDWR, 0) 40 if err != nil { 41 continue 42 } 43 return f, nil 44 } 45 46 return nil, fmt.Errorf("all FUSE devices busy") 47 } 48 49 const oldLoadBin = "/Library/Filesystems/osxfusefs.fs/Support/load_osxfusefs" 50 const newLoadBin = "/Library/Filesystems/osxfuse.fs/Contents/Resources/load_osxfuse" 51 52 const oldMountBin = "/Library/Filesystems/osxfusefs.fs/Support/mount_osxfusefs" 53 const newMountBin = "/Library/Filesystems/osxfuse.fs/Contents/Resources/mount_osxfuse" 54 55 func mount(mountPoint string, opts *MountOptions, ready chan<- error) (fd int, err error) { 56 f, err := openFUSEDevice() 57 if err != nil { 58 return 0, err 59 } 60 61 bin := oldMountBin 62 if _, err := os.Stat(newMountBin); err == nil { 63 bin = newMountBin 64 } 65 66 cmd := exec.Command(bin, "-o", strings.Join(opts.optionsStrings(), ","), "-o", fmt.Sprintf("iosize=%d", opts.MaxWrite), "3", mountPoint) 67 cmd.ExtraFiles = []*os.File{f} 68 cmd.Env = append(os.Environ(), "MOUNT_FUSEFS_CALL_BY_LIB=", "MOUNT_OSXFUSE_CALL_BY_LIB=", 69 "MOUNT_OSXFUSE_DAEMON_PATH="+os.Args[0], 70 "MOUNT_FUSEFS_DAEMON_PATH="+os.Args[0]) 71 72 var out, errOut bytes.Buffer 73 cmd.Stdout = &out 74 cmd.Stderr = &errOut 75 76 if err := cmd.Start(); err != nil { 77 f.Close() 78 return 0, err 79 } 80 go func() { 81 err := cmd.Wait() 82 if err != nil { 83 err = fmt.Errorf("mount_osxfusefs failed: %v. Stderr: %s, Stdout: %s", err, errOut.String(), out.String()) 84 } 85 86 ready <- err 87 close(ready) 88 }() 89 90 // The finalizer for f will close its fd so we return a dup. 91 defer f.Close() 92 return syscall.Dup(int(f.Fd())) 93 } 94 95 func unmount(dir string) error { 96 return syscall.Unmount(dir, 0) 97 }