mirror of
https://github.com/restic/restic.git
synced 2024-12-21 23:33:03 +00:00
archiver: fix file type change test
The test did not test the case that the type of a file changed unexpectedly.
This commit is contained in:
parent
d7f4b9db60
commit
6cb19e0190
2 changed files with 66 additions and 35 deletions
|
@ -369,7 +369,7 @@ func (arch *Archiver) dirToNodeAndEntries(snPath, dir string, meta fs.File) (nod
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
if node.Type != restic.NodeTypeDir {
|
if node.Type != restic.NodeTypeDir {
|
||||||
return nil, nil, fmt.Errorf("directory %v changed type, refusing to archive", snPath)
|
return nil, nil, fmt.Errorf("directory %q changed type, refusing to archive", snPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
names, err = meta.Readdirnames(-1)
|
names, err = meta.Readdirnames(-1)
|
||||||
|
@ -548,7 +548,7 @@ func (arch *Archiver) save(ctx context.Context, snPath, target string, previous
|
||||||
|
|
||||||
// make sure it's still a file
|
// make sure it's still a file
|
||||||
if !fi.Mode().IsRegular() {
|
if !fi.Mode().IsRegular() {
|
||||||
err = errors.Errorf("file %v changed type, refusing to archive", target)
|
err = errors.Errorf("file %q changed type, refusing to archive", target)
|
||||||
return filterError(err)
|
return filterError(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2202,9 +2202,10 @@ func snapshot(t testing.TB, repo archiverRepo, fs fs.FS, parent *restic.Snapshot
|
||||||
|
|
||||||
type overrideFS struct {
|
type overrideFS struct {
|
||||||
fs.FS
|
fs.FS
|
||||||
overrideFI os.FileInfo
|
overrideFI os.FileInfo
|
||||||
overrideNode *restic.Node
|
resetFIOnRead bool
|
||||||
overrideErr error
|
overrideNode *restic.Node
|
||||||
|
overrideErr error
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *overrideFS) OpenFile(name string, flag int, metadataOnly bool) (fs.File, error) {
|
func (m *overrideFS) OpenFile(name string, flag int, metadataOnly bool) (fs.File, error) {
|
||||||
|
@ -2213,7 +2214,7 @@ func (m *overrideFS) OpenFile(name string, flag int, metadataOnly bool) (fs.File
|
||||||
return f, err
|
return f, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if filepath.Base(name) == "testfile" {
|
if filepath.Base(name) == "testfile" || filepath.Base(name) == "testdir" {
|
||||||
return &overrideFile{f, m}, nil
|
return &overrideFile{f, m}, nil
|
||||||
}
|
}
|
||||||
return f, nil
|
return f, nil
|
||||||
|
@ -2225,7 +2226,18 @@ type overrideFile struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f overrideFile) Stat() (os.FileInfo, error) {
|
func (f overrideFile) Stat() (os.FileInfo, error) {
|
||||||
|
if f.ofs.overrideFI == nil {
|
||||||
|
return f.File.Stat()
|
||||||
|
}
|
||||||
return f.ofs.overrideFI, nil
|
return f.ofs.overrideFI, nil
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f overrideFile) MakeReadable() error {
|
||||||
|
if f.ofs.resetFIOnRead {
|
||||||
|
f.ofs.overrideFI = nil
|
||||||
|
}
|
||||||
|
return f.File.MakeReadable()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f overrideFile) ToNode(ignoreXattrListError bool) (*restic.Node, error) {
|
func (f overrideFile) ToNode(ignoreXattrListError bool) (*restic.Node, error) {
|
||||||
|
@ -2320,48 +2332,67 @@ func TestMetadataChanged(t *testing.T) {
|
||||||
checker.TestCheckRepo(t, repo, false)
|
checker.TestCheckRepo(t, repo, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRacyFileSwap(t *testing.T) {
|
func TestRacyFileTypeSwap(t *testing.T) {
|
||||||
files := TestDir{
|
files := TestDir{
|
||||||
"testfile": TestFile{
|
"testfile": TestFile{
|
||||||
Content: "foo bar test file",
|
Content: "foo bar test file",
|
||||||
},
|
},
|
||||||
|
"testdir": TestDir{},
|
||||||
}
|
}
|
||||||
|
|
||||||
tempdir, repo := prepareTempdirRepoSrc(t, files)
|
for _, dirError := range []bool{false, true} {
|
||||||
|
desc := "file changed type"
|
||||||
|
if dirError {
|
||||||
|
desc = "dir changed type"
|
||||||
|
}
|
||||||
|
t.Run(desc, func(t *testing.T) {
|
||||||
|
tempdir, repo := prepareTempdirRepoSrc(t, files)
|
||||||
|
|
||||||
back := rtest.Chdir(t, tempdir)
|
back := rtest.Chdir(t, tempdir)
|
||||||
defer back()
|
defer back()
|
||||||
|
|
||||||
// get metadata of current folder
|
// get metadata of current folder
|
||||||
fi := lstat(t, ".")
|
var fakeName, realName string
|
||||||
tempfile := filepath.Join(tempdir, "testfile")
|
if dirError {
|
||||||
|
// lstat claims this is a directory, but it's actually a file
|
||||||
|
fakeName = "testdir"
|
||||||
|
realName = "testfile"
|
||||||
|
} else {
|
||||||
|
fakeName = "testfile"
|
||||||
|
realName = "testdir"
|
||||||
|
}
|
||||||
|
fakeFI := lstat(t, fakeName)
|
||||||
|
tempfile := filepath.Join(tempdir, realName)
|
||||||
|
|
||||||
statfs := &overrideFS{
|
statfs := &overrideFS{
|
||||||
FS: fs.Local{},
|
FS: fs.Local{},
|
||||||
overrideFI: fi,
|
overrideFI: fakeFI,
|
||||||
}
|
resetFIOnRead: true,
|
||||||
|
}
|
||||||
|
|
||||||
ctx, cancel := context.WithCancel(context.Background())
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
wg, ctx := errgroup.WithContext(ctx)
|
wg, ctx := errgroup.WithContext(ctx)
|
||||||
repo.StartPackUploader(ctx, wg)
|
repo.StartPackUploader(ctx, wg)
|
||||||
|
|
||||||
arch := New(repo, fs.Track{FS: statfs}, Options{})
|
arch := New(repo, fs.Track{FS: statfs}, Options{})
|
||||||
arch.Error = func(item string, err error) error {
|
arch.Error = func(item string, err error) error {
|
||||||
t.Logf("archiver error as expected for %v: %v", item, err)
|
t.Logf("archiver error as expected for %v: %v", item, err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
arch.runWorkers(ctx, wg)
|
arch.runWorkers(ctx, wg)
|
||||||
|
|
||||||
// fs.Track will panic if the file was not closed
|
// fs.Track will panic if the file was not closed
|
||||||
_, excluded, err := arch.save(ctx, "/", tempfile, nil)
|
_, excluded, err := arch.save(ctx, "/", tempfile, nil)
|
||||||
if err == nil {
|
rtest.Assert(t, err != nil && strings.Contains(err.Error(), "changed type, refusing to archive"), "save() returned wrong error: %v", err)
|
||||||
t.Errorf("Save() should have failed")
|
tpe := "file"
|
||||||
}
|
if dirError {
|
||||||
|
tpe = "directory"
|
||||||
if excluded {
|
}
|
||||||
t.Errorf("Save() excluded the node, that's unexpected")
|
rtest.Assert(t, strings.Contains(err.Error(), tpe+" "), "unexpected item type in error: %v", err)
|
||||||
|
rtest.Assert(t, !excluded, "Save() excluded the node, that's unexpected")
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue