Browse Source

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
Jakob Borg 8 years ago
parent
commit
2b65e1062e
1 changed files with 26 additions and 22 deletions
  1. 26 22
      lib/model/rwfolder.go

+ 26 - 22
lib/model/rwfolder.go

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