lib/model: Fix rescan detection (fixes #4505, fixes #4506)

Diff is large due to comment reformatting and indentation but all it
does is wrap the file mtime/size/permissions check in an "if
stat.IsRegular()".

GitHub-Pull-Request: https://github.com/syncthing/syncthing/pull/4507
This commit is contained in:
Jakob Borg 2017-11-13 06:57:07 +00:00
parent 80031c59da
commit 2b65e1062e

View File

@ -1384,29 +1384,33 @@ func (f *sendReceiveFolder) performFinish(state *sharedPullerState) error {
curMode |= 0111 curMode |= 0111
} }
// Check that the file on disk is what we expect it to be according to // Check that the file on disk is what we expect it to be according
// the database. If there's a mismatch here, there might be local // to the database. If there's a mismatch here, there might be local
// changes that we don't know about yet and we should scan before // changes that we don't know about yet and we should scan before
// touching the file. // touching the file. There is also a case where we think the file
// There is also a case where we think the file should be there, but // should be there, but it was removed, which is a conflict, yet
// it was removed, which is a conflict, yet creations always wins when // creations always wins when competing with a deletion, so no need
// competing with a deletion, so no need to handle that specially. // to handle that specially.
switch { if stat.IsRegular() {
// The file reappeared from nowhere, or mtime/size has changed, fallthrough -> rescan. switch {
case !state.hasCurFile || !stat.ModTime().Equal(state.curFile.ModTime()) || stat.Size() != state.curFile.Size: // The file reappeared from nowhere or the modification or size
fallthrough // has changed, rescan.
// Permissions have changed, means the file has changed, rescan. case !state.hasCurFile || !stat.ModTime().Equal(state.curFile.ModTime()) || stat.Size() != state.curFile.Size:
case !f.ignorePermissions(state.curFile) && state.curFile.HasPermissionBits() && !scanner.PermsEqual(state.curFile.Permissions, curMode): fallthrough
l.Debugln("file modified but not rescanned; not finishing:", state.curFile.Name)
// Scan() is synchronous (i.e. blocks until the scan is // Permissions have changed, means the file has changed, rescan.
// completed and returns an error), but a scan can't happen case !f.ignorePermissions(state.curFile) && state.curFile.HasPermissionBits() && !scanner.PermsEqual(state.curFile.Permissions, curMode):
// while we're in the puller routine. Request the scan in the l.Debugln("file modified but not rescanned; not finishing:", state.curFile.Name)
// background and it'll be handled when the current pulling // Scan() is synchronous (i.e. blocks until the scan is
// sweep is complete. As we do retries, we'll queue the scan // completed and returns an error), but a scan can't happen
// for this file up to ten times, but the last nine of those // while we're in the puller routine. Request the scan in the
// scans will be cheap... // background and it'll be handled when the current pulling
go f.Scan([]string{state.curFile.Name}) // sweep is complete. As we do retries, we'll queue the scan
return fmt.Errorf("file modified but not rescanned; will try again later") // for this file up to ten times, but the last nine of those
// scans will be cheap...
go f.Scan([]string{state.curFile.Name})
return fmt.Errorf("file modified but not rescanned; will try again later")
}
} }
switch { switch {