@cryptotaxi247 / kubo / commits / e9bc92362

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 +}