GNU find rejects an unrecognized predicate with
"find: unknown predicate '<arg>'", but we printed
"find: Unrecognized flag: '<arg>'". Match GNU so the
tests/find/refuse-noop GNU test (and others hitting the same path)
pass. Add an integration test covering -noop and ---noop.
`\NNN` octal escapes were parsed by slicing a fixed 3 bytes off the
format string, which panics when fewer than 3 octal digits are followed
by a multibyte character (e.g. `-printf '\0€'`): the 3-byte slice lands
inside the multibyte char and trips a char-boundary assertion.
Parse the octal escape from the leading octal digits only (1 to 3, all
ASCII) and advance by their byte length. This also fixes `\1`..`\7`,
which previously fell through to the single-character escape table and
errored instead of being treated as octal, matching GNU find.
`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.
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.
The -fstype matcher called path.symlink_metadata() (a statx/lstat syscall)
on every entry before consulting its cache, just to obtain the device id.
With several -fstype clauses on the same expression (as updatedb builds:
nfs/NFS/proc), every file was stat'd once per clause.
Derive the device id from WalkEntry::metadata() instead, which is cached on
the entry in a OnceCell and shared across all matchers, so each file is
stat'd at most once regardless of how many -fstype clauses run.
On 'updatedb --localpaths=/usr' (~506k files) this drops statx calls from
~1.52M to ~506k and wall-clock from ~1.82s to ~1.32s, with byte-identical
output.
Enable the broader clippy lint set used by uutils/coreutils (the all,
cargo and pedantic groups plus the use_self nursery lint), allowing the
noisy/low-value lints. The preceding commits fix the warnings these
groups surface so the tree stays warning-free.
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.