fuse_dir.go 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. // Copyright 2017 The go-ethereum Authors
  2. // This file is part of the go-ethereum library.
  3. //
  4. // The go-ethereum library is free software: you can redistribute it and/or modify
  5. // it under the terms of the GNU Lesser General Public License as published by
  6. // the Free Software Foundation, either version 3 of the License, or
  7. // (at your option) any later version.
  8. //
  9. // The go-ethereum library is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU Lesser General Public License for more details.
  13. //
  14. // You should have received a copy of the GNU Lesser General Public License
  15. // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
  16. // +build linux darwin freebsd
  17. package fuse
  18. import (
  19. "os"
  20. "path/filepath"
  21. "sync"
  22. "bazil.org/fuse"
  23. "bazil.org/fuse/fs"
  24. "golang.org/x/net/context"
  25. )
  26. var (
  27. _ fs.Node = (*SwarmDir)(nil)
  28. _ fs.NodeRequestLookuper = (*SwarmDir)(nil)
  29. _ fs.HandleReadDirAller = (*SwarmDir)(nil)
  30. _ fs.NodeCreater = (*SwarmDir)(nil)
  31. _ fs.NodeRemover = (*SwarmDir)(nil)
  32. _ fs.NodeMkdirer = (*SwarmDir)(nil)
  33. )
  34. type SwarmDir struct {
  35. inode uint64
  36. name string
  37. path string
  38. directories []*SwarmDir
  39. files []*SwarmFile
  40. mountInfo *MountInfo
  41. lock *sync.RWMutex
  42. }
  43. func NewSwarmDir(fullpath string, minfo *MountInfo) *SwarmDir {
  44. newdir := &SwarmDir{
  45. inode: NewInode(),
  46. name: filepath.Base(fullpath),
  47. path: fullpath,
  48. directories: []*SwarmDir{},
  49. files: []*SwarmFile{},
  50. mountInfo: minfo,
  51. lock: &sync.RWMutex{},
  52. }
  53. return newdir
  54. }
  55. func (sd *SwarmDir) Attr(ctx context.Context, a *fuse.Attr) error {
  56. a.Inode = sd.inode
  57. a.Mode = os.ModeDir | 0700
  58. a.Uid = uint32(os.Getuid())
  59. a.Gid = uint32(os.Getegid())
  60. return nil
  61. }
  62. func (sd *SwarmDir) Lookup(ctx context.Context, req *fuse.LookupRequest, resp *fuse.LookupResponse) (fs.Node, error) {
  63. for _, n := range sd.files {
  64. if n.name == req.Name {
  65. return n, nil
  66. }
  67. }
  68. for _, n := range sd.directories {
  69. if n.name == req.Name {
  70. return n, nil
  71. }
  72. }
  73. return nil, fuse.ENOENT
  74. }
  75. func (sd *SwarmDir) ReadDirAll(ctx context.Context) ([]fuse.Dirent, error) {
  76. var children []fuse.Dirent
  77. for _, file := range sd.files {
  78. children = append(children, fuse.Dirent{Inode: file.inode, Type: fuse.DT_File, Name: file.name})
  79. }
  80. for _, dir := range sd.directories {
  81. children = append(children, fuse.Dirent{Inode: dir.inode, Type: fuse.DT_Dir, Name: dir.name})
  82. }
  83. return children, nil
  84. }
  85. func (sd *SwarmDir) Create(ctx context.Context, req *fuse.CreateRequest, resp *fuse.CreateResponse) (fs.Node, fs.Handle, error) {
  86. newFile := NewSwarmFile(sd.path, req.Name, sd.mountInfo)
  87. newFile.fileSize = 0 // 0 means, file is not in swarm yet and it is just created
  88. sd.lock.Lock()
  89. defer sd.lock.Unlock()
  90. sd.files = append(sd.files, newFile)
  91. return newFile, newFile, nil
  92. }
  93. func (sd *SwarmDir) Remove(ctx context.Context, req *fuse.RemoveRequest) error {
  94. if req.Dir && sd.directories != nil {
  95. newDirs := []*SwarmDir{}
  96. for _, dir := range sd.directories {
  97. if dir.name == req.Name {
  98. removeDirectoryFromSwarm(dir)
  99. } else {
  100. newDirs = append(newDirs, dir)
  101. }
  102. }
  103. if len(sd.directories) > len(newDirs) {
  104. sd.lock.Lock()
  105. defer sd.lock.Unlock()
  106. sd.directories = newDirs
  107. }
  108. return nil
  109. } else if !req.Dir && sd.files != nil {
  110. newFiles := []*SwarmFile{}
  111. for _, f := range sd.files {
  112. if f.name == req.Name {
  113. removeFileFromSwarm(f)
  114. } else {
  115. newFiles = append(newFiles, f)
  116. }
  117. }
  118. if len(sd.files) > len(newFiles) {
  119. sd.lock.Lock()
  120. defer sd.lock.Unlock()
  121. sd.files = newFiles
  122. }
  123. return nil
  124. }
  125. return fuse.ENOENT
  126. }
  127. func (sd *SwarmDir) Mkdir(ctx context.Context, req *fuse.MkdirRequest) (fs.Node, error) {
  128. newDir := NewSwarmDir(req.Name, sd.mountInfo)
  129. sd.lock.Lock()
  130. defer sd.lock.Unlock()
  131. sd.directories = append(sd.directories, newDir)
  132. return newDir, nil
  133. }