Expand description
bzip2recover: stuffr behaving as bzip2recover 1.0.8.
Ported from bzip2 1.0.8’s bzip2recover.c, copyright (C) 1996-2019
Julian Seward, under the bzip2 licence reproduced in LICENSE-bzip2.
main is followed line by line, quirks included:
- two passes over the input: the first finds every 48-bit block and end-of-stream magic and records the blocks between them; the second copies each recorded block’s bits into its own stream;
- a “block” is whatever lies between two magics and is recorded when it spans at least 130 bits, measured in unsigned 64-bit arithmetic, so a magic that follows another within 49 bits wraps round and is recorded with its end before its start (the second pass then writes nothing for it);
- a block the input ends inside is reported as
(incomplete)but never written; - each output is
BZh9, the block magic, the block’s bits, the end-of-stream magic and, as the combined CRC, the block’s own stored CRC: nothing is decompressed, recompressed or checked; - outputs are
rec%05dand the input’s base name, split at the last/, with.bz2appended unless the result already ends in it, opened asfopen(.., "wb")does (created mode 0666 less the umask, or an existing file truncated). So, as upstream does, an output is written through a symlink already at its name and truncates a file already there; Debian’sbzip2recover-race-open-output.diffrefuses both; - the limits:
BZ_MAX_FILENAME(an operand of 1980 bytes or more is refused) andBZ_MAX_HANDLED_BLOCKS(50000), with their messages; every failure exits 1.
Memory is bounded by the block cap: the input is streamed twice, and only the recorded blocks’ bit positions (at most 50000 pairs) are kept.
Known deviations from bzip2recover 1.0.8:
- At exactly 50000 magics (for example 49999 blocks plus the
end-of-stream marker) with at least 40 bits after the last, 1.0.8
writes past its
bEndarray and, on macOS, silently drops block 1; stuffr writes it, as if the arrays were 50001 long. Debian’s gcc build of the same source instead stops at the 50000th magic (“more than 50000 blocks”, exit 1); stuffr, like upstream, stops at the 50001st. - Like bzip2, a read error is reported with its
strerrortext; a staleerrnothat the C library left nonzero at a clean end of file (which would make 1.0.8 report a read error) is not reproduced. mallocFailcannot happen: nothing is allocated per bit or per block beyond the bounded position list.
Functions§
- run
- Entry point:
argv0is the program path as invoked (bzip2recover prints it in full),argsthe arguments after it.