mirror of
https://https.git.savannah.gnu.org/git/findutils.git
synced 2026-01-26 07:37:52 +00:00
Compare commits
129 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6b49775f9d | ||
|
|
6cf0fe34d7 | ||
|
|
c56b96a54f | ||
|
|
99b3365ec3 | ||
|
|
ebea22e88b | ||
|
|
3c2af8a185 | ||
|
|
09a4602970 | ||
|
|
b698bc19a1 | ||
|
|
a86cd78912 | ||
|
|
8d74646de9 | ||
|
|
214285e6f2 | ||
|
|
341ba019f4 | ||
|
|
289eaa25dc | ||
|
|
ab387c1cdc | ||
|
|
2b9f253b15 | ||
|
|
c5dfe4c378 | ||
|
|
6d695cc480 | ||
|
|
34142ca063 | ||
|
|
4055cf7bbc | ||
|
|
5c31ac2aeb | ||
|
|
4e562ab11f | ||
|
|
cd4977172c | ||
|
|
5a000f9a50 | ||
|
|
a64197a3d8 | ||
|
|
236a3c8647 | ||
|
|
755d9fbf38 | ||
|
|
30f820abf7 | ||
|
|
897264c8e8 | ||
|
|
c4f03874ac | ||
|
|
bbce846161 | ||
|
|
2923a0d78f | ||
|
|
7cb135d5fb | ||
|
|
f0e2bbe45b | ||
|
|
e0d0dab353 | ||
|
|
a81c9c431d | ||
|
|
ba94c5423e | ||
|
|
700e8cae79 | ||
|
|
1520e3d307 | ||
|
|
10235e591a | ||
|
|
c2b67c7c92 | ||
|
|
d9cef9e7da | ||
|
|
3d398b07cd | ||
|
|
7e8712f0ca | ||
|
|
fe5b98b247 | ||
|
|
ad7e34650a | ||
|
|
d1edc59b19 | ||
|
|
627072f022 | ||
|
|
2749632838 | ||
|
|
04738593b4 | ||
|
|
0d8de87299 | ||
|
|
6da3a73f73 | ||
|
|
cd8568758a | ||
|
|
733bb9a054 | ||
|
|
e69e78fb1d | ||
|
|
580be65e25 | ||
|
|
99cfb6cf42 | ||
|
|
c9a2aaa354 | ||
|
|
8821923b49 | ||
|
|
7156420fab | ||
|
|
bccc4f8a28 | ||
|
|
c78d103e81 | ||
|
|
aa292af4c1 | ||
|
|
9e505ec52f | ||
|
|
93ce19f0d5 | ||
|
|
499e792fc0 | ||
|
|
deb3f7066d | ||
|
|
c41a617953 | ||
|
|
56a376a26d | ||
|
|
c18bba5c59 | ||
|
|
0cac25f6e7 | ||
|
|
cabfc3b184 | ||
|
|
74d25ac58d | ||
|
|
1c39dc6055 | ||
|
|
fbbda507c6 | ||
|
|
facc27e180 | ||
|
|
c9c2c51175 | ||
|
|
c7f5ff1ed8 | ||
|
|
acd4564eda | ||
|
|
1ef8d7c2cf | ||
|
|
bad1de52aa | ||
|
|
97b8920482 | ||
|
|
45530ee875 | ||
|
|
ee500667d4 | ||
|
|
8e1331d8a7 | ||
|
|
2be6812e01 | ||
|
|
f3a3833320 | ||
|
|
dc3365628e | ||
|
|
faa1301368 | ||
|
|
e5d6eb919b | ||
|
|
d44172075a | ||
|
|
0c20228608 | ||
|
|
85c67e9c3c | ||
|
|
a465fc58bc | ||
|
|
b52c6688ff | ||
|
|
7752c3da26 | ||
|
|
00e698e1b2 | ||
|
|
f1f6471ae8 | ||
|
|
a78812c62e | ||
|
|
1da19bdba7 | ||
|
|
00e82f2c15 | ||
|
|
324b5dddc2 | ||
|
|
aff4e48c11 | ||
|
|
eac8aecaad | ||
|
|
e65a91d2fb | ||
|
|
5db475b306 | ||
|
|
ea9288c6be | ||
|
|
baab958700 | ||
|
|
744da6ddcc | ||
|
|
f4ec39eee0 | ||
|
|
d0187016e1 | ||
|
|
57fb016b73 | ||
|
|
2ef0b4ce38 | ||
|
|
128c5b18c9 | ||
|
|
727d261bb8 | ||
|
|
1dcdf3de8e | ||
|
|
457acfa06b | ||
|
|
e38e2f8a36 | ||
|
|
523043b313 | ||
|
|
f65a2a960f | ||
|
|
4a719e65d2 | ||
|
|
889d001ab7 | ||
|
|
07bd7fa675 | ||
|
|
85fc8966e5 | ||
|
|
b94986a897 | ||
|
|
76ddbb913e | ||
|
|
bb13ef8f93 | ||
|
|
1c8f85de97 | ||
|
|
e178314ae3 | ||
|
|
c8fd333368 |
12
Makefile.am
12
Makefile.am
@ -1,6 +1,6 @@
|
||||
# Make findutils.
|
||||
|
||||
# Copyright (C) 1996-2024 Free Software Foundation, Inc.
|
||||
# Copyright (C) 1996-2026 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
|
||||
@ -111,14 +111,8 @@ gnulib-sync update-gnulib-to-latest:
|
||||
&& git submodule foreach git pull origin master \
|
||||
&& cp -v gnulib/doc/COPYINGv3 COPYING \
|
||||
&& cp -v gnulib/doc/fdl.texi doc/fdl.texi \
|
||||
&& cp -v gnulib/top/autogen.sh autogen.sh \
|
||||
&& cp -v gnulib/top/autopull.sh autopull.sh \
|
||||
&& cp -v gnulib/top/bootstrap bootstrap \
|
||||
&& cp -v gnulib/top/bootstrap-funclib.sh bootstrap-funclib.sh \
|
||||
&& cp -v gnulib/tests/init.sh tests/init.sh \
|
||||
&& git status --short -- gnulib COPYING doc/fdl.texi autogen.sh \
|
||||
autopull.sh bootstrap bootstrap-funclib.sh tests/init.sh \
|
||||
tests/init.sh \
|
||||
&& cp -v gnulib/build-aux/bootstrap bootstrap \
|
||||
&& git status --short -- gnulib COPYING doc/fdl.texi bootstrap \
|
||||
)
|
||||
|
||||
# Clean coverage files generated by running binaries built with gcc
|
||||
|
||||
86
NEWS
86
NEWS
@ -1,5 +1,59 @@
|
||||
GNU findutils NEWS - User visible changes. -*- outline -*- (allout)
|
||||
|
||||
* Noteworthy changes in release ?.? (????-??-??) [?]
|
||||
|
||||
** Bug Fixes
|
||||
|
||||
find no longer crashes when diagnosing a directory cycle (without a symlink
|
||||
being involved pointing to a parent directory).
|
||||
[Bug present since the FTS implementation.]
|
||||
|
||||
'find -ignore_readdir_race' now better handles races between FTS reading a
|
||||
directory and visiting its entries when the file or directory was meanwhile
|
||||
removed. [#45930]
|
||||
|
||||
To fix a POSIX compatibility bug, -exec foo Z{} + is no longer a
|
||||
complete predicate, because '+' is only a terminator when it follows
|
||||
an argument which is exactly '{}'. The findutils documentation
|
||||
already states this, and now find's behaviour matches the
|
||||
documentation.
|
||||
|
||||
** Changes in find
|
||||
|
||||
As announced since the release of 4.7.0 (2019) and mandated by POSIX 2024,
|
||||
the behaviour of the -mount option changed: while it was a mere alias for
|
||||
the -xdev option to prevent descending into directories of another device,
|
||||
the -mount option now makes find(1) ignore files on another device, i.e.,
|
||||
'find -mount' will skip the entry of active mount points already.
|
||||
Example, assuming the PROC filesystem is mounted on '/proc':
|
||||
$ find / -mount -path /proc -print
|
||||
$ find / -xdev -path /proc -print
|
||||
/proc
|
||||
[#54745]
|
||||
|
||||
The actions -execdir and -okdir now refuse the '{}' replacement in the zeroth
|
||||
argument of the command to be run. While POSIX allows this for -exec, this is
|
||||
deemed insecure as an attacker could influence which files could be found.
|
||||
|
||||
find now issues a warning when the punctuation operators '(', ')', '!' and ','
|
||||
are passed with a leading dash, e.g. '-!'. Future releases will not accept
|
||||
that any more. Accepting that was rather a bug "since the beginning".
|
||||
|
||||
** Documentation Changes
|
||||
|
||||
The forthcoming Issue 8 of the POSIX standard will standardise "find
|
||||
-print0" and "xargs -0". Our documentation now points this out.
|
||||
|
||||
The code example for "Finding the Shallowest Instance" in the Texinfo manual
|
||||
and the corresponding one in the EXAMPLES section in the find.1 man page have
|
||||
been fixed. [#62259]
|
||||
|
||||
Translators contributed numerous fixes for issues in the find.1 man page.
|
||||
|
||||
The list of actions that suppress the default -print action has been
|
||||
supplemented with the missing '-print0' and '-fprint0' actions.
|
||||
|
||||
|
||||
* Noteworthy changes in release 4.10.0 (2024-06-01) [stable]
|
||||
|
||||
** Bug Fixes
|
||||
@ -472,7 +526,7 @@ posix-egrep. This is the result of a change to gnulib to bring it
|
||||
into line with GNU grep (see https://debbugs.gnu.org/20974#22).
|
||||
|
||||
** Translations
|
||||
Updated translations: Estonian, Swedish, Polish, Vietnamese, Ukranian,
|
||||
Updated translations: Estonian, Swedish, Polish, Vietnamese, Ukrainian,
|
||||
Norwegian Bokmaal, Czech, Russian, French, Hungarian.
|
||||
|
||||
** Bug Fixes:
|
||||
@ -501,7 +555,7 @@ Norwegian Bokmaal, Czech, Russian, French, Hungarian.
|
||||
#45062: Enabling CACHE_IDS causes segfaults (this bug affects many
|
||||
historic releases, probably since release 3.0 in 1991). You
|
||||
would not have been affected by this problem unless you used
|
||||
the option --enable-id-cache when invoking confgure.
|
||||
the option --enable-id-cache when invoking configure.
|
||||
|
||||
#42903: checklists.py now supports Python 3.
|
||||
|
||||
@ -549,7 +603,7 @@ Some minor documentation improvements are listed in "Bug Fixes" below.
|
||||
|
||||
** Translations
|
||||
|
||||
Updated translations: Estonian, Polish, Ukranian.
|
||||
Updated translations: Estonian, Polish, Ukrainian.
|
||||
|
||||
|
||||
* Major changes in release 4.5.12, 2013-09-22
|
||||
@ -648,7 +702,7 @@ For example use "xargs /bin/echo < foo" rather than "xargs < foo".
|
||||
|
||||
A new option is provided, --process-slot-var. If you set this, xargs
|
||||
will set the indicated environment variable in each child. The values
|
||||
are re-used, but no executing child process will have the same value
|
||||
are reused, but no executing child process will have the same value
|
||||
as another executing child process. This wishlist item was Savannah
|
||||
bug #29512.
|
||||
|
||||
@ -678,7 +732,7 @@ expression types selected by the -regextype option have slightly
|
||||
changed, to bring them into line with the behaviour of the GNU C
|
||||
library. For "awk", character classes (such as [[:digit:]]) are now
|
||||
supported. For "gnu-awk" and "posix-awk", intervals are supported and
|
||||
invalid interval specifcations are treated as literals (for example
|
||||
invalid interval specifications are treated as literals (for example
|
||||
'a{1' is treated as 'a\{1').
|
||||
|
||||
|
||||
@ -761,7 +815,7 @@ Updated Vietnamese, Czech, Dutch, Polish, Russian translations.
|
||||
|
||||
** Performance changes
|
||||
|
||||
If you use the -fstype FOO predicate and specify a filsystem type FOO
|
||||
If you use the -fstype FOO predicate and specify a filesystem type FOO
|
||||
which is not known (e.g. present in /etc/mtab) at the time find
|
||||
starts, that predicate is now equivalent to -false. This substitution
|
||||
currently occurs at optimisation level 2 and above.
|
||||
@ -837,7 +891,7 @@ in the text).
|
||||
|
||||
#22708: Exit status 126 and 127 from the utility invoked from xargs
|
||||
now makes xargs return 123, meaning that exit status values 126 and
|
||||
127 now unambigously mean that the utility could not be run or could
|
||||
127 now unambiguously mean that the utility could not be run or could
|
||||
not be found, respectively.
|
||||
|
||||
** Documentation Changes
|
||||
@ -877,13 +931,13 @@ unknown user or is missing.
|
||||
#25154: Allow compilation with C compilers that don't allow
|
||||
declarations to follow statements.
|
||||
|
||||
#24342: -inum predicate shoud use dirent.d_ino instead of stat.st_ino
|
||||
#24342: -inum predicate should use dirent.d_ino instead of stat.st_ino
|
||||
(this is a performance bug).
|
||||
|
||||
** Translations
|
||||
|
||||
Updated translations for Bulgarian, German, Irish, Hungarian,
|
||||
Lithuanian, Dutch, Polish, Slovenian, Swedish, Turkish, Ukranian,
|
||||
Lithuanian, Dutch, Polish, Slovenian, Swedish, Turkish, Ukrainian,
|
||||
Vietnamese.
|
||||
|
||||
** Documentation Changes
|
||||
@ -901,7 +955,7 @@ The file README-CVS has been renamed to README-hacking and improved.
|
||||
Changes to gnulib's fts code should provide performance improvements
|
||||
in find when processing very large directories (for example
|
||||
directories containing significantly more than 10000 filenames).
|
||||
Performance imporvements may only exist for some find command lines
|
||||
Performance improvements may only exist for some find command lines
|
||||
(performance testing was done for the fts implementation itself but
|
||||
we haven't done the analogous performance tests in find).
|
||||
|
||||
@ -1364,7 +1418,7 @@ servers.
|
||||
|
||||
#11668: FreeBSD extensions for time specification are now
|
||||
implemented. In fact, these were included in findutils-4.3.3. The
|
||||
change was listed as a functional change (whcih it is) and this bug
|
||||
change was listed as a functional change (which it is) and this bug
|
||||
report was not mentioned.
|
||||
|
||||
** Documentation Fixes
|
||||
@ -1589,7 +1643,7 @@ problem was worse for -exec.
|
||||
Savannah bug #16579: Updatedb now works if it is running as a user
|
||||
whose login shell is not actually a shell.
|
||||
|
||||
There have also been a number of documentation improvements (includng
|
||||
There have also been a number of documentation improvements (including
|
||||
Savannah bug #16269).
|
||||
|
||||
** Functional changes
|
||||
@ -1909,7 +1963,7 @@ Some typos in the manual pages have been fixed. Various parts of the
|
||||
manual now point out that it is good practice to quote the argument of
|
||||
"-name". The manpage now has a "NON-BUGS" section which explains some
|
||||
symptoms that look like bugs but aren't. The explanations of the "%k"
|
||||
and "%b" directives to "find -printf" have been imrpoved.
|
||||
and "%b" directives to "find -printf" have been improved.
|
||||
|
||||
|
||||
* Major changes in release 4.2.21, 2005-06-07
|
||||
@ -2125,7 +2179,7 @@ New Vietnamese message translation.
|
||||
have it.
|
||||
*** Bugfix to the findutils 4.2.6 automount handling (which hadn't been enabled
|
||||
on Solaris).
|
||||
*** Reenabled internationalisation support (which had been accidentally
|
||||
*** Re-enabled internationalisation support (which had been accidentally
|
||||
disabled in findutils-4.2.5).
|
||||
|
||||
* Major changes in release 4.2.6, 2004-11-21
|
||||
@ -2163,7 +2217,7 @@ New Vietnamese message translation.
|
||||
*** If you specify a 'find' option after non-option, a warning message
|
||||
is now issued. Options should be specified immediately after the
|
||||
list of paths to search. These warnings are enabled if you
|
||||
specify the -warn option, or if stdin is a tty. They are diabled
|
||||
specify the -warn option, or if stdin is a tty. They are disabled
|
||||
by the use of the -nowarn option.
|
||||
*** Like find, the locate program now supports an option --null (short form -0)
|
||||
which changes the result separator from newline to NULL.
|
||||
@ -2396,7 +2450,7 @@ LocalWords: strncasecmp strcasecmp LIBOBJS FUNC prunefs allout libexec
|
||||
LocalWords: testsuite Texinfo chdir inode fstype afs fls ls EOF lname
|
||||
LocalWords: regex ilname iname ipath iregex printf fprintf
|
||||
|
||||
Copyright (C) 1996-2024 Free Software Foundation, Inc.
|
||||
Copyright (C) 1996-2026 Free Software Foundation, Inc.
|
||||
|
||||
Permission is granted to copy, distribute and/or modify this document
|
||||
under the terms of the GNU Free Documentation License, Version 1.3 or
|
||||
|
||||
2
README
2
README
@ -100,7 +100,7 @@ We are looking forward to hacking with you!
|
||||
|
||||
========================================================================
|
||||
|
||||
Copyright (C) 1996-2024 Free Software Foundation, Inc.
|
||||
Copyright (C) 1996-2026 Free Software Foundation, Inc.
|
||||
|
||||
Permission is granted to copy, distribute and/or modify this document
|
||||
under the terms of the GNU Free Documentation License, Version 1.3 or
|
||||
|
||||
@ -14,6 +14,7 @@ Prerequisites
|
||||
on a POSIX system should work.
|
||||
* GNU Autoconf
|
||||
* GNU Automake
|
||||
* GNU Bison
|
||||
* GNU m4
|
||||
* GNU gettext
|
||||
* GNU Dejagnu
|
||||
@ -105,7 +106,7 @@ proc_max.
|
||||
MAX_PROC_MAX.
|
||||
--- example ends ---
|
||||
|
||||
There are several things to notice about this checkin message. Most
|
||||
There are several things to notice about this check-in message. Most
|
||||
importantly, it begins with a single line summary of the whole change.
|
||||
This needs to be short. It would be used as the subject line of
|
||||
patches mailed by "git send-email". Some people begin that line with
|
||||
@ -248,7 +249,7 @@ In case you're wondering why we bother with all of this, read this:
|
||||
|
||||
|
||||
========================================================================
|
||||
Copyright (C) 2009-2024 Free Software Foundation, Inc.
|
||||
Copyright (C) 2009-2026 Free Software Foundation, Inc.
|
||||
|
||||
Permission is granted to copy, distribute and/or modify this document
|
||||
under the terms of the GNU Free Documentation License, Version 1.3 or
|
||||
|
||||
2
TODO
2
TODO
@ -86,7 +86,7 @@ LocalWords: findutils Debian cron
|
||||
|
||||
-----
|
||||
|
||||
Copyright (C) 1996-2024 Free Software Foundation, Inc.
|
||||
Copyright (C) 1996-2026 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
|
||||
|
||||
39
autogen.sh
39
autogen.sh
@ -1,39 +0,0 @@
|
||||
#!/bin/sh
|
||||
# Convenience script for regenerating all autogeneratable files that are
|
||||
# omitted from the version control repository. In particular, this script
|
||||
# also regenerates all aclocal.m4, config.h.in, Makefile.in, configure files
|
||||
# with new versions of autoconf or automake.
|
||||
|
||||
# Copyright (C) 2003-2024 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/>.
|
||||
|
||||
# Originally written by Paul Eggert. The canonical version of this
|
||||
# script is maintained as top/autogen.sh in gnulib. However, to be
|
||||
# useful to your package, you should place a copy of it under version
|
||||
# control in the top-level directory of your package. The intent is
|
||||
# that all customization can be done with a bootstrap.conf file also
|
||||
# maintained in your version control; gnulib comes with a template
|
||||
# build-aux/bootstrap.conf to get you started.
|
||||
#
|
||||
# Alternatively, you can use an autogen.sh script that is specific
|
||||
# to your package.
|
||||
|
||||
me="$0"
|
||||
medir=`dirname "$me"`
|
||||
|
||||
# Read the function library and the configuration.
|
||||
. "$medir"/bootstrap-funclib.sh
|
||||
|
||||
autogen "$@"
|
||||
37
autopull.sh
37
autopull.sh
@ -1,37 +0,0 @@
|
||||
#!/bin/sh
|
||||
# Convenience script for fetching auxiliary files that are omitted from
|
||||
# the version control repository of this package.
|
||||
|
||||
# Copyright (C) 2003-2024 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/>.
|
||||
|
||||
# Originally written by Paul Eggert. The canonical version of this
|
||||
# script is maintained as top/autopull.sh in gnulib. However, to be
|
||||
# useful to your package, you should place a copy of it under version
|
||||
# control in the top-level directory of your package. The intent is
|
||||
# that all customization can be done with a bootstrap.conf file also
|
||||
# maintained in your version control; gnulib comes with a template
|
||||
# build-aux/bootstrap.conf to get you started.
|
||||
#
|
||||
# Alternatively, you can use an autopull.sh script that is specific
|
||||
# to your package.
|
||||
|
||||
me="$0"
|
||||
medir=`dirname "$me"`
|
||||
|
||||
# Read the function library and the configuration.
|
||||
. "$medir"/bootstrap-funclib.sh
|
||||
|
||||
autopull "$@"
|
||||
1321
bootstrap-funclib.sh
1321
bootstrap-funclib.sh
File diff suppressed because it is too large
Load Diff
@ -1,6 +1,6 @@
|
||||
# Bootstrap configuration.
|
||||
|
||||
# Copyright (C) 2006-2024 Free Software Foundation, Inc.
|
||||
# Copyright (C) 2006-2026 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
|
||||
@ -55,7 +55,7 @@ gendocs
|
||||
# consider using gendocs
|
||||
# consider using sig2str in xargs
|
||||
# consider using signal (why not: maybe we don't need those features)
|
||||
# consider using the dev-ino moduile to support -samefile.
|
||||
# consider using the dev-ino module to support -samefile.
|
||||
|
||||
# consider removing stpcpy
|
||||
# We have rpmatch, either use it for -ok and xargs or remove the dependency
|
||||
@ -76,20 +76,22 @@ gnulib_modules="
|
||||
argmatch
|
||||
argv-iter
|
||||
assert
|
||||
byteswap
|
||||
basename-lgpl
|
||||
bool
|
||||
c-strcasestr
|
||||
c-strstr
|
||||
canonicalize
|
||||
cloexec
|
||||
closein
|
||||
closeout
|
||||
ctype
|
||||
ctype-h
|
||||
d-ino
|
||||
d-type
|
||||
dirent-safer
|
||||
dirname
|
||||
dup2
|
||||
errno
|
||||
endian
|
||||
errno-h
|
||||
error
|
||||
faccessat
|
||||
fchdir
|
||||
@ -107,7 +109,7 @@ gnulib_modules="
|
||||
getline
|
||||
getopt-gnu
|
||||
gettext-h
|
||||
gettimeofday
|
||||
gettime
|
||||
git-version-gen
|
||||
gnupload
|
||||
gpl-3.0
|
||||
@ -116,13 +118,13 @@ gnulib_modules="
|
||||
idcache
|
||||
inline
|
||||
intprops
|
||||
inttypes
|
||||
inttypes-h
|
||||
isblank
|
||||
locale
|
||||
locale-h
|
||||
lstat
|
||||
malloc-gnu
|
||||
manywarnings
|
||||
math
|
||||
math-h
|
||||
mbrtowc
|
||||
mbscasestr
|
||||
mbswidth
|
||||
@ -140,7 +142,7 @@ gnulib_modules="
|
||||
progname
|
||||
quotearg
|
||||
readlink
|
||||
realloc-gnu
|
||||
realloc-posix
|
||||
regex
|
||||
rpmatch
|
||||
safe-read
|
||||
@ -153,22 +155,22 @@ gnulib_modules="
|
||||
stat-macros
|
||||
stat-size
|
||||
stat-time
|
||||
stdarg
|
||||
stdbool
|
||||
stddef
|
||||
stdio
|
||||
stdint
|
||||
stdlib
|
||||
stdarg-h
|
||||
stddef-h
|
||||
stdio-h
|
||||
stdint-h
|
||||
stdlib-h
|
||||
stpcpy
|
||||
strcasestr
|
||||
strdup-posix
|
||||
string
|
||||
string-h
|
||||
strndup
|
||||
strtoull
|
||||
strtoumax
|
||||
sys_stat
|
||||
sys_time
|
||||
sys_wait
|
||||
sys_stat-h
|
||||
sys_time-h
|
||||
sys_types-h
|
||||
sys_wait-h
|
||||
timespec
|
||||
uname
|
||||
unistd-safer
|
||||
@ -177,7 +179,7 @@ gnulib_modules="
|
||||
version-etc
|
||||
version-etc-fsf
|
||||
warnings
|
||||
wchar
|
||||
wchar-h
|
||||
wcwidth
|
||||
xalloc
|
||||
xalloc-die
|
||||
@ -203,7 +205,7 @@ gnulib_name=libgnulib
|
||||
# Create 'gl/Makefile.am' which is mentioned in 'configure.ac'.
|
||||
hack_gnulib_tool_makefile() {
|
||||
cat > gl/Makefile.am <<EOF
|
||||
# Copyright (C) 2006-2024 Free Software Foundation, Inc.
|
||||
# Copyright (C) 2006-2026 Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is free software, distributed under the terms of the GNU
|
||||
# General Public License. As a special exception to the GNU General
|
||||
@ -221,7 +223,10 @@ EOF
|
||||
# after 'gnulib-tool' is done, create the 'gl/Makefile.am' to be backward
|
||||
# compatible with 'import-gnulib.sh'.
|
||||
bootstrap_post_import_hook() {
|
||||
hack_gnulib_tool_makefile
|
||||
hack_gnulib_tool_makefile
|
||||
|
||||
# Copy tests/init.sh from Gnulib.
|
||||
$gnulib_tool --copy-file tests/init.sh
|
||||
}
|
||||
|
||||
# For compatibility with 'import-gnulib.sh', add gnulib's test directory.
|
||||
@ -273,6 +278,7 @@ buildreq="\
|
||||
autoconf 2.64
|
||||
automake 1.11.2
|
||||
autopoint 0.19.2
|
||||
bison -
|
||||
gettext 0.19.2
|
||||
git 1.5.5
|
||||
m4 -
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
# Copyright (C) 2007-2024 Free Software Foundation, Inc.
|
||||
# Copyright (C) 2007-2026 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
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
#! /bin/sh
|
||||
# check-testfiles.sh -- Check we distributed all the test files we need
|
||||
# Copyright (C) 2007-2024 Free Software Foundation, Inc.
|
||||
# Copyright (C) 2007-2026 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
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
#! /bin/sh
|
||||
# Generate the ChangeLog for findutils.
|
||||
|
||||
# Copyright (C) 2015-2024 Free Software Foundation, Inc.
|
||||
# Copyright (C) 2015-2026 Free Software Foundation, Inc.
|
||||
# Written by James Youngman.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
#! /bin/sh
|
||||
# Copyright (C) 2007-2024 Free Software Foundation, Inc.
|
||||
# Copyright (C) 2007-2026 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
|
||||
@ -14,20 +14,60 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
rv=0
|
||||
case "${GROFF}" in
|
||||
:)
|
||||
echo "groff is not installed, so we cannot check manual pages. Continuing without checking them." >&2
|
||||
exit 0
|
||||
;;
|
||||
"")
|
||||
echo "The GROFF environment is not set; this is normally set when invoking this command from the Makefile; assuming GNU groff is at 'groff'." >&2
|
||||
GROFF=groff
|
||||
;;
|
||||
*)
|
||||
;;
|
||||
esac
|
||||
|
||||
srcdir="$1" ; shift
|
||||
|
||||
for manpage
|
||||
do
|
||||
what="lint check on manpage $manpage"
|
||||
echo -n "$what: "
|
||||
messages="$( groff -t -man ${srcdir}/${manpage} 2>&1 >/dev/null )"
|
||||
if test -z "$messages" ; then
|
||||
echo "passed"
|
||||
else
|
||||
echo "FAILED:" >&2
|
||||
echo "$messages" >&2
|
||||
rv=1
|
||||
fi
|
||||
done
|
||||
exit $rv
|
||||
fixed_width_context_message_without_newline() {
|
||||
printf '%-45s (%15s): ' "$1" "$2"
|
||||
}
|
||||
|
||||
|
||||
check_manpages_format_without_error_messages() {
|
||||
for manpage
|
||||
do
|
||||
fixed_width_context_message_without_newline \
|
||||
'check_manpages_format_without_error_messages' "${manpage}"
|
||||
messages="$( ${GROFF} -t -man ${srcdir}/${manpage} 2>&1 >/dev/null )"
|
||||
if test -z "$messages"
|
||||
then
|
||||
printf 'OK\n'
|
||||
else
|
||||
printf 'FAILED\n%s\n' "$messages" >&2
|
||||
return 1
|
||||
fi
|
||||
done
|
||||
return 0
|
||||
}
|
||||
|
||||
check_manpages_with_groff_checkstyle_2() {
|
||||
for manpage
|
||||
do
|
||||
fixed_width_context_message_without_newline \
|
||||
'check_manpages_with_groff_checkstyle_2' "${manpage}"
|
||||
messages="$( ${GROFF} -t -z -ww -rCHECKSTYLE=2 -man ${srcdir}/${manpage} 2>&1 )"
|
||||
if test -z "$messages"
|
||||
then
|
||||
printf 'OK\n'
|
||||
else
|
||||
printf 'FAILED\n%s\n' "$messages" >&2
|
||||
return 1
|
||||
fi
|
||||
done
|
||||
return 0
|
||||
}
|
||||
|
||||
rv=0
|
||||
check_manpages_format_without_error_messages "$@" &&
|
||||
check_manpages_with_groff_checkstyle_2 "$@"
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
#! /usr/bin/env python
|
||||
|
||||
# src-sniff.py: checks source code for patterns that look like common errors.
|
||||
# Copyright (C) 2007-2024 Free Software Foundation, Inc.
|
||||
# Copyright (C) 2007-2026 Free Software Foundation, Inc.
|
||||
#
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
|
||||
108
build-aux/tabs-to-spaces.sh
Normal file
108
build-aux/tabs-to-spaces.sh
Normal file
@ -0,0 +1,108 @@
|
||||
#! /bin/sh
|
||||
|
||||
# You might use this tool like this:
|
||||
#
|
||||
# sh build-aux/tabs-to-spaces.sh check $( find find lib locate tests xargs -regextype posix-extended -regex '.*[.]([ch]|cc)$' )
|
||||
set -u
|
||||
|
||||
|
||||
error() {
|
||||
echo "$@" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
cleanup() {
|
||||
if ! rm -f "$@"
|
||||
then
|
||||
error "failed to delete temporary file(s) $@"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
usage_error() {
|
||||
error "Please specify a sub-command (either 'check' or 'fix')."
|
||||
}
|
||||
|
||||
make_expanded_file() {
|
||||
if output="$(mktemp)"
|
||||
then
|
||||
expand -- "$1" > "${output}" && echo "${output}"
|
||||
else
|
||||
error 'failed to create temporary file'
|
||||
fi
|
||||
}
|
||||
|
||||
check() {
|
||||
result=0
|
||||
for input
|
||||
do
|
||||
if expanded="$(make_expanded_file ${input})"
|
||||
then
|
||||
cmp -s -- "${input}" "${expanded}"
|
||||
rv="$?"
|
||||
if ! cleanup "${expanded}"
|
||||
then
|
||||
return 1
|
||||
fi
|
||||
case "$rv" in
|
||||
0) ;;
|
||||
1) echo "${input} is incorrectly formatted (it contains tabs)"
|
||||
result=1
|
||||
;;
|
||||
*) error "failed to compare ${input} with ${expanded}"
|
||||
;;
|
||||
esac
|
||||
else
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
return $result
|
||||
}
|
||||
|
||||
fix() {
|
||||
for input
|
||||
do
|
||||
if expanded="$(make_expanded_file ${input})"
|
||||
then
|
||||
cmp -s -- "${input}" "${expanded}"
|
||||
rv="$?"
|
||||
case "$rv" in
|
||||
0) if ! cleanup "${expanded}"
|
||||
then
|
||||
return 1
|
||||
fi
|
||||
# Otherwise, continue with next file.
|
||||
;;
|
||||
1) if ! mv "${expanded}" "${input}"
|
||||
then
|
||||
cleanup "${expanded}"
|
||||
error "failed to replace ${input} with tab-expanded version ${expanded}"
|
||||
else
|
||||
unset expanded
|
||||
fi
|
||||
# Otherwise, continue with next file.
|
||||
;;
|
||||
*) error "failed to compare ${input} with ${expanded}"
|
||||
;;
|
||||
esac
|
||||
else
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
main() {
|
||||
if [ $# -eq 0 ]
|
||||
then
|
||||
usage_error
|
||||
fi
|
||||
case "$1" in
|
||||
check) shift; check "$@" ;;
|
||||
fix) shift; fix "$@" ;;
|
||||
*) usage_error ;;
|
||||
|
||||
esac
|
||||
}
|
||||
|
||||
|
||||
main "$@"
|
||||
@ -1,5 +1,5 @@
|
||||
#! /bin/sh
|
||||
# Copyright (C) 2019-2024 Free Software Foundation, Inc.
|
||||
# Copyright (C) 2019-2026 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
|
||||
@ -30,7 +30,7 @@ usage: $0 location-of-${PACKAGE}-build-directory
|
||||
EOF
|
||||
}
|
||||
|
||||
checkfiles="CVS dvi ${TEXIBASE}.html html_node html_mono info ps texi text ${TEXIBASE}.pdf"
|
||||
checkfiles="CVS ${TEXIBASE}.html html_node html_mono info ps texi text ${TEXIBASE}.pdf"
|
||||
|
||||
if [ $# -ne 1 ]; then
|
||||
usage >&2
|
||||
@ -99,9 +99,6 @@ then
|
||||
cp ${BUILDDIR}/doc/manual/${TEXIBASE}.texi.tar.gz texi/${TEXIBASE}.texi.tar.gz
|
||||
cp ${BUILDDIR}/doc/manual/${TEXIBASE}.info.tar.gz info/${TEXIBASE}-info.tar.gz
|
||||
|
||||
echo Collecting the DVI file...
|
||||
cp $BUILDDIR/doc/manual/${TEXIBASE}.dvi.gz dvi/${TEXIBASE}.dvi.gz
|
||||
|
||||
echo Collecting the PDF file...
|
||||
cp $BUILDDIR/doc/manual/${TEXIBASE}.pdf .
|
||||
|
||||
@ -178,9 +175,6 @@ This manual is available in the following formats:
|
||||
<LI>
|
||||
$(linkfor "text/${TEXIBASE}.txt.gz" "gzipped characters" "ASCII text")
|
||||
</LI>
|
||||
<LI>
|
||||
$(linkfor "dvi/${TEXIBASE}.dvi.gz" "gzipped" "a TeX dvi file")
|
||||
</LI>
|
||||
<LI>
|
||||
$(linkfor "${TEXIBASE}.pdf" "PDF file" PDF)
|
||||
</LI>
|
||||
@ -208,8 +202,8 @@ send other questions to
|
||||
<A HREF="mailto:gnu@gnu.org"><EM>gnu@gnu.org</EM></A>.
|
||||
|
||||
<P>
|
||||
Copyright © 1997, 1998, 2003, 2005, 2006, 2008 Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
Copyright © 1997-2026 Free Software Foundation, Inc.,
|
||||
<<A HREF="https://fsf.org/">https://fsf.org/</A>>
|
||||
|
||||
<P>
|
||||
Verbatim copying and distribution of this entire article is
|
||||
|
||||
39
cfg.mk
39
cfg.mk
@ -1,5 +1,5 @@
|
||||
# cfg.mk -- configuration file for the maintainer makefile provided by gnulib.
|
||||
# Copyright (C) 2010-2024 Free Software Foundation, Inc.
|
||||
# Copyright (C) 2010-2026 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
|
||||
@ -21,11 +21,15 @@ gendocs_options_ = -s find.texi -I $(abs_builddir)/doc
|
||||
|
||||
local-checks-to-skip :=
|
||||
|
||||
# Tools used to bootstrap this package, used for "announcement".
|
||||
bootstrap-tools = autoconf,automake,gnulib,bison
|
||||
|
||||
# Errors I think are too picky anyway.
|
||||
local-checks-to-skip += sc_error_message_period sc_error_message_uppercase \
|
||||
sc_file_system sc_indent
|
||||
|
||||
exclude_file_name_regexp--sc_obsolete_symbols = build-aux/src-sniff\.py
|
||||
exclude_file_name_regexp--sc_fsf_postal = build-aux/src-sniff\.py
|
||||
exclude_file_name_regexp--sc_space_tab = \
|
||||
xargs/testsuite/(inputs/.*\.xi|xargs.(gnu|posix|sysv)/.*\.xo)|find/testsuite/test_escapechars\.golden$$
|
||||
|
||||
@ -92,6 +96,13 @@ exclude_file_name_regexp--sc_bindtextdomain = \
|
||||
exclude_file_name_regexp--sc_unmarked_diagnostics = \
|
||||
^(tests/xargs/test-sigusr)\.c$$
|
||||
|
||||
# Things that 'codespell' mistakenly flags as typos.
|
||||
codespell_ignore_words_list = afile,bu,debbugs,filll,fo,hel,ois,siz,ublic,TE,
|
||||
|
||||
# Files to exclude from sc_codespell
|
||||
exclude_file_name_regexp--sc_codespell = \
|
||||
^(THANKS|build-aux/git-log-fix)$$
|
||||
|
||||
# sc_prohibit_strcmp is broken because it gives false positives for
|
||||
# cases where neither argument is a string literal.
|
||||
local-checks-to-skip += sc_prohibit_strcmp
|
||||
@ -274,6 +285,32 @@ sc_prohibit_unhyphenated_eof:
|
||||
halt='use "end-of-file", not "e''nd of file"' \
|
||||
$(_sc_search_regexp)
|
||||
|
||||
# Prohibit the use of tabs in findutils C source files (but not
|
||||
# gnulib). This is not the same as sc_space_tab which prohibits only
|
||||
# tabs which follow spaces.
|
||||
sc_spaces_not_tabs:
|
||||
@cd $(srcdir) \
|
||||
&& GIT_PAGER= git grep -n ' ' -- \
|
||||
"find/*.[ch]" \
|
||||
"lib/*.[ch]" \
|
||||
"locate/*.[ch]" \
|
||||
"tests/*.[ch]" \
|
||||
"xargs/*.[ch]" \
|
||||
&& { echo '$(ME): Indent C sources with spaces, not tabs (fix with build-aux/tabs-to-spaces.sh)' 1>&2; exit 1; } \
|
||||
|| :
|
||||
|
||||
# Enforce standard references "standard input/output/error".
|
||||
sc_standard_outputs:
|
||||
@cd $(srcdir) || exit 1; \
|
||||
GIT_PAGER= git grep -En '_\("[^"]*std(in|out|err)' -- '*/*.c' \
|
||||
&& { echo '$@: use "standard ....." in translated strings' 1>&2; \
|
||||
fail=1; } || :; \
|
||||
GIT_PAGER= git grep -En '[^/]std(in|out|err)' -- \
|
||||
'*/*.1' '*/*.5' 'doc/*.texi' \
|
||||
&& { echo '$@: use "standard ....." in user docs' 1>&2; \
|
||||
fail=1; } || :; \
|
||||
exit $$fail
|
||||
|
||||
# Now that we have better tests, make this the default.
|
||||
export VERBOSE = yes
|
||||
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
# -*- autoconf -*-
|
||||
# Process this file with autoconf to produce a configure script.
|
||||
|
||||
# Copyright (C) 1996-2024 Free Software Foundation, Inc.
|
||||
# Copyright (C) 1996-2026 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
|
||||
@ -101,7 +101,6 @@ dnl AC_PROG_LIBTOOL
|
||||
AC_PROG_MAKE_SET
|
||||
AC_SYS_LARGEFILE
|
||||
|
||||
|
||||
gl_INIT
|
||||
|
||||
AC_ARG_ENABLE(compiler-warnings,
|
||||
@ -116,7 +115,6 @@ AC_ARG_ENABLE(compiler-warnings,
|
||||
|
||||
# Set up the list of the pointless, undesired warnings.
|
||||
findutils_nw=
|
||||
findutils_nw="$findutils_nw -Wsystem-headers" # Don't let system headers trigger warnings
|
||||
findutils_nw="$findutils_nw -Wundef" # All compiler preprocessors support #if UNDEF
|
||||
findutils_nw="$findutils_nw -Wtraditional" # All compilers nowadays support ANSI C
|
||||
findutils_nw="$findutils_nw -Wconversion" # These warnings usually don't point to mistakes.
|
||||
@ -298,6 +296,11 @@ AM_CONDITIONAL([HAVE_PYTHON], [test "$PYTHON" != :])
|
||||
AC_CHECK_PROGS([FAKETIME],[faketime],[:])
|
||||
AM_CONDITIONAL([HAVE_FAKETIME], [test "$FAKETIME" != :])
|
||||
|
||||
dnl Manpage linting.
|
||||
AC_ARG_VAR(GROFF,[Location of GNU groff])
|
||||
AC_CHECK_PROGS([GROFF], [groff],[:])
|
||||
|
||||
|
||||
# This is necessary so that .o files in LIBOBJS are also built via
|
||||
# the ANSI2KNR-filtering rules.
|
||||
#LIBOBJS=`echo $LIBOBJS|sed 's/\.o /\$U.o /g;s/\.o$/\$U.o/'`
|
||||
|
||||
2
doc/.gitignore
vendored
2
doc/.gitignore
vendored
@ -4,7 +4,6 @@
|
||||
/find.aux
|
||||
/find.cp
|
||||
/find.cps
|
||||
/find.dvi
|
||||
/find.fn
|
||||
/find.fns
|
||||
/find.html/
|
||||
@ -17,7 +16,6 @@
|
||||
/find.toc
|
||||
/find.tp
|
||||
/find.vr
|
||||
/find-maint.dvi
|
||||
/find-maint.html/
|
||||
/find-maint.pdf
|
||||
/find-maint.ps
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
# Copyright (C) 1996-2024 Free Software Foundation, Inc.
|
||||
# Copyright (C) 1996-2026 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
|
||||
|
||||
@ -23,7 +23,7 @@ be made and tested, and what resources exist to help developers.
|
||||
|
||||
This document corresponds to version @value{VERSION} of the GNU findutils.
|
||||
|
||||
Copyright @copyright{} 2007--2024 Free Software Foundation, Inc.
|
||||
Copyright @copyright{} 2007--2026 Free Software Foundation, Inc.
|
||||
|
||||
@quotation
|
||||
Permission is granted to copy, distribute and/or modify this document
|
||||
@ -87,7 +87,7 @@ This manual aims to be useful without necessarily being verbose. It's
|
||||
also a recent document, so there will be a many areas in which
|
||||
improvements can be made. If you find that the document misses out
|
||||
important information or any part of the document is be so terse as to
|
||||
be unuseful, please ask for help on the @email{bug-findutils@@gnu.org}
|
||||
be useless, please ask for help on the @email{bug-findutils@@gnu.org}
|
||||
mailing list. We'll try to improve this document too.
|
||||
|
||||
|
||||
@ -537,7 +537,7 @@ Make sure your editor follows symbolic links so that your changes to
|
||||
directory you checked out earlier. Observe that your test now passes.
|
||||
@item Prepare a Gnulib patch
|
||||
In the gnulib subdirectory, use @code{git format-patch} to prepare the
|
||||
patch. Follow the normal usage for checkin comments (take a look at
|
||||
patch. Follow the normal usage for check-in comments (take a look at
|
||||
the output of @code{git log}). Check that the patch conforms with the
|
||||
GNU coding standards, and email it to the Gnulib mailing list.
|
||||
@item Wait for the patch to be applied
|
||||
@ -674,7 +674,7 @@ changes). The level of detail used for this file should be sufficient
|
||||
to answer the questions ``what changed?'' and ``why was it changed?''.
|
||||
The file is generated from the git commit messages during @code{make dist}.
|
||||
If a change fixes a bug, always give the bug reference number in the
|
||||
@file{NEWS} file and of course also in the checkin message.
|
||||
@file{NEWS} file and of course also in the check-in message.
|
||||
In general, it should be possible to enumerate all
|
||||
material changes to a function by searching for its name in
|
||||
@file{ChangeLog}. Mention when each release is made.
|
||||
@ -947,7 +947,7 @@ VI. VENDOR RESPONSE
|
||||
The GNU project discovered the problem while 'locate' was being worked
|
||||
on; this is the first public announcement of the problem.
|
||||
|
||||
The GNU findutils mantainer has issued a patch as part of this
|
||||
The GNU findutils maintainer has issued a patch as part of this
|
||||
announcement. The patch appears below.
|
||||
|
||||
A source release of findutils-4.2.31 will be issued on 2007-05-30.
|
||||
|
||||
231
doc/find.texi
231
doc/find.texi
@ -30,7 +30,7 @@
|
||||
This manual documents version @value{VERSION} of the GNU utilities for finding
|
||||
files that match certain criteria and performing various operations on them.
|
||||
|
||||
Copyright @copyright{} 1994--2024 Free Software Foundation, Inc.
|
||||
Copyright @copyright{} 1994--2026 Free Software Foundation, Inc.
|
||||
|
||||
@quotation
|
||||
Permission is granted to copy, distribute and/or modify this document
|
||||
@ -328,10 +328,21 @@ connect primaries into more complex expressions.
|
||||
The @samp{-print} action is performed on all files for which the
|
||||
entire expression is true (@pxref{Print File Name}), unless the
|
||||
expression contains an action other than @samp{-prune} or
|
||||
@samp{-quit}. Actions which inhibit the default @samp{-print} are
|
||||
@samp{-delete}, @samp{-exec}, @samp{-execdir}, @samp{-ok},
|
||||
@samp{-okdir}, @samp{-fls}, @samp{-fprint}, @samp{-fprintf},
|
||||
@samp{-ls}, @samp{-print} and @samp{-printf}.
|
||||
@samp{-quit}.
|
||||
Actions which inhibit the default @samp{-print} are
|
||||
@samp{-delete},
|
||||
@samp{-execdir},
|
||||
@samp{-exec},
|
||||
@samp{-fls},
|
||||
@samp{-fprint0},
|
||||
@samp{-fprintf},
|
||||
@samp{-fprint},
|
||||
@samp{-ls},
|
||||
@samp{-okdir},
|
||||
@samp{-ok},
|
||||
@samp{-print0},
|
||||
@samp{-printf}
|
||||
and @samp{-print}.
|
||||
|
||||
Options take effect immediately, rather than being evaluated for each
|
||||
file when their place in the expression is reached. Therefore, for
|
||||
@ -497,6 +508,9 @@ Because the leading directories are removed, the file names considered
|
||||
for a match with @samp{-name} will never include a slash, so
|
||||
@samp{-name a/b} will never match anything (you probably need to use
|
||||
@samp{-path} instead).
|
||||
|
||||
The @samp{-iname} option appeared first in POSIX Issue 8 (IEEE Std 1003.1-2024)
|
||||
while GNU @code{find} supports it since version 3.8 (1993).
|
||||
@end deffn
|
||||
|
||||
|
||||
@ -521,8 +535,8 @@ arguments ending in @samp{/} will match nothing (except perhaps a
|
||||
start point specified on the command line).
|
||||
|
||||
The name @samp{-wholename} is GNU-specific, but @samp{-path} is more
|
||||
portable; it is supported by HP-UX @code{find} and is part of the
|
||||
POSIX 2008 standard.
|
||||
portable: the latter is supported by HP-UX @code{find} and is part of the
|
||||
POSIX standard (since IEEE Std 1003.1-2008).
|
||||
|
||||
@end deffn
|
||||
|
||||
@ -808,7 +822,7 @@ Actions that can cause symbolic links to become broken while
|
||||
confusing behaviour. Take for example the command line
|
||||
@samp{find -L . -type d -delete}. This will delete empty
|
||||
directories. If a subtree includes only directories and symbolic
|
||||
links to directoires, this command may still not successfully delete
|
||||
links to directories, this command may still not successfully delete
|
||||
it, since deletion of the target of the symbolic link will cause the
|
||||
symbolic link to become broken and @samp{-type d} is false for broken
|
||||
symbolic links.
|
||||
@ -1025,8 +1039,9 @@ command line.
|
||||
|
||||
@deffn Test -newerXY reference
|
||||
Succeeds if timestamp @samp{X} of the file being considered is newer
|
||||
than timestamp @samp{Y} of the file @file{reference}. The letters
|
||||
@samp{X} and @samp{Y} can be any of the following letters:
|
||||
than timestamp @samp{Y} of the file @file{reference}.
|
||||
Fails if the timestamps are @emph{equal}.
|
||||
The letters @samp{X} and @samp{Y} can be any of the following letters:
|
||||
|
||||
@table @samp
|
||||
@item a
|
||||
@ -1066,7 +1081,8 @@ not UFS1 file systems.
|
||||
|
||||
|
||||
There are two ways to list files in @file{/usr} modified after
|
||||
February 1 of the current year. One uses @samp{-newermt}:
|
||||
@emph{the start} of February 1 of the current year. One uses
|
||||
@samp{-newermt}:
|
||||
|
||||
@example
|
||||
find /usr -newermt "Feb 1"
|
||||
@ -1087,6 +1103,7 @@ rm -f /tmp/stamp$$
|
||||
True if the time of the last access (or status change or data modification)
|
||||
of the current file is more recent than that of the last data modification
|
||||
of the @var{reference} file.
|
||||
False if the timestamps are equal.
|
||||
As such, @samp{-anewer} is equivalent to @samp{-neweram},
|
||||
@samp{-cnewer} to @samp{-newercm}, and @samp{-newer} to @samp{-newermm}.
|
||||
|
||||
@ -1536,7 +1553,7 @@ This is different to @samp{-prune} because @samp{-prune} only applies
|
||||
to the contents of pruned directories, while @samp{-quit} simply makes
|
||||
@code{find} stop immediately. No child processes will be left
|
||||
running. Any command lines which have been built by @samp{-exec
|
||||
... \+} or @samp{-execdir ... \+} are invoked before the program is
|
||||
... @{@} +} or @samp{-execdir ... \+} are invoked before the program is
|
||||
exited. After @samp{-quit} is executed, no more files specified on
|
||||
the command line will be processed. For example, @samp{find /tmp/foo
|
||||
/tmp/bar -print -quit} will print only @samp{/tmp/foo}. One common
|
||||
@ -1607,10 +1624,12 @@ them.
|
||||
There are two ways to avoid searching certain filesystems. One way is
|
||||
to tell @code{find} to only search one filesystem:
|
||||
|
||||
@deffn Option -mount
|
||||
Ignore files on other devices.
|
||||
@end deffn
|
||||
|
||||
@deffn Option -xdev
|
||||
@deffnx Option -mount
|
||||
Don't descend directories on other filesystems. These options are
|
||||
synonyms.
|
||||
Don't descend into directories on other devices.
|
||||
@end deffn
|
||||
|
||||
The other way is to check the type of filesystem each file is on, and
|
||||
@ -1752,7 +1771,7 @@ you are searching might contain a newline, you should use
|
||||
@c @item -fls
|
||||
@c Escaped if @samp{how} is @samp{safe}
|
||||
@c @item -print
|
||||
@c Always quoted if stdout is a tty,
|
||||
@c Always quoted if standard output is a tty,
|
||||
@c @samp{-show-control-chars} is ignored
|
||||
@c @item -print0
|
||||
@c Always literal, never escaped
|
||||
@ -1765,7 +1784,7 @@ you are searching might contain a newline, you should use
|
||||
@c If the destination is a tty, the @samp{%f},
|
||||
@c @samp{%F}, @samp{%h}, @samp{%l}, @samp{%p},
|
||||
@c and @samp{%P} directives produce quoted
|
||||
@c strings if stdout is a tty and are treated
|
||||
@c strings if standard output is a tty and are treated
|
||||
@c literally otherwise.
|
||||
@c @item -printf
|
||||
@c As for @code{-fprintf}.
|
||||
@ -2318,13 +2337,16 @@ Here is how to run a command on one file at a time.
|
||||
@deffn Action -execdir command ;
|
||||
Execute @var{command}; true if @var{command} returns zero. @code{find}
|
||||
takes all arguments after @samp{-execdir} to be part of the command until
|
||||
an argument consisting of @samp{;} is reached. It replaces the string
|
||||
@samp{@{@}} by the current file name being processed everywhere it
|
||||
occurs in the command. Both of these constructions need to be escaped
|
||||
(with a @samp{\}) or quoted to protect them from expansion by the
|
||||
shell. The command is executed in the directory which @code{find}
|
||||
was searching at the time the action was executed (that is, @{@} will
|
||||
expand to a file in the local directory).
|
||||
an argument consisting of @samp{;} is reached.
|
||||
It replaces the string @samp{@{@}} by the current file name being processed
|
||||
everywhere it occurs in the command.
|
||||
Each file name except for the root directory @samp{/} is prepended with
|
||||
@samp{./}.
|
||||
Both of these constructions need to be escaped (with a @samp{\}) or quoted to
|
||||
protect them from expansion by the shell.
|
||||
The command is executed in the directory which @code{find} was searching at the
|
||||
time the action was executed (that is, @{@} will expand to a file in the local
|
||||
directory).
|
||||
|
||||
For example, to compare each C header file in or below the current
|
||||
directory with the file @file{/tmp/master}:
|
||||
@ -2388,15 +2410,17 @@ The @samp{-execdir} and @samp{-exec} actions have variants that build
|
||||
command lines containing as many matched files as possible.
|
||||
|
||||
@deffn Action -execdir command @{@} +
|
||||
This works as for @samp{-execdir command ;}, except that the result is
|
||||
always true, and the @samp{@{@}} at the end of the command is expanded
|
||||
to a list of names of matching files. This expansion is done in such
|
||||
a way as to avoid exceeding the maximum command line length available
|
||||
on the system. Only one @samp{@{@}} is allowed within the command,
|
||||
and it must appear at the end, immediately before the @samp{+}. A
|
||||
@samp{+} appearing in any position other than immediately after
|
||||
@samp{@{@}} is not considered to be special (that is, it does not
|
||||
terminate the command).
|
||||
This works as for @samp{-execdir command ;}, except that the result is always
|
||||
true, and the @samp{@{@}} at the end of the command is expanded to a list of
|
||||
names of matching files.
|
||||
Each file name except for the root directory @samp{/} is prepended with
|
||||
@samp{./}.
|
||||
This expansion is done in such a way as to avoid exceeding the maximum command
|
||||
line length available on the system.
|
||||
Only one @samp{@{@}} is allowed within the command, and it must appear at the
|
||||
end, immediately before the @samp{+}.
|
||||
A @samp{+} appearing in any position other than immediately after @samp{@{@}}
|
||||
is not considered to be special (that is, it does not terminate the command).
|
||||
@end deffn
|
||||
|
||||
|
||||
@ -2453,7 +2477,7 @@ should consider the following line to be part of this one.
|
||||
|
||||
Instead of blank-delimited names, it is safer to use @samp{find
|
||||
-print0} or @samp{find -fprint0} and process the output by giving the
|
||||
@samp{-0} or @samp{--null} option to GNU @code{xargs}, GNU @code{tar},
|
||||
@samp{-0} or @samp{--null} option to @code{xargs}, GNU @code{tar},
|
||||
GNU @code{cpio}, or @code{perl}. The @code{locate} command also has a
|
||||
@samp{-0} or @samp{--null} option which does the same thing.
|
||||
|
||||
@ -2566,6 +2590,9 @@ can process file names generated this way by giving the @samp{-0} or
|
||||
@samp{--null} option to GNU @code{xargs}, GNU @code{tar}, GNU
|
||||
@code{cpio}, or @code{perl}.
|
||||
|
||||
Both @code{find . -print0} and @code{xargs -0} are
|
||||
POSIX-conforming since Issue 8 (IEEE Std 1003.1-2024).
|
||||
|
||||
@deffn Action -print0
|
||||
True; print the entire file name on the standard output, followed by a
|
||||
null character.
|
||||
@ -2786,16 +2813,17 @@ if @code{xargs} is running commands that are waiting for a response from a
|
||||
distant network connection, running a few in parallel may reduce the
|
||||
overall latency by overlapping their waiting time.
|
||||
|
||||
If you are running commands in parallel, you need to think about how
|
||||
they should arbitrate access to any resources that they share. For
|
||||
example, if more than one of them tries to print to stdout, the output
|
||||
will be produced in an indeterminate order (and very likely mixed up)
|
||||
unless the processes collaborate in some way to prevent this. Using
|
||||
some kind of locking scheme is one way to prevent such problems. In
|
||||
general, using a locking scheme will help ensure correct output but
|
||||
reduce performance. If you don't want to tolerate the performance
|
||||
difference, simply arrange for each process to produce a separate output
|
||||
file (or otherwise use separate resources).
|
||||
If you are running commands in parallel, you need to think about how they should
|
||||
arbitrate access to any resources that they share.
|
||||
For example, if more than one of them tries to print to standard output, the
|
||||
output will be produced in an indeterminate order (and very likely mixed up)
|
||||
unless the processes collaborate in some way to prevent this.
|
||||
Using some kind of locking scheme is one way to prevent such problems.
|
||||
In general, using a locking scheme will help ensure correct output but reduce
|
||||
performance.
|
||||
If you don't want to tolerate the performance difference, simply arrange for
|
||||
each process to produce a separate output file (or otherwise use separate
|
||||
resources).
|
||||
|
||||
@code{xargs} also allows ``turning up'' or ``turning down'' its parallelism
|
||||
in the middle of a run. Suppose you are keeping your four-processor
|
||||
@ -2853,7 +2881,7 @@ delaying for a few seconds between signals (unless your system is very
|
||||
heavily loaded).
|
||||
|
||||
Whether or not parallel execution will work well for you depends on
|
||||
the nature of the commmand you are running in parallel, on the
|
||||
the nature of the command you are running in parallel, on the
|
||||
configuration of the system on which you are running the command, and
|
||||
on the other work being done on the system at the time.
|
||||
|
||||
@ -3348,7 +3376,7 @@ useful or which are not obvious are explained here.
|
||||
@section Leaf Optimisation
|
||||
|
||||
Files in Unix file systems have a link count which indicates how many
|
||||
names point to the same inode. Directories in Unix filssytems have a
|
||||
names point to the same inode. Directories in Unix filesystems have a
|
||||
@file{..} entry which functions as a hard link to the parent directory
|
||||
and a @file{.} entry which functions as a link to the directory itself.
|
||||
The @file{..} entry of the root directory also points to the root.
|
||||
@ -3549,7 +3577,7 @@ information from the inode. On many modern versions of Unix, file
|
||||
types are returned by @code{readdir()} and so these predicates are
|
||||
faster to evaluate than predicates which need to stat the file first.
|
||||
|
||||
If you use the @samp{-fstype FOO} predicate and specify a filsystem
|
||||
If you use the @samp{-fstype FOO} predicate and specify a filesystem
|
||||
type @samp{FOO} which is not known (that is, present in
|
||||
@file{/etc/mtab}) at the time @code{find} starts, that predicate is
|
||||
equivalent to @samp{-false}.
|
||||
@ -3655,7 +3683,7 @@ database file names. You can also use the environment variable
|
||||
option overrides the environment variable if both are used. Empty
|
||||
elements in @var{path} (that is, a leading or trailing colon, or two
|
||||
colons in a row) are taken to stand for the default database.
|
||||
A database can be supplied on stdin, using @samp{-} as an element
|
||||
A database can be supplied on standard input, using @samp{-} as an element
|
||||
of @samp{path}. If more than one element of @samp{path} is @samp{-},
|
||||
later instances are ignored (but a warning message is printed).
|
||||
|
||||
@ -3856,6 +3884,10 @@ Print the version number of @code{updatedb} and exit.
|
||||
xargs @r{[}@var{option}@dots{}@r{]} @r{[}@var{command} @r{[}@var{initial-arguments}@r{]}@r{]}
|
||||
@end example
|
||||
|
||||
@code{xargs} executes the @var{command} - the default is @file{echo} - one or
|
||||
more times with any @var{initial-arguments} followed by arguments read from
|
||||
standard input.
|
||||
|
||||
@code{xargs} exits with the following status:
|
||||
|
||||
@table @asis
|
||||
@ -3901,15 +3933,15 @@ rejecting this as unrecognized option.
|
||||
@itemx -a @r{@var{inputfile}}
|
||||
Read names from the file @var{inputfile} instead of standard input.
|
||||
If you use this option, the standard input stream remains unchanged
|
||||
when commands are run. Otherwise, stdin is redirected from
|
||||
@file{/dev/null}.
|
||||
when commands are run.
|
||||
Otherwise, standard input is redirected from @file{/dev/null}.
|
||||
|
||||
@item --null
|
||||
@itemx -0
|
||||
Input file names are terminated by a null character instead of by
|
||||
whitespace, and any quotes and backslash characters are not considered
|
||||
special (every character is taken literally). Disables the end of
|
||||
file string, which is treated like any other argument.
|
||||
special (every character is taken literally).
|
||||
Disables the end-of-file string, which is treated like any other argument.
|
||||
|
||||
@item --delimiter @var{delim}
|
||||
@itemx -d @var{delim}
|
||||
@ -3979,7 +4011,7 @@ case @code{xargs} will exit.
|
||||
|
||||
@item --open-tty
|
||||
@itemx -o
|
||||
Reopen stdin as @file{/dev/tty} in the child process before executing
|
||||
Reopen standard input as @file{/dev/tty} in the child process before executing
|
||||
the command, thus allowing that command to be associated to the terminal
|
||||
while @code{xargs} reads from a different stream, e.g. from a pipe.
|
||||
This is useful if you want @code{xargs} to run an interactive application.
|
||||
@ -4048,7 +4080,7 @@ The options @samp{--max-lines} (@samp{-L}, @samp{-l}), @samp{--replace}
|
||||
If some of them are specified at the same time, then @code{xargs} will
|
||||
generally use the option specified last on the command line, i.e., it will
|
||||
reset the value of the offending option (given before) to its default value.
|
||||
Additionally, @code{xargs} will issue a warning diagnostic on @file{stderr}.
|
||||
Additionally, @code{xargs} will issue a warning diagnostic on standard error.
|
||||
|
||||
@example
|
||||
$ seq 4 | xargs -L2 -n3
|
||||
@ -4148,7 +4180,7 @@ process creation.
|
||||
|
||||
Although GNU @code{xargs} and the implementations on some other platforms
|
||||
like BSD support the @samp{-o} option to achieve the same, the above is
|
||||
the portable way to redirect stdin to @file{/dev/tty}.
|
||||
the portable way to redirect standard input to @file{/dev/tty}.
|
||||
|
||||
Sometimes, though, it can be helpful to keep the shell process around:
|
||||
|
||||
@ -4247,7 +4279,7 @@ they are units of 1024 bytes.
|
||||
|
||||
Setting this variable also turns off warning messages (that is, implies
|
||||
@samp{-nowarn}) by default, because POSIX requires that apart from
|
||||
the output for @samp{-ok}, all messages printed on stderr are
|
||||
the output for @samp{-ok}, all messages printed on standard error are
|
||||
diagnostics and must result in a non-zero exit status.
|
||||
|
||||
When @env{POSIXLY_CORRECT} is set, the response to the prompt made by the
|
||||
@ -4328,7 +4360,7 @@ nothing). The capitalised @samp{Emacs} on the command line is used as
|
||||
|
||||
Please note that the implementations in GNU @code{xargs} and at least BSD
|
||||
support the @samp{-o} option as extension to achieve the same, while the
|
||||
above is the portable way to redirect stdin to @file{/dev/tty}.
|
||||
above is the portable way to redirect standard input to @file{/dev/tty}.
|
||||
|
||||
@node Archiving
|
||||
@section Archiving
|
||||
@ -4654,6 +4686,9 @@ there are lots of files to delete. Since the task is to delete
|
||||
unwanted files, this is precisely the time we don't want things to go
|
||||
wrong.
|
||||
|
||||
There is also a second problem with this method. We will discuss that
|
||||
below.
|
||||
|
||||
@subsection Making Use of @code{xargs}
|
||||
|
||||
So, is there a way to be more efficient in the use of @code{fork()}
|
||||
@ -4719,13 +4754,15 @@ this command:
|
||||
find /var/tmp/stuff -mtime +90 -print0 | xargs -0 /bin/rm
|
||||
@end smallexample
|
||||
|
||||
The result is an efficient way of proceeding that
|
||||
correctly handles all the possible characters that could appear in the
|
||||
list of files to delete. This is good news. However, there is, as
|
||||
I'm sure you're expecting, also more bad news. The problem is that
|
||||
this is not a portable construct; although other versions of Unix
|
||||
(notably BSD-derived ones) support @samp{-print0}, it's not
|
||||
universal. So, is there a more universal mechanism?
|
||||
The result is an efficient way of proceeding that correctly handles
|
||||
all the possible characters that could appear in the list of files to
|
||||
delete. This is good news. However, there is, as I'm sure you're
|
||||
expecting, also more bad news. The problem is that this is not a
|
||||
portable construct. Support for @samp{-print0} is not universal.
|
||||
|
||||
Although some other versions of Unix (notably BSD-derived ones)
|
||||
support @samp{-print0}, this is only required in POSIX from Issue 8
|
||||
(IEEE Std 1003.1-2024). So, is there a more universal mechanism?
|
||||
|
||||
@subsection Going back to @code{-exec}
|
||||
|
||||
@ -4992,7 +5029,7 @@ different ways to do it.
|
||||
The obvious but wrong answer is just to use @samp{-newer}:
|
||||
|
||||
@smallexample
|
||||
find subdir -newer timestamp -exec touch -r @{@} timestamp \;
|
||||
find subdir -type f -newer timestamp -exec touch -r @{@} timestamp \;
|
||||
@end smallexample
|
||||
|
||||
This does the right sort of thing but has a bug. Suppose that two
|
||||
@ -5013,7 +5050,7 @@ compared against it, but that will reduce the performance of
|
||||
The @code{test} command can be used to compare timestamps:
|
||||
|
||||
@smallexample
|
||||
find subdir -exec test @{@} -nt timestamp \; -exec touch -r @{@} timestamp \;
|
||||
find subdir -type f -exec test @{@} -nt timestamp \; -exec touch -r @{@} timestamp \;
|
||||
@end smallexample
|
||||
|
||||
This will ensure that any changes made to the modification time of
|
||||
@ -5027,13 +5064,14 @@ We can of course still use @samp{-newer} to cut down on the number of
|
||||
calls to @code{test}:
|
||||
|
||||
@smallexample
|
||||
find subdir -newer timestamp -and \
|
||||
find subdir -type f -newer timestamp -and \
|
||||
-exec test @{@} -nt timestamp \; -and \
|
||||
-exec touch -r @{@} timestamp \;
|
||||
@end smallexample
|
||||
|
||||
Here, the @samp{-newer} test excludes all the files which are
|
||||
definitely older than the timestamp, but all the files which are newer
|
||||
definitely older than or the same age as
|
||||
the timestamp, but all the files which are newer
|
||||
than the old value of the timestamp are compared against the current
|
||||
updated timestamp.
|
||||
|
||||
@ -5046,10 +5084,8 @@ It is possible to use the @samp{-printf} action to abandon the use of
|
||||
@code{test} entirely:
|
||||
|
||||
@smallexample
|
||||
newest=$(find subdir -newer timestamp -printf "%A@@:%p\n" |
|
||||
sort -n |
|
||||
tail -n1 |
|
||||
cut -d: -f2- )
|
||||
newest="$(find subdir -type f -newer timestamp -printf "%A@@:%p\n" |
|
||||
env LC_ALL=C sh -c 'sort -n | tail -n1 | cut -d: -f2-' )"
|
||||
touch -r "$@{newest:-timestamp@}" timestamp
|
||||
@end smallexample
|
||||
|
||||
@ -5057,19 +5093,20 @@ The command above works by generating a list of the timestamps and
|
||||
names of all the files which are newer than the timestamp. The
|
||||
@code{sort}, @code{tail} and @code{cut} commands simply pull out the
|
||||
name of the file with the largest timestamp value (that is, the latest
|
||||
file). The @code{touch} command is then used to update the timestamp,
|
||||
file). We run those programs (which normally read and write text)
|
||||
with with the @env{LC_ALL} environment variable set to @samp{C} in
|
||||
order to avoid character encoding problems; file names are not
|
||||
guaranteed to have a valid (or consistent) character encoding. The
|
||||
@code{touch} command is then used to update the timestamp,
|
||||
|
||||
The @code{"$@{newest:-timestamp@}"} expression simply expands to the
|
||||
value of @code{$newest} if that variable is set, but to
|
||||
@file{timestamp} otherwise. This ensures that an argument is always
|
||||
given to the @samp{-r} option of the @code{touch} command.
|
||||
|
||||
This approach seems quite efficient, but unfortunately it has a
|
||||
problem. Many operating systems now keep file modification time
|
||||
information at a granularity which is finer than one second.
|
||||
Findutils version 4.3.3 and later will print a fractional part with
|
||||
%A@@, but older versions will not.
|
||||
|
||||
@c We used to warn the reader about older versions of Find where %A@
|
||||
@c didn't include a fractional part, but since Findutils 4.3.3 was
|
||||
@c released in 2007, people are unlikely to have a problem today.
|
||||
|
||||
@subsection Solving the problem with @code{make}
|
||||
|
||||
@ -5078,8 +5115,9 @@ use @code{find} to generate a @file{Makefile} file on the fly and then
|
||||
use @code{make} to update the timestamps:
|
||||
|
||||
@smallexample
|
||||
makefile=$(mktemp)
|
||||
makefile="$(mktemp)"
|
||||
find subdir \
|
||||
-type f \
|
||||
\( \! -xtype l \) \
|
||||
-newer timestamp \
|
||||
-printf "timestamp:: %p\n\ttouch -r %p timestamp\n\n" > "$makefile"
|
||||
@ -5099,14 +5137,15 @@ space), and do things more efficiently too. The following command
|
||||
works with newlines and doesn't need to sort the list of filenames.
|
||||
|
||||
@smallexample
|
||||
find subdir -newer timestamp -printf "%A@@:%p\0" |
|
||||
find subdir -type f -newer timestamp -printf "%A@@:%p\0" |
|
||||
perl -0 newest.pl |
|
||||
xargs --no-run-if-empty --null --replace \
|
||||
find @{@} -maxdepth 0 -newer timestamp -exec touch -r @{@} timestamp \;
|
||||
@end smallexample
|
||||
|
||||
The first @code{find} command generates a list of files which are
|
||||
newer than the original timestamp file, and prints a list of them with
|
||||
newer than (and not the same age as) the original timestamp file,
|
||||
and prints a list of them with
|
||||
their timestamps. The @file{newest.pl} script simply filters out all
|
||||
the filenames which have timestamps which are older than whatever the
|
||||
newest file is:
|
||||
@ -5168,13 +5207,24 @@ already found.
|
||||
|
||||
@smallexample
|
||||
find repo/ \
|
||||
-exec test -d @{@}/.svn \; -or \
|
||||
-exec test -d @{@}/.git \; -or \
|
||||
-exec test -d @{@}/CVS \; -print -prune
|
||||
\( \
|
||||
-exec test -d @{@}/.svn \; -or \
|
||||
-exec test -d @{@}/.git \; -or \
|
||||
-exec test -d @{@}/CVS \; \
|
||||
\) -print -prune
|
||||
@end smallexample
|
||||
|
||||
Output:
|
||||
|
||||
@smallexample
|
||||
repo/project1
|
||||
repo/gnu/project2
|
||||
repo/gnu/project3
|
||||
repo/project4
|
||||
@end smallexample
|
||||
|
||||
In this example, @command{test} is used to tell if we are currently
|
||||
examining a directory which appears to the a project's root directory
|
||||
examining a directory which appears to be a project's root directory
|
||||
(because it has an SCM subdirectory). When we find a project root,
|
||||
there is no need to search inside it, and @code{-prune} makes sure
|
||||
that we descend no further.
|
||||
@ -5600,9 +5650,10 @@ The only ways to avoid this problem are either to avoid all use of
|
||||
available) @samp{find -execdir}, or to use the @samp{-0} option, which
|
||||
ensures that @code{xargs} considers file names to be separated by
|
||||
ASCII NUL characters rather than whitespace. However, useful as this
|
||||
option is, the POSIX standard does not make it mandatory.
|
||||
option is, the POSIX standard did not make it mandatory prior to
|
||||
Issue 8 (IEEE Std 1003.1-2024).
|
||||
|
||||
POSIX also specifies that @code{xargs} interprets quoting and trailing
|
||||
POSIX also specifies that @code{xargs} without @code{-0} interprets quoting and trailing
|
||||
whitespace specially in filenames, too. This means that using
|
||||
@code{find ... -print | xargs ...} can cause the commands run by
|
||||
@code{xargs} to receive a list of file names which is not the same as
|
||||
@ -5840,8 +5891,8 @@ If you don't plan to send it those signals, this warning can be ignored
|
||||
why @code{xargs} is confused by your operating system).
|
||||
|
||||
@item failed to redirect standard input of the child process
|
||||
@code{xargs} redirects the stdin stream of the command to be run to either
|
||||
@file{/dev/null} or to @file{/dev/tty} for the @samp{-o} option.
|
||||
@code{xargs} redirects the standard input stream of the command to be run to
|
||||
either @file{/dev/null} or to @file{/dev/tty} for the @samp{-o} option.
|
||||
See the manual of the system call @code{dup2(2)}.
|
||||
@end table
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
@c File mode bits
|
||||
|
||||
@c Copyright (C) 1994--2024 Free Software Foundation, Inc.
|
||||
@c Copyright (C) 1994--2026 Free Software Foundation, Inc.
|
||||
|
||||
@c Permission is granted to copy, distribute and/or modify this document
|
||||
@c under the terms of the GNU Free Documentation License, Version 1.3 or
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
@c Copyright (C) 1994--2024 Free Software Foundation, Inc.
|
||||
@c Copyright (C) 1994--2026 Free Software Foundation, Inc.
|
||||
@c
|
||||
@c Permission is granted to copy, distribute and/or modify this document
|
||||
@c under the terms of the GNU Free Documentation License, Version 1.3 or
|
||||
@ -11,14 +11,14 @@
|
||||
|
||||
@menu
|
||||
* findutils-default regular expression syntax::
|
||||
* awk regular expression syntax::
|
||||
* egrep regular expression syntax::
|
||||
* emacs regular expression syntax::
|
||||
* gnu-awk regular expression syntax::
|
||||
* grep regular expression syntax::
|
||||
* posix-awk regular expression syntax::
|
||||
* awk regular expression syntax::
|
||||
* posix-basic regular expression syntax::
|
||||
* posix-egrep regular expression syntax::
|
||||
* egrep regular expression syntax::
|
||||
* posix-extended regular expression syntax::
|
||||
@end menu
|
||||
|
||||
@ -42,7 +42,7 @@ matches a @samp{?}.
|
||||
@end table
|
||||
|
||||
|
||||
Bracket expressions are used to match ranges of characters. Bracket expressions where the range is backward, for example @samp{[z-a]}, are ignored. Within square brackets, @samp{\} is taken literally. Character classes are not supported, so for example you would need to use @samp{[0-9]} instead of @samp{[[:digit:]]}.
|
||||
Bracket expressions are used to match ranges of characters. Bracket expressions where the range is backward, for example @samp{[z-a]}, are ignored. Within square brackets, @samp{\} is taken literally. Character classes are supported; for example @samp{[[:digit:]]} will match a single decimal digit.
|
||||
|
||||
|
||||
GNU extensions are supported:
|
||||
@ -108,11 +108,124 @@ The character @samp{$} only represents the end of a string when it appears:
|
||||
@end enumerate
|
||||
|
||||
|
||||
Intervals are specified by @samp{\@{} and @samp{\@}}.
|
||||
Invalid intervals such as @samp{a\@{1z} are not accepted.
|
||||
|
||||
|
||||
The longest possible match is returned; this applies to the regular expression as a whole and (subject to this constraint) to subexpressions within groups.
|
||||
|
||||
|
||||
@node awk regular expression syntax
|
||||
@subsection @samp{awk} regular expression syntax
|
||||
|
||||
|
||||
The character @samp{.} matches any single character except the null character.
|
||||
|
||||
|
||||
@table @samp
|
||||
|
||||
@item +
|
||||
indicates that the regular expression should match one or more occurrences of the previous atom or regexp.
|
||||
@item ?
|
||||
indicates that the regular expression should match zero or one occurrence of the previous atom or regexp.
|
||||
@item \+
|
||||
matches a @samp{+}
|
||||
@item \?
|
||||
matches a @samp{?}.
|
||||
@end table
|
||||
|
||||
|
||||
Bracket expressions are used to match ranges of characters. Bracket expressions where the range is backward, for example @samp{[z-a]}, are invalid. Within square brackets, @samp{\} can be used to quote the following character. Character classes are supported; for example @samp{[[:digit:]]} will match a single decimal digit.
|
||||
|
||||
|
||||
GNU extensions are not supported and so @samp{\w}, @samp{\W}, @samp{\<}, @samp{\>}, @samp{\b}, @samp{\B}, @samp{\`}, and @samp{\'} match @samp{w}, @samp{W}, @samp{<}, @samp{>}, @samp{b}, @samp{B}, @samp{`}, and @samp{'} respectively.
|
||||
|
||||
|
||||
Grouping is performed with parentheses @samp{()}. An unmatched @samp{)} matches just itself. A backslash followed by a digit matches that digit.
|
||||
|
||||
The alternation operator is @samp{|}.
|
||||
|
||||
The characters @samp{^} and @samp{$} always represent the beginning and end of a string respectively, except within square brackets. Within brackets, @samp{^} can be used to invert the membership of the character class being specified.
|
||||
|
||||
|
||||
@samp{*}, @samp{+} and @samp{?} are special at any point in a regular expression except:
|
||||
@enumerate
|
||||
|
||||
@item At the beginning of a regular expression
|
||||
|
||||
@item After an open-group, signified by @samp{(}
|
||||
|
||||
@item After the alternation operator @samp{|}
|
||||
|
||||
@end enumerate
|
||||
|
||||
|
||||
|
||||
|
||||
The longest possible match is returned; this applies to the regular expression as a whole and (subject to this constraint) to subexpressions within groups.
|
||||
|
||||
|
||||
@node egrep regular expression syntax
|
||||
@subsection @samp{egrep} regular expression syntax
|
||||
|
||||
|
||||
The character @samp{.} matches any single character.
|
||||
|
||||
|
||||
@table @samp
|
||||
|
||||
@item +
|
||||
indicates that the regular expression should match one or more occurrences of the previous atom or regexp.
|
||||
@item ?
|
||||
indicates that the regular expression should match zero or one occurrence of the previous atom or regexp.
|
||||
@item \+
|
||||
matches a @samp{+}
|
||||
@item \?
|
||||
matches a @samp{?}.
|
||||
@end table
|
||||
|
||||
|
||||
Bracket expressions are used to match ranges of characters. Bracket expressions where the range is backward, for example @samp{[z-a]}, are invalid. Within square brackets, @samp{\} is taken literally. Character classes are supported; for example @samp{[[:digit:]]} will match a single decimal digit.
|
||||
|
||||
|
||||
GNU extensions are supported:
|
||||
@enumerate
|
||||
|
||||
@item @samp{\w} matches a character within a word
|
||||
|
||||
@item @samp{\W} matches a character which is not within a word
|
||||
|
||||
@item @samp{\<} matches the beginning of a word
|
||||
|
||||
@item @samp{\>} matches the end of a word
|
||||
|
||||
@item @samp{\b} matches a word boundary
|
||||
|
||||
@item @samp{\B} matches characters which are not a word boundary
|
||||
|
||||
@item @samp{\`} matches the beginning of the whole input
|
||||
|
||||
@item @samp{\'} matches the end of the whole input
|
||||
|
||||
@end enumerate
|
||||
|
||||
|
||||
Grouping is performed with parentheses @samp{()}. An unmatched @samp{)} matches just itself. A backslash followed by a digit acts as a back-reference and matches the same thing as the previous grouped expression indicated by that number. For example @samp{\2} matches the second group expression. The order of group expressions is determined by the position of their opening parenthesis @samp{(}.
|
||||
|
||||
The alternation operator is @samp{|}.
|
||||
|
||||
The characters @samp{^} and @samp{$} always represent the beginning and end of a string respectively, except within square brackets. Within brackets, @samp{^} can be used to invert the membership of the character class being specified.
|
||||
|
||||
|
||||
The characters @samp{*}, @samp{+} and @samp{?} are special anywhere in a regular expression.
|
||||
|
||||
|
||||
Intervals are specified by @samp{@{} and @samp{@}}.
|
||||
Invalid intervals are treated as literals, for example @samp{a@{1} is treated as @samp{a\@{1}
|
||||
|
||||
The longest possible match is returned; this applies to the regular expression as a whole and (subject to this constraint) to subexpressions within groups.
|
||||
|
||||
|
||||
@node emacs regular expression syntax
|
||||
@subsection @samp{emacs} regular expression syntax
|
||||
|
||||
@ -133,7 +246,7 @@ matches a @samp{?}.
|
||||
@end table
|
||||
|
||||
|
||||
Bracket expressions are used to match ranges of characters. Bracket expressions where the range is backward, for example @samp{[z-a]}, are ignored. Within square brackets, @samp{\} is taken literally. Character classes are not supported, so for example you would need to use @samp{[0-9]} instead of @samp{[[:digit:]]}.
|
||||
Bracket expressions are used to match ranges of characters. Bracket expressions where the range is backward, for example @samp{[z-a]}, are ignored. Within square brackets, @samp{\} is taken literally. Character classes are supported; for example @samp{[[:digit:]]} will match a single decimal digit.
|
||||
|
||||
|
||||
GNU extensions are supported:
|
||||
@ -199,6 +312,8 @@ The character @samp{$} only represents the end of a string when it appears:
|
||||
@end enumerate
|
||||
|
||||
|
||||
Intervals are specified by @samp{\@{} and @samp{\@}}.
|
||||
Invalid intervals such as @samp{a\@{1z} are not accepted.
|
||||
|
||||
|
||||
The longest possible match is returned; this applies to the regular expression as a whole and (subject to this constraint) to subexpressions within groups.
|
||||
@ -420,56 +535,6 @@ The characters @samp{^} and @samp{$} always represent the beginning and end of a
|
||||
Intervals are specified by @samp{@{} and @samp{@}}.
|
||||
Invalid intervals are treated as literals, for example @samp{a@{1} is treated as @samp{a\@{1}
|
||||
|
||||
The longest possible match is returned; this applies to the regular expression as a whole and (subject to this constraint) to subexpressions within groups.
|
||||
|
||||
|
||||
@node awk regular expression syntax
|
||||
@subsection @samp{awk} regular expression syntax
|
||||
|
||||
|
||||
The character @samp{.} matches any single character except the null character.
|
||||
|
||||
|
||||
@table @samp
|
||||
|
||||
@item +
|
||||
indicates that the regular expression should match one or more occurrences of the previous atom or regexp.
|
||||
@item ?
|
||||
indicates that the regular expression should match zero or one occurrence of the previous atom or regexp.
|
||||
@item \+
|
||||
matches a @samp{+}
|
||||
@item \?
|
||||
matches a @samp{?}.
|
||||
@end table
|
||||
|
||||
|
||||
Bracket expressions are used to match ranges of characters. Bracket expressions where the range is backward, for example @samp{[z-a]}, are invalid. Within square brackets, @samp{\} can be used to quote the following character. Character classes are supported; for example @samp{[[:digit:]]} will match a single decimal digit.
|
||||
|
||||
|
||||
GNU extensions are not supported and so @samp{\w}, @samp{\W}, @samp{\<}, @samp{\>}, @samp{\b}, @samp{\B}, @samp{\`}, and @samp{\'} match @samp{w}, @samp{W}, @samp{<}, @samp{>}, @samp{b}, @samp{B}, @samp{`}, and @samp{'} respectively.
|
||||
|
||||
|
||||
Grouping is performed with parentheses @samp{()}. An unmatched @samp{)} matches just itself. A backslash followed by a digit matches that digit.
|
||||
|
||||
The alternation operator is @samp{|}.
|
||||
|
||||
The characters @samp{^} and @samp{$} always represent the beginning and end of a string respectively, except within square brackets. Within brackets, @samp{^} can be used to invert the membership of the character class being specified.
|
||||
|
||||
|
||||
@samp{*}, @samp{+} and @samp{?} are special at any point in a regular expression except:
|
||||
@enumerate
|
||||
|
||||
@item At the beginning of a regular expression
|
||||
|
||||
@item After an open-group, signified by @samp{(}
|
||||
|
||||
@item After the alternation operator @samp{|}
|
||||
|
||||
@end enumerate
|
||||
|
||||
|
||||
|
||||
|
||||
The longest possible match is returned; this applies to the regular expression as a whole and (subject to this constraint) to subexpressions within groups.
|
||||
|
||||
|
||||
@ -567,68 +632,7 @@ The longest possible match is returned; this applies to the regular expression a
|
||||
|
||||
@node posix-egrep regular expression syntax
|
||||
@subsection @samp{posix-egrep} regular expression syntax
|
||||
|
||||
|
||||
The character @samp{.} matches any single character.
|
||||
|
||||
|
||||
@table @samp
|
||||
|
||||
@item +
|
||||
indicates that the regular expression should match one or more occurrences of the previous atom or regexp.
|
||||
@item ?
|
||||
indicates that the regular expression should match zero or one occurrence of the previous atom or regexp.
|
||||
@item \+
|
||||
matches a @samp{+}
|
||||
@item \?
|
||||
matches a @samp{?}.
|
||||
@end table
|
||||
|
||||
|
||||
Bracket expressions are used to match ranges of characters. Bracket expressions where the range is backward, for example @samp{[z-a]}, are invalid. Within square brackets, @samp{\} is taken literally. Character classes are supported; for example @samp{[[:digit:]]} will match a single decimal digit.
|
||||
|
||||
|
||||
GNU extensions are supported:
|
||||
@enumerate
|
||||
|
||||
@item @samp{\w} matches a character within a word
|
||||
|
||||
@item @samp{\W} matches a character which is not within a word
|
||||
|
||||
@item @samp{\<} matches the beginning of a word
|
||||
|
||||
@item @samp{\>} matches the end of a word
|
||||
|
||||
@item @samp{\b} matches a word boundary
|
||||
|
||||
@item @samp{\B} matches characters which are not a word boundary
|
||||
|
||||
@item @samp{\`} matches the beginning of the whole input
|
||||
|
||||
@item @samp{\'} matches the end of the whole input
|
||||
|
||||
@end enumerate
|
||||
|
||||
|
||||
Grouping is performed with parentheses @samp{()}. An unmatched @samp{)} matches just itself. A backslash followed by a digit acts as a back-reference and matches the same thing as the previous grouped expression indicated by that number. For example @samp{\2} matches the second group expression. The order of group expressions is determined by the position of their opening parenthesis @samp{(}.
|
||||
|
||||
The alternation operator is @samp{|}.
|
||||
|
||||
The characters @samp{^} and @samp{$} always represent the beginning and end of a string respectively, except within square brackets. Within brackets, @samp{^} can be used to invert the membership of the character class being specified.
|
||||
|
||||
|
||||
The characters @samp{*}, @samp{+} and @samp{?} are special anywhere in a regular expression.
|
||||
|
||||
|
||||
Intervals are specified by @samp{@{} and @samp{@}}.
|
||||
Invalid intervals are treated as literals, for example @samp{a@{1} is treated as @samp{a\@{1}
|
||||
|
||||
The longest possible match is returned; this applies to the regular expression as a whole and (subject to this constraint) to subexpressions within groups.
|
||||
|
||||
|
||||
@node egrep regular expression syntax
|
||||
@subsection @samp{egrep} regular expression syntax
|
||||
This is a synonym for posix-egrep.
|
||||
This is a synonym for egrep.
|
||||
@node posix-extended regular expression syntax
|
||||
@subsection @samp{posix-extended} regular expression syntax
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
## Copyright (C) 1996-2024 Free Software Foundation, Inc.
|
||||
## Copyright (C) 1996-2026 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
|
||||
@ -28,11 +28,11 @@ man_MANS = find.1
|
||||
|
||||
EXTRA_DIST = defs.h sharefile.h print.h $(man_MANS)
|
||||
AM_CPPFLAGS = -I../gl/lib -I$(top_srcdir)/lib -I$(top_srcdir)/gl/lib -DLOCALEDIR=\"$(localedir)\"
|
||||
LDADD = libfindtools.a ../lib/libfind.a ../gl/lib/libgnulib.a $(LIBINTL) $(LIB_CLOCK_GETTIME) $(LIB_EACCESS) $(LIB_SELINUX) $(LIB_CLOSE) $(MODF_LIBM) $(FINDLIBS) $(GETHOSTNAME_LIB) $(LIB_EACCESS) $(LIB_SETLOCALE_NULL) $(LIB_MBRTOWC)
|
||||
LDADD = libfindtools.a ../lib/libfind.a ../gl/lib/libgnulib.a $(LIBINTL) $(CLOCK_TIME_LIB) $(EUIDACCESS_LIBGEN) $(LIB_SELINUX) $(MODF_LIBM) $(FINDLIBS) $(GETHOSTNAME_LIB) $(EUIDACCESS_LIBGEN) $(SETLOCALE_NULL_LIB) $(MBRTOWC_LIB)
|
||||
# gnulib advises we link against <first> because we use <second>:
|
||||
# $(GETHOSTNAME_LIB) uname
|
||||
# $(LIB_CLOCK_GETTIME) (some indirect dependency)
|
||||
# $(LIB_EACCESS) faccessat
|
||||
# $(CLOCK_TIME_LIB) gettime
|
||||
# $(EUIDACCESS_LIBGEN) faccessat
|
||||
# $(LIB_SELINUX) selinux-h
|
||||
# $(MODF_LIBM) modf
|
||||
|
||||
@ -40,7 +40,7 @@ SUBDIRS = . testsuite
|
||||
|
||||
noinst_PROGRAMS = getlimits
|
||||
|
||||
dist-hook: findutils-check-manpages
|
||||
check-local: findutils-check-manpages
|
||||
|
||||
# Clean coverage files generated by running binaries built with
|
||||
# gcc -fprofile-arcs -ftest-coverage
|
||||
@ -50,4 +50,4 @@ coverage-clean:
|
||||
clean-local: coverage-clean
|
||||
|
||||
findutils-check-manpages:
|
||||
$(top_srcdir)/build-aux/man-lint.sh $(srcdir) $(man_MANS)
|
||||
env GROFF=$(GROFF) $(top_srcdir)/build-aux/man-lint.sh $(srcdir) $(man_MANS)
|
||||
|
||||
116
find/defs.h
116
find/defs.h
@ -1,5 +1,5 @@
|
||||
/* defs.h -- data types and declarations.
|
||||
Copyright (C) 1990-2024 Free Software Foundation, Inc.
|
||||
Copyright (C) 1990-2026 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
|
||||
@ -38,14 +38,14 @@ Please stop compiling the program now
|
||||
|
||||
/* XXX: some of these includes probably don't belong in a common header file */
|
||||
# include <sys/stat.h>
|
||||
# include <stdio.h> /* for FILE* */
|
||||
# include <stdio.h> /* for FILE* */
|
||||
# include <string.h>
|
||||
# include <stdlib.h>
|
||||
# include <unistd.h>
|
||||
# include <time.h>
|
||||
# include <limits.h> /* for CHAR_BIT */
|
||||
# include <stdbool.h> /* for bool */
|
||||
# include <stdint.h> /* for uintmax_t */
|
||||
# include <limits.h> /* for CHAR_BIT */
|
||||
# include <stdbool.h> /* for bool */
|
||||
# include <stdint.h> /* for uintmax_t */
|
||||
# include <sys/stat.h> /* S_ISUID etc. */
|
||||
# include <selinux/selinux.h>
|
||||
|
||||
@ -73,11 +73,11 @@ void set_stat_placeholders (struct stat *p);
|
||||
int get_statinfo (const char *pathname, const char *name, struct stat *p);
|
||||
|
||||
|
||||
# define MODE_WXUSR (S_IWUSR | S_IXUSR)
|
||||
# define MODE_R (S_IRUSR | S_IRGRP | S_IROTH)
|
||||
# define MODE_RW (S_IWUSR | S_IWGRP | S_IWOTH | MODE_R)
|
||||
# define MODE_RWX (S_IXUSR | S_IXGRP | S_IXOTH | MODE_RW)
|
||||
# define MODE_ALL (S_ISUID | S_ISGID | S_ISVTX | MODE_RWX)
|
||||
# define MODE_WXUSR (S_IWUSR | S_IXUSR)
|
||||
# define MODE_R (S_IRUSR | S_IRGRP | S_IROTH)
|
||||
# define MODE_RW (S_IWUSR | S_IWGRP | S_IWOTH | MODE_R)
|
||||
# define MODE_RWX (S_IXUSR | S_IXGRP | S_IXOTH | MODE_RW)
|
||||
# define MODE_ALL (S_ISUID | S_ISGID | S_ISVTX | MODE_RWX)
|
||||
|
||||
|
||||
struct predicate;
|
||||
@ -87,7 +87,7 @@ struct options;
|
||||
typedef bool (*PRED_FUNC)(const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr);
|
||||
|
||||
/* The number of seconds in a day. */
|
||||
# define DAYSECS 86400
|
||||
# define DAYSECS 86400
|
||||
|
||||
/* Argument structures for predicates. */
|
||||
|
||||
@ -128,7 +128,7 @@ enum predicate_precedence
|
||||
struct long_val
|
||||
{
|
||||
enum comparison_type kind;
|
||||
bool negative; /* Defined only when representing time_t. */
|
||||
bool negative; /* Defined only when representing time_t. */
|
||||
uintmax_t l_val;
|
||||
};
|
||||
|
||||
@ -191,14 +191,14 @@ struct time_val
|
||||
|
||||
struct exec_val
|
||||
{
|
||||
bool multiple; /* -exec {} \+ denotes multiple argument. */
|
||||
bool multiple; /* -exec {} \+ denotes multiple argument. */
|
||||
struct buildcmd_control ctl;
|
||||
struct buildcmd_state state;
|
||||
char **replace_vec; /* Command arguments (for ";" style) */
|
||||
char **replace_vec; /* Command arguments (for ";" style) */
|
||||
int num_args;
|
||||
bool close_stdin; /* If true, close stdin in the child. */
|
||||
bool close_stdin; /* If true, close stdin in the child. */
|
||||
struct saved_cwd *wd_for_exec; /* What directory to perform the exec in. */
|
||||
int last_child_status; /* Status of the most recent child. */
|
||||
int last_child_status; /* Status of the most recent child. */
|
||||
};
|
||||
|
||||
/* The format string for a -printf or -fprintf is chopped into one or
|
||||
@ -209,26 +209,26 @@ struct exec_val
|
||||
/* Special values for the `kind' field of `struct segment'. */
|
||||
enum SegmentKind
|
||||
{
|
||||
KIND_PLAIN=0, /* Segment containing just plain text. */
|
||||
KIND_STOP=1, /* \c -- stop printing and flush output. */
|
||||
KIND_FORMAT, /* Regular format */
|
||||
KIND_PLAIN=0, /* Segment containing just plain text. */
|
||||
KIND_STOP=1, /* \c -- stop printing and flush output. */
|
||||
KIND_FORMAT, /* Regular format */
|
||||
};
|
||||
|
||||
struct segment
|
||||
{
|
||||
enum SegmentKind segkind; /* KIND_FORMAT, KIND_PLAIN, KIND_STOP */
|
||||
char format_char[2]; /* Format chars if kind is KIND_FORMAT */
|
||||
char *text; /* Plain text or `%' format string. */
|
||||
int text_len; /* Length of `text'. */
|
||||
struct segment *next; /* Next segment for this predicate. */
|
||||
char format_char[2]; /* Format chars if kind is KIND_FORMAT */
|
||||
char *text; /* Plain text or `%' format string. */
|
||||
int text_len; /* Length of `text'. */
|
||||
struct segment *next; /* Next segment for this predicate. */
|
||||
};
|
||||
|
||||
struct format_val
|
||||
{
|
||||
struct segment *segment; /* Linked list of segments. */
|
||||
FILE *stream; /* Output stream to print on. */
|
||||
const char *filename; /* We need the filename for error messages. */
|
||||
bool dest_is_tty; /* True if the destination is a terminal. */
|
||||
struct segment *segment; /* Linked list of segments. */
|
||||
FILE *stream; /* Output stream to print on. */
|
||||
const char *filename; /* We need the filename for error messages. */
|
||||
bool dest_is_tty; /* True if the destination is a terminal. */
|
||||
struct quoting_options *quote_opts;
|
||||
};
|
||||
|
||||
@ -304,17 +304,17 @@ struct predicate
|
||||
Next to each member are listed the predicates that use it. */
|
||||
union
|
||||
{
|
||||
const char *str; /* fstype [i]lname [i]name [i]path */
|
||||
const char *str; /* fstype [i]lname [i]name [i]path */
|
||||
struct re_pattern_buffer *regex; /* regex */
|
||||
struct exec_val exec_vec; /* exec ok */
|
||||
struct long_val numinfo; /* gid inum links uid */
|
||||
struct size_val size; /* size */
|
||||
uid_t uid; /* user */
|
||||
gid_t gid; /* group */
|
||||
struct time_val reftime; /* newer newerXY anewer cnewer mtime atime ctime mmin amin cmin */
|
||||
struct perm_val perm; /* perm */
|
||||
struct exec_val exec_vec; /* exec ok */
|
||||
struct long_val numinfo; /* gid inum links uid */
|
||||
struct size_val size; /* size */
|
||||
uid_t uid; /* user */
|
||||
gid_t gid; /* group */
|
||||
struct time_val reftime; /* newer newerXY anewer cnewer mtime atime ctime mmin amin cmin */
|
||||
struct perm_val perm; /* perm */
|
||||
struct samefile_file_id samefileid; /* samefile */
|
||||
bool types[FTYPE_COUNT]; /* file type(s) */
|
||||
bool types[FTYPE_COUNT]; /* file type(s) */
|
||||
struct format_val printf_vec; /* printf fprintf fprint ls fls print0 fprint0 print */
|
||||
char *scontext; /* security context */
|
||||
} args;
|
||||
@ -347,9 +347,9 @@ bool is_fts_cwdfd_enabled(void);
|
||||
*/
|
||||
enum SymlinkOption
|
||||
{
|
||||
SYMLINK_NEVER_DEREF, /* Option -P */
|
||||
SYMLINK_ALWAYS_DEREF, /* Option -L */
|
||||
SYMLINK_DEREF_ARGSONLY /* Option -H */
|
||||
SYMLINK_NEVER_DEREF, /* Option -P */
|
||||
SYMLINK_ALWAYS_DEREF, /* Option -L */
|
||||
SYMLINK_DEREF_ARGSONLY /* Option -H */
|
||||
};
|
||||
|
||||
void set_follow_state (enum SymlinkOption opt);
|
||||
@ -364,20 +364,20 @@ dev_t * get_mounted_devices (size_t *);
|
||||
|
||||
enum arg_type
|
||||
{
|
||||
ARG_OPTION, /* regular options like -maxdepth */
|
||||
ARG_NOOP, /* does nothing, returns true, internal use only */
|
||||
ARG_POSITIONAL_OPTION, /* options whose position is important (-follow) */
|
||||
ARG_TEST, /* a like -name */
|
||||
ARG_SPECIAL_PARSE, /* complex to parse, don't eat the test name before calling parse_xx(). */
|
||||
ARG_PUNCTUATION, /* like -o or ( */
|
||||
ARG_ACTION /* like -print */
|
||||
ARG_OPTION, /* regular options like -maxdepth */
|
||||
ARG_NOOP, /* does nothing, returns true, internal use only */
|
||||
ARG_POSITIONAL_OPTION, /* options whose position is important (-follow) */
|
||||
ARG_TEST, /* a like -name */
|
||||
ARG_SPECIAL_PARSE, /* complex to parse, don't eat the test name before calling parse_xx(). */
|
||||
ARG_PUNCTUATION, /* like -o or ( */
|
||||
ARG_ACTION /* like -print */
|
||||
};
|
||||
|
||||
|
||||
struct parser_table;
|
||||
/* Pointer to a parser function. */
|
||||
typedef bool (*PARSE_FUNC)(const struct parser_table *p,
|
||||
char *argv[], int *arg_ptr);
|
||||
char *argv[], int *arg_ptr);
|
||||
struct parser_table
|
||||
{
|
||||
enum arg_type type;
|
||||
@ -462,11 +462,6 @@ PREDICATEFUNCTION pred_context;
|
||||
bool pred_quit (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
|
||||
_GL_ATTRIBUTE_NORETURN;
|
||||
|
||||
|
||||
|
||||
char *find_pred_name (PRED_FUNC pred_func);
|
||||
|
||||
|
||||
void print_predicate (FILE *fp, const struct predicate *p);
|
||||
void print_tree (FILE*, struct predicate *node, int indent);
|
||||
void print_list (FILE*, struct predicate *node);
|
||||
@ -482,7 +477,7 @@ struct predicate * get_eval_tree (void);
|
||||
struct predicate *get_new_pred_noarg (const struct parser_table *entry);
|
||||
struct predicate *get_new_pred (const struct parser_table *entry);
|
||||
struct predicate *get_new_pred_chk_op (const struct parser_table *entry,
|
||||
const char *arg);
|
||||
const char *arg);
|
||||
float calculate_derived_rates (struct predicate *p);
|
||||
|
||||
/* util.c */
|
||||
@ -507,7 +502,7 @@ int process_leading_options (int argc, char *argv[]);
|
||||
void set_option_defaults (struct options *p);
|
||||
|
||||
# if 0
|
||||
# define apply_predicate(pathname, stat_buf_ptr, node) \
|
||||
# define apply_predicate(pathname, stat_buf_ptr, node) \
|
||||
(*(node)->pred_func)((pathname), (stat_buf_ptr), (node))
|
||||
# else
|
||||
bool apply_predicate(const char *pathname, struct stat *stat_buf, struct predicate *p);
|
||||
@ -554,8 +549,11 @@ struct options
|
||||
are non-directories. */
|
||||
bool no_leaf_check;
|
||||
|
||||
/* If true, skip files on other devices. */
|
||||
bool mount;
|
||||
|
||||
/* If true, don't cross filesystem boundaries. */
|
||||
bool stay_on_filesystem;
|
||||
bool xdev;
|
||||
|
||||
/* If true, we ignore the problem where we find that a directory entry
|
||||
* no longer exists by the time we get around to processing it.
|
||||
@ -577,7 +575,7 @@ struct options
|
||||
*/
|
||||
bool posixly_correct;
|
||||
|
||||
struct timespec start_time; /* Time at start of execution. */
|
||||
struct timespec start_time; /* Time at start of execution. */
|
||||
|
||||
/* Either one day before now (the default), or the start of today (if -daystart is given). */
|
||||
struct timespec cur_day_start;
|
||||
@ -585,7 +583,7 @@ struct options
|
||||
/* If true, cur_day_start has been adjusted to the start of the day. */
|
||||
bool full_days;
|
||||
|
||||
int output_block_size; /* Output block size. */
|
||||
int output_block_size; /* Output block size. */
|
||||
|
||||
/* bitmask for debug options */
|
||||
unsigned long debug_options;
|
||||
@ -638,7 +636,7 @@ struct state
|
||||
|
||||
/* If true, we know the type of the current path. */
|
||||
bool have_type;
|
||||
mode_t type; /* this is the actual type */
|
||||
mode_t type; /* this is the actual type */
|
||||
|
||||
/* The file being operated on, relative to the current directory.
|
||||
Used for stat, readlink, remove, and opendir. */
|
||||
@ -653,7 +651,7 @@ struct state
|
||||
int starting_path_length;
|
||||
|
||||
/* If true, don't descend past current directory.
|
||||
Can be set by -prune, -maxdepth, and -xdev/-mount. */
|
||||
Can be set by -prune, -maxdepth, -mount and -xdev. */
|
||||
bool stop_at_current_level;
|
||||
|
||||
/* Status value to return to system. */
|
||||
|
||||
176
find/exec.c
176
find/exec.c
@ -1,5 +1,5 @@
|
||||
/* exec.c -- Implementation of -exec, -execdir, -ok, -okdir.
|
||||
Copyright (C) 1990-2024 Free Software Foundation, Inc.
|
||||
Copyright (C) 1990-2026 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
|
||||
@ -64,30 +64,30 @@ record_exec_dir (struct exec_val *execp)
|
||||
if (!execp->state.todo)
|
||||
{
|
||||
/* working directory not already known, so must be a *dir variant,
|
||||
and this must be the first arg we added. However, this may
|
||||
be -execdir foo {} \; (i.e. not multiple). */
|
||||
and this must be the first arg we added. However, this may
|
||||
be -execdir foo {} \; (i.e. not multiple). */
|
||||
assert (!execp->state.todo);
|
||||
|
||||
/* Record the WD. If we're using -L or fts chooses to do so for
|
||||
any other reason, state.cwd_dir_fd may in fact not be the
|
||||
directory containing the target file. When this happens,
|
||||
rel_path will contain directory components (since it is the
|
||||
path from state.cwd_dir_fd to the target file).
|
||||
any other reason, state.cwd_dir_fd may in fact not be the
|
||||
directory containing the target file. When this happens,
|
||||
rel_path will contain directory components (since it is the
|
||||
path from state.cwd_dir_fd to the target file).
|
||||
|
||||
We deal with this by extracting any directory part and using
|
||||
that to adjust what goes into execp->wd_for_exec.
|
||||
We deal with this by extracting any directory part and using
|
||||
that to adjust what goes into execp->wd_for_exec.
|
||||
*/
|
||||
if (strchr (state.rel_pathname, '/'))
|
||||
{
|
||||
char *dir = mdir_name (state.rel_pathname);
|
||||
bool result = initialize_wd_for_exec (execp, state.cwd_dir_fd, dir);
|
||||
free (dir);
|
||||
return result;
|
||||
}
|
||||
{
|
||||
char *dir = mdir_name (state.rel_pathname);
|
||||
bool result = initialize_wd_for_exec (execp, state.cwd_dir_fd, dir);
|
||||
free (dir);
|
||||
return result;
|
||||
}
|
||||
else
|
||||
{
|
||||
return initialize_wd_for_exec (execp, state.cwd_dir_fd, ".");
|
||||
}
|
||||
{
|
||||
return initialize_wd_for_exec (execp, state.cwd_dir_fd, ".");
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -126,7 +126,7 @@ impl_pred_exec (const char *pathname,
|
||||
target = buf = base_name (state.rel_pathname);
|
||||
if ('/' == target[0])
|
||||
{
|
||||
/* find / execdir ls -d {} \; */
|
||||
/* find / -execdir ls -d {} \; */
|
||||
prefix = NULL;
|
||||
pfxlen = 0;
|
||||
}
|
||||
@ -217,13 +217,13 @@ impl_pred_exec (const char *pathname,
|
||||
|
||||
Possible returns:
|
||||
|
||||
ret errno status(h) status(l)
|
||||
ret errno status(h) status(l)
|
||||
|
||||
pid x signal# 0177 stopped
|
||||
pid x exit arg 0 term by _exit
|
||||
pid x 0 signal # term by signal
|
||||
-1 EINTR parent got signal
|
||||
-1 other some other kind of error
|
||||
pid x signal# 0177 stopped
|
||||
pid x exit arg 0 term by _exit
|
||||
pid x 0 signal # term by signal
|
||||
-1 EINTR parent got signal
|
||||
-1 other some other kind of error
|
||||
|
||||
Return true only if the pid matches, status(l) is
|
||||
zero, and the exit arg (status high) is 0.
|
||||
@ -237,27 +237,27 @@ prep_child_for_exec (bool close_stdin, const struct saved_cwd *wd)
|
||||
const char inputfile[] = "/dev/null";
|
||||
|
||||
if (close (0) < 0)
|
||||
{
|
||||
error (0, errno, _("Cannot close standard input"));
|
||||
ok = false;
|
||||
}
|
||||
{
|
||||
error (0, errno, _("Cannot close standard input"));
|
||||
ok = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (open (inputfile, O_RDONLY
|
||||
{
|
||||
if (open (inputfile, O_RDONLY
|
||||
#if defined O_LARGEFILE
|
||||
|O_LARGEFILE
|
||||
|O_LARGEFILE
|
||||
#endif
|
||||
) < 0)
|
||||
{
|
||||
/* This is not entirely fatal, since
|
||||
* executing the child with a closed
|
||||
* stdin is almost as good as executing it
|
||||
* with its stdin attached to /dev/null.
|
||||
*/
|
||||
error (0, errno, "%s", safely_quote_err_filename (0, inputfile));
|
||||
/* do not set ok=false, it is OK to continue anyway. */
|
||||
}
|
||||
}
|
||||
) < 0)
|
||||
{
|
||||
/* This is not entirely fatal, since
|
||||
* executing the child with a closed
|
||||
* stdin is almost as good as executing it
|
||||
* with its stdin attached to /dev/null.
|
||||
*/
|
||||
error (0, errno, "%s", safely_quote_err_filename (0, inputfile));
|
||||
/* do not set ok=false, it is OK to continue anyway. */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Even if DebugSearch is set, don't announce our change of
|
||||
@ -268,8 +268,8 @@ prep_child_for_exec (bool close_stdin, const struct saved_cwd *wd)
|
||||
if (0 != restore_cwd (wd))
|
||||
{
|
||||
error (0, errno, _("Failed to change directory%s%s"),
|
||||
(wd->desc < 0 && wd->name) ? ": " : "",
|
||||
(wd->desc < 0 && wd->name) ? wd->name : "");
|
||||
(wd->desc < 0 && wd->name) ? ": " : "",
|
||||
(wd->desc < 0 && wd->name) ? wd->name : "");
|
||||
ok = false;
|
||||
}
|
||||
return ok;
|
||||
@ -283,8 +283,8 @@ launch (struct buildcmd_control *ctl, void *usercontext, int argc, char **argv)
|
||||
static int first_time = 1;
|
||||
struct exec_val *execp = usercontext;
|
||||
|
||||
(void) ctl; /* silence compiler warning */
|
||||
(void) argc; /* silence compiler warning */
|
||||
(void) ctl; /* silence compiler warning */
|
||||
(void) argc; /* silence compiler warning */
|
||||
|
||||
if (options.debug_options & DebugExec)
|
||||
{
|
||||
@ -292,10 +292,10 @@ launch (struct buildcmd_control *ctl, void *usercontext, int argc, char **argv)
|
||||
fprintf (stderr, "DebugExec: launching process (argc=%" PRIuMAX "):",
|
||||
(uintmax_t) execp->state.cmd_argc - 1);
|
||||
for (i=0; i<execp->state.cmd_argc -1; ++i)
|
||||
{
|
||||
fprintf (stderr, " %s",
|
||||
safely_quote_err_filename (0, execp->state.cmd_argv[i]));
|
||||
}
|
||||
{
|
||||
fprintf (stderr, " %s",
|
||||
safely_quote_err_filename (0, execp->state.cmd_argv[i]));
|
||||
}
|
||||
fprintf (stderr, "\n");
|
||||
}
|
||||
|
||||
@ -318,54 +318,54 @@ launch (struct buildcmd_control *ctl, void *usercontext, int argc, char **argv)
|
||||
/* We are the child. */
|
||||
assert (NULL != execp->wd_for_exec);
|
||||
if (!prep_child_for_exec (execp->close_stdin, execp->wd_for_exec))
|
||||
{
|
||||
_exit (1);
|
||||
}
|
||||
{
|
||||
_exit (1);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (fd_leak_check_is_enabled ())
|
||||
{
|
||||
complain_about_leaky_fds ();
|
||||
}
|
||||
}
|
||||
{
|
||||
if (fd_leak_check_is_enabled ())
|
||||
{
|
||||
complain_about_leaky_fds ();
|
||||
}
|
||||
}
|
||||
|
||||
if (bc_args_exceed_testing_limit (argv))
|
||||
errno = E2BIG;
|
||||
errno = E2BIG;
|
||||
else
|
||||
execvp (argv[0], argv);
|
||||
execvp (argv[0], argv);
|
||||
/* TODO: use a pipe to pass back the errno value, like xargs does */
|
||||
error (0, errno, "%s",
|
||||
safely_quote_err_filename (0, argv[0]));
|
||||
safely_quote_err_filename (0, argv[0]));
|
||||
_exit (1);
|
||||
}
|
||||
|
||||
while (waitpid (child_pid, &(execp->last_child_status), 0) == (pid_t) -1)
|
||||
{
|
||||
if (errno != EINTR)
|
||||
{
|
||||
error (0, errno, _("error waiting for %s"),
|
||||
safely_quote_err_filename (0, argv[0]));
|
||||
state.exit_status = EXIT_FAILURE;
|
||||
return 0; /* FAIL */
|
||||
}
|
||||
{
|
||||
error (0, errno, _("error waiting for %s"),
|
||||
safely_quote_err_filename (0, argv[0]));
|
||||
state.exit_status = EXIT_FAILURE;
|
||||
return 0; /* FAIL */
|
||||
}
|
||||
}
|
||||
|
||||
if (WIFSIGNALED (execp->last_child_status))
|
||||
{
|
||||
error (0, 0, _("%s terminated by signal %d"),
|
||||
quotearg_n_style (0, options.err_quoting_style, argv[0]),
|
||||
WTERMSIG (execp->last_child_status));
|
||||
quotearg_n_style (0, options.err_quoting_style, argv[0]),
|
||||
WTERMSIG (execp->last_child_status));
|
||||
|
||||
if (execp->multiple)
|
||||
{
|
||||
/* -exec \; just returns false if the invoked command fails.
|
||||
* -exec {} + returns true if the invoked command fails, but
|
||||
* sets the program exit status.
|
||||
*/
|
||||
state.exit_status = EXIT_FAILURE;
|
||||
}
|
||||
{
|
||||
/* -exec \; just returns false if the invoked command fails.
|
||||
* -exec {} + returns true if the invoked command fails, but
|
||||
* sets the program exit status.
|
||||
*/
|
||||
state.exit_status = EXIT_FAILURE;
|
||||
}
|
||||
|
||||
return 1; /* OK */
|
||||
return 1; /* OK */
|
||||
}
|
||||
|
||||
int ex = WEXITSTATUS (execp->last_child_status);
|
||||
@ -380,22 +380,22 @@ launch (struct buildcmd_control *ctl, void *usercontext, int argc, char **argv)
|
||||
|
||||
if (0 == ex)
|
||||
{
|
||||
return 1; /* OK */
|
||||
return 1; /* OK */
|
||||
}
|
||||
else
|
||||
{
|
||||
if (execp->multiple)
|
||||
{
|
||||
/* -exec \; just returns false if the invoked command fails.
|
||||
* -exec {} + returns true if the invoked command fails, but
|
||||
* sets the program exit status.
|
||||
*/
|
||||
state.exit_status = EXIT_FAILURE;
|
||||
}
|
||||
{
|
||||
/* -exec \; just returns false if the invoked command fails.
|
||||
* -exec {} + returns true if the invoked command fails, but
|
||||
* sets the program exit status.
|
||||
*/
|
||||
state.exit_status = EXIT_FAILURE;
|
||||
}
|
||||
/* The child failed, but this is the exec callback. We
|
||||
* don't want to run the child again in this case anwyay.
|
||||
*/
|
||||
return 1; /* FAIL (but don't try again) */
|
||||
return 1; /* FAIL (but don't try again) */
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
834
find/find.1
834
find/find.1
File diff suppressed because it is too large
Load Diff
@ -1,5 +1,5 @@
|
||||
/* finddata.c -- global data for "find".
|
||||
Copyright (C) 1990-2024 Free Software Foundation, Inc.
|
||||
Copyright (C) 1990-2026 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
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/* fstype.c -- determine type of file systems that files are on
|
||||
Copyright (C) 1990-2024 Free Software Foundation, Inc.
|
||||
Copyright (C) 1990-2026 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
|
||||
@ -27,9 +27,6 @@
|
||||
/* system headers. */
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#if HAVE_MNTENT_H
|
||||
# include <mntent.h>
|
||||
#endif
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@ -101,7 +98,7 @@ in_afs (char *path)
|
||||
|
||||
if (pioctl (path, VIOC_FILE_CELL_NAME, &vi, 1)
|
||||
&& (errno == EINVAL || errno == ENOENT))
|
||||
return 0;
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
#endif /* AFS */
|
||||
@ -148,7 +145,7 @@ filesystem_type (const struct stat *statp, const char *path)
|
||||
if (current_fstype != NULL)
|
||||
{
|
||||
if (fstype_known && statp->st_dev == current_dev)
|
||||
return current_fstype; /* Cached value. */
|
||||
return current_fstype; /* Cached value. */
|
||||
free (current_fstype);
|
||||
}
|
||||
current_dev = statp->st_dev;
|
||||
@ -162,25 +159,25 @@ is_used_fs_type(const char *name)
|
||||
if (0 == strcmp("afs", name))
|
||||
{
|
||||
/* I guess AFS may not appear in /etc/mtab (or equivalent) but still be in use,
|
||||
so assume we always need to check for AFS. */
|
||||
so assume we always need to check for AFS. */
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
const struct mount_entry *entries = get_file_system_list(false);
|
||||
if (entries)
|
||||
{
|
||||
const struct mount_entry *entry;
|
||||
for (entry = entries; entry; entry = entry->me_next)
|
||||
{
|
||||
if (0 == strcmp(name, entry->me_type))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
{
|
||||
const struct mount_entry *entry;
|
||||
for (entry = entries; entry; entry = entry->me_next)
|
||||
{
|
||||
if (0 == strcmp(name, entry->me_type))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return true;
|
||||
}
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@ -194,16 +191,16 @@ set_fstype_devno (struct mount_entry *p)
|
||||
{
|
||||
set_stat_placeholders (&stbuf);
|
||||
if (0 == (options.xstat)(p->me_mountdir, &stbuf))
|
||||
{
|
||||
p->me_dev = stbuf.st_dev;
|
||||
return 0;
|
||||
}
|
||||
{
|
||||
p->me_dev = stbuf.st_dev;
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return 0; /* not needed */
|
||||
return 0; /* not needed */
|
||||
}
|
||||
|
||||
/* Return a newly allocated string naming the type of file system that the
|
||||
@ -242,21 +239,21 @@ file_system_type_uncached (const struct stat *statp, const char *path,
|
||||
{
|
||||
#ifdef MNTTYPE_IGNORE
|
||||
if (!strcmp (entry->me_type, MNTTYPE_IGNORE))
|
||||
continue;
|
||||
continue;
|
||||
#endif
|
||||
if (0 == set_fstype_devno (entry))
|
||||
{
|
||||
if (entry->me_dev == statp->st_dev)
|
||||
{
|
||||
best = entry;
|
||||
/* Don't exit the loop, because some systems (for
|
||||
example Linux-based systems in which /etc/mtab is a
|
||||
symlink to /proc/mounts) can have duplicate entries
|
||||
in the filesystem list. This happens most frequently
|
||||
for /.
|
||||
*/
|
||||
}
|
||||
}
|
||||
{
|
||||
if (entry->me_dev == statp->st_dev)
|
||||
{
|
||||
best = entry;
|
||||
/* Don't exit the loop, because some systems (for
|
||||
example Linux-based systems in which /etc/mtab is a
|
||||
symlink to /proc/mounts) can have duplicate entries
|
||||
in the filesystem list. This happens most frequently
|
||||
for /.
|
||||
*/
|
||||
}
|
||||
}
|
||||
}
|
||||
if (best)
|
||||
{
|
||||
@ -290,19 +287,19 @@ get_mounted_devices (size_t *n)
|
||||
{
|
||||
void *p = extendbuf (result, sizeof(dev_t)*(used+1), &alloc_size);
|
||||
if (p)
|
||||
{
|
||||
result = p;
|
||||
if (0 == set_fstype_devno (entry))
|
||||
{
|
||||
result[used] = entry->me_dev;
|
||||
++used;
|
||||
}
|
||||
}
|
||||
{
|
||||
result = p;
|
||||
if (0 == set_fstype_devno (entry))
|
||||
{
|
||||
result[used] = entry->me_dev;
|
||||
++used;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
free (result);
|
||||
result = NULL;
|
||||
}
|
||||
{
|
||||
free (result);
|
||||
result = NULL;
|
||||
}
|
||||
}
|
||||
free_file_system_list (entries);
|
||||
if (result)
|
||||
|
||||
303
find/ftsfind.c
303
find/ftsfind.c
@ -1,5 +1,5 @@
|
||||
/* find -- search for files in a directory hierarchy (fts version)
|
||||
Copyright (C) 1990-2024 Free Software Foundation, Inc.
|
||||
Copyright (C) 1990-2026 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
|
||||
@ -81,10 +81,10 @@ left_dir (void)
|
||||
if (ftsoptions & FTS_CWDFD)
|
||||
{
|
||||
if (curr_fd >= 0)
|
||||
{
|
||||
close (curr_fd);
|
||||
curr_fd = -1;
|
||||
}
|
||||
{
|
||||
close (curr_fd);
|
||||
curr_fd = -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -106,23 +106,23 @@ inside_dir (int dir_fd)
|
||||
|
||||
state.cwd_dir_fd = dir_fd;
|
||||
if (curr_fd < 0)
|
||||
{
|
||||
if (AT_FDCWD == dir_fd)
|
||||
{
|
||||
curr_fd = AT_FDCWD;
|
||||
}
|
||||
else if (dir_fd >= 0)
|
||||
{
|
||||
curr_fd = dup_cloexec (dir_fd);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* curr_fd is invalid, but dir_fd is also invalid.
|
||||
* This should not have happened.
|
||||
*/
|
||||
assert (curr_fd >= 0 || dir_fd >= 0);
|
||||
}
|
||||
}
|
||||
{
|
||||
if (AT_FDCWD == dir_fd)
|
||||
{
|
||||
curr_fd = AT_FDCWD;
|
||||
}
|
||||
else if (dir_fd >= 0)
|
||||
{
|
||||
curr_fd = dup_cloexec (dir_fd);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* curr_fd is invalid, but dir_fd is also invalid.
|
||||
* This should not have happened.
|
||||
*/
|
||||
assert (curr_fd >= 0 || dir_fd >= 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -188,27 +188,6 @@ visit (FTS *p, FTSENT *ent, struct stat *pstat)
|
||||
}
|
||||
}
|
||||
|
||||
static const char*
|
||||
partial_quotearg_n (int n, char *s, size_t len, enum quoting_style style)
|
||||
{
|
||||
if (0 == len)
|
||||
{
|
||||
return quotearg_n_style (n, style, "");
|
||||
}
|
||||
else
|
||||
{
|
||||
char saved;
|
||||
const char *result;
|
||||
|
||||
saved = s[len];
|
||||
s[len] = 0;
|
||||
result = quotearg_n_style (n, style, s);
|
||||
s[len] = saved;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* We've detected a file system loop. This is caused by one of
|
||||
* two things:
|
||||
*
|
||||
@ -218,7 +197,7 @@ partial_quotearg_n (int n, char *s, size_t len, enum quoting_style style)
|
||||
*
|
||||
* 2. We have hit a real cycle in the directory hierarchy. In this
|
||||
* case, we issue a diagnostic message (POSIX requires this) and we
|
||||
* skip that directory entry.
|
||||
* will skip that directory entry.
|
||||
*/
|
||||
static void
|
||||
issue_loop_warning (FTSENT * ent)
|
||||
@ -226,8 +205,8 @@ issue_loop_warning (FTSENT * ent)
|
||||
if (S_ISLNK(ent->fts_statp->st_mode))
|
||||
{
|
||||
error (0, 0,
|
||||
_("Symbolic link %s is part of a loop in the directory hierarchy; we have already visited the directory to which it points."),
|
||||
safely_quote_err_filename (0, ent->fts_path));
|
||||
_("Symbolic link %s is part of a loop in the directory hierarchy; we have already visited the directory to which it points."),
|
||||
safely_quote_err_filename (0, ent->fts_path));
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -240,13 +219,9 @@ issue_loop_warning (FTSENT * ent)
|
||||
* to /a/b/c.
|
||||
*/
|
||||
error (0, 0,
|
||||
_("File system loop detected; "
|
||||
"%s is part of the same file system loop as %s."),
|
||||
safely_quote_err_filename (0, ent->fts_path),
|
||||
partial_quotearg_n (1,
|
||||
ent->fts_cycle->fts_path,
|
||||
ent->fts_cycle->fts_pathlen,
|
||||
options.err_quoting_style));
|
||||
_("File system loop detected; "
|
||||
"the following directory is part of the cycle: %s"),
|
||||
safely_quote_err_filename (0, ent->fts_path));
|
||||
}
|
||||
}
|
||||
|
||||
@ -274,14 +249,14 @@ consider_visiting (FTS *p, FTSENT *ent)
|
||||
|
||||
if (options.debug_options & DebugSearch)
|
||||
fprintf (stderr,
|
||||
"consider_visiting (early): %s: "
|
||||
"fts_info=%-6s, fts_level=%2d, prev_depth=%d "
|
||||
"fts_path=%s, fts_accpath=%s\n",
|
||||
quotearg_n_style (0, options.err_quoting_style, ent->fts_path),
|
||||
get_fts_info_name (ent->fts_info),
|
||||
(int)ent->fts_level, prev_depth,
|
||||
quotearg_n_style (1, options.err_quoting_style, ent->fts_path),
|
||||
quotearg_n_style (2, options.err_quoting_style, ent->fts_accpath));
|
||||
"consider_visiting (early): %s: "
|
||||
"fts_info=%-6s, fts_level=%2d, prev_depth=%d "
|
||||
"fts_path=%s, fts_accpath=%s\n",
|
||||
quotearg_n_style (0, options.err_quoting_style, ent->fts_path),
|
||||
get_fts_info_name (ent->fts_info),
|
||||
(int)ent->fts_level, prev_depth,
|
||||
quotearg_n_style (1, options.err_quoting_style, ent->fts_path),
|
||||
quotearg_n_style (2, options.err_quoting_style, ent->fts_accpath));
|
||||
|
||||
if (ent->fts_info == FTS_DP)
|
||||
{
|
||||
@ -304,15 +279,18 @@ consider_visiting (FTS *p, FTSENT *ent)
|
||||
}
|
||||
if (ent->fts_info == FTS_DNR)
|
||||
{
|
||||
/* Ignore ENOENT error for vanished directories. */
|
||||
if (ENOENT == ent->fts_errno && options.ignore_readdir_race)
|
||||
return;
|
||||
nonfatal_target_file_error (ent->fts_errno, ent->fts_path);
|
||||
if (options.do_dir_first)
|
||||
{
|
||||
/* Return for unreadable directories without -depth.
|
||||
* With -depth, the directory itself has to be processed, yet the
|
||||
* error message above has to be output.
|
||||
*/
|
||||
return;
|
||||
}
|
||||
{
|
||||
/* Return for unreadable directories without -depth.
|
||||
* With -depth, the directory itself has to be processed, yet the
|
||||
* error message above has to be output.
|
||||
*/
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (ent->fts_info == FTS_DC)
|
||||
{
|
||||
@ -330,45 +308,49 @@ consider_visiting (FTS *p, FTSENT *ent)
|
||||
* of the file (fts_path) in the error message.
|
||||
*/
|
||||
if (symlink_loop (ent->fts_accpath))
|
||||
{
|
||||
nonfatal_target_file_error (ELOOP, ent->fts_path);
|
||||
return;
|
||||
}
|
||||
{
|
||||
nonfatal_target_file_error (ELOOP, ent->fts_path);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (ent->fts_info == FTS_NS)
|
||||
{
|
||||
if (ent->fts_level == 0)
|
||||
{
|
||||
/* e.g., nonexistent starting point */
|
||||
nonfatal_target_file_error (ent->fts_errno, ent->fts_path);
|
||||
return;
|
||||
}
|
||||
{
|
||||
/* e.g., nonexistent starting point */
|
||||
nonfatal_target_file_error (ent->fts_errno, ent->fts_path);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* The following if statement fixes Savannah bug #19605
|
||||
* (failure to diagnose a symbolic link loop)
|
||||
*/
|
||||
if (symlink_loop (ent->fts_accpath))
|
||||
{
|
||||
nonfatal_target_file_error (ELOOP, ent->fts_path);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
nonfatal_target_file_error (ent->fts_errno, ent->fts_path);
|
||||
/* Continue despite the error, as file name without stat info
|
||||
* might be better than not even processing the file name. This
|
||||
* can lead to repeated error messages later on, though, if a
|
||||
* predicate requires stat information.
|
||||
*
|
||||
* Not printing an error message here would be even more wrong,
|
||||
* though, as this could cause the contents of a directory to be
|
||||
* silently ignored, as the directory wouldn't be identified as
|
||||
* such.
|
||||
*/
|
||||
}
|
||||
{
|
||||
/* The following if statement fixes Savannah bug #19605
|
||||
* (failure to diagnose a symbolic link loop)
|
||||
*/
|
||||
if (symlink_loop (ent->fts_accpath))
|
||||
{
|
||||
nonfatal_target_file_error (ELOOP, ent->fts_path);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Ignore ENOENT error for vanished files. */
|
||||
if (ENOENT == ent->fts_errno && options.ignore_readdir_race)
|
||||
return;
|
||||
|
||||
}
|
||||
nonfatal_target_file_error (ent->fts_errno, ent->fts_path);
|
||||
/* Continue despite the error, as file name without stat info
|
||||
* might be better than not even processing the file name. This
|
||||
* can lead to repeated error messages later on, though, if a
|
||||
* predicate requires stat information.
|
||||
*
|
||||
* Not printing an error message here would be even more wrong,
|
||||
* though, as this could cause the contents of a directory to be
|
||||
* silently ignored, as the directory wouldn't be identified as
|
||||
* such.
|
||||
*/
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/* Cope with the usual cases. */
|
||||
@ -387,11 +369,11 @@ consider_visiting (FTS *p, FTSENT *ent)
|
||||
state.type = mode = statbuf.st_mode;
|
||||
|
||||
if (00000 == mode)
|
||||
{
|
||||
/* Savannah bug #16378. */
|
||||
error (0, 0, _("WARNING: file %s appears to have mode 0000"),
|
||||
quotearg_n_style (0, options.err_quoting_style, ent->fts_path));
|
||||
}
|
||||
{
|
||||
/* Savannah bug #16378. */
|
||||
error (0, 0, _("WARNING: file %s appears to have mode 0000"),
|
||||
quotearg_n_style (0, options.err_quoting_style, ent->fts_path));
|
||||
}
|
||||
}
|
||||
|
||||
/* update state.curdepth before calling digest_mode(), because digest_mode
|
||||
@ -401,7 +383,7 @@ consider_visiting (FTS *p, FTSENT *ent)
|
||||
if (mode)
|
||||
{
|
||||
if (!digest_mode (&mode, ent->fts_path, ent->fts_name, &statbuf, 0))
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
/* examine this item. */
|
||||
@ -425,12 +407,12 @@ consider_visiting (FTS *p, FTSENT *ent)
|
||||
if (options.maxdepth >= 0)
|
||||
{
|
||||
if (ent->fts_level >= options.maxdepth)
|
||||
{
|
||||
fts_set (p, ent, FTS_SKIP); /* descend no further */
|
||||
{
|
||||
fts_set (p, ent, FTS_SKIP); /* descend no further */
|
||||
|
||||
if (ent->fts_level > options.maxdepth)
|
||||
ignore = 1; /* don't even look at this one */
|
||||
}
|
||||
if (ent->fts_level > options.maxdepth)
|
||||
ignore = 1; /* don't even look at this one */
|
||||
}
|
||||
}
|
||||
|
||||
if ( (ent->fts_info == FTS_D) && !options.do_dir_first )
|
||||
@ -450,11 +432,11 @@ consider_visiting (FTS *p, FTSENT *ent)
|
||||
|
||||
if (options.debug_options & DebugSearch)
|
||||
fprintf (stderr,
|
||||
"consider_visiting (late): %s: "
|
||||
"fts_info=%-6s, isdir=%d ignore=%d have_stat=%d have_type=%d \n",
|
||||
quotearg_n_style (0, options.err_quoting_style, ent->fts_path),
|
||||
get_fts_info_name (ent->fts_info),
|
||||
isdir, ignore, state.have_stat, state.have_type);
|
||||
"consider_visiting (late): %s: "
|
||||
"fts_info=%-6s, isdir=%d ignore=%d have_stat=%d have_type=%d \n",
|
||||
quotearg_n_style (0, options.err_quoting_style, ent->fts_path),
|
||||
get_fts_info_name (ent->fts_info),
|
||||
isdir, ignore, state.have_stat, state.have_type);
|
||||
|
||||
if (!ignore)
|
||||
{
|
||||
@ -498,14 +480,17 @@ find (char *arg)
|
||||
break;
|
||||
}
|
||||
|
||||
if (options.stay_on_filesystem)
|
||||
if (options.mount)
|
||||
ftsoptions |= FTS_MOUNT;
|
||||
|
||||
if (options.xdev)
|
||||
ftsoptions |= FTS_XDEV;
|
||||
|
||||
p = fts_open (arglist, ftsoptions, NULL);
|
||||
if (NULL == p)
|
||||
{
|
||||
error (0, errno, _("cannot search %s"),
|
||||
safely_quote_err_filename (0, arg));
|
||||
safely_quote_err_filename (0, arg));
|
||||
state.exit_status = EXIT_FAILURE;
|
||||
}
|
||||
else
|
||||
@ -513,48 +498,48 @@ find (char *arg)
|
||||
int level = INT_MIN;
|
||||
|
||||
while ( (errno=0, ent=fts_read (p)) != NULL )
|
||||
{
|
||||
if (state.execdirs_outstanding && ((int)ent->fts_level != level))
|
||||
{
|
||||
/* If we changed level, perform any outstanding
|
||||
* execdirs. If we see a sequence of directory entries
|
||||
* like this: fffdfffdfff, we could build a command line
|
||||
* of 9 files, but this simple-minded implementation
|
||||
* builds a command line for only 3 files at a time
|
||||
* (since fts descends into the directories).
|
||||
*/
|
||||
complete_pending_execdirs ();
|
||||
}
|
||||
level = (int)ent->fts_level;
|
||||
{
|
||||
if (state.execdirs_outstanding && ((int)ent->fts_level != level))
|
||||
{
|
||||
/* If we changed level, perform any outstanding
|
||||
* execdirs. If we see a sequence of directory entries
|
||||
* like this: fffdfffdfff, we could build a command line
|
||||
* of 9 files, but this simple-minded implementation
|
||||
* builds a command line for only 3 files at a time
|
||||
* (since fts descends into the directories).
|
||||
*/
|
||||
complete_pending_execdirs ();
|
||||
}
|
||||
level = (int)ent->fts_level;
|
||||
|
||||
state.already_issued_stat_error_msg = false;
|
||||
state.have_stat = false;
|
||||
state.have_type = !!ent->fts_statp->st_mode;
|
||||
state.type = state.have_type ? ent->fts_statp->st_mode : 0;
|
||||
consider_visiting (p, ent);
|
||||
}
|
||||
state.already_issued_stat_error_msg = false;
|
||||
state.have_stat = false;
|
||||
state.have_type = !!ent->fts_statp->st_mode;
|
||||
state.type = state.have_type ? ent->fts_statp->st_mode : 0;
|
||||
consider_visiting (p, ent);
|
||||
}
|
||||
/* fts_read returned NULL; distinguish between "finished" and "error". */
|
||||
if (errno)
|
||||
{
|
||||
error (0, errno,
|
||||
"failed to read file names from file system at or below %s",
|
||||
safely_quote_err_filename (0, arg));
|
||||
state.exit_status = EXIT_FAILURE;
|
||||
return false;
|
||||
}
|
||||
{
|
||||
error (0, errno,
|
||||
"failed to read file names from file system at or below %s",
|
||||
safely_quote_err_filename (0, arg));
|
||||
state.exit_status = EXIT_FAILURE;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (0 != fts_close (p))
|
||||
{
|
||||
/* Here we break the abstraction of fts_close a bit, because we
|
||||
* are going to skip the rest of the start points, and return with
|
||||
* nonzero exit status. Hence we need to issue a diagnostic on
|
||||
* stderr. */
|
||||
error (0, errno,
|
||||
_("failed to restore working directory after searching %s"),
|
||||
arg);
|
||||
state.exit_status = EXIT_FAILURE;
|
||||
return false;
|
||||
}
|
||||
{
|
||||
/* Here we break the abstraction of fts_close a bit, because we
|
||||
* are going to skip the rest of the start points, and return with
|
||||
* nonzero exit status. Hence we need to issue a diagnostic on
|
||||
* stderr. */
|
||||
error (0, errno,
|
||||
_("failed to restore working directory after searching %s"),
|
||||
arg);
|
||||
state.exit_status = EXIT_FAILURE;
|
||||
return false;
|
||||
}
|
||||
p = NULL;
|
||||
}
|
||||
return true;
|
||||
@ -636,7 +621,7 @@ process_all_startpoints (int argc, char *argv[])
|
||||
{
|
||||
if (!argv_starting_points)
|
||||
{
|
||||
/* If no starting points are given on the comman line, then
|
||||
/* If no starting points are given on the command line, then
|
||||
* fall back to processing the current directory, i.e., ".".
|
||||
* We use a temporary variable here because some actions modify
|
||||
* the path temporarily. Hence if we use a string constant,
|
||||
@ -752,7 +737,7 @@ main (int argc, char **argv)
|
||||
if (NULL == state.shared_files)
|
||||
{
|
||||
error (EXIT_FAILURE, errno,
|
||||
_("Failed to initialize shared-file hash table"));
|
||||
_("Failed to initialize shared-file hash table"));
|
||||
}
|
||||
|
||||
/* Set the option defaults before we do the locale initialisation as
|
||||
@ -812,7 +797,7 @@ main (int argc, char **argv)
|
||||
* the wrong directory for example.
|
||||
*/
|
||||
if (process_all_startpoints (argc-end_of_leading_options,
|
||||
argv+end_of_leading_options))
|
||||
argv+end_of_leading_options))
|
||||
{
|
||||
/* If "-exec ... {} +" has been used, there may be some
|
||||
* partially-full command lines which have been built,
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/* getlimits - print various platform dependent limits.
|
||||
Copyright (C) 2023-2024 Free Software Foundation, Inc.
|
||||
Copyright (C) 2023-2026 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
|
||||
@ -38,6 +38,11 @@
|
||||
# define MIN(a,b) (a<b?a:b)
|
||||
#endif
|
||||
|
||||
/* Silence GCC 14. */
|
||||
#if 14 <= __GNUC__
|
||||
# pragma GCC diagnostic ignored "-Wanalyzer-out-of-bounds"
|
||||
#endif
|
||||
|
||||
/* Add one to the absolute value of the number whose textual
|
||||
representation is BUF + 1. Do this in-place, in the buffer.
|
||||
Return a pointer to the result, which is normally BUF + 1, but is
|
||||
|
||||
1653
find/parser.c
1653
find/parser.c
File diff suppressed because it is too large
Load Diff
479
find/pred.c
479
find/pred.c
@ -1,5 +1,5 @@
|
||||
/* pred.c -- execute the expression tree.
|
||||
Copyright (C) 1990-2024 Free Software Foundation, Inc.
|
||||
Copyright (C) 1990-2026 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
|
||||
@ -63,7 +63,7 @@ static bool match_lname (const char *pathname, struct stat *stat_buf, struct pre
|
||||
|
||||
/* Returns ts1 - ts2 */
|
||||
static double ts_difference (struct timespec ts1,
|
||||
struct timespec ts2)
|
||||
struct timespec ts2)
|
||||
{
|
||||
double d = difftime (ts1.tv_sec, ts2.tv_sec)
|
||||
+ (1.0e-9 * (ts1.tv_nsec - ts2.tv_nsec));
|
||||
@ -73,7 +73,7 @@ static double ts_difference (struct timespec ts1,
|
||||
|
||||
static int
|
||||
compare_ts (struct timespec ts1,
|
||||
struct timespec ts2)
|
||||
struct timespec ts2)
|
||||
{
|
||||
if ((ts1.tv_sec == ts2.tv_sec) &&
|
||||
(ts1.tv_nsec == ts2.tv_nsec))
|
||||
@ -116,21 +116,21 @@ pred_timewindow (struct timespec ts, struct predicate const *pred_ptr, int windo
|
||||
|
||||
case COMP_EQ:
|
||||
{
|
||||
/* consider "find . -mtime 0".
|
||||
*
|
||||
* Here, the origin is exactly 86400 seconds before the start
|
||||
* of the program (since -daystart was not specified). This
|
||||
* function will be called with window=86400 and
|
||||
* pred_ptr->args.reftime.ts as the origin. Hence a file
|
||||
* created the instant the program starts will show a time
|
||||
* difference (value of delta) of 86400. Similarly, a file
|
||||
* created exactly 24h ago would be the newest file which was
|
||||
* _not_ created today. So, if delta is 0.0, the file
|
||||
* was not created today. If the delta is 86400, the file
|
||||
* was created this instant.
|
||||
*/
|
||||
double delta = ts_difference (ts, pred_ptr->args.reftime.ts);
|
||||
return (delta > 0.0 && delta <= window);
|
||||
/* consider "find . -mtime 0".
|
||||
*
|
||||
* Here, the origin is exactly 86400 seconds before the start
|
||||
* of the program (since -daystart was not specified). This
|
||||
* function will be called with window=86400 and
|
||||
* pred_ptr->args.reftime.ts as the origin. Hence a file
|
||||
* created the instant the program starts will show a time
|
||||
* difference (value of delta) of 86400. Similarly, a file
|
||||
* created exactly 24h ago would be the newest file which was
|
||||
* _not_ created today. So, if delta is 0.0, the file
|
||||
* was not created today. If the delta is 86400, the file
|
||||
* was created this instant.
|
||||
*/
|
||||
double delta = ts_difference (ts, pred_ptr->args.reftime.ts);
|
||||
return (delta > 0.0 && delta <= window);
|
||||
}
|
||||
}
|
||||
assert (0);
|
||||
@ -231,32 +231,32 @@ pred_delete (const char *pathname, struct stat *stat_buf, struct predicate *pred
|
||||
{
|
||||
int flags=0;
|
||||
if (state.have_stat && S_ISDIR(stat_buf->st_mode))
|
||||
flags |= AT_REMOVEDIR;
|
||||
flags |= AT_REMOVEDIR;
|
||||
if (perform_delete (flags))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ENOENT == errno && options.ignore_readdir_race)
|
||||
{
|
||||
/* Ignore unlink() error for vanished files. */
|
||||
errno = 0;
|
||||
return true;
|
||||
}
|
||||
if (EISDIR == errno)
|
||||
{
|
||||
if ((flags & AT_REMOVEDIR) == 0)
|
||||
{
|
||||
/* unlink() operation failed because we should have done rmdir(). */
|
||||
flags |= AT_REMOVEDIR;
|
||||
if (perform_delete (flags))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
if (ENOENT == errno && options.ignore_readdir_race)
|
||||
{
|
||||
/* Ignore unlink() error for vanished files. */
|
||||
errno = 0;
|
||||
return true;
|
||||
}
|
||||
if (EISDIR == errno)
|
||||
{
|
||||
if ((flags & AT_REMOVEDIR) == 0)
|
||||
{
|
||||
/* unlink() operation failed because we should have done rmdir(). */
|
||||
flags |= AT_REMOVEDIR;
|
||||
if (perform_delete (flags))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
error (0, errno, _("cannot delete %s"),
|
||||
safely_quote_err_filename (0, pathname));
|
||||
safely_quote_err_filename (0, pathname));
|
||||
/* Previously I had believed that having the -delete action
|
||||
* return false provided the user with control over whether an
|
||||
* error message is issued. While this is true, the policy of
|
||||
@ -277,6 +277,27 @@ pred_delete (const char *pathname, struct stat *stat_buf, struct predicate *pred
|
||||
}
|
||||
}
|
||||
|
||||
static bool
|
||||
compare_num (enum comparison_type kind, uintmax_t l_val, uintmax_t val)
|
||||
{
|
||||
switch (kind)
|
||||
{
|
||||
case COMP_GT:
|
||||
if (val > l_val)
|
||||
return true;
|
||||
break;
|
||||
case COMP_LT:
|
||||
if (val < l_val)
|
||||
return true;
|
||||
break;
|
||||
case COMP_EQ:
|
||||
if (val == l_val)
|
||||
return true;
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
pred_empty (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
|
||||
{
|
||||
@ -293,49 +314,49 @@ pred_empty (const char *pathname, struct stat *stat_buf, struct predicate *pred_
|
||||
errno = 0;
|
||||
if ((fd = openat (state.cwd_dir_fd, state.rel_pathname, O_RDONLY
|
||||
#if defined O_LARGEFILE
|
||||
| O_LARGEFILE
|
||||
| O_LARGEFILE
|
||||
#endif
|
||||
| O_CLOEXEC | O_DIRECTORY | O_NOCTTY | O_NONBLOCK)) < 0)
|
||||
{
|
||||
error (0, errno, "%s", safely_quote_err_filename (0, pathname));
|
||||
state.exit_status = EXIT_FAILURE;
|
||||
return false;
|
||||
}
|
||||
| O_CLOEXEC | O_DIRECTORY | O_NOCTTY | O_NONBLOCK)) < 0)
|
||||
{
|
||||
error (0, errno, "%s", safely_quote_err_filename (0, pathname));
|
||||
state.exit_status = EXIT_FAILURE;
|
||||
return false;
|
||||
}
|
||||
d = fdopendir (fd);
|
||||
if (d == NULL)
|
||||
{
|
||||
error (0, errno, "%s", safely_quote_err_filename (0, pathname));
|
||||
state.exit_status = EXIT_FAILURE;
|
||||
close (fd);
|
||||
return false;
|
||||
}
|
||||
{
|
||||
error (0, errno, "%s", safely_quote_err_filename (0, pathname));
|
||||
state.exit_status = EXIT_FAILURE;
|
||||
close (fd);
|
||||
return false;
|
||||
}
|
||||
/* errno is not touched in the loop body, so initializing it here
|
||||
* once before the loop is enough to detect readdir(3) errors. */
|
||||
errno = 0;
|
||||
for (dp = readdir (d); dp; dp = readdir (d))
|
||||
{
|
||||
if (dp->d_name[0] != '.'
|
||||
|| (dp->d_name[1] != '\0'
|
||||
&& (dp->d_name[1] != '.' || dp->d_name[2] != '\0')))
|
||||
{
|
||||
empty = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
{
|
||||
if (dp->d_name[0] != '.'
|
||||
|| (dp->d_name[1] != '\0'
|
||||
&& (dp->d_name[1] != '.' || dp->d_name[2] != '\0')))
|
||||
{
|
||||
empty = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (errno)
|
||||
{
|
||||
/* Handle errors from readdir(3). */
|
||||
error (0, errno, "%s", safely_quote_err_filename (0, pathname));
|
||||
state.exit_status = EXIT_FAILURE;
|
||||
CLOSEDIR (d);
|
||||
return false;
|
||||
}
|
||||
{
|
||||
/* Handle errors from readdir(3). */
|
||||
error (0, errno, "%s", safely_quote_err_filename (0, pathname));
|
||||
state.exit_status = EXIT_FAILURE;
|
||||
CLOSEDIR (d);
|
||||
return false;
|
||||
}
|
||||
if (CLOSEDIR (d))
|
||||
{
|
||||
error (0, errno, "%s", safely_quote_err_filename (0, pathname));
|
||||
state.exit_status = EXIT_FAILURE;
|
||||
return false;
|
||||
}
|
||||
{
|
||||
error (0, errno, "%s", safely_quote_err_filename (0, pathname));
|
||||
state.exit_status = EXIT_FAILURE;
|
||||
return false;
|
||||
}
|
||||
return (empty);
|
||||
}
|
||||
else if (S_ISREG (stat_buf->st_mode))
|
||||
@ -374,9 +395,9 @@ pred_fls (const char *pathname, struct stat *stat_buf, struct predicate *pred_pt
|
||||
{
|
||||
FILE * stream = pred_ptr->args.printf_vec.stream;
|
||||
list_file (pathname, state.cwd_dir_fd, state.rel_pathname, stat_buf,
|
||||
options.start_time.tv_sec,
|
||||
options.output_block_size,
|
||||
options.literal_control_chars, stream);
|
||||
options.start_time.tv_sec,
|
||||
options.output_block_size,
|
||||
options.literal_control_chars, stream);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -387,10 +408,10 @@ pred_fprint (const char *pathname, struct stat *stat_buf, struct predicate *pred
|
||||
(void) &stat_buf;
|
||||
|
||||
print_quoted (pred_ptr->args.printf_vec.stream,
|
||||
pred_ptr->args.printf_vec.quote_opts,
|
||||
pred_ptr->args.printf_vec.dest_is_tty,
|
||||
"%s\n",
|
||||
pathname);
|
||||
pred_ptr->args.printf_vec.quote_opts,
|
||||
pred_ptr->args.printf_vec.dest_is_tty,
|
||||
"%s\n",
|
||||
pathname);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -424,22 +445,9 @@ pred_gid (const char *pathname, struct stat *stat_buf, struct predicate *pred_pt
|
||||
{
|
||||
(void) pathname;
|
||||
|
||||
switch (pred_ptr->args.numinfo.kind)
|
||||
{
|
||||
case COMP_GT:
|
||||
if (stat_buf->st_gid > pred_ptr->args.numinfo.l_val)
|
||||
return (true);
|
||||
break;
|
||||
case COMP_LT:
|
||||
if (stat_buf->st_gid < pred_ptr->args.numinfo.l_val)
|
||||
return (true);
|
||||
break;
|
||||
case COMP_EQ:
|
||||
if (stat_buf->st_gid == pred_ptr->args.numinfo.l_val)
|
||||
return (true);
|
||||
break;
|
||||
}
|
||||
return (false);
|
||||
return compare_num (pred_ptr->args.numinfo.kind,
|
||||
pred_ptr->args.numinfo.l_val,
|
||||
stat_buf->st_gid);
|
||||
}
|
||||
|
||||
bool
|
||||
@ -496,22 +504,9 @@ pred_inum (const char *pathname, struct stat *stat_buf, struct predicate *pred_p
|
||||
{
|
||||
(void) pathname;
|
||||
|
||||
switch (pred_ptr->args.numinfo.kind)
|
||||
{
|
||||
case COMP_GT:
|
||||
if (stat_buf->st_ino > pred_ptr->args.numinfo.l_val)
|
||||
return (true);
|
||||
break;
|
||||
case COMP_LT:
|
||||
if (stat_buf->st_ino < pred_ptr->args.numinfo.l_val)
|
||||
return (true);
|
||||
break;
|
||||
case COMP_EQ:
|
||||
if (stat_buf->st_ino == pred_ptr->args.numinfo.l_val)
|
||||
return (true);
|
||||
break;
|
||||
}
|
||||
return (false);
|
||||
return compare_num (pred_ptr->args.numinfo.kind,
|
||||
pred_ptr->args.numinfo.l_val,
|
||||
stat_buf->st_ino);
|
||||
}
|
||||
|
||||
bool
|
||||
@ -529,22 +524,9 @@ pred_links (const char *pathname, struct stat *stat_buf, struct predicate *pred_
|
||||
{
|
||||
(void) pathname;
|
||||
|
||||
switch (pred_ptr->args.numinfo.kind)
|
||||
{
|
||||
case COMP_GT:
|
||||
if (stat_buf->st_nlink > pred_ptr->args.numinfo.l_val)
|
||||
return (true);
|
||||
break;
|
||||
case COMP_LT:
|
||||
if (stat_buf->st_nlink < pred_ptr->args.numinfo.l_val)
|
||||
return (true);
|
||||
break;
|
||||
case COMP_EQ:
|
||||
if (stat_buf->st_nlink == pred_ptr->args.numinfo.l_val)
|
||||
return (true);
|
||||
break;
|
||||
}
|
||||
return (false);
|
||||
return compare_num (pred_ptr->args.numinfo.kind,
|
||||
pred_ptr->args.numinfo.l_val,
|
||||
stat_buf->st_nlink);
|
||||
}
|
||||
|
||||
bool
|
||||
@ -562,16 +544,16 @@ match_lname (const char *pathname, struct stat *stat_buf, struct predicate *pred
|
||||
{
|
||||
char *linkname = areadlinkat (state.cwd_dir_fd, state.rel_pathname);
|
||||
if (linkname)
|
||||
{
|
||||
if (fnmatch (pred_ptr->args.str, linkname,
|
||||
ignore_case ? FNM_CASEFOLD : 0) == 0)
|
||||
ret = true;
|
||||
}
|
||||
{
|
||||
if (fnmatch (pred_ptr->args.str, linkname,
|
||||
ignore_case ? FNM_CASEFOLD : 0) == 0)
|
||||
ret = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
nonfatal_target_file_error (errno, pathname);
|
||||
state.exit_status = EXIT_FAILURE;
|
||||
}
|
||||
{
|
||||
nonfatal_target_file_error (errno, pathname);
|
||||
state.exit_status = EXIT_FAILURE;
|
||||
}
|
||||
free (linkname);
|
||||
}
|
||||
#endif /* S_ISLNK */
|
||||
@ -643,12 +625,12 @@ pred_newerXY (const char *pathname, struct stat *stat_buf, struct predicate *pre
|
||||
ts = get_stat_birthtime (stat_buf);
|
||||
collected = true;
|
||||
if (ts.tv_nsec < 0)
|
||||
{
|
||||
/* XXX: Cannot determine birth time. Warn once. */
|
||||
error (0, 0, _("WARNING: cannot determine birth time of file %s"),
|
||||
safely_quote_err_filename (0, pathname));
|
||||
return false;
|
||||
}
|
||||
{
|
||||
/* XXX: Cannot determine birth time. Warn once. */
|
||||
error (0, 0, _("WARNING: cannot determine birth time of file %s"),
|
||||
safely_quote_err_filename (0, pathname));
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
||||
case XVAL_CTIME:
|
||||
@ -783,9 +765,9 @@ pred_perm (const char *pathname, struct stat *stat_buf, struct predicate *pred_p
|
||||
|
||||
*/
|
||||
if (0 == perm_val)
|
||||
return true; /* Savannah bug 14748; we used to return false */
|
||||
return true; /* Savannah bug 14748; we used to return false */
|
||||
else
|
||||
return (mode & perm_val) != 0;
|
||||
return (mode & perm_val) != 0;
|
||||
break;
|
||||
|
||||
case PERM_EXACT:
|
||||
@ -839,9 +821,9 @@ pred_print (const char *pathname, struct stat *stat_buf, struct predicate *pred_
|
||||
(void) pred_ptr;
|
||||
|
||||
print_quoted (pred_ptr->args.printf_vec.stream,
|
||||
pred_ptr->args.printf_vec.quote_opts,
|
||||
pred_ptr->args.printf_vec.dest_is_tty,
|
||||
"%s\n", pathname);
|
||||
pred_ptr->args.printf_vec.quote_opts,
|
||||
pred_ptr->args.printf_vec.dest_is_tty,
|
||||
"%s\n", pathname);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -860,7 +842,7 @@ pred_prune (const char *pathname, struct stat *stat_buf, struct predicate *pred_
|
||||
if (options.do_dir_first == true) { /* no effect with -depth */
|
||||
assert (state.have_stat);
|
||||
if (stat_buf != NULL &&
|
||||
S_ISDIR(stat_buf->st_mode))
|
||||
S_ISDIR(stat_buf->st_mode))
|
||||
state.stop_at_current_level = true;
|
||||
}
|
||||
|
||||
@ -886,7 +868,7 @@ pred_quit (const char *pathname, struct stat *stat_buf, struct predicate *pred_p
|
||||
/* Since -exec and friends don't leave child processes running in the
|
||||
* background, there is no need to wait for them here.
|
||||
*/
|
||||
exit (state.exit_status); /* 0 for success, etc. */
|
||||
exit (state.exit_status); /* 0 for success, etc. */
|
||||
}
|
||||
|
||||
bool
|
||||
@ -895,7 +877,7 @@ pred_regex (const char *pathname, struct stat *stat_buf, struct predicate *pred_
|
||||
int len = strlen (pathname);
|
||||
(void) stat_buf;
|
||||
if (re_match (pred_ptr->args.regex, pathname, len, 0,
|
||||
(struct re_registers *) NULL) == len)
|
||||
(struct re_registers *) NULL) == len)
|
||||
return (true);
|
||||
return (false);
|
||||
}
|
||||
@ -907,23 +889,11 @@ pred_size (const char *pathname, struct stat *stat_buf, struct predicate *pred_p
|
||||
|
||||
(void) pathname;
|
||||
f_val = ((stat_buf->st_size / pred_ptr->args.size.blocksize)
|
||||
+ (stat_buf->st_size % pred_ptr->args.size.blocksize != 0));
|
||||
switch (pred_ptr->args.size.kind)
|
||||
{
|
||||
case COMP_GT:
|
||||
if (f_val > pred_ptr->args.size.size)
|
||||
return (true);
|
||||
break;
|
||||
case COMP_LT:
|
||||
if (f_val < pred_ptr->args.size.size)
|
||||
return (true);
|
||||
break;
|
||||
case COMP_EQ:
|
||||
if (f_val == pred_ptr->args.size.size)
|
||||
return (true);
|
||||
break;
|
||||
}
|
||||
return (false);
|
||||
+ (stat_buf->st_size % pred_ptr->args.size.blocksize != 0));
|
||||
|
||||
return compare_num (pred_ptr->args.size.kind,
|
||||
pred_ptr->args.size.size,
|
||||
f_val);
|
||||
}
|
||||
|
||||
bool
|
||||
@ -951,14 +921,14 @@ pred_samefile (const char *pathname, struct stat *stat_buf, struct predicate *pr
|
||||
if (stat_buf->st_ino)
|
||||
{
|
||||
if (stat_buf->st_ino != pred_ptr->args.samefileid.ino)
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
/* Now stat the file to check the device number. */
|
||||
if (0 == get_statinfo (pathname, state.rel_pathname, stat_buf))
|
||||
{
|
||||
/* the repeated test here is necessary in case stat_buf.st_ino had been zero. */
|
||||
return stat_buf->st_ino == pred_ptr->args.samefileid.ino
|
||||
&& stat_buf->st_dev == pred_ptr->args.samefileid.dev;
|
||||
&& stat_buf->st_dev == pred_ptr->args.samefileid.dev;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1076,22 +1046,9 @@ bool
|
||||
pred_uid (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
|
||||
{
|
||||
(void) pathname;
|
||||
switch (pred_ptr->args.numinfo.kind)
|
||||
{
|
||||
case COMP_GT:
|
||||
if (stat_buf->st_uid > pred_ptr->args.numinfo.l_val)
|
||||
return (true);
|
||||
break;
|
||||
case COMP_LT:
|
||||
if (stat_buf->st_uid < pred_ptr->args.numinfo.l_val)
|
||||
return (true);
|
||||
break;
|
||||
case COMP_EQ:
|
||||
if (stat_buf->st_uid == pred_ptr->args.numinfo.l_val)
|
||||
return (true);
|
||||
break;
|
||||
}
|
||||
return (false);
|
||||
return compare_num (pred_ptr->args.numinfo.kind,
|
||||
pred_ptr->args.numinfo.l_val,
|
||||
stat_buf->st_uid);
|
||||
}
|
||||
|
||||
bool
|
||||
@ -1146,7 +1103,7 @@ err_signals_broken_link(int errno_value)
|
||||
bool
|
||||
pred_xtype (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
|
||||
{
|
||||
struct stat sbuf; /* local copy, not stat_buf because we're using a different stat method */
|
||||
struct stat sbuf; /* local copy, not stat_buf because we're using a different stat method */
|
||||
int (*ystat) (const char*, struct stat *p);
|
||||
|
||||
|
||||
@ -1163,18 +1120,18 @@ pred_xtype (const char *pathname, struct stat *stat_buf, struct predicate *pred_
|
||||
if ((*ystat) (state.rel_pathname, &sbuf) != 0)
|
||||
{
|
||||
if (ystat_follows_links && err_signals_broken_link (errno))
|
||||
{
|
||||
/* If we failed to follow the symlink,
|
||||
* fall back on looking at the symlink itself.
|
||||
*/
|
||||
/* Mimic behavior of ls -lL. */
|
||||
return pred_type (pathname, stat_buf, pred_ptr);
|
||||
}
|
||||
{
|
||||
/* If we failed to follow the symlink,
|
||||
* fall back on looking at the symlink itself.
|
||||
*/
|
||||
/* Mimic behavior of ls -lL. */
|
||||
return pred_type (pathname, stat_buf, pred_ptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
error (0, errno, "%s", safely_quote_err_filename (0, pathname));
|
||||
state.exit_status = EXIT_FAILURE;
|
||||
}
|
||||
{
|
||||
error (0, errno, "%s", safely_quote_err_filename (0, pathname));
|
||||
state.exit_status = EXIT_FAILURE;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
/* Now that we have our stat() information, query it in the same
|
||||
@ -1186,17 +1143,17 @@ pred_xtype (const char *pathname, struct stat *stat_buf, struct predicate *pred_
|
||||
|
||||
bool
|
||||
pred_context (const char *pathname, struct stat *stat_buf,
|
||||
struct predicate *pred_ptr)
|
||||
struct predicate *pred_ptr)
|
||||
{
|
||||
char *scontext;
|
||||
int rv = (*options.x_getfilecon) (state.cwd_dir_fd, state.rel_pathname,
|
||||
&scontext);
|
||||
&scontext);
|
||||
(void) stat_buf;
|
||||
|
||||
if (rv < 0)
|
||||
{
|
||||
error (0, errno, _("getfilecon failed: %s"),
|
||||
safely_quote_err_filename (0, pathname));
|
||||
safely_quote_err_filename (0, pathname));
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -1248,24 +1205,24 @@ print_parenthesised (FILE *fp, struct predicate *node)
|
||||
if (node)
|
||||
{
|
||||
if ((pred_is (node, pred_or) || pred_is (node, pred_and))
|
||||
&& node->pred_left == NULL)
|
||||
{
|
||||
/* We print "<nothing> or X" as just "X"
|
||||
* We print "<nothing> and X" as just "X"
|
||||
*/
|
||||
print_parenthesised(fp, node->pred_right);
|
||||
}
|
||||
&& node->pred_left == NULL)
|
||||
{
|
||||
/* We print "<nothing> or X" as just "X"
|
||||
* We print "<nothing> and X" as just "X"
|
||||
*/
|
||||
print_parenthesised(fp, node->pred_right);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (node->pred_left || node->pred_right)
|
||||
parens = 1;
|
||||
{
|
||||
if (node->pred_left || node->pred_right)
|
||||
parens = 1;
|
||||
|
||||
if (parens)
|
||||
fprintf (fp, "%s", " ( ");
|
||||
print_optlist (fp, node);
|
||||
if (parens)
|
||||
fprintf (fp, "%s", " ) ");
|
||||
}
|
||||
if (parens)
|
||||
fprintf (fp, "%s", " ( ");
|
||||
print_optlist (fp, node);
|
||||
if (parens)
|
||||
fprintf (fp, "%s", " ) ");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1343,52 +1300,52 @@ pred_sanity_check (const struct predicate *predicates)
|
||||
* the parse_xxx function fills it in, so we can't check it.
|
||||
*/
|
||||
if (p->parser_entry->pred_func)
|
||||
{
|
||||
assert (p->parser_entry->pred_func == p->pred_func);
|
||||
}
|
||||
{
|
||||
assert (p->parser_entry->pred_func == p->pred_func);
|
||||
}
|
||||
|
||||
switch (p->parser_entry->type)
|
||||
{
|
||||
/* Options all take effect during parsing, so there should
|
||||
* be no predicate entries corresponding to them. Hence we
|
||||
* should not see any ARG_OPTION or ARG_POSITIONAL_OPTION
|
||||
* items.
|
||||
*
|
||||
* This is a silly way of coding this test, but it prevents
|
||||
* a compiler warning (i.e. otherwise it would think that
|
||||
* there would be case statements missing).
|
||||
*/
|
||||
case ARG_OPTION:
|
||||
case ARG_POSITIONAL_OPTION:
|
||||
assert (p->parser_entry->type != ARG_OPTION);
|
||||
assert (p->parser_entry->type != ARG_POSITIONAL_OPTION);
|
||||
break;
|
||||
{
|
||||
/* Options all take effect during parsing, so there should
|
||||
* be no predicate entries corresponding to them. Hence we
|
||||
* should not see any ARG_OPTION or ARG_POSITIONAL_OPTION
|
||||
* items.
|
||||
*
|
||||
* This is a silly way of coding this test, but it prevents
|
||||
* a compiler warning (i.e. otherwise it would think that
|
||||
* there would be case statements missing).
|
||||
*/
|
||||
case ARG_OPTION:
|
||||
case ARG_POSITIONAL_OPTION:
|
||||
assert (p->parser_entry->type != ARG_OPTION);
|
||||
assert (p->parser_entry->type != ARG_POSITIONAL_OPTION);
|
||||
break;
|
||||
|
||||
case ARG_ACTION:
|
||||
assert (p->side_effects); /* actions have side effects. */
|
||||
if (!pred_is (p, pred_prune) && !pred_is(p, pred_quit))
|
||||
{
|
||||
/* actions other than -prune and -quit should
|
||||
* inhibit the default -print
|
||||
*/
|
||||
assert (p->no_default_print);
|
||||
}
|
||||
break;
|
||||
case ARG_ACTION:
|
||||
assert (p->side_effects); /* actions have side effects. */
|
||||
if (!pred_is (p, pred_prune) && !pred_is(p, pred_quit))
|
||||
{
|
||||
/* actions other than -prune and -quit should
|
||||
* inhibit the default -print
|
||||
*/
|
||||
assert (p->no_default_print);
|
||||
}
|
||||
break;
|
||||
|
||||
/* We happen to know that the only user of ARG_SPECIAL_PARSE
|
||||
* is a test, so handle it like ARG_TEST.
|
||||
*/
|
||||
case ARG_SPECIAL_PARSE:
|
||||
case ARG_TEST:
|
||||
case ARG_PUNCTUATION:
|
||||
case ARG_NOOP:
|
||||
/* Punctuation and tests should have no side
|
||||
* effects and not inhibit default print.
|
||||
*/
|
||||
assert (!p->no_default_print);
|
||||
assert (!p->side_effects);
|
||||
break;
|
||||
}
|
||||
/* We happen to know that the only user of ARG_SPECIAL_PARSE
|
||||
* is a test, so handle it like ARG_TEST.
|
||||
*/
|
||||
case ARG_SPECIAL_PARSE:
|
||||
case ARG_TEST:
|
||||
case ARG_PUNCTUATION:
|
||||
case ARG_NOOP:
|
||||
/* Punctuation and tests should have no side
|
||||
* effects and not inhibit default print.
|
||||
*/
|
||||
assert (!p->no_default_print);
|
||||
assert (!p->side_effects);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
22
find/print.c
22
find/print.c
@ -1,5 +1,5 @@
|
||||
/* print.c -- print/printf-related code.
|
||||
Copyright (C) 1990-2024 Free Software Foundation, Inc.
|
||||
Copyright (C) 1990-2026 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
|
||||
@ -588,7 +588,7 @@ format_date (struct timespec ts, int kind)
|
||||
* For example, some systems return junk in the tv_nsec part of
|
||||
* st_birthtime. An example of this is the NetBSD-4.0-RELENG kernel
|
||||
* (at Sat Mar 24 18:46:46 2007) running a NetBSD-3.1-RELEASE
|
||||
* runtime and examining files on an msdos filesytem. So for that
|
||||
* runtime and examining files on an msdos filesystem. So for that
|
||||
* reason we set NS_BUF_LEN to 32, which is simply "long enough" as
|
||||
* opposed to "exactly the right size". Note that the behaviour of
|
||||
* NetBSD appears to be a result of the use of uninitialized data,
|
||||
@ -698,7 +698,7 @@ format_date (struct timespec ts, int kind)
|
||||
*--p = '-'; /* XXX: Ugh, relying on internal details of human_readable(). */
|
||||
|
||||
/* Add the nanoseconds part. Because we cannot enforce a
|
||||
* particlar implementation of human_readable, we cannot assume
|
||||
* particular implementation of human_readable, we cannot assume
|
||||
* any particular value for (p-buf). So we need to be careful
|
||||
* that there is enough space remaining in the buffer.
|
||||
*/
|
||||
@ -1250,14 +1250,14 @@ do_fprintf (struct format_val *dest,
|
||||
break;
|
||||
|
||||
case 0:
|
||||
/* Trailing single %. This should have been rejected by
|
||||
insert_fprintf. We use %s here in the error message
|
||||
simply to ensure that the error message matches the one
|
||||
in insert_fprintf, easing the translation burden.
|
||||
*/
|
||||
error (EXIT_FAILURE, 0, _("error: %s at end of format string"), "%");
|
||||
/*NOTREACHED*/
|
||||
break;
|
||||
/* Trailing single %. This should have been rejected by
|
||||
insert_fprintf. We use %s here in the error message
|
||||
simply to ensure that the error message matches the one
|
||||
in insert_fprintf, easing the translation burden.
|
||||
*/
|
||||
error (EXIT_FAILURE, 0, _("error: %s at end of format string"), "%");
|
||||
/*NOTREACHED*/
|
||||
break;
|
||||
}
|
||||
/* end of KIND_FORMAT case */
|
||||
break;
|
||||
|
||||
14
find/print.h
14
find/print.h
@ -1,5 +1,5 @@
|
||||
/* print.h -- declarations for symbols in print.c.
|
||||
Copyright (C) 2011-2024 Free Software Foundation, Inc.
|
||||
Copyright (C) 2011-2026 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
|
||||
@ -25,13 +25,13 @@ struct predicate;
|
||||
struct segment;
|
||||
|
||||
struct segment **make_segment (struct segment **segment,
|
||||
char *format, int len,
|
||||
int kind, char format_char,
|
||||
char aux_format_char,
|
||||
struct predicate *pred);
|
||||
char *format, int len,
|
||||
int kind, char format_char,
|
||||
char aux_format_char,
|
||||
struct predicate *pred);
|
||||
bool
|
||||
insert_fprintf (struct format_val *vec,
|
||||
const struct parser_table *entry,
|
||||
char *format);
|
||||
const struct parser_table *entry,
|
||||
char *format);
|
||||
|
||||
#endif /* PRINT_H */
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/* sharefile.c -- open files just once.
|
||||
Copyright (C) 2008-2024 Free Software Foundation, Inc.
|
||||
Copyright (C) 2008-2026 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
|
||||
@ -80,7 +80,7 @@ entry_free (void *pv)
|
||||
if (p->fp)
|
||||
{
|
||||
if (0 != fclose (p->fp))
|
||||
fatal_nontarget_file_error (errno, p->name);
|
||||
fatal_nontarget_file_error (errno, p->name);
|
||||
}
|
||||
free (p->name);
|
||||
free (p);
|
||||
@ -105,25 +105,25 @@ sharefile_init (const char *mode)
|
||||
{
|
||||
p->mode = strdup (mode);
|
||||
if (p->mode)
|
||||
{
|
||||
p->table = hash_initialize (DefaultHashTableSize, NULL,
|
||||
entry_hashfunc,
|
||||
entry_comparator,
|
||||
entry_free);
|
||||
if (p->table)
|
||||
{
|
||||
return p;
|
||||
}
|
||||
else
|
||||
{
|
||||
free (p->mode);
|
||||
free (p);
|
||||
}
|
||||
}
|
||||
{
|
||||
p->table = hash_initialize (DefaultHashTableSize, NULL,
|
||||
entry_hashfunc,
|
||||
entry_comparator,
|
||||
entry_free);
|
||||
if (p->table)
|
||||
{
|
||||
return p;
|
||||
}
|
||||
else
|
||||
{
|
||||
free (p->mode);
|
||||
free (p);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
free (p);
|
||||
}
|
||||
{
|
||||
free (p);
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
@ -168,36 +168,36 @@ sharefile_fopen (sharefile_handle h, const char *filename)
|
||||
set_cloexec_flag (fd, true);
|
||||
if (fstat (fd, &st) < 0)
|
||||
{
|
||||
entry_free (new_entry);
|
||||
entry_free (new_entry);
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
void *existing;
|
||||
void *existing;
|
||||
|
||||
new_entry->device = st.st_dev;
|
||||
new_entry->inode = st.st_ino;
|
||||
|
||||
existing = hash_lookup (p->table, new_entry);
|
||||
if (existing) /* We have previously opened that file. */
|
||||
{
|
||||
entry_free (new_entry); /* don't need new_entry. */
|
||||
return ((const struct SharefileEntry*)existing)->fp;
|
||||
}
|
||||
if (existing) /* We have previously opened that file. */
|
||||
{
|
||||
entry_free (new_entry); /* don't need new_entry. */
|
||||
return ((const struct SharefileEntry*)existing)->fp;
|
||||
}
|
||||
else /* We didn't open it already */
|
||||
{
|
||||
if (hash_insert (p->table, new_entry))
|
||||
{
|
||||
return new_entry->fp;
|
||||
}
|
||||
else /* failed to insert in hashtable. */
|
||||
{
|
||||
const int save_errno = errno;
|
||||
entry_free (new_entry);
|
||||
errno = save_errno;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
{
|
||||
if (hash_insert (p->table, new_entry))
|
||||
{
|
||||
return new_entry->fp;
|
||||
}
|
||||
else /* failed to insert in hashtable. */
|
||||
{
|
||||
const int save_errno = errno;
|
||||
entry_free (new_entry);
|
||||
errno = save_errno;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/* sharefile.h -- open files just once.
|
||||
Copyright (C) 2008-2024 Free Software Foundation, Inc.
|
||||
Copyright (C) 2008-2026 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
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
# Copyright (C) 2001-2024 Free Software Foundation, Inc.
|
||||
# Copyright (C) 2001-2026 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
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
# Copyright (C) 2014-2024 Free Software Foundation, Inc.
|
||||
# Copyright (C) 2014-2026 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
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
# -*- TCL -*-
|
||||
# Test-specific TCL procedures required by DejaGNU.
|
||||
# Copyright (C) 2000-2024 Free Software Foundation, Inc.
|
||||
# Copyright (C) 2000-2026 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
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
# If -exec \; fails, it should return false. The return
|
||||
# value of find should stil; be 0, unless another error has
|
||||
# value of find should still be 0, unless another error has
|
||||
# happened.
|
||||
find_start p { /tmp -exec false \; -o \( -printf "yep\n" -quit \) }
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
# tests for -execdir ... \+
|
||||
# Specifically, ensure that output for separate directoires is not mixed.
|
||||
# Specifically, ensure that output for separate directories is not mixed.
|
||||
if { [ safe_path ] } {
|
||||
exec rm -rf tmp
|
||||
exec mkdir tmp tmp/two
|
||||
|
||||
@ -22,8 +22,7 @@ set -e
|
||||
here=`pwd`
|
||||
d=`basename $here`
|
||||
|
||||
for arg;
|
||||
do
|
||||
for arg; do
|
||||
echo "$d" "$arg"
|
||||
done | LC_ALL=C sort
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
exec rm -rf tmp
|
||||
exec mkdir tmp
|
||||
# shoud not result in a fatal error.
|
||||
# should not result in a fatal error.
|
||||
find_start p { tmp \( -depth \) -false -print }
|
||||
|
||||
@ -21,7 +21,7 @@ for f; do echo "$f"; done
|
||||
close $script
|
||||
exec chmod 0500 tmp/list.sh
|
||||
|
||||
send_log "creeating files $file_list\n"
|
||||
send_log "creating files $file_list\n"
|
||||
foreach filename $file_list {
|
||||
}
|
||||
|
||||
|
||||
@ -2,7 +2,7 @@ set files "\(1 "
|
||||
|
||||
foreach file $files { touch $file }
|
||||
|
||||
# shoud not result in a fatal error.
|
||||
# should not result in a fatal error.
|
||||
find_start p { \(1 }
|
||||
|
||||
foreach file $files { file delete -- $file }
|
||||
|
||||
@ -2,7 +2,7 @@ set files "!2"
|
||||
|
||||
foreach file $files { touch $file }
|
||||
|
||||
# shoud not result in a fatal error.
|
||||
# should not result in a fatal error.
|
||||
find_start p { !2 }
|
||||
|
||||
foreach file $files { file delete -- $file }
|
||||
|
||||
@ -2,7 +2,7 @@ set files "\)"
|
||||
|
||||
foreach file $files { touch $file }
|
||||
|
||||
# shoud not result in a fatal error.
|
||||
# should not result in a fatal error.
|
||||
find_start p { \) }
|
||||
|
||||
foreach file $files { file delete -- $file }
|
||||
|
||||
896
find/tree.c
896
find/tree.c
File diff suppressed because it is too large
Load Diff
476
find/util.c
476
find/util.c
@ -1,5 +1,5 @@
|
||||
/* util.c -- functions for initializing new tree elements, and other things.
|
||||
Copyright (C) 1990-2024 Free Software Foundation, Inc.
|
||||
Copyright (C) 1990-2026 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
|
||||
@ -74,10 +74,10 @@ static struct debug_option_assoc debugassoc[] =
|
||||
|
||||
Fills in the following cells of the new predicate node:
|
||||
|
||||
pred_func PRED_FUNC
|
||||
args(.str) NULL
|
||||
p_type PRIMARY_TYPE
|
||||
p_prec NO_PREC
|
||||
pred_func PRED_FUNC
|
||||
args(.str) NULL
|
||||
p_type PRIMARY_TYPE
|
||||
p_prec NO_PREC
|
||||
|
||||
Other cells that need to be filled in are defaulted by
|
||||
get_new_pred_chk_op, which is used to ensure that the prior node is
|
||||
@ -86,8 +86,8 @@ static struct debug_option_assoc debugassoc[] =
|
||||
|
||||
struct predicate *
|
||||
insert_primary_withpred (const struct parser_table *entry,
|
||||
PRED_FUNC pred_func,
|
||||
const char *arg)
|
||||
PRED_FUNC pred_func,
|
||||
const char *arg)
|
||||
{
|
||||
struct predicate *new_pred;
|
||||
|
||||
@ -106,10 +106,10 @@ insert_primary_withpred (const struct parser_table *entry,
|
||||
|
||||
Fills in the following cells of the new predicate node:
|
||||
|
||||
pred_func PRED_FUNC
|
||||
args(.str) NULL
|
||||
p_type PRIMARY_TYPE
|
||||
p_prec NO_PREC
|
||||
pred_func PRED_FUNC
|
||||
args(.str) NULL
|
||||
p_type PRIMARY_TYPE
|
||||
p_prec NO_PREC
|
||||
|
||||
Other cells that need to be filled in are defaulted by
|
||||
get_new_pred_chk_op, which is used to ensure that the prior node is
|
||||
@ -138,18 +138,18 @@ show_valid_debug_options (int full)
|
||||
if (full)
|
||||
{
|
||||
for (i=0; i<N_DEBUGASSOC; ++i)
|
||||
{
|
||||
fprintf (stdout, "%-10s %s\n",
|
||||
debugassoc[i].name,
|
||||
debugassoc[i].docstring);
|
||||
}
|
||||
{
|
||||
fprintf (stdout, "%-10s %s\n",
|
||||
debugassoc[i].name,
|
||||
debugassoc[i].docstring);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i=0; i<N_DEBUGASSOC; ++i)
|
||||
{
|
||||
fprintf (stdout, "%s%s", (i>0 ? ", " : ""), debugassoc[i].name);
|
||||
}
|
||||
{
|
||||
fprintf (stdout, "%s%s", (i>0 ? ", " : " "), debugassoc[i].name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -188,8 +188,8 @@ Tests (N can be +N or -N or N):\n\
|
||||
-ctime N -empty -false -fstype TYPE -gid N -group NAME -ilname PATTERN\n\
|
||||
-iname PATTERN -inum N -iwholename PATTERN -iregex PATTERN\n\
|
||||
-links N -lname PATTERN -mmin N -mtime N -name PATTERN -newer FILE\n\
|
||||
-nouser -nogroup -path PATTERN -perm [-/]MODE -regex PATTERN\n\
|
||||
-readable -writable -executable\n\
|
||||
-newerXY REFERENCE -nouser -nogroup -path PATTERN -perm [-/]MODE\n\
|
||||
-regex PATTERN -readable -writable -executable\n\
|
||||
-wholename PATTERN -size N[bcwkMG] -true -type [bcdpflsD] -uid N\n\
|
||||
-used N -user NAME -xtype [bcdpfls]\n"));
|
||||
HTL (_("\n\
|
||||
@ -204,9 +204,13 @@ Other common options:\n"));
|
||||
HTL (_(" --help display this help and exit\n"));
|
||||
HTL (_(" --version output version information and exit\n\n"));
|
||||
|
||||
HTL (_("\n\
|
||||
In -newerXY, XY stands for the combination [aBcm][aBcmt]; see find(1).\n\
|
||||
\n"));
|
||||
|
||||
show_valid_debug_options (0);
|
||||
HTL (_("\n\
|
||||
Use '-D help' for a description of the options, or see find(1)\n\
|
||||
Use '-D help' for a description of the options, or see find(1).\n\
|
||||
\n"));
|
||||
|
||||
explain_how_to_report_bugs (stdout, program_name);
|
||||
@ -250,23 +254,23 @@ get_statinfo (const char *pathname, const char *name, struct stat *p)
|
||||
{
|
||||
set_stat_placeholders (p);
|
||||
if (0 == (*options.xstat) (name, p))
|
||||
{
|
||||
if (00000 == p->st_mode)
|
||||
{
|
||||
/* Savannah bug #16378. */
|
||||
error (0, 0, _("WARNING: file %s appears to have mode 0000"),
|
||||
quotearg_n_style (0, options.err_quoting_style, name));
|
||||
state.exit_status = EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
{
|
||||
if (00000 == p->st_mode)
|
||||
{
|
||||
/* Savannah bug #16378. */
|
||||
error (0, 0, _("WARNING: file %s appears to have mode 0000"),
|
||||
quotearg_n_style (0, options.err_quoting_style, name));
|
||||
state.exit_status = EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!options.ignore_readdir_race || (errno != ENOENT) )
|
||||
{
|
||||
nonfatal_target_file_error (errno, pathname);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
{
|
||||
if (!options.ignore_readdir_race || (errno != ENOENT) )
|
||||
{
|
||||
nonfatal_target_file_error (errno, pathname);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
state.have_stat = true;
|
||||
state.have_type = true;
|
||||
@ -280,8 +284,8 @@ get_statinfo (const char *pathname, const char *name, struct stat *p)
|
||||
*/
|
||||
static int
|
||||
get_info (const char *pathname,
|
||||
struct stat *p,
|
||||
struct predicate *pred_ptr)
|
||||
struct stat *p,
|
||||
struct predicate *pred_ptr)
|
||||
{
|
||||
bool todo = false;
|
||||
|
||||
@ -290,34 +294,34 @@ get_info (const char *pathname,
|
||||
*/
|
||||
if (pred_ptr->need_stat && !state.have_stat)
|
||||
{
|
||||
todo = true; /* need full stat info */
|
||||
todo = true; /* need full stat info */
|
||||
}
|
||||
else if (pred_ptr->need_type && !state.have_type)
|
||||
{
|
||||
todo = true; /* need to stat to get the type */
|
||||
todo = true; /* need to stat to get the type */
|
||||
}
|
||||
else if (pred_ptr->need_inum)
|
||||
{
|
||||
if (!p->st_ino)
|
||||
{
|
||||
todo = true; /* need to stat to get the inode number */
|
||||
}
|
||||
{
|
||||
todo = true; /* need to stat to get the inode number */
|
||||
}
|
||||
else if ((!state.have_type) || S_ISDIR(p->st_mode))
|
||||
{
|
||||
/* For now we decide not to trust struct dirent.d_ino for
|
||||
* directory entries that are subdirectories, in case this
|
||||
* subdirectory is a mount point. We also need to call a
|
||||
* stat function if we don't have st_ino (i.e. it is zero).
|
||||
*/
|
||||
todo = true;
|
||||
}
|
||||
{
|
||||
/* For now we decide not to trust struct dirent.d_ino for
|
||||
* directory entries that are subdirectories, in case this
|
||||
* subdirectory is a mount point. We also need to call a
|
||||
* stat function if we don't have st_ino (i.e. it is zero).
|
||||
*/
|
||||
todo = true;
|
||||
}
|
||||
}
|
||||
if (todo)
|
||||
{
|
||||
if (get_statinfo (pathname, state.rel_pathname, p) != 0)
|
||||
return -1; /* failure. */
|
||||
return -1; /* failure. */
|
||||
}
|
||||
return 0; /* success, or nothing to do. */
|
||||
return 0; /* success, or nothing to do. */
|
||||
}
|
||||
|
||||
/* Determine if we can use O_NOFOLLOW.
|
||||
@ -342,15 +346,15 @@ check_nofollow (void)
|
||||
release = conversion (uts.release);
|
||||
|
||||
if (0 == strcmp ("Linux", uts.sysname))
|
||||
{
|
||||
/* Linux kernels 2.1.126 and earlier ignore the O_NOFOLLOW flag. */
|
||||
return release >= 2.2f; /* close enough */
|
||||
}
|
||||
{
|
||||
/* Linux kernels 2.1.126 and earlier ignore the O_NOFOLLOW flag. */
|
||||
return release >= 2.2f; /* close enough */
|
||||
}
|
||||
else if (0 == strcmp ("FreeBSD", uts.sysname))
|
||||
{
|
||||
/* FreeBSD 3.0-CURRENT and later support it */
|
||||
return release >= 3.1f;
|
||||
}
|
||||
{
|
||||
/* FreeBSD 3.0-CURRENT and later support it */
|
||||
return release >= 3.1f;
|
||||
}
|
||||
}
|
||||
|
||||
/* Well, O_NOFOLLOW was defined, so we'll try to use it. */
|
||||
@ -404,18 +408,18 @@ do_complete_pending_execdirs (struct predicate *p)
|
||||
/* It's an exec-family predicate. p->args.exec_val is valid. */
|
||||
assert(predicate_uses_exec(p));
|
||||
if (p->args.exec_vec.multiple)
|
||||
{
|
||||
struct exec_val *execp = &p->args.exec_vec;
|
||||
{
|
||||
struct exec_val *execp = &p->args.exec_vec;
|
||||
|
||||
/* This one was terminated by '+' and so might have some
|
||||
* left... Run it if necessary.
|
||||
*/
|
||||
if (execp->state.todo)
|
||||
{
|
||||
/* There are not-yet-executed arguments. */
|
||||
do_exec (execp);
|
||||
}
|
||||
}
|
||||
/* This one was terminated by '+' and so might have some
|
||||
* left... Run it if necessary.
|
||||
*/
|
||||
if (execp->state.todo)
|
||||
{
|
||||
/* There are not-yet-executed arguments. */
|
||||
do_exec (execp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
do_complete_pending_execdirs (p->pred_right);
|
||||
@ -455,10 +459,10 @@ complete_pending_execs (struct predicate *p)
|
||||
* there are any problems.
|
||||
*/
|
||||
if (execp->state.todo)
|
||||
{
|
||||
/* There are not-yet-executed arguments. */
|
||||
bc_do_exec (&execp->ctl, &execp->state);
|
||||
}
|
||||
{
|
||||
/* There are not-yet-executed arguments. */
|
||||
bc_do_exec (&execp->ctl, &execp->state);
|
||||
}
|
||||
}
|
||||
|
||||
complete_pending_execs (p->pred_right);
|
||||
@ -471,9 +475,9 @@ record_initial_cwd (void)
|
||||
if (0 != save_cwd (initial_wd))
|
||||
{
|
||||
error (EXIT_FAILURE, errno,
|
||||
_("Failed to save initial working directory%s%s"),
|
||||
(initial_wd->desc < 0 && initial_wd->name) ? ": " : "",
|
||||
(initial_wd->desc < 0 && initial_wd->name) ? initial_wd->name : "");
|
||||
_("Failed to save initial working directory%s%s"),
|
||||
(initial_wd->desc < 0 && initial_wd->name) ? ": " : "",
|
||||
(initial_wd->desc < 0 && initial_wd->name) ? initial_wd->name : "");
|
||||
}
|
||||
}
|
||||
|
||||
@ -490,9 +494,9 @@ cleanup_initial_cwd (void)
|
||||
{
|
||||
/* since we may already be in atexit, die with _exit(). */
|
||||
error (0, errno,
|
||||
_("Failed to restore initial working directory%s%s"),
|
||||
(initial_wd->desc < 0 && initial_wd->name) ? ": " : "",
|
||||
(initial_wd->desc < 0 && initial_wd->name) ? initial_wd->name : "");
|
||||
_("Failed to restore initial working directory%s%s"),
|
||||
(initial_wd->desc < 0 && initial_wd->name) ? ": " : "",
|
||||
(initial_wd->desc < 0 && initial_wd->name) ? initial_wd->name : "");
|
||||
_exit (EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
@ -500,7 +504,7 @@ cleanup_initial_cwd (void)
|
||||
|
||||
static void
|
||||
traverse_tree (struct predicate *tree,
|
||||
void (*callback)(struct predicate*))
|
||||
void (*callback)(struct predicate*))
|
||||
{
|
||||
if (tree->pred_left)
|
||||
traverse_tree (tree->pred_left, callback);
|
||||
@ -571,7 +575,7 @@ fallback_stat (const char *name, struct stat *p, int prev_rv)
|
||||
case ENOENT:
|
||||
case ENOTDIR:
|
||||
if (options.debug_options & DebugStat)
|
||||
fprintf(stderr, "fallback_stat(): stat(%s) failed; falling back on lstat()\n", name);
|
||||
fprintf(stderr, "fallback_stat(): stat(%s) failed; falling back on lstat()\n", name);
|
||||
return fstatat(state.cwd_dir_fd, name, p, AT_SYMLINK_NOFOLLOW);
|
||||
|
||||
case EACCES:
|
||||
@ -579,7 +583,7 @@ fallback_stat (const char *name, struct stat *p, int prev_rv)
|
||||
case ELOOP:
|
||||
case ENAMETOOLONG:
|
||||
#ifdef EOVERFLOW
|
||||
case EOVERFLOW: /* EOVERFLOW is not #defined on UNICOS. */
|
||||
case EOVERFLOW: /* EOVERFLOW is not #defined on UNICOS. */
|
||||
#endif
|
||||
default:
|
||||
return prev_rv;
|
||||
@ -611,9 +615,9 @@ optionh_stat (const char *name, struct stat *p)
|
||||
int rv;
|
||||
rv = fstatat (state.cwd_dir_fd, name, p, 0);
|
||||
if (0 == rv)
|
||||
return 0; /* success */
|
||||
return 0; /* success */
|
||||
else
|
||||
return fallback_stat (name, p, rv);
|
||||
return fallback_stat (name, p, rv);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -637,7 +641,7 @@ optionl_stat(const char *name, struct stat *p)
|
||||
set_stat_placeholders (p);
|
||||
rv = fstatat (state.cwd_dir_fd, name, p, 0);
|
||||
if (0 == rv)
|
||||
return 0; /* normal case. */
|
||||
return 0; /* normal case. */
|
||||
else
|
||||
return fallback_stat (name, p, rv);
|
||||
}
|
||||
@ -698,10 +702,10 @@ following_links(void)
|
||||
*/
|
||||
bool
|
||||
digest_mode (mode_t *mode,
|
||||
const char *pathname,
|
||||
const char *name,
|
||||
struct stat *pstat,
|
||||
bool leaf)
|
||||
const char *pathname,
|
||||
const char *name,
|
||||
struct stat *pstat,
|
||||
bool leaf)
|
||||
{
|
||||
/* If we know the type of the directory entry, and it is not a
|
||||
* symbolic link, we may be able to avoid a stat() or lstat() call.
|
||||
@ -709,18 +713,18 @@ digest_mode (mode_t *mode,
|
||||
if (*mode)
|
||||
{
|
||||
if (S_ISLNK(*mode) && following_links())
|
||||
{
|
||||
/* mode is wrong because we should have followed the symlink. */
|
||||
if (get_statinfo (pathname, name, pstat) != 0)
|
||||
return false;
|
||||
*mode = state.type = pstat->st_mode;
|
||||
state.have_type = true;
|
||||
}
|
||||
{
|
||||
/* mode is wrong because we should have followed the symlink. */
|
||||
if (get_statinfo (pathname, name, pstat) != 0)
|
||||
return false;
|
||||
*mode = state.type = pstat->st_mode;
|
||||
state.have_type = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
state.have_type = true;
|
||||
pstat->st_mode = state.type = *mode;
|
||||
}
|
||||
{
|
||||
state.have_type = true;
|
||||
pstat->st_mode = state.type = *mode;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -729,24 +733,24 @@ digest_mode (mode_t *mode,
|
||||
* know at this stage)
|
||||
*/
|
||||
if (leaf)
|
||||
{
|
||||
state.have_stat = false;
|
||||
state.have_type = false;
|
||||
state.type = 0;
|
||||
}
|
||||
{
|
||||
state.have_stat = false;
|
||||
state.have_type = false;
|
||||
state.type = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (get_statinfo (pathname, name, pstat) != 0)
|
||||
return false;
|
||||
{
|
||||
if (get_statinfo (pathname, name, pstat) != 0)
|
||||
return false;
|
||||
|
||||
/* If -L is in effect and we are dealing with a symlink,
|
||||
* st_mode is the mode of the pointed-to file, while mode is
|
||||
* the mode of the directory entry (S_IFLNK). Hence now
|
||||
* that we have the stat information, override "mode".
|
||||
*/
|
||||
state.type = *mode = pstat->st_mode;
|
||||
state.have_type = true;
|
||||
}
|
||||
/* If -L is in effect and we are dealing with a symlink,
|
||||
* st_mode is the mode of the pointed-to file, while mode is
|
||||
* the mode of the directory entry (S_IFLNK). Hence now
|
||||
* that we have the stat information, override "mode".
|
||||
*/
|
||||
state.type = *mode = pstat->st_mode;
|
||||
state.have_type = true;
|
||||
}
|
||||
}
|
||||
|
||||
/* success. */
|
||||
@ -764,7 +768,7 @@ default_prints (struct predicate *pred)
|
||||
while (pred != NULL)
|
||||
{
|
||||
if (pred->no_default_print)
|
||||
return (false);
|
||||
return (false);
|
||||
pred = pred->pred_next;
|
||||
}
|
||||
return (true);
|
||||
@ -776,18 +780,18 @@ looks_like_expression (const char *arg, bool leading)
|
||||
switch (arg[0])
|
||||
{
|
||||
case '-':
|
||||
if (arg[1]) /* "-foo" is an expression. */
|
||||
return true;
|
||||
if (arg[1]) /* "-foo" is an expression. */
|
||||
return true;
|
||||
else
|
||||
return false; /* Just "-" is a filename. */
|
||||
return false; /* Just "-" is a filename. */
|
||||
break;
|
||||
|
||||
case ')':
|
||||
case ',':
|
||||
if (arg[1])
|
||||
return false; /* )x and ,z are not expressions */
|
||||
return false; /* )x and ,z are not expressions */
|
||||
else
|
||||
return !leading; /* A leading ) or , is not either */
|
||||
return !leading; /* A leading ) or , is not either */
|
||||
|
||||
/* ( and ! are part of an expression, but (2 and !foo are
|
||||
* filenames.
|
||||
@ -795,9 +799,9 @@ looks_like_expression (const char *arg, bool leading)
|
||||
case '!':
|
||||
case '(':
|
||||
if (arg[1])
|
||||
return false;
|
||||
return false;
|
||||
else
|
||||
return true;
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
@ -819,18 +823,18 @@ process_debug_options (char *arg)
|
||||
empty = false;
|
||||
|
||||
for (i=0; i<N_DEBUGASSOC; ++i)
|
||||
{
|
||||
if (0 == strcmp (debugassoc[i].name, p))
|
||||
{
|
||||
options.debug_options |= debugassoc[i].val;
|
||||
break;
|
||||
}
|
||||
}
|
||||
{
|
||||
if (0 == strcmp (debugassoc[i].name, p))
|
||||
{
|
||||
options.debug_options |= debugassoc[i].val;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i >= N_DEBUGASSOC)
|
||||
{
|
||||
error (0, 0, _("Ignoring unrecognised debug flag %s"),
|
||||
quotearg_n_style (0, options.err_quoting_style, arg));
|
||||
}
|
||||
{
|
||||
error (0, 0, _("Ignoring unrecognised debug flag %s"),
|
||||
quotearg_n_style (0, options.err_quoting_style, arg));
|
||||
}
|
||||
p = strtok_r (NULL, delimiters, &token_context);
|
||||
}
|
||||
if (empty)
|
||||
@ -852,7 +856,7 @@ process_optimisation_option (const char *arg)
|
||||
if (0 == arg[0])
|
||||
{
|
||||
error (EXIT_FAILURE, 0,
|
||||
_("The -O option must be immediately followed by a decimal integer"));
|
||||
_("The -O option must be immediately followed by a decimal integer"));
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -860,48 +864,48 @@ process_optimisation_option (const char *arg)
|
||||
char *end;
|
||||
|
||||
if (!isdigit ( (unsigned char) arg[0] ))
|
||||
{
|
||||
error (EXIT_FAILURE, 0,
|
||||
_("Please specify a decimal number immediately after -O"));
|
||||
}
|
||||
{
|
||||
error (EXIT_FAILURE, 0,
|
||||
_("Please specify a decimal number immediately after -O"));
|
||||
}
|
||||
else
|
||||
{
|
||||
int prev_errno = errno;
|
||||
errno = 0;
|
||||
{
|
||||
int prev_errno = errno;
|
||||
errno = 0;
|
||||
|
||||
opt_level = strtoul (arg, &end, 10);
|
||||
if ( (0==opt_level) && (end==arg) )
|
||||
{
|
||||
error (EXIT_FAILURE, 0,
|
||||
_("Please specify a decimal number immediately after -O"));
|
||||
}
|
||||
else if (*end)
|
||||
{
|
||||
/* unwanted trailing characters. */
|
||||
error (EXIT_FAILURE, 0, _("Invalid optimisation level %s"), arg);
|
||||
}
|
||||
else if ( (ULONG_MAX==opt_level) && errno)
|
||||
{
|
||||
error (EXIT_FAILURE, errno,
|
||||
_("Invalid optimisation level %s"), arg);
|
||||
}
|
||||
else if (opt_level > USHRT_MAX)
|
||||
{
|
||||
/* tricky to test, as on some platforms USHORT_MAX and ULONG_MAX
|
||||
* can have the same value, though this is unusual.
|
||||
*/
|
||||
error (EXIT_FAILURE, 0,
|
||||
_("Optimisation level %lu is too high. "
|
||||
"If you want to find files very quickly, "
|
||||
"consider using GNU locate."),
|
||||
opt_level);
|
||||
}
|
||||
else
|
||||
{
|
||||
options.optimisation_level = opt_level;
|
||||
errno = prev_errno;
|
||||
}
|
||||
}
|
||||
opt_level = strtoul (arg, &end, 10);
|
||||
if ( (0==opt_level) && (end==arg) )
|
||||
{
|
||||
error (EXIT_FAILURE, 0,
|
||||
_("Please specify a decimal number immediately after -O"));
|
||||
}
|
||||
else if (*end)
|
||||
{
|
||||
/* unwanted trailing characters. */
|
||||
error (EXIT_FAILURE, 0, _("Invalid optimisation level %s"), arg);
|
||||
}
|
||||
else if ( (ULONG_MAX==opt_level) && errno)
|
||||
{
|
||||
error (EXIT_FAILURE, errno,
|
||||
_("Invalid optimisation level %s"), arg);
|
||||
}
|
||||
else if (opt_level > USHRT_MAX)
|
||||
{
|
||||
/* tricky to test, as on some platforms USHORT_MAX and ULONG_MAX
|
||||
* can have the same value, though this is unusual.
|
||||
*/
|
||||
error (EXIT_FAILURE, 0,
|
||||
_("Optimisation level %lu is too high. "
|
||||
"If you want to find files very quickly, "
|
||||
"consider using GNU locate."),
|
||||
opt_level);
|
||||
}
|
||||
else
|
||||
{
|
||||
options.optimisation_level = opt_level;
|
||||
errno = prev_errno;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -913,73 +917,53 @@ process_leading_options (int argc, char *argv[])
|
||||
for (i=1; (end_of_leading_options = i) < argc; ++i)
|
||||
{
|
||||
if (0 == strcmp ("-H", argv[i]))
|
||||
{
|
||||
/* Meaning: dereference symbolic links on command line, but nowhere else. */
|
||||
set_follow_state (SYMLINK_DEREF_ARGSONLY);
|
||||
}
|
||||
{
|
||||
/* Meaning: dereference symbolic links on command line, but nowhere else. */
|
||||
set_follow_state (SYMLINK_DEREF_ARGSONLY);
|
||||
}
|
||||
else if (0 == strcmp ("-L", argv[i]))
|
||||
{
|
||||
/* Meaning: dereference all symbolic links. */
|
||||
set_follow_state (SYMLINK_ALWAYS_DEREF);
|
||||
}
|
||||
{
|
||||
/* Meaning: dereference all symbolic links. */
|
||||
set_follow_state (SYMLINK_ALWAYS_DEREF);
|
||||
}
|
||||
else if (0 == strcmp ("-P", argv[i]))
|
||||
{
|
||||
/* Meaning: never dereference symbolic links (default). */
|
||||
set_follow_state (SYMLINK_NEVER_DEREF);
|
||||
}
|
||||
{
|
||||
/* Meaning: never dereference symbolic links (default). */
|
||||
set_follow_state (SYMLINK_NEVER_DEREF);
|
||||
}
|
||||
else if (0 == strcmp ("--", argv[i]))
|
||||
{
|
||||
/* -- signifies the end of options. */
|
||||
end_of_leading_options = i+1; /* Next time start with the next option */
|
||||
break;
|
||||
}
|
||||
{
|
||||
/* -- signifies the end of options. */
|
||||
end_of_leading_options = i+1; /* Next time start with the next option */
|
||||
break;
|
||||
}
|
||||
else if (0 == strcmp ("-D", argv[i]))
|
||||
{
|
||||
if (argc <= i+1)
|
||||
{
|
||||
error (0, 0, _("Missing argument after the -D option."));
|
||||
usage (EXIT_FAILURE);
|
||||
}
|
||||
process_debug_options (argv[i+1]);
|
||||
++i; /* skip the argument too. */
|
||||
}
|
||||
{
|
||||
if (argc <= i+1)
|
||||
{
|
||||
error (0, 0, _("Missing argument after the -D option."));
|
||||
usage (EXIT_FAILURE);
|
||||
}
|
||||
process_debug_options (argv[i+1]);
|
||||
++i; /* skip the argument too. */
|
||||
}
|
||||
else if (0 == strncmp ("-O", argv[i], 2))
|
||||
{
|
||||
process_optimisation_option (argv[i]+2);
|
||||
}
|
||||
{
|
||||
process_optimisation_option (argv[i]+2);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Hmm, must be one of
|
||||
* (a) A path name
|
||||
* (b) A predicate
|
||||
*/
|
||||
end_of_leading_options = i; /* Next time start with this option */
|
||||
break;
|
||||
}
|
||||
{
|
||||
/* Hmm, must be one of
|
||||
* (a) A path name
|
||||
* (b) A predicate
|
||||
*/
|
||||
end_of_leading_options = i; /* Next time start with this option */
|
||||
break;
|
||||
}
|
||||
}
|
||||
return end_of_leading_options;
|
||||
}
|
||||
|
||||
static struct timespec
|
||||
now(void)
|
||||
{
|
||||
struct timespec retval;
|
||||
struct timeval tv;
|
||||
time_t t;
|
||||
|
||||
if (0 == gettimeofday (&tv, NULL))
|
||||
{
|
||||
retval.tv_sec = tv.tv_sec;
|
||||
retval.tv_nsec = tv.tv_usec * 1000; /* convert unit from microseconds to nanoseconds */
|
||||
return retval;
|
||||
}
|
||||
t = time (NULL);
|
||||
assert (t != (time_t)-1);
|
||||
retval.tv_sec = t;
|
||||
retval.tv_nsec = 0;
|
||||
return retval;
|
||||
}
|
||||
|
||||
void
|
||||
set_option_defaults (struct options *p)
|
||||
{
|
||||
@ -989,7 +973,7 @@ set_option_defaults (struct options *p)
|
||||
p->posixly_correct = false;
|
||||
|
||||
/* We call check_nofollow() before setlocale() because the numbers
|
||||
* for which we check (in the results of uname) definitiely have "."
|
||||
* for which we check (in the results of uname) definitely have "."
|
||||
* as the decimal point indicator even under locales for which that
|
||||
* is not normally true. Hence atof would do the wrong thing
|
||||
* if we call it after setlocale().
|
||||
@ -1021,12 +1005,12 @@ set_option_defaults (struct options *p)
|
||||
p->explicit_depth = false;
|
||||
p->maxdepth = p->mindepth = -1;
|
||||
|
||||
p->start_time = now ();
|
||||
p->start_time = current_timespec ();
|
||||
p->cur_day_start.tv_sec = p->start_time.tv_sec - DAYSECS;
|
||||
p->cur_day_start.tv_nsec = p->start_time.tv_nsec;
|
||||
|
||||
p->full_days = false;
|
||||
p->stay_on_filesystem = false;
|
||||
p->mount = p->xdev = false;
|
||||
p->ignore_readdir_race = false;
|
||||
|
||||
if (p->posixly_correct)
|
||||
@ -1040,9 +1024,9 @@ set_option_defaults (struct options *p)
|
||||
if (getenv ("FIND_BLOCK_SIZE"))
|
||||
{
|
||||
error (EXIT_FAILURE, 0,
|
||||
_("The environment variable FIND_BLOCK_SIZE is not supported, "
|
||||
"the only thing that affects the block size is the "
|
||||
"POSIXLY_CORRECT environment variable"));
|
||||
_("The environment variable FIND_BLOCK_SIZE is not supported, "
|
||||
"the only thing that affects the block size is the "
|
||||
"POSIXLY_CORRECT environment variable"));
|
||||
}
|
||||
|
||||
#if LEAF_OPTIMISATION
|
||||
@ -1074,7 +1058,7 @@ apply_predicate(const char *pathname, struct stat *stat_buf, struct predicate *p
|
||||
{
|
||||
/* We may need a stat here. */
|
||||
if (get_info(pathname, stat_buf, p) != 0)
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
if ((p->pred_func)(pathname, stat_buf, p))
|
||||
{
|
||||
@ -1110,7 +1094,7 @@ safely_quote_err_filename (int n, char const *arg)
|
||||
*/
|
||||
static void
|
||||
report_file_err(int exitval, int errno_value,
|
||||
bool is_target_file, const char *name)
|
||||
bool is_target_file, const char *name)
|
||||
{
|
||||
/* It is important that the errno value is passed in as a function
|
||||
* argument before we call safely_quote_err_filename(), because otherwise
|
||||
|
||||
2
gnulib
2
gnulib
@ -1 +1 @@
|
||||
Subproject commit 623bcc22f4744b409ac5e1c00c3b6fd6494b49ce
|
||||
Subproject commit 43d801a0234994cf97f5d7c34a5fb9b23b9be55a
|
||||
@ -1,6 +1,6 @@
|
||||
/* gcc-function-attribtues.h -- GCC-specific function attributes
|
||||
|
||||
Copyright (C) 2016-2024 Free Software Foundation, Inc.
|
||||
Copyright (C) 2016-2026 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
|
||||
|
||||
4
init.cfg
4
init.cfg
@ -1,6 +1,6 @@
|
||||
# This file is sourced by init.sh, *before* its initialization.
|
||||
|
||||
# Copyright (C) 2010-2024 Free Software Foundation, Inc.
|
||||
# Copyright (C) 2010-2026 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
|
||||
@ -560,7 +560,7 @@ require_sparse_support_()
|
||||
|
||||
# Compile a shared lib using the GCC options for doing so.
|
||||
# Pass input and output file as parameters respectively.
|
||||
# Any other optional parmeters are passed to $CC.
|
||||
# Any other optional parameters are passed to $CC.
|
||||
gcc_shared_()
|
||||
{
|
||||
local in=$1
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
## Process this file with automake to produce Makefile.in.
|
||||
|
||||
## Copyright (C) 1996-2024 Free Software Foundation, Inc.
|
||||
## Copyright (C) 1996-2026 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
|
||||
@ -24,7 +24,7 @@ noinst_LIBRARIES = libfind.a
|
||||
check_PROGRAMS = regexprops test_splitstring
|
||||
check_SCRIPTS = check-regexprops
|
||||
regexprops_SOURCES = regexprops.c regextype.c
|
||||
regexprops_LDADD = $(LDADD) $(LIB_SETLOCALE_NULL) $(LIB_MBRTOWC)
|
||||
regexprops_LDADD = $(LDADD) $(SETLOCALE_NULL_LIB) $(MBRTOWC_LIB)
|
||||
|
||||
TESTS =
|
||||
if CROSS_COMPILING
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/* bugreports.h -- explain how to report bugs
|
||||
Copyright (C) 2016-2024 Free Software Foundation, Inc.
|
||||
Copyright (C) 2016-2026 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
|
||||
@ -31,9 +31,9 @@ explain_how_to_report_bugs (FILE *f, const char *program_name)
|
||||
"program via the %s bug-reporting page at\n"
|
||||
"%s or, if\n"
|
||||
"you have no web access, by sending email to <%s>.\n"),
|
||||
PACKAGE_URL,
|
||||
program_name,
|
||||
PACKAGE_NAME,
|
||||
PACKAGE_BUGREPORT_URL,
|
||||
PACKAGE_BUGREPORT);
|
||||
PACKAGE_URL,
|
||||
program_name,
|
||||
PACKAGE_NAME,
|
||||
PACKAGE_BUGREPORT_URL,
|
||||
PACKAGE_BUGREPORT);
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/* bugreports.h -- explain how to report bugs
|
||||
Copyright (C) 2016-2024 Free Software Foundation, Inc.
|
||||
Copyright (C) 2016-2026 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
|
||||
|
||||
180
lib/buildcmd.c
180
lib/buildcmd.c
@ -1,5 +1,5 @@
|
||||
/* buildcmd.c -- build command lines from a list of arguments.
|
||||
Copyright (C) 1990-2024 Free Software Foundation, Inc.
|
||||
Copyright (C) 1990-2026 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
|
||||
@ -55,7 +55,7 @@ static const char *special_terminating_arg = "do_not_care";
|
||||
/* Add a terminator to the argument list. */
|
||||
static void
|
||||
bc_args_complete (struct buildcmd_control *ctl,
|
||||
struct buildcmd_state *state)
|
||||
struct buildcmd_state *state)
|
||||
{
|
||||
bc_push_arg (ctl, state, special_terminating_arg, 0, NULL, 0, 0);
|
||||
}
|
||||
@ -112,7 +112,7 @@ bc_do_insert (struct buildcmd_control *ctl,
|
||||
if (bytes_left <= len)
|
||||
break;
|
||||
else
|
||||
bytes_left -= len;
|
||||
bytes_left -= len;
|
||||
|
||||
strncpy (p, arg, len);
|
||||
p += len;
|
||||
@ -121,16 +121,16 @@ bc_do_insert (struct buildcmd_control *ctl,
|
||||
|
||||
if (s)
|
||||
{
|
||||
if (bytes_left <= (lblen + pfxlen))
|
||||
break;
|
||||
else
|
||||
bytes_left -= (lblen + pfxlen);
|
||||
if (bytes_left <= (lblen + pfxlen))
|
||||
break;
|
||||
else
|
||||
bytes_left -= (lblen + pfxlen);
|
||||
|
||||
if (prefix)
|
||||
{
|
||||
strcpy (p, prefix);
|
||||
p += pfxlen;
|
||||
}
|
||||
if (prefix)
|
||||
{
|
||||
strcpy (p, prefix);
|
||||
p += pfxlen;
|
||||
}
|
||||
strcpy (p, linebuf);
|
||||
p += lblen;
|
||||
|
||||
@ -144,7 +144,7 @@ bc_do_insert (struct buildcmd_control *ctl,
|
||||
*p++ = '\0';
|
||||
|
||||
bc_push_arg (ctl, state,
|
||||
insertbuf, p - insertbuf,
|
||||
insertbuf, p - insertbuf,
|
||||
NULL, 0,
|
||||
initial_args);
|
||||
}
|
||||
@ -155,55 +155,55 @@ bc_do_insert (struct buildcmd_control *ctl,
|
||||
*/
|
||||
static size_t
|
||||
update_limit (struct buildcmd_control *ctl,
|
||||
struct buildcmd_state *state,
|
||||
bool success,
|
||||
size_t limit)
|
||||
struct buildcmd_state *state,
|
||||
bool success,
|
||||
size_t limit)
|
||||
{
|
||||
if (success)
|
||||
{
|
||||
if (limit > state->largest_successful_arg_count)
|
||||
state->largest_successful_arg_count = limit;
|
||||
state->largest_successful_arg_count = limit;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (limit < state->smallest_failed_arg_count
|
||||
|| (0 == state->smallest_failed_arg_count))
|
||||
state->smallest_failed_arg_count = limit;
|
||||
|| (0 == state->smallest_failed_arg_count))
|
||||
state->smallest_failed_arg_count = limit;
|
||||
}
|
||||
|
||||
if (0 == (state->largest_successful_arg_count)
|
||||
|| (state->smallest_failed_arg_count <= state->largest_successful_arg_count))
|
||||
{
|
||||
/* No success yet, or running on a system which has
|
||||
limits on total argv length, but not arg count. */
|
||||
limits on total argv length, but not arg count. */
|
||||
if (success)
|
||||
{
|
||||
if (limit < SIZE_MAX)
|
||||
++limit;
|
||||
}
|
||||
{
|
||||
if (limit < SIZE_MAX)
|
||||
++limit;
|
||||
}
|
||||
else
|
||||
{
|
||||
limit /= 2;
|
||||
}
|
||||
{
|
||||
limit /= 2;
|
||||
}
|
||||
}
|
||||
else /* We can use bisection. */
|
||||
{
|
||||
const size_t shift = (state->smallest_failed_arg_count
|
||||
- state->largest_successful_arg_count) / 2;
|
||||
- state->largest_successful_arg_count) / 2;
|
||||
if (success)
|
||||
{
|
||||
if (shift)
|
||||
limit += shift;
|
||||
else
|
||||
++limit;
|
||||
}
|
||||
{
|
||||
if (shift)
|
||||
limit += shift;
|
||||
else
|
||||
++limit;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (shift)
|
||||
limit -= shift;
|
||||
else
|
||||
--limit;
|
||||
}
|
||||
{
|
||||
if (shift)
|
||||
limit -= shift;
|
||||
else
|
||||
--limit;
|
||||
}
|
||||
}
|
||||
|
||||
/* Make sure the returned value is such that progress is
|
||||
@ -223,8 +223,8 @@ update_limit (struct buildcmd_control *ctl,
|
||||
*/
|
||||
static size_t
|
||||
copy_args (struct buildcmd_control *ctl,
|
||||
struct buildcmd_state *state,
|
||||
char** working_args, size_t limit, size_t done)
|
||||
struct buildcmd_state *state,
|
||||
char** working_args, size_t limit, size_t done)
|
||||
{
|
||||
size_t dst_pos = 0;
|
||||
size_t src_pos = 0;
|
||||
@ -249,7 +249,7 @@ copy_args (struct buildcmd_control *ctl,
|
||||
/* Execute the program with the currently-built list of arguments. */
|
||||
void
|
||||
bc_do_exec (struct buildcmd_control *ctl,
|
||||
struct buildcmd_state *state)
|
||||
struct buildcmd_state *state)
|
||||
{
|
||||
char** working_args;
|
||||
size_t limit, done;
|
||||
@ -266,28 +266,28 @@ bc_do_exec (struct buildcmd_control *ctl,
|
||||
|
||||
do
|
||||
{
|
||||
const size_t dst_pos = copy_args (ctl, state, working_args,
|
||||
limit, done);
|
||||
if (ctl->exec_callback (ctl, state->usercontext, dst_pos, working_args))
|
||||
{
|
||||
limit = update_limit (ctl, state, true, limit);
|
||||
done += (dst_pos - ctl->initial_argc);
|
||||
}
|
||||
else /* got E2BIG, adjust arguments */
|
||||
{
|
||||
if (limit <= ctl->initial_argc + 1)
|
||||
{
|
||||
/* No room to reduce the length of the argument list.
|
||||
Issue an error message and give up. */
|
||||
error (EXIT_FAILURE, 0,
|
||||
_("can't call exec() due to argument size restrictions"));
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Try fewer arguments. */
|
||||
limit = update_limit (ctl, state, false, limit);
|
||||
}
|
||||
}
|
||||
const size_t dst_pos = copy_args (ctl, state, working_args,
|
||||
limit, done);
|
||||
if (ctl->exec_callback (ctl, state->usercontext, dst_pos, working_args))
|
||||
{
|
||||
limit = update_limit (ctl, state, true, limit);
|
||||
done += (dst_pos - ctl->initial_argc);
|
||||
}
|
||||
else /* got E2BIG, adjust arguments */
|
||||
{
|
||||
if (limit <= ctl->initial_argc + 1)
|
||||
{
|
||||
/* No room to reduce the length of the argument list.
|
||||
Issue an error message and give up. */
|
||||
error (EXIT_FAILURE, 0,
|
||||
_("can't call exec() due to argument size restrictions"));
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Try fewer arguments. */
|
||||
limit = update_limit (ctl, state, false, limit);
|
||||
}
|
||||
}
|
||||
}
|
||||
while ((done + 1) < (state->cmd_argc - ctl->initial_argc));
|
||||
/* (state->cmd_argc - ctl->initial_argc) includes the terminating NULL,
|
||||
@ -307,8 +307,8 @@ bc_do_exec (struct buildcmd_control *ctl,
|
||||
*/
|
||||
static int
|
||||
bc_argc_limit_reached (int initial_args,
|
||||
const struct buildcmd_control *ctl,
|
||||
struct buildcmd_state *state)
|
||||
const struct buildcmd_control *ctl,
|
||||
struct buildcmd_state *state)
|
||||
{
|
||||
/* Check to see if we about to exceed a limit set by xargs' -n option */
|
||||
if (!initial_args && ctl->args_per_exec &&
|
||||
@ -379,7 +379,7 @@ bc_push_arg (struct buildcmd_control *ctl,
|
||||
{
|
||||
state->cmd_argv_alloc *= 2;
|
||||
state->cmd_argv = xrealloc (state->cmd_argv,
|
||||
sizeof (char *) * state->cmd_argv_alloc);
|
||||
sizeof (char *) * state->cmd_argv_alloc);
|
||||
}
|
||||
}
|
||||
|
||||
@ -401,9 +401,9 @@ bc_push_arg (struct buildcmd_control *ctl,
|
||||
* do the exec immediately.
|
||||
*/
|
||||
if (bc_argc_limit_reached (initial_args, ctl, state))
|
||||
{
|
||||
bc_do_exec (ctl, state);
|
||||
}
|
||||
{
|
||||
bc_do_exec (ctl, state);
|
||||
}
|
||||
}
|
||||
|
||||
/* If this is an initial argument, set the high-water mark. */
|
||||
@ -453,9 +453,9 @@ bc_get_arg_max (void)
|
||||
|
||||
static int
|
||||
cb_exec_noop (struct buildcmd_control * ctl,
|
||||
void *usercontext,
|
||||
int argc,
|
||||
char **argv)
|
||||
void *usercontext,
|
||||
int argc,
|
||||
char **argv)
|
||||
{
|
||||
/* does nothing. */
|
||||
(void) ctl;
|
||||
@ -483,7 +483,7 @@ bc_size_of_environment (void)
|
||||
|
||||
enum BC_INIT_STATUS
|
||||
bc_init_controlinfo (struct buildcmd_control *ctl,
|
||||
size_t headroom)
|
||||
size_t headroom)
|
||||
{
|
||||
size_t size_of_environment = bc_size_of_environment ();
|
||||
|
||||
@ -557,8 +557,8 @@ bc_use_sensible_arg_max (struct buildcmd_control *ctl)
|
||||
|
||||
void
|
||||
bc_init_state (const struct buildcmd_control *ctl,
|
||||
struct buildcmd_state *state,
|
||||
void *context)
|
||||
struct buildcmd_state *state,
|
||||
void *context)
|
||||
{
|
||||
state->cmd_argc = 0;
|
||||
state->cmd_argv_chars = 0;
|
||||
@ -583,7 +583,7 @@ bc_init_state (const struct buildcmd_control *ctl,
|
||||
|
||||
void
|
||||
bc_clear_args (const struct buildcmd_control *ctl,
|
||||
struct buildcmd_state *state)
|
||||
struct buildcmd_state *state)
|
||||
{
|
||||
state->cmd_argc = ctl->initial_argc;
|
||||
state->cmd_argv_chars = state->cmd_initial_argv_chars;
|
||||
@ -605,18 +605,18 @@ exceeds (const char *env_var_name, size_t quantity)
|
||||
unsigned long limit;
|
||||
|
||||
if (xstrtoul (val, &tmp, 10, &limit, NULL) == LONGINT_OK)
|
||||
{
|
||||
if (quantity > limit)
|
||||
return 1;
|
||||
}
|
||||
{
|
||||
if (quantity > limit)
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
error (EXIT_FAILURE, errno,
|
||||
_("Environment variable %s is not set to a "
|
||||
"valid decimal number"),
|
||||
env_var_name);
|
||||
return 0;
|
||||
}
|
||||
{
|
||||
error (EXIT_FAILURE, errno,
|
||||
_("Environment variable %s is not set to a "
|
||||
"valid decimal number"),
|
||||
env_var_name);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -637,5 +637,5 @@ bc_args_exceed_testing_limit (char **argv)
|
||||
}
|
||||
|
||||
return (exceeds ("__GNU_FINDUTILS_EXEC_ARG_COUNT_LIMIT", args) ||
|
||||
exceeds ("__GNU_FINDUTILS_EXEC_ARG_LENGTH_LIMIT", chars));
|
||||
exceeds ("__GNU_FINDUTILS_EXEC_ARG_LENGTH_LIMIT", chars));
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/* buildcmd.[ch] -- build command lines from a stream of arguments
|
||||
Copyright (C) 2005-2024 Free Software Foundation, Inc.
|
||||
Copyright (C) 2005-2026 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
|
||||
@ -25,7 +25,7 @@
|
||||
struct buildcmd_state
|
||||
{
|
||||
/* Number of valid elements in `cmd_argv', including terminating NULL. */
|
||||
size_t cmd_argc; /* 0 */
|
||||
size_t cmd_argc; /* 0 */
|
||||
|
||||
/* The list of args being built. */
|
||||
char **cmd_argv; /* NULL */
|
||||
@ -90,14 +90,14 @@ struct buildcmd_control
|
||||
const char *replace_pat;
|
||||
|
||||
/* Number of initial arguments given on the command line. */
|
||||
size_t initial_argc; /* 0 */
|
||||
size_t initial_argc; /* 0 */
|
||||
|
||||
/* exec callback. */
|
||||
int (*exec_callback)(struct buildcmd_control *, void *usercontext, int argc, char **argv);
|
||||
|
||||
/* If nonzero, the maximum number of nonblank lines from stdin to use
|
||||
per command line. */
|
||||
unsigned long lines_per_exec; /* 0 */
|
||||
unsigned long lines_per_exec; /* 0 */
|
||||
|
||||
/* The maximum number of arguments to use per command line. */
|
||||
size_t args_per_exec;
|
||||
@ -114,30 +114,30 @@ extern size_t bc_size_of_environment (void);
|
||||
|
||||
|
||||
extern void bc_do_insert (struct buildcmd_control *ctl,
|
||||
struct buildcmd_state *state,
|
||||
char *arg, size_t arglen,
|
||||
const char *prefix, size_t pfxlen,
|
||||
const char *linebuf, size_t lblen,
|
||||
int initial_args);
|
||||
struct buildcmd_state *state,
|
||||
char *arg, size_t arglen,
|
||||
const char *prefix, size_t pfxlen,
|
||||
const char *linebuf, size_t lblen,
|
||||
int initial_args);
|
||||
|
||||
extern void bc_do_exec (struct buildcmd_control *ctl,
|
||||
struct buildcmd_state *state);
|
||||
struct buildcmd_state *state);
|
||||
|
||||
extern void bc_push_arg (struct buildcmd_control *ctl,
|
||||
struct buildcmd_state *state,
|
||||
const char *arg, size_t len,
|
||||
const char *prefix, size_t pfxlen,
|
||||
int initial_args);
|
||||
struct buildcmd_state *state,
|
||||
const char *arg, size_t len,
|
||||
const char *prefix, size_t pfxlen,
|
||||
int initial_args);
|
||||
|
||||
extern void bc_init_state(const struct buildcmd_control *ctl,
|
||||
struct buildcmd_state *state,
|
||||
void *usercontext);
|
||||
struct buildcmd_state *state,
|
||||
void *usercontext);
|
||||
extern enum BC_INIT_STATUS bc_init_controlinfo(struct buildcmd_control *ctl,
|
||||
size_t arglen_headroom);
|
||||
size_t arglen_headroom);
|
||||
extern size_t bc_get_arg_max(void);
|
||||
extern void bc_use_sensible_arg_max(struct buildcmd_control *ctl);
|
||||
extern void bc_clear_args(const struct buildcmd_control *ctl,
|
||||
struct buildcmd_state *state);
|
||||
struct buildcmd_state *state);
|
||||
bool bc_args_exceed_testing_limit(char **argv);
|
||||
|
||||
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
#! /bin/sh
|
||||
# Generate regexprops.texi and compare it against the checked-in version.
|
||||
#
|
||||
# Copyright (C) 2009-2024 Free Software Foundation, Inc.
|
||||
# Copyright (C) 2009-2026 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
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/* listfile.c -- run a function in a specific directory
|
||||
Copyright (C) 2007-2024 Free Software Foundation, Inc.
|
||||
Copyright (C) 2007-2026 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
|
||||
@ -36,7 +36,7 @@
|
||||
|
||||
int
|
||||
run_in_dir (const struct saved_cwd *there,
|
||||
int (*callback)(void*), void *usercontext)
|
||||
int (*callback)(void*), void *usercontext)
|
||||
{
|
||||
int err = -1;
|
||||
int saved_errno = 0;
|
||||
@ -44,17 +44,17 @@ run_in_dir (const struct saved_cwd *there,
|
||||
if (0 == save_cwd (&here))
|
||||
{
|
||||
if (0 == restore_cwd (there))
|
||||
{
|
||||
err = callback(usercontext);
|
||||
saved_errno = (err < 0 ? errno : 0);
|
||||
}
|
||||
{
|
||||
err = callback(usercontext);
|
||||
saved_errno = (err < 0 ? errno : 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
openat_restore_fail (errno);
|
||||
}
|
||||
{
|
||||
openat_restore_fail (errno);
|
||||
}
|
||||
|
||||
if (restore_cwd (&here) != 0)
|
||||
openat_restore_fail (errno);
|
||||
openat_restore_fail (errno);
|
||||
|
||||
free_cwd (&here);
|
||||
}
|
||||
@ -82,26 +82,26 @@ run_in_dirfd (int dir_fd, int (*callback)(void*), void *usercontext)
|
||||
int err;
|
||||
|
||||
if (save_cwd (&saved_cwd) != 0)
|
||||
openat_save_fail (errno);
|
||||
openat_save_fail (errno);
|
||||
|
||||
if (fchdir (dir_fd) != 0)
|
||||
{
|
||||
saved_errno = errno;
|
||||
free_cwd (&saved_cwd);
|
||||
errno = saved_errno;
|
||||
return -1;
|
||||
}
|
||||
{
|
||||
saved_errno = errno;
|
||||
free_cwd (&saved_cwd);
|
||||
errno = saved_errno;
|
||||
return -1;
|
||||
}
|
||||
|
||||
err = (*callback)(usercontext);
|
||||
saved_errno = (err < 0 ? errno : 0);
|
||||
|
||||
if (restore_cwd (&saved_cwd) != 0)
|
||||
openat_restore_fail (errno);
|
||||
openat_restore_fail (errno);
|
||||
|
||||
free_cwd (&saved_cwd);
|
||||
|
||||
if (saved_errno)
|
||||
errno = saved_errno;
|
||||
errno = saved_errno;
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/* listfile.h -- display a long listing of a file
|
||||
Copyright (C) 2007-2024 Free Software Foundation, Inc.
|
||||
Copyright (C) 2007-2026 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
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/* extendbuf.c -- manage a dynamically-allocated buffer
|
||||
|
||||
Copyright (C) 2004-2024 Free Software Foundation, Inc.
|
||||
Copyright (C) 2004-2026 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
|
||||
@ -52,7 +52,7 @@ decide_size (size_t current, size_t wanted)
|
||||
while (newsize < wanted)
|
||||
{
|
||||
if (2 * newsize < newsize)
|
||||
return wanted;
|
||||
return wanted;
|
||||
newsize *= 2;
|
||||
}
|
||||
return newsize;
|
||||
@ -84,24 +84,24 @@ extendbuf (void* existing, size_t wanted, size_t *allocated)
|
||||
else
|
||||
{
|
||||
if (newsize != (*allocated) )
|
||||
{
|
||||
(*allocated) = newsize;
|
||||
result = realloc (existing, newsize);
|
||||
if (NULL == result)
|
||||
{
|
||||
saved_errno = errno;
|
||||
}
|
||||
}
|
||||
{
|
||||
(*allocated) = newsize;
|
||||
result = realloc (existing, newsize);
|
||||
if (NULL == result)
|
||||
{
|
||||
saved_errno = errno;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result = existing;
|
||||
}
|
||||
{
|
||||
result = existing;
|
||||
}
|
||||
}
|
||||
|
||||
if (result)
|
||||
{
|
||||
/* malloc () or realloc () may have changed errno, but in the
|
||||
success case we want to preserve the previous value.
|
||||
success case we want to preserve the previous value.
|
||||
*/
|
||||
errno = saved_errno;
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/* extendbuf.h -- Manage a dynamically-alloicated buffer
|
||||
|
||||
Copyright (C) 2004-2024 Free Software Foundation, Inc.
|
||||
Copyright (C) 2004-2026 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
|
||||
|
||||
164
lib/fdleak.c
164
lib/fdleak.c
@ -1,5 +1,5 @@
|
||||
/* fdleak.c -- detect file descriptor leaks
|
||||
Copyright (C) 2010-2024 Free Software Foundation, Inc.
|
||||
Copyright (C) 2010-2026 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
|
||||
@ -73,31 +73,31 @@ get_proc_max_fd (void)
|
||||
|
||||
while (1)
|
||||
{
|
||||
errno = 0;
|
||||
dent = readdir (dir);
|
||||
if (NULL == dent)
|
||||
{
|
||||
if (errno)
|
||||
{
|
||||
error (0, errno, "%s", quotearg_n_style (0, locale_quoting_style, path));
|
||||
good = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
errno = 0;
|
||||
dent = readdir (dir);
|
||||
if (NULL == dent)
|
||||
{
|
||||
if (errno)
|
||||
{
|
||||
error (0, errno, "%s", quotearg_n_style (0, locale_quoting_style, path));
|
||||
good = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (dent->d_name[0] != '.'
|
||||
|| (dent->d_name[1] != 0
|
||||
&& (dent->d_name[1] != '.' || dent->d_name[2] != 0)))
|
||||
{
|
||||
const int fd = safe_atoi (dent->d_name, literal_quoting_style);
|
||||
if (fd > maxfd)
|
||||
maxfd = fd;
|
||||
good = 1;
|
||||
}
|
||||
}
|
||||
if (dent->d_name[0] != '.'
|
||||
|| (dent->d_name[1] != 0
|
||||
&& (dent->d_name[1] != '.' || dent->d_name[2] != 0)))
|
||||
{
|
||||
const int fd = safe_atoi (dent->d_name, literal_quoting_style);
|
||||
if (fd > maxfd)
|
||||
maxfd = fd;
|
||||
good = 1;
|
||||
}
|
||||
}
|
||||
closedir (dir);
|
||||
if (good)
|
||||
return maxfd;
|
||||
return maxfd;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
@ -116,7 +116,7 @@ get_max_fd (void)
|
||||
|
||||
open_max = sysconf (_SC_OPEN_MAX);
|
||||
if (open_max == -1)
|
||||
open_max = _POSIX_OPEN_MAX; /* underestimate */
|
||||
open_max = _POSIX_OPEN_MAX; /* underestimate */
|
||||
|
||||
/* We assume if RLIMIT_NOFILE is defined, all the related macros are, too. */
|
||||
#if defined HAVE_GETRLIMIT && defined RLIMIT_NOFILE
|
||||
@ -124,10 +124,10 @@ get_max_fd (void)
|
||||
struct rlimit fd_limit;
|
||||
if (0 == getrlimit (RLIMIT_NOFILE, &fd_limit))
|
||||
{
|
||||
if (fd_limit.rlim_cur == RLIM_INFINITY)
|
||||
return open_max;
|
||||
else
|
||||
return (int) fd_limit.rlim_cur;
|
||||
if (fd_limit.rlim_cur == RLIM_INFINITY)
|
||||
return open_max;
|
||||
else
|
||||
return (int) fd_limit.rlim_cur;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@ -138,7 +138,7 @@ get_max_fd (void)
|
||||
|
||||
static int
|
||||
visit_open_fds (int fd_min, int fd_max,
|
||||
int (*callback)(int, void*), void *cb_context)
|
||||
int (*callback)(int, void*), void *cb_context)
|
||||
{
|
||||
enum { MAX_POLL = 64 };
|
||||
struct pollfd pf[MAX_POLL];
|
||||
@ -149,31 +149,31 @@ visit_open_fds (int fd_min, int fd_max,
|
||||
int i;
|
||||
int limit = fd_max - fd_min;
|
||||
if (limit > MAX_POLL)
|
||||
limit = MAX_POLL;
|
||||
limit = MAX_POLL;
|
||||
|
||||
for (i=0; i<limit; i++)
|
||||
{
|
||||
pf[i].events = POLLIN|POLLOUT;
|
||||
pf[i].revents = 0;
|
||||
pf[i].fd = fd_min + i;
|
||||
}
|
||||
{
|
||||
pf[i].events = POLLIN|POLLOUT;
|
||||
pf[i].revents = 0;
|
||||
pf[i].fd = fd_min + i;
|
||||
}
|
||||
rv = poll (pf, limit, 0);
|
||||
if (-1 == rv)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
int j;
|
||||
for (j=0; j<limit; j++)
|
||||
{
|
||||
if (pf[j].revents != POLLNVAL)
|
||||
{
|
||||
if (0 != (rv = callback (pf[j].fd, cb_context)))
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
int j;
|
||||
for (j=0; j<limit; j++)
|
||||
{
|
||||
if (pf[j].revents != POLLNVAL)
|
||||
{
|
||||
if (0 != (rv = callback (pf[j].fd, cb_context)))
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
}
|
||||
fd_min += limit;
|
||||
}
|
||||
return 0;
|
||||
@ -208,19 +208,19 @@ remember_fd_if_non_cloexec (int fd, void *context)
|
||||
{
|
||||
struct remember_fd_context * const p = context;
|
||||
void *newbuf = extendbuf (p->buf,
|
||||
sizeof (p->buf[0])*(p->used+1),
|
||||
&(p->allocated));
|
||||
sizeof (p->buf[0])*(p->used+1),
|
||||
&(p->allocated));
|
||||
if (newbuf)
|
||||
{
|
||||
p->buf = newbuf;
|
||||
p->buf[p->used] = fd;
|
||||
++p->used;
|
||||
return 0;
|
||||
}
|
||||
{
|
||||
p->buf = newbuf;
|
||||
p->buf[p->used] = fd;
|
||||
++p->used;
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -259,26 +259,26 @@ find_first_leak_callback (int fd, void *context)
|
||||
{
|
||||
struct fd_leak_context *p = context;
|
||||
while (p->lookup_pos < p->used)
|
||||
{
|
||||
if (p->prev_buf[p->lookup_pos] < fd)
|
||||
{
|
||||
++p->lookup_pos;
|
||||
}
|
||||
else if (p->prev_buf[p->lookup_pos] == fd)
|
||||
{
|
||||
/* FD was open and still is, it's not a leak. */
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
{
|
||||
if (p->prev_buf[p->lookup_pos] < fd)
|
||||
{
|
||||
++p->lookup_pos;
|
||||
}
|
||||
else if (p->prev_buf[p->lookup_pos] == fd)
|
||||
{
|
||||
/* FD was open and still is, it's not a leak. */
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* We come here if p->prev_buf[p->lookup_pos] > fd, or
|
||||
if we ran out of items in the lookup table.
|
||||
Either way, this is a leak. */
|
||||
if we ran out of items in the lookup table.
|
||||
Either way, this is a leak. */
|
||||
p->leaked_fd = fd;
|
||||
return -1; /* No more callbacks needed. */
|
||||
return -1; /* No more callbacks needed. */
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -387,10 +387,10 @@ complain_about_leaky_fds (void)
|
||||
{
|
||||
no_leaks = 0;
|
||||
error (0, 0,
|
||||
_("File descriptor %d will leak; please report this as a bug, "
|
||||
"remembering to include a detailed description of the simplest "
|
||||
"way to reproduce this problem."),
|
||||
leaking_fd);
|
||||
_("File descriptor %d will leak; please report this as a bug, "
|
||||
"remembering to include a detailed description of the simplest "
|
||||
"way to reproduce this problem."),
|
||||
leaking_fd);
|
||||
}
|
||||
assert (no_leaks);
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/* fdleak.h -- detect file descriptor leaks
|
||||
Copyright (C) 2010-2024 Free Software Foundation, Inc.
|
||||
Copyright (C) 2010-2026 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
|
||||
@ -17,7 +17,7 @@
|
||||
#ifndef FDLEAK_H
|
||||
# define FDLEAK_H
|
||||
|
||||
# include <stdbool.h> /* for bool */
|
||||
# include <stdbool.h> /* for bool */
|
||||
|
||||
void remember_non_cloexec_fds (void);
|
||||
void forget_non_cloexec_fds (void);
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/* findutils-version.c -- show version information for findutils
|
||||
Copyright (C) 2007-2024 Free Software Foundation, Inc.
|
||||
Copyright (C) 2007-2026 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
|
||||
@ -34,7 +34,7 @@
|
||||
#endif
|
||||
|
||||
extern char *program_name;
|
||||
const char *version_string = VERSION;
|
||||
static const char *version_string = VERSION;
|
||||
|
||||
void
|
||||
display_findutils_version (const char *official_name)
|
||||
@ -45,9 +45,9 @@ display_findutils_version (const char *official_name)
|
||||
*/
|
||||
fflush (stderr);
|
||||
version_etc (stdout,
|
||||
official_name, PACKAGE_NAME, version_string,
|
||||
_("Eric B. Decker"),
|
||||
_("James Youngman"),
|
||||
_("Kevin Dalley"),
|
||||
(const char*) NULL);
|
||||
official_name, PACKAGE_NAME, version_string,
|
||||
_("Eric B. Decker"),
|
||||
_("James Youngman"),
|
||||
_("Kevin Dalley"),
|
||||
(const char*) NULL);
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/* findutils-version.h -- show version information for findutils
|
||||
Copyright (C) 2007-2024 Free Software Foundation, Inc.
|
||||
Copyright (C) 2007-2026 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
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/* listfile.c -- display a long listing of a file
|
||||
Copyright (C) 1991-2024 Free Software Foundation, Inc.
|
||||
Copyright (C) 1991-2026 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
|
||||
@ -182,17 +182,17 @@ list_file (const char *name,
|
||||
so we removed the trailing space. Happily this also makes it
|
||||
easier to update nlink_width. */
|
||||
chars_out = fprintf (stream, "%*lu",
|
||||
nlink_width, (unsigned long) statp->st_nlink);
|
||||
nlink_width, (unsigned long) statp->st_nlink);
|
||||
if (chars_out < 0)
|
||||
{
|
||||
output_good = false;
|
||||
failed_at = 300;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (chars_out > nlink_width)
|
||||
nlink_width = chars_out;
|
||||
}
|
||||
{
|
||||
if (chars_out > nlink_width)
|
||||
nlink_width = chars_out;
|
||||
}
|
||||
}
|
||||
|
||||
if (output_good)
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/* listfile.h -- display a long listing of a file
|
||||
Copyright (C) 1991-2024 Free Software Foundation, Inc.
|
||||
Copyright (C) 1991-2026 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
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/* printquoted.c -- print a specified string with any necessary quoting.
|
||||
|
||||
Copyright (C) 1990-2024 Free Software Foundation, Inc.
|
||||
Copyright (C) 1990-2026 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
|
||||
@ -35,10 +35,10 @@
|
||||
*/
|
||||
int
|
||||
print_quoted (FILE *fp,
|
||||
const struct quoting_options *qopts,
|
||||
bool dest_is_tty,
|
||||
const char *format,
|
||||
const char *s)
|
||||
const struct quoting_options *qopts,
|
||||
bool dest_is_tty,
|
||||
const char *format,
|
||||
const char *s)
|
||||
{
|
||||
int rv;
|
||||
|
||||
@ -48,28 +48,28 @@ print_quoted (FILE *fp,
|
||||
size_t len = quotearg_buffer (smallbuf, sizeof smallbuf, s, -1, qopts);
|
||||
char *buf;
|
||||
if (len < sizeof smallbuf)
|
||||
buf = smallbuf;
|
||||
buf = smallbuf;
|
||||
else
|
||||
{
|
||||
/* The original coreutils code uses alloca(), but I don't
|
||||
* want to take on the anguish of introducing alloca() to
|
||||
* 'find'.
|
||||
* XXX: newsflash: we already have alloca().
|
||||
*/
|
||||
buf = xmalloc (len + 1);
|
||||
quotearg_buffer (buf, len + 1, s, -1, qopts);
|
||||
}
|
||||
{
|
||||
/* The original coreutils code uses alloca(), but I don't
|
||||
* want to take on the anguish of introducing alloca() to
|
||||
* 'find'.
|
||||
* XXX: newsflash: we already have alloca().
|
||||
*/
|
||||
buf = xmalloc (len + 1);
|
||||
quotearg_buffer (buf, len + 1, s, -1, qopts);
|
||||
}
|
||||
|
||||
/* Replace any remaining funny characters with '?'. */
|
||||
len = qmark_chars (buf, len);
|
||||
buf[len] = 0;
|
||||
|
||||
rv = fprintf (fp, format, buf); /* Print the quoted version */
|
||||
rv = fprintf (fp, format, buf); /* Print the quoted version */
|
||||
if (buf != smallbuf)
|
||||
{
|
||||
free (buf);
|
||||
buf = NULL;
|
||||
}
|
||||
{
|
||||
free (buf);
|
||||
buf = NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/* Print a string, appropriately quoted.
|
||||
|
||||
Copyright (C) 1997-2024 Free Software Foundation, Inc.
|
||||
Copyright (C) 1997-2026 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
|
||||
|
||||
164
lib/qmark.c
164
lib/qmark.c
@ -1,6 +1,6 @@
|
||||
/* qmark.c -- quote 'dangerous' filenames
|
||||
Derived from coreutils' ls.c.
|
||||
Copyright (C) 1985-2024 Free Software Foundation, Inc.
|
||||
Copyright (C) 1985-2026 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
|
||||
@ -93,7 +93,7 @@ unibyte_qmark_chars (char *buf, size_t len)
|
||||
while (p < plimit)
|
||||
{
|
||||
if (! ISPRINT (to_uchar (*p)))
|
||||
*p = '?';
|
||||
*p = '?';
|
||||
p++;
|
||||
}
|
||||
return len;
|
||||
@ -124,91 +124,91 @@ qmark_chars (char *buf, size_t len)
|
||||
char *q = buf;
|
||||
|
||||
while (p < plimit)
|
||||
switch (*p)
|
||||
{
|
||||
case ' ': case '!': case '"': case '#': case '%':
|
||||
case '&': case '\'': case '(': case ')': case '*':
|
||||
case '+': case ',': case '-': case '.': case '/':
|
||||
case '0': case '1': case '2': case '3': case '4':
|
||||
case '5': case '6': case '7': case '8': case '9':
|
||||
case ':': case ';': case '<': case '=': case '>':
|
||||
case '?':
|
||||
case 'A': case 'B': case 'C': case 'D': case 'E':
|
||||
case 'F': case 'G': case 'H': case 'I': case 'J':
|
||||
case 'K': case 'L': case 'M': case 'N': case 'O':
|
||||
case 'P': case 'Q': case 'R': case 'S': case 'T':
|
||||
case 'U': case 'V': case 'W': case 'X': case 'Y':
|
||||
case 'Z':
|
||||
case '[': case '\\': case ']': case '^': case '_':
|
||||
case 'a': case 'b': case 'c': case 'd': case 'e':
|
||||
case 'f': case 'g': case 'h': case 'i': case 'j':
|
||||
case 'k': case 'l': case 'm': case 'n': case 'o':
|
||||
case 'p': case 'q': case 'r': case 's': case 't':
|
||||
case 'u': case 'v': case 'w': case 'x': case 'y':
|
||||
case 'z': case '{': case '|': case '}': case '~':
|
||||
/* These characters are printable ASCII characters. */
|
||||
*q++ = *p++;
|
||||
break;
|
||||
default:
|
||||
/* If we have a multibyte sequence, copy it until we
|
||||
reach its end, replacing each non-printable multibyte
|
||||
character with a single question mark. */
|
||||
{
|
||||
mbstate_t mbstate;
|
||||
memset (&mbstate, 0, sizeof mbstate);
|
||||
do
|
||||
{
|
||||
wchar_t wc;
|
||||
size_t bytes;
|
||||
int w;
|
||||
switch (*p)
|
||||
{
|
||||
case ' ': case '!': case '"': case '#': case '%':
|
||||
case '&': case '\'': case '(': case ')': case '*':
|
||||
case '+': case ',': case '-': case '.': case '/':
|
||||
case '0': case '1': case '2': case '3': case '4':
|
||||
case '5': case '6': case '7': case '8': case '9':
|
||||
case ':': case ';': case '<': case '=': case '>':
|
||||
case '?':
|
||||
case 'A': case 'B': case 'C': case 'D': case 'E':
|
||||
case 'F': case 'G': case 'H': case 'I': case 'J':
|
||||
case 'K': case 'L': case 'M': case 'N': case 'O':
|
||||
case 'P': case 'Q': case 'R': case 'S': case 'T':
|
||||
case 'U': case 'V': case 'W': case 'X': case 'Y':
|
||||
case 'Z':
|
||||
case '[': case '\\': case ']': case '^': case '_':
|
||||
case 'a': case 'b': case 'c': case 'd': case 'e':
|
||||
case 'f': case 'g': case 'h': case 'i': case 'j':
|
||||
case 'k': case 'l': case 'm': case 'n': case 'o':
|
||||
case 'p': case 'q': case 'r': case 's': case 't':
|
||||
case 'u': case 'v': case 'w': case 'x': case 'y':
|
||||
case 'z': case '{': case '|': case '}': case '~':
|
||||
/* These characters are printable ASCII characters. */
|
||||
*q++ = *p++;
|
||||
break;
|
||||
default:
|
||||
/* If we have a multibyte sequence, copy it until we
|
||||
reach its end, replacing each non-printable multibyte
|
||||
character with a single question mark. */
|
||||
{
|
||||
mbstate_t mbstate;
|
||||
memset (&mbstate, 0, sizeof mbstate);
|
||||
do
|
||||
{
|
||||
wchar_t wc;
|
||||
size_t bytes;
|
||||
int w;
|
||||
|
||||
bytes = mbrtowc (&wc, p, plimit - p, &mbstate);
|
||||
bytes = mbrtowc (&wc, p, plimit - p, &mbstate);
|
||||
|
||||
if (bytes == (size_t) -1)
|
||||
{
|
||||
/* An invalid multibyte sequence was
|
||||
encountered. Skip one input byte, and
|
||||
put a question mark. */
|
||||
p++;
|
||||
*q++ = '?';
|
||||
break;
|
||||
}
|
||||
if (bytes == (size_t) -1)
|
||||
{
|
||||
/* An invalid multibyte sequence was
|
||||
encountered. Skip one input byte, and
|
||||
put a question mark. */
|
||||
p++;
|
||||
*q++ = '?';
|
||||
break;
|
||||
}
|
||||
|
||||
if (bytes == (size_t) -2)
|
||||
{
|
||||
/* An incomplete multibyte character
|
||||
at the end. Replace it entirely with
|
||||
a question mark. */
|
||||
p = plimit;
|
||||
*q++ = '?';
|
||||
break;
|
||||
}
|
||||
if (bytes == (size_t) -2)
|
||||
{
|
||||
/* An incomplete multibyte character
|
||||
at the end. Replace it entirely with
|
||||
a question mark. */
|
||||
p = plimit;
|
||||
*q++ = '?';
|
||||
break;
|
||||
}
|
||||
|
||||
if (bytes == 0)
|
||||
/* A null wide character was encountered. */
|
||||
bytes = 1;
|
||||
if (bytes == 0)
|
||||
/* A null wide character was encountered. */
|
||||
bytes = 1;
|
||||
|
||||
w = wcwidth (wc);
|
||||
if (w >= 0)
|
||||
{
|
||||
/* A printable multibyte character.
|
||||
Keep it. */
|
||||
for (; bytes > 0; --bytes)
|
||||
*q++ = *p++;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* An unprintable multibyte character.
|
||||
Replace it entirely with a question
|
||||
mark. */
|
||||
p += bytes;
|
||||
*q++ = '?';
|
||||
}
|
||||
}
|
||||
while (! mbsinit (&mbstate));
|
||||
}
|
||||
break;
|
||||
}
|
||||
w = wcwidth (wc);
|
||||
if (w >= 0)
|
||||
{
|
||||
/* A printable multibyte character.
|
||||
Keep it. */
|
||||
for (; bytes > 0; --bytes)
|
||||
*q++ = *p++;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* An unprintable multibyte character.
|
||||
Replace it entirely with a question
|
||||
mark. */
|
||||
p += bytes;
|
||||
*q++ = '?';
|
||||
}
|
||||
}
|
||||
while (! mbsinit (&mbstate));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/* The buffer may have shrunk. */
|
||||
len = q - buf;
|
||||
|
||||
342
lib/regexprops.c
342
lib/regexprops.c
@ -1,7 +1,7 @@
|
||||
/* regexprops.c -- document the properties of the regular expressions
|
||||
understood by gnulib.
|
||||
|
||||
Copyright (C) 2005-2024 Free Software Foundation, Inc.
|
||||
Copyright (C) 2005-2026 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
|
||||
@ -98,9 +98,9 @@ enum_item (const char *s)
|
||||
|
||||
static void
|
||||
begin_subsection (const char *name,
|
||||
const char *next,
|
||||
const char *prev,
|
||||
const char *up)
|
||||
const char *next,
|
||||
const char *prev,
|
||||
const char *up)
|
||||
{
|
||||
(void) next;
|
||||
(void) prev;
|
||||
@ -173,9 +173,9 @@ describe_regex_syntax (int options)
|
||||
if (options & RE_DOT_NOT_NULL)
|
||||
{
|
||||
if ( (options & RE_DOT_NEWLINE) == 0 )
|
||||
content (" and");
|
||||
content (" and");
|
||||
else
|
||||
content (" except");
|
||||
content (" except");
|
||||
|
||||
content (" the null character");
|
||||
}
|
||||
@ -186,29 +186,29 @@ describe_regex_syntax (int options)
|
||||
{
|
||||
begintable_markup ("@samp");
|
||||
if (options & RE_BK_PLUS_QM)
|
||||
{
|
||||
enum_item ("\\+");
|
||||
content ("indicates that the regular expression should match one"
|
||||
" or more occurrences of the previous atom or regexp.");
|
||||
enum_item ("\\?");
|
||||
content ("indicates that the regular expression should match zero"
|
||||
" or one occurrence of the previous atom or regexp.");
|
||||
enum_item ("+ and ?");
|
||||
content ("match themselves.\n");
|
||||
}
|
||||
{
|
||||
enum_item ("\\+");
|
||||
content ("indicates that the regular expression should match one"
|
||||
" or more occurrences of the previous atom or regexp.");
|
||||
enum_item ("\\?");
|
||||
content ("indicates that the regular expression should match zero"
|
||||
" or one occurrence of the previous atom or regexp.");
|
||||
enum_item ("+ and ?");
|
||||
content ("match themselves.\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
enum_item ("+");
|
||||
content ("indicates that the regular expression should match one"
|
||||
" or more occurrences of the previous atom or regexp.");
|
||||
enum_item ("?");
|
||||
content ("indicates that the regular expression should match zero"
|
||||
" or one occurrence of the previous atom or regexp.");
|
||||
enum_item ("\\+");
|
||||
literal ("matches a @samp{+}");
|
||||
enum_item ("\\?");
|
||||
literal ("matches a @samp{?}.");
|
||||
}
|
||||
{
|
||||
enum_item ("+");
|
||||
content ("indicates that the regular expression should match one"
|
||||
" or more occurrences of the previous atom or regexp.");
|
||||
enum_item ("?");
|
||||
content ("indicates that the regular expression should match zero"
|
||||
" or one occurrence of the previous atom or regexp.");
|
||||
enum_item ("\\+");
|
||||
literal ("matches a @samp{+}");
|
||||
enum_item ("\\?");
|
||||
literal ("matches a @samp{?}.");
|
||||
}
|
||||
endtable ();
|
||||
}
|
||||
|
||||
@ -224,17 +224,17 @@ describe_regex_syntax (int options)
|
||||
|
||||
if (options & RE_BACKSLASH_ESCAPE_IN_LISTS)
|
||||
literal ("Within square brackets, @samp{\\} can be used to quote "
|
||||
"the following character. ");
|
||||
"the following character. ");
|
||||
else
|
||||
literal ("Within square brackets, @samp{\\} is taken literally. ");
|
||||
|
||||
if (options & RE_CHAR_CLASSES)
|
||||
content ("Character classes are supported; for example "
|
||||
"@samp{[[:digit:]]} will match a single decimal digit.\n");
|
||||
"@samp{[[:digit:]]} will match a single decimal digit.\n");
|
||||
else
|
||||
literal ("Character classes are not supported, so for example "
|
||||
"you would need to use @samp{[0-9]} "
|
||||
"instead of @samp{[[:digit:]]}.\n");
|
||||
"you would need to use @samp{[0-9]} "
|
||||
"instead of @samp{[[:digit:]]}.\n");
|
||||
|
||||
if (options & RE_HAT_LISTS_NOT_NEWLINE)
|
||||
{
|
||||
@ -244,9 +244,9 @@ describe_regex_syntax (int options)
|
||||
if (options & RE_NO_GNU_OPS)
|
||||
{
|
||||
content ("GNU extensions are not supported and so "
|
||||
"@samp{\\w}, @samp{\\W}, @samp{\\<}, @samp{\\>}, @samp{\\b}, @samp{\\B}, @samp{\\`}, and @samp{\\'} "
|
||||
"match "
|
||||
"@samp{w}, @samp{W}, @samp{<}, @samp{>}, @samp{b}, @samp{B}, @samp{`}, and @samp{'} respectively.\n");
|
||||
"@samp{\\w}, @samp{\\W}, @samp{\\<}, @samp{\\>}, @samp{\\b}, @samp{\\B}, @samp{\\`}, and @samp{\\'} "
|
||||
"match "
|
||||
"@samp{w}, @samp{W}, @samp{<}, @samp{>}, @samp{b}, @samp{B}, @samp{`}, and @samp{'} respectively.\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -271,7 +271,7 @@ describe_regex_syntax (int options)
|
||||
literal ("Grouping is performed with parentheses @samp{()}. ");
|
||||
|
||||
if (options & RE_UNMATCHED_RIGHT_PAREN_ORD)
|
||||
literal ("An unmatched @samp{)} matches just itself. ");
|
||||
literal ("An unmatched @samp{)} matches just itself. ");
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -286,9 +286,9 @@ describe_regex_syntax (int options)
|
||||
{
|
||||
literal ("A backslash followed by a digit acts as a back-reference and matches the same thing as the previous grouped expression indicated by that number. For example @samp{\\2} matches the second group expression. The order of group expressions is determined by the position of their opening parenthesis ");
|
||||
if (options & RE_NO_BK_PARENS)
|
||||
literal ("@samp{(}");
|
||||
literal ("@samp{(}");
|
||||
else
|
||||
literal ("@samp{\\(}");
|
||||
literal ("@samp{\\(}");
|
||||
content (".");
|
||||
}
|
||||
|
||||
@ -297,9 +297,9 @@ describe_regex_syntax (int options)
|
||||
if (!(options & RE_LIMITED_OPS))
|
||||
{
|
||||
if (options & RE_NO_BK_VBAR)
|
||||
literal ("The alternation operator is @samp{|}.");
|
||||
literal ("The alternation operator is @samp{|}.");
|
||||
else
|
||||
literal ("The alternation operator is @samp{\\|}.");
|
||||
literal ("The alternation operator is @samp{\\|}.");
|
||||
}
|
||||
newpara ();
|
||||
|
||||
@ -313,24 +313,24 @@ describe_regex_syntax (int options)
|
||||
beginenum ();
|
||||
enum_item ("At the beginning of a regular expression");
|
||||
if (options & RE_NO_BK_PARENS)
|
||||
{
|
||||
enum_item ("After an open-group, signified by @samp{(}");
|
||||
}
|
||||
{
|
||||
enum_item ("After an open-group, signified by @samp{(}");
|
||||
}
|
||||
else
|
||||
{
|
||||
enum_item ("After an open-group, signified by @samp{\\(}");
|
||||
}
|
||||
{
|
||||
enum_item ("After an open-group, signified by @samp{\\(}");
|
||||
}
|
||||
newline ();
|
||||
if (!(options & RE_LIMITED_OPS))
|
||||
{
|
||||
if (options & RE_NEWLINE_ALT)
|
||||
enum_item ("After a newline");
|
||||
{
|
||||
if (options & RE_NEWLINE_ALT)
|
||||
enum_item ("After a newline");
|
||||
|
||||
if (options & RE_NO_BK_VBAR )
|
||||
enum_item ("After the alternation operator @samp{|}");
|
||||
else
|
||||
enum_item ("After the alternation operator @samp{\\|}");
|
||||
}
|
||||
if (options & RE_NO_BK_VBAR )
|
||||
enum_item ("After the alternation operator @samp{|}");
|
||||
else
|
||||
enum_item ("After the alternation operator @samp{\\|}");
|
||||
}
|
||||
endenum ();
|
||||
|
||||
newpara ();
|
||||
@ -338,71 +338,71 @@ describe_regex_syntax (int options)
|
||||
beginenum ();
|
||||
enum_item ("At the end of a regular expression");
|
||||
if (options & RE_NO_BK_PARENS)
|
||||
{
|
||||
enum_item ("Before a close-group, signified by @samp{)}");
|
||||
}
|
||||
{
|
||||
enum_item ("Before a close-group, signified by @samp{)}");
|
||||
}
|
||||
else
|
||||
{
|
||||
enum_item ("Before a close-group, signified by @samp{\\)}");
|
||||
}
|
||||
{
|
||||
enum_item ("Before a close-group, signified by @samp{\\)}");
|
||||
}
|
||||
if (!(options & RE_LIMITED_OPS))
|
||||
{
|
||||
if (options & RE_NEWLINE_ALT)
|
||||
enum_item ("Before a newline");
|
||||
{
|
||||
if (options & RE_NEWLINE_ALT)
|
||||
enum_item ("Before a newline");
|
||||
|
||||
if (options & RE_NO_BK_VBAR)
|
||||
enum_item ("Before the alternation operator @samp{|}");
|
||||
else
|
||||
enum_item ("Before the alternation operator @samp{\\|}");
|
||||
}
|
||||
if (options & RE_NO_BK_VBAR)
|
||||
enum_item ("Before the alternation operator @samp{|}");
|
||||
else
|
||||
enum_item ("Before the alternation operator @samp{\\|}");
|
||||
}
|
||||
endenum ();
|
||||
}
|
||||
newpara ();
|
||||
if (!(options & RE_LIMITED_OPS) )
|
||||
{
|
||||
if ((options & RE_CONTEXT_INDEP_OPS)
|
||||
&& !(options & RE_CONTEXT_INVALID_OPS))
|
||||
{
|
||||
literal ("The characters @samp{*}, @samp{+} and @samp{?} are special anywhere in a regular expression.\n");
|
||||
}
|
||||
&& !(options & RE_CONTEXT_INVALID_OPS))
|
||||
{
|
||||
literal ("The characters @samp{*}, @samp{+} and @samp{?} are special anywhere in a regular expression.\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (options & RE_BK_PLUS_QM)
|
||||
literal ("@samp{\\*}, @samp{\\+} and @samp{\\?} ");
|
||||
else
|
||||
literal ("@samp{*}, @samp{+} and @samp{?} ");
|
||||
{
|
||||
if (options & RE_BK_PLUS_QM)
|
||||
literal ("@samp{\\*}, @samp{\\+} and @samp{\\?} ");
|
||||
else
|
||||
literal ("@samp{*}, @samp{+} and @samp{?} ");
|
||||
|
||||
if (options & RE_CONTEXT_INVALID_OPS)
|
||||
{
|
||||
content ("are special at any point in a regular expression except the following places, where they are not allowed:");
|
||||
}
|
||||
else
|
||||
{
|
||||
content ("are special at any point in a regular expression except:");
|
||||
}
|
||||
if (options & RE_CONTEXT_INVALID_OPS)
|
||||
{
|
||||
content ("are special at any point in a regular expression except the following places, where they are not allowed:");
|
||||
}
|
||||
else
|
||||
{
|
||||
content ("are special at any point in a regular expression except:");
|
||||
}
|
||||
|
||||
beginenum ();
|
||||
enum_item ("At the beginning of a regular expression");
|
||||
if (options & RE_NO_BK_PARENS)
|
||||
{
|
||||
enum_item ("After an open-group, signified by @samp{(}");
|
||||
}
|
||||
else
|
||||
{
|
||||
enum_item ("After an open-group, signified by @samp{\\(}");
|
||||
}
|
||||
if (!(options & RE_LIMITED_OPS))
|
||||
{
|
||||
if (options & RE_NEWLINE_ALT)
|
||||
enum_item ("After a newline");
|
||||
beginenum ();
|
||||
enum_item ("At the beginning of a regular expression");
|
||||
if (options & RE_NO_BK_PARENS)
|
||||
{
|
||||
enum_item ("After an open-group, signified by @samp{(}");
|
||||
}
|
||||
else
|
||||
{
|
||||
enum_item ("After an open-group, signified by @samp{\\(}");
|
||||
}
|
||||
if (!(options & RE_LIMITED_OPS))
|
||||
{
|
||||
if (options & RE_NEWLINE_ALT)
|
||||
enum_item ("After a newline");
|
||||
|
||||
if (options & RE_NO_BK_VBAR)
|
||||
enum_item ("After the alternation operator @samp{|}");
|
||||
else
|
||||
enum_item ("After the alternation operator @samp{\\|}");
|
||||
}
|
||||
endenum ();
|
||||
}
|
||||
if (options & RE_NO_BK_VBAR)
|
||||
enum_item ("After the alternation operator @samp{|}");
|
||||
else
|
||||
enum_item ("After the alternation operator @samp{\\|}");
|
||||
}
|
||||
endenum ();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -410,29 +410,29 @@ describe_regex_syntax (int options)
|
||||
if (options & RE_INTERVALS)
|
||||
{
|
||||
if (options & RE_NO_BK_BRACES)
|
||||
{
|
||||
literal ("Intervals are specified by @samp{@{} and @samp{@}}.\n");
|
||||
if (options & RE_INVALID_INTERVAL_ORD)
|
||||
{
|
||||
literal ("Invalid intervals are treated as literals, for example @samp{a@{1} is treated as @samp{a\\@{1}");
|
||||
}
|
||||
else
|
||||
{
|
||||
literal ("Invalid intervals such as @samp{a@{1z} are not accepted.\n");
|
||||
}
|
||||
}
|
||||
{
|
||||
literal ("Intervals are specified by @samp{@{} and @samp{@}}.\n");
|
||||
if (options & RE_INVALID_INTERVAL_ORD)
|
||||
{
|
||||
literal ("Invalid intervals are treated as literals, for example @samp{a@{1} is treated as @samp{a\\@{1}");
|
||||
}
|
||||
else
|
||||
{
|
||||
literal ("Invalid intervals such as @samp{a@{1z} are not accepted.\n");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
literal ("Intervals are specified by @samp{\\@{} and @samp{\\@}}.\n");
|
||||
if (options & RE_INVALID_INTERVAL_ORD)
|
||||
{
|
||||
literal ("Invalid intervals are treated as literals, for example @samp{a\\@{1} is treated as @samp{a@{1}");
|
||||
}
|
||||
else
|
||||
{
|
||||
literal ("Invalid intervals such as @samp{a\\@{1z} are not accepted.\n");
|
||||
}
|
||||
}
|
||||
{
|
||||
literal ("Intervals are specified by @samp{\\@{} and @samp{\\@}}.\n");
|
||||
if (options & RE_INVALID_INTERVAL_ORD)
|
||||
{
|
||||
literal ("Invalid intervals are treated as literals, for example @samp{a\\@{1} is treated as @samp{a@{1}");
|
||||
}
|
||||
else
|
||||
{
|
||||
literal ("Invalid intervals such as @samp{a\\@{1z} are not accepted.\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
newpara ();
|
||||
@ -454,7 +454,7 @@ copying (void)
|
||||
static const char *copy_para[]=
|
||||
{
|
||||
/* The copyright year number range is with "--" in Texinfo files. */
|
||||
"Copyright (C) 1994--2024 Free Software Foundation, Inc."
|
||||
"Copyright (C) 1994--2026 Free Software Foundation, Inc."
|
||||
,""
|
||||
,"Permission is granted to copy, distribute and/or modify this document"
|
||||
,"under the terms of the GNU Free Documentation License, Version 1.3 or"
|
||||
@ -485,17 +485,17 @@ menu (unsigned int context)
|
||||
output ("@menu\n", 0);
|
||||
for (i=0;
|
||||
get_regex_type_flags (i),
|
||||
name=get_regex_type_name (i);
|
||||
name=get_regex_type_name (i);
|
||||
++i)
|
||||
{
|
||||
if (!ignore (i, context))
|
||||
{
|
||||
output ("* ", 0);
|
||||
output (name, 0);
|
||||
content (" regular expression syntax");
|
||||
output ("::", 0);
|
||||
newline ();
|
||||
}
|
||||
{
|
||||
output ("* ", 0);
|
||||
output (name, 0);
|
||||
content (" regular expression syntax");
|
||||
output ("::", 0);
|
||||
newline ();
|
||||
}
|
||||
}
|
||||
output ("@end menu\n", 0);
|
||||
}
|
||||
@ -509,13 +509,13 @@ get_next (unsigned int ix, unsigned int context)
|
||||
while (get_regex_type_name (ix))
|
||||
{
|
||||
if (!ignore (ix, context))
|
||||
{
|
||||
next = get_regex_type_name (ix);
|
||||
if (NULL == next)
|
||||
return "";
|
||||
else
|
||||
return next;
|
||||
}
|
||||
{
|
||||
next = get_regex_type_name (ix);
|
||||
if (NULL == next)
|
||||
return "";
|
||||
else
|
||||
return next;
|
||||
}
|
||||
++ix;
|
||||
}
|
||||
return "";
|
||||
@ -524,8 +524,8 @@ get_next (unsigned int ix, unsigned int context)
|
||||
|
||||
static void
|
||||
describe_all (const char *contextname,
|
||||
unsigned int context,
|
||||
const char *up)
|
||||
unsigned int context,
|
||||
const char *up)
|
||||
{
|
||||
const char *name, *next, *previous;
|
||||
int regopts;
|
||||
@ -543,33 +543,33 @@ describe_all (const char *contextname,
|
||||
|
||||
for (i=0;
|
||||
regopts = get_regex_type_flags (i),
|
||||
name=get_regex_type_name (i);
|
||||
name=get_regex_type_name (i);
|
||||
++i)
|
||||
{
|
||||
if (ignore (i, context))
|
||||
{
|
||||
fprintf (stderr,
|
||||
"Skipping regexp type %s for context %s\n",
|
||||
name, contextname);
|
||||
name = previous;
|
||||
continue;
|
||||
}
|
||||
{
|
||||
fprintf (stderr,
|
||||
"Skipping regexp type %s for context %s\n",
|
||||
name, contextname);
|
||||
name = previous;
|
||||
continue;
|
||||
}
|
||||
|
||||
next = get_next (i+1, context);
|
||||
if (NULL == next)
|
||||
next = "";
|
||||
next = "";
|
||||
begin_subsection (name, next, previous, up);
|
||||
parent = get_regex_type_synonym (i, context);
|
||||
if (parent >= 0)
|
||||
{
|
||||
content ("This is a synonym for ");
|
||||
content (get_regex_type_name (parent));
|
||||
content (".");
|
||||
}
|
||||
{
|
||||
content ("This is a synonym for ");
|
||||
content (get_regex_type_name (parent));
|
||||
content (".");
|
||||
}
|
||||
else
|
||||
{
|
||||
describe_regex_syntax (regopts);
|
||||
}
|
||||
{
|
||||
describe_regex_syntax (regopts);
|
||||
}
|
||||
previous = name;
|
||||
}
|
||||
}
|
||||
@ -596,17 +596,17 @@ main (int argc, char *argv[])
|
||||
{
|
||||
contextname = argv[2];
|
||||
if (0 == strcmp (contextname, "findutils"))
|
||||
context = CONTEXT_FINDUTILS;
|
||||
context = CONTEXT_FINDUTILS;
|
||||
else if (0 == strcmp (contextname, "generic"))
|
||||
context = CONTEXT_GENERIC;
|
||||
context = CONTEXT_GENERIC;
|
||||
else if (0 == strcmp (contextname, "all"))
|
||||
context = CONTEXT_ALL;
|
||||
context = CONTEXT_ALL;
|
||||
else
|
||||
{
|
||||
fprintf (stderr, "Unexpected context %s",
|
||||
contextname);
|
||||
return 1;
|
||||
}
|
||||
{
|
||||
fprintf (stderr, "Unexpected context %s",
|
||||
contextname);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
describe_all (contextname, context, up);
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
/* regextype.c -- Decode the name of a regular expression syntax into am
|
||||
option name.
|
||||
|
||||
Copyright (C) 2005-2024 Free Software Foundation, Inc.
|
||||
Copyright (C) 2005-2026 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
|
||||
@ -47,15 +47,15 @@ struct tagRegexTypeMap
|
||||
static struct tagRegexTypeMap regex_map[] =
|
||||
{
|
||||
{ "findutils-default", CONTEXT_FINDUTILS, RE_SYNTAX_EMACS|RE_DOT_NEWLINE },
|
||||
{ "awk", CONTEXT_ALL, RE_SYNTAX_AWK },
|
||||
{ "ed", CONTEXT_GENERIC, RE_SYNTAX_ED },
|
||||
{ "egrep", CONTEXT_ALL, RE_SYNTAX_EGREP },
|
||||
{ "emacs", CONTEXT_ALL, RE_SYNTAX_EMACS },
|
||||
{ "gnu-awk", CONTEXT_ALL, RE_SYNTAX_GNU_AWK },
|
||||
{ "grep", CONTEXT_ALL, RE_SYNTAX_GREP },
|
||||
{ "posix-awk", CONTEXT_ALL, RE_SYNTAX_POSIX_AWK },
|
||||
{ "awk", CONTEXT_ALL, RE_SYNTAX_AWK },
|
||||
{ "posix-basic", CONTEXT_ALL, RE_SYNTAX_POSIX_BASIC },
|
||||
{ "posix-egrep", CONTEXT_ALL, RE_SYNTAX_POSIX_EGREP },
|
||||
{ "egrep", CONTEXT_ALL, RE_SYNTAX_EGREP },
|
||||
{ "posix-extended", CONTEXT_ALL, RE_SYNTAX_POSIX_EXTENDED },
|
||||
{ "posix-minimal-basic", CONTEXT_GENERIC, RE_SYNTAX_POSIX_MINIMAL_BASIC },
|
||||
{ "sed", CONTEXT_GENERIC, RE_SYNTAX_SED },
|
||||
@ -74,9 +74,9 @@ get_regex_type (const char *s)
|
||||
for (i=0u; i<N_REGEX_MAP_ENTRIES; ++i)
|
||||
{
|
||||
if (0 == strcmp (regex_map[i].name, s))
|
||||
return regex_map[i].option_val;
|
||||
return regex_map[i].option_val;
|
||||
else
|
||||
msglen += strlen (quote (regex_map[i].name)) + 2u;
|
||||
msglen += strlen (quote (regex_map[i].name)) + 2u;
|
||||
}
|
||||
|
||||
/* We didn't find a match for the type of regular expression that the
|
||||
@ -86,10 +86,10 @@ get_regex_type (const char *s)
|
||||
for (i=0u; i<N_REGEX_MAP_ENTRIES; ++i)
|
||||
{
|
||||
if (i > 0u)
|
||||
{
|
||||
strcpy (p, ", ");
|
||||
p += 2;
|
||||
}
|
||||
{
|
||||
strcpy (p, ", ");
|
||||
p += 2;
|
||||
}
|
||||
p += sprintf (p, "%s", quote (regex_map[i].name));
|
||||
}
|
||||
|
||||
@ -143,15 +143,15 @@ get_regex_type_synonym (unsigned int ix, unsigned int context)
|
||||
for (i=0u; i<ix; ++i)
|
||||
{
|
||||
if ((regex_map[i].context & context) == 0)
|
||||
{
|
||||
/* It is pointless to state that "x is a synonym of y" if we
|
||||
are not in fact going to include y. */
|
||||
continue;
|
||||
}
|
||||
{
|
||||
/* It is pointless to state that "x is a synonym of y" if we
|
||||
are not in fact going to include y. */
|
||||
continue;
|
||||
}
|
||||
else if (flags == regex_map[i].option_val)
|
||||
{
|
||||
return i;
|
||||
}
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/* regextype.h -- Decode the name of a regular expression syntax.
|
||||
|
||||
Copyright (C) 2005-2024 Free Software Foundation, Inc.
|
||||
Copyright (C) 2005-2026 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
|
||||
@ -40,7 +40,7 @@ enum {
|
||||
const char * get_regex_type_name(unsigned int ix);
|
||||
|
||||
|
||||
/* Returns the option mask name corresponding to regular expresion
|
||||
/* Returns the option mask name corresponding to regular expression
|
||||
* type index IX. Indexes start at 0. Behaviour is undefined if IX
|
||||
* has a value which would cause get_regex_type_name to return NULL.
|
||||
*/
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/* safe-atoi.c -- checked string-to-int conversion.
|
||||
Copyright (C) 2007-2024 Free Software Foundation, Inc.
|
||||
Copyright (C) 2007-2026 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
|
||||
@ -42,15 +42,15 @@ safe_atoi (const char *s, enum quoting_style style)
|
||||
{
|
||||
/* max/min possible value, or an error. */
|
||||
if (errno == ERANGE)
|
||||
{
|
||||
/* too big, or too small. */
|
||||
error (EXIT_FAILURE, errno, "%s", s);
|
||||
}
|
||||
{
|
||||
/* too big, or too small. */
|
||||
error (EXIT_FAILURE, errno, "%s", s);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* not a valid number */
|
||||
error (EXIT_FAILURE, errno, "%s", s);
|
||||
}
|
||||
{
|
||||
/* not a valid number */
|
||||
error (EXIT_FAILURE, errno, "%s", s);
|
||||
}
|
||||
/* Otherwise, we do a range check against INT_MAX and INT_MIN
|
||||
* below.
|
||||
*/
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/* safe-atoi.h -- checked string-to-int conversion.
|
||||
Copyright (C) 2010-2024 Free Software Foundation, Inc.
|
||||
Copyright (C) 2010-2026 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
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/* splitstring.c -- split a const string into fields.
|
||||
Copyright (C) 2011-2024 Free Software Foundation, Inc.
|
||||
Copyright (C) 2011-2026 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
|
||||
@ -37,7 +37,7 @@ field_length (const char *str, const char *separators)
|
||||
{
|
||||
const char *end = strpbrk (str, separators);
|
||||
if (end)
|
||||
return end - str;
|
||||
return end - str;
|
||||
}
|
||||
return strlen (str);
|
||||
}
|
||||
@ -45,7 +45,7 @@ field_length (const char *str, const char *separators)
|
||||
|
||||
bool
|
||||
splitstring(const char *s, const char *separators, bool first,
|
||||
size_t *pos, size_t *len)
|
||||
size_t *pos, size_t *len)
|
||||
{
|
||||
if (first)
|
||||
{
|
||||
@ -54,11 +54,11 @@ splitstring(const char *s, const char *separators, bool first,
|
||||
}
|
||||
else
|
||||
{
|
||||
*pos += *len; /* advance to the next field. */
|
||||
*pos += *len; /* advance to the next field. */
|
||||
if (s[*pos])
|
||||
++*pos; /* skip the separator */
|
||||
++*pos; /* skip the separator */
|
||||
else
|
||||
return false; /* we reached the end. */
|
||||
return false; /* we reached the end. */
|
||||
}
|
||||
*len = field_length (&s[*pos], separators);
|
||||
return true;
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/* splitstring.h -- split a const string into fields.
|
||||
Copyright (C) 2011-2024 Free Software Foundation, Inc.
|
||||
Copyright (C) 2011-2026 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
|
||||
@ -23,7 +23,7 @@
|
||||
/* Split a string into fields. The string is never modified.
|
||||
*
|
||||
* A false return value indicates that there are no more fields.
|
||||
* Otherwise the next field is at the poisition indicated by *POS and
|
||||
* Otherwise the next field is at the position indicated by *POS and
|
||||
* has length *LEN.
|
||||
*
|
||||
* Set FIRST to true only on the first call for any given value of s.
|
||||
@ -39,6 +39,6 @@
|
||||
# include <stddef.h>
|
||||
|
||||
bool splitstring(const char *s, const char *separators,
|
||||
bool first, size_t *pos, size_t *len);
|
||||
bool first, size_t *pos, size_t *len);
|
||||
|
||||
#endif
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/* system.h -- system-dependent definitions for findutils
|
||||
|
||||
Copyright (C) 2017-2024 Free Software Foundation, Inc.
|
||||
Copyright (C) 2017-2026 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
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/* test_splitstring.c -- unit test for splitstring()
|
||||
Copyright (C) 2011-2024 Free Software Foundation, Inc.
|
||||
Copyright (C) 2011-2026 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
|
||||
@ -29,11 +29,11 @@
|
||||
|
||||
static void
|
||||
assertEqualFunc(const char *file, int line, const char *label,
|
||||
size_t expected, size_t got)
|
||||
size_t expected, size_t got)
|
||||
{
|
||||
if (expected != got)
|
||||
fprintf(stderr, "%s line %d: %s: expected %lu, got %lu\n",
|
||||
file, line, label, (unsigned long)expected, (unsigned long)got);
|
||||
file, line, label, (unsigned long)expected, (unsigned long)got);
|
||||
}
|
||||
#define ASSERT_EQUAL(expected,got) \
|
||||
do{ \
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/* unused-result.h -- macros for ensuring callers don't ignore return values
|
||||
Copyright (C) 2010-2024 Free Software Foundation, Inc.
|
||||
Copyright (C) 2010-2026 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
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
# The default database to build and search.
|
||||
|
||||
## Copyright (C) 1996-2024 Free Software Foundation, Inc.
|
||||
## Copyright (C) 1996-2026 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
|
||||
@ -35,7 +35,7 @@ nodist_locate_TEXINFOS = dblocation.texi
|
||||
|
||||
AM_CPPFLAGS = -I$(top_srcdir)/lib -I../gl/lib -I$(top_srcdir)/gl/lib -DLOCATE_DB=\"$(LOCATE_DB)\" -DLOCALEDIR=\"$(localedir)\"
|
||||
|
||||
LDADD = ../lib/libfind.a ../gl/lib/libgnulib.a $(LIB_CLOSE) $(LIBINTL) $(LIB_SETLOCALE_NULL) $(LIB_MBRTOWC)
|
||||
LDADD = ../lib/libfind.a ../gl/lib/libgnulib.a $(LIBINTL) $(SETLOCALE_NULL_LIB) $(MBRTOWC_LIB)
|
||||
|
||||
$(PROGRAMS) $(LIBPROGRAMS): ../lib/libfind.a ../gl/lib/libgnulib.a
|
||||
|
||||
@ -79,10 +79,10 @@ dblocation.texi:
|
||||
|
||||
SUBDIRS = . testsuite
|
||||
|
||||
dist-hook: findutils-check-manpages
|
||||
check-local: findutils-check-manpages
|
||||
|
||||
findutils-check-manpages:
|
||||
$(top_srcdir)/build-aux/man-lint.sh $(srcdir) $(man_MANS)
|
||||
env GROFF=$(GROFF) $(top_srcdir)/build-aux/man-lint.sh $(srcdir) $(man_MANS)
|
||||
|
||||
# Clean coverage files generated by running binaries built with
|
||||
# gcc -fprofile-arcs -ftest-coverage
|
||||
|
||||
156
locate/frcode.c
156
locate/frcode.c
@ -1,5 +1,5 @@
|
||||
/* frcode -- front-compress a sorted list
|
||||
Copyright (C) 1994-2024 Free Software Foundation, Inc.
|
||||
Copyright (C) 1994-2026 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
|
||||
@ -117,7 +117,7 @@ prefix_length (char *s1, char *s2)
|
||||
* our return type.
|
||||
*/
|
||||
if (0 == --limit)
|
||||
break;
|
||||
break;
|
||||
}
|
||||
return s1 - start;
|
||||
}
|
||||
@ -130,8 +130,6 @@ static struct option const longopts[] =
|
||||
{NULL, no_argument, NULL, 0}
|
||||
};
|
||||
|
||||
extern char *version_string;
|
||||
|
||||
static void _GL_ATTRIBUTE_NORETURN
|
||||
usage (int status)
|
||||
{
|
||||
@ -142,8 +140,8 @@ usage (int status)
|
||||
}
|
||||
|
||||
fprintf (stdout,
|
||||
_("Usage: %s [-0 | --null] [--version] [--help]\n"),
|
||||
program_name);
|
||||
_("Usage: %s [-0 | --null] [--version] [--help]\n"),
|
||||
program_name);
|
||||
|
||||
explain_how_to_report_bugs (stdout, program_name);
|
||||
exit (status);
|
||||
@ -164,7 +162,7 @@ get_seclevel (char *s)
|
||||
if ((0==result) && (p == optarg))
|
||||
{
|
||||
error (EXIT_FAILURE, 0,
|
||||
_("You need to specify a security level as a decimal integer."));
|
||||
_("You need to specify a security level as a decimal integer."));
|
||||
/*NOTREACHED*/
|
||||
return -1;
|
||||
}
|
||||
@ -172,7 +170,7 @@ get_seclevel (char *s)
|
||||
|
||||
{
|
||||
error (EXIT_FAILURE, 0,
|
||||
_("Security level %s is outside the convertible range."), s);
|
||||
_("Security level %s is outside the convertible range."), s);
|
||||
/*NOTREACHED*/
|
||||
return -1;
|
||||
}
|
||||
@ -180,7 +178,7 @@ get_seclevel (char *s)
|
||||
{
|
||||
/* Some suffix exists */
|
||||
error (EXIT_FAILURE, 0,
|
||||
_("Security level %s has unexpected suffix %s."), s, p);
|
||||
_("Security level %s has unexpected suffix %s."), s, p);
|
||||
/*NOTREACHED*/
|
||||
return -1;
|
||||
}
|
||||
@ -200,11 +198,11 @@ outerr (void)
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
char *path; /* The current input entry. */
|
||||
char *oldpath; /* The previous input entry. */
|
||||
size_t pathsize, oldpathsize; /* Amounts allocated for them. */
|
||||
char *path; /* The current input entry. */
|
||||
char *oldpath; /* The previous input entry. */
|
||||
size_t pathsize, oldpathsize; /* Amounts allocated for them. */
|
||||
int count, oldcount, diffcount; /* Their prefix lengths & the difference. */
|
||||
int line_len; /* Length of input line. */
|
||||
int line_len; /* Length of input line. */
|
||||
int delimiter = '\n';
|
||||
int optc;
|
||||
int slocate_compat = 0;
|
||||
@ -232,29 +230,29 @@ main (int argc, char **argv)
|
||||
switch (optc)
|
||||
{
|
||||
case '0':
|
||||
delimiter = 0;
|
||||
break;
|
||||
delimiter = 0;
|
||||
break;
|
||||
|
||||
case 'S':
|
||||
slocate_compat = 1;
|
||||
slocate_seclevel = get_seclevel (optarg);
|
||||
if (slocate_seclevel < 0 || slocate_seclevel > 1)
|
||||
{
|
||||
error (EXIT_FAILURE, 0,
|
||||
_("slocate security level %ld is unsupported."),
|
||||
slocate_seclevel);
|
||||
}
|
||||
break;
|
||||
slocate_compat = 1;
|
||||
slocate_seclevel = get_seclevel (optarg);
|
||||
if (slocate_seclevel < 0 || slocate_seclevel > 1)
|
||||
{
|
||||
error (EXIT_FAILURE, 0,
|
||||
_("slocate security level %ld is unsupported."),
|
||||
slocate_seclevel);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'h':
|
||||
usage (EXIT_SUCCESS);
|
||||
usage (EXIT_SUCCESS);
|
||||
|
||||
case 'v':
|
||||
display_findutils_version ("frcode");
|
||||
return 0;
|
||||
display_findutils_version ("frcode");
|
||||
return 0;
|
||||
|
||||
default:
|
||||
usage (EXIT_FAILURE);
|
||||
usage (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* We expect to have no arguments. */
|
||||
@ -275,76 +273,76 @@ main (int argc, char **argv)
|
||||
{
|
||||
/* GNU LOCATE02 format */
|
||||
if (fwrite (LOCATEDB_MAGIC, 1, sizeof (LOCATEDB_MAGIC), stdout)
|
||||
!= sizeof (LOCATEDB_MAGIC))
|
||||
{
|
||||
error (EXIT_FAILURE, errno, _("Failed to write to standard output"));
|
||||
}
|
||||
!= sizeof (LOCATEDB_MAGIC))
|
||||
{
|
||||
error (EXIT_FAILURE, errno, _("Failed to write to standard output"));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
while ((line_len = getdelim (&path, &pathsize, delimiter, stdin)) > 0)
|
||||
{
|
||||
if (path[line_len - 1] != delimiter)
|
||||
{
|
||||
error (0, 0, _("The input file should end with the delimiter"));
|
||||
}
|
||||
{
|
||||
error (0, 0, _("The input file should end with the delimiter"));
|
||||
}
|
||||
else
|
||||
{
|
||||
path[line_len - 1] = '\0'; /* FIXME temporary: nuke the delimiter. */
|
||||
}
|
||||
{
|
||||
path[line_len - 1] = '\0'; /* FIXME temporary: nuke the delimiter. */
|
||||
}
|
||||
|
||||
count = prefix_length (oldpath, path);
|
||||
diffcount = count - oldcount;
|
||||
if ( (diffcount > SHRT_MAX) || (diffcount < SHRT_MIN) )
|
||||
{
|
||||
/* We do this to prevent overflow of the value we
|
||||
* write with put_short ()
|
||||
*/
|
||||
count = 0;
|
||||
diffcount = (-oldcount);
|
||||
}
|
||||
{
|
||||
/* We do this to prevent overflow of the value we
|
||||
* write with put_short ()
|
||||
*/
|
||||
count = 0;
|
||||
diffcount = (-oldcount);
|
||||
}
|
||||
oldcount = count;
|
||||
|
||||
if (slocate_compat)
|
||||
{
|
||||
/* Emit no count for the first pathname. */
|
||||
slocate_compat = 0;
|
||||
}
|
||||
{
|
||||
/* Emit no count for the first pathname. */
|
||||
slocate_compat = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* If the difference is small, it fits in one byte;
|
||||
otherwise, two bytes plus a marker noting that fact. */
|
||||
if (diffcount < LOCATEDB_ONEBYTE_MIN
|
||||
|| diffcount > LOCATEDB_ONEBYTE_MAX)
|
||||
{
|
||||
if (EOF == putc (LOCATEDB_ESCAPE, stdout))
|
||||
outerr ();
|
||||
if (!put_short (diffcount, stdout))
|
||||
outerr ();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (EOF == putc (diffcount, stdout))
|
||||
outerr ();
|
||||
}
|
||||
}
|
||||
{
|
||||
/* If the difference is small, it fits in one byte;
|
||||
otherwise, two bytes plus a marker noting that fact. */
|
||||
if (diffcount < LOCATEDB_ONEBYTE_MIN
|
||||
|| diffcount > LOCATEDB_ONEBYTE_MAX)
|
||||
{
|
||||
if (EOF == putc (LOCATEDB_ESCAPE, stdout))
|
||||
outerr ();
|
||||
if (!put_short (diffcount, stdout))
|
||||
outerr ();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (EOF == putc (diffcount, stdout))
|
||||
outerr ();
|
||||
}
|
||||
}
|
||||
|
||||
if ( (EOF == fputs (path + count, stdout))
|
||||
|| (EOF == putc ('\0', stdout)))
|
||||
{
|
||||
outerr ();
|
||||
}
|
||||
|| (EOF == putc ('\0', stdout)))
|
||||
{
|
||||
outerr ();
|
||||
}
|
||||
|
||||
if (1)
|
||||
{
|
||||
/* Swap path and oldpath and their sizes. */
|
||||
char *tmppath = oldpath;
|
||||
size_t tmppathsize = oldpathsize;
|
||||
oldpath = path;
|
||||
oldpathsize = pathsize;
|
||||
path = tmppath;
|
||||
pathsize = tmppathsize;
|
||||
}
|
||||
{
|
||||
/* Swap path and oldpath and their sizes. */
|
||||
char *tmppath = oldpath;
|
||||
size_t tmppathsize = oldpathsize;
|
||||
oldpath = path;
|
||||
oldpathsize = pathsize;
|
||||
path = tmppath;
|
||||
pathsize = tmppathsize;
|
||||
}
|
||||
}
|
||||
|
||||
free (path);
|
||||
|
||||
138
locate/locate.1
138
locate/locate.1
@ -1,28 +1,83 @@
|
||||
.TH LOCATE 1 \" -*- nroff -*-
|
||||
.TH LOCATE 1 2020-12-27 findutils \" -*- nroff -*-
|
||||
.\" As a GNU troff extension, \% at the beginning of a word suppresses
|
||||
.\" its hyphenation.
|
||||
.ie \n(.g \{\
|
||||
. ds ^ \(ha
|
||||
. ds en \(en
|
||||
. ds % \%
|
||||
.\}
|
||||
.el \{\
|
||||
. ds ^ ^
|
||||
. ds en \-
|
||||
. ds % \" empty
|
||||
.\}
|
||||
.SH NAME
|
||||
locate \- list files in databases that match a pattern
|
||||
.
|
||||
.SH SYNOPSIS
|
||||
.TP \" FIXME-2027: switch to .HP when groff-1.24 is more commonly available.
|
||||
.nr sA \n(.j \" Save the adjustment mode.
|
||||
.na
|
||||
.B locate
|
||||
[\-d path | \-\-database=path]
|
||||
[\-e | \-E | \-\-[non\-]existing]
|
||||
[\-i | \-\-ignore-case]
|
||||
[\-0 | \-\-null]
|
||||
[\-c | \-\-count]
|
||||
[\-w | \-\-wholename]
|
||||
[\-b | \-\-basename]
|
||||
[\-l N | \-\-limit=N]
|
||||
[\-S | \-\-statistics]
|
||||
[\-r | \-\-regex ]
|
||||
[\-\-regextype R]
|
||||
[\-\-max-database-age D]
|
||||
[\-P | \-H | \-\-nofollow]
|
||||
[\-L | \-\-follow]
|
||||
[\-\-version]
|
||||
[\-A | \-\-all]
|
||||
[\-p | \-\-print]
|
||||
[\-\-help]
|
||||
pattern...
|
||||
.RB [ \-d\ \c
|
||||
.I path
|
||||
|
|
||||
.BI \*%\-\-database= path\c
|
||||
]
|
||||
.RB [ \-e
|
||||
|
|
||||
.B \-E
|
||||
|
|
||||
.BR \*%\-\- [ non\- ] existing ]
|
||||
.RB [ \-i
|
||||
|
|
||||
.BR \*%\-\-ignore\-case ]
|
||||
.RB [ \-0
|
||||
|
|
||||
.BR \-\-null ]
|
||||
.RB [ \-c
|
||||
|
|
||||
.BR \*%\-\-count ]
|
||||
.RB [ \-w
|
||||
|
|
||||
.BR \*%\-\-wholename ]
|
||||
.RB [ \-b
|
||||
|
|
||||
.BR \*%\-\-basename ]
|
||||
.RB [ \-l\ \c
|
||||
.I N
|
||||
|
|
||||
.BI \*%\-\-limit= N\c
|
||||
]
|
||||
.RB [ \-S
|
||||
|
|
||||
.BR \*%\-\-statistics ]
|
||||
.RB [ \-r
|
||||
|
|
||||
.BR \*%\-\-regex ]
|
||||
.RB \*%[ \-\-regextype\ \c
|
||||
.IR R ]
|
||||
.RB \*%[ \-\-max\-database\-age\ \c
|
||||
.IR D ]
|
||||
.RB [ \-P
|
||||
|
|
||||
.B \-H
|
||||
|
|
||||
.BR \*%\-\-nofollow ]
|
||||
.RB [ \-L
|
||||
|
|
||||
.BR \*%\-\-follow ]
|
||||
.RB \*%[ \-\-version ]
|
||||
.RB [ \-A
|
||||
|
|
||||
.BR \-\-all ]
|
||||
.RB [ \-p
|
||||
|
|
||||
.BR \*%\-\-print ]
|
||||
.RB \*%[ \-\-help ]
|
||||
.IR pattern .\|.\|.
|
||||
.ad \n(sA \" Restore the adjustment mode.
|
||||
.rr sA
|
||||
.
|
||||
.SH DESCRIPTION
|
||||
This manual page
|
||||
@ -91,8 +146,9 @@ to set the list of database files to search.
|
||||
The option overrides the environment variable if both are used. Empty
|
||||
elements in the path are taken to be synonyms for the file name of the
|
||||
default database.
|
||||
A database can be supplied on stdin, using `\-' as an element
|
||||
of \fIpath\fP. If more than one element of \fIpath\fP is `\-',
|
||||
A database can be supplied on standard input, using `\-' as an element
|
||||
of \fIpath\fP.
|
||||
If more than one element of \fIpath\fP is `\-',
|
||||
later instances are ignored (and a warning message is printed).
|
||||
.IP
|
||||
The file name database format changed starting with GNU
|
||||
@ -240,22 +296,32 @@ appears to be derived from the same code.
|
||||
Significant changes to
|
||||
.B locate
|
||||
in reverse order:
|
||||
.P
|
||||
.TS
|
||||
tab(|);
|
||||
LL.
|
||||
4.3.7 | Byte-order independent support for old database format
|
||||
4.3.3 | locate \fI\-i\fR supports multi-byte characters correctly
|
||||
| Introduced \fI\-\-max_db_age\fR
|
||||
4.3.2 | Support for the slocate database format
|
||||
4.2.22| Introduced the \fI\-\-all\fR option
|
||||
4.2.15| Introduced the \fI\-\-regex\fR option
|
||||
4.2.14| Introduced options \fI\-L, \-P, \-H\fR
|
||||
4.2.12| Empty items in \fBLOCATE_PATH\fR now indicate the default database
|
||||
4.2.11| Introduced the \fI\-\-statistics\fR option
|
||||
4.2.4 | Introduced \fI\-\-count\fR and \fI\-\-limit\fR
|
||||
4.2.0 | Glob characters cause matching against the whole file name
|
||||
4.0 | Introduced the LOCATE02 database format
|
||||
3.7 | Locate can search multiple databases
|
||||
4.3.7|T{
|
||||
.na
|
||||
Byte-order independent support for old database format
|
||||
T}
|
||||
4.3.3|locate \fI\-i\fR supports multi-byte characters correctly
|
||||
\^|Introduced \fI\-\-max_db_age\fR
|
||||
4.3.2|Support for the slocate database format
|
||||
4.2.22|Introduced the \fI\-\-all\fR option
|
||||
4.2.15|Introduced the \fI\-\-regex\fR option
|
||||
4.2.14|Introduced options \fI\-L, \-P, \-H\fR
|
||||
4.2.12|T{
|
||||
.na
|
||||
Empty items in \fBLOCATE_PATH\fR now indicate the default database
|
||||
T}
|
||||
4.2.11|Introduced the \fI\-\-statistics\fR option
|
||||
4.2.4|Introduced \fI\-\-count\fR and \fI\-\-limit\fR
|
||||
4.2.0|T{
|
||||
.na
|
||||
Glob characters cause matching against the whole file name
|
||||
T}
|
||||
4.0|Introduced the LOCATE02 database format
|
||||
3.7|Locate can search multiple databases
|
||||
.TE
|
||||
.
|
||||
.SH "BUGS"
|
||||
@ -287,7 +353,7 @@ mailing list:
|
||||
.RE
|
||||
.
|
||||
.SH COPYRIGHT
|
||||
Copyright \(co 1994\(en2024 Free Software Foundation, Inc.
|
||||
Copyright \(co 1994\*(en2026 Free Software Foundation, Inc.
|
||||
License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>.
|
||||
.br
|
||||
This is free software: you are free to change and redistribute it.
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/* locate -- search databases for filenames that match patterns
|
||||
Copyright (C) 1994-2024 Free Software Foundation, Inc.
|
||||
Copyright (C) 1994-2026 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
|
||||
@ -35,7 +35,7 @@
|
||||
8, No 1, February/March, 1983, p. 8.
|
||||
|
||||
However, latterly code changes to provide additional functionality
|
||||
became dificult to make with the existing reading scheme, and so
|
||||
became difficult to make with the existing reading scheme, and so
|
||||
we no longer perform the matching as efficiently as we used to (that is,
|
||||
we no longer use the same algorithm).
|
||||
|
||||
@ -1033,7 +1033,7 @@ search_one_database (int argc,
|
||||
* We ensure that we can return to the previous behaviour
|
||||
* by using two variables, do_check_existence (which we act on)
|
||||
* and check_existence (which indicates the default before we
|
||||
* adjust it on the bassis of what kind of database we;re using
|
||||
* adjust it on the basis of what kind of database we're using
|
||||
*/
|
||||
do_check_existence = check_existence;
|
||||
|
||||
@ -1353,8 +1353,6 @@ search_one_database (int argc,
|
||||
}
|
||||
|
||||
|
||||
extern char *version_string;
|
||||
|
||||
static void _GL_ATTRIBUTE_NORETURN
|
||||
usage (int status)
|
||||
{
|
||||
@ -1758,7 +1756,7 @@ dolocate (int argc, char **argv, int secure_db_fd)
|
||||
if (did_stdin)
|
||||
{
|
||||
error (0, 0,
|
||||
_("warning: the locate database can only be read from stdin once."));
|
||||
_("warning: the locate database can only be read from standard input once."));
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
|
||||
@ -1,4 +1,10 @@
|
||||
.TH LOCATEDB 5 \" -*- nroff -*-
|
||||
.TH LOCATEDB 5 2020-12-27 findutils \" -*- nroff -*-
|
||||
.ie \n(.g \{\
|
||||
. ds en \(en
|
||||
.\}
|
||||
.el \{\
|
||||
. ds en \-
|
||||
.\}
|
||||
.SH NAME
|
||||
locatedb \- front-compressed file name database
|
||||
.
|
||||
@ -107,7 +113,7 @@ format starts with a 256 byte table containing the 128 most common
|
||||
bigrams in the file list. A bigram is a pair of adjacent bytes.
|
||||
Bytes in the database that have the high bit set are indexes (with the
|
||||
high bit cleared) into the bigram table. The bigram and
|
||||
offset-differential count coding makes these databases 20\(en25% smaller
|
||||
offset-differential count coding makes these databases 20\*(en25% smaller
|
||||
than the new format, but makes them not 8-bit clean. Any byte in a
|
||||
file name that is in the ranges used for the special codes is replaced
|
||||
in the database by a question mark, which not coincidentally is the
|
||||
@ -115,20 +121,20 @@ shell wildcard to match a single character.
|
||||
.
|
||||
.SH EXAMPLE
|
||||
.nf
|
||||
|
||||
\&
|
||||
Input to \fBfrcode\fP:
|
||||
.\" with nulls changed to newlines:
|
||||
/usr/src
|
||||
/usr/src/cmd/aardvark.c
|
||||
/usr/src/cmd/armadillo.c
|
||||
/usr/tmp/zoo
|
||||
|
||||
\&
|
||||
Length of the longest prefix of the preceding entry to share:
|
||||
0 /usr/src
|
||||
8 /cmd/aardvark.c
|
||||
14 rmadillo.c
|
||||
5 tmp/zoo
|
||||
|
||||
\&
|
||||
.fi
|
||||
Output from \fBfrcode\fP, with trailing nulls changed to newlines
|
||||
and count bytes made printable:
|
||||
@ -138,8 +144,8 @@ and count bytes made printable:
|
||||
8 /cmd/aardvark.c
|
||||
6 rmadillo.c
|
||||
\-9 tmp/zoo
|
||||
|
||||
(6 = 14 - 8, and -9 = 5 - 14)
|
||||
\&
|
||||
(6 = 14 \- 8, and \-9 = 5 \- 14)
|
||||
.fi
|
||||
.
|
||||
.SH "REPORTING BUGS"
|
||||
@ -159,7 +165,7 @@ mailing list:
|
||||
.RE
|
||||
.
|
||||
.SH COPYRIGHT
|
||||
Copyright \(co 1994\(en2024 Free Software Foundation, Inc.
|
||||
Copyright \(co 1994\*(en2026 Free Software Foundation, Inc.
|
||||
License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>.
|
||||
.br
|
||||
This is free software: you are free to change and redistribute it.
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/* locatedb.h -- declarations for the locate database
|
||||
Copyright (C) 1994-2024 Free Software Foundation, Inc.
|
||||
Copyright (C) 1994-2026 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
|
||||
@ -47,10 +47,10 @@
|
||||
/* These are used for old, bigram-encoded databases: */
|
||||
|
||||
/* Means the differential count follows in a 2-byte int instead. */
|
||||
# define LOCATEDB_OLD_ESCAPE 30
|
||||
# define LOCATEDB_OLD_ESCAPE 30
|
||||
|
||||
/* Offset added to differential counts to encode them as positive numbers. */
|
||||
# define LOCATEDB_OLD_OFFSET 14
|
||||
# define LOCATEDB_OLD_OFFSET 14
|
||||
|
||||
typedef enum
|
||||
{
|
||||
@ -60,8 +60,8 @@ typedef enum
|
||||
} GetwordEndianState;
|
||||
|
||||
int getword (FILE *fp, const char *filename,
|
||||
size_t maxvalue,
|
||||
GetwordEndianState *endian_state_flag);
|
||||
size_t maxvalue,
|
||||
GetwordEndianState *endian_state_flag);
|
||||
|
||||
# define SLOCATE_DB_MAGIC_LEN 2
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
# Copyright (C) 2001-2024 Free Software Foundation, Inc.
|
||||
# Copyright (C) 2001-2026 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
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
# -*- TCL -*-
|
||||
# Test-specific TCL procedures required by DejaGNU.
|
||||
# Copyright (C) 1994-2024 Free Software Foundation, Inc.
|
||||
# Copyright (C) 1994-2026 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
|
||||
|
||||
@ -1,8 +1,15 @@
|
||||
.TH UPDATEDB 1 \" -*- nroff -*-
|
||||
.TH UPDATEDB 1 2023-11-10 findutils \" -*- nroff -*-
|
||||
.ie \n(.g \{\
|
||||
. ds en \(en
|
||||
.\}
|
||||
.el \{\
|
||||
. ds en \-
|
||||
.\}
|
||||
.SH NAME
|
||||
updatedb \- update a file name database
|
||||
.SH SYNOPSIS
|
||||
.B updatedb [\fIoptions\fP]
|
||||
.B updatedb
|
||||
.RI [ options ]
|
||||
.
|
||||
.SH DESCRIPTION
|
||||
This manual page
|
||||
@ -139,7 +146,7 @@ mailing list:
|
||||
.RE
|
||||
.
|
||||
.SH COPYRIGHT
|
||||
Copyright \(co 1994\(en2024 Free Software Foundation, Inc.
|
||||
Copyright \(co 1994\*(en2026 Free Software Foundation, Inc.
|
||||
License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>.
|
||||
.br
|
||||
This is free software: you are free to change and redistribute it.
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
#! /bin/sh
|
||||
# updatedb -- build a locate pathname database
|
||||
# Copyright (C) 1994-2024 Free Software Foundation, Inc.
|
||||
# Copyright (C) 1994-2026 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
|
||||
@ -39,7 +39,7 @@ Written by Eric B. Decker, James Youngman, and Kevin Dalley.
|
||||
# character encoding errors in text-based tools like "sort". To avoid
|
||||
# this, we set LC_ALL=C. This will, presumably, not work perfectly on
|
||||
# systems where LC_ALL is not the way to do locale configuration or
|
||||
# some other seting can override this.
|
||||
# some other setting can override this.
|
||||
LC_ALL=C
|
||||
export LC_ALL
|
||||
|
||||
@ -147,7 +147,7 @@ select_shell() {
|
||||
# Any global options for find?
|
||||
: ${FINDOPTIONS=}
|
||||
|
||||
# What shell shoud we use? We should use a POSIX-ish sh.
|
||||
# What shell should we use? We should use a POSIX-ish sh.
|
||||
: ${SHELL="/bin/sh"}
|
||||
|
||||
# Non-network directories to put in the database.
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/* word_io.c -- word oriented I/O
|
||||
Copyright (C) 2007-2024 Free Software Foundation, Inc.
|
||||
Copyright (C) 2007-2026 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
|
||||
@ -20,13 +20,13 @@
|
||||
|
||||
/* system headers. */
|
||||
#include <errno.h>
|
||||
#include <stdbool.h> /* for bool */
|
||||
#include <stdbool.h> /* for bool */
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
/* gnulib headers. */
|
||||
#include "byteswap.h"
|
||||
#include <endian.h>
|
||||
#include "quotearg.h"
|
||||
|
||||
/* find headers. */
|
||||
@ -38,62 +38,62 @@ enum { WORDBYTES=4 };
|
||||
|
||||
static int
|
||||
decode_value (const unsigned char data[],
|
||||
int limit,
|
||||
GetwordEndianState *endian_state_flag,
|
||||
const char *filename)
|
||||
int limit,
|
||||
GetwordEndianState *endian_state_flag,
|
||||
const char *filename)
|
||||
{
|
||||
int swapped;
|
||||
union
|
||||
{
|
||||
int ival; /* native representation */
|
||||
int ival; /* native representation */
|
||||
unsigned char data[WORDBYTES];
|
||||
} u;
|
||||
u.ival = 0;
|
||||
memcpy (&u.data, data, WORDBYTES);
|
||||
swapped = bswap_32(u.ival); /* byteswapped */
|
||||
swapped = htobe32 (u.ival); /* byteswapped */
|
||||
|
||||
if (*endian_state_flag == GetwordEndianStateInitial)
|
||||
{
|
||||
if (u.ival <= limit)
|
||||
{
|
||||
if (swapped > limit)
|
||||
{
|
||||
/* the native value is inside the limit and the
|
||||
* swapped value is not. We take this as proof
|
||||
* that we should be using the native byte order.
|
||||
*/
|
||||
*endian_state_flag = GetwordEndianStateNative;
|
||||
}
|
||||
return u.ival;
|
||||
}
|
||||
{
|
||||
if (swapped > limit)
|
||||
{
|
||||
/* the native value is inside the limit and the
|
||||
* swapped value is not. We take this as proof
|
||||
* that we should be using the native byte order.
|
||||
*/
|
||||
*endian_state_flag = GetwordEndianStateNative;
|
||||
}
|
||||
return u.ival;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (swapped <= limit)
|
||||
{
|
||||
/* Aha, now we know we have to byte-swap. */
|
||||
error (0, 0,
|
||||
_("WARNING: locate database %s was "
|
||||
"built with a different byte order"),
|
||||
quotearg_n_style (0, locale_quoting_style, filename));
|
||||
*endian_state_flag = GetwordEndianStateSwab;
|
||||
return swapped;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* u.ival > limit and swapped > limit. For the moment, assume
|
||||
* native ordering.
|
||||
*/
|
||||
return u.ival;
|
||||
}
|
||||
}
|
||||
{
|
||||
if (swapped <= limit)
|
||||
{
|
||||
/* Aha, now we know we have to byte-swap. */
|
||||
error (0, 0,
|
||||
_("WARNING: locate database %s was "
|
||||
"built with a different byte order"),
|
||||
quotearg_n_style (0, locale_quoting_style, filename));
|
||||
*endian_state_flag = GetwordEndianStateSwab;
|
||||
return swapped;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* u.ival > limit and swapped > limit. For the moment, assume
|
||||
* native ordering.
|
||||
*/
|
||||
return u.ival;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* We already know the byte order. */
|
||||
if (*endian_state_flag == GetwordEndianStateSwab)
|
||||
return swapped;
|
||||
return swapped;
|
||||
else
|
||||
return u.ival;
|
||||
return u.ival;
|
||||
}
|
||||
}
|
||||
|
||||
@ -101,9 +101,9 @@ decode_value (const unsigned char data[],
|
||||
|
||||
int
|
||||
getword (FILE *fp,
|
||||
const char *filename,
|
||||
size_t maxvalue,
|
||||
GetwordEndianState *endian_state_flag)
|
||||
const char *filename,
|
||||
size_t maxvalue,
|
||||
GetwordEndianState *endian_state_flag)
|
||||
{
|
||||
unsigned char data[4];
|
||||
size_t bytes_read;
|
||||
@ -113,15 +113,15 @@ getword (FILE *fp,
|
||||
if (bytes_read != 1)
|
||||
{
|
||||
const char * quoted_name = quotearg_n_style (0, locale_quoting_style,
|
||||
filename);
|
||||
filename);
|
||||
/* Distinguish between a truncated database and an I/O error.
|
||||
* Either condition is fatal.
|
||||
*/
|
||||
if (feof (fp))
|
||||
error (EXIT_FAILURE, 0, _("unexpected EOF in %s"), quoted_name);
|
||||
error (EXIT_FAILURE, 0, _("unexpected EOF in %s"), quoted_name);
|
||||
else
|
||||
error (EXIT_FAILURE, errno,
|
||||
_("error reading a word from %s"), quoted_name);
|
||||
error (EXIT_FAILURE, errno,
|
||||
_("error reading a word from %s"), quoted_name);
|
||||
abort ();
|
||||
}
|
||||
else
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
dnl Copyright (C) 1995-2024 Free Software Foundation, Inc.
|
||||
dnl Copyright (C) 1995-2026 Free Software Foundation, Inc.
|
||||
dnl This file is free software; the Free Software Foundation
|
||||
dnl gives unlimited permission to copy and/or distribute it,
|
||||
dnl with or without modifications, as long as this notice is preserved.
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
dnl Copyright (C) 2007-2024 Free Software Foundation, Inc.
|
||||
dnl Copyright (C) 2007-2026 Free Software Foundation, Inc.
|
||||
dnl This file is free software; the Free Software Foundation
|
||||
dnl gives unlimited permission to copy and/or distribute it,
|
||||
dnl with or without modifications, as long as this notice is preserved.
|
||||
|
||||
1
po/.gitignore
vendored
1
po/.gitignore
vendored
@ -1,3 +1,4 @@
|
||||
/insert-header.sed
|
||||
/*.gmo
|
||||
/*.po
|
||||
/.reference/
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
# List of source files containing translatable strings.
|
||||
# Copyright (C) 2000-2024 Free Software Foundation, Inc.
|
||||
# Copyright (C) 2000-2026 Free Software Foundation, Inc.
|
||||
|
||||
# Copying and distribution of this file, with or without
|
||||
# modification, are permitted provided the copyright notice
|
||||
|
||||
1
tests/.gitignore
vendored
1
tests/.gitignore
vendored
@ -1,5 +1,6 @@
|
||||
/*/*.log
|
||||
/*/*.trs
|
||||
/init.sh
|
||||
/test-suite.log
|
||||
/xargs/.dirstamp
|
||||
/xargs/test-sigusr
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user