github.com/SmartMeshFoundation/Spectrum@v0.0.0-20220621030607-452a266fee1e/swarm/fuse/fuse_dir.go (about) 1 // Copyright 2017 The Spectrum Authors 2 // This file is part of the Spectrum library. 3 // 4 // The Spectrum 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 Spectrum 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 Spectrum library. If not, see <http://www.gnu.org/licenses/>. 16 17 // +build linux darwin freebsd 18 19 package fuse 20 21 import ( 22 "bazil.org/fuse" 23 "bazil.org/fuse/fs" 24 "golang.org/x/net/context" 25 "os" 26 "path/filepath" 27 "sync" 28 ) 29 30 var ( 31 _ fs.Node = (*SwarmDir)(nil) 32 _ fs.NodeRequestLookuper = (*SwarmDir)(nil) 33 _ fs.HandleReadDirAller = (*SwarmDir)(nil) 34 _ fs.NodeCreater = (*SwarmDir)(nil) 35 _ fs.NodeRemover = (*SwarmDir)(nil) 36 _ fs.NodeMkdirer = (*SwarmDir)(nil) 37 ) 38 39 type SwarmDir struct { 40 inode uint64 41 name string 42 path string 43 directories []*SwarmDir 44 files []*SwarmFile 45 46 mountInfo *MountInfo 47 lock *sync.RWMutex 48 } 49 50 func NewSwarmDir(fullpath string, minfo *MountInfo) *SwarmDir { 51 newdir := &SwarmDir{ 52 inode: NewInode(), 53 name: filepath.Base(fullpath), 54 path: fullpath, 55 directories: []*SwarmDir{}, 56 files: []*SwarmFile{}, 57 mountInfo: minfo, 58 lock: &sync.RWMutex{}, 59 } 60 return newdir 61 } 62 63 func (sd *SwarmDir) Attr(ctx context.Context, a *fuse.Attr) error { 64 a.Inode = sd.inode 65 a.Mode = os.ModeDir | 0700 66 a.Uid = uint32(os.Getuid()) 67 a.Gid = uint32(os.Getegid()) 68 return nil 69 } 70 71 func (sd *SwarmDir) Lookup(ctx context.Context, req *fuse.LookupRequest, resp *fuse.LookupResponse) (fs.Node, error) { 72 73 for _, n := range sd.files { 74 if n.name == req.Name { 75 return n, nil 76 } 77 } 78 for _, n := range sd.directories { 79 if n.name == req.Name { 80 return n, nil 81 } 82 } 83 return nil, fuse.ENOENT 84 } 85 86 func (sd *SwarmDir) ReadDirAll(ctx context.Context) ([]fuse.Dirent, error) { 87 var children []fuse.Dirent 88 for _, file := range sd.files { 89 children = append(children, fuse.Dirent{Inode: file.inode, Type: fuse.DT_File, Name: file.name}) 90 } 91 for _, dir := range sd.directories { 92 children = append(children, fuse.Dirent{Inode: dir.inode, Type: fuse.DT_Dir, Name: dir.name}) 93 } 94 return children, nil 95 } 96 97 func (sd *SwarmDir) Create(ctx context.Context, req *fuse.CreateRequest, resp *fuse.CreateResponse) (fs.Node, fs.Handle, error) { 98 99 newFile := NewSwarmFile(sd.path, req.Name, sd.mountInfo) 100 newFile.fileSize = 0 // 0 means, file is not in swarm yet and it is just created 101 102 sd.lock.Lock() 103 defer sd.lock.Unlock() 104 sd.files = append(sd.files, newFile) 105 106 return newFile, newFile, nil 107 } 108 109 func (sd *SwarmDir) Remove(ctx context.Context, req *fuse.RemoveRequest) error { 110 111 if req.Dir && sd.directories != nil { 112 newDirs := []*SwarmDir{} 113 for _, dir := range sd.directories { 114 if dir.name == req.Name { 115 removeDirectoryFromSwarm(dir) 116 } else { 117 newDirs = append(newDirs, dir) 118 } 119 } 120 if len(sd.directories) > len(newDirs) { 121 sd.lock.Lock() 122 defer sd.lock.Unlock() 123 sd.directories = newDirs 124 } 125 return nil 126 } else if !req.Dir && sd.files != nil { 127 newFiles := []*SwarmFile{} 128 for _, f := range sd.files { 129 if f.name == req.Name { 130 removeFileFromSwarm(f) 131 } else { 132 newFiles = append(newFiles, f) 133 } 134 } 135 if len(sd.files) > len(newFiles) { 136 sd.lock.Lock() 137 defer sd.lock.Unlock() 138 sd.files = newFiles 139 } 140 return nil 141 } 142 return fuse.ENOENT 143 } 144 145 func (sd *SwarmDir) Mkdir(ctx context.Context, req *fuse.MkdirRequest) (fs.Node, error) { 146 147 newDir := NewSwarmDir(req.Name, sd.mountInfo) 148 149 sd.lock.Lock() 150 defer sd.lock.Unlock() 151 sd.directories = append(sd.directories, newDir) 152 153 return newDir, nil 154 155 }