eric aa374bc66e Track confirmed pcap content instead of raw file length for growth/finalize
A preallocating capture writer (ftruncate-extend, zero-filled) reports the
full reserved file size immediately and fills real data into it in place,
without file length ever reflecting real progress until a final truncate at
rotation. The tailer trusted raw file length for both "is there new data"
and "are we done", so it read (and, in raw mode, forwarded) preallocated
zero padding as real packet data, then could never satisfy pos == file_len
once the file was truncated down at rotation -- a permanent hang, and worse,
a corrupted destination even when the hang didn't bite.

Replace file-length-based tracking with confirmed_len(), derived from
actually walking pcap records (RecordAlignedChunker), for any partial
(still-growing) source -- non-compress non-partial transfers are untouched,
preserving today's "arbitrary content" guarantee there. Growth detection now
re-reads from the last confirmed boundary every poll rather than only ever
reading forward past what's already been read, since a preallocating writer
can flip a byte from zero to real content without file length ever changing.

Two correctness properties enforced by the new record scanner, both gated to
partial sources only:
- A record's header being fully present and plausible is not proof its
  payload is real (header and payload aren't necessarily written
  atomically) -- a candidate record is only confirmed once the *next*
  record's header has also been observed and looks real, proof the writer
  moved past it. This holds complete_len one record behind by construction.
- That rule alone would starve the true last record of any capture forever,
  so a narrow escape hatch trusts the trailing record on its own
  plausibility once the rename has been observed and the file's length has
  been stable across continuous re-checks for a grace period -- backed by
  the writer's own "I'm done" signal (the rename), not a timing guess alone.

Also: an all-zero global header on a partial source is now treated as "not
written yet" rather than a hard error, for the same preallocation reason.

Verified against a live preallocation simulation over ssh (locl.sh): a
source truncated to a padded size well beyond its real content, with a
writer catch-up (in-place record write with no length change) before the
final truncate-and-rename, transfers with no hang and a byte-exact
destination -- confirmed_len stalls precisely at the real/padding boundary
and only advances once content, not file length, proves growth.
2026-08-27 23:07:01 -04:00
2026-08-21 17:40:12 -04:00
2026-08-25 09:03:56 -04:00
2026-08-25 09:03:56 -04:00
S
Description
No description provided
193 KiB
Languages
Rust 91.2%
Shell 6.7%
Python 2.1%