tree.go 1.9 KB

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