github.com/zignig/go-ipfs@v0.0.0-20141111235910-c9e5fdf55a52/fuse/ipns/mount_unix.go (about)

     1  package ipns
     2  
     3  import (
     4  	"fmt"
     5  	"os"
     6  	"os/exec"
     7  	"os/signal"
     8  	"runtime"
     9  	"syscall"
    10  	"time"
    11  
    12  	"github.com/jbenet/go-ipfs/Godeps/_workspace/src/bazil.org/fuse"
    13  	"github.com/jbenet/go-ipfs/Godeps/_workspace/src/bazil.org/fuse/fs"
    14  	"github.com/jbenet/go-ipfs/core"
    15  )
    16  
    17  // Mount mounts an IpfsNode instance at a particular path. It
    18  // serves until the process receives exit signals (to Unmount).
    19  func Mount(ipfs *core.IpfsNode, fpath string, ipfspath string) error {
    20  
    21  	sigc := make(chan os.Signal, 1)
    22  	signal.Notify(sigc, syscall.SIGHUP, syscall.SIGINT,
    23  		syscall.SIGTERM, syscall.SIGQUIT)
    24  
    25  	go func() {
    26  		defer ipfs.Network.Close()
    27  		<-sigc
    28  		for {
    29  			err := Unmount(fpath)
    30  			if err == nil {
    31  				return
    32  			}
    33  			time.Sleep(time.Millisecond * 100)
    34  		}
    35  	}()
    36  
    37  	c, err := fuse.Mount(fpath)
    38  	if err != nil {
    39  		return err
    40  	}
    41  	defer c.Close()
    42  
    43  	fsys, err := NewIpns(ipfs, ipfspath)
    44  	if err != nil {
    45  		return err
    46  	}
    47  
    48  	err = fs.Serve(c, fsys)
    49  	if err != nil {
    50  		return err
    51  	}
    52  
    53  	// check if the mount process has an error to report
    54  	<-c.Ready
    55  	if err := c.MountError; err != nil {
    56  		return err
    57  	}
    58  	return nil
    59  }
    60  
    61  // Unmount attempts to unmount the provided FUSE mount point, forcibly
    62  // if necessary.
    63  func Unmount(point string) error {
    64  	fmt.Printf("Unmounting %s...\n", point)
    65  
    66  	var cmd *exec.Cmd
    67  	switch runtime.GOOS {
    68  	case "darwin":
    69  		cmd = exec.Command("diskutil", "umount", "force", point)
    70  	case "linux":
    71  		cmd = exec.Command("fusermount", "-u", point)
    72  	default:
    73  		return fmt.Errorf("unmount: unimplemented")
    74  	}
    75  
    76  	errc := make(chan error, 1)
    77  	go func() {
    78  		if err := exec.Command("umount", point).Run(); err == nil {
    79  			errc <- err
    80  		}
    81  		// retry to unmount with the fallback cmd
    82  		errc <- cmd.Run()
    83  	}()
    84  
    85  	select {
    86  	case <-time.After(1 * time.Second):
    87  		return fmt.Errorf("umount timeout")
    88  	case err := <-errc:
    89  		return err
    90  	}
    91  }