Close file if file type has changed after initial stat
This commit is contained in:
parent
4de384087d
commit
a135699397
2 changed files with 55 additions and 3 deletions
|
@ -377,6 +377,7 @@ func (arch *Archiver) Save(ctx context.Context, snPath, target string, previous
|
|||
// make sure it's still a file
|
||||
if !fs.IsRegularFile(fi) {
|
||||
err = errors.Errorf("file %v changed type, refusing to archive")
|
||||
_ = file.Close()
|
||||
err = arch.error(abstarget, fi, err)
|
||||
if err != nil {
|
||||
return FutureNode{}, false, err
|
||||
|
|
|
@ -1985,12 +1985,15 @@ func chmod(t testing.TB, filename string, mode os.FileMode) {
|
|||
type StatFS struct {
|
||||
fs.FS
|
||||
|
||||
OverrideLstat map[string]os.FileInfo
|
||||
OverrideLstat map[string]os.FileInfo
|
||||
OnlyOverrideStat bool
|
||||
}
|
||||
|
||||
func (fs *StatFS) Lstat(name string) (os.FileInfo, error) {
|
||||
if fi, ok := fs.OverrideLstat[name]; ok {
|
||||
return fi, nil
|
||||
if !fs.OnlyOverrideStat {
|
||||
if fi, ok := fs.OverrideLstat[name]; ok {
|
||||
return fi, nil
|
||||
}
|
||||
}
|
||||
|
||||
return fs.FS.Lstat(name)
|
||||
|
@ -2102,3 +2105,51 @@ func TestMetadataChanged(t *testing.T) {
|
|||
|
||||
checker.TestCheckRepo(t, repo)
|
||||
}
|
||||
|
||||
func TestRacyFileSwap(t *testing.T) {
|
||||
files := TestDir{
|
||||
"file": TestFile{
|
||||
Content: "foo bar test file",
|
||||
},
|
||||
}
|
||||
|
||||
tempdir, repo, cleanup := prepareTempdirRepoSrc(t, files)
|
||||
defer cleanup()
|
||||
|
||||
back := fs.TestChdir(t, tempdir)
|
||||
defer back()
|
||||
|
||||
// get metadata of current folder
|
||||
fi := lstat(t, ".")
|
||||
tempfile := filepath.Join(tempdir, "file")
|
||||
|
||||
statfs := &StatFS{
|
||||
FS: fs.Local{},
|
||||
OverrideLstat: map[string]os.FileInfo{
|
||||
tempfile: fi,
|
||||
},
|
||||
OnlyOverrideStat: true,
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
|
||||
var tmb tomb.Tomb
|
||||
|
||||
arch := New(repo, fs.Track{FS: statfs}, Options{})
|
||||
arch.Error = func(item string, fi os.FileInfo, err error) error {
|
||||
t.Logf("archiver error as expected for %v: %v", item, err)
|
||||
return err
|
||||
}
|
||||
arch.runWorkers(tmb.Context(ctx), &tmb)
|
||||
|
||||
// fs.Track will panic if the file was not closed
|
||||
_, excluded, err := arch.Save(ctx, "/", tempfile, nil)
|
||||
if err == nil {
|
||||
t.Errorf("Save() should have failed")
|
||||
}
|
||||
|
||||
if excluded {
|
||||
t.Errorf("Save() excluded the node, that's unexpected")
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue