mirror of https://github.com/restic/restic.git
Examine file ctime when checking if files have changed.
This commit is contained in:
parent
ecc2458de8
commit
b8c2544dcb
|
@ -0,0 +1,8 @@
|
|||
Bugfix: Use ctime when checking for file changes
|
||||
|
||||
Previously, restic only checked a file's mtime (along with other non-timestamp
|
||||
data) to decide if a file has changed. This could cause it to not notice changes
|
||||
if something edits a file and then resets the timestamp. Restic now also checks
|
||||
the ctime, so any modification to a file should be noticed.
|
||||
|
||||
https://github.com/restic/restic/issues/2179
|
|
@ -453,8 +453,13 @@ func fileChanged(fi os.FileInfo, node *restic.Node, ignoreInode bool) bool {
|
|||
return true
|
||||
}
|
||||
|
||||
// check size
|
||||
// check status change timestamp
|
||||
extFI := fs.ExtendedStat(fi)
|
||||
if !extFI.ChangeTime.Equal(node.ChangeTime) {
|
||||
return true
|
||||
}
|
||||
|
||||
// check size
|
||||
if uint64(fi.Size()) != node.Size || uint64(extFI.Size) != node.Size {
|
||||
return true
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package archiver
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
|
@ -576,6 +577,26 @@ func TestFileChanged(t *testing.T) {
|
|||
save(t, filename, defaultContent)
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "new-content-same-timestamp",
|
||||
Modify: func(t testing.TB, filename string) {
|
||||
fi, _ := os.Stat(filename)
|
||||
extFI := fs.ExtendedStat(fi)
|
||||
save(t, filename, bytes.ToUpper(defaultContent))
|
||||
sleep()
|
||||
ts := []syscall.Timespec{
|
||||
{
|
||||
Sec: extFI.AccessTime.Unix(),
|
||||
Nsec: int64(extFI.AccessTime.Nanosecond()),
|
||||
},
|
||||
{
|
||||
Sec: extFI.ModTime.Unix(),
|
||||
Nsec: int64(extFI.ModTime.Nanosecond()),
|
||||
},
|
||||
}
|
||||
syscall.UtimesNano(filename, ts)
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "other-content",
|
||||
Modify: func(t testing.TB, filename string) {
|
||||
|
|
|
@ -22,6 +22,7 @@ type ExtendedFileInfo struct {
|
|||
|
||||
AccessTime time.Time // last access time stamp
|
||||
ModTime time.Time // last (content) modification time stamp
|
||||
ChangeTime time.Time // last status change time stamp
|
||||
}
|
||||
|
||||
// ExtendedStat returns an ExtendedFileInfo constructed from the os.FileInfo.
|
||||
|
|
|
@ -30,6 +30,7 @@ func extendedStat(fi os.FileInfo) ExtendedFileInfo {
|
|||
|
||||
AccessTime: time.Unix(s.Atimespec.Unix()),
|
||||
ModTime: time.Unix(s.Mtimespec.Unix()),
|
||||
ChangeTime: time.Unix(s.Ctimespec.Unix()),
|
||||
}
|
||||
|
||||
return extFI
|
||||
|
|
|
@ -30,6 +30,7 @@ func extendedStat(fi os.FileInfo) ExtendedFileInfo {
|
|||
|
||||
AccessTime: time.Unix(s.Atim.Unix()),
|
||||
ModTime: time.Unix(s.Mtim.Unix()),
|
||||
ChangeTime: time.Unix(s.Ctim.Unix()),
|
||||
}
|
||||
|
||||
return extFI
|
||||
|
|
|
@ -27,5 +27,7 @@ func extendedStat(fi os.FileInfo) ExtendedFileInfo {
|
|||
mtime := syscall.NsecToTimespec(s.LastWriteTime.Nanoseconds())
|
||||
extFI.ModTime = time.Unix(mtime.Unix())
|
||||
|
||||
extFI.ChangeTime = extFI.ModTime
|
||||
|
||||
return extFI
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue