Skip to content

Commit

Permalink
various fixes for /ipfs fuse code
Browse files Browse the repository at this point in the history
  • Loading branch information
whyrusleeping committed Aug 31, 2017
1 parent c5d362e commit 5f0791d
Show file tree
Hide file tree
Showing 4 changed files with 86 additions and 29 deletions.
2 changes: 1 addition & 1 deletion core/commands/mount_unix.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ baz
}

// error if we aren't running node in online mode
if !node.OnlineMode() {
if node.LocalMode() {
res.SetError(errNotOnline, cmds.ErrClient)
return
}
Expand Down
13 changes: 8 additions & 5 deletions fuse/node/mount_unix.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,12 +75,15 @@ func doMount(node *core.IpfsNode, fsdir, nsdir string) error {
done <- struct{}{}
}()

go func() {
nsmount, err2 = ipns.Mount(node, nsdir, fsdir)
done <- struct{}{}
}()
if node.OnlineMode() {
go func() {
nsmount, err2 = ipns.Mount(node, nsdir, fsdir)
done <- struct{}{}
}()

<-done
}

<-done
<-done

if err1 != nil {
Expand Down
95 changes: 73 additions & 22 deletions fuse/readonly/readonly_unix.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (

logging "gx/ipfs/QmSpJByNKFX1sCsHBEp3R73FL4NF6FnQTEGyNAXHm2GS52/go-log"
lgbl "gx/ipfs/QmT4PgCNdv73hnFAqzHqwW44q7M9PWpykSswHDxndquZbc/go-libp2p-loggables"
format "gx/ipfs/QmYNyRZJBUYPNrLszFmrBrPJbsBh2vMsefz5gnDpB5M1P6/go-ipld-format"
proto "gx/ipfs/QmZ4Qi3GaRbjcx28Sme5eMH7RQjGkt8wHxt2a65oLaeFEV/gogo-protobuf/proto"
fuse "gx/ipfs/QmaFNtBAXX4nVMQWbUqNysXyhevUj1k4B1y5uS45LC7Vw9/fuse"
fs "gx/ipfs/QmaFNtBAXX4nVMQWbUqNysXyhevUj1k4B1y5uS45LC7Vw9/fuse/fs"
Expand Down Expand Up @@ -60,19 +61,28 @@ func (s *Root) Lookup(ctx context.Context, name string) (fs.Node, error) {
return nil, fuse.ENOENT
}

nd, err := s.Ipfs.Resolver.ResolvePath(ctx, path.Path(name))
p, err := path.ParsePath(name)
if err != nil {
log.Debugf("fuse failed to parse path: %q: %s", name, err)
return nil, fuse.ENOENT
}

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

pbnd, ok := nd.(*mdag.ProtoNode)
if !ok {
switch nd := nd.(type) {
case *mdag.ProtoNode:
return &Node{Ipfs: s.Ipfs, Nd: nd}, nil
case *mdag.RawNode:
return &Node{Ipfs: s.Ipfs, Nd: nd}, nil
default:
log.Error("fuse node was not a protobuf node")
return nil, fuse.ENOTSUP
}

return &Node{Ipfs: s.Ipfs, Nd: pbnd}, nil
}

// ReadDirAll reads a particular directory. Disallowed for root.
Expand All @@ -84,25 +94,37 @@ func (*Root) ReadDirAll(ctx context.Context) ([]fuse.Dirent, error) {
// Node is the core object representing a filesystem tree node.
type Node struct {
Ipfs *core.IpfsNode
Nd *mdag.ProtoNode
Nd format.Node
cached *ftpb.Data
}

func (s *Node) loadData() error {
s.cached = new(ftpb.Data)
return proto.Unmarshal(s.Nd.Data(), s.cached)
if pbnd, ok := s.Nd.(*mdag.ProtoNode); ok {
s.cached = new(ftpb.Data)
return proto.Unmarshal(pbnd.Data(), s.cached)
}
return nil
}

// Attr returns the attributes of a given node.
func (s *Node) Attr(ctx context.Context, a *fuse.Attr) error {
log.Debug("Node attr")
if rawnd, ok := s.Nd.(*mdag.RawNode); ok {
a.Mode = 0444
a.Size = uint64(len(rawnd.RawData()))
a.Blocks = 1
a.Uid = uint32(os.Getuid()) // TODO: should probably cache these calls. No sense making multiple syscalls for each attr call here
a.Gid = uint32(os.Getgid())
return nil
}

if s.cached == nil {
if err := s.loadData(); err != nil {
return fmt.Errorf("readonly: loadData() failed: %s", err)
}
}
switch s.cached.GetType() {
case ftpb.Data_Directory:
case ftpb.Data_Directory, ftpb.Data_HAMTShard:
a.Mode = os.ModeDir | 0555
a.Uid = uint32(os.Getuid())
a.Gid = uint32(os.Getgid())
Expand Down Expand Up @@ -133,31 +155,54 @@ func (s *Node) Attr(ctx context.Context, a *fuse.Attr) error {
// Lookup performs a lookup under this node.
func (s *Node) Lookup(ctx context.Context, name string) (fs.Node, error) {
log.Debugf("Lookup '%s'", name)
nodes, err := s.Ipfs.Resolver.ResolveLinks(ctx, s.Nd, []string{name})
if err != nil {
link, _, err := uio.ResolveUnixfsOnce(ctx, s.Ipfs.DAG, s.Nd, []string{name})
switch err {
case os.ErrNotExist, mdag.ErrLinkNotFound:
// todo: make this error more versatile.
return nil, fuse.ENOENT
default:
log.Errorf("fuse lookup %q: %s", name, err)
return nil, fuse.EIO
case nil:
// noop
}

pbnd, ok := nodes[len(nodes)-1].(*mdag.ProtoNode)
if !ok {
log.Error("fuse lookup got non-protobuf node")
return nil, fuse.ENOTSUP
nd, err := s.Ipfs.DAG.Get(ctx, link.Cid)
switch err {
case mdag.ErrNotFound:
default:
log.Errorf("fuse lookup %q: %s", name, err)
return nil, err
case nil:
// noop
}

return &Node{Ipfs: s.Ipfs, Nd: pbnd}, nil
return &Node{Ipfs: s.Ipfs, Nd: nd}, nil
}

// ReadDirAll reads the link structure as directory entries
func (s *Node) ReadDirAll(ctx context.Context) ([]fuse.Dirent, error) {
log.Debug("Node ReadDir")
entries := make([]fuse.Dirent, len(s.Nd.Links()))
for i, link := range s.Nd.Links() {
n := link.Name
dir, err := uio.NewDirectoryFromNode(s.Ipfs.DAG, s.Nd)
if err != nil {
return nil, err
}

var entries []fuse.Dirent
err = dir.ForEachLink(ctx, func(lnk *format.Link) error {
n := lnk.Name
if len(n) == 0 {
n = link.Cid.String()
n = lnk.Cid.String()
}
entries[i] = fuse.Dirent{Name: n, Type: fuse.DT_File}
// TODO: calling everything a DT_File here might cause issues. But it
// will be expensive to query each child. However most shells call an
// additional 'stat' on each item in a directory listing, its probably
// okay.
entries = append(entries, fuse.Dirent{Name: n, Type: fuse.DT_File})
return nil
})
if err != nil {
return nil, err
}

if len(entries) > 0 {
Expand All @@ -166,15 +211,20 @@ func (s *Node) ReadDirAll(ctx context.Context) ([]fuse.Dirent, error) {
return nil, fuse.ENOENT
}

func (s *Node) Getxattr(ctx context.Context, req *fuse.GetxattrRequest, resp *fuse.GetxattrResponse) error {
// TODO: is nil the right response for 'bug off, we aint got none' ?
resp.Xattr = nil
return nil
}

func (s *Node) Readlink(ctx context.Context, req *fuse.ReadlinkRequest) (string, error) {
if s.cached.GetType() != ftpb.Data_Symlink {
if s.cached == nil || s.cached.GetType() != ftpb.Data_Symlink {
return "", fuse.Errno(syscall.EINVAL)
}
return string(s.cached.GetData()), nil
}

func (s *Node) Read(ctx context.Context, req *fuse.ReadRequest, resp *fuse.ReadResponse) error {

c := s.Nd.Cid()

// setup our logging event
Expand Down Expand Up @@ -220,6 +270,7 @@ type roNode interface {
fs.Node
fs.NodeStringLookuper
fs.NodeReadlinker
fs.NodeGetxattrer
}

var _ roNode = (*Node)(nil)
Expand Down
5 changes: 4 additions & 1 deletion merkledag/merkledag.go
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,10 @@ type sesGetter struct {

func (sg *sesGetter) Get(ctx context.Context, c *cid.Cid) (node.Node, error) {
blk, err := sg.bs.GetBlock(ctx, c)
if err != nil {
switch err {
case bserv.ErrNotFound:
return nil, ErrNotFound
default:
return nil, err
}

Expand Down

1 comment on commit 5f0791d

@GitCop
Copy link

@GitCop GitCop commented on 5f0791d Aug 31, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There were the following issues with your Pull Request

We ask for a few features in the commit message for Open Source licensing hygiene and commit message clarity.
git commit --amend can often help you quickly improve the commit message.
Guidelines and a script are available to help in the long run.
Your feedback on GitCop is welcome on this issue.


This message was auto-generated by https://gitcop.com

Please sign in to comment.