From aab414b368e713ccc4491d747a14312a16aac28b Mon Sep 17 00:00:00 2001 From: Alexander Neumann Date: Sun, 7 Jan 2018 14:50:47 +0100 Subject: [PATCH 1/3] Add test case for #1512 --- internal/restic/restorer_test.go | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/internal/restic/restorer_test.go b/internal/restic/restorer_test.go index 9e3c5528a..ad3cf1423 100644 --- a/internal/restic/restorer_test.go +++ b/internal/restic/restorer_test.go @@ -29,6 +29,7 @@ type File struct { type Dir struct { Nodes map[string]Node + Mode os.FileMode } func saveFile(t testing.TB, repo restic.Repository, node File) restic.ID { @@ -63,9 +64,15 @@ func saveDir(t testing.TB, repo restic.Repository, nodes map[string]Node) restic }) case Dir: id = saveDir(t, repo, node.Nodes) + + mode := node.Mode + if mode == 0 { + mode = 0755 + } + tree.Insert(&restic.Node{ Type: "dir", - Mode: 0755, + Mode: mode, Name: name, UID: uint32(os.Getuid()), GID: uint32(os.Getgid()), @@ -166,6 +173,21 @@ func TestRestorer(t *testing.T) { "dir/subdir/file": "file in subdir", }, }, + { + Snapshot: Snapshot{ + Nodes: map[string]Node{ + "dir": Dir{ + Mode: 0444, + Nodes: map[string]Node{ + "file": File{"file in dir"}, + }, + }, + }, + }, + Files: map[string]string{ + "dir/file": "file in dir", + }, + }, // test cases with invalid/constructed names { From b8620429e27ce28c565f657359b4a93b72c42837 Mon Sep 17 00:00:00 2001 From: Alexander Neumann Date: Sun, 7 Jan 2018 15:13:24 +0100 Subject: [PATCH 2/3] restorer: Set directory mode as last step Closes #1512 --- internal/restic/restorer.go | 26 ++++++++++++-------------- internal/restic/restorer_test.go | 13 +++++++++++++ 2 files changed, 25 insertions(+), 14 deletions(-) diff --git a/internal/restic/restorer.go b/internal/restic/restorer.go index 0424fdb64..69ae7c356 100644 --- a/internal/restic/restorer.go +++ b/internal/restic/restorer.go @@ -79,13 +79,6 @@ func (res *Restorer) restoreTo(ctx context.Context, target, location string, tre selectedForRestore, childMayBeSelected := res.SelectFilter(nodeLocation, nodeTarget, node) debug.Log("SelectFilter returned %v %v", selectedForRestore, childMayBeSelected) - if selectedForRestore { - err = res.restoreNodeTo(ctx, node, nodeTarget, nodeLocation, idx) - if err != nil { - return err - } - } - if node.Type == "dir" && childMayBeSelected { if node.Subtree == nil { return errors.Errorf("Dir without subtree in tree %v", treeID.Str()) @@ -98,14 +91,19 @@ func (res *Restorer) restoreTo(ctx context.Context, target, location string, tre return err } } + } - if selectedForRestore { - // Restore directory timestamp at the end. If we would do it earlier, restoring files within - // the directory would overwrite the timestamp of the directory they are in. - err = node.RestoreTimestamps(nodeTarget) - if err != nil { - return err - } + if selectedForRestore { + err = res.restoreNodeTo(ctx, node, nodeTarget, nodeLocation, idx) + if err != nil { + return err + } + + // Restore directory timestamp at the end. If we would do it earlier, restoring files within + // the directory would overwrite the timestamp of the directory they are in. + err = node.RestoreTimestamps(nodeTarget) + if err != nil { + return err } } } diff --git a/internal/restic/restorer_test.go b/internal/restic/restorer_test.go index ad3cf1423..ec3282e5d 100644 --- a/internal/restic/restorer_test.go +++ b/internal/restic/restorer_test.go @@ -178,6 +178,19 @@ func TestRestorer(t *testing.T) { Nodes: map[string]Node{ "dir": Dir{ Mode: 0444, + }, + "file": File{"top-level file"}, + }, + }, + Files: map[string]string{ + "file": "top-level file", + }, + }, + { + Snapshot: Snapshot{ + Nodes: map[string]Node{ + "dir": Dir{ + Mode: 0555, Nodes: map[string]Node{ "file": File{"file in dir"}, }, From b708cfee3f39a5c6fb9e8eb3de4705a4b9638acb Mon Sep 17 00:00:00 2001 From: Alexander Neumann Date: Sun, 7 Jan 2018 15:15:45 +0100 Subject: [PATCH 3/3] Add entry to changelog --- changelog/0.8.2/issue-1512 | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 changelog/0.8.2/issue-1512 diff --git a/changelog/0.8.2/issue-1512 b/changelog/0.8.2/issue-1512 new file mode 100644 index 000000000..4e30fbbf8 --- /dev/null +++ b/changelog/0.8.2/issue-1512 @@ -0,0 +1,9 @@ +Bugfix: Restore directory permissions as the last step + +This change allows restoring into directories that were not writable during +backup. Before, restic created the directory, set the read-only mode and then +failed to create files in the directory. This change now restores the directory +(with its permissions) as the very last step. + +https://github.com/restic/restic/issues/1512 +https://github.com/restic/restic/pull/1536