github uutils/coreutils 0.10.0

7 hours ago

Rust Coreutils 0.10.0 Release:

We are happy to announce the release of Rust Coreutils 0.10.0 - a release focused on GNU compatibility and robustness. The GNU test suite results improved sharply this cycle (645 passing, 29 failing, down from 56), we landed a second wave of security hardening (TOCTOU races, safe recursive descent, SELinux labeling at creation, backup guards), and we ran a broad anti-panic campaign across the utilities. On top of that: new features (mv --exchange, install --reflink, an OpenSSL backend for the checksum utilities), more zero-copy/read-ahead performance work, and wasm32-wasip2 support.


GNU Test Suite Compatibility:

Result 0.9.0 0.10.0 Change 0.9.0 to 0.10.0 % Total 0.9.0 % Total 0.10.0 % Change 0.9.0 to 0.10.0
Pass 625 645 +20 90.58% 93.48% +2.90%
Skip 8 15 +7 1.16% 2.17% +1.01%
Fail 56 29 -27 8.12% 4.20% -3.92%
Error 1 1 0 0.14% 0.14% 0%
Total 690 690 0

Note: 0.9.0 bumped the GNU reference to 9.11, which added 25 new tests and temporarily pushed the failure count up. This cycle absorbed most of that debt: failures dropped from 56 to 29 and passes reached an all-time high of 645.
As we contributed many tests to the GNU implementation, we are also the source of some of these regressions!


GNU testsuite evolution


Highlights:

  • GNU Compatibility

    • 645 passing GNU tests (+20) and 27 fewer failures, the largest single-cycle drop we have had
    • Dozens of behavior alignments: pr (-w/-W/-l/-e/-o, merge mode, page ranges), nproc (cgroups v2 quota, affinity mask, offline cores, OMP_* handling), date (out-of-range years, -d -, O modifier, timezone strings), numfmt, ls, du, install, od, truncate, fold, head/tail, sum, stat
    • Many error messages now carry the file name and the real OS error instead of a vague or stripped message
  • Security Hardening

    • Continued the TOCTOU work started in 0.9.0: touch no longer uses O_TRUNC on create, mkfifo drops the path-based chmod, head checks the open fd instead of the path, split hardens the output-open path, chcon anchors recursive relabeling to the traversal dirfd
    • Safe recursive descent fixes for chmod/chown (symlink cycles, --preserve-root re-checked during the descent), and cp no longer descends into a destination subdirectory that is a symlink
    • SELinux labels are now applied at creation in mkdir, mkfifo and mknod instead of being applied afterwards
    • mv fails closed when recreating a cross-device directory destination, compares file identity in the --backup=simple guard, and strips setuid/setgid when a cross-device copy cannot preserve ownership
    • chroot chroots exactly the path --skip-chdir validated; stdbuf refuses a libstdbuf path that cannot be represented in LD_PRELOAD; install finalizes ownership before mode
    • Added SECURITY.md documenting our threat model, scope and reporting process
  • Robustness: Anti-Panic Campaign

    • Removed panics and aborts across a long list of utilities: shuf, printf, numfmt, fmt, pr, chroot, dircolors, install, ln, touch, stat, split, expand, more, kill, cp, du, rm, runcon, sort, chown/chgrp, dirname, expr, cksum, dd, truncate, hashsum
    • Recurring classes fixed: write failures on /dev/full, char-boundary panics on multibyte input, integer overflow on extreme widths/precisions/sizes, and unbounded allocations for huge arguments
    • expr now uses an iterative parser, so deeply nested expressions no longer overflow the stack
  • New Features

    • mv --exchange to atomically swap two paths
    • install --reflink support, and install -C now works with --preserve-timestamps
    • OpenSSL backend for the faster checksum utilities
    • cut -O as a short option for --output-delimiter
    • rm --one-file-system
    • timeout now works on Windows, and tail -f/-F finally follows files on Windows
  • Performance

    • Read-ahead hints across the cksum family, sum, split, expand/unexpand and the base* utilities
    • tee zero-copy fast path; cat throughput improvements; faster non-reflink cp; cross-device mv via the fast copy path
    • expr: index went from O(N*M) to O(N+M); uniq and du improvements; tsort now buffers its output
    • New benchmarks for expr, tr, cut, uniq and locale-aware sort merges
  • Internationalization

    • cut supports multibyte characters in non-UTF-8 locales
    • ls uses Unicode quotes for the locale/clocale styles in UTF-8 locales and escapes non-ASCII control characters
    • Fixed C.UTF-8 being detected as ASCII, and incomplete Fluent fallback bundles
    • cksum quotes file names in a locale-aware way
  • Cross-platform Reach

    • New wasm32-wasip2 target support
    • Windows: timeout implementation, sparse copy support in cp, tail -f, cksum CRLF fix
    • ls --numeric-uid-gid on non-unix platforms, uptime uses CLOCK_BOOTTIME on more platforms
  • Code Quality

    • clippy::collapsible_if and clippy::match_same_arms are now clean and enabled workspace-wide
    • Continued nixrustix migration (dd, kill, sync, uptime) and further removal of unsafe and to_string_lossy
  • Contributions: This release was made possible by 50 new contributors joining our community


Call to Action:

Try it in your browser - Online Playground powered by WebAssembly
Help us translate - Contribute to Rust Coreutils on Weblate
Sponsor us on GitHub to accelerate development: github.com/sponsors/uutils

What's Changed

arch

base32, base64, basenc

cat

chgrp

  • chgrp: unstripped error on operation not permitted error by @Devel08 in #13361
  • chgrp: fix error message for --from nonexisting_group GROUP by @cakebaker in #13490
  • chgrp: make test_reference less strict on Linux by @cakebaker in #13650

chmod

  • chmod: always call chmod(2) even when mode bits are unchanged by @sylvestre in #13213
  • test_chmod.rs: remove an ignored test covered by check-safe-traversal.sh by @oech3 in #13298
  • chmod: fix 2 clippy::collapsible_if by @oech3 in #13509
  • chmod: report the real error when a target's metadata is inaccessible by @0xfandom in #13637

chown

  • chown: -h on symlink to directory operates on link, not target by @rossilor95 in #12522
  • chown: restrict no-dereference symlink ctime test to Linux by @rossilor95 in #12556
  • chown, chgrp: report a verbose stdout write error instead of panicking by @leeewee in #13381
  • fix(chown,chgrp): print --verbose success lines to stdout by @l46983284-cpu in #13419

chroot

  • chroot: don't panic on --skip-chdir with a non-resolving NEWROOT by @leeewee in #12732
  • chroot: avoid unwrap-like operation by @oech3 in #13306

cksum

comm

cp

csplit

cut

date

dd

df

dir

dircolors

dirname

  • dirname: fix dirname . >/dev/full panic by @oech3 in #12810

du

env

expand

expr

fmt

fold

  • fold: fix crash when reading from pseudo-devices by @lavafroth in #11314
  • fold: insert fold newline at read-buffer boundary by @sylvestre in #12682
  • gnucompability(fold): uutils fold accept width 0 but gnu fold rejects it by @Devel08 in #12744
  • fold: continue processing files after an open error by @sylvestre in #12668

groups

hashsum

head

hostid

id

  • id: don't exit 1 when uid/gid name lookup fails in default output by @c-tonneslan in #12341

install

join

kill

ln

ls

mkdir

mkfifo

  • mkfifo: handle required arg by clap by @oech3 in #13504
  • mkfifo: stop hardcoding "File exists" as the error message by @Gooh456 in #13551

mktemp

more

mv

nice

nohup

nproc

numfmt

  • numfmt: prevent panic if float precision specifier > 65535 by @Devel08 in #12600
  • numfmt: bound --format precision for a zero value by @leeewee in #12939
  • numfmt: require equals for --header by @bachorp in #13273
  • numfmt: reject an oversized --from-unit/--to-unit instead of panicking by @leeewee in #13484
  • numfmt: do not panic on a multibyte whitespace field separator by @leeewee in #13485
  • numfmt: add --from=auto test for multibyte whitespace separator by @kushals256 in #13487
  • numfmt: prevent panic for --format precision > 65535 on remaining paths by @SAY-5 in #13514
  • numfmt: simplify bool & fix clippy::collapsible_if by @oech3 in #13526

od

paste

  • paste: reset the delimiter list per file in serial mode by @winklemad in #13439
  • paste: simplify 2 loop by while by @oech3 in #13740

pr

printf

  • printf: avoid panic on integer precision above u16::MAX by @SAY-5 in #12579
  • printf, csplit: fix formatting for zero value when precision is zero by @eyupcanakman in #13425

ptx

  • ptx: fix panic caused by improper assert by @WhateverAWS in #10916
  • ptx: reject invalid sentence regexps by @TheAdamWarlock in #12892
  • fix(ptx): missing filename in error messages by @HackingRepo in #13251
  • ptx: use char counts for before-chunk sizing in get_output_chunks by @sylvestre in #12685
  • ptx: simplify match by @oech3 in #13709

pwd

  • pwd: ignore non-option arguments, drop getcwd disabling from pwd-long test by @sylvestre in #12610
  • pwd: remove to_string_lossy by @oech3 in #13366

realpath

  • realpath: fix 'nonexistent/./' to be treated as invalid by @LoukasPap in #13164
  • realpath: remove to_string_lossy by @oech3 in #13360
  • realpath: don't require read permission on a directory just to confirm a trailing slash by @Chaganti-Reddy in #13315

rm

runcon

  • runcon: report a stdout write error instead of panicking by @leeewee in #13380
  • runcon: fix clippy::match_same_arms by @oech3 in #13649

seq

  • seq, printf: avoid integer overflow on extreme precision/exponent by @sylvestre in #13246
  • seq: simplify match by .map_err by @oech3 in #13598

shred

shuf

  • shuf: fix panic/abort on large -i range without small --head-count by @leeewee in #12501
  • shuf: don't truncate -o output when input or random source fails by @sylvestre in #13113

sort

  • sort: fix locale collation strength for hyphen ordering by @JuanCruzMateos in #12677
  • sort: reject --parallel non-zero by @oech3 in #13024
  • sort: ignore --parallel on WASI by @cakebaker in #13028
  • sort: test punctuation-only differences are kept by -u under locale by @sylvestre in #13142
  • sort: add merge benchmarks for the UTF-8 locale by @sylvestre in #13196
  • sort: fix panic on non-UTF-8 filenames with --files0-from by @ppmpreetham in #11593
  • sort: use os_string_from_vec for --files0-from names by @leeewee in #12773
  • sort: fix clippy::collapsible_if by @oech3 in #13530
  • sort: simplify match of chars by @oech3 in #13536
  • sort: do not panic when a write fails during a merge by @mgravell in #13654
  • sort: do not panic when --check stops at the first disorder by @mgravell in #13652
  • sort: make return value of loop explicit by @cakebaker in #13674

split

stat

  • stat: fix char-boundary panic on an invalid directive after a multibyte char by @leeewee in #12617
  • stat: bad error message when directory doesn't exist by @Devel08 in #13026
  • chore(l10n): fix typo in stat -L size by @BAMF0 in #13429
  • stat: fix clippy::collapsible_if by @oech3 in #13531
  • stat: use .filter & dedup check for char by @oech3 in #13535
  • stat: fix clippy::match_same_arms by @oech3 in #13648

stty

  • stty: avoid overflow when rounding max baud rate by @sjh9714 in #13318
  • stty: fix trailing semicolon in macro used in expression position by @sylvestre in #13468

sum

sync

tac

tail

  • tail: replace .ok().is_some_and by .is_ok_and by @oech3 in #12690
  • tail: remove unnecessary .as_fd() by @oech3 in #12739
  • tail: drop outdated comment about <&- by @oech3 in #12752
  • tail: reduce code by @oech3 in #12755
  • tail: fix a collapsible_if by @oech3 in #13107
  • tail: treat a watched file replaced by a symlink as untailable by @sylvestre in #12661
  • tail: remove .to_string_lossy() by @oech3 in #13356
  • tail: continue processing files after error by @lauchimoon in #13445
  • tail, touch: fix clippy::collapsible_if by @oech3 in #13533
  • tail: remove commented out line by @cakebaker in #13539
  • tail: simplify match by @oech3 in #13563
  • tail: fix -f/-F not following files on Windows (#4827) by @crutkas in #13248
  • tail: remove an unused var: old_md by @oech3 in #13636
  • tail: replace matches! by is_some_and, avoid negative name by @oech3 in #13635
  • tail: remove an unwrap() by @oech3 in #13707
  • tests(tail): fix race in untailable-symlink test by @eduardomourar in #13704
  • tail(test): Attempt to fix flaky tail pipe test by increasing byte count by @Xylphy in #13701

tee

timeout

  • fix(timeout, uucore): use sigwait and timers for waiting by @Alonely0 in #13237
  • timeout: Implemention for windows by @nikolalukovic in #13363

touch

tr

  • tr: add codspeed benchmark by @parasol-aser in #12189

true

  • true, false: strip errno & cleanup use by @oech3 in #13591

truncate

tsort

  • tsort: simplify code by @oech3 in #12550
  • Add buffered printing and lock output stream to tsort by @mrkalling in #12733
  • tsort simplify cfg by @oech3 in #13219
  • tsort: remove unreachable error case by @cakebaker in #13238
  • tsort: remove unnecessary uses of unsafe by @mrkalling in #13323
  • tsort: improve expect error message by @xtqqczze in #13566

unexpand

  • unexpand: reject too-large --tabs increment instead of overflowing by @santhreal in #13383

uniq

uptime

users

  • users: fix clippy::collapsible_if (OpenBSD) by @oech3 in #13547

wc

who

yes

uucore

  • simplify pipe wrapper by @oech3 in #12528
  • pipes:rs: replace unnecessary splice by read-ahead hint by @oech3 in #12548
  • pipes.rs: fix typo by @oech3 in #12554
  • uucore: remove unnecessary .as_fd() by @oech3 in #12740
  • uucore: supress clippy::collapsible_if warning by @oech3 in #12940
  • uucore: handle SIGRTMIN+N and SIGRTMAX-N notation by @enr0n in #12149
  • uucore: remove dead code by @oech3 in #13183
  • uucore: rename copy_stream to copy_fast to avoid confusion by @oech3 in #13289
  • locale: fix incomplete fallback bundles by @BAMF0 in #13257
  • locale: simplify partial-resource fallback with unwrap_or_else by @sylvestre in #13301
  • perms.rs: replace unnecessary to_string_lossy by @oech3 in #13359
  • uucore: replace unnecessary to_string_lossy by @oech3 in #13358
  • uucore/fsxattr: simplify two matches by @cakebaker in #13362
  • fn starts_with_plus by @oech3 in #13357
  • backup_control.rs: remove unsafe & Mutex by @oech3 in #12290
  • uucore parser: fix clippy::collapsible_if by @oech3 in #13510
  • signals.rs: fix clippy::collapsible_if by @oech3 in #13508
  • uucore: fix C.UTF-8 locale incorrectly detected as ASCII by @mufeedali in #12525
  • lib.rs: simplify fn read_yes by @oech3 in #13692
  • uucore: document strip_errno with an example by @sylvestre in #13724
  • uucore: use workspace dependencies by @xtqqczze in #13729
  • error: clarify UUsageError documentation by @xtqqczze in #13737

Security

Code Quality & Cleanup

CI & Build

Documentation

Platform Support

Dependency Updates

Version Management

New Contributors

Full Changelog: 0.9.0...0.10.0

Don't miss a new coreutils release

NewReleases is sending notifications on new releases.