Skip to content

Version 0.9.0 - POSIX conformance achieved

Latest

Choose a tag to compare

@jgarzik jgarzik released this 17 Sep 15:04
· 75 commits to main since this release
40ce91f

posixutils-rs v0.9.0

Depth over breadth: a POSIX.1-2024 conformance pass across the tree

1,009 commits (70 PRs) since v0.8.0 (2026-06-25); 817 files changed,
+178,348 / −66,622.

Nearly every utility touched this cycle was audited against POSIX.1-2024
clause by clause, and the findings fixed. The C compiler alone accounts for a
third of the commits.

Highlights

  • pcc is now c17 — the C compiler driver ships under the name of the
    one language it compiles. Dialect switching is gone; -std= remains only as
    a compatibility shim.
  • make builds real Makefiles — VPATH, built-in inference rules, %
    pattern rules, $(eval), the macro function set, conditionals and
    define/endef.
  • pax speaks tar and cpio — both command lines route into pax.
  • man renders pages real systems ship — the pest grammar is gone,
    replaced by a roff/mdoc interpreter with tbl text blocks, man-db config
    support and in-process decompression.
  • Byte-faithful text handlingsh, tr, diff, echo, expr, pax,
    i18n and plib carry file and argument data as bytes, so a non-UTF-8
    filename or IFS=é no longer aborts anything.
  • Dependency diet — the workspace went from 159 to 102 crates.
  • aarch64 Linux CI — a second architecture now gates every push.

C compiler (c17, cflow, ctags, cxref)

  • Renamed pccc17; compiles exactly one language, C17.
  • ABI correctness across x86-64 and AArch64: HFAs, all-SSE and mixed structs,
    MEMORY-class aggregates, stacked-argument placement and alignment,
    __int128 and binary128 pairs, Darwin variadic aggregates, and the
    register tally a fixed parameter actually spends.
  • New types and extensions: __float128 (IEEE binary128), _Float16,
    _Generic, __attribute__((mode)), transparent_union, vector_size,
    computed goto, case ranges, designated-initializer ranges, GNU ?:,
    __real__/__imag__, #pragma pack, _Atomic operators that are actually
    atomic.
  • Builtins: checked arithmetic, floating classification, __builtin_va_arg_pack,
    __builtin_object_size, the fortified _chk entry points, the ffs/clrsb
    family, and a working <tgmath.h>, <stdint.h> and <stdatomic.h>.
  • Preprocessor: __VA_OPT__, -dM, -P, -include, the -M dependency
    family, #include_next, include-guard detection, a correct macro hide set,
    and -E output that keeps its source lines.
  • TLS: dynamic model with TLS descriptors; -fPIC selects a
    position-independent model.
  • Debug info: -g now emits line information a debugger can use, plus DWARF
    descriptions of functions and their variables.
  • Constant folding rebuilt to fold each constant at its own width and in the
    expression's own format.
  • Diagnostics: dozens of constraint violations that used to compile silently
    are now rejected, and diagnostic message bodies are translatable.
  • cflow analyzes object files, assembler source, and lex/yacc input;
    ctags/cxref output formats corrected.
  • CPython 3.12.9 builds and passes its full test suite at -O0 and -O2.

Shell (sh)

  • Expansion, lexing and pattern matching carry byte strings end to end.
  • Field splitting rewritten as one state machine transcribing POSIX 2.6.5.
  • Job control: async lists, bg/fg, blocking waitpid, status retention
    until wait collects it, and refusal of fg/bg in a subshell.
  • Built-ins: test/[ sharing one evaluator with the utility, pwd, true,
    false, cd -e, a conforming ulimit, umask, unalias, fc.
  • Correct exit statuses, $-, $!, errexit, and-or short-circuiting,
    subshell traps, and command-substitution status.
  • Fixed two here-document hangs, eight process-aborting panics, and pipeline
    descriptor leaks.
  • New PTY test harness.

Editors (vi, ex, ed)

  • vi: :map/:unmap/:ab/:una with shortest-match lookup, a tag stack
    (:tag, ^], ^T), autoindent with spec-correct ^D, abbreviations, and
    key input driven through a real terminal queue.
  • vi: undo recorded for every buffer-changing command; motions classified so
    operators act on the right region; character and display-column counting
    where bytes were counted; buffer preserved on hangup.
  • ex: address resolution rebuilt (separators, marks, line 0, excess
    addresses), POSIX write and join rules, real substitute flags and
    replacement escapes, +command and argument lists.
  • ed: mark tracking across structural edits, one substitute per undo, wq
    parsing, n output format.

Build tools (make, lex, yacc, nm, strip, ar)

  • make: VPATH and the vpath directive, built-in inference rules, %
    pattern rules, $(eval), macro functions, conditionals, define/endef,
    override ranking, .SCCS_GET retrieval, PROJECTDIR search, -p database
    dump in makefile syntax, and a ledger-based build state. The rowan CST was
    replaced by a line scanner.
  • lex: equivalence classes derived from the NFA, per-start-condition entry
    states, ^ resolved by automaton rather than post-match filter, REJECT
    history, bracket-expression conformance, YY_INPUT.
  • yacc: LALR closure termination, non-productive non-terminal rejection,
    precedence from the last terminal, $n resolution in mid-rule actions,
    yytname in internal symbol order, $undefined.
  • nm/strip: filter interaction, section symbols, long archive member names.

Archives and file transfer (pax, compress)

  • tar and cpio front-ends.
  • Extraction is fd-relative, so a planted symlink cannot redirect a write.
  • Extended headers: path= records for oversized names, non-UTF-8 pathnames
    under -o invalid=binary, -o keyword options when listing, time keywords.
  • Correct -s substitution, -u per member, hard-link contents in cpio,
    multi-volume ustar prefixes, and attribute restoration on copy.
  • compress preserves mtime at nanosecond resolution and pre-1970 timestamps.

Text utilities

  • diff: -c/-u built from grouped sections, byte comparison, directory
    differences in the exit status.
  • patch: reads context diffs the way diff writes them, refuses absolute
    and parent-directory names, detects format over the whole patch, recognizes
    mailed headers.
  • tr: locale-driven case conversion and class membership, -c vs -C,
    equivalence classes, the string2 class rules.
  • od: float rendering as shortest-round-trip %g in aligned columns, -t f
    size letters, long double conversion, block-group duplicate suppression,
    -N as a byte count.
  • printf: XBD Ch. 5 precision and flag rules, %n$ numbered conversions,
    unsigned conversions that saturate, incremental writes.
  • more: streaming input, cell-based measurement, LINES/COLUMNS on resize,
    and a PTY test harness.
  • split, csplit, strings, uniq, pr, expr, echo, find, du,
    getconf: conformance and diagnostic fixes throughout.

Other utilities

  • mailx: one command table in place of three interpreters, mailbox locking,
    mbox that reads back, blind recipients, terminal-derived screenfuls.
  • talk/talkd: the local transport works at all now; terminfo-driven
    drawing, BSD address precedence, signal-safe teardown, end-to-end tests.
  • sccs (ten utilities): one shared implementation of each rule, s-file
    protection enforcement, delta by minimal diff (and on binaries), -i/-x
    SID lists, z-file locking with registered cleanup.
  • cron/crontab/at/batch: CRON_ALLOW/CRON_DENY gating, signal
    handlers installed before forking, $SHELL as the job interpreter, edits
    preserved on editor failure.
  • bc: pest grammar replaced by a hand-written lexer and parser; scale-correct
    division, sqrt and modulus; POSIX dynamic scoping; streamed, column-wrapped
    output.
  • m4: GNU differential gate, lazy -s line directives matching GNU byte for
    byte, ifelse warning parity.
  • man: see Highlights; also -M, -S, -k/-f native NAME search,
    architecture subdirectories, .so restricted to manual roots, recursion
    bounds throughout the roff interpreter.

Internationalization

  • gettext-rs loads real message catalogs, honoring NLSPATH, with
    positional-argument and plural formatting.
  • Diagnostics across the tree route through plib::diag / io_error_text, so
    no utility leaks Rust's Display or (os error N).
  • Locale-aware collation, case mapping and character classes in plib.

Library and infrastructure

  • plib: byte-oriented regex and collation, plib::tmp (replacing tempfile
    and retiring rustix), plib::tty with the terminal-write TOCTOU closed,
    a descriptor guard, close-on-exec temporaries, and strerror-faithful
    error text.
  • Dependency reduction from 159 to 102 crates; one codegen unit per crate for
    release builds.
  • CI runs the suite on aarch64 Linux as well as x86-64 Linux and macOS.
  • Audit files across the tree were re-probed by execution and reduced to their
    open items; cflow, ctags, cxref, echo, printf, talk, talkd,
    tr and csplit were promoted to Stage 6 (Audited).

Security-relevant fixes

  • pax extracts fd-relative; patch refuses absolute and parent-directory
    paths.
  • gettext-rs bounds catalog allocation taken from an untrusted header.
  • cron/lp guard environment overrides against set-gid, not only set-uid.
  • Temporary files are created close-on-exec, with cleanup armed and identity
    logged.
  • Recursion and output budgets bounded in man/roff, m4, bc, make and
    lex.

Contributors

Jeff Garzik, grisenti