1// FUSE directory tree, for servers that wish to use it with the service loop. 2 3package fs 4 5import ( 6 "os" 7 pathpkg "path" 8 "strings" 9 10 "golang.org/x/net/context" 11) 12 13import ( 14 "bazil.org/fuse" 15) 16 17// A Tree implements a basic read-only directory tree for FUSE. 18// The Nodes contained in it may still be writable. 19type Tree struct { 20 tree 21} 22 23func (t *Tree) Root() (Node, error) { 24 return &t.tree, nil 25} 26 27// Add adds the path to the tree, resolving to the given node. 28// If path or a prefix of path has already been added to the tree, 29// Add panics. 30// 31// Add is only safe to call before starting to serve requests. 32func (t *Tree) Add(path string, node Node) { 33 path = pathpkg.Clean("/" + path)[1:] 34 elems := strings.Split(path, "/") 35 dir := Node(&t.tree) 36 for i, elem := range elems { 37 dt, ok := dir.(*tree) 38 if !ok { 39 panic("fuse: Tree.Add for " + strings.Join(elems[:i], "/") + " and " + path) 40 } 41 n := dt.lookup(elem) 42 if n != nil { 43 if i+1 == len(elems) { 44 panic("fuse: Tree.Add for " + path + " conflicts with " + elem) 45 } 46 dir = n 47 } else { 48 if i+1 == len(elems) { 49 dt.add(elem, node) 50 } else { 51 dir = &tree{} 52 dt.add(elem, dir) 53 } 54 } 55 } 56} 57 58type treeDir struct { 59 name string 60 node Node 61} 62 63type tree struct { 64 dir []treeDir 65} 66 67func (t *tree) lookup(name string) Node { 68 for _, d := range t.dir { 69 if d.name == name { 70 return d.node 71 } 72 } 73 return nil 74} 75 76func (t *tree) add(name string, n Node) { 77 t.dir = append(t.dir, treeDir{name, n}) 78} 79 80func (t *tree) Attr(ctx context.Context, a *fuse.Attr) error { 81 a.Mode = os.ModeDir | 0555 82 return nil 83} 84 85func (t *tree) Lookup(ctx context.Context, name string) (Node, error) { 86 n := t.lookup(name) 87 if n != nil { 88 return n, nil 89 } 90 return nil, fuse.ENOENT 91} 92 93func (t *tree) ReadDirAll(ctx context.Context) ([]fuse.Dirent, error) { 94 var out []fuse.Dirent 95 for _, d := range t.dir { 96 out = append(out, fuse.Dirent{Name: d.name}) 97 } 98 return out, nil 99} 100