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  }