110 Commits

Author SHA1 Message Date
weili a70f5ccd7c find: -ls: don't panic on an unmapped owner uid/gid
`find <file> -ls` panicked (exit 101) when the file's owning uid (or gid) had
no `/etc/passwd` (`/etc/group`) entry: it resolved the name with
`User::from_uid(...).unwrap().unwrap()`, and the inner unwrap aborts on the
`Ok(None)` that an unmapped id returns. Unmapped owners are routine (extracted
archives, NFS, deleted accounts, container images).

Resolve the uid/gid via `uucore::entries::uid2usr`/`gid2grp`, falling back to
the numeric id when there is no entry, matching GNU find (which prints the
number). These helpers already serialize the non-thread-safe getpwuid/getgrgid
behind a mutex, so reuse them rather than reimplementing the lookup.

Add a -ls integration test that chowns a file to an unmapped id and checks the
numeric fallback; it skips when the process lacks the privilege to do so.
2026-06-10 07:45:53 +02:00
weili 5992901805 find: -printf: test octal escape before a multibyte char
Regression test for the panic fixed in #720/#723: a `\NNN` octal escape
immediately followed by a multibyte character (`\0€`) used to slice the
format string mid-char and abort. Assert `-printf` emits the escape byte
and the following character intact.
2026-06-10 07:45:25 +02:00
weili e2d84e98d5 locate: don't panic on a too-short --database file
`locate -d <file> <pattern>` panicked (slice index underflow, exit 101) when
the database file is exactly one byte: `check_db` consumes that byte with
`read_exact`, then `read_until(b'\0', ...)` hits EOF and appends nothing,
leaving `buf` empty. `&buf[..buf.len() - 1]` then underflows `buf.len() - 1`
to `usize::MAX` and slices out of bounds.

Strip the trailing nul with `strip_suffix(b"\0")` (falling back to the whole
buffer when `read_until` stopped at EOF without one) instead of slicing
`buf.len() - 1`. An empty buffer now yields `None` (unrecognized format), so
the too-short database is skipped like any other invalid one and locate exits
1 instead of crashing. Adds a regression test.
2026-06-09 22:23:23 +02:00
Sylvestre Ledru 62deaf6e60 updatedb: clear error when the output database can't be created
Opening the output file with `?` surfaced a bare "No such file or
directory" with no indication of which file failed (easy to hit because the
default output path /usr/local/var/locatedb often doesn't exist).

Report it like GNU does, naming the path and the reason, e.g.
`cannot create '/usr/local/var/locatedb': No such file or directory`.
strip_errno() drops the trailing "(os error N)" noise.
2026-06-08 23:38:59 +02:00
Sylvestre Ledru 42f8a9af36 find: fix clippy::needless_for_each 2026-06-08 22:48:45 +02:00
✿ Fleur de Blue fb9f8df047 fix: Handle write failures when printing --help/--version (#656) 2026-06-07 19:05:03 +02:00
Sylvestre Ledru 2044d1e31d make locate and updatedb work on Windows (#704)
locate and updatedb were Unix-only (gated behind cfg and stubbed out on
Windows). Make them cross-platform:

- locate: decode raw DB entries via a platform-specific bytes_to_path
  (verbatim bytes on Unix, lossy UTF-8 elsewhere), use Metadata::len()
  instead of the unix-only size(), and a cross-platform make_symlink in
  tests that skips gracefully when symlink creation is unprivileged.
- drop the #[cfg(unix)] gate on the locate module and the
  "unsupported on Windows" main stubs for locate/updatedb.
- db_tests: remove #[cfg(not(windows))] gates, write updatedb output to
  a tempdir instead of /dev/null, and add a full updatedb->locate
  roundtrip test that is platform-independent.
2026-06-07 11:52:08 +02:00
Jeremy Smart c5ff1bbb6b implement locate and updatedb (#536)
---------

Co-authored-by: Sylvestre Ledru <sylvestre@debian.org>
2026-06-06 10:10:44 +02:00
Sylvestre Ledru e7c34ab12f test: properly exercise {} in -exec utility name (#702)
The test from #647 used {} only in an argument, so it passed on
unpatched code. Rewrite it to make the matched entry the
testing-commandline binary and pass {} as the utility name, so the
placeholder must resolve to the entry's path and execute.
2026-06-06 09:35:34 +02:00
Matt Van Horn 1a77a83432 fix: replace {} placeholder in -exec utility name (#647)
* fix: replace {} placeholder in -exec utility name

The {} placeholder was only replaced in arguments to -exec, not in the
utility_name position itself. Running `find -exec {} \;` passed the
literal string "{}" to Command::new, causing "No such file or directory".

Extracted arg parsing into a shared `parse_arg` helper and changed the
`executable` field from String to the existing Arg enum so it undergoes
the same {} replacement as other arguments.

Fixes #614

* test: add test for {} placeholder in utility name

Verify that SingleExecMatcher resolves {} in arguments
when the executable is a known path. Covers the case
where -exec receives {} in argument positions.

---------

Co-authored-by: Matt Van Horn <455140+mvanhorn@users.noreply.github.com>
2026-06-06 08:50:24 +02:00
Sylvestre Ledru a65160f724 find: match GNU prompt format for -ok/-okdir (#699)
The -ok/-okdir prompt rendered the full substituted command, but GNU
find prints a fixed, abbreviated form: "< executable ... pathname > ? "
(literal ..., a space before ?, and always the full entry path even for
-okdir). Match it exactly and update the prompt-format test.

Verified byte-for-byte against GNU findutils 4.10.0.
2026-06-05 13:18:13 +08:00
Sylvestre Ledru 9a1e379a9d fix: avoid panic on -fprintf with missing arguments (#698)
Fixes #696
2026-06-05 02:41:58 +08:00
Jesse Rosenstock 5269e233a6 find: implement -ok and -okdir (#650)
-ok is like -exec ... ; but prompts the user on stderr before each
invocation and only runs the command if the response is affirmative
(starts with 'y' or 'Y').  -okdir is the corresponding -execdir variant.
Only the ';' terminator is accepted: POSIX does not define -ok ... + and
GNU find rejects it.

Response source: GNU find reads from /dev/tty so that the user's answer
always comes from the real terminal even when stdin is occupied (e.g.
`find -files0-from - -ok rm {} \;` reads paths from stdin, so responses
cannot also come from there).  /dev/tty is the POSIX name for a
process's controlling terminal and exists on all Unix-like systems.  We
open /dev/tty only when stdin is itself a terminal
(std::io::stdin().is_terminal() == true).  When stdin is a pipe or file,
we read from stdin directly — matching BSD find and making scripted use
(and integration tests via pipe_in()) work naturally without any special
environment variable.  On Windows, or when /dev/tty cannot be opened, we
likewise fall back to stdin.

Implementation: rather than a separate OkMatcher that duplicated
SingleExecMatcher's fields, constructor, and exec logic, the interactive
prompt is folded into SingleExecMatcher behind an `interactive: bool`
field.  `SingleExecMatcher::new_interactive()` constructs the -ok/-okdir
variant; `matches()` adds a guarded block that builds a GNU-find-style
prompt ("< executable arg... >? ") and calls `matcher_io.confirm()`
before executing.  If the user declines, the expression is false and the
command is not run.  This keeps the arg-parsing, path resolution,
current_dir logic, and error handling in one place so bug fixes apply to
both -exec and -ok.

Dependencies::confirm() trait method: abstracts prompt+read so matchers
remain testable without a real terminal; FakeDependencies uses a
VecDeque of preset responses.

Tests:
- Unit tests (exec_unit_tests.rs): confirmed executes command, declined
  skips command and returns false, confirmed but command fails returns
  false, -okdir runs in parent dir
- Parser unit tests (matchers/mod.rs): missing-arg errors, missing
  semicolon, correct parse, confirm/decline via FakeDependencies
- Integration tests (test_find.rs): pipe_in() makes stdin a pipe so
  is_terminal() returns false and responses are read from the pipe;
  "y"/"Y"/"yes"/" y" run command, "n" and empty response skip command,
  -okdir runs in parent dir, prompt format verified, missing-semicolon
  error

Closes https://github.com/uutils/findutils/issues/8.
2026-06-04 20:31:54 +02:00
Daniel Hofstetter 29c644fc72 tests/common/mod.rs: adapt to change in ctor 2026-05-07 10:47:04 +02:00
Kevin Burke 69a20eb6df xargs: accept hyphenated -I and -E values
GNU xargs treats the arguments to -I, -E, and -e as values even when
they begin with a hyphen. Clap was parsing those strings as options
instead, so invocations like 'xargs -I -_' failed before xargs could
process input.

Allow hyphen-leading values for those options and add regression
coverage for replacement and EOF markers that start with '-'.
2026-05-05 16:26:23 +02:00
Jesse Rosenstock 41778576e2 tests: port to uutests (#645)
Replaces assert_cmd/predicates/pretty_assertions/serial_test with uutests and
ctor in dev-dependencies.

Closes https://github.com/uutils/findutils/issues/537.

- Port tests/find_cmd_tests.rs → tests/test_find.rs (uutests API)
- Port tests/xargs_tests.rs → tests/test_xargs.rs (uutests API)
- Centralize UUTESTS_BINARY_PATH init via #[ctor::ctor] in tests/common/mod.rs

Implementation notes:
- Use TestScenario::cmd(BINARY_PATH) rather than ucmd(): find/xargs are
  dedicated binaries, not multi-call, so ucmd() would prepend the utility name
  as a spurious first argument
- Set CWD to CARGO_MANIFEST_DIR in find's ucmd() so relative test_data/ paths
  resolve correctly regardless of where cargo runs
- delete_on_dot_dir sets the child process CWD via UCommand::current_dir()
  instead of mutating the process-wide CWD, removing the need for serial_test
  and all #[serial(working_dir)] attributes

Also fixes find_samefile, find_fprinter, and find_fprintf, which were writing
temporary files directly into test_data/. They now use isolated temp
directories, eliminating a source of test pollution when running in parallel.
2026-04-03 10:21:47 +02:00
Brian Pane c5c5a16700 Merge pull request #603 from brian-pane/eof
Ignore -E/-e flag when a delimiter is specified
2025-12-07 11:54:27 +01:00
Brian Pane dfc460a627 xargs: add support for -l option 2025-11-20 20:11:47 +00:00
Brian Pane 573b9b7788 xargs: add support for -E option (#593)
* xargs: add support for -E option

* Additional test coverage for xargs -E

* Simplify EofArgumentReader and test its error pass-through
2025-11-19 09:33:14 +01:00
Daniel Hofstetter 120ff526f7 tests: replace deprecated Command::cargo_bin
with cargo_bin_cmd!
2025-10-30 07:47:16 +01:00
cryptodarth 3f026bfe6b Merge pull request #534 from Crypto-Darth/error-msgs
change "Error:" to "find:" + Testcase fix
2025-04-24 20:26:59 +02:00
cryptodarth a571de6812 Implement : Chained Type matcher arguments (#527)
* code dump

* fix : new checks + working stage

* minor fixes + duplicates check

* fix : add check for incorrect chained commands

* add : Chained Argument matching for -xtype

* add: test

* cargo fmt

* Add : more tests + old test fix

* refactor : move common code to function

* fix : convert match to if/else

* Improve : Testcase for xtype

* cargo clippy fix

* update : testcase

* fix : error handling

* fix : use single type

* add: basic tests on binary level

* Add : -xtype tests

* refactor : use single type without Option<>

* fix : use better search logic

* refactor : use HashSet<> instead of Vec<>

* remove : unnecessary hashmap usage

* Update src/find/matchers/type_matcher.rs

Co-authored-by: Tavian Barnes <tavianator@tavianator.com>

* change: variable name

* remove: type and replace with HashSet<FileType>

* remove: trimming

---------

Co-authored-by: Tavian Barnes <tavianator@tavianator.com>
2025-04-24 20:17:39 +02:00
Daniel Hofstetter 61b396ac31 find: fix typo in test (slashs -> slashes) 2025-04-05 10:14:03 +02:00
Tavian Barnes 0429507f15 tests: Make -exec {} + tests deterministic
These tests failed on my system because directory entries were returned
in a different order, causing an output mismatch.  Add --sort to the
testing_commandline to make the output deterministic.
2025-04-02 22:11:27 -04:00
milkory 5235d78291 find: Implement exec[dir] + (#515)
* add argmax dependency

* implement finished and finished_dir callback

* implement multi exec matcher

* fix finished_dir not working correctly

* add more test for multi exec matcher

* fix execdir multi in current directory not working

* add more test for parsing multi exec

* set exit code when exec + failed

* fix clippy warnings

* prevent multi exec panics on long paths

---------

Co-authored-by: hanbings <hanbings@hanbings.io>
2025-04-02 21:04:48 +08:00