aa374bc66ebccc22e1996119c1c859e9a4c79832
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.
Description
No description provided
193 KiB
Languages
Rust
91.2%
Shell
6.7%
Python
2.1%