From 82ae942965ed2b30efa0ca7b296f0a8d4a36f594 Mon Sep 17 00:00:00 2001 From: Alexander Neumann Date: Sat, 21 Nov 2020 22:08:37 +0100 Subject: [PATCH] backup: Keep mountpoints for --one-file-system When a file system is mounted at a directory, lstat() returns attributes of the root node of the mounted file system, including the device ID of the other file system. The previous code used when --one-file-system is specified excluded the directory itself because of that. This commit changes the code so that mountpoints are kept as empty directories, its attributes set to the root note of the mounted file system. The behavior mimics `tar`, which does the same. --- cmd/restic/exclude.go | 44 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) diff --git a/cmd/restic/exclude.go b/cmd/restic/exclude.go index 3c6000877..e63c689ec 100644 --- a/cmd/restic/exclude.go +++ b/cmd/restic/exclude.go @@ -288,7 +288,49 @@ func rejectByDevice(samples []string) (RejectFunc, error) { panic(fmt.Sprintf("error checking device ID of %v: %v", item, err)) } - return !allowed + if allowed { + // accept item + return false + } + + // reject everything except directories + if !fi.IsDir() { + return true + } + + // special case: make sure we keep mountpoints (directories which + // contain a mounted file system). Test this by checking if the parent + // directory would be included. + parentDir := filepath.Dir(filepath.Clean(item)) + + parentFI, err := fs.Lstat(parentDir) + if err != nil { + debug.Log("item %v: error running lstat() on parent directory: %v", item, err) + // if in doubt, reject + return true + } + + parentDeviceID, err := fs.DeviceID(parentFI) + if err != nil { + debug.Log("item %v: getting device ID of parent directory: %v", item, err) + // if in doubt, reject + return true + } + + parentAllowed, err := deviceMap.IsAllowed(parentDir, parentDeviceID) + if err != nil { + debug.Log("item %v: error checking parent directory: %v", item, err) + // if in doubt, reject + return true + } + + if parentAllowed { + // we found a mount point, so accept the directory + return false + } + + // reject everything else + return true }, nil }