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