Commit e9bc9236 authored by Juan Batiz-Benet's avatar Juan Batiz-Benet

fuse using github.com/hanwen/go-fuse

parent ac0f9b1e
......@@ -42,6 +42,7 @@ Use "ipfs help <command>" for more information about a command.
cmdIpfsRefs,
cmdIpfsVersion,
cmdIpfsCommands,
cmdIpfsMount,
},
Flag: *flag.NewFlagSet("ipfs", flag.ExitOnError),
}
......
package main
import (
"fmt"
"github.com/gonuts/flag"
"github.com/jbenet/commander"
rofs "github.com/jbenet/go-ipfs/fuse/readonly"
u "github.com/jbenet/go-ipfs/util"
)
var cmdIpfsMount = &commander.Command{
UsageLine: "mount",
Short: "Mount an ipfs read-only mountpoint.",
Long: `ipfs mount <os-path> - Mount an ipfs read-only mountpoint.
Mount ipfs at a read-only mountpoint on the OS. All ipfs objects
will be accessible under that directory. Note that the root will
not be listable, as it is virtual. Accessing known paths directly.
`,
Run: mountCmd,
Flag: *flag.NewFlagSet("ipfs-mount", flag.ExitOnError),
}
func mountCmd(c *commander.Command, inp []string) error {
if len(inp) < 1 || len(inp[0]) == 0 {
u.POut(c.Long)
return nil
}
n, err := localNode()
if err != nil {
return err
}
mp := inp[0]
fmt.Printf("Mounting at %s\n", mp)
fs := rofs.NewFileSystem(n)
s, err := rofs.Mount(fs, mp)
if err != nil {
return err
}
s.SetDebug(true)
s.Serve()
return nil
}
// A Go mirror of libfuse's hello.c
package readonly
import (
"github.com/hanwen/go-fuse/fuse"
"github.com/hanwen/go-fuse/fuse/nodefs"
"github.com/hanwen/go-fuse/fuse/pathfs"
core "github.com/jbenet/go-ipfs/core"
)
type FileSystem struct {
Ipfs *core.IpfsNode
pathfs.FileSystem
}
func NewFileSystem(ipfs *core.IpfsNode) *FileSystem {
return &FileSystem{
Ipfs: ipfs,
FileSystem: pathfs.NewDefaultFileSystem(),
}
}
func (s *FileSystem) GetAttr(name string, context *fuse.Context) (*fuse.Attr, fuse.Status) {
if name == "/" { // -rw +x on root
return &fuse.Attr{Mode: fuse.S_IFDIR | 0111}, fuse.OK
}
nd, err := s.Ipfs.Resolver.ResolvePath(name)
if err != nil {
// todo: make this error more versatile.
return nil, fuse.ENOENT
}
// links? say dir. could have data...
if len(nd.Links) > 0 {
return &fuse.Attr{Mode: fuse.S_IFDIR | 0555}, fuse.OK
}
// size
size, _ := nd.Size()
// file.
return &fuse.Attr{
Mode: fuse.S_IFREG | 0444,
Size: uint64(size),
}, fuse.OK
}
func (s *FileSystem) OpenDir(name string, context *fuse.Context) (c []fuse.DirEntry, code fuse.Status) {
if name == "/" { // nope
return nil, fuse.EPERM
}
nd, err := s.Ipfs.Resolver.ResolvePath(name)
if err != nil {
// todo: make this error more versatile.
return nil, fuse.ENOENT
}
entries := make([]fuse.DirEntry, len(nd.Links))
for i, link := range nd.Links {
n := link.Name
if len(n) == 0 {
n = link.Hash.B58String()
}
entries[i] = fuse.DirEntry{Name: n, Mode: fuse.S_IFREG | 0444}
}
if len(entries) > 0 {
return entries, fuse.OK
}
return nil, fuse.ENOENT
}
func (s *FileSystem) Open(name string, flags uint32, context *fuse.Context) (
file nodefs.File, code fuse.Status) {
// read only, bro!
if flags&fuse.O_ANYWRITE != 0 {
return nil, fuse.EPERM
}
nd, err := s.Ipfs.Resolver.ResolvePath(name)
if err != nil {
// todo: make this error more versatile.
return nil, fuse.ENOENT
}
return nodefs.NewDataFile([]byte(nd.Data)), fuse.OK
}
func (s *FileSystem) String() string {
return "IpfsReadOnly"
}
func (s *FileSystem) OnMount(nodeFs *pathfs.PathNodeFs) {
}
func Mount(s *FileSystem, path string) (*fuse.Server, error) {
rfs := pathfs.NewReadonlyFileSystem(s)
fs := pathfs.NewPathNodeFs(rfs, nil)
ser, _, err := nodefs.MountRoot(path, fs.Root(), nil)
return ser, err
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment