git » summer » commit 05ea437

Add comments about the order of operations

author Alberto Bertogli
2023-08-14 09:11:54 UTC
committer Alberto Bertogli
2023-08-19 11:18:56 UTC
parent 222f7188f2bf19ba45964776a2150e74fc846c39

Add comments about the order of operations

It's important we get mtime before the first read, so document it to
prevent accidents in the future.

summer.go +17 -0

diff --git a/summer.go b/summer.go
index e7860a3..0ca24bc 100644
--- a/summer.go
+++ b/summer.go
@@ -149,6 +149,18 @@ type ChecksumV1 struct {
 
 	// Modification time of the file when the checksum was computed.
 	// In Unix microseconds.
+	//
+	// Because we do not lock the file, it could be modified as we read it,
+	// and then depending on the order of operations, the checksum could be
+	// wrong and cause a false positive.
+	// To avoid this, we always read the modification time prior to reading
+	// the file contents. That way, if the file changes while we are reading
+	// it, it should be detected later as modified instead of corrupted.
+	//
+	// This relies on mtime having enough resolution to detect the change. On
+	// some filesystems that may not be the case, and a file modified very
+	// quickly may not be detected as modified. This is a limitation of the
+	// filesystem, and there is nothing we can do about it.
 	ModTimeUsec int64
 }
 
@@ -168,6 +180,11 @@ func openAndInfo(path string, d fs.DirEntry, err error, rootDev uint64) (bool, *
 	if d.IsDir() || !d.Type().IsRegular() {
 		return false, nil, nil, nil
 	}
+
+	// It is important that we obtain fs.FileInfo at this point, before
+	// reading any of the file contents, because the file could be modified
+	// while we do so. See the comment on ChecksumV1.ModTimeUsec for more
+	// details.
 	info, err := d.Info()
 	if err != nil {
 		return true, nil, nil, err