fuse using github.com/hanwen/go-fuse
Juan Batiz-Benet committed
Jul 6, 2014 at 02:27 UTC
e9bc92362b1bb68803b4afd39a112dfacee70ca1
3 files changed
+153
cli/ipfs.go
+1
@@ -42,6 +42,7 @@ Use "ipfs help <command>" for more information about a command.
42
cmdIpfsRefs,
43
cmdIpfsVersion,
44
cmdIpfsCommands,
45
+ cmdIpfsMount,
46
},
47
Flag: *flag.NewFlagSet("ipfs", flag.ExitOnError),
48
}
cli/mount.go
new
+47
@@ -0,0 +1,47 @@
1
+package main
2
+
3
+import (
4
+ "fmt"
5
+ "github.com/gonuts/flag"
6
+ "github.com/jbenet/commander"
7
+ rofs "github.com/jbenet/go-ipfs/fuse/readonly"
8
+ u "github.com/jbenet/go-ipfs/util"
9
+)
10
+
11
+var cmdIpfsMount = &commander.Command{
12
+ UsageLine: "mount",
13
+ Short: "Mount an ipfs read-only mountpoint.",
14
+ Long: `ipfs mount <os-path> - Mount an ipfs read-only mountpoint.
15
+
16
+ Mount ipfs at a read-only mountpoint on the OS. All ipfs objects
17
+ will be accessible under that directory. Note that the root will
18
+ not be listable, as it is virtual. Accessing known paths directly.
19
+
20
+`,
21
+ Run: mountCmd,
22
+ Flag: *flag.NewFlagSet("ipfs-mount", flag.ExitOnError),
23
+}
24
+
25
+func mountCmd(c *commander.Command, inp []string) error {
26
+ if len(inp) < 1 || len(inp[0]) == 0 {
27
+ u.POut(c.Long)
28
+ return nil
29
+ }
30
+
31
+ n, err := localNode()
32
+ if err != nil {
33
+ return err
34
+ }
35
+
36
+ mp := inp[0]
37
+ fmt.Printf("Mounting at %s\n", mp)
38
+
39
+ fs := rofs.NewFileSystem(n)
40
+ s, err := rofs.Mount(fs, mp)
41
+ if err != nil {
42
+ return err
43
+ }
44
+ s.SetDebug(true)
45
+ s.Serve()
46
+ return nil
47
+}
fuse/readonly/readonly.go
new
+105
@@ -0,0 +1,105 @@
1
+// A Go mirror of libfuse's hello.c
2
+
3
+package readonly
4
+
5
+import (
6
+ "github.com/hanwen/go-fuse/fuse"
7
+ "github.com/hanwen/go-fuse/fuse/nodefs"
8
+ "github.com/hanwen/go-fuse/fuse/pathfs"
9
+ core "github.com/jbenet/go-ipfs/core"
10
+)
11
+
12
+type FileSystem struct {
13
+ Ipfs *core.IpfsNode
14
+ pathfs.FileSystem
15
+}
16
+
17
+func NewFileSystem(ipfs *core.IpfsNode) *FileSystem {
18
+ return &FileSystem{
19
+ Ipfs: ipfs,
20
+ FileSystem: pathfs.NewDefaultFileSystem(),
21
+ }
22
+}
23
+
24
+func (s *FileSystem) GetAttr(name string, context *fuse.Context) (*fuse.Attr, fuse.Status) {
25
+ if name == "/" { // -rw +x on root
26
+ return &fuse.Attr{Mode: fuse.S_IFDIR | 0111}, fuse.OK
27
+ }
28
+
29
+ nd, err := s.Ipfs.Resolver.ResolvePath(name)
30
+ if err != nil {
31
+ // todo: make this error more versatile.
32
+ return nil, fuse.ENOENT
33
+ }
34
+
35
+ // links? say dir. could have data...
36
+ if len(nd.Links) > 0 {
37
+ return &fuse.Attr{Mode: fuse.S_IFDIR | 0555}, fuse.OK
38
+ }
39
+
40
+ // size
41
+ size, _ := nd.Size()
42
+
43
+ // file.
44
+ return &fuse.Attr{
45
+ Mode: fuse.S_IFREG | 0444,
46
+ Size: uint64(size),
47
+ }, fuse.OK
48
+}
49
+
50
+func (s *FileSystem) OpenDir(name string, context *fuse.Context) (c []fuse.DirEntry, code fuse.Status) {
51
+ if name == "/" { // nope
52
+ return nil, fuse.EPERM
53
+ }
54
+
55
+ nd, err := s.Ipfs.Resolver.ResolvePath(name)
56
+ if err != nil {
57
+ // todo: make this error more versatile.
58
+ return nil, fuse.ENOENT
59
+ }
60
+
61
+ entries := make([]fuse.DirEntry, len(nd.Links))
62
+ for i, link := range nd.Links {
63
+ n := link.Name
64
+ if len(n) == 0 {
65
+ n = link.Hash.B58String()
66
+ }
67
+ entries[i] = fuse.DirEntry{Name: n, Mode: fuse.S_IFREG | 0444}
68
+ }
69
+
70
+ if len(entries) > 0 {
71
+ return entries, fuse.OK
72
+ }
73
+ return nil, fuse.ENOENT
74
+}
75
+
76
+func (s *FileSystem) Open(name string, flags uint32, context *fuse.Context) (
77
+ file nodefs.File, code fuse.Status) {
78
+
79
+ // read only, bro!
80
+ if flags&fuse.O_ANYWRITE != 0 {
81
+ return nil, fuse.EPERM
82
+ }
83
+
84
+ nd, err := s.Ipfs.Resolver.ResolvePath(name)
85
+ if err != nil {
86
+ // todo: make this error more versatile.
87
+ return nil, fuse.ENOENT
88
+ }
89
+
90
+ return nodefs.NewDataFile([]byte(nd.Data)), fuse.OK
91
+}
92
+
93
+func (s *FileSystem) String() string {
94
+ return "IpfsReadOnly"
95
+}
96
+
97
+func (s *FileSystem) OnMount(nodeFs *pathfs.PathNodeFs) {
98
+}
99
+
100
+func Mount(s *FileSystem, path string) (*fuse.Server, error) {
101
+ rfs := pathfs.NewReadonlyFileSystem(s)
102
+ fs := pathfs.NewPathNodeFs(rfs, nil)
103
+ ser, _, err := nodefs.MountRoot(path, fs.Root(), nil)
104
+ return ser, err
105
+}