backup: exclude irregular files from backup

restic cannot backup irregular files as those don't behave like normal
files. Thus skip them with an error.
This commit is contained in:
Michael Eischer 2024-09-14 18:59:59 +02:00
parent 3c82fe6ef5
commit fc1fc00aa4
4 changed files with 63 additions and 1 deletions

View file

@ -262,7 +262,8 @@ func (arch *Archiver) nodeFromFileInfo(snPath, filename string, fi os.FileInfo,
} }
// overwrite name to match that within the snapshot // overwrite name to match that within the snapshot
node.Name = path.Base(snPath) node.Name = path.Base(snPath)
if err != nil { // do not filter error for nodes of irregular or invalid type
if node.Type != "irregular" && node.Type != "" && err != nil {
err = fmt.Errorf("incomplete metadata for %v: %w", filename, err) err = fmt.Errorf("incomplete metadata for %v: %w", filename, err)
return node, arch.error(filename, err) return node, arch.error(filename, err)
} }

View file

@ -2423,4 +2423,47 @@ func TestMetadataBackupErrorFiltering(t *testing.T) {
rtest.Assert(t, node != nil, "node is missing") rtest.Assert(t, node != nil, "node is missing")
rtest.Assert(t, err == replacementErr, "expected %v got %v", replacementErr, err) rtest.Assert(t, err == replacementErr, "expected %v got %v", replacementErr, err)
rtest.Assert(t, filteredErr != nil, "missing inner error") rtest.Assert(t, filteredErr != nil, "missing inner error")
// check that errors from reading irregular file are not filtered
filteredErr = nil
node, err = arch.nodeFromFileInfo("file", filename, wrapIrregularFileInfo(fi), false)
rtest.Assert(t, node != nil, "node is missing")
rtest.Assert(t, filteredErr == nil, "error for irregular node should not have been filtered")
rtest.Assert(t, strings.Contains(err.Error(), "irregular"), "unexpected error %q does not warn about irregular file mode", err)
}
func TestIrregularFile(t *testing.T) {
files := TestDir{
"testfile": TestFile{
Content: "foo bar test file",
},
}
tempdir, repo := prepareTempdirRepoSrc(t, files)
back := rtest.Chdir(t, tempdir)
defer back()
tempfile := filepath.Join(tempdir, "testfile")
fi := lstat(t, "testfile")
statfs := &StatFS{
FS: fs.Local{},
OverrideLstat: map[string]os.FileInfo{
tempfile: wrapIrregularFileInfo(fi),
},
}
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
arch := New(repo, fs.Track{FS: statfs}, Options{})
_, excluded, err := arch.save(ctx, "/", tempfile, nil)
if err == nil {
t.Fatalf("Save() should have failed")
}
rtest.Assert(t, strings.Contains(err.Error(), "irregular"), "unexpected error %q does not warn about irregular file mode", err)
if excluded {
t.Errorf("Save() excluded the node, that's unexpected")
}
} }

View file

@ -46,6 +46,16 @@ func wrapFileInfo(fi os.FileInfo) os.FileInfo {
return res return res
} }
// wrapIrregularFileInfo returns a new os.FileInfo with the mode changed to irregular file
func wrapIrregularFileInfo(fi os.FileInfo) os.FileInfo {
// wrap the os.FileInfo so we can return a modified stat_t
return wrappedFileInfo{
FileInfo: fi,
sys: fi.Sys().(*syscall.Stat_t),
mode: (fi.Mode() &^ os.ModeType) | os.ModeIrregular,
}
}
func statAndSnapshot(t *testing.T, repo archiverRepo, name string) (*restic.Node, *restic.Node) { func statAndSnapshot(t *testing.T, repo archiverRepo, name string) (*restic.Node, *restic.Node) {
fi := lstat(t, name) fi := lstat(t, name)
want, err := restic.NodeFromFileInfo(name, fi, false) want, err := restic.NodeFromFileInfo(name, fi, false)

View file

@ -26,3 +26,11 @@ func wrapFileInfo(fi os.FileInfo) os.FileInfo {
return res return res
} }
// wrapIrregularFileInfo returns a new os.FileInfo with the mode changed to irregular file
func wrapIrregularFileInfo(fi os.FileInfo) os.FileInfo {
return wrappedFileInfo{
FileInfo: fi,
mode: (fi.Mode() &^ os.ModeType) | os.ModeIrregular,
}
}