From dde0fd84218a9f1d78e948474a3cde694adf3e00 Mon Sep 17 00:00:00 2001 From: Alexander Neumann Date: Sun, 26 Jul 2015 20:41:29 +0200 Subject: [PATCH] Add option to use root as owner of files/dirs --- cmd/restic/cmd_mount.go | 4 +++- fuse/dir.go | 39 ++++++++++++++++++++++----------------- fuse/file.go | 23 ++++++++++++++--------- fuse/file_test.go | 2 +- fuse/link.go | 14 +++++++++----- fuse/snapshot.go | 13 ++++++++++--- 6 files changed, 59 insertions(+), 36 deletions(-) diff --git a/cmd/restic/cmd_mount.go b/cmd/restic/cmd_mount.go index 290ae4056..dc2ad673d 100644 --- a/cmd/restic/cmd_mount.go +++ b/cmd/restic/cmd_mount.go @@ -13,6 +13,8 @@ import ( ) type CmdMount struct { + Root bool `long:"owner-root" description:"use 'root' as the owner of files and dirs" default:"false"` + global *GlobalOptions ready chan struct{} done chan struct{} @@ -69,7 +71,7 @@ func (cmd CmdMount) Execute(args []string) error { } root := fs.Tree{} - root.Add("snapshots", fuse.NewSnapshotsDir(repo)) + root.Add("snapshots", fuse.NewSnapshotsDir(repo, cmd.Root)) cmd.global.Printf("Now serving %s at %s\n", repo.Backend().Location(), mountpoint) cmd.global.Printf("Don't forget to umount after quitting!\n") diff --git a/fuse/dir.go b/fuse/dir.go index 580feacf8..7588b31e6 100644 --- a/fuse/dir.go +++ b/fuse/dir.go @@ -16,13 +16,14 @@ var _ = fs.HandleReadDirAller(&dir{}) var _ = fs.NodeStringLookuper(&dir{}) type dir struct { - repo *repository.Repository - items map[string]*restic.Node - inode uint64 - node *restic.Node + repo *repository.Repository + items map[string]*restic.Node + inode uint64 + node *restic.Node + ownerIsRoot bool } -func newDir(repo *repository.Repository, node *restic.Node) (*dir, error) { +func newDir(repo *repository.Repository, node *restic.Node, ownerIsRoot bool) (*dir, error) { tree, err := restic.LoadTree(repo, *node.Subtree) if err != nil { return nil, err @@ -33,14 +34,15 @@ func newDir(repo *repository.Repository, node *restic.Node) (*dir, error) { } return &dir{ - repo: repo, - node: node, - items: items, - inode: node.Inode, + repo: repo, + node: node, + items: items, + inode: node.Inode, + ownerIsRoot: ownerIsRoot, }, nil } -func newDirFromSnapshot(repo *repository.Repository, snapshot SnapshotWithId) (*dir, error) { +func newDirFromSnapshot(repo *repository.Repository, snapshot SnapshotWithId, ownerIsRoot bool) (*dir, error) { tree, err := restic.LoadTree(repo, *snapshot.Tree) if err != nil { return nil, err @@ -60,8 +62,9 @@ func newDirFromSnapshot(repo *repository.Repository, snapshot SnapshotWithId) (* ChangeTime: snapshot.Time, Mode: os.ModeDir | 0555, }, - items: items, - inode: inodeFromBackendId(snapshot.ID), + items: items, + inode: inodeFromBackendId(snapshot.ID), + ownerIsRoot: ownerIsRoot, }, nil } @@ -69,8 +72,10 @@ func (d *dir) Attr(ctx context.Context, a *fuse.Attr) error { a.Inode = d.inode a.Mode = os.ModeDir | d.node.Mode - a.Uid = d.node.UID - a.Gid = d.node.GID + if !d.ownerIsRoot { + a.Uid = d.node.UID + a.Gid = d.node.GID + } a.Atime = d.node.AccessTime a.Ctime = d.node.ChangeTime a.Mtime = d.node.ModTime @@ -108,11 +113,11 @@ func (d *dir) Lookup(ctx context.Context, name string) (fs.Node, error) { } switch node.Type { case "dir": - return newDir(d.repo, node) + return newDir(d.repo, node, d.ownerIsRoot) case "file": - return newFile(d.repo, node) + return newFile(d.repo, node, d.ownerIsRoot) case "symlink": - return newLink(d.repo, node) + return newLink(d.repo, node, d.ownerIsRoot) default: return nil, fuse.ENOENT } diff --git a/fuse/file.go b/fuse/file.go index e8a5ec93d..20e6fdd16 100644 --- a/fuse/file.go +++ b/fuse/file.go @@ -24,8 +24,9 @@ type BlobLoader interface { } type file struct { - repo BlobLoader - node *restic.Node + repo BlobLoader + node *restic.Node + ownerIsRoot bool sizes []uint blobs [][]byte @@ -39,7 +40,7 @@ var blobPool = sync.Pool{ }, } -func newFile(repo BlobLoader, node *restic.Node) (*file, error) { +func newFile(repo BlobLoader, node *restic.Node, ownerIsRoot bool) (*file, error) { sizes := make([]uint, len(node.Content)) for i, id := range node.Content { size, err := repo.LookupBlobSize(id) @@ -51,10 +52,11 @@ func newFile(repo BlobLoader, node *restic.Node) (*file, error) { } return &file{ - repo: repo, - node: node, - sizes: sizes, - blobs: make([][]byte, len(node.Content)), + repo: repo, + node: node, + sizes: sizes, + blobs: make([][]byte, len(node.Content)), + ownerIsRoot: ownerIsRoot, }, nil } @@ -62,8 +64,11 @@ func (f *file) Attr(ctx context.Context, a *fuse.Attr) error { a.Inode = f.node.Inode a.Mode = f.node.Mode a.Size = f.node.Size - a.Uid = f.node.UID - a.Gid = f.node.GID + + if !f.ownerIsRoot { + a.Uid = f.node.UID + a.Gid = f.node.GID + } a.Atime = f.node.AccessTime a.Ctime = f.node.ChangeTime a.Mtime = f.node.ModTime diff --git a/fuse/file_test.go b/fuse/file_test.go index 25ea574c3..2bf224ac2 100644 --- a/fuse/file_test.go +++ b/fuse/file_test.go @@ -121,7 +121,7 @@ func TestFuseFile(t *testing.T) { Size: 42, Content: ids, } - f, err := newFile(repo, node) + f, err := newFile(repo, node, false) OK(t, err) attr := fuse.Attr{} diff --git a/fuse/link.go b/fuse/link.go index f60f8a0fa..61e05b3fd 100644 --- a/fuse/link.go +++ b/fuse/link.go @@ -12,11 +12,12 @@ import ( var _ = fs.NodeReadlinker(&link{}) type link struct { - node *restic.Node + node *restic.Node + ownerIsRoot bool } -func newLink(repo *repository.Repository, node *restic.Node) (*link, error) { - return &link{node: node}, nil +func newLink(repo *repository.Repository, node *restic.Node, ownerIsRoot bool) (*link, error) { + return &link{node: node, ownerIsRoot: ownerIsRoot}, nil } func (l *link) Readlink(ctx context.Context, req *fuse.ReadlinkRequest) (string, error) { @@ -26,8 +27,11 @@ func (l *link) Readlink(ctx context.Context, req *fuse.ReadlinkRequest) (string, func (l *link) Attr(ctx context.Context, a *fuse.Attr) error { a.Inode = l.node.Inode a.Mode = l.node.Mode - a.Uid = l.node.UID - a.Gid = l.node.GID + + if !l.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 diff --git a/fuse/snapshot.go b/fuse/snapshot.go index 6f82998c4..99f84e806 100644 --- a/fuse/snapshot.go +++ b/fuse/snapshot.go @@ -27,23 +27,30 @@ var _ = fs.HandleReadDirAller(&SnapshotsDir{}) var _ = fs.NodeStringLookuper(&SnapshotsDir{}) type SnapshotsDir struct { - repo *repository.Repository + repo *repository.Repository + ownerIsRoot bool // knownSnapshots maps snapshot timestamp to the snapshot sync.RWMutex knownSnapshots map[string]SnapshotWithId } -func NewSnapshotsDir(repo *repository.Repository) *SnapshotsDir { +func NewSnapshotsDir(repo *repository.Repository, ownerIsRoot bool) *SnapshotsDir { return &SnapshotsDir{ repo: repo, knownSnapshots: make(map[string]SnapshotWithId), + ownerIsRoot: ownerIsRoot, } } func (sn *SnapshotsDir) Attr(ctx context.Context, attr *fuse.Attr) error { attr.Inode = 0 attr.Mode = os.ModeDir | 0555 + + if !sn.ownerIsRoot { + attr.Uid = uint32(os.Getuid()) + attr.Gid = uint32(os.Getgid()) + } return nil } @@ -105,5 +112,5 @@ func (sn *SnapshotsDir) Lookup(ctx context.Context, name string) (fs.Node, error } } - return newDirFromSnapshot(sn.repo, snapshot) + return newDirFromSnapshot(sn.repo, snapshot, sn.ownerIsRoot) }