diff --git a/swarm/api/fuse.go b/swarm/api/fuse.go index 4b1f817f8c..58a5d18ae8 100644 --- a/swarm/api/fuse.go +++ b/swarm/api/fuse.go @@ -29,9 +29,6 @@ import ( "golang.org/x/net/context" ) - - - // Data structures used for Fuse filesystem, serving directories and serving files to Fuse driver type FS struct { root *Dir @@ -55,7 +52,6 @@ type File struct { reader storage.LazySectionReader } - // Functions which satisfy the Fuse File System requests func (filesystem *FS) Root() (fs.Node, error) { return filesystem.root, nil @@ -104,14 +100,12 @@ func (d *Dir) ReadDirAll(ctx context.Context) ([]fuse.Dirent, error) { } func (file *File) Attr(ctx context.Context, a *fuse.Attr) error { - a.Inode = file.inode //TODO: need to get permission as argument a.Mode = 0500 a.Uid = uint32(os.Getuid()) a.Gid = uint32(os.Getegid()) - reader := file.swarmApi.Retrieve(file.key) quitC := make(chan bool) size, err := reader.Size(quitC) @@ -135,5 +129,4 @@ func (file *File) Read(ctx context.Context, req *fuse.ReadRequest, resp *fuse.Re } resp.Data = buf[:n] return err - } diff --git a/swarm/api/swarmfs.go b/swarm/api/swarmfs.go index 8427d3c5b1..78a61cf9de 100644 --- a/swarm/api/swarmfs.go +++ b/swarm/api/swarmfs.go @@ -17,25 +17,22 @@ package api import ( - "time" "sync" + "time" ) const ( Swarmfs_Version = "0.1" - mountTimeout = time.Second * 5 - maxFuseMounts = 5 + mountTimeout = time.Second * 5 + maxFuseMounts = 5 ) - type SwarmFS struct { swarmApi *Api activeMounts map[string]*MountInfo activeLock *sync.RWMutex } - - func NewSwarmFS(api *Api) *SwarmFS { swarmfs := &SwarmFS{ swarmApi: api, @@ -44,5 +41,3 @@ func NewSwarmFS(api *Api) *SwarmFS { } return swarmfs } - - diff --git a/swarm/api/swarmfs_windows.go b/swarm/api/swarmfs_fallback.go similarity index 80% rename from swarm/api/swarmfs_windows.go rename to swarm/api/swarmfs_fallback.go index 525a25399a..748c40cfc8 100644 --- a/swarm/api/swarmfs_windows.go +++ b/swarm/api/swarmfs_fallback.go @@ -14,35 +14,35 @@ // You should have received a copy of the GNU Lesser General Public License // along with the go-ethereum library. If not, see . -// +build windows +// +build !linux,!darwin,!freebsd package api import ( - "github.com/ethereum/go-ethereum/log" + "errors" ) -// Dummy struct and functions to satsfy windows build -type MountInfo struct { +var errNoFUSE = errors.New("FUSE is not supported on this platform") + +func isFUSEUnsupportedError(err error) bool { + return err == errNoFUSE } +// Dummy struct and functions to satsfy windows build +type MountInfo struct{} func (self *SwarmFS) Mount(mhash, mountpoint string) error { - log.Info("Platform not supported") - return nil + return errNoFUSE } func (self *SwarmFS) Unmount(mountpoint string) error { - log.Info("Platform not supported") - return nil + return errNoFUSE } func (self *SwarmFS) Listmounts() (string, error) { - log.Info("Platform not supported") - return "",nil + return "", errNoFUSE } func (self *SwarmFS) Stop() error { - log.Info("Platform not supported") return nil -} \ No newline at end of file +} diff --git a/swarm/api/swarmfs_unix_test.go b/swarm/api/swarmfs_test.go similarity index 90% rename from swarm/api/swarmfs_unix_test.go rename to swarm/api/swarmfs_test.go index 4f59dba5b6..45d2dc1692 100644 --- a/swarm/api/swarmfs_unix_test.go +++ b/swarm/api/swarmfs_test.go @@ -14,8 +14,6 @@ // You should have received a copy of the GNU Lesser General Public License // along with the go-ethereum library. If not, see . -// +build linux darwin - package api import ( @@ -35,7 +33,6 @@ func testFuseFileSystem(t *testing.T, f func(*FileSystem)) { } func createTestFiles(t *testing.T, files []string) { - os.RemoveAll(testUploadDir) os.RemoveAll(testMountDir) defer os.MkdirAll(testMountDir, 0777) @@ -58,9 +55,7 @@ func createTestFiles(t *testing.T, files []string) { } func compareFiles(t *testing.T, files []string) { - for f := range files { - sourceFile := filepath.Join(testUploadDir, files[f]) destinationFile := filepath.Join(testMountDir, files[f]) @@ -81,12 +76,10 @@ func compareFiles(t *testing.T, files []string) { if dfinfo.Mode().Perm().String() != "-r-x------" { t.Fatalf("Permission is not 0500for file: %v", err) } - } } func doHashTest(fs *FileSystem, t *testing.T, ensName string, files ...string) { - createTestFiles(t, files) bzzhash, err := fs.Upload(testUploadDir, "") if err != nil { @@ -94,29 +87,29 @@ func doHashTest(fs *FileSystem, t *testing.T, ensName string, files ...string) { } swarmfs := NewSwarmFS(fs.api) - _ ,err1 := swarmfs.Mount(bzzhash, testMountDir) - if err1 != nil { + defer swarmfs.Stop() - t.Fatalf("Error mounting hash %v: %v", bzzhash, err) + _, err = swarmfs.Mount(bzzhash, testMountDir) + if isFUSEUnsupportedError(err) { + t.Skip("FUSE not supported:", err) + } else if err != nil { + t.Fatalf("Error mounting hash %v: %v", bzzhash, err) } + compareFiles(t, files) - _, err2 := swarmfs.Unmount(testMountDir) - if err2 != nil { - t.Fatalf("Error unmounting path %v: %v", testMountDir, err) - } - swarmfs.Stop() + if _, err := swarmfs.Unmount(testMountDir); err != nil { + t.Fatalf("Error unmounting path %v: %v", testMountDir, err) + } } // mounting with manifest Hash func TestFuseMountingScenarios(t *testing.T) { testFuseFileSystem(t, func(fs *FileSystem) { - //doHashTest(fs,t, "test","1.txt") doHashTest(fs, t, "", "1.txt") doHashTest(fs, t, "", "1.txt", "11.txt", "111.txt", "two/2.txt", "two/two/2.txt", "three/3.txt") doHashTest(fs, t, "", "1/2/3/4/5/6/7/8/9/10/11/12/1.txt") doHashTest(fs, t, "", "one/one.txt", "one.txt", "once/one.txt", "one/one/one.txt") - }) } diff --git a/swarm/api/swarmfs_unix.go b/swarm/api/swarmfs_unix.go index ae0216e1d7..f650b43c5d 100644 --- a/swarm/api/swarmfs_unix.go +++ b/swarm/api/swarmfs_unix.go @@ -14,29 +14,37 @@ // You should have received a copy of the GNU Lesser General Public License // along with the go-ethereum library. If not, see . -// +build linux darwin +// +build linux darwin freebsd package api import ( - "path/filepath" "fmt" + "os" + "path/filepath" "strings" - "time" - "github.com/ethereum/go-ethereum/swarm/storage" - "bazil.org/fuse" - "github.com/ethereum/go-ethereum/log" - "github.com/ethereum/go-ethereum/common" - "bazil.org/fuse/fs" "sync" -) + "time" + "bazil.org/fuse" + "bazil.org/fuse/fs" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/swarm/storage" +) var ( - inode uint64 = 1 - inodeLock sync.RWMutex + inode uint64 = 1 + inodeLock sync.RWMutex ) +func isFUSEUnsupportedError(err error) bool { + if perr, ok := err.(*os.PathError); ok { + return perr.Op == "open" && perr.Path == "/dev/fuse" + } + return err == fuse.ErrOSXFUSENotFound +} + // information about every active mount type MountInfo struct { mountPoint string @@ -49,15 +57,12 @@ type MountInfo struct { // Inode numbers need to be unique, they are used for caching inside fuse func NewInode() uint64 { inodeLock.Lock() - defer inodeLock.Unlock() + defer inodeLock.Unlock() inode += 1 return inode } - - -func (self *SwarmFS) Mount(mhash, mountpoint string) (string, error) { - +func (self *SwarmFS) Mount(mhash, mountpoint string) (string, error) { self.activeLock.Lock() defer self.activeLock.Unlock() @@ -110,7 +115,6 @@ func (self *SwarmFS) Mount(mhash, mountpoint string) (string, error) { dirTree["root"] = rootDir err = trie.listWithPrefix(path, quitC, func(entry *manifestTrieEntry, suffix string) { - key = common.Hex2Bytes(entry.Hash) fullpath := "/" + suffix basepath := filepath.Dir(fullpath) @@ -177,7 +181,7 @@ func (self *SwarmFS) Mount(mhash, mountpoint string) (string, error) { return err.Error(), err case err := <-mounterr: - errStr := fmt.Sprintf("Mounting %s encountered error: %v", cleanedMountPoint, err) + errStr := fmt.Sprintf("Mounting %s encountered error: %v", cleanedMountPoint, err) log.Warn(errStr) return errStr, err @@ -185,8 +189,6 @@ func (self *SwarmFS) Mount(mhash, mountpoint string) (string, error) { log.Debug(fmt.Sprintf("Mounting connection succeeded for : %v", cleanedMountPoint)) } - - //Assemble and Store the mount information for future use mountInformation := &MountInfo{ mountPoint: cleanedMountPoint, @@ -203,8 +205,7 @@ func (self *SwarmFS) Mount(mhash, mountpoint string) (string, error) { return succString, nil } -func (self *SwarmFS) Unmount(mountpoint string) (string, error) { - +func (self *SwarmFS) Unmount(mountpoint string) (string, error) { self.activeLock.Lock() defer self.activeLock.Unlock() @@ -216,7 +217,6 @@ func (self *SwarmFS) Unmount(mountpoint string) (string, error) { // Get the mount information based on the mountpoint argument mountInfo := self.activeMounts[cleanedMountPoint] - if mountInfo == nil || mountInfo.mountPoint != cleanedMountPoint { err := fmt.Errorf("Could not find mount information for %s ", cleanedMountPoint) log.Warn(err.Error()) @@ -242,7 +242,6 @@ func (self *SwarmFS) Unmount(mountpoint string) (string, error) { } func (self *SwarmFS) Listmounts() (string, error) { - self.activeLock.RLock() defer self.activeLock.RUnlock() @@ -256,7 +255,6 @@ func (self *SwarmFS) Listmounts() (string, error) { } func (self *SwarmFS) Stop() bool { - for mp := range self.activeMounts { mountInfo := self.activeMounts[mp] self.Unmount(mountInfo.mountPoint)