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 }