@cryptotaxi247 / kubo / commits / 3588f5ad2

fuse works now

Juan Batiz-Benet committed Jul 6, 2014 at 03:49 UTC 3588f5ad25e419db572a3e572d64352bd0a620c3
1 file changed +118 -73
fuse/readonly/readonly.go
+118 -73
@@ -3,116 +3,161 @@
3 package readonly
4
5 import (
6 - "os"
6 "bazil.org/fuse"
8 - "bazil.org/fuse/fs"
9 - core "github.com/jbenet/go-ipfs/core"
10 - mdag "github.com/jbenet/go-ipfs/merkledag"
7 + "bazil.org/fuse/fs"
8 + "fmt"
9 + core "github.com/jbenet/go-ipfs/core"
10 + mdag "github.com/jbenet/go-ipfs/merkledag"
11 + "os"
12 + "os/exec"
13 + "os/signal"
14 + "runtime"
15 + "syscall"
16 + "time"
17 )
18
13 -
19 type FileSystem struct {
15 - Ipfs *core.IpfsNode
20 + Ipfs *core.IpfsNode
21 }
22
23 func NewFileSystem(ipfs *core.IpfsNode) *FileSystem {
19 - return &FileSystem{ Ipfs: ipfs }
24 + return &FileSystem{Ipfs: ipfs}
25 }
26
27 func (f FileSystem) Root() (fs.Node, fuse.Error) {
23 - return Root{Ipfs: f.Ipfs }, nil
28 + return &Root{Ipfs: f.Ipfs}, nil
29 }
30
26 -
31 type Root struct {
28 - Ipfs *core.IpfsNode
32 + Ipfs *core.IpfsNode
33 }
34
31 -func (Root) Attr() fuse.Attr {
32 - return fuse.Attr{Inode: 1, Mode: os.ModeDir | 0111} // -rw+x
35 +func (*Root) Attr() fuse.Attr {
36 + return fuse.Attr{Mode: os.ModeDir | 0111} // -rw+x
37 }
38
39 func (s *Root) Lookup(name string, intr fs.Intr) (fs.Node, fuse.Error) {
36 -
37 - nd, err := s.Ipfs.Resolver.ResolvePath(name)
38 - if err != nil {
39 - // todo: make this error more versatile.
40 - return nil, fuse.ENOENT
41 - }
42 -
43 - return Node{Ipfs: s.Ipfs, Nd: nd}, nil
40 + switch name {
41 + case "mach_kernel", ".hidden", "._.":
42 + // Just quiet some log noise on OS X.
43 + return nil, fuse.ENOENT
44 + }
45 +
46 + nd, err := s.Ipfs.Resolver.ResolvePath(name)
47 + if err != nil {
48 + // todo: make this error more versatile.
49 + return nil, fuse.ENOENT
50 + }
51 +
52 + return &Node{Ipfs: s.Ipfs, Nd: nd}, nil
53 }
54
46 -func (Root) ReadDir(intr fs.Intr) ([]fuse.Dirent, fuse.Error) {
47 - return nil, fuse.EPERM
55 +func (*Root) ReadDir(intr fs.Intr) ([]fuse.Dirent, fuse.Error) {
56 + return nil, fuse.EPERM
57 }
58
59 type Node struct {
51 - Ipfs *core.IpfsNode
52 - Nd *mdag.Node
60 + Ipfs *core.IpfsNode
61 + Nd *mdag.Node
62 }
63
55 -func (s Node) Attr() fuse.Attr {
56 -
57 - if len(s.Nd.Links) > 0 {
58 - return fuse.Attr{Mode: os.ModeDir | 0555}
59 - }
64 +func (s *Node) Attr() fuse.Attr {
65 + if len(s.Nd.Links) > 0 {
66 + return fuse.Attr{Mode: os.ModeDir | 0555}
67 + }
68
61 - size, _ := s.Nd.Size()
62 - return fuse.Attr{Mode: 0444, Size: uint64(size)}
69 + size, _ := s.Nd.Size()
70 + return fuse.Attr{Mode: 0444, Size: uint64(size)}
71 }
72
73 func (s *Node) Lookup(name string, intr fs.Intr) (fs.Node, fuse.Error) {
74 + nd, err := s.Ipfs.Resolver.ResolveLinks(s.Nd, []string{name})
75 + if err != nil {
76 + // todo: make this error more versatile.
77 + return nil, fuse.ENOENT
78 + }
79
67 - nd, err := s.Ipfs.Resolver.ResolveLinks(s.Nd, []string{name})
68 - if err != nil {
69 - // todo: make this error more versatile.
70 - return nil, fuse.ENOENT
71 - }
72 -
73 - return Node{Ipfs: s.Ipfs, Nd: nd}, nil
80 + return &Node{Ipfs: s.Ipfs, Nd: nd}, nil
81 }
82
83 func (s *Node) ReadDir(intr fs.Intr) ([]fuse.Dirent, fuse.Error) {
77 -
78 - entries := make([]fuse.Dirent, len(s.Nd.Links))
79 - for i, link := range s.Nd.Links {
80 - n := link.Name
81 - if len(n) == 0 {
82 - n = link.Hash.B58String()
83 - }
84 - entries[i] = fuse.Dirent{Name: n, Type: fuse.DT_File}
85 - }
86 -
87 - if len(entries) > 0 {
88 - return entries, nil
89 - }
90 - return nil, fuse.ENOENT
84 + entries := make([]fuse.Dirent, len(s.Nd.Links))
85 + for i, link := range s.Nd.Links {
86 + n := link.Name
87 + if len(n) == 0 {
88 + n = link.Hash.B58String()
89 + }
90 + entries[i] = fuse.Dirent{Name: n, Type: fuse.DT_File}
91 + }
92 +
93 + if len(entries) > 0 {
94 + return entries, nil
95 + }
96 + return nil, fuse.ENOENT
97 }
98
99 func (s *Node) ReadAll(intr fs.Intr) ([]byte, fuse.Error) {
94 - return []byte(s.Nd.Data), nil
100 + return []byte(s.Nd.Data), nil
101 }
102
103 +func Mount(ipfs *core.IpfsNode, fpath string) error {
104 +
105 + sigc := make(chan os.Signal, 1)
106 + signal.Notify(sigc, syscall.SIGHUP, syscall.SIGINT,
107 + syscall.SIGTERM, syscall.SIGQUIT)
108 +
109 + go func() {
110 + <-sigc
111 + Unmount(fpath)
112 + }()
113 +
114 + c, err := fuse.Mount(fpath)
115 + if err != nil {
116 + return err
117 + }
118 + defer c.Close()
119 +
120 + err = fs.Serve(c, FileSystem{Ipfs: ipfs})
121 + if err != nil {
122 + return err
123 + }
124 +
125 + // check if the mount process has an error to report
126 + <-c.Ready
127 + if err := c.MountError; err != nil {
128 + return err
129 + }
130 + return nil
131 +}
132
98 -
99 -func Mount(ipfs *core.IpfsNode, fpath string) (error) {
100 -
101 - c, err := fuse.Mount(fpath)
102 - if err != nil {
103 - return err
104 - }
105 - defer c.Close()
106 -
107 - err = fs.Serve(c, FileSystem{Ipfs: ipfs})
108 - if err != nil {
109 - return err
110 - }
111 -
112 - // check if the mount process has an error to report
113 - <-c.Ready
114 - if err := c.MountError; err != nil {
115 - return err
116 - }
117 - return nil
133 +// Unmount attempts to unmount the provided FUSE mount point, forcibly
134 +// if necessary.
135 +func Unmount(point string) error {
136 + fmt.Printf("Unmounting %s...\n", point)
137 +
138 + var cmd *exec.Cmd
139 + switch runtime.GOOS {
140 + case "darwin":
141 + cmd = exec.Command("diskutil", "umount", "force", point)
142 + case "linux":
143 + cmd = exec.Command("fusermount", "-u", point)
144 + default:
145 + return fmt.Errorf("unmount: unimplemented")
146 + }
147 +
148 + errc := make(chan error, 1)
149 + go func() {
150 + if err := exec.Command("umount", point).Run(); err == nil {
151 + errc <- err
152 + }
153 + // retry to unmount with the fallback cmd
154 + errc <- cmd.Run()
155 + }()
156 +
157 + select {
158 + case <-time.After(1 * time.Second):
159 + return fmt.Errorf("umount timeout")
160 + case err := <-errc:
161 + return err
162 + }
163 }