diff options
author | Bernhard Voelker <mail@bernhard-voelker.de> | 2021-05-06 23:24:43 +0200 |
---|---|---|
committer | Bernhard Voelker <mail@bernhard-voelker.de> | 2021-05-08 14:13:36 +0200 |
commit | 11576f4e6ab6938faf3f39cd693c8131b75551f3 (patch) | |
tree | 5a3b7b48b854d4f68d433b30cef2b5ddc510ba40 /tests/find | |
parent | 9ec8970ce7601a829a8343de4b7353f5066ed738 (diff) | |
download | findutils-11576f4e6ab6938faf3f39cd693c8131b75551f3.tar.gz |
find: add -files0-from option
* bootstrap.conf (gnulib_modules): Add argv-iter and same-inode.
* find/defs.h (struct options): Add files0_from and ok_prompt_stdin
members.
* find/ftsfind.c (argv-iter.h, same-inode.h, xalloc.h): Add #include
for gnulib headers.
(process_all_startpoints): Change loop over starting point arguments
to a loop using the argv_iter gnulib module.
* find/parser.c (parse_table): Add option.
(parse_files0_from): Declare and define function.
(insert_exec_ok): Set options flag ok_prompt_stdin to true for
the -ok and -okdir action.
* find/util.c (usage): Add new option.
(set_option_defaults): Initialize new struct members.
* doc/find.texi (node Starting points): Add new section describing
the regular processing of starting points, and that with the new
option. Also mention in the description of -ok and -okdir that they
conflict with the new option.
* find/find.1: Document the new option here as well.
* tests/find/files0-from.sh: Add test.
* tests/local.mk (all_tests): Reference it.
* NEWS (New features in find): Mention the new option.
Diffstat (limited to 'tests/find')
-rwxr-xr-x | tests/find/files0-from.sh | 170 |
1 files changed, 170 insertions, 0 deletions
diff --git a/tests/find/files0-from.sh b/tests/find/files0-from.sh new file mode 100755 index 00000000..b930a999 --- /dev/null +++ b/tests/find/files0-from.sh @@ -0,0 +1,170 @@ +#!/bin/sh +# Exercise -files0-from option. + +# Copyright (C) 2021 Free Software Foundation, Inc. + +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +. "${srcdir=.}/tests/init.sh"; fu_path_prepend_ +print_ver_ find + +# Option -files0-from requires a file name argument. +returns_ 1 find -files0-from > out 2> err \ + && grep 'missing argument.*files0' err \ + || { grep . out err; fail=1; } + +# Option -files0-from must not be combined with passing starting points on +# the command line. +returns_ 1 find OFFENDING -files0-from FILE > out 2> err \ + && grep 'extra operand .*OFFENDING' err \ + && grep 'file operands cannot be combined with -files0-from' err \ + || { grep . out err; fail=1; } + +# Process "." as default when starting points neither passed via -files0-from +# nor on the command line. +printf "%s\n" '.' > exp || framework_failure_ +find -maxdepth 0 > out 2> err || fail=1 +compare exp out || fail=1 +compare /dev/null err || fail=1 + +# Option -files0-from with argument "-" (=stdin) must not be combined with +# the -ok action: getting the user confirmation would mess with stdin. +returns_ 1 find -files0-from - -ok echo '{}' ';' < /dev/null > out 2> err \ + && grep 'files0.* standard input .*cannot be combined with .*ok' err \ + || { grep . out err; fail=1; } + +# Option -files0-from with argument "-" (=stdin) must not be combined with +# the -okdir action: getting the user confirmation would mess with stdin. +returns_ 1 find -files0-from - -okdir echo '{}' ';' < /dev/null > out 2> err \ + && grep 'files0.* standard input .*cannot be combined with .*ok' err \ + || { grep . out err; fail=1; } + +# File argument of -files0-from option must not refer to the same file as stdin. +printf '.' > in || framework_failure_ +returns_ 1 find -files0-from in -ok echo '{}' ';' < in > out 2> err \ + && grep 'files0.* standard input .*same file .*with -ok, -okdir' err \ + || { grep . out err; fail=1; } + +# Likewise via a symlink. +if ln -s in inlink; then + returns_ 1 find -files0-from inlink -ok echo '{}' ';' < in > out 2> err \ + && grep 'files0.* standard input .*same file .*with -ok, -okdir' err \ + || { grep . out err; fail=1; } + # ... and vice versa. + returns_ 1 find -files0-from in -ok echo '{}' ';' < inlink > out 2> err \ + && grep 'files0.* standard input .*same file .*with -ok, -okdir' err \ + || { grep . out err; fail=1; } +fi + +# Likewise when the system provides the name '/dev/stdin'. +if ls /dev/stdin >/dev/null 2>&1; then + returns_ 1 find -files0-from /dev/stdin -ok echo '{}' ';' < in > out 2> err \ + && grep 'files0.* standard input .*same file .*with -ok, -okdir' err \ + || { grep . out err; fail=1; } +fi + +# Exercise a non-existing file. +returns_ 1 find -files0-from ENOENT > out 2> err \ + && grep 'cannot open .ENOENT. for reading: No such' err \ + || { grep . out err; fail=1; } + +# Exercise a file which cannot be opened. +# The shadow(5) file seems to be a good choice for reasonable coverage. +f='/etc/shadow' +if test -e $f && test '!' -r $f; then + returns_ 1 find -files0-from $f > out 2> err \ + && grep 'cannot open .* for reading: Permission denied' err \ + || { grep . out err; fail=1; } +fi + +# Exercise a directory argument. +returns_ 1 find -files0-from / > out 2> err \ + && grep 'read error' err \ + || { grep . out err; fail=1; } + +# Exercise an empty input file. +returns_ 1 find -files0-from /dev/null > out 2> err || fail=1 +compare /dev/null out || fail=1 +grep 'file with starting points is empty:' err || fail=1 + +# Likewise via stdin. +returns_ 1 find -files0-from - < /dev/null > out 2> err || fail=1 +compare /dev/null out || fail=1 +grep 'file with starting points is empty:.*standard input' err || fail=1 + +# Likewise via a pipe on stdin. +cat /dev/null | returns_ 1 find -files0-from - > out 2> err || fail=1 +compare /dev/null out || fail=1 +grep 'file with starting points is empty:.*standard input' err || fail=1 + +# Now a regular case: 2 files: expect the same output. +touch a b || framework_failure_ +printf '%s\0' a b > in || framework_failure_ +tr '\0' '\n' < in > exp || framework_failure_ +find -files0-from in -print > out 2> err || fail=1 +compare exp out || fail=1 +compare /dev/null err || fail=1 + +# Demonstrate that -files0-from accepts file names which would otherwise be +# rejected because they are recognized as test or action. +touch ./-print ./-mtime ./-size || framework_failure_ +printf '%s\0' _print _mtime _size | tr '_' '-' > in || framework_failure_ +tr '\0' '\n' < in > exp || framework_failure_ +find -files0-from in -printf '%p\n' > out 2> err || fail=1 +compare exp out || fail=1 +compare /dev/null err || fail=1 + +# Zero-length file name on position 2, once per stdin ... +printf '%s\n' a b > exp || framework_failure_ +printf '%s\0' a '' b \ + | tee file \ + | returns_ 1 find -files0-from - -print > out 2> err || fail=1 +compare exp out || fail=1 +grep '(standard input).:2: invalid zero-length file name' err || fail=1 +# ... and once per file. +returns_ 1 find -files0-from file -print > out 2> err || fail=1 +compare exp out || fail=1 +grep 'file.:2: invalid zero-length file name' err || fail=1 + +# Non-existing file name. +printf '%s\0' a ENOENT b \ + | returns_ 1 find -files0-from - -print > out 2> err || fail=1 +compare exp out || fail=1 +grep 'ENOENT' err || fail=1 + +# Demonstrate (the usual!) recursion ... +mkdir d1 d1/d2 d1/d2/d3 && touch d1/d2/d3/file || framework_failure_ +printf '%s\n' d1 d1/d2 d1/d2/d3 d1/d2/d3/file > exp || framework_failure_ +printf 'd1' \ + | find -files0-from - > out 2> err || fail=1 +compare exp out || fail=1 +compare /dev/null err || fail=1 +# ... and how to avoid recursion with -maxdepth 0. +find d1 -print0 \ + | find -files0-from - -maxdepth 0 > out 2> err || fail=1 +compare exp out || fail=1 +compare /dev/null err || fail=1 + +# Large input with files. +# Create file 'exp' with many times its own name as content, NUL-separated; +# and let find(1) check that it worked (4x in bytes). +yes exp | head -n 100000 | tr '\n' '\0' > exp \ + && find exp -size 400000c | grep . || framework_failure_ +# Run the test. +find -files0-from exp > out 2> err || fail=1 +# ... and verify. +test $( wc -l < out ) = 100000 || fail=1 +find out -size 400000c | grep . || fail=1 + +Exit $fail |