github.com/FUSIONFoundation/efsn@v3.6.2-0.20200916075423-dbb5dd5d2cc7+incompatible/swarm/fuse/fuse_dir.go (about)

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