readonly.go 2.24 KB
Newer Older
1 2 3 4 5
// A Go mirror of libfuse's hello.c

package readonly

import (
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
6 7 8 9 10
  "os"
	"bazil.org/fuse"
  "bazil.org/fuse/fs"
  core "github.com/jbenet/go-ipfs/core"
  mdag "github.com/jbenet/go-ipfs/merkledag"
11 12
)

Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
13

14
type FileSystem struct {
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
15
  Ipfs *core.IpfsNode
16 17 18
}

func NewFileSystem(ipfs *core.IpfsNode) *FileSystem {
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
  return &FileSystem{ Ipfs: ipfs }
}

func (f FileSystem) Root() (fs.Node, fuse.Error) {
  return Root{Ipfs: f.Ipfs }, nil
}


type Root struct {
  Ipfs *core.IpfsNode
}

func (Root) Attr() fuse.Attr {
  return fuse.Attr{Inode: 1, Mode: os.ModeDir | 0111} // -rw+x
}

func (s *Root) Lookup(name string, intr fs.Intr) (fs.Node, fuse.Error) {

  nd, err := s.Ipfs.Resolver.ResolvePath(name)
  if err != nil {
    // todo: make this error more versatile.
    return nil, fuse.ENOENT
  }

  return Node{Ipfs: s.Ipfs, Nd: nd}, nil
44 45
}

Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
46 47
func (Root) ReadDir(intr fs.Intr) ([]fuse.Dirent, fuse.Error) {
  return nil, fuse.EPERM
48 49
}

Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
50 51 52
type Node struct {
  Ipfs *core.IpfsNode
  Nd *mdag.Node
53 54
}

Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
55 56 57 58 59 60 61 62 63
func (s Node) Attr() fuse.Attr {

  if len(s.Nd.Links) > 0 {
    return fuse.Attr{Mode: os.ModeDir | 0555}
  }

  size, _ := s.Nd.Size()
  return fuse.Attr{Mode: 0444, Size: uint64(size)}
}
64

Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
65
func (s *Node) Lookup(name string, intr fs.Intr) (fs.Node, fuse.Error) {
66

Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
67 68 69 70 71
  nd, err := s.Ipfs.Resolver.ResolveLinks(s.Nd, []string{name})
  if err != nil {
    // todo: make this error more versatile.
    return nil, fuse.ENOENT
  }
72

Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
73
  return Node{Ipfs: s.Ipfs, Nd: nd}, nil
74 75
}

Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
76 77 78 79 80 81 82 83 84 85 86 87 88 89 90
func (s *Node) ReadDir(intr fs.Intr) ([]fuse.Dirent, fuse.Error) {

  entries := make([]fuse.Dirent, len(s.Nd.Links))
  for i, link := range s.Nd.Links {
    n := link.Name
    if len(n) == 0 {
      n = link.Hash.B58String()
    }
    entries[i] = fuse.Dirent{Name: n, Type: fuse.DT_File}
  }

  if len(entries) > 0 {
    return entries, nil
  }
  return nil, fuse.ENOENT
91 92
}

Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
93 94
func (s *Node) ReadAll(intr fs.Intr) ([]byte, fuse.Error) {
  return []byte(s.Nd.Data), nil
95 96
}

Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117


func Mount(ipfs *core.IpfsNode, fpath string) (error) {

  c, err := fuse.Mount(fpath)
  if err != nil {
    return err
  }
  defer c.Close()

  err = fs.Serve(c, FileSystem{Ipfs: ipfs})
  if err != nil {
    return err
  }

  // check if the mount process has an error to report
  <-c.Ready
  if err := c.MountError; err != nil {
    return err
  }
  return nil
118
}