freshen records a file's size from the scan with the hash of what it reads later, so a file that changes in between gets an entry check can never pass #207

Closed
opened 2026-10-13 19:19:39 +02:00 by clawbot · 1 comment
Collaborator

freshenHasher.processEntry in internal/cli/freshen.go hashes a changed or new file with hashFile, which returns how many bytes it read, then records the entry with e.size, the size freshenScanner.recordEntry took from stat during the scan phase. The bytes read are never compared with that size. A file that grows or shrinks between the scan and the hash, such as a log being written to or a download still in progress, gets an entry whose size is from one version of the file and whose hash is from another; no content of that size has that hash, so check fails the file (SIZE_MISMATCH or HASH_MISMATCH) even if it never changes again, and nothing says why. gen refuses this: Builder.AddFile fails with size mismatch when the bytes read differ from the declared size (#25).

Confirmed on next (61238e4) with a scratch test: processEntry given a freshenEntry with size: 3 for a file that now holds 5 bytes returns nil and adds an entry of size 3 carrying the hash of the 5 bytes.

Severity: minor. It takes a file changing while freshen runs; the manifest is then wrong without a word.

Correct: processEntry fails when the bytes read differ from the size recorded at scan time, naming the file, as Builder.AddFile does; freshen then exits 1 and leaves the manifest unchanged.

Definition of done

  • Failing test first: processEntry on an entry whose recorded size differs from the file's returns an error naming the file; through the CLI, freshen exits 1 and leaves the manifest as it was.
  • The fix in internal/cli/freshen.go.
  • make check passes.

Model: fable-5-1

`freshenHasher.processEntry` in `internal/cli/freshen.go` hashes a changed or new file with `hashFile`, which returns how many bytes it read, then records the entry with `e.size`, the size `freshenScanner.recordEntry` took from `stat` during the scan phase. The bytes read are never compared with that size. A file that grows or shrinks between the scan and the hash, such as a log being written to or a download still in progress, gets an entry whose size is from one version of the file and whose hash is from another; no content of that size has that hash, so `check` fails the file (`SIZE_MISMATCH` or `HASH_MISMATCH`) even if it never changes again, and nothing says why. `gen` refuses this: `Builder.AddFile` fails with `size mismatch` when the bytes read differ from the declared size (https://git.eeqj.de/sneak/mfer/issues/25). Confirmed on `next` (61238e4) with a scratch test: `processEntry` given a `freshenEntry` with `size: 3` for a file that now holds 5 bytes returns nil and adds an entry of size 3 carrying the hash of the 5 bytes. Severity: minor. It takes a file changing while `freshen` runs; the manifest is then wrong without a word. Correct: `processEntry` fails when the bytes read differ from the size recorded at scan time, naming the file, as `Builder.AddFile` does; `freshen` then exits 1 and leaves the manifest unchanged. ## Definition of done - Failing test first: `processEntry` on an entry whose recorded size differs from the file's returns an error naming the file; through the CLI, `freshen` exits 1 and leaves the manifest as it was. - The fix in `internal/cli/freshen.go`. - `make check` passes. Model: fable-5-1
clawbot self-assigned this 2026-10-13 19:19:39 +02:00
Author
Collaborator

Fixed in #218: freshen now fails, naming the file, when a file's size changed between the scan and the hash, and leaves the manifest as it was.

Model: opus-5-5

Fixed in https://git.eeqj.de/sneak/mfer/pulls/218: freshen now fails, naming the file, when a file's size changed between the scan and the hash, and leaves the manifest as it was. Model: opus-5-5
Sign in to join this conversation.