5975 Commits
Author SHA1 Message Date
fixfon 3017dccfaf printf: reject a * precision above INT_MAX for %s
The %s arm resolved a `*` precision without the check_precision call
the integer and float arms make, so a value above i32::MAX was used as
is instead of failing with "invalid precision". Check it there, for a
`*` precision only; a precision written in the format is still accepted.

Closes #15663
2026-10-28 00:26:46 +01:00
Eylul Seyitoglu c21b7adc66 chmod: report umask conflict below the -R operand
with a bare mode like -w, only the operand itself was checked for bits the umask kept. Entries found while recursing were changed silently. Chmod also exited with 0. Moved the check into a helper function and call it safe_chmod_file()
2026-10-27 23:45:47 +01:00
fixfon b80c167a49 checksum: do not let improperly formatted lines select the line format 2026-10-27 23:10:11 +01:00
gibkimandClaude Opus 5.5 24074234d7 mv: do not replace an empty directory with a symlink to a directory
The source was checked with is_dir(), which follows symlinks, so a
symlink to a directory removed an empty destination directory and was
then moved into its place. Check the source entry itself, without its
trailing slashes, which would also make lstat follow the link.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-27 22:14:34 +01:00
John Costa d7413be9bb uucore: quote a lone brace in the shell quoting styles
GNU quotes `{` and `}` when they are the whole name in the shell
quoting styles, while braces inside a longer name stay bare. This
affects `printf %q` and `ls --quoting-style=shell*`.
2026-10-27 22:10:45 +01:00
frogscooper 3caad2f042 seq, tac, numfmt, sum, ptx: accept repeated options like GNU
GNU accepts a flag or option given more than once, and the last value
wins. These utilities rejected that with "cannot be used multiple
times". Set args_override_self on their commands, as done for chown and
chgrp in #15669.

numfmt keeps the case GNU still rejects: a repeated --field fails with
"multiple field specifications".
2026-10-27 21:39:32 +01:00
tirdesh 5fc0d3b566 uucore: report unreadable files under --ignore-missing
--ignore-missing dropped every file whose open failed, not only the ones
that were absent, so a file that exists but cannot be read was skipped
without a word and the run exited 0.

Classify the error in get_file_to_check: only NotFound stays on the
missing path, anything else is printed, counted through failed_open and
returned as CantOpenFile. Drop the matching !ignore_missing guard on the
final failed_open_file check, which ignored missing files never reach.
2026-10-27 19:44:04 +01:00
vibhuthespeedst e031c6698d basenc: decode --base58 input in one piece
Base58 text is one big number, but the decoder flushed every 1024
digits, so longer input decoded to the wrong bytes and basenc could not
read back its own output.

Fixes #15776
2026-10-27 19:41:45 +01:00
Parman Mohammadalizadeh 06f3b01722 join: fold -i keys to upper case like sort -f 2026-10-27 19:41:07 +01:00
Parman Mohammadalizadeh cdca137584 fold: keep zero-width characters after a newline 2026-10-27 16:38:50 +01:00
fixfon 80eb3e903b uniq: only treat blanks as field separators for -f (#15679)
* uniq: only treat blanks as field separators for -f

skip_fields_offset used is_ascii_whitespace, which also ends a field at
\n, \r and \f. Only space and tab separate fields, so check for those.

Closes #15659

* tests: uniq: cover -z with a newline inside a record

* uniq: keep newline as a field separator with -z

GNU uniq 9.12 still ends a field at a newline with -z; only \r and \f
stop being separators.
2026-10-27 14:54:56 +01:00
gibkimandClaude Opus 5.5 217973b166 install: check for the same file before removing the destination with -D
With -D, the destination was removed before the same-file check ran, so
`install -D a a` deleted `a`. Run the check before the removal.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-27 12:27:27 +01:00
fixfon 3ee13ab487 cat: keep a single blank line after a line split across reads with -s
write_new_line() recorded a blank line as already printed for every
newline, including one that only finishes a line begun in an earlier
file or read. The real blank line right after it was then squeezed away.
Only a newline at the start of a line counts as a blank line now.

Closes #15655
2026-10-27 11:20:08 +01:00
John Costa 31a42863ae join: compare a missing join field as an empty one
A line too short to have the join field was ordered before a line whose
join field is empty, while `sort -k` gives both the same empty key. So
`join --check-order` rejected input that `sort -k` had just sorted, and
such lines never paired with each other.

Closes #15741
2026-10-27 10:20:11 +01:00
oech3 c9f618a6ae mv: don't skip cross_device_xattr_failure_keeps_the_rest fails on tmpfs 2026-10-27 09:23:19 +01:00
dragonandClaude Opus 5.5 c1f172886c groups, pinky: look up user operands by name only
Passwd::locate(&str) falls back to getpwuid() when no account has the
given name and it parses as a number, so `groups 1000` or `groups +0`
answered for that uid while GNU reports "no such user". Add a name-only
locate_name() to uucore::entries, keep locate(&str) built on it with the
existing numeric fallback for id, chown and others, and use it in
groups and pinky.

Fixes #15813

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-26 22:23:14 +01:00
dragonandClaude Opus 5.5 fb8fc2b675 rm: escape the operand in the "same as '/'" preserve-root error
The message formatted the path with Path::display(), so control
characters in a symlink name were written to stderr unescaped. Use
quote() like the other rm diagnostics and drop the literal quotes from
the en-US and fr-FR strings.

Fixes #15811

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-26 22:11:20 +01:00
Adel-Ayoub 35069f11eb test: cover empty backup suffix fallback 2026-10-26 19:57:06 +01:00
oech3 ca5c757638 workspace.wordlist.txt: add some words 2026-10-26 16:50:09 +01:00
Anubhav 9cf8156539 expr: anchor every top-level alternative of a regex 2026-10-26 16:41:11 +01:00
komal shrestha ef86b87ea6 sort: reject mixing silent and diagnosing --check modes (#15735)
* sort: reject mixing silent and diagnosing --check modes

* sort: test -c=silent -c=diagnose-first from the issue
2026-10-26 15:00:42 +01:00
Karl Mehltretter ff46288898 sort: reject incompatible modes across repeated --sort options
--sort overrides earlier occurrences of itself in clap, so ModeFlags
only sees the last --sort=<WORD> value. Passing conflicting modes such
as --sort=general-numeric --sort=human-numeric, or -h followed by
--sort=general-numeric --sort=human-numeric, drops the earlier value
and skips the incompatibility check.

Append --sort values in clap and collect every --sort occurrence in
ModeFlags::from_matches. Repeated identical --sort values remain
accepted, and conflicting modes now fail with "options '-...' are
incompatible".

Closes #15596
2026-10-26 13:59:45 +01:00
DevKaurav-14 e0056e3e3b csplit: don't strip \r before matching a regex 2026-10-26 13:45:45 +01:00
Parman Mohammadalizadeh 91d4f6adac fmt: treat -N operands after -- as file names 2026-10-26 11:19:52 +01:00
fixfon 442cfe60df tee: handle closed stdin
Refs #10154
2026-10-26 10:51:48 +01:00
sarankumar1325 0d0974dfa4 cut: don't rewrite a -d= file operand after --
A file operand named `-d=` after `--` was rewritten to `--delimiter==`
before clap parsing, so cut opened the wrong file. Stop the rewrite once
`--` has been seen.

Fixes #15806
2026-10-26 10:29:23 +01:00
xtqqczze 736703c37d build: avoid unsupported rlimit crate on fuchsia 2026-10-26 10:11:42 +01:00
sarankumar1325 98e83741f5 cut: trim Unicode blanks with -w=trimmed
In a UTF-8 locale the whitespace matcher splits fields on Unicode blanks
such as U+3000, but -w=trimmed only stripped SPACE and TAB from the ends
of a line. A leading Unicode blank then emptied field 1 and shifted every
word, a trailing one added an empty last field, and -s kept one-word
lines. Trim with the same matcher that splits the fields, and update the
help text, which still said Space/Tab only.

Fixes #15819
2026-10-26 09:42:25 +01:00
gabrielhnf 5700c9a95c shred: skip stdout tests under WASI 2026-10-26 01:27:39 +01:00
gabrielhnf bee79f2898 shred: handle '-' as stdout 2026-10-26 01:27:39 +01:00
gabrielhnf 081f2cd71e fix clippy warning 2026-10-26 01:16:19 +01:00
gabrielhnf 97e37205fc fix formatting 2026-10-26 01:16:19 +01:00
gabrielhnf 7a8c13a559 chmod: add test for EROFS error message 2026-10-26 01:16:19 +01:00
oech3 0aae92274b test_sync.rs: don't depend on chmod 2026-10-25 16:06:53 +01:00
fixfon 24f90f5f40 tests: sort: don't write stdin in early-error tests 2026-10-25 13:41:47 +01:00
fixfon 35cb6b9baa sort: reject conflicting -t separators
The -t argument kept the default set-action together with
args_override_self, so a later -t silently replaced an earlier one.
Collect every occurrence and fail with "incompatible tabs" (exit 2)
when they differ, the same way repeated -o is handled. Repeating the
same separator keeps working.

Fixes #15598
2026-10-25 13:41:47 +01:00
Tanbir Hossain Ramim b8afbcd2be uucore: keep numeric-looking arguments verbatim in clap errors 2026-10-25 10:24:41 +01:00
xtqqczze 8b6327eda1 refactor(tests): replace rustix::process dependency with rlimit 2026-10-25 09:33:00 +01:00
Jake Abendroth fecc31cb17 install: zero umask while creating ancestor directories
install -d and -D passed 0755 to mkdir(2), so the caller's umask still
applied to the ancestors they created. Run the Directory/Standard
dispatch under a umask of 0, as GNU does, so new ancestors get exactly
0755 and the strip program sees a umask of 0.
2026-10-25 09:27:10 +01:00
fixfon bd22b33a08 chmod: accept modes like -=r, -+x and -,u+x
extract_negative_modes only took an argument starting with '-' as a mode when its second character was a permission letter or a digit. Modes such as "-=r", "-+x" and "-,u+x" went on to clap, which has no such option and rejected them. Also accept '=', '+' and ',' there; no option starts with those.

Closes #15665
2026-10-25 09:08:07 +01:00
Jay Hemnani 6f5138a82d pr: keep the column separator with -J
-J only turns off truncation and column alignment, as in GNU pr. The separator between columns and merged files was dropped too, so pr -2 -J -S, printed 116 instead of 1,16. The joined.log fixture recorded the glued lines; it now has the tab GNU pr writes between the merged files.
2026-10-24 21:45:39 +02:00
NdekoCode 64daabd6b9 tests: chmod: accept any errno for the root operand
'/' is read-only on macOS, so the message ends differently there.
2026-10-24 21:40:55 +02:00
NdekoCode bbc031ea69 chmod: report every failure from one place
change_file printed its own error and returned a bare exit code, which
the recursive walk told apart from a real error by its empty message.
Return the error instead and let one helper print it, unless -f, and
set the exit status, for the operand loop as well as for the walk: every
failing operand is reported, as GNU does. The umask diagnostic is shown
where it is found, since GNU prints it even under -f.
2026-10-24 21:40:55 +02:00
NdekoCode b311031b70 chmod: check the mode once, before any file is touched
The mode was parsed again for every file, so under -R a bad one was
reported once per entry, after the walk had started. Whether it parses
does not depend on the file: check it up front, as GNU does.
2026-10-24 21:40:55 +02:00
NdekoCode b97c335a4b chmod: report every failure met under -R
Failures met while walking a tree were returned up through
`Result::and`, so only one of them reached stderr, after all the other
output, and `-f` could not hide it. An unreadable directory was also
reported as "cannot access", where GNU says "cannot read directory",
and on Hurd the `read_dir` error came back without its path.

Report each failure where it happens and keep the exit status, let
`-f` hide the messages, report an unreadable directory as
"cannot read directory", and with `-v` add the "could not be accessed"
line that GNU prints for it.
2026-10-24 21:40:55 +02:00
sarankumar1325 469c9cea76 date: keep leading zeros of %N when a width is given
%3N stripped the leading zeros of the nanosecond field before truncating
it, so 0.005123456 printed 512 instead of 005, and %s%3N timestamps
could go backwards. Handle %N as a fraction: a width keeps the first
digits and pads on the right, trailing zeros become the pad character,
and the - flag drops them. This matches GNU for the flag and width
combinations covered by the new test.

Fixes #15697
2026-10-24 16:22:56 +02:00
fixfon eef962bcb2 numfmt: drop issue link comment 2026-10-24 14:46:36 +02:00
fixfon b8eaf91e62 numfmt: drop a duplicated --to=si test case 2026-10-24 14:46:36 +02:00
fixfon e5cadd1ba3 numfmt: print an unsigned zero when rounding a negative number to zero
round_with_precision turns a small negative value into -0.0, and
format_float prints the sign of a negative zero, so `-0.3` with
`--round=up --format=%.0f` came out as `-0` (and `-0000` when
zero-padded). Drop the sign of a zero produced by rounding on the
plain path. The --to path keeps its existing `-0` output.

Closes #15661
2026-10-24 14:46:36 +02:00
Jake Wallin 6ddc30c7cf rmdir: handle verbose output failures without panicking 2026-10-24 14:30:48 +02:00