diff --git a/cmd/restic/format.go b/cmd/restic/format.go index 5a1f2ba8c..9f66d1c1d 100644 --- a/cmd/restic/format.go +++ b/cmd/restic/format.go @@ -68,17 +68,29 @@ func formatNode(prefix string, n *restic.Node, long bool) string { return filepath.Join(prefix, n.Name) } + var mode os.FileMode + var target string + switch n.Type { case "file": - return fmt.Sprintf("%s %5d %5d %6d %s %s", - n.Mode, n.UID, n.GID, n.Size, n.ModTime.Format(TimeFormat), filepath.Join(prefix, n.Name)) + mode = 0 case "dir": - return fmt.Sprintf("%s %5d %5d %6d %s %s", - n.Mode|os.ModeDir, n.UID, n.GID, n.Size, n.ModTime.Format(TimeFormat), filepath.Join(prefix, n.Name)) + mode = os.ModeDir case "symlink": - return fmt.Sprintf("%s %5d %5d %6d %s %s -> %s", - n.Mode|os.ModeSymlink, n.UID, n.GID, n.Size, n.ModTime.Format(TimeFormat), filepath.Join(prefix, n.Name), n.LinkTarget) - default: - return fmt.Sprintf("", n.Type, n.Name) + mode = os.ModeSymlink + target = fmt.Sprintf(" -> %v", n.LinkTarget) + case "dev": + mode = os.ModeDevice + case "chardev": + mode = os.ModeDevice | os.ModeCharDevice + case "fifo": + mode = os.ModeNamedPipe + case "socket": + mode = os.ModeSocket } + + return fmt.Sprintf("%s %5d %5d %6d %s %s%s", + mode|n.Mode, n.UID, n.GID, n.Size, + n.ModTime.Format(TimeFormat), filepath.Join(prefix, n.Name), + target) } diff --git a/internal/fuse/dir.go b/internal/fuse/dir.go index f26f439c9..f0c829f1c 100644 --- a/internal/fuse/dir.go +++ b/internal/fuse/dir.go @@ -185,6 +185,8 @@ func (d *dir) Lookup(ctx context.Context, name string) (fs.Node, error) { return newFile(ctx, d.root, fs.GenerateDynamicInode(d.inode, name), node) case "symlink": return newLink(ctx, d.root, fs.GenerateDynamicInode(d.inode, name), node) + case "dev", "chardev", "fifo", "socket": + return newOther(ctx, d.root, fs.GenerateDynamicInode(d.inode, name), node) default: debug.Log(" node %v has unknown type %v", name, node.Type) return nil, fuse.ENOENT diff --git a/internal/fuse/other.go b/internal/fuse/other.go new file mode 100644 index 000000000..899e341ce --- /dev/null +++ b/internal/fuse/other.go @@ -0,0 +1,41 @@ +// +build !openbsd +// +build !windows + +package fuse + +import ( + "bazil.org/fuse" + "github.com/restic/restic/internal/restic" + "golang.org/x/net/context" +) + +type other struct { + root *Root + node *restic.Node + inode uint64 +} + +func newOther(ctx context.Context, root *Root, inode uint64, node *restic.Node) (*other, error) { + return &other{root: root, inode: inode, node: node}, nil +} + +func (l *other) Readlink(ctx context.Context, req *fuse.ReadlinkRequest) (string, error) { + return l.node.LinkTarget, nil +} + +func (l *other) Attr(ctx context.Context, a *fuse.Attr) error { + a.Inode = l.inode + a.Mode = l.node.Mode + + if !l.root.cfg.OwnerIsRoot { + a.Uid = l.node.UID + a.Gid = l.node.GID + } + a.Atime = l.node.AccessTime + a.Ctime = l.node.ChangeTime + a.Mtime = l.node.ModTime + + a.Nlink = uint32(l.node.Links) + + return nil +} diff --git a/internal/restic/node.go b/internal/restic/node.go index 0adf4a524..afa5d9792 100644 --- a/internal/restic/node.go +++ b/internal/restic/node.go @@ -61,16 +61,26 @@ func (n Nodes) Less(i, j int) bool { return n[i].Name < n[j].Name } func (n Nodes) Swap(i, j int) { n[i], n[j] = n[j], n[i] } func (node Node) String() string { + var mode os.FileMode switch node.Type { case "file": - return fmt.Sprintf("%s %5d %5d %6d %s %s", - node.Mode, node.UID, node.GID, node.Size, node.ModTime, node.Name) + mode = 0 case "dir": - return fmt.Sprintf("%s %5d %5d %6d %s %s", - node.Mode|os.ModeDir, node.UID, node.GID, node.Size, node.ModTime, node.Name) + mode = os.ModeDir + case "symlink": + mode = os.ModeSymlink + case "dev": + mode = os.ModeDevice + case "chardev": + mode = os.ModeDevice | os.ModeCharDevice + case "fifo": + mode = os.ModeNamedPipe + case "socket": + mode = os.ModeSocket } - return fmt.Sprintf("", node.Type, node.Name) + return fmt.Sprintf("%s %5d %5d %6d %s %s", + mode|node.Mode, node.UID, node.GID, node.Size, node.ModTime, node.Name) } // NodeFromFileInfo returns a new node from the given path and FileInfo. It