Skip to main content

Module unzip

Module unzip 

Source
Expand description

The unzip family (unzip, zipinfo, funzip): stuffr behaving as the platform’s Info-ZIP UnZip 6.00.

A port of Apple’s zip-33 tree (unzip/unzip60/, the Info-ZIP licence version 2009-Jan-02, LICENSE-infozip; this is an altered version, marked as such by every banner). Each ported function carries // port: <file>.c:<function>, each Apple change // apple: <file>.c:<line>, each Ubuntu difference // ubuntu: <patch> or // ubuntu: -D<DEFINE>, and each rule taken from the binary rather than the source // probe: <command>; where the two disagree, the binary wins. Every string is in messages.rs.

Flavours (Flavour, flavour.rs): Apple’s /usr/bin/unzip on macOS and the BSDs, Ubuntu 24.04’s 6.0-28ubuntu4.1 elsewhere (default_flavour), or as STUFFR_UNZIP_FLAVOR (apple, ubuntu) says; run reads it once, and anything else in it is refused, exit 1, in stuffr’s own words. Ubuntu’s build options (its -D DEFINES) and its patch series are flavour checks at the points they change behaviour (R13), each marked // ubuntu:.

G becomes Uz (R5): Info-ZIP’s global G (and its uO options) is one value per run, holding the host, the flavour, the options and the state, so a sandboxed run ([run_in_counted]) touches nothing of the process.

What is here: the names, the flavour, the command line (unzip.c’s unzip() front half and uz_opts(), zipinfo.c’s zi_opts(), envargs.c), the usage screens, -hh, the -v screen and funzip’s usage (Task 7); opening archives, wildcard archive names, the end records, Zip64, the central directory walk, wildcards and unzip’s listings -l, -v, -z, -T (process.rs, unix/mod.rs, matching.rs, list.rs, fileio.rs: Task 8); zipinfo’s listings, every format, the totals and the -v report (zipinfo/: Task 9); testing and extraction (extract/: extract.c, fileio.c’s output side, crypt.c’s decrypt(); unix/mapname.rs, unix/attrs.rs: unix.c’s names, paths, modes, times and symlinks; unix/beneath.rs: the resolve-beneath walk every change goes through; Task 10); the terminal (ttyio.rs: getp() on /dev/tty, zgetch(), screensize(); fileio.rs: UzpPassword(), UzpMorePause(); -M’s line counting in Uz::print_raw; crypt.c’s retries; the interrupt handler, exit 80: Task 11); funzip (funzip.rs: funzip.c, Task 12); Ubuntu’s build options and patch series as flavour checks throughout (Tasks 13 and 14; process/unicode.rs is Ubuntu’s alone). Known deviations (the source of truth; the README and the spec mirror this list):

  1. SIGPIPE: run restores SIGPIPE’s default action, as the other families do; under a parent that ignores SIGPIPE, unzip sees EPIPE and stuffr still dies of the signal (the Rust runtime ignores it before main, so the inherited disposition cannot be told apart).
  2. The first banner line of each program’s usage and -v names stuffr and says it is altered (Info-ZIP licence clause 3): UnZip 6.00 of 20 April 2009, by stuffr X.Y.Z (altered; original by Info-ZIP, with modifications by Apple Inc.). (Ubuntu: (altered; Debian's build, original by Info-ZIP).), and likewise for zipinfo and funzip. That line is wider than the pager’s 80 columns, so under -M it counts as two screen lines and -Mh pauses one text line earlier than the reference (P26). -v’s Compiled with line is the recorded reference build’s (Apple: this release’s macOS build), so other macOS builds print a different one.
  3. Pre-existing symlinks: the Ubuntu flavour also stays beneath the extraction root, as Apple’s does. On unix only: off unix (Windows) the walk (unix/beneath.rs’s imp_std) follows symlinks, so neither flavour is contained there.
  4. The archive being read is never overwritten.
  5. -O/-I (Ubuntu) convert names through iconv(3); they are unavailable on Windows, where they are parsed as Ubuntu parses them and convert nothing, as a conversion Ubuntu’s iconv_open() refuses (silently: the names stay as stored; ruling T14-5).
  6. Locale-dependent output is identical under C, C.UTF-8 and en_US.UTF-8 only.
  7. On macOS the Ubuntu flavour also propagates the archive’s quarantine attribute (R9), as Apple’s does.
  8. The terminal (T11-1, P28): after a prompt, a pager key or an interrupt, the terminal’s mode is put back exactly as it was, where unzip’s echon() only sets echo again (after an interrupt in the -M pager it leaves canonical mode off). A SIGABRT stuffr raises itself (a crash) kills it by the signal; one sent by another process exits 80, as unzip does for both. funzip installs no handler, so a signal at its password prompt kills it, echo off; stuffr puts the mode back first, then dies of the same signal (host::arm_tty_restore).
  9. funzip never loses a write failure (T12-4): a failed write to standard output is answered out of space on stdout, exit 9, on a real host too. The C writes through buffered stdio and does not check its final fflush(), so it loses the data and exits 0.
  10. Undefined behaviour and endless loops are not reproduced. Where a reference’s behaviour is undefined, or never ends, stuffr gives a defined answer instead. Ubuntu’s bzip2 decoding loops for ever on a truncated entry; stuffr answers as for bad bzip2 data, exit 2 (T13-2). Apple’s -: on a ../ directory entry changes the directory above the extraction root; stuffr refuses (T10-10). After a failed create Apple writes through the previous entry’s closed stream; stuffr says “cannot create” and goes on (T10-11). At the end of input the C asks for a new name for ever at the rename prompt, and waits for ever at the -M pager’s; stuffr takes [N]one and stops pausing (T10-9, T11-4). Buffer overflows are answered in both flavours with the forms of Ubuntu’s CVE fixes: a method above 999 is Unk and four hex digits (Unk03E8), and a password prompt whose names are too long is “Enter password: “ (T11-5). The full set is in the code’s // ruling: comments.

Enums§

Flavour
Which reference the family behaves as.

Functions§

default_flavour
The flavour a build uses when STUFFR_UNZIP_FLAVOR is unset or empty: Apple on macOS and the BSDs, Ubuntu everywhere else, Windows included.
run
Entry point for unzip, zipinfo and funzip; name is the canonical invoked name, argv0 the program as invoked (unzip.c reads its last component for ZipInfo mode) and args the arguments after it.