find: fix -used predicate

* find/pred.c (pred_used): Reverse the check for the delta between
the atime and ctime of the file to accomodate to how pred_timewindow
is working.
Also return false if atime < ctime.
Bug introduced in FINDUTILS_4_3_3-1 in commit a4718831e17.
* tests/find/used.sh: Add test.
* tests/local.mk (all_tests): Reference the test.
* NEWS (Bug Fixes): Mention the fix.

Reported by Martin Schulte in
<https://lists.gnu.org/r/bug-findutils/2019-11/msg00010.html>
This commit is contained in:
Bernhard Voelker 2020-04-22 19:35:13 +02:00
parent abec46d204
commit 7642d172e1
4 changed files with 106 additions and 3 deletions

4
NEWS
View File

@ -12,6 +12,10 @@ of each constructed command line to be executed. [#57291]
find no longer crashes when an XFS filesystem is heavily changed during the run.
Discussed at: <https://lists.gnu.org/r/bug-gnulib/2020-04/msg00068.html>
find -used works again. This predicate was not working properly since adding
the support for sub-second timestamp resolution for various predicates in
FINDUTILS_4_3_3-1 back in 2007.
#54730: Add additional valuable example of find -quit
#48135: Fix testsuite error on Hurd and BSD related to ln

View File

@ -1163,11 +1163,15 @@ pred_used (const char *pathname, struct stat *stat_buf, struct predicate *pred_p
(void) pathname;
/* TODO: this needs to be retested carefully (manually, if necessary) */
at = get_stat_atime (stat_buf);
ct = get_stat_ctime (stat_buf);
delta.tv_sec = at.tv_sec - ct.tv_sec;
delta.tv_nsec = at.tv_nsec - ct.tv_nsec;
/* Always evaluate to false if atime < ctime. */
if (compare_ts (at, ct) < 0)
return false;
delta.tv_sec = ct.tv_sec - at.tv_sec;
delta.tv_nsec = ct.tv_nsec - at.tv_nsec;
if (delta.tv_nsec < 0)
{
delta.tv_nsec += 1000000000;

94
tests/find/used.sh Executable file
View File

@ -0,0 +1,94 @@
#!/bin/sh
# Verify that find -used works.
# Copyright (C) 2020 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
# Create sample files with the access date D=1,3,5,7 days in the future.
for d in 1 3 5 7; do
touch -a -d "$(date -d "$d day" '+%Y-%m-%d %H:%M:%S')" t$d \
|| skip_ "creating files with future timestamp failed"
# Check with stat(1) the access (%X) vs. the status change time (%z).
exp="$( expr 86400 '*' $d )" \
&& x="$( stat -c "%X" t$d )" \
&& z="$( stat -c "%Z" t$d )" \
&& tdiff="$( expr "$x" - "$z" )" \
&& test "$tdiff" -ge "$exp" \
|| skip_ "cannot verify timestamps of sample files"
done
# Create another sample file with timestamp now.
touch t0 \
|| skip_ "creating sample file failed"
stat -c "Name: %n Access: %x Change: %z" t? || : # ignore error.
# Verify the output for "find -used $d". Use even number of days to avoid
# possibly strange effects due to atime/ctime precision etc.
for d in -8 -6 -4 -2 -0 0 2 4 6 8 +0 +2 +4 +6 +8; do
echo "== testing: find -used $d"
find . -type f -name 't*' -used $d > out2 \
|| fail=1
LC_ALL=C sort out2 || framework_failure_
done > out
cat <<\EOF > exp || framework_failure_
== testing: find -used -8
./t0
./t1
./t3
./t5
./t7
== testing: find -used -6
./t0
./t1
./t3
./t5
== testing: find -used -4
./t0
./t1
./t3
== testing: find -used -2
./t0
./t1
== testing: find -used -0
== testing: find -used 0
== testing: find -used 2
== testing: find -used 4
== testing: find -used 6
== testing: find -used 8
== testing: find -used +0
./t1
./t3
./t5
./t7
== testing: find -used +2
./t3
./t5
./t7
== testing: find -used +4
./t5
./t7
== testing: find -used +6
./t7
== testing: find -used +8
EOF
compare exp out || { fail=1; cat out; }
Exit $fail

View File

@ -116,6 +116,7 @@ all_tests = \
tests/find/exec-plus-last-file.sh \
tests/find/refuse-noop.sh \
tests/find/debug-missing-arg.sh \
tests/find/used.sh \
tests/xargs/verbose-quote.sh \
$(all_root_tests)