Rust Coreutils 0.8.0 Release:
We are excited to announce the release of Rust Coreutils 0.8.0 — a major release featuring significant performance gains across core utilities, expanded WebAssembly (WASI) support with a brand-new online playground, and continued hardening against edge-case panics, /dev/full aborts and start of a large-scale migration from nix to rustix** for lower-level syscall safety!
GNU Test Suite Compatibility:
──────┬─────┬─────┬─────────────────────┬─────────────┬─────────────┬───────────────────────
Result│0.7.0│0.8.0│Change 0.7.0 to 0.8.0│% Total 0.7.0│% Total 0.8.0│% Change 0.7.0 to 0.8.0
──────┼─────┼─────┼─────────────────────┼─────────────┼─────────────┼───────────────────────
Pass │629 │630 │+1 │94.59% │94.74% │+0.15%
──────┼─────┼─────┼─────────────────────┼─────────────┼─────────────┼───────────────────────
Skip │13 │14 │+1 │1.95% │2.11% │+0.16%
──────┼─────┼─────┼─────────────────────┼─────────────┼─────────────┼───────────────────────
Fail │23 │21 │-2 │3.46% │3.16% │-0.30%
──────┼─────┼─────┼─────────────────────┼─────────────┼─────────────┼───────────────────────
Error │0 │0 │0 │0% │0% │0%
──────┼─────┼─────┼─────────────────────┼─────────────┼─────────────┼───────────────────────
Total │665 │665 │0 │ │ │
──────┴─────┴─────┴─────────────────────┴─────────────┴─────────────┴───────────────────────
Highlights:
- GNU Compatibility & Upstream Collaboration
- 630 passing GNU tests, with 2 fewer failures than 0.7.0
- Continued contributing tests and bug reports upstream to GNU coreutils, strengthening both projects
- Our compatibility work regularly uncovers edge cases in GNU itself, leading to fixes on both sides
- nix → rustix Migration
- Replaced nix crate with rustix across cat, df, wc, tty, tsort, tail, touch, date, mkdir, and uucore
- Reduced range of unsafe code in hostname, logname, who, and nice
- uucore: uses rustix for splice(), restricted to Linux
- Performance Improvements
- uucore: Share fluent resources between threads — dd perf +45%
- uucore: Call rt_sigaction once instead of 62 times — faster startup
- ls: Replace recursion with iterative depth-first search; remove many unnecessary allocations
- sort: Performance improvements across sorting paths
- wc: Improved -c performance with unextended pipe input (Linux)
- cat: Avoid unnecessary pipe() when stdout is already a pipe; don't lock stdout before splice()
- dd: Avoid zero-filling buffer at read_and_discard
- tee: Increased buffer size for large input; removed Box and dyn overhead
- numfmt: Protect name from argv[0] — +3% perf
- pr: Avoid String conversion when storing lines to print
- true/false/echo: Avoid uu_app().render_version() for smaller binary
- WebAssembly (WASI) Support & Online Playground
- New: Online Playground — try Rust Coreutils directly in your browser, powered by WebAssembly (blog post)
- Added WASI support for 70+ utilities including ls, head, cat, cp, mv, sort, tail, and many more
- Embedded all locales in the WASI binary
- Added WASI platform stubs for FileInformation and IO module in uucore
- Single-threaded sort path for WASI; disabled rayon on WASI
- Platform Support
- NetBSD: Multiple fixes, stdbuf support, expanded CI coverage
- pathchk: Now builds for Windows
- wc: Cross-platform building and 32-bit support
- stdbuf: Fixed Cygwin cfg block; detect unsupported target at build time
- uucore(fs): Made display_permissions_unix cross-platform
- uucore: Support realtime signals (RTMIN/RTMAX) in signal_by_name_or_value
- uucore: Permit D as decimal suffix modifier for GNU compatibility
- Documentation & Manpages
- Manpages now include TL;DR examples, links to the source code, and open bugs — see for example ls
- Manpages are available in multiple languages including French and Spanish, refreshed daily
- Added manpage linting in CI to catch formatting issues early
- TL;DR attribution and disclaimer are now translatable
- Contributions: This release was made possible by 13 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 or TL;DR pages
Sponsor us on GitHub to accelerate development: github.com/sponsors/uutils
What's Changed
cat
- cat: Drop a clone() and use clap's default value by @oech3 in #11298
- cat: replace nix with rustix by @oech3 in #11567
- cat: avoid pipe() if stdout is pipe, extend pipe by @oech3 in #11551
- cat: add bench for large size for splice by @oech3 in #11587
- cat: add WASI stub for is_unsafe_overwrite and add to feat_wasm by @sylvestre in #11573
- cat: fallback with pipe() failure by @oech3 in #11635
- cat: don't lock stdout before splice() by @oech3 in #11643
- cat: simplify splice & fix comment by @oech3 in #11627
- cat: add bench by @oech3 in #11525
- cat: remove some unnecessary to_owned() calls by @cakebaker in #11676
chown
- chown(ref): parse_uid flattened syntax by @hlsxx in #11351
- chown: warn when '.' is used as owner:group separator by @eyupcanakman in #11438
cksum
- cksum family: #[allow(clippy::unwrap_used)] by @oech3 in #11307
- cksum: add length support for shake128 and shake256 validation by @AldanTanneo in #11320
- cksum: Bring back blake3 algorithm by @RenjiSann in #11316
- cksum: rework blake length validation, add tests by @RenjiSann in #11437
- cksum: Match GNU behavior for digest length errors in --check mode by @RenjiSann in #11499
- *sum: protect names against argv[0] by @oech3 in #11375
coreutils
- coreutils: --help >/dev/full panics by @oech3 in #11444
- coreutils: --list arg and no args should fail by @oech3 in #11385
- coreutils: Protect against env -a for security by @oech3 in #10773
- coreutils: strip errno by @oech3 in #11484
- yes, coreutils: backport(enable) 2 GnuTests by @oech3 in #11480
cp
- clippy(cp): fix collapsible_if lint by @mattsu2020 in #11288
- fix(cp): always create dest dirs with owner write bit before fixing permissions by @baa-ableton in #11318
- wasm: add support for cp & mv by @sylvestre in #11572
cut
- cut: Drop a clone() and use clap's default value by @oech3 in #11310
- cut: improve some error messages by @cakebaker in #11338
- cut: reject literal '' delimiter special-casing by @can1357 in #11399
- cut: honor only-delimited in newline-delimiter mode by @can1357 in #11394
- cut: use ? instead of match by @cakebaker in #11461
date
- date: replace nix by rustix by @oech3 in #11646
- date: fix "unused variable" warning by @cakebaker in #11637
- date: fix date +%9223372036854775807c panic by @mattsu2020 in #11046
- date: fix %#P case-swap on lowercase am/pm by @vishakha1411 in #11671
- date: honor narrow width on wide default strftime fields by @vishakha1411 in #11670
- date: apply locale-aware localization before GNU modifier processing by @sylvestre in #11661
- date: add ignored tests for GNU compatibility gaps found by fuzz_date by @sylvestre in #11665
dd
- dd: fix ISO-8859-1 case conversion for conv=lcase/ucase by @sylvestre in #10830
- dd: catch OOM by @oech3 in #11562
- dd: avoid 0-filling buf at read_and_discard by @oech3 in #11583
- dd: do not show zero multiplier warning when zero is the multiplicand by @iburaky2 in #11673
df
- df: replace unsafe libc sync with nix crate by @mattsu2020 in #11279
- df: replace nix by rustix by @oech3 in #11576
env
- env: fix --version and protect against argv[0] by @oech3 in #11370
- env: Disallow ALL in --{ignore,default,block}-signal by @aweinstock314 in #11218
expand
- clippy(expand): fix collapsible_if lint by @xtqqczze in #11286
expr
- expr: fix eager evaluation of parenthesized dead branches by @can1357 in #11395
factor
- factor: fix crash on malformed input by @Alonely0 in #11190
- factor: deduplicate code, refactor & optimize parsing by @Alonely0 in #11292
head
- head: reset stale partial line state on reused buffers by @can1357 in #11407
- head: fix error message when input is a directory by @aguimaraes in #11541
- head: split head.rs by @oech3 in #11679
- feat_wasm: add head to the WASM-compatible utilities by @sylvestre in #11570
install
- install: refactor conditional expression by @xtqqczze in #11280
- install: rename unprivileged property by @cakebaker in #11283
- clippy(install): fix collapsible_if lint by @xtqqczze in #11285
- install: improve help texts by @cakebaker in #11290
ln
- ln: Avoid dereferencing target if --no-dereference is passed by @aweinstock314 in #11253
- ln: Restore backup to destination if linking fails by @aweinstock314 in #11355
- ln: simplify the code by @sylvestre in #11390
ls
- ls: replace recursion with depth-first search by @Alonely0 in #11386
- ls: remove many unnecessary allocations by @Alonely0 in #11447
- chore(ls): refactor codebase into new files by @Alonely0 in #11429
- ls: add header to new files by @cakebaker in #11442
- ls: Fix error message for ls file/missing-file by @oech3 in #11333
- ls: fall back to "." metadata for ".." on WASI by @sylvestre in #11633
- ls,dir,vdir: protect names against argv[0] by @oech3 in #11371
- simplify the ls code by @sylvestre in #11391
mkdir
- mkdir: replace libc and unsafe by rustix by @oech3 in #11647
nice
- nice: Remove unsafe and reduce bin size by @oech3 in #11489
numfmt
- numfmt: protect name from argv[0], perf +3% by @oech3 in #11379
- numfmt: move duplicate code to function by @cakebaker in #11381
- numfmt: implement the last changes by @sylvestre in #11411
- numfmt: preserve fractional digits when --from-unit is used without suffix by @Eshwar1440 in #11674
- numfmt: add failing test cases by @sylvestre in #11668
- numfmt & others: Dedup some code by @sylvestre in #11645
od
- od: default -t f to double precision by @can1357 in #11396
pr