core/commands2: Added 'mount' command
Matt Bell committed
Nov 6, 2014 at 00:36 UTC
1c5979e549a647a9be71f878244b6b6d6c9a44da
4 files changed
+165
core/commands2/mount_darwin.go
new
+33
@@ -0,0 +1,33 @@
1
+package commands
2
+
3
+import (
4
+ "fmt"
5
+ "runtime"
6
+ "strings"
7
+ "syscall"
8
+)
9
+
10
+func init() {
11
+ // this is a hack, but until we need to do it another way, this works.
12
+ platformFuseChecks = darwinFuseCheckVersion
13
+}
14
+
15
+func darwinFuseCheckVersion() error {
16
+ // on OSX, check FUSE version.
17
+ if runtime.GOOS != "darwin" {
18
+ return nil
19
+ }
20
+
21
+ ov, err := syscall.Sysctl("osxfuse.version.number")
22
+ if err != nil {
23
+ return err
24
+ }
25
+
26
+ if strings.HasPrefix(ov, "2.7.") || strings.HasPrefix(ov, "2.8.") {
27
+ return nil
28
+ }
29
+
30
+ return fmt.Errorf("osxfuse version %s not supported.\n%s\n%s", ov,
31
+ "Older versions of osxfuse have kernel panic bugs; please upgrade!",
32
+ "https://github.com/jbenet/go-ipfs/issues/177")
33
+}
core/commands2/mount_unix.go
new
+117
@@ -0,0 +1,117 @@
1
+// +build linux darwin freebsd
2
+
3
+package commands
4
+
5
+import (
6
+ "fmt"
7
+ "time"
8
+
9
+ cmds "github.com/jbenet/go-ipfs/commands"
10
+ "github.com/jbenet/go-ipfs/config"
11
+ core "github.com/jbenet/go-ipfs/core"
12
+ ipns "github.com/jbenet/go-ipfs/fuse/ipns"
13
+ rofs "github.com/jbenet/go-ipfs/fuse/readonly"
14
+)
15
+
16
+// amount of time to wait for mount errors
17
+const mountTimeout = time.Second
18
+
19
+var mountCmd = &cmds.Command{
20
+ Options: []cmds.Option{
21
+ cmds.Option{[]string{"f"}, cmds.String},
22
+ cmds.Option{[]string{"n"}, cmds.String},
23
+ },
24
+ Help: `ipfs mount <os-path> - Mount an ipfs read-only mountpoint.
25
+
26
+ Mount ipfs at a read-only mountpoint on the OS. All ipfs objects
27
+ will be accessible under that directory. Note that the root will
28
+ not be listable, as it is virtual. Accessing known paths directly.
29
+`,
30
+ Run: func(res cmds.Response, req cmds.Request) {
31
+ ctx := req.Context()
32
+
33
+ // error if we aren't running node in online mode
34
+ if ctx.Node.Network == nil {
35
+ res.SetError(errNotOnline, cmds.ErrNormal)
36
+ return
37
+ }
38
+
39
+ if err := platformFuseChecks(); err != nil {
40
+ res.SetError(err, cmds.ErrNormal)
41
+ return
42
+ }
43
+
44
+ // update fsdir with flag.
45
+ fsdir := ctx.Config.Mounts.IPFS
46
+ opt, _ := req.Option("f")
47
+ if val, ok := opt.(string); ok && val != "" {
48
+ fsdir = val
49
+ }
50
+ fsdone := mountIpfs(ctx.Node, fsdir)
51
+
52
+ // get default mount points
53
+ nsdir := ctx.Config.Mounts.IPNS
54
+ opt, _ = req.Option("f")
55
+ if val, ok := opt.(string); ok && val != "" {
56
+ nsdir = val
57
+ }
58
+ nsdone := mountIpns(ctx.Node, nsdir, fsdir)
59
+
60
+ // wait until mounts return an error (or timeout if successful)
61
+ var err error
62
+ select {
63
+ case err = <-fsdone:
64
+ case err = <-nsdone:
65
+
66
+ // mounted successfully, we timed out with no errors
67
+ case <-time.After(mountTimeout):
68
+ output := ctx.Config.Mounts
69
+ res.SetOutput(&output)
70
+ return
71
+ }
72
+
73
+ res.SetError(err, cmds.ErrNormal)
74
+ },
75
+ Type: &config.Mounts{},
76
+ Marshallers: map[cmds.EncodingType]cmds.Marshaller{
77
+ cmds.Text: func(res cmds.Response) ([]byte, error) {
78
+ v := res.Output().(*config.Mounts)
79
+ s := fmt.Sprintf("IPFS mounted at: %s\n", v.IPFS)
80
+ s += fmt.Sprintf("IPNS mounted at: %s\n", v.IPNS)
81
+ return []byte(s), nil
82
+ },
83
+ },
84
+}
85
+
86
+func mountIpfs(node *core.IpfsNode, fsdir string) <-chan error {
87
+ done := make(chan error)
88
+ log.Info("Mounting IPFS at ", fsdir)
89
+
90
+ go func() {
91
+ err := rofs.Mount(node, fsdir)
92
+ done <- err
93
+ close(done)
94
+ }()
95
+
96
+ return done
97
+}
98
+
99
+func mountIpns(node *core.IpfsNode, nsdir, fsdir string) <-chan error {
100
+ if nsdir == "" {
101
+ return nil
102
+ }
103
+ done := make(chan error)
104
+ log.Info("Mounting IPNS at ", nsdir)
105
+
106
+ go func() {
107
+ err := ipns.Mount(node, nsdir, fsdir)
108
+ done <- err
109
+ close(done)
110
+ }()
111
+
112
+ return done
113
+}
114
+
115
+var platformFuseChecks = func() error {
116
+ return nil
117
+}
core/commands2/mount_windows.go
new
+14
@@ -0,0 +1,14 @@
1
+package commands
2
+
3
+import (
4
+ "errors"
5
+
6
+ cmds "github.com/jbenet/go-ipfs/commands"
7
+)
8
+
9
+var ipfsMount = &cmds.Command{
10
+ Help: `Not yet implemented on Windows.`,
11
+ Run: func(res cmds.Response, req cmds.Request) {
12
+ res.SetError(errors.New("Mount isn't compatible with Windows yet"), cmds.ErrNormal)
13
+ },
14
+}
core/commands2/root.go
+1
@@ -68,6 +68,7 @@ var rootSubcommands = map[string]*cmds.Command{
68
"version": versionCmd,
69
"config": configCmd,
70
"bootstrap": bootstrapCmd,
71
+ "mount": mountCmd,
72
73
// test subcommands
74
// TODO: remove these when we don't need them anymore