github.com/devfans/go-ethereum@v1.5.10-0.20170326212234-7419d0c38291/swarm/api/fuse.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 !windows
    18  
    19  package api
    20  
    21  import (
    22  	"io"
    23  	"os"
    24  
    25  	"bazil.org/fuse"
    26  	"bazil.org/fuse/fs"
    27  	"github.com/ethereum/go-ethereum/log"
    28  	"github.com/ethereum/go-ethereum/swarm/storage"
    29  	"golang.org/x/net/context"
    30  )
    31  
    32  
    33  
    34  
    35  // Data structures used for Fuse filesystem, serving directories and serving files to Fuse driver
    36  type FS struct {
    37  	root *Dir
    38  }
    39  
    40  type Dir struct {
    41  	inode       uint64
    42  	name        string
    43  	path        string
    44  	directories []*Dir
    45  	files       []*File
    46  }
    47  
    48  type File struct {
    49  	inode    uint64
    50  	name     string
    51  	path     string
    52  	key      storage.Key
    53  	swarmApi *Api
    54  	fileSize uint64
    55  	reader   storage.LazySectionReader
    56  }
    57  
    58  
    59  // Functions which satisfy the Fuse File System requests
    60  func (filesystem *FS) Root() (fs.Node, error) {
    61  	return filesystem.root, nil
    62  }
    63  
    64  func (directory *Dir) Attr(ctx context.Context, a *fuse.Attr) error {
    65  	a.Inode = directory.inode
    66  	//TODO: need to get permission as argument
    67  	a.Mode = os.ModeDir | 0500
    68  	a.Uid = uint32(os.Getuid())
    69  	a.Gid = uint32(os.Getegid())
    70  	return nil
    71  }
    72  
    73  func (directory *Dir) Lookup(ctx context.Context, name string) (fs.Node, error) {
    74  	if directory.files != nil {
    75  		for _, n := range directory.files {
    76  			if n.name == name {
    77  				return n, nil
    78  			}
    79  		}
    80  	}
    81  	if directory.directories != nil {
    82  		for _, n := range directory.directories {
    83  			if n.name == name {
    84  				return n, nil
    85  			}
    86  		}
    87  	}
    88  	return nil, fuse.ENOENT
    89  }
    90  
    91  func (d *Dir) ReadDirAll(ctx context.Context) ([]fuse.Dirent, error) {
    92  	var children []fuse.Dirent
    93  	if d.files != nil {
    94  		for _, file := range d.files {
    95  			children = append(children, fuse.Dirent{Inode: file.inode, Type: fuse.DT_File, Name: file.name})
    96  		}
    97  	}
    98  	if d.directories != nil {
    99  		for _, dir := range d.directories {
   100  			children = append(children, fuse.Dirent{Inode: dir.inode, Type: fuse.DT_Dir, Name: dir.name})
   101  		}
   102  	}
   103  	return children, nil
   104  }
   105  
   106  func (file *File) Attr(ctx context.Context, a *fuse.Attr) error {
   107  
   108  	a.Inode = file.inode
   109  	//TODO: need to get permission as argument
   110  	a.Mode = 0500
   111  	a.Uid = uint32(os.Getuid())
   112  	a.Gid = uint32(os.Getegid())
   113  
   114  
   115  	reader := file.swarmApi.Retrieve(file.key)
   116  	quitC := make(chan bool)
   117  	size, err := reader.Size(quitC)
   118  	if err != nil {
   119  		log.Warn("Couldnt file size of file %s : %v", file.path, err)
   120  		a.Size = uint64(0)
   121  	}
   122  	a.Size = uint64(size)
   123  	file.fileSize = a.Size
   124  	return nil
   125  }
   126  
   127  var _ = fs.HandleReader(&File{})
   128  
   129  func (file *File) Read(ctx context.Context, req *fuse.ReadRequest, resp *fuse.ReadResponse) error {
   130  	buf := make([]byte, req.Size)
   131  	reader := file.swarmApi.Retrieve(file.key)
   132  	n, err := reader.ReadAt(buf, req.Offset)
   133  	if err == io.ErrUnexpectedEOF || err == io.EOF {
   134  		err = nil
   135  	}
   136  	resp.Data = buf[:n]
   137  	return err
   138  
   139  }