1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
//! The `bzip2` / `bunzip2` / `bzcat` family: stuffr behaving as bzip2 1.0.8.
//!
//! Ported from bzip2 1.0.8's `bzip2.c`, copyright (C) 1996-2019 Julian R
//! Seward, under the bzip2 licence reproduced in `LICENSE-bzip2`. Its flag
//! handling, checks, messages and exit codes are followed line by line; the
//! compression itself is stuffr's bzip2 codec, whose output is byte-identical
//! to bzip2's at every level. In file-to-file mode SIGINT, SIGTERM and SIGHUP
//! are caught (even if inherited as ignored, as bzip2's `signal()` does) and
//! answered at the next chunk with bzip2's message and `cleanUpAndFail(1)`.
//!
//! Known deviations from bzip2 1.0.8:
//!
//! - `--version`/`-V`/`-L`/`--license` name stuffr and its version on the
//! licence's first line (the rest is verbatim).
//! - Verbosity 2 and above (`-vv`) behaves as `-v`: libbzip2's internal
//! trace (block CRCs, sorting statistics) is not reachable through stuffr's
//! codec API, and bzip2.c's own extra blank lines at that level only frame
//! that trace, so they are left out with it.
//! - In file-to-file mode with `-f` reading a FIFO or terminal, an interrupt
//! is answered once the blocked read returns, where bzip2 answers at once:
//! stuffr's handlers only set a flag that the read loops poll, and they
//! restart an interrupted read.
//! - When the parent ignores `SIGPIPE` (`SIG_IGN` inherited across exec),
//! bzip2 reports a Broken pipe I/O error and exits 1; stuffr dies of
//! `SIGPIPE`, because the Rust runtime sets `SIG_IGN` before `main` and the
//! inherited disposition cannot be read on stable Rust.
//! - The `perror` text after a cut-short stream reproduces the `errno` that
//! bzip2 happens to leave behind as measured on macOS; elsewhere it prints
//! `strerror(0)`.
use OsString;
use ;
use Path;
use ExitCode;
use AtomicU64;
use ;
use ;
/// Entry point for `bzip2`, `bunzip2` and `bzcat`; `name` is the canonical
/// invoked name and `args` the arguments after `argv[0]`.
/// bzip2.c's `main` after the program name: the flags, then the run.
/// [`run`] without the process: operands resolve against `dir`, standard
/// input is `stdin` (read as a pipe), standard output and error are
/// captured and returned with the exit code, neither is a terminal, `$BZIP2`
/// and `$BZIP` are unset, and `SIGPIPE` is left alone. Output is capped at
/// [`SANDBOX_OUTPUT_CAP`], and the bytes `-t` decodes (which go nowhere)
/// are charged to the same cap. For the fuzz target; not a stable interface.