diff --git a/fuse/ipns/ipns_unix.go b/fuse/ipns/ipns_unix.go index 56f964b12..a725c382a 100644 --- a/fuse/ipns/ipns_unix.go +++ b/fuse/ipns/ipns_unix.go @@ -1,14 +1,9 @@ package ipns import ( - "fmt" "io/ioutil" "os" - "os/exec" - "os/signal" "path/filepath" - "runtime" - "syscall" "time" "bytes" @@ -469,130 +464,3 @@ func (n *Node) Rename(req *fuse.RenameRequest, newDir fs.Node, intr fs.Intr) fus } return nil } - -// Mount mounts an IpfsNode instance at a particular path. It -// serves until the process receives exit signals (to Unmount). -func Mount(ipfs *core.IpfsNode, fpath string, ipfspath string) error { - - sigc := make(chan os.Signal, 1) - signal.Notify(sigc, syscall.SIGHUP, syscall.SIGINT, - syscall.SIGTERM, syscall.SIGQUIT) - - go func() { - <-sigc - for { - err := Unmount(fpath) - if err == nil { - return - } - time.Sleep(time.Millisecond * 100) - } - ipfs.Network.Close() - }() - - c, err := fuse.Mount(fpath) - if err != nil { - return err - } - defer c.Close() - - fsys, err := NewIpns(ipfs, ipfspath) - if err != nil { - return err - } - - err = fs.Serve(c, fsys) - if err != nil { - return err - } - - // check if the mount process has an error to report - <-c.Ready - if err := c.MountError; err != nil { - return err - } - return nil -} - -// Unmount attempts to unmount the provided FUSE mount point, forcibly -// if necessary. -func Unmount(point string) error { - fmt.Printf("Unmounting %s...\n", point) - - var cmd *exec.Cmd - switch runtime.GOOS { - case "darwin": - cmd = exec.Command("diskutil", "umount", "force", point) - case "linux": - cmd = exec.Command("fusermount", "-u", point) - default: - return fmt.Errorf("unmount: unimplemented") - } - - errc := make(chan error, 1) - go func() { - if err := exec.Command("umount", point).Run(); err == nil { - errc <- err - } - // retry to unmount with the fallback cmd - errc <- cmd.Run() - }() - - select { - case <-time.After(1 * time.Second): - return fmt.Errorf("umount timeout") - case err := <-errc: - return err - } -} - -type Link struct { - Target string -} - -func (l *Link) Attr() fuse.Attr { - log.Debug("Link attr.") - return fuse.Attr{ - Mode: os.ModeSymlink | 0555, - } -} - -func (l *Link) Readlink(req *fuse.ReadlinkRequest, intr fs.Intr) (string, fuse.Error) { - log.Debug("ReadLink: %s", l.Target) - return l.Target, nil -} - -type Republisher struct { - Timeout time.Duration - Publish chan struct{} - node *Node -} - -func NewRepublisher(n *Node, tout time.Duration) *Republisher { - return &Republisher{ - Timeout: tout, - Publish: make(chan struct{}), - node: n, - } -} - -func (np *Republisher) Run() { - for _ = range np.Publish { - timer := time.After(np.Timeout) - for { - select { - case <-timer: - //Do the publish! - log.Info("Publishing Changes!") - err := np.node.updateTree() - if err != nil { - log.Critical("updateTree error: %s", err) - } - goto done - case <-np.Publish: - timer = time.After(np.Timeout) - } - } - done: - } -} diff --git a/fuse/ipns/link_unix.go b/fuse/ipns/link_unix.go new file mode 100644 index 000000000..e81576c6e --- /dev/null +++ b/fuse/ipns/link_unix.go @@ -0,0 +1,24 @@ +package ipns + +import ( + "os" + + "github.com/jbenet/go-ipfs/Godeps/_workspace/src/bazil.org/fuse" + "github.com/jbenet/go-ipfs/Godeps/_workspace/src/bazil.org/fuse/fs" +) + +type Link struct { + Target string +} + +func (l *Link) Attr() fuse.Attr { + log.Debug("Link attr.") + return fuse.Attr{ + Mode: os.ModeSymlink | 0555, + } +} + +func (l *Link) Readlink(req *fuse.ReadlinkRequest, intr fs.Intr) (string, fuse.Error) { + log.Debug("ReadLink: %s", l.Target) + return l.Target, nil +} diff --git a/fuse/ipns/mount_unix.go b/fuse/ipns/mount_unix.go new file mode 100644 index 000000000..7df6f140c --- /dev/null +++ b/fuse/ipns/mount_unix.go @@ -0,0 +1,91 @@ +package ipns + +import ( + "fmt" + "os" + "os/exec" + "os/signal" + "runtime" + "syscall" + "time" + + "github.com/jbenet/go-ipfs/Godeps/_workspace/src/bazil.org/fuse" + "github.com/jbenet/go-ipfs/Godeps/_workspace/src/bazil.org/fuse/fs" + "github.com/jbenet/go-ipfs/core" +) + +// Mount mounts an IpfsNode instance at a particular path. It +// serves until the process receives exit signals (to Unmount). +func Mount(ipfs *core.IpfsNode, fpath string, ipfspath string) error { + + sigc := make(chan os.Signal, 1) + signal.Notify(sigc, syscall.SIGHUP, syscall.SIGINT, + syscall.SIGTERM, syscall.SIGQUIT) + + go func() { + <-sigc + for { + err := Unmount(fpath) + if err == nil { + return + } + time.Sleep(time.Millisecond * 100) + } + ipfs.Network.Close() + }() + + c, err := fuse.Mount(fpath) + if err != nil { + return err + } + defer c.Close() + + fsys, err := NewIpns(ipfs, ipfspath) + if err != nil { + return err + } + + err = fs.Serve(c, fsys) + if err != nil { + return err + } + + // check if the mount process has an error to report + <-c.Ready + if err := c.MountError; err != nil { + return err + } + return nil +} + +// Unmount attempts to unmount the provided FUSE mount point, forcibly +// if necessary. +func Unmount(point string) error { + fmt.Printf("Unmounting %s...\n", point) + + var cmd *exec.Cmd + switch runtime.GOOS { + case "darwin": + cmd = exec.Command("diskutil", "umount", "force", point) + case "linux": + cmd = exec.Command("fusermount", "-u", point) + default: + return fmt.Errorf("unmount: unimplemented") + } + + errc := make(chan error, 1) + go func() { + if err := exec.Command("umount", point).Run(); err == nil { + errc <- err + } + // retry to unmount with the fallback cmd + errc <- cmd.Run() + }() + + select { + case <-time.After(1 * time.Second): + return fmt.Errorf("umount timeout") + case err := <-errc: + return err + } +} diff --git a/fuse/ipns/repub_unix.go b/fuse/ipns/repub_unix.go new file mode 100644 index 000000000..93d07c92f --- /dev/null +++ b/fuse/ipns/repub_unix.go @@ -0,0 +1,38 @@ +package ipns + +import "time" + +type Republisher struct { + Timeout time.Duration + Publish chan struct{} + node *Node +} + +func NewRepublisher(n *Node, tout time.Duration) *Republisher { + return &Republisher{ + Timeout: tout, + Publish: make(chan struct{}), + node: n, + } +} + +func (np *Republisher) Run() { + for _ = range np.Publish { + timer := time.After(np.Timeout) + for { + select { + case <-timer: + //Do the publish! + log.Info("Publishing Changes!") + err := np.node.updateTree() + if err != nil { + log.Critical("updateTree error: %s", err) + } + goto done + case <-np.Publish: + timer = time.After(np.Timeout) + } + } + done: + } +}