From 642cd3bebf97ff8d1c93eeaa5815efe749054f0a Mon Sep 17 00:00:00 2001 From: Pauline Middelink Date: Sun, 12 Mar 2017 16:39:37 +0100 Subject: [PATCH] Fix restoring files as non-root user As we cannot reliably detect in advance if we can set ownership, permissions, timestamps or ext attributes, execute ALL the requested changes before returning the first error we found. Report total errors at end of restore and stop printing entire stacktraces where just the error message is sufficient. Fixes #655 --- src/cmds/restic/cmd_restore.go | 10 ++++++++-- src/restic/node.go | 30 ++++++++++++++++-------------- 2 files changed, 24 insertions(+), 16 deletions(-) diff --git a/src/cmds/restic/cmd_restore.go b/src/cmds/restic/cmd_restore.go index 6a9ec953d..b19b58075 100644 --- a/src/cmds/restic/cmd_restore.go +++ b/src/cmds/restic/cmd_restore.go @@ -103,8 +103,10 @@ func runRestore(opts RestoreOptions, gopts GlobalOptions, args []string) error { Exitf(2, "creating restorer failed: %v\n", err) } + totalErrors := 0 res.Error = func(dir string, node *restic.Node, err error) error { - Warnf("error for %s: %+v\n", dir, err) + Warnf("ignoring error for %s: %s\n", dir, err) + totalErrors++ return nil } @@ -134,5 +136,9 @@ func runRestore(opts RestoreOptions, gopts GlobalOptions, args []string) error { Verbosef("restoring %s to %s\n", res.Snapshot(), opts.Target) - return res.RestoreTo(opts.Target) + err = res.RestoreTo(opts.Target) + if totalErrors > 0 { + Printf("There were %d errors\n", totalErrors) + } + return err } diff --git a/src/restic/node.go b/src/restic/node.go index 552e4f063..b634ed34b 100644 --- a/src/restic/node.go +++ b/src/restic/node.go @@ -158,35 +158,37 @@ func (node *Node) CreateAt(path string, repo Repository, idx *HardlinkIndex) err } func (node Node) restoreMetadata(path string) error { - var err error + var firsterr error - err = lchown(path, int(node.UID), int(node.GID)) - if err != nil { - return errors.Wrap(err, "Lchown") + if err := lchown(path, int(node.UID), int(node.GID)); err != nil { + firsterr = errors.Wrap(err, "Lchown") } if node.Type != "symlink" { - err = fs.Chmod(path, node.Mode) - if err != nil { - return errors.Wrap(err, "Chmod") + if err := fs.Chmod(path, node.Mode); err != nil { + if firsterr != nil { + firsterr = errors.Wrap(err, "Chmod") + } } } if node.Type != "dir" { - err = node.RestoreTimestamps(path) - if err != nil { + if err := node.RestoreTimestamps(path); err != nil { debug.Log("error restoring timestamps for dir %v: %v", path, err) - return err + if firsterr != nil { + firsterr = err + } } } - err = node.restoreExtendedAttributes(path) - if err != nil { + if err := node.restoreExtendedAttributes(path); err != nil { debug.Log("error restoring extended attributes for %v: %v", path, err) - return err + if firsterr != nil { + firsterr = err + } } - return nil + return firsterr } func (node Node) restoreExtendedAttributes(path string) error {