Package init

This commit is contained in:
overweight 2019-09-30 10:38:48 -04:00
commit 3afccfd019
38 changed files with 5196 additions and 0 deletions

View File

@ -0,0 +1,108 @@
From 26d48c7cf9c25ddc8874d5483c0b5156dcc62132 Mon Sep 17 00:00:00 2001
From: Maximiliano Curia <maxy@debian.org>
Date: Thu, 30 Jun 2016 01:18:17 +0200
Subject: [PATCH 069/224] Fix bug #48314: find: fix -type option regression on
some platforms
Since commit v4.6.0-61-g6c37ce4, the option -type and -ltype is broken
on armel, armhf and mipsel at least. The reason is that the union member
args of the struct predicate was not completely initialized as its new
bool types[] member may be implemented larger than the union member
initialized: str.
* find/tree.c (set_new_parent): Replace xmalloc() by xzalloc() to
initialize the complete new predicate structure. Therefore, remove all
individual NULL and false initializations.
(get_new_pred): Likewise, plus move the xzmalloc() invocations before
the if-condition to have only one place left for the allocation, thus
improving readability.
Reported by Andreas Metzler <ametzler@bebt.de> in
https://savannah.gnu.org/bugs/?48314
Co-authored-by: Bernhard Voelker <mail@bernhard-voelker.de>
Copyright-paperwork-exempt: Yes
---
find/tree.c | 31 +++++--------------------------
1 file changed, 5 insertions(+), 26 deletions(-)
diff --git a/find/tree.c b/find/tree.c
index 8a413f88..2bbfbe5a 100644
--- a/find/tree.c
+++ b/find/tree.c
@@ -865,14 +865,11 @@ set_new_parent (struct predicate *curr, enum predicate_precedence high_prec, str
{
struct predicate *new_parent;
- new_parent = xmalloc (sizeof (struct predicate));
+ /* Allocate + initialize a new predicate. */
+ new_parent = xzalloc (sizeof (struct predicate));
new_parent->p_type = BI_OP;
new_parent->p_prec = high_prec;
- new_parent->need_stat = false;
- new_parent->need_type = false;
- new_parent->need_inum = false;
new_parent->p_cost = NeedsNothing;
- new_parent->arg_text = NULL;
switch (high_prec)
{
@@ -895,14 +892,8 @@ set_new_parent (struct predicate *curr, enum predicate_precedence high_prec, str
; /* empty */
}
- new_parent->side_effects = false;
- new_parent->no_default_print = false;
- new_parent->args.str = NULL;
- new_parent->pred_next = NULL;
-
/* Link in new_parent.
Pushes rest of left branch down 1 level to new_parent->pred_right. */
- new_parent->pred_left = NULL;
new_parent->pred_right = curr;
*prevp = new_parent;
@@ -1488,37 +1479,25 @@ get_new_pred (const struct parser_table *entry)
assert (entry->type != ARG_OPTION);
assert (entry->type != ARG_POSITIONAL_OPTION);
+ /* Allocate + initialize a new predicate. */
+ new_pred = xzalloc (sizeof (struct predicate));
if (predicates == NULL)
{
- predicates = (struct predicate *)
- xmalloc (sizeof (struct predicate));
- last_pred = predicates;
+ last_pred = predicates = new_pred;
}
else
{
- new_pred = xmalloc (sizeof (struct predicate));
last_pred->pred_next = new_pred;
last_pred = new_pred;
}
last_pred->parser_entry = entry;
- last_pred->pred_func = NULL;
- last_pred->p_name = NULL;
last_pred->p_type = NO_TYPE;
last_pred->p_prec = NO_PREC;
- last_pred->side_effects = false;
- last_pred->no_default_print = false;
last_pred->need_stat = true;
last_pred->need_type = true;
- last_pred->need_inum = false;
last_pred->p_cost = NeedsUnknown;
last_pred->arg_text = "ThisShouldBeSetToSomethingElse";
- last_pred->args.str = NULL;
- last_pred->args.scontext = NULL;
- last_pred->pred_next = NULL;
- last_pred->pred_left = NULL;
- last_pred->pred_right = NULL;
last_pred->literal_control_chars = options.literal_control_chars;
- last_pred->artificial = false;
last_pred->est_success_rate = 1.0;
init_pred_perf (last_pred);
return last_pred;
--
2.19.1

View File

@ -0,0 +1,32 @@
From bcd85897c2e55d955c325f72791d3ff99eacf820 Mon Sep 17 00:00:00 2001
From: James Youngman <jay@gnu.org>
Date: Wed, 30 Dec 2015 20:23:22 +0000
Subject: [PATCH 011/224] Remove the --enable-id-cache configure option.
* configure.ac: Remove the --enable-id-cache option. This option
became a no-op in findutils-4.5.15. Before that it did something
but the code was buggy. See https://savannah.gnu.org/bugs/?45062
for details.
* NEWS: State that this configure option is removed.
---
NEWS | 5 +++++
configure.ac | 3 ---
2 files changed, 5 insertions(+), 3 deletions(-)
diff --git a/configure.ac b/configure.ac
index 0b9ef281..bfc94f1c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -15,9 +15,6 @@ AC_SUBST(AUXDIR,$ac_aux_dir)
dnl check for --with-fts
FIND_WITH_FTS
-AC_ARG_ENABLE(id-cache,
-[ --enable-id-cache This currently has no effect.],)
-
AC_ARG_ENABLE(debug,
AS_HELP_STRING(--enable-debug,Enable debugging output which is likely to be interesting to people debugging findutils),
[ac_cv_debug=$enableval],[ac_cv_debug=no])
--
2.19.1

View File

@ -0,0 +1,30 @@
From bb51d3581d52890cd1c2b0e5ee919c00b0ba9eb5 Mon Sep 17 00:00:00 2001
From: James Youngman <jay@gnu.org>
Date: Thu, 5 Jul 2018 13:34:06 +0100
Subject: [PATCH 175/224] Shorten output of qmark_chars after replacing a
multibyte characer.
When qmark_chars() replaces a multibyte character with a single
character, this reduces the length of the string. When this happens,
terminate the now-shorter string at the new length.
This is simple workaround for bug http://savannah.gnu.org/bugs/?54236.
---
lib/printquoted.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/lib/printquoted.c b/lib/printquoted.c
index 5a31664b..14665c95 100644
--- a/lib/printquoted.c
+++ b/lib/printquoted.c
@@ -62,6 +62,7 @@ print_quoted (FILE *fp,
/* Replace any remaining funny characters with '?'. */
len = qmark_chars (buf, len);
+ buf[len] = 0;
rv = fprintf (fp, format, buf); /* Print the quoted version */
if (buf != smallbuf)
--
2.19.1

View File

@ -0,0 +1,217 @@
From e7b976a7e8b4023bd9ac2493341320f88aa9189c Mon Sep 17 00:00:00 2001
From: James Youngman <jay@gnu.org>
Date: Sat, 2 Jan 2016 13:04:24 +0000
Subject: [PATCH 023/224] find: Fix a number of compiler warnings (mostly
const-correctness).
* find/find.c (get_current_dirfd): remove unused function.
(process_dir): make parameters const: parent, pathname, name.
(process_path): make parameters const: parent, pathname, name.
(at_top): Modify the function pointer parameter accordingly.
* find/ftsfind.c (get_fts_info_name): Now returns const char*, not
char*.
(show_outstanding_execdirs): Fix type of loop variable to avoid
possible overflow.
(process_all_startpoints): Avoid compiler warning about overflow
of int loop variable.
* find/defs.h (struct predicate): Make p_name const.
(struct state): make rel_pathname const.
* find/exec.c (impl_pred_exec): Make prefix const.
(launch): Silence compiler warning about unused parameter argc.
* find/pred.c (blank_rtrim): Make str parameter const, since we do
not modify it.
* find/util.c (debug_option_assoc): name and docstring are now
const qualified.
(show_valid_debug_options): Avoid signed/unsigned comparison by
using a size_t array index.
(set_stat_placeholders): Avoid a compiler warning on systems
lacking birth time fields (and on which this function therefore
does nothing).
---
find/defs.h | 3 ++-
find/exec.c | 4 +++-
find/ftsfind.c | 6 ++++--
find/oldfind.c | 28 +++++++++++++---------------
find/util.c | 5 +++--
5 files changed, 25 insertions(+), 21 deletions(-)
diff --git a/find/defs.h b/find/defs.h
index a4647e83..981c5336 100644
--- a/find/defs.h
+++ b/find/defs.h
@@ -633,7 +633,8 @@ struct state
/* The file being operated on, relative to the current directory.
Used for stat, readlink, remove, and opendir. */
- char *rel_pathname;
+ const char *rel_pathname;
+
/* The directory fd to which rel_pathname is relative. This is relevant
* when we're navigating the hierarchy with fts() and using FTS_CWDFD.
*/
diff --git a/find/exec.c b/find/exec.c
index f8bd4389..8d20143f 100644
--- a/find/exec.c
+++ b/find/exec.c
@@ -114,7 +114,7 @@ impl_pred_exec (const char *pathname,
const char *target;
bool result;
const bool local = is_exec_in_local_dir (pred_ptr->pred_func);
- char *prefix;
+ const char *prefix;
size_t pfxlen;
(void) stat_buf;
@@ -292,6 +292,8 @@ launch (struct buildcmd_control *ctl, void *usercontext, int argc, char **argv)
static int first_time = 1;
struct exec_val *execp = usercontext;
+ (void) argc; /* silence compiler warning */
+
/* Make sure output of command doesn't get mixed with find output. */
fflush (stdout);
fflush (stderr);
diff --git a/find/ftsfind.c b/find/ftsfind.c
index cbb46de9..5128e574 100644
--- a/find/ftsfind.c
+++ b/find/ftsfind.c
@@ -152,7 +152,7 @@ static void init_mounted_dev_list (void);
#define STRINGIFY(X) #X
#define HANDLECASE(N) case N: return #N;
-static char *
+static const char *
get_fts_info_name (int info)
{
static char buf[10];
@@ -615,16 +615,18 @@ static bool
process_all_startpoints (int argc, char *argv[])
{
int i;
+ bool empty = true;
/* figure out how many start points there are */
for (i = 0; i < argc && !looks_like_expression (argv[i], true); i++)
{
+ empty = false;
state.starting_path_length = strlen (argv[i]); /* TODO: is this redundant? */
if (!find (argv[i]))
return false;
}
- if (i == 0)
+ if (empty)
{
/*
* We use a temporary variable here because some actions modify
diff --git a/find/oldfind.c b/find/oldfind.c
index 986e7b4c..cd235c06 100644
--- a/find/oldfind.c
+++ b/find/oldfind.c
@@ -95,11 +95,9 @@ enum
static void init_mounted_dev_list (int mandatory);
#endif
-static void process_top_path (char *pathname, mode_t mode, ino_t inum);
-static int process_path (char *pathname, char *name, bool leaf, char *parent, mode_t type, ino_t inum);
-static void process_dir (char *pathname, char *name, int pathlen, const struct stat *statp, char *parent);
-
-
+static void process_top_path (const char *pathname, mode_t mode, ino_t inum);
+static int process_path (const char *pathname, const char *name, bool leaf, const char *parent, mode_t type, ino_t inum);
+static void process_dir (const char *pathname, const char *name, int pathlen, const struct stat *statp, const char *parent);
/* A file descriptor open to the initial working directory.
Doing it this way allows us to work when the i.w.d. has
@@ -981,12 +979,12 @@ chdir_back (void)
* specified directory is a child of "." or is the root directory.
*/
static void
-at_top (char *pathname,
+at_top (const char *pathname,
mode_t mode,
ino_t inum,
struct stat *pstat,
- void (*action)(char *pathname,
- char *basename,
+ void (*action)(const char *pathname,
+ const char *basename,
int mode,
ino_t inum,
struct stat *pstat))
@@ -1056,8 +1054,8 @@ at_top (char *pathname,
}
-static void do_process_top_dir (char *pathname,
- char *base,
+static void do_process_top_dir (const char *pathname,
+ const char *base,
int mode,
ino_t inum,
struct stat *pstat)
@@ -1069,8 +1067,8 @@ static void do_process_top_dir (char *pathname,
}
static void
-do_process_predicate (char *pathname,
- char *base,
+do_process_predicate (const char *pathname,
+ const char *base,
int mode,
ino_t inum,
struct stat *pstat)
@@ -1095,7 +1093,7 @@ do_process_predicate (char *pathname,
and move to that.
*/
static void
-process_top_path (char *pathname, mode_t mode, ino_t inum)
+process_top_path (const char *pathname, mode_t mode, ino_t inum)
{
at_top (pathname, mode, inum, NULL, do_process_top_dir);
}
@@ -1181,7 +1179,7 @@ issue_loop_warning (const char *name, const char *pathname, int level)
Return nonzero iff PATHNAME is a directory. */
static int
-process_path (char *pathname, char *name, bool leaf, char *parent,
+process_path (const char *pathname, const char *name, bool leaf, const char *parent,
mode_t mode, ino_t inum)
{
struct stat stat_buf;
@@ -1307,7 +1305,7 @@ process_path (char *pathname, char *name, bool leaf, char *parent,
starting directory. */
static void
-process_dir (char *pathname, char *name, int pathlen, const struct stat *statp, char *parent)
+process_dir (const char *pathname, const char *name, int pathlen, const struct stat *statp, const char *parent)
{
int subdirs_left; /* Number of unexamined subdirs in PATHNAME. */
bool subdirs_unreliable; /* if true, cannot use dir link count as subdir limif (if false, it may STILL be unreliable) */
diff --git a/find/util.c b/find/util.c
index cf7965fc..1b4a07af 100644
--- a/find/util.c
+++ b/find/util.c
@@ -55,9 +55,9 @@
struct debug_option_assoc
{
- char *name;
+ const char *name;
int val;
- char *docstring;
+ const char *docstring;
};
static struct debug_option_assoc debugassoc[] =
{
@@ -176,6 +176,7 @@ usage (FILE *fp, int status, char *msg)
void
set_stat_placeholders (struct stat *p)
{
+ (void) p; /* silence warning for systems lacking these fields. */
#if HAVE_STRUCT_STAT_ST_BIRTHTIME
p->st_birthtime = 0;
#endif
--
2.19.1

View File

@ -0,0 +1,34 @@
From febde26dd0e66dda5d4060fa29b85443ddc6a865 Mon Sep 17 00:00:00 2001
From: Bernhard Voelker <mail@bernhard-voelker.de>
Date: Mon, 28 Aug 2017 23:15:12 +0200
Subject: [PATCH 117/224] find: avoid buffer-overflow with -printf '%T+'
* find/print.c (format_date): Increase size of local variable
FMT to match the longest possible content.
Fixes https://bugs.debian.org/873032 reported upstream by
Andreas Metzler in https://savannah.gnu.org/bugs/?51841;
fix proposed by Kamil Dudka.
Bug introduced in commit v4.6.0-111-g95816b2, so no released version
ever saw this; therefore not adding a NEWS entry.
---
find/print.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/find/print.c b/find/print.c
index 682197f4..6b568d9c 100644
--- a/find/print.c
+++ b/find/print.c
@@ -611,7 +611,7 @@ format_date (struct timespec ts, int kind)
char ns_buf[NS_BUF_LEN]; /* -.9999999990 (- sign can happen!)*/
int charsprinted, need_ns_suffix;
struct tm *tm;
- char fmt[6];
+ char fmt[12];
/* human_readable() assumes we pass a buffer which is at least as
* long as LONGEST_HUMAN_READABLE. We use an assertion here to
--
2.19.1

View File

@ -0,0 +1,33 @@
From 95816b29d46fb6b64754d4a66e7d918b3f134a1f Mon Sep 17 00:00:00 2001
From: James Youngman <jay@gnu.org>
Date: Sun, 23 Jul 2017 22:19:42 +0100
Subject: [PATCH 110/224] find: avoid strftime's non-portable %F specifier.
* find/print.c (format_date): Avoid passing %F to strftime since
some implementation lack it. Pass the synonymous %Y-%m-%d
instead. This fixes a bug manifesting on HP Tru64 UNIX V5.1B.
Reported by Steven M. Schweda <sms@antinode.info>.
---
find/print.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/find/print.c b/find/print.c
index db6155c9..682197f4 100644
--- a/find/print.c
+++ b/find/print.c
@@ -631,7 +631,11 @@ format_date (struct timespec ts, int kind)
/* Format the main part of the time. */
if (kind == '+')
{
- strcpy (fmt, "%F+%T");
+ /* Avoid %F, some Unix versions lack it. For example:
+ HP Tru64 UNIX V5.1B (Rev. 2650); Wed Feb 17 22:59:59 CST 2016
+ Also, some older HP-UX versions expand %F as the full month (like %B).
+ Reported by Steven M. Schweda <sms@antinode.info> */
+ strcpy (fmt, "%Y-%m-%d+%T");
need_ns_suffix = 1;
}
else
--
2.19.1

View File

@ -0,0 +1,43 @@
From 50a7c5d1f572d50d6c9d43d04e9c9fd55d66b466 Mon Sep 17 00:00:00 2001
From: Bernhard Voelker <mail@bernhard-voelker.de>
Date: Thu, 10 Aug 2017 08:45:56 +0200
Subject: [PATCH 113/224] find: avoid usage() in more error cases
When the user passes a bad command line, then find(1) outputs the
error message followed by a short usage() text, e.g. (wrapped):
$ find . -name a* b*
find: paths must precede expression: bfile
Usage: find [-H] [-L] [-P] [-Olevel] \
[-D help|tree|search|stat|rates|opt|exec] [path...] [expression]
Omit the usage() text in more cases like this in order to make the
error diagnostic more eye-catching.
* find/tree.c (build_expression_tree): Exit with EXIT_FAILURE
immediately in more cases, i.e., without outputting also a short
usage() text. While at it, add quotes around the offending argument
in one another place.
* NEWS (Improvements): Mention the fix.
Reported in https://savannah.gnu.org/bugs/?51711
---
NEWS | 3 +++
find/tree.c | 17 +++++------------
2 files changed, 8 insertions(+), 12 deletions(-)
diff --git a/find/tree.c b/find/tree.c
index 2bbfbe5a..ee466ea6 100644
--- a/find/tree.c
+++ b/find/tree.c
@@ -1281,10 +1281,7 @@
{
state.already_issued_stat_error_msg = false;
if (!looks_like_expression (argv[i], false))
- {
- error (0, 0, _("paths must precede expression: %s"), argv[i]);
- usage (stderr, 1, NULL);
- }
+ error (EXIT_FAILURE, 0, _("paths must precede expression: `%s'"), argv[i]);
predicate_name = argv[i];
parse_entry = find_parser (predicate_name);

View File

@ -0,0 +1,45 @@
From c1556892a639f609e6d63cd456c2062419e06459 Mon Sep 17 00:00:00 2001
From: Goffredo Baroncelli <kreijack@inwind.it>
Date: Fri, 27 Jan 2017 02:16:08 +0100
Subject: [PATCH 090/224] find: fix memory leak in mount list handling
The following gnulib commit added the structure member me_mntroot
which our free_file_system_list function didn't consider, thus leading
to a memory leak:
http://git.sv.gnu.org/cgit/gnulib.git/commit/?id=c6148bca89e9
* find/fstype.c (free_file_system_list): Use gnulib's free_mount_entry
function to free the mount list instead of free()ing all members here
manually.
* NEWS (Bug Fixes): Mention the fix.
Reported in
http://lists.gnu.org/archive/html/findutils-patches/2016-12/msg00000.html
---
NEWS | 3 +++
find/fstype.c | 9 +--------
2 files changed, 4 insertions(+), 8 deletions(-)
diff --git a/find/fstype.c b/find/fstype.c
index 535f9202..a0ac8bca 100644
--- a/find/fstype.c
+++ b/find/fstype.c
@@ -75,14 +75,7 @@ free_file_system_list (struct mount_entry *p)
while (p)
{
struct mount_entry *pnext = p->me_next;
-
- free (p->me_devname);
- free (p->me_mountdir);
-
- if (p->me_type_malloced)
- free (p->me_type);
- p->me_next = NULL;
- free (p);
+ free_mount_entry (p);
p = pnext;
}
}
--
2.19.1

View File

@ -0,0 +1,80 @@
From 7b7a19c95f236cd18f48e44b7cc6794d21c0369f Mon Sep 17 00:00:00 2001
From: Bernhard Voelker <mail@bernhard-voelker.de>
Date: Fri, 20 Jul 2018 10:07:13 +0200
Subject: [PATCH 181/224] find: fix -printf %Y output to 'N' for broken links
The format %Y shall output 'N' for broken links (ENOENT), 'L' for ELOOP,
and '?' for any other error when stat()ing the symlink target.
The %Y implementation implicitly fell back to lstat(); therefore it
output 'l' for dangling symlinks.
$ ln -s ENOENT DANGLE
$ find -D stat DANGLE -printf '%y %Y %p\n'
fallback_stat(): stat(DANGLE) failed; falling back on lstat()
l l DANGLE
* find/print.c (do_fprintf): For %Y, always follow links to determine
the type of the symlink target.
* find/testsuite/find.gnu/printf-symlink.exp: Add a test case for broken
links and the ELOOP case ...
* find/testsuite/find.gnu/printf-symlink.xo: ... with the expected output.
* NEWS (Bug fixes): Mention the fix.
Bug introduced in version v4.5.8 with commit '25e7c5fbf9'.
---
NEWS | 4 ++++
find/print.c | 9 +++++----
find/testsuite/find.gnu/printf-symlink.exp | 5 ++++-
find/testsuite/find.gnu/printf-symlink.xo | 4 ++++
4 files changed, 17 insertions(+), 5 deletions(-)
diff --git a/find/print.c b/find/print.c
index 3af3e91d..545df96a 100644
--- a/find/print.c
+++ b/find/print.c
@@ -1175,11 +1175,12 @@ do_fprintf (struct format_val *dest,
if (S_ISLNK (stat_buf->st_mode))
{
struct stat sbuf;
- /* If we would normally follow links, do not do so.
- * If we would normally not follow links, do so.
+ /* %Y needs to stat the symlink target regardless of
+ * whether we would normally follow symbolic links or not.
+ * (Actually we do not even come here when following_links()
+ * other than the ENOENT case.)
*/
- if ((following_links () ? optionp_stat : optionl_stat)
- (state.rel_pathname, &sbuf) != 0)
+ if (fstatat (state.cwd_dir_fd, state.rel_pathname, &sbuf, 0) != 0)
{
if ( errno == ENOENT )
{
diff --git a/find/testsuite/find.gnu/printf-symlink.exp b/find/testsuite/find.gnu/printf-symlink.exp
index 6acc3e68..453f07fc 100644
--- a/find/testsuite/find.gnu/printf-symlink.exp
+++ b/find/testsuite/find.gnu/printf-symlink.exp
@@ -2,5 +2,8 @@ exec rm -rf tmp
exec mkdir tmp
exec touch tmp/file
exec ln -s file tmp/LINK
-find_start p {tmp/LINK -printf "RESULT: %y %Y %p\n" -printf "RESULT2: %Y %y %p\n" }
+exec ln -s ENOENT tmp/DANGLE
+exec ln -s SELF tmp/SELF
+exec ls -ls tmp
+find_start p {tmp/LINK tmp/DANGLE tmp/SELF -printf "RESULT: %y %Y %p\n" -printf "RESULT2: %Y %y %p\n" }
exec rm -rf tmp
diff --git a/find/testsuite/find.gnu/printf-symlink.xo b/find/testsuite/find.gnu/printf-symlink.xo
index cc2b69c4..08eb83c6 100644
--- a/find/testsuite/find.gnu/printf-symlink.xo
+++ b/find/testsuite/find.gnu/printf-symlink.xo
@@ -1,2 +1,6 @@
RESULT: l f tmp/LINK
RESULT2: f l tmp/LINK
+RESULT: l N tmp/DANGLE
+RESULT2: N l tmp/DANGLE
+RESULT: l L tmp/SELF
+RESULT2: L l tmp/SELF
--
2.19.1

View File

@ -0,0 +1,250 @@
From 2a6129bfccec9f23a50f037e187f85c4d000bc87 Mon Sep 17 00:00:00 2001
From: Bernhard Voelker <mail@bernhard-voelker.de>
Date: Mon, 20 Feb 2017 18:53:48 +0100
Subject: [PATCH 098/224] find: fix -printf '%h' for arguments with one or more
trailing slashes
Previously, find would output the pathname name for the '%h' format
when that was passed with a trailing slash:
$ mkdir foo
$ find foo/ -printf '%h/%f\n'
foo/foo/
* find/print.c (do_fprintf -> 'h'): Strip trailing slashes, i.e. any
number of directory separators, unless this is the root "/" directory.
* find/testsuite/find.gnu/printf-h.exp: Enhance test with various
combinations of "/", "./", "foo/", "./foo", "./foolink/", etc.
* find/testsuite/find.gnu/printf-h.xo: Add the expected output for the
above new test cases.
* NEWS: Mention the fix.
Bug introduced in commit FINDUTILS_4_2_18-1-6-g0fd15a4.
Reported by Tavian Barnes <tavianator@gmail.com> in
https://savannah.gnu.org/bugs/?50259
---
NEWS | 8 ++-
find/print.c | 21 +++++--
find/testsuite/find.gnu/printf-h.exp | 94 ++++++++++++++++++++++++++--
find/testsuite/find.gnu/printf-h.xo | 70 ++++++++++++++++++++-
4 files changed, 181 insertions(+), 12 deletions(-)
diff --git a/find/print.c b/find/print.c
index 20351572..db6155c9 100644
--- a/find/print.c
+++ b/find/print.c
@@ -965,8 +965,18 @@ do_fprintf (struct format_val *dest,
case 'h': /* leading directories part of path */
/* sanitised */
{
- cp = strrchr (pathname, '/');
- if (cp == NULL) /* No leading directories. */
+ char *pname = strdup (pathname);
+
+ /* Remove trailing slashes - unless it's the root '/' directory. */
+ char *s = pname + strlen (pname) -1;
+ for ( ; pname <= s; s--)
+ if (*s != '/')
+ break;
+ if (pname < s && *(s+1) == '/')
+ *(s+1) = '\0';
+
+ s = strrchr (pname, '/');
+ if (s == NULL) /* No leading directories. */
{
/* If there is no slash in the pathname, we still
* print the string because it contains characters
@@ -976,11 +986,10 @@ do_fprintf (struct format_val *dest,
}
else
{
- char *s = strdup (pathname);
- s[cp - pathname] = 0;
- checked_print_quoted (dest, segment->text, s);
- free (s);
+ *s = '\0';
+ checked_print_quoted (dest, segment->text, pname);
}
+ free (pname);
}
break;
diff --git a/find/testsuite/find.gnu/printf-h.exp b/find/testsuite/find.gnu/printf-h.exp
index fb0187cc..094a37b5 100644
--- a/find/testsuite/find.gnu/printf-h.exp
+++ b/find/testsuite/find.gnu/printf-h.exp
@@ -1,5 +1,91 @@
# Test case for Savannah bug ID #12085.
-exec rm -rf tmp
-exec touch tmp
-find_start p {tmp -printf "RESULT: %h %f\n" }
-exec rm -rf tmp
+exec rm -rf foo
+exec mkdir foo foo/bar
+exec ln -s foo foolink
+#
+# Create the combinations with:
+# $ printf '%s \\\n' {,./,.//}{/,.,foo,foolink,foo/bar}{,/,//,/.,//.} | sort -u
+#
+# Manual check against installed version:
+# $ for opt in '' -H -L -P ; do
+# printf "\n=== Differences for option: '%s' ===\n" "$opt"
+# diff -u0 \
+# <( /usr/bin/find $opt {,./,.//}{/,.,foo,foolink,foo/bar}{,/,//,/.,//.} \
+# -maxdepth 1 -printf "%h/%f,%%p=%p,%%h='%h',%%f='%f'\n" ) \
+# <( ./find $opt {,./,.//}{/,.,foo,foolink,foo/bar}{,/,//,/.,//.} \
+# -maxdepth 1 -printf "%h/%f,%%p=%p,%%h='%h',%%f='%f'\n" )
+# done | column -t -s,
+
+find_start p {\
+/ \
+// \
+/// \
+///. \
+//. \
+. \
+./ \
+.// \
+./// \
+.//// \
+.///// \
+./////. \
+.////. \
+.///. \
+.//. \
+.//./ \
+.//.// \
+.//.//. \
+.//./. \
+./. \
+././ \
+./.// \
+././/. \
+././. \
+.//foo \
+.//foo/ \
+.//foo// \
+.//foo//. \
+.//foo/. \
+./foo \
+./foo/ \
+./foo// \
+./foo//. \
+./foo/. \
+foo \
+foo/ \
+foo// \
+foo//. \
+foo/. \
+.//foo/bar \
+.//foo/bar/ \
+.//foo/bar// \
+.//foo/bar//. \
+.//foo/bar/. \
+./foo/bar \
+./foo/bar/ \
+./foo/bar// \
+./foo/bar//. \
+./foo/bar/. \
+foo/bar \
+foo/bar/ \
+foo/bar// \
+foo/bar//. \
+foo/bar/. \
+.//foolink \
+.//foolink/ \
+.//foolink// \
+.//foolink//. \
+.//foolink/. \
+./foolink \
+./foolink/ \
+./foolink// \
+./foolink//. \
+./foolink/. \
+foolink \
+foolink/ \
+foolink// \
+foolink//. \
+foolink/. \
+-maxdepth 0 -printf "%p,%h,%f\n" }
+
+exec rm -rf foo foolink
diff --git a/find/testsuite/find.gnu/printf-h.xo b/find/testsuite/find.gnu/printf-h.xo
index dc6ce01e..0ed6ad9d 100644
--- a/find/testsuite/find.gnu/printf-h.xo
+++ b/find/testsuite/find.gnu/printf-h.xo
@@ -1 +1,69 @@
-RESULT: . tmp
+/,,/
+//,/,/
+///,//,/
+///.,//,.
+//.,/,.
+.,.,.
+./,.,./
+.//,./,./
+.///,.//,./
+.////,.///,./
+./////,.////,./
+./////.,.////,.
+.////.,.///,.
+.///.,.//,.
+.//.,./,.
+.//./,./,./
+.//.//,./,./
+.//.//.,.//./,.
+.//./.,.//.,.
+./.,.,.
+././,.,./
+././/,.,./
+././/.,././,.
+././.,./.,.
+.//foo/bar,.//foo,bar
+.//foo/bar/,.//foo,bar/
+.//foo/bar//,.//foo,bar/
+.//foo/bar//.,.//foo/bar/,.
+.//foo/bar/.,.//foo/bar,.
+./foo/bar,./foo,bar
+./foo/bar/,./foo,bar/
+./foo/bar//,./foo,bar/
+./foo/bar//.,./foo/bar/,.
+./foo/bar/.,./foo/bar,.
+foo/bar,foo,bar
+foo/bar/,foo,bar/
+foo/bar//,foo,bar/
+foo/bar//.,foo/bar/,.
+foo/bar/.,foo/bar,.
+.//foo,./,foo
+.//foo/,./,foo/
+.//foo//,./,foo/
+.//foo//.,.//foo/,.
+.//foo/.,.//foo,.
+./foo,.,foo
+./foo/,.,foo/
+./foo//,.,foo/
+./foo//.,./foo/,.
+./foo/.,./foo,.
+foo,.,foo
+foo/,.,foo/
+foo//,.,foo/
+foo//.,foo/,.
+foo/.,foo,.
+.//foolink,./,foolink
+.//foolink/,./,foolink/
+.//foolink//,./,foolink/
+.//foolink//.,.//foolink/,.
+.//foolink/.,.//foolink,.
+./foolink,.,foolink
+./foolink/,.,foolink/
+./foolink//,.,foolink/
+./foolink//.,./foolink/,.
+./foolink/.,./foolink,.
+foolink,.,foolink
+foolink/,.,foolink/
+foolink//,.,foolink/
+foolink//.,foolink/,.
+foolink/.,foolink,.
--
2.19.1

View File

@ -0,0 +1,47 @@
From 9530e31f6d4febf8ff08f931f70b40d41603ef8d Mon Sep 17 00:00:00 2001
From: Assaf Gordon <assafgordon@gmail.com>
Date: Wed, 16 Aug 2017 14:09:17 -0600
Subject: [PATCH 114/224] find: give helpful hint for unquoted patterns errors
Try to detect cases where the user provided an unquoted shell-glob
pattern (which was expanded by the shell before calling find(1),
resulting in an invalid usage).
$ touch a.txt b.txt c.txt
$ find -name *.txt
find: paths must precede expression: `b.txt'
find: possible unquoted pattern after predicate `-name'?
Continuation of
https://savannah.gnu.org/bugs/?51711
https://lists.gnu.org/archive/html/bug-findutils/2017-08/msg00000.html
https://git.sv.gnu.org/cgit/findutils.git/commit/?id=50a7c5d1f572
* find/tree.c (build_expression_tree): If the offending argument is an
existing file, print a hint with the last (valid) predicate.
---
find/tree.c | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/find/tree.c b/find/tree.c
index ee466ea6..cc7772d2 100644
--- a/find/tree.c
+++ b/find/tree.c
@@ -1275,7 +1275,13 @@ build_expression_tree (int argc, char *argv[], int end_of_leading_options)
{
state.already_issued_stat_error_msg = false;
if (!looks_like_expression (argv[i], false))
- error (EXIT_FAILURE, 0, _("paths must precede expression: `%s'"), argv[i]);
+ {
+ error (0, 0, _("paths must precede expression: `%s'"), argv[i]);
+ if (access(argv[i], F_OK)==0)
+ error (0, 0, _("possible unquoted pattern after predicate `%s'?"),
+ last_pred->p_name);
+ exit (EXIT_FAILURE);
+ }
predicate_name = argv[i];
parse_entry = find_parser (predicate_name);
--
2.19.1

View File

@ -0,0 +1,89 @@
From 7a6e548690b116878070665bd9844275823bb730 Mon Sep 17 00:00:00 2001
From: Bernhard Voelker <mail@bernhard-voelker.de>
Date: Wed, 2 Nov 2016 07:32:01 +0100
Subject: [PATCH 080/224] find: handle more readdir(3) errors
Similar to the FTS readdir fix in v4.6.0-72-g155c9d1, handle the last
two unhandled readdir(3) errors.
* find/pred.c (pred_empty): Do the above.
* lib/fdleak.c (get_proc_max_fd): Likewise. While at it, fix the
condition to only skip "." and ".."; previously, also other files
beginning with ".." would have been skipped - that was theoretically,
as we only expect the FD files in "/proc/self/fd".
---
find/pred.c | 10 ++++++++++
lib/fdleak.c | 21 +++++++++++++++++----
2 files changed, 27 insertions(+), 4 deletions(-)
diff --git a/find/pred.c b/find/pred.c
index f7e9b59c..c064606d 100644
--- a/find/pred.c
+++ b/find/pred.c
@@ -380,6 +380,9 @@ pred_empty (const char *pathname, struct stat *stat_buf, struct predicate *pred_
state.exit_status = 1;
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] != '.'
@@ -390,6 +393,13 @@ pred_empty (const char *pathname, struct stat *stat_buf, struct predicate *pred_
break;
}
}
+ if (errno)
+ {
+ /* Handle errors from readdir(3). */
+ error (0, errno, "%s", safely_quote_err_filename (0, pathname));
+ state.exit_status = 1;
+ return false;
+ }
if (CLOSEDIR (d))
{
error (0, errno, "%s", safely_quote_err_filename (0, pathname));
diff --git a/lib/fdleak.c b/lib/fdleak.c
index 5dc4cb1e..cf19fa26 100644
--- a/lib/fdleak.c
+++ b/lib/fdleak.c
@@ -19,6 +19,7 @@
/* system headers. */
#include <assert.h>
+#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <poll.h>
@@ -77,11 +78,23 @@ get_proc_max_fd (void)
int good = 0;
struct dirent *dent;
- while ((dent=readdir (dir)) != NULL)
- {
+ 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;
+ }
+
if (dent->d_name[0] != '.'
- || (dent->d_name[0] != 0
- && dent->d_name[1] != 0 && dent->d_name[1] != '.'))
+ || (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)
--
2.19.1

View File

@ -0,0 +1,73 @@
From 66174c10c617a1a50fa804c1e2f9c6becd7c90f8 Mon Sep 17 00:00:00 2001
From: Bernhard Voelker <mail@bernhard-voelker.de>
Date: Wed, 26 Dec 2018 10:47:11 +0100
Subject: [PATCH 207/224] find: improve warning diagnostic for the -name/-iname
with '/' in pattern
* find/parser.c (check_name_arg): Add parameter ALT for the alternative
option to suggest. Avoid confusing quoting in the warning by making
the message more terse.
(parse_iname): Pass "-iwholename" as alternative parameter.
(parse_name): Pass "-wholename" as alternative parameter.
Reported by Andreas Metzler in
https://sv.gnu.org/bugs/?55272
---
find/parser.c | 24 +++++++++++-------------
1 file changed, 11 insertions(+), 13 deletions(-)
diff --git a/find/parser.c b/find/parser.c
index ae456ddb..a3b9e762 100644
--- a/find/parser.c
+++ b/find/parser.c
@@ -1257,20 +1257,18 @@ fnmatch_sanitycheck (void)
static bool
-check_name_arg (const char *pred, const char *arg)
+check_name_arg (const char *pred, const char *alt, const char *arg)
{
if (should_issue_warnings () && strchr (arg, '/'))
{
- error (0, 0,_("warning: Unix filenames usually don't contain slashes "
- "(though pathnames do). That means that '%s %s' will "
- "probably evaluate to false all the time on this system. "
- "You might find the '-wholename' test more useful, or "
- "perhaps '-samefile'. Alternatively, if you are using "
- "GNU grep, you could "
- "use 'find ... -print0 | grep -FzZ %s'."),
- pred,
- safely_quote_err_filename (0, arg),
- safely_quote_err_filename (1, arg));
+ error (0, 0,
+ _("warning: %s matches against basenames only, "
+ "but the given pattern contains a directory separator (%s), "
+ "thus the expression will evaluate to false all the time. "
+ "Did you mean %s?"),
+ safely_quote_err_filename (0, pred),
+ safely_quote_err_filename (1, "/"),
+ safely_quote_err_filename (2, alt));
}
return true; /* allow it anyway */
}
@@ -1284,7 +1282,7 @@ parse_iname (const struct parser_table* entry, char **argv, int *arg_ptr)
fnmatch_sanitycheck ();
if (collect_arg (argv, arg_ptr, &name))
{
- if (check_name_arg ("-iname", name))
+ if (check_name_arg ("-iname", "-iwholename", name))
{
struct predicate *our_pred = insert_primary (entry, name);
our_pred->need_stat = our_pred->need_type = false;
@@ -1471,7 +1469,7 @@ parse_name (const struct parser_table* entry, char **argv, int *arg_ptr)
if (collect_arg (argv, arg_ptr, &name))
{
fnmatch_sanitycheck ();
- if (check_name_arg ("-name", name))
+ if (check_name_arg ("-name", "-wholename", name))
{
struct predicate *our_pred = insert_primary (entry, name);
our_pred->need_stat = our_pred->need_type = false;
--
2.19.1

View File

@ -0,0 +1,89 @@
From 0afb2efada7e435ae18ef7d3db0758464189f44f Mon Sep 17 00:00:00 2001
From: Bernhard Voelker <mail@bernhard-voelker.de>
Date: Tue, 30 Jan 2018 23:30:09 +0100
Subject: [PATCH 159/224] find: make -delete honour the -ignore_readdir_race
option
* find/pred.c (pred_delete): Return true when the -ignore_readdir_race
option is active and unlinkat() came back with ENOENT.
* doc/find.texi (Option -ignore_readdir_race): Document the change.
(Action -delete): Likewise.
* find/find.1: Likewise.
* NEWS (Bug Fixes): Mention the fix.
For now, it seems a bit hard to add a proper test for this,
so the following shell snippet demonstrates the race:
$ seq 10 | xargs touch
$ env time -f 'find exit status: %x\nfind time: %e' \
find -ignore_readdir_race -type f \
-delete \
-exec sh -c 'sleep $(basename {})' \; \
-printf 'find deleted: %p\n' \
& \
sleep 20; \
seq 10 | xargs rm -fv; \
wait $!
Reported by Alexander Golubev in
https://savannah.gnu.org/bugs/?52981
---
NEWS | 4 ++++
doc/find.texi | 15 ++++++++++++++-
find/find.1 | 22 ++++++++++++++++++++++
find/pred.c | 6 ++++++
4 files changed, 46 insertions(+), 1 deletion(-)
diff --git a/doc/find.texi b/doc/find.texi
index 3580be75..0089193e 100644
--- a/doc/find.texi
+++ b/doc/find.texi
@@ -1424,7 +1424,15 @@ gives a significant increase in search speed.
If a file disappears after its name has been read from a directory but
before @code{find} gets around to examining the file with @code{stat},
don't issue an error message. If you don't specify this option, an
-error message will be issued. This option can be useful in system
+error message will be issued.
+
+Furthermore, @code{find} with the @samp{-ignore_readdir_race} option
+will ignore errors of the @samp{-delete} action in the case the file
+has disappeared since the parent directory was read: it will not output
+an error diagnostic, and the return code of the @samp{-delete} action
+will be true.
+
+This option can be useful in system
scripts (cron scripts, for example) that examine areas of the
filesystem that change frequently (mail queues, temporary directories,
and so forth), because this scenario is common for those sorts of
@@ -2787,6 +2795,11 @@ explicitly.
If @samp{-delete} fails, @code{find}'s exit status will be nonzero
(when it eventually exits).
+
+Together with the @samp{-ignore_readdir_race} option, @code{find} will
+ignore errors of the @samp{-delete} action in the case the file has disappeared
+since the parent directory was read: it will not output an error diagnostic, and
+the return code of the @samp{-delete} action will be true.
@end deffn
@node Adding Tests
diff --git a/find/pred.c b/find/pred.c
index 7e2a7bde..af3bacbc 100644
--- a/find/pred.c
+++ b/find/pred.c
@@ -316,6 +316,12 @@ pred_delete (const char *pathname, struct stat *stat_buf, struct predicate *pred
}
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)
--
2.19.1

View File

@ -0,0 +1,58 @@
From 235f21673cd8e3458795cdadca6e78a3423ab024 Mon Sep 17 00:00:00 2001
From: Bernhard Voelker <mail@bernhard-voelker.de>
Date: Sat, 9 Feb 2019 15:57:19 +0100
Subject: [PATCH 224/224] find: make pred_empty safer and avoid fd leaks
There is a small race condition between the previous stat call
and openat/fdopendir (which cannot be avoided): if the directory
got replaced by another file type, then openat would succeed but the
subsequent fdopendir would fail with ENOTDIR. Detect this earlier
by passing the O_DIRECTORY flag.
Furthermore, the opened file descriptor was leaked in that case
(bug introduced in FINDUTILS_4_3_2-1-80-gb46b0d89 in 2007).
Later on, after a readdir error, also the directory stream was leaked
(bug introduced by myself in commit 7a6e548690b1).
* find/pred.c (pred_empty): Add more flags to the openat call,
especially O_DIRECTORY; inspired by gnulib's opendirat module.
Close the file descriptor when fdopendir failed.
Close the directory stream when readdir failed.
---
find/pred.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/find/pred.c b/find/pred.c
index e34a41dc..688103d6 100644
--- a/find/pred.c
+++ b/find/pred.c
@@ -363,9 +363,9 @@ 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
- )) < 0)
+ | O_CLOEXEC | O_DIRECTORY | O_NOCTTY | O_NONBLOCK)) < 0)
{
error (0, errno, "%s", safely_quote_err_filename (0, pathname));
state.exit_status = 1;
@@ -376,6 +376,7 @@ pred_empty (const char *pathname, struct stat *stat_buf, struct predicate *pred_
{
error (0, errno, "%s", safely_quote_err_filename (0, pathname));
state.exit_status = 1;
+ close (fd);
return false;
}
/* errno is not touched in the loop body, so initializing it here
@@ -396,6 +397,7 @@ pred_empty (const char *pathname, struct stat *stat_buf, struct predicate *pred_
/* Handle errors from readdir(3). */
error (0, errno, "%s", safely_quote_err_filename (0, pathname));
state.exit_status = 1;
+ CLOSEDIR (d);
return false;
}
if (CLOSEDIR (d))
--
2.19.1

View File

@ -0,0 +1,74 @@
From ba6be2889642010c8f30affe403981aa2cc39631 Mon Sep 17 00:00:00 2001
From: Bernhard Voelker <mail@bernhard-voelker.de>
Date: Tue, 24 Jul 2018 08:34:38 +0200
Subject: [PATCH 184/224] find -printf %Y: handle ENOTDIR also as broken
symlink
The above command should output 'N' (for broken symlinks) not only in
the ENOENT case, but also when an intermediate part of the symlink target
file name is a file (ENOTDIR):
$ touch file
$ ln -s file/ENOTDIR link
$ find link -printf '%Y %p\n'
N link
Previously, find output 'l' as for a resolvable symlink.
* find/print.c (do_fprintf): Treat ENOTDIR the same as ENOENT to detect
broken symlinks.
* find/testsuite/find.gnu/printf-symlink.exp: Extend the test, and ...
* find/testsuite/find.gnu/printf-symlink.xo: ... the expected output.
* NEWS (Bug fixes, #54262): Explicitly mention that both ENOENT and ENOTDIR
are used to detect broken symlinks.
Suggested by Tavian Barnes.
---
NEWS | 4 ++--
find/print.c | 2 +-
find/testsuite/find.gnu/printf-symlink.exp | 3 ++-
find/testsuite/find.gnu/printf-symlink.xo | 2 ++
4 files changed, 7 insertions(+), 4 deletions(-)
diff --git a/find/print.c b/find/print.c
index 24bd9692..1bfccbfc 100644
--- a/find/print.c
+++ b/find/print.c
@@ -1182,7 +1182,7 @@ do_fprintf (struct format_val *dest,
*/
if (fstatat (state.cwd_dir_fd, state.rel_pathname, &sbuf, 0) != 0)
{
- if ( errno == ENOENT )
+ if ( (errno == ENOENT) || (errno == ENOTDIR) )
{
checked_fprintf (dest, segment->text, "N");
break;
diff --git a/find/testsuite/find.gnu/printf-symlink.exp b/find/testsuite/find.gnu/printf-symlink.exp
index 453f07fc..077f18b5 100644
--- a/find/testsuite/find.gnu/printf-symlink.exp
+++ b/find/testsuite/find.gnu/printf-symlink.exp
@@ -3,7 +3,8 @@ exec mkdir tmp
exec touch tmp/file
exec ln -s file tmp/LINK
exec ln -s ENOENT tmp/DANGLE
+exec ln -s file/ENOTDIR tmp/ENOTDIR
exec ln -s SELF tmp/SELF
exec ls -ls tmp
-find_start p {tmp/LINK tmp/DANGLE tmp/SELF -printf "RESULT: %y %Y %p\n" -printf "RESULT2: %Y %y %p\n" }
+find_start p {tmp/LINK tmp/DANGLE tmp/ENOTDIR tmp/SELF -printf "RESULT: %y %Y %p\n" -printf "RESULT2: %Y %y %p\n" }
exec rm -rf tmp
diff --git a/find/testsuite/find.gnu/printf-symlink.xo b/find/testsuite/find.gnu/printf-symlink.xo
index 08eb83c6..978c6673 100644
--- a/find/testsuite/find.gnu/printf-symlink.xo
+++ b/find/testsuite/find.gnu/printf-symlink.xo
@@ -2,5 +2,7 @@ RESULT: l f tmp/LINK
RESULT2: f l tmp/LINK
RESULT: l N tmp/DANGLE
RESULT2: N l tmp/DANGLE
+RESULT: l N tmp/ENOTDIR
+RESULT2: N l tmp/ENOTDIR
RESULT: l L tmp/SELF
RESULT2: L l tmp/SELF
--
2.19.1

View File

@ -0,0 +1,49 @@
From 22ff99e150faa82980361e577cff643cc17e7fac Mon Sep 17 00:00:00 2001
From: Bernhard Voelker <mail@bernhard-voelker.de>
Date: Sun, 8 Jul 2018 00:17:27 +0200
Subject: [PATCH 176/224] find: process unreadable directories with -depth
* find/ftsfind.c (consider_visiting): Split the FTS_ERR and FTS_DNR
cases to be able to continue processing that entry in the latter case
(unreadable directory) when the -depth option is given.
* NEWS (Bug Fixes): Mention the fix.
Reported by Tavian Barnes in https://savannah.gnu.org/bugs/?54171.
---
NEWS | 4 ++++
find/ftsfind.c | 15 +++++++++++++--
2 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/find/ftsfind.c b/find/ftsfind.c
index 0e2aca33..607ea8d3 100644
--- a/find/ftsfind.c
+++ b/find/ftsfind.c
@@ -342,12 +342,23 @@ consider_visiting (FTS *p, FTSENT *ent)
statbuf.st_ino = ent->fts_statp->st_ino;
/* Cope with various error conditions. */
- if (ent->fts_info == FTS_ERR
- || ent->fts_info == FTS_DNR)
+ if (ent->fts_info == FTS_ERR)
{
nonfatal_target_file_error (ent->fts_errno, ent->fts_path);
return;
}
+ if (ent->fts_info == FTS_DNR)
+ {
+ 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;
+ }
+ }
else if (ent->fts_info == FTS_DC)
{
issue_loop_warning (ent);
--
2.19.1

View File

@ -0,0 +1,132 @@
From 17e470dc1acca4824b70328d733d5f99c12d0d65 Mon Sep 17 00:00:00 2001
From: Kamil Dudka <kdudka@redhat.com>
Date: Wed, 11 May 2011 16:46:45 +0200
Subject: [PATCH 3/4] findutils-4.4.2-xautofs.patch
---
doc/find.texi | 4 ++++
find/defs.h | 3 +++
find/find.1 | 3 +++
find/ftsfind.c | 6 ++++++
find/parser.c | 11 ++++++++++-
find/util.c | 1 +
6 files changed, 27 insertions(+), 1 deletions(-)
diff --git a/doc/find.texi b/doc/find.texi
index c584298..9731b71 100644
--- a/doc/find.texi
+++ b/doc/find.texi
@@ -1446,6 +1446,10 @@ them.
There are two ways to avoid searching certain filesystems. One way is
to tell @code{find} to only search one filesystem:
+@deffn Option -xautofs
+Don't descend directories on autofs filesystems.
+@end deffn
+
@deffn Option -xdev
@deffnx Option -mount
Don't descend directories on other filesystems. These options are
diff --git a/find/defs.h b/find/defs.h
index 11d1d00..f95ce72 100644
--- a/find/defs.h
+++ b/find/defs.h
@@ -557,6 +557,9 @@ struct options
/* If true, don't cross filesystem boundaries. */
bool stay_on_filesystem;
+ /* If true, don't descend directories on autofs filesystems. */
+ bool bypass_autofs;
+
/* 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.
*/
diff --git a/find/find.1 b/find/find.1
index e851f82..a4799ff 100644
--- a/find/find.1
+++ b/find/find.1
@@ -520,6 +520,9 @@ to stat them; this gives a significant increase in search speed.
.IP "\-version, \-\-version"
Print the \fBfind\fR version number and exit.
+.IP \-xautofs
+Don't descend directories on autofs filesystems.
+
.IP \-xdev
Don't descend directories on other filesystems.
diff --git a/find/ftsfind.c b/find/ftsfind.c
index 9fdb8ef..bd7cc37 100644
--- a/find/ftsfind.c
+++ b/find/ftsfind.c
@@ -485,6 +485,12 @@ consider_visiting (FTS *p, FTSENT *ent)
}
}
+ if (options.bypass_autofs &&
+ 0 == strcmp ("autofs", filesystem_type (&statbuf, ent->fts_name)))
+ {
+ fts_set(p, ent, FTS_SKIP); /* descend no further */
+ }
+
if ( (ent->fts_info == FTS_D) && !options.do_dir_first )
{
/* this is the preorder visit, but user said -depth */
diff --git a/find/parser.c b/find/parser.c
index 52a1ef6..995aec3 100644
--- a/find/parser.c
+++ b/find/parser.c
@@ -146,6 +146,7 @@ static bool parse_user (const struct parser_table*, char *argv[], int *
static bool parse_version (const struct parser_table*, char *argv[], int *arg_ptr);
static bool parse_wholename (const struct parser_table*, char *argv[], int *arg_ptr);
static bool parse_xdev (const struct parser_table*, char *argv[], int *arg_ptr);
+static bool parse_xautofs (const struct parser_table*, char *argv[], int *arg_ptr);
static bool parse_ignore_race (const struct parser_table*, char *argv[], int *arg_ptr);
static bool parse_noignore_race (const struct parser_table*, char *argv[], int *arg_ptr);
static bool parse_warn (const struct parser_table*, char *argv[], int *arg_ptr);
@@ -306,6 +307,7 @@ static struct parser_table const parse_table[] =
PARSE_TEST_NP ("wholename", wholename), /* GNU, replaced -path, but anyway -path will soon be in POSIX */
{ARG_TEST, "writable", parse_accesscheck, pred_writable}, /* GNU, 4.3.0+ */
PARSE_OPTION ("xdev", xdev), /* POSIX */
+ PARSE_OPTION ("xautofs", xautofs),
PARSE_TEST ("xtype", xtype), /* GNU */
#ifdef UNIMPLEMENTED_UNIX
/* It's pretty ugly for find to know about archive formats.
@@ -1239,7 +1241,7 @@ operators (decreasing precedence; -and is implicit where no others are given):\n
positional options (always true): -daystart -follow -regextype\n\n\
normal options (always true, specified before other expressions):\n\
-depth --help -maxdepth LEVELS -mindepth LEVELS -mount -noleaf\n\
- --version -xdev -ignore_readdir_race -noignore_readdir_race\n"));
+ --version -xautofs -xdev -ignore_readdir_race -noignore_readdir_race\n"));
puts (_("\
tests (N can be +N or -N or N): -amin N -anewer FILE -atime N -cmin N\n\
-cnewer FILE -ctime N -empty -false -fstype TYPE -gid N -group NAME\n\
@@ -2683,6 +2685,13 @@ parse_xdev (const struct parser_table* entry, char **argv, int *arg_ptr)
}
static bool
+parse_xautofs (const struct parser_table* entry, char **argv, int *arg_ptr)
+{
+ options.bypass_autofs = true;
+ return parse_noop (entry, argv, arg_ptr);
+}
+
+static bool
parse_ignore_race (const struct parser_table* entry, char **argv, int *arg_ptr)
{
options.ignore_readdir_race = true;
diff --git a/find/util.c b/find/util.c
index 8577396..4d45f84 100644
--- a/find/util.c
+++ b/find/util.c
@@ -1017,6 +1017,7 @@ set_option_defaults (struct options *p)
p->full_days = false;
p->stay_on_filesystem = false;
+ p->bypass_autofs = false;
p->ignore_readdir_race = false;
if (p->posixly_correct)
--
1.7.4.4

View File

@ -0,0 +1,53 @@
From 690d4bd9f29a805999a3ce4651dac9585ccc9917 Mon Sep 17 00:00:00 2001
From: Kamil Dudka <kdudka@redhat.com>
Date: Wed, 11 May 2011 16:46:57 +0200
Subject: [PATCH 1/2] findutils-4.5.7-warnings.patch
---
xargs/xargs.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/xargs/xargs.c b/xargs/xargs.c
index 5e373f2..c0a8676 100644
--- a/xargs/xargs.c
+++ b/xargs/xargs.c
@@ -1289,7 +1289,8 @@ xargs_do_exec (struct buildcmd_control *ctl, void *usercontext, int argc, char *
* utility if we run it, for POSIX compliance on the
* handling of exit values.
*/
- write (fd[1], &errno, sizeof (int));
+ int sink = write (fd[1], &errno, sizeof (int));
+ (void) sink;
}
close (fd[1]);
--
1.7.1
From c5654b9ca5f50daa1ca406ebd7b4546f24d00db6 Mon Sep 17 00:00:00 2001
From: Kamil Dudka <kdudka@redhat.com>
Date: Mon, 23 Sep 2013 15:04:03 +0200
Subject: [PATCH 2/2] parser: silence a [-Wmaybe-uninitialized] GCC warning
... caused by a missing model of error()
---
find/parser.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/find/parser.c b/find/parser.c
index 89d8bcf..8c399d7 100644
--- a/find/parser.c
+++ b/find/parser.c
@@ -2723,7 +2723,7 @@ insert_type (char **argv, int *arg_ptr,
const struct parser_table *entry,
PRED_FUNC which_pred)
{
- mode_t type_cell;
+ mode_t type_cell /* to silence GCC warning */ = 0;
struct predicate *our_pred;
float rate = 0.5;
const char *typeletter;
--
1.9.3

View File

@ -0,0 +1,185 @@
From 3e5e311d23ac0a5bd5930ddb4094f7555b886329 Mon Sep 17 00:00:00 2001
From: Kamil Dudka <kdudka@redhat.com>
Date: Sat, 19 Dec 2015 22:56:40 +0100
Subject: [PATCH 1/2] Revert "Don't include dblocation.texi from original spot,
symlink it."
This reverts commit f59d88e456553dfe0b5185caf75e4041285fd595.
---
configure.ac | 2 +-
doc/Makefile.am | 8 +-------
doc/find.texi | 2 +-
3 files changed, 3 insertions(+), 9 deletions(-)
diff --git a/configure.ac b/configure.ac
index 7962719..ce0e768 100644
--- a/configure.ac
+++ b/configure.ac
@@ -70,7 +70,7 @@ AC_PROG_CPP
dnl for gnulib
gl_EARLY
-AC_PROG_LN_S
+
AC_PROG_INSTALL
AC_CHECK_TOOLS([AR], [ar])
AC_CHECK_TOOLS([RANLIB], [ranlib], [:])
diff --git a/doc/Makefile.am b/doc/Makefile.am
index f6f7443..6fbf57b 100644
--- a/doc/Makefile.am
+++ b/doc/Makefile.am
@@ -16,11 +16,9 @@ AM_CFLAGS = $(WARN_CFLAGS)
info_TEXINFOS = find.texi find-maint.texi
find_TEXINFOS = perm.texi parse-datetime.texi regexprops.texi fdl.texi
-BUILT_SOURCES = dblocation.texi
-nodist_find_TEXINFOS = dblocation.texi
find_maint_TEXINFOS = fdl.texi
MOSTLYCLEANFILES = find.cps
-CLEANFILES = find.txt find_mono.html findutils.texi_html_node.tar.gz dblocation.texi
+CLEANFILES = find.txt find_mono.html findutils.texi_html_node.tar.gz
MAKEINFOTXT = $(MAKEINFO) --plaintext
@@ -69,7 +67,3 @@ find_mono.html: find.texi
# for "make all" or "make install" (or even "make check").
findutils.texi_html_node.tar.gz: find.html
tar zcf $@ $<
-
-
-dblocation.texi: ../locate/dblocation.texi
- $(LN_S) ../locate/dblocation.texi $@
diff --git a/doc/find.texi b/doc/find.texi
index a83a645..c2714dd 100644
--- a/doc/find.texi
+++ b/doc/find.texi
@@ -7,7 +7,7 @@
@c %**end of header
@include version.texi
-@include dblocation.texi
+@include ../locate/dblocation.texi
@iftex
@finalout
--
2.5.0
From d5473caa86f689ebcadacc593f5a71781c99e829 Mon Sep 17 00:00:00 2001
From: Kamil Dudka <kdudka@redhat.com>
Date: Wed, 11 May 2011 16:46:13 +0200
Subject: [PATCH 2/2] findutils-4.4.0-no-locate.patch
---
Makefile.am | 2 +-
configure.ac | 2 --
doc/find.texi | 24 ++++++++----------------
3 files changed, 9 insertions(+), 19 deletions(-)
diff --git a/Makefile.am b/Makefile.am
index af82d54..6ad453b 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -9,7 +9,7 @@ DISTCLEANFILES = tool-versions.txt
# "tests" is the gnulib unit test dir.
-SUBDIRS = gl tests build-aux lib find xargs locate doc po m4
+SUBDIRS = gl tests build-aux lib find xargs doc po m4
ACLOCAL_AMFLAGS = -I gl/m4 -I m4
diff --git a/configure.ac b/configure.ac
index ce0e768..521e665 100644
--- a/configure.ac
+++ b/configure.ac
@@ -248,8 +248,6 @@ find/testsuite/Makefile
gl/Makefile
gl/lib/Makefile
lib/Makefile
-locate/Makefile
-locate/testsuite/Makefile
m4/Makefile
po/Makefile.in
po/Makefile
diff --git a/doc/find.texi b/doc/find.texi
index c2714dd..01367a4 100644
--- a/doc/find.texi
+++ b/doc/find.texi
@@ -7,7 +7,6 @@
@c %**end of header
@include version.texi
-@include ../locate/dblocation.texi
@iftex
@finalout
@@ -571,8 +570,7 @@ the databases are updated, and the directories for which they contain
entries.
Here is how to select which file name databases @code{locate}
-searches. The default is system-dependent. At the time this document
-was generated, the default was @file{@value{LOCATE_DB}}.
+searches. The default is system-dependent.
@table @code
@item --database=@var{path}
@@ -2892,13 +2890,9 @@ thrashing the network.
directories are indexed by each database file.
The default location for the locate database depends on how findutils
-is built, but the findutils installation accompanying this manual uses
-the default location @file{@value{LOCATE_DB}}.
-
-If no database exists at @file{@value{LOCATE_DB}} but the user did not
-specify where to look (by using @samp{-d} or setting
-@code{LOCATE_PATH}), then @code{locate} will also check for a
-``secure'' database in @file{/var/lib/slocate/slocate.db}.
+is built. If user did not specify where to look (by using @samp{-d}
+or setting @code{LOCATE_PATH}), then @code{locate} will also check for
+a ``secure'' database in @file{/var/lib/slocate/slocate.db}.
@node Database Formats
@section Database Formats
@@ -3438,8 +3432,7 @@ present.
@item --database=@var{path}
@itemx -d @var{path}
-Instead of searching the default @code{locate} database
-@file{@value{LOCATE_DB}}, @code{locate} searches the file
+@code{locate} searches the file
name databases in @var{path}, which is a colon-separated list of
database file names. You can also use the environment variable
@code{LOCATE_PATH} to set the list of database files to search. The
@@ -3614,8 +3607,7 @@ The environment variable @code{PRUNEFS} also sets this value. Default
is @file{nfs NFS proc}.
@item --output=@var{dbfile}
-The database file to build. The default is system-dependent, but
-when this document was formatted it was @file{@value{LOCATE_DB}}.
+The database file to build.
@item --localuser=@var{user}
The user to search the non-network directories as, using @code{su}.
@@ -5635,7 +5627,7 @@ why @code{xargs} is confused by your operating system).
@section Error Messages From @code{locate}
@table @samp
-@item warning: database @file{@value{LOCATE_DB}} is more than 8 days old
+@item warning: database @file{LOCATE_DB} is more than 8 days old
The @code{locate} program relies on a database which is periodically
built by the @code{updatedb} program. That hasn't happened in a long
time. To fix this problem, run @code{updatedb} manually. This can
@@ -5643,7 +5635,7 @@ often happen on systems that are generally not left on, so the
periodic ``cron'' task which normally does this doesn't get a chance
to run.
-@item locate database @file{@value{LOCATE_DB}} is corrupt or invalid
+@item locate database @file{LOCATE_DB} is corrupt or invalid
This should not happen. Re-run @code{updatedb}. If that works, but
@code{locate} still produces this error, run @code{locate --version}
and @code{updatedb --version}. These should produce the same output.
--
2.5.0

View File

@ -0,0 +1,226 @@
From 443166adaf1c8b91e16a716f3b13f47493b895cc Mon Sep 17 00:00:00 2001
From: Bernhard Voelker <mail@bernhard-voelker.de>
Date: Tue, 31 May 2016 10:38:52 +0200
Subject: [PATCH] Fix bug #48030: find: -exec + does not pass all arguments in
certain cases
When the -exec arguments buffer (usually 128k) is full and the given
command has been executed with all that arguments, find(1) missed to
execute the command yet another time if only 1 another file would have
to be processed.
Both find(1), i.e., nowadays FTS-version, and oldfind are affected.
This bug was present since the implementation of '-exec +' in 2005,
see commit FINDUTILS_4_2_11-1-25-gf0a6ac6.
* lib/buildcmd.c (bc_push_arg): Move the assignment to set 'state->todo'
to 1 down after the immediate execution which resets that flag.
* find/testsuite/sv-48030-exec-plus-bug.sh: Add a test.
* find/testsuite/Makefile.am (test_shell_progs): Reference the test.
* NEWS (Bug Fixes): Mention the fix.
Reported by Joe Philip Ninan <indiajoe@gmail.com> in
https://savannah.gnu.org/bugs/?48030
Upstream-commit: 8cdc9767e305c9566f537af9d1acf71d1bc6ee8e
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
---
find/testsuite/Makefile.am | 3 +-
find/testsuite/sv-48030-exec-plus-bug.sh | 143 +++++++++++++++++++++++++++++++
lib/buildcmd.c | 10 +--
3 files changed, 150 insertions(+), 6 deletions(-)
create mode 100644 find/testsuite/sv-48030-exec-plus-bug.sh
diff --git a/find/testsuite/Makefile.am b/find/testsuite/Makefile.am
index c1369c3..ab5dbe8 100644
--- a/find/testsuite/Makefile.am
+++ b/find/testsuite/Makefile.am
@@ -258,7 +258,8 @@ test_escapechars.sh \
test_escape_c.sh \
test_inode.sh \
sv-34079.sh \
-sv-34976-execdir-fd-leak.sh
+sv-34976-execdir-fd-leak.sh \
+sv-48030-exec-plus-bug.sh
EXTRA_DIST = $(EXTRA_DIST_EXP) $(EXTRA_DIST_XO) $(EXTRA_DIST_GOLDEN) \
$(test_shell_progs) binary_locations.sh checklists.py
diff --git a/find/testsuite/sv-48030-exec-plus-bug.sh b/find/testsuite/sv-48030-exec-plus-bug.sh
new file mode 100755
index 0000000..4dbf149
--- /dev/null
+++ b/find/testsuite/sv-48030-exec-plus-bug.sh
@@ -0,0 +1,143 @@
+#! /bin/sh
+# Copyright (C) 2016 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 <http://www.gnu.org/licenses/>.
+#
+
+# This test verifies that find invokes the given command for the
+# multiple-argument sytax '-exec CMD {} +'. Between FINDUTILS-4.2.12
+# and v4.6.0, find(1) would have failed to execute CMD another time
+# if there was only one last single file argument.
+
+testname="$(basename $0)"
+
+. "${srcdir}"/binary_locations.sh
+
+die() {
+ echo "$@" >&2
+ exit 1
+}
+
+# This is used to simplify checking of the return value
+# which is useful when ensuring a command fails as desired.
+# I.e., just doing `command ... &&fail=1` will not catch
+# a segfault in command for example. With this helper you
+# instead check an explicit exit code like
+# returns_ 1 command ... || fail
+returns_ () {
+ # Disable tracing so it doesn't interfere with stderr of the wrapped command
+ { set +x; } 2>/dev/null
+
+ local exp_exit="$1"
+ shift
+ "$@"
+ test $? -eq $exp_exit && ret_=0 || ret_=1
+
+ set -x
+ { return $ret_; } 2>/dev/null
+}
+
+# Define the nicest compare available (borrowed from gnulib).
+if diff_out_=`exec 2>/dev/null; diff -u "$0" "$0" < /dev/null` \
+ && diff -u Makefile "$0" 2>/dev/null | grep '^[+]#!' >/dev/null; then
+ # diff accepts the -u option and does not (like AIX 7 'diff') produce an
+ # extra space on column 1 of every content line.
+ if test -z "$diff_out_"; then
+ compare () { diff -u "$@"; }
+ else
+ compare ()
+ {
+ if diff -u "$@" > diff.out; then
+ # No differences were found, but Solaris 'diff' produces output
+ # "No differences encountered". Hide this output.
+ rm -f diff.out
+ true
+ else
+ cat diff.out
+ rm -f diff.out
+ false
+ fi
+ }
+ fi
+elif diff_out_=`exec 2>/dev/null; diff -c "$0" "$0" < /dev/null`; then
+ if test -z "$diff_out_"; then
+ compare () { diff -c "$@"; }
+ else
+ compare ()
+ {
+ if diff -c "$@" > diff.out; then
+ # No differences were found, but AIX and HP-UX 'diff' produce output
+ # "No differences encountered" or "There are no differences between the
+ # files.". Hide this output.
+ rm -f diff.out
+ true
+ else
+ cat diff.out
+ rm -f diff.out
+ false
+ fi
+ }
+ fi
+elif cmp -s /dev/null /dev/null 2>/dev/null; then
+ compare () { cmp -s "$@"; }
+else
+ compare () { cmp "$@"; }
+fi
+
+DIR='RashuBug'
+# Name of the CMD to execute: the file name must be 6 characters long
+# (to trigger the bug in combination with the test files).
+CMD='tstcmd'
+
+# Create test files.
+make_test_data() {
+ # Create the CMD script and check that it works.
+ mkdir "$DIR" 'bin' \
+ && echo 'printf "%s\n" "$@"' > "bin/$CMD" \
+ && chmod +x "bin/$CMD" \
+ && PATH="$PWD/bin:$PATH" \
+ && [ $( "${ftsfind}" bin -maxdepth 0 -exec "$CMD" '{}' + ) = 'bin' ] \
+ || return 1
+
+ # Create expected output file - also used for creating the test data.
+ { seq -f "${DIR}/abcdefghijklmnopqrstuv%04g" 901 &&
+ seq -f "${DIR}/abcdefghijklmnopqrstu%04g" 902 3719
+ } > exp2 \
+ && LC_ALL=C sort exp2 > exp \
+ && rm exp2 \
+ || return 1
+
+ # Create test files, and check if test data has been created correctly.
+ xargs touch < exp \
+ && [ -f "${DIR}/abcdefghijklmnopqrstu3719" ] \
+ && [ 3719 = $( "${ftsfind}" "$DIR" -type f | wc -l ) ] \
+ || return 1
+}
+
+set -x
+tmpdir="$(mktemp -d)" \
+ && cd "$tmpdir" \
+ && make_test_data "${tmpdir}" \
+ || die "FAIL: failed to set up the test in ${tmpdir}"
+
+fail=0
+for exe in "${ftsfind}" "${oldfind}"; do
+ "$exe" "$DIR" -type f -exec "$CMD" '{}' + > out || fail=1
+ LC_ALL=C sort out > out2 || fail=1
+ compare exp out2 || fail=1
+done
+
+cd ..
+rm -rf "${tmpdir}" || exit 1
+exit $fail
diff --git a/lib/buildcmd.c b/lib/buildcmd.c
index a58f67e..27e9ce5 100644
--- a/lib/buildcmd.c
+++ b/lib/buildcmd.c
@@ -356,11 +356,6 @@ bc_push_arg (struct buildcmd_control *ctl,
assert (arg != NULL);
- if (!initial_args)
- {
- state->todo = 1;
- }
-
if (!terminate)
{
if (state->cmd_argv_chars + len + pfxlen > ctl->arg_max)
@@ -380,6 +375,11 @@ bc_push_arg (struct buildcmd_control *ctl,
bc_do_exec (ctl, state);
}
+ if (!initial_args)
+ {
+ state->todo = 1;
+ }
+
if (state->cmd_argc >= state->cmd_argv_alloc)
{
/* XXX: we could use extendbuf() here. */
--
2.5.5

View File

@ -0,0 +1,990 @@
From f3337786e55909538aacfd7c29b1cf58ff444fbf Mon Sep 17 00:00:00 2001
From: Kamil Dudka <kdudka@redhat.com>
Date: Mon, 12 Feb 2018 12:45:36 +0100
Subject: [PATCH 1/4] import gnulib's FTS module from upstream commit 281b825e
---
gl/lib/fts.c | 424 +++++++++++++++++++++++++++++-----------------------------
gl/lib/fts_.h | 10 +-
2 files changed, 221 insertions(+), 213 deletions(-)
diff --git a/gl/lib/fts.c b/gl/lib/fts.c
index c91d7a1..bfa73e3 100644
--- a/gl/lib/fts.c
+++ b/gl/lib/fts.c
@@ -1,6 +1,6 @@
/* Traverse a file hierarchy.
- Copyright (C) 2004-2015 Free Software Foundation, Inc.
+ Copyright (C) 2004-2018 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
@@ -13,7 +13,7 @@
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 <http://www.gnu.org/licenses/>. */
+ along with this program. If not, see <https://www.gnu.org/licenses/>. */
/*-
* Copyright (c) 1990, 1993, 1994
@@ -46,9 +46,9 @@
#include <config.h>
-#if defined(LIBC_SCCS) && !defined(lint)
+#if defined LIBC_SCCS && !defined GCC_LINT && !defined lint
static char sccsid[] = "@(#)fts.c 8.6 (Berkeley) 8/14/94";
-#endif /* LIBC_SCCS and not lint */
+#endif
#include "fts_.h"
@@ -71,11 +71,7 @@ static char sccsid[] = "@(#)fts.c 8.6 (Berkeley) 8/14/94";
#if ! _LIBC
# include "fcntl--.h"
-# include "dirent--.h"
-# include "unistd--.h"
-/* FIXME - use fcntl(F_DUPFD_CLOEXEC)/openat(O_CLOEXEC) once they are
- supported. */
-# include "cloexec.h"
+# include "flexmember.h"
# include "openat.h"
# include "same-inode.h"
#endif
@@ -202,6 +198,14 @@ enum Fts_stat
while (false)
#endif
+#ifndef FALLTHROUGH
+# if __GNUC__ < 7
+# define FALLTHROUGH ((void) 0)
+# else
+# define FALLTHROUGH __attribute__ ((__fallthrough__))
+# endif
+#endif
+
static FTSENT *fts_alloc (FTS *, const char *, size_t) internal_function;
static FTSENT *fts_build (FTS *, int) internal_function;
static void fts_lfree (FTSENT *) internal_function;
@@ -296,14 +300,13 @@ static DIR *
internal_function
opendirat (int fd, char const *dir, int extra_flags, int *pdir_fd)
{
- int new_fd = openat (fd, dir,
- (O_RDONLY | O_DIRECTORY | O_NOCTTY | O_NONBLOCK
- | extra_flags));
+ int open_flags = (O_RDONLY | O_CLOEXEC | O_DIRECTORY | O_NOCTTY
+ | O_NONBLOCK | extra_flags);
+ int new_fd = openat (fd, dir, open_flags);
DIR *dirp;
if (new_fd < 0)
return NULL;
- set_cloexec_flag (new_fd, true);
dirp = fdopendir (new_fd);
if (dirp)
*pdir_fd = new_fd;
@@ -366,15 +369,13 @@ static int
internal_function
diropen (FTS const *sp, char const *dir)
{
- int open_flags = (O_SEARCH | O_DIRECTORY | O_NOCTTY | O_NONBLOCK
+ int open_flags = (O_SEARCH | O_CLOEXEC | O_DIRECTORY | O_NOCTTY | O_NONBLOCK
| (ISSET (FTS_PHYSICAL) ? O_NOFOLLOW : 0)
| (ISSET (FTS_NOATIME) ? O_NOATIME : 0));
int fd = (ISSET (FTS_CWDFD)
? openat (sp->fts_cwd_fd, dir, open_flags)
: open (dir, open_flags));
- if (0 <= fd)
- set_cloexec_flag (fd, true);
return fd;
}
@@ -470,6 +471,7 @@ fts_open (char * const *argv,
if ((parent = fts_alloc(sp, "", 0)) == NULL)
goto mem2;
parent->fts_level = FTS_ROOTPARENTLEVEL;
+ parent->fts_n_dirs_remaining = -1;
}
/* The classic fts implementation would call fts_stat with
@@ -656,39 +658,139 @@ fts_close (FTS *sp)
return (0);
}
+/* Minimum link count of a traditional Unix directory. When leaf
+ optimization is OK and MIN_DIR_NLINK <= st_nlink, then st_nlink is
+ an upper bound on the number of subdirectories (counting "." and
+ ".."). */
+enum { MIN_DIR_NLINK = 2 };
+
+/* Whether leaf optimization is OK for a directory. */
+enum leaf_optimization
+ {
+ /* st_nlink is not reliable for this directory's subdirectories. */
+ NO_LEAF_OPTIMIZATION,
+
+ /* Leaf optimization is OK, but is not useful for avoiding stat calls. */
+ OK_LEAF_OPTIMIZATION,
+
+ /* Leaf optimization is not only OK: it is useful for avoiding
+ stat calls, because dirent.d_type does not work. */
+ NOSTAT_LEAF_OPTIMIZATION
+ };
+
#if defined __linux__ \
&& HAVE_SYS_VFS_H && HAVE_FSTATFS && HAVE_STRUCT_STATFS_F_TYPE
# include <sys/vfs.h>
/* Linux-specific constants from coreutils' src/fs.h */
-# define S_MAGIC_TMPFS 0x1021994
+# define S_MAGIC_AFS 0x5346414F
# define S_MAGIC_NFS 0x6969
+# define S_MAGIC_PROC 0x9FA0
# define S_MAGIC_REISERFS 0x52654973
+# define S_MAGIC_TMPFS 0x1021994
# define S_MAGIC_XFS 0x58465342
-# define S_MAGIC_PROC 0x9FA0
-/* Return false if it is easy to determine the file system type of
- the directory on which DIR_FD is open, and sorting dirents on
- inode numbers is known not to improve traversal performance with
- that type of file system. Otherwise, return true. */
+# ifdef HAVE___FSWORD_T
+typedef __fsword_t fsword;
+# else
+typedef long int fsword;
+# endif
+
+/* Map a stat.st_dev number to a file system type number f_ftype. */
+struct dev_type
+{
+ dev_t st_dev;
+ fsword f_type;
+};
+
+/* Use a tiny initial size. If a traversal encounters more than
+ a few devices, the cost of growing/rehashing this table will be
+ rendered negligible by the number of inodes processed. */
+enum { DEV_TYPE_HT_INITIAL_SIZE = 13 };
+
+static size_t
+dev_type_hash (void const *x, size_t table_size)
+{
+ struct dev_type const *ax = x;
+ uintmax_t dev = ax->st_dev;
+ return dev % table_size;
+}
+
static bool
-dirent_inode_sort_may_be_useful (int dir_fd)
+dev_type_compare (void const *x, void const *y)
+{
+ struct dev_type const *ax = x;
+ struct dev_type const *ay = y;
+ return ax->st_dev == ay->st_dev;
+}
+
+/* Return the file system type of P, or 0 if not known.
+ Try to cache known values. */
+
+static fsword
+filesystem_type (FTSENT const *p)
+{
+ FTS *sp = p->fts_fts;
+ Hash_table *h = sp->fts_leaf_optimization_works_ht;
+ struct dev_type *ent;
+ struct statfs fs_buf;
+
+ /* If we're not in CWDFD mode, don't bother with this optimization,
+ since the caller is not serious about performance. */
+ if (!ISSET (FTS_CWDFD))
+ return 0;
+
+ if (! h)
+ h = sp->fts_leaf_optimization_works_ht
+ = hash_initialize (DEV_TYPE_HT_INITIAL_SIZE, NULL, dev_type_hash,
+ dev_type_compare, free);
+ if (h)
+ {
+ struct dev_type tmp;
+ tmp.st_dev = p->fts_statp->st_dev;
+ ent = hash_lookup (h, &tmp);
+ if (ent)
+ return ent->f_type;
+ }
+
+ /* Look-up failed. Query directly and cache the result. */
+ if (fstatfs (p->fts_fts->fts_cwd_fd, &fs_buf) != 0)
+ return 0;
+
+ if (h)
+ {
+ struct dev_type *t2 = malloc (sizeof *t2);
+ if (t2)
+ {
+ t2->st_dev = p->fts_statp->st_dev;
+ t2->f_type = fs_buf.f_type;
+
+ ent = hash_insert (h, t2);
+ if (ent)
+ fts_assert (ent == t2);
+ else
+ free (t2);
+ }
+ }
+
+ return fs_buf.f_type;
+}
+
+/* Return false if it is easy to determine the file system type of the
+ directory P, and sorting dirents on inode numbers is known not to
+ improve traversal performance with that type of file system.
+ Otherwise, return true. */
+static bool
+dirent_inode_sort_may_be_useful (FTSENT const *p)
{
/* Skip the sort only if we can determine efficiently
that skipping it is the right thing to do.
The cost of performing an unnecessary sort is negligible,
while the cost of *not* performing it can be O(N^2) with
a very large constant. */
- struct statfs fs_buf;
-
- /* If fstatfs fails, assume sorting would be useful. */
- if (fstatfs (dir_fd, &fs_buf) != 0)
- return true;
- /* FIXME: what about when f_type is not an integral type?
- deal with that if/when it's encountered. */
- switch (fs_buf.f_type)
+ switch (filesystem_type (p))
{
case S_MAGIC_TMPFS:
case S_MAGIC_NFS:
@@ -701,133 +803,58 @@ dirent_inode_sort_may_be_useful (int dir_fd)
}
}
-/* Given a file descriptor DIR_FD open on a directory D,
- return true if it is valid to apply the leaf-optimization
- technique of counting directories in D via stat.st_nlink. */
-static bool
-leaf_optimization_applies (int dir_fd)
+/* Given an FTS entry P for a directory D,
+ return true if it is both useful and valid to apply leaf optimization.
+ The optimization is useful only for file systems that lack usable
+ dirent.d_type info. The optimization is valid if an st_nlink value
+ of at least MIN_DIR_NLINK is an upper bound on the number of
+ subdirectories of D, counting "." and ".." as subdirectories. */
+static enum leaf_optimization
+leaf_optimization (FTSENT const *p)
{
- struct statfs fs_buf;
-
- /* If fstatfs fails, assume we can't use the optimization. */
- if (fstatfs (dir_fd, &fs_buf) != 0)
- return false;
-
- /* FIXME: do we need to detect AFS mount points? I doubt it,
- unless fstatfs can report S_MAGIC_REISERFS for such a directory. */
-
- switch (fs_buf.f_type)
+ switch (filesystem_type (p))
{
- case S_MAGIC_NFS:
- /* NFS provides usable dirent.d_type but not necessarily for all entries
- of large directories. See <https://bugzilla.redhat.com/1252549>. */
- return true;
-
- /* List here the file system types that lack usable dirent.d_type
+ /* List here the file system types that may lack usable dirent.d_type
info, yet for which the optimization does apply. */
case S_MAGIC_REISERFS:
- case S_MAGIC_XFS:
- return true;
-
+ case S_MAGIC_XFS: /* XFS lacked it until 2013-08-22 commit. */
+ return NOSTAT_LEAF_OPTIMIZATION;
+
+ case 0:
+ /* Leaf optimization is unsafe if the file system type is unknown. */
+ FALLTHROUGH;
+ case S_MAGIC_AFS:
+ /* Although AFS mount points are not counted in st_nlink, they
+ act like directories. See <https://bugs.debian.org/143111>. */
+ FALLTHROUGH;
+ case S_MAGIC_NFS:
+ /* NFS provides usable dirent.d_type but not necessarily for all entries
+ of large directories, so as per <https://bugzilla.redhat.com/1252549>
+ NFS should return true. However st_nlink values are not accurate on
+ all implementations as per <https://bugzilla.redhat.com/1299169>. */
+ FALLTHROUGH;
case S_MAGIC_PROC:
- /* Explicitly listing this or any other file system type for which
- the optimization is not applicable is not necessary, but we leave
- it here to document the risk. Per http://bugs.debian.org/143111,
- /proc may have bogus stat.st_nlink values. */
- /* fall through */
+ /* Per <https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=143111> /proc
+ may have bogus stat.st_nlink values. */
+ return NO_LEAF_OPTIMIZATION;
+
default:
- return false;
+ return OK_LEAF_OPTIMIZATION;
}
}
#else
static bool
-dirent_inode_sort_may_be_useful (int dir_fd _GL_UNUSED) { return true; }
-static bool
-leaf_optimization_applies (int dir_fd _GL_UNUSED) { return false; }
-#endif
-
-/* link-count-optimization entry:
- map a stat.st_dev number to a boolean: leaf_optimization_works */
-struct LCO_ent
-{
- dev_t st_dev;
- bool opt_ok;
-};
-
-/* Use a tiny initial size. If a traversal encounters more than
- a few devices, the cost of growing/rehashing this table will be
- rendered negligible by the number of inodes processed. */
-enum { LCO_HT_INITIAL_SIZE = 13 };
-
-static size_t
-LCO_hash (void const *x, size_t table_size)
-{
- struct LCO_ent const *ax = x;
- return (uintmax_t) ax->st_dev % table_size;
-}
-
-static bool
-LCO_compare (void const *x, void const *y)
+dirent_inode_sort_may_be_useful (FTSENT const *p _GL_UNUSED)
{
- struct LCO_ent const *ax = x;
- struct LCO_ent const *ay = y;
- return ax->st_dev == ay->st_dev;
+ return true;
}
-
-/* Ask the same question as leaf_optimization_applies, but query
- the cache first (FTS.fts_leaf_optimization_works_ht), and if necessary,
- update that cache. */
-static bool
-link_count_optimize_ok (FTSENT const *p)
+static enum leaf_optimization
+leaf_optimization (FTSENT const *p _GL_UNUSED)
{
- FTS *sp = p->fts_fts;
- Hash_table *h = sp->fts_leaf_optimization_works_ht;
- struct LCO_ent tmp;
- struct LCO_ent *ent;
- bool opt_ok;
- struct LCO_ent *t2;
-
- /* If we're not in CWDFD mode, don't bother with this optimization,
- since the caller is not serious about performance. */
- if (!ISSET(FTS_CWDFD))
- return false;
-
- /* map st_dev to the boolean, leaf_optimization_works */
- if (h == NULL)
- {
- h = sp->fts_leaf_optimization_works_ht
- = hash_initialize (LCO_HT_INITIAL_SIZE, NULL, LCO_hash,
- LCO_compare, free);
- if (h == NULL)
- return false;
- }
- tmp.st_dev = p->fts_statp->st_dev;
- ent = hash_lookup (h, &tmp);
- if (ent)
- return ent->opt_ok;
-
- /* Look-up failed. Query directly and cache the result. */
- t2 = malloc (sizeof *t2);
- if (t2 == NULL)
- return false;
-
- /* Is it ok to perform the optimization in the dir, FTS_CWD_FD? */
- opt_ok = leaf_optimization_applies (sp->fts_cwd_fd);
- t2->opt_ok = opt_ok;
- t2->st_dev = p->fts_statp->st_dev;
-
- ent = hash_insert (h, t2);
- if (ent == NULL)
- {
- /* insertion failed */
- free (t2);
- return false;
- }
- fts_assert (ent == t2);
-
- return opt_ok;
+ return NO_LEAF_OPTIMIZATION;
}
+#endif
/*
* Special case of "/" at the end of the file name so that slashes aren't
@@ -1014,13 +1041,11 @@ check_for_dir:
if (p->fts_statp->st_size == FTS_STAT_REQUIRED)
{
FTSENT *parent = p->fts_parent;
- if (FTS_ROOTLEVEL < p->fts_level
- /* ->fts_n_dirs_remaining is not valid
- for command-line-specified names. */
- && parent->fts_n_dirs_remaining == 0
+ if (parent->fts_n_dirs_remaining == 0
&& ISSET(FTS_NOSTAT)
&& ISSET(FTS_PHYSICAL)
- && link_count_optimize_ok (parent))
+ && (leaf_optimization (parent)
+ == NOSTAT_LEAF_OPTIMIZATION))
{
/* nothing more needed */
}
@@ -1029,7 +1054,8 @@ check_for_dir:
p->fts_info = fts_stat(sp, p, false);
if (S_ISDIR(p->fts_statp->st_mode)
&& p->fts_level != FTS_ROOTLEVEL
- && parent->fts_n_dirs_remaining)
+ && 0 < parent->fts_n_dirs_remaining
+ && parent->fts_n_dirs_remaining != (nlink_t) -1)
parent->fts_n_dirs_remaining--;
}
}
@@ -1298,8 +1324,6 @@ fts_build (register FTS *sp, int type)
bool descend;
bool doadjust;
ptrdiff_t level;
- nlink_t nlinks;
- bool nostat;
size_t len, maxlen, new_len;
char *cp;
int dir_fd;
@@ -1369,24 +1393,6 @@ fts_build (register FTS *sp, int type)
sorting, yet not so large that we risk exhausting memory. */
max_entries = sp->fts_compar ? SIZE_MAX : FTS_MAX_READDIR_ENTRIES;
- /*
- * Nlinks is the number of possible entries of type directory in the
- * directory if we're cheating on stat calls, 0 if we're not doing
- * any stat calls at all, (nlink_t) -1 if we're statting everything.
- */
- if (type == BNAMES) {
- nlinks = 0;
- /* Be quiet about nostat, GCC. */
- nostat = false;
- } else if (ISSET(FTS_NOSTAT) && ISSET(FTS_PHYSICAL)) {
- nlinks = (cur->fts_statp->st_nlink
- - (ISSET(FTS_SEEDOT) ? 0 : 2));
- nostat = true;
- } else {
- nlinks = -1;
- nostat = false;
- }
-
/*
* If we're going to need to stat anything or we want to descend
* and stay in the directory, chdir. If this fails we keep going,
@@ -1408,15 +1414,22 @@ fts_build (register FTS *sp, int type)
the required dirp and dir_fd. */
descend = true;
}
- else if (nlinks || type == BREAD) {
+ else
+ {
+ /* Try to descend unless it is a names-only fts_children,
+ or the directory is known to lack subdirectories. */
+ descend = (type != BNAMES
+ && ! (ISSET (FTS_NOSTAT) && ISSET (FTS_PHYSICAL)
+ && ! ISSET (FTS_SEEDOT)
+ && cur->fts_statp->st_nlink == MIN_DIR_NLINK
+ && (leaf_optimization (cur)
+ != NO_LEAF_OPTIMIZATION)));
+ if (descend || type == BREAD)
+ {
if (ISSET(FTS_CWDFD))
- {
- dir_fd = dup (dir_fd);
- if (0 <= dir_fd)
- set_cloexec_flag (dir_fd, true);
- }
+ dir_fd = fcntl (dir_fd, F_DUPFD_CLOEXEC, STDERR_FILENO + 1);
if (dir_fd < 0 || fts_safe_changedir(sp, cur, dir_fd, NULL)) {
- if (nlinks && type == BREAD)
+ if (descend && type == BREAD)
cur->fts_errno = errno;
cur->fts_flags |= FTS_DONTCHDIR;
descend = false;
@@ -1426,8 +1439,8 @@ fts_build (register FTS *sp, int type)
cur->fts_dirp = NULL;
} else
descend = true;
- } else
- descend = false;
+ }
+ }
/*
* Figure out the max file name length that can be stored in the
@@ -1458,11 +1471,19 @@ fts_build (register FTS *sp, int type)
tail = NULL;
nitems = 0;
while (cur->fts_dirp) {
- bool is_dir;
size_t d_namelen;
+ __set_errno (0);
struct dirent *dp = readdir(cur->fts_dirp);
- if (dp == NULL)
+ if (dp == NULL) {
+ if (errno) {
+ cur->fts_errno = errno;
+ /* If we've not read any items yet, treat
+ the error as if we can't access the dir. */
+ cur->fts_info = (continue_readdir || nitems)
+ ? FTS_ERR : FTS_DNR;
+ }
break;
+ }
if (!ISSET(FTS_SEEDOT) && ISDOT(dp->d_name))
continue;
@@ -1550,19 +1571,10 @@ mem1: saved_errno = errno;
to caller, when possible. */
set_stat_type (p->fts_statp, D_TYPE (dp));
fts_set_stat_required(p, !skip_stat);
- is_dir = (ISSET(FTS_PHYSICAL)
- && DT_MUST_BE(dp, DT_DIR));
} else {
p->fts_info = fts_stat(sp, p, false);
- is_dir = (p->fts_info == FTS_D
- || p->fts_info == FTS_DC
- || p->fts_info == FTS_DOT);
}
- /* Decrement link count if applicable. */
- if (nlinks > 0 && is_dir)
- nlinks -= nostat;
-
/* We walk in directory order so "ls -f" doesn't get upset. */
p->fts_link = NULL;
if (head == NULL)
@@ -1621,7 +1633,8 @@ mem1: saved_errno = errno;
/* If didn't find anything, return NULL. */
if (!nitems) {
- if (type == BREAD)
+ if (type == BREAD
+ && cur->fts_info != FTS_DNR && cur->fts_info != FTS_ERR)
cur->fts_info = FTS_DP;
fts_lfree(head);
return (NULL);
@@ -1633,8 +1646,7 @@ mem1: saved_errno = errno;
inode numbers. */
if (nitems > _FTS_INODE_SORT_DIR_ENTRIES_THRESHOLD
&& !sp->fts_compar
- && ISSET (FTS_CWDFD)
- && dirent_inode_sort_may_be_useful (sp->fts_cwd_fd)) {
+ && dirent_inode_sort_may_be_useful (cur)) {
sp->fts_compar = fts_compare_ino;
head = fts_sort (sp, head, nitems);
sp->fts_compar = NULL;
@@ -1757,7 +1769,7 @@ fd_ring_check (FTS const *sp)
I_ring fd_w = sp->fts_fd_ring;
int cwd_fd = sp->fts_cwd_fd;
- cwd_fd = dup (cwd_fd);
+ cwd_fd = fcntl (cwd_fd, F_DUPFD_CLOEXEC, STDERR_FILENO + 1);
char *dot = getcwdat (cwd_fd, NULL, 0);
error (0, 0, "===== check ===== cwd: %s", dot);
free (dot);
@@ -1766,7 +1778,8 @@ fd_ring_check (FTS const *sp)
int fd = i_ring_pop (&fd_w);
if (0 <= fd)
{
- int parent_fd = openat (cwd_fd, "..", O_SEARCH | O_NOATIME);
+ int open_flags = O_SEARCH | O_CLOEXEC | O_NOATIME;
+ int parent_fd = openat (cwd_fd, "..", open_flags);
if (parent_fd < 0)
{
// Warn?
@@ -1795,7 +1808,6 @@ internal_function
fts_stat(FTS *sp, register FTSENT *p, bool follow)
{
struct stat *sbp = p->fts_statp;
- int saved_errno;
if (p->fts_level == FTS_ROOTLEVEL && ISSET(FTS_COMFOLLOW))
follow = true;
@@ -1807,13 +1819,12 @@ fts_stat(FTS *sp, register FTSENT *p, bool follow)
*/
if (ISSET(FTS_LOGICAL) || follow) {
if (stat(p->fts_accpath, sbp)) {
- saved_errno = errno;
if (errno == ENOENT
&& lstat(p->fts_accpath, sbp) == 0) {
__set_errno (0);
return (FTS_SLNONE);
}
- p->fts_errno = saved_errno;
+ p->fts_errno = errno;
goto err;
}
} else if (fstatat(sp->fts_cwd_fd, p->fts_accpath, sbp,
@@ -1824,8 +1835,11 @@ err: memset(sbp, 0, sizeof(struct stat));
}
if (S_ISDIR(sbp->st_mode)) {
- p->fts_n_dirs_remaining = (sbp->st_nlink
- - (ISSET(FTS_SEEDOT) ? 0 : 2));
+ p->fts_n_dirs_remaining
+ = ((sbp->st_nlink < MIN_DIR_NLINK
+ || p->fts_level <= FTS_ROOTLEVEL)
+ ? -1
+ : sbp->st_nlink - (ISSET (FTS_SEEDOT) ? 0 : MIN_DIR_NLINK));
if (ISDOT(p->fts_name)) {
/* Command-line "." and ".." are real directories. */
return (p->fts_level == FTS_ROOTLEVEL ? FTS_D : FTS_DOT);
@@ -1914,17 +1928,7 @@ fts_alloc (FTS *sp, const char *name, register size_t namelen)
* The file name is a variable length array. Allocate the FTSENT
* structure and the file name in one chunk.
*/
- len = offsetof(FTSENT, fts_name) + namelen + 1;
- /* Align the allocation size so that it works for FTSENT,
- so that trailing padding may be referenced by direct access
- to the flexible array members, without triggering undefined behavior
- by accessing bytes beyond the heap allocation. This implicit access
- was seen for example with ISDOT() and GCC 5.1.1 at -O2.
- Do not use alignof (FTSENT) here, since C11 prohibits
- taking the alignment of a structure containing a flexible
- array member. */
- len += alignof (max_align_t) - 1;
- len &= ~ (alignof (max_align_t) - 1);
+ len = FLEXSIZEOF(FTSENT, fts_name, namelen + 1);
if ((p = malloc(len)) == NULL)
return (NULL);
diff --git a/gl/lib/fts_.h b/gl/lib/fts_.h
index b9a3f12..70cc9e3 100644
--- a/gl/lib/fts_.h
+++ b/gl/lib/fts_.h
@@ -1,6 +1,6 @@
/* Traverse a file hierarchy.
- Copyright (C) 2004-2015 Free Software Foundation, Inc.
+ Copyright (C) 2004-2018 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
@@ -13,7 +13,7 @@
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 <http://www.gnu.org/licenses/>. */
+ along with this program. If not, see <https://www.gnu.org/licenses/>. */
/*
* Copyright (c) 1989, 1993
@@ -220,7 +220,11 @@ typedef struct _ftsent {
ptrdiff_t fts_level; /* depth (-1 to N) */
size_t fts_namelen; /* strlen(fts_name) */
- nlink_t fts_n_dirs_remaining; /* count down from st_nlink */
+
+ /* If not (nlink_t) -1, an upper bound on the number of
+ remaining subdirectories of interest. If this becomes
+ zero, some work can be avoided. */
+ nlink_t fts_n_dirs_remaining;
# define FTS_D 1 /* preorder directory */
# define FTS_DC 2 /* directory that causes cycles */
--
2.13.6
From ea88dd373c60feab541fe037369805f326dc3494 Mon Sep 17 00:00:00 2001
From: rpm-build <rpm-build>
Date: Mon, 12 Feb 2018 18:58:30 +0100
Subject: [PATCH 2/4] fts: remove dependency on gnulib's fleximember.h
... by reverting upstream commit edb9d82948cb23f67a19e1b435047a0570225df3
---
gl/lib/fts.c | 13 +++++++++++--
1 file changed, 11 insertions(+), 2 deletions(-)
diff --git a/gl/lib/fts.c b/gl/lib/fts.c
index bfa73e3..c37ebe2 100644
--- a/gl/lib/fts.c
+++ b/gl/lib/fts.c
@@ -71,7 +71,6 @@ static char sccsid[] = "@(#)fts.c 8.6 (Berkeley) 8/14/94";
#if ! _LIBC
# include "fcntl--.h"
-# include "flexmember.h"
# include "openat.h"
# include "same-inode.h"
#endif
@@ -1928,7 +1927,17 @@ fts_alloc (FTS *sp, const char *name, register size_t namelen)
* The file name is a variable length array. Allocate the FTSENT
* structure and the file name in one chunk.
*/
- len = FLEXSIZEOF(FTSENT, fts_name, namelen + 1);
+ len = offsetof(FTSENT, fts_name) + namelen + 1;
+ /* Align the allocation size so that it works for FTSENT,
+ so that trailing padding may be referenced by direct access
+ to the flexible array members, without triggering undefined behavior
+ by accessing bytes beyond the heap allocation. This implicit access
+ was seen for example with ISDOT() and GCC 5.1.1 at -O2.
+ Do not use alignof (FTSENT) here, since C11 prohibits
+ taking the alignment of a structure containing a flexible
+ array member. */
+ len += alignof (max_align_t) - 1;
+ len &= ~ (alignof (max_align_t) - 1);
if ((p = malloc(len)) == NULL)
return (NULL);
--
2.13.6
From 9c1720c99bbf8998dfdaa5976bca8bdc6d93f8e7 Mon Sep 17 00:00:00 2001
From: Paul Eggert <eggert@cs.ucla.edu>
Date: Thu, 5 Apr 2018 08:48:01 -0700
Subject: [PATCH 3/4] fts: treat CIFS like NFS
Problem reported by Kamil Dudka in:
https://lists.gnu.org/r/bug-gnulib/2018-04/msg00015.html
* lib/fts.c (S_MAGIC_CIFS): New macro.
(dirent_inode_sort_may_be_useful, leaf_optimization):
Treat CIFS like NFS.
Upstream-commit: 2e53df541a30d438859087ed4b5a396e04697b9b
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
---
gl/lib/fts.c | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/gl/lib/fts.c b/gl/lib/fts.c
index c37ebe2..508ceac 100644
--- a/gl/lib/fts.c
+++ b/gl/lib/fts.c
@@ -684,6 +684,7 @@ enum leaf_optimization
/* Linux-specific constants from coreutils' src/fs.h */
# define S_MAGIC_AFS 0x5346414F
+# define S_MAGIC_CIFS 0xFF534D42
# define S_MAGIC_NFS 0x6969
# define S_MAGIC_PROC 0x9FA0
# define S_MAGIC_REISERFS 0x52654973
@@ -791,8 +792,9 @@ dirent_inode_sort_may_be_useful (FTSENT const *p)
switch (filesystem_type (p))
{
- case S_MAGIC_TMPFS:
+ case S_MAGIC_CIFS:
case S_MAGIC_NFS:
+ case S_MAGIC_TMPFS:
/* On a file system of any of these types, sorting
is unnecessary, and hence wasteful. */
return false;
@@ -826,6 +828,10 @@ leaf_optimization (FTSENT const *p)
/* Although AFS mount points are not counted in st_nlink, they
act like directories. See <https://bugs.debian.org/143111>. */
FALLTHROUGH;
+ case S_MAGIC_CIFS:
+ /* Leaf optimization causes 'find' to abort. See
+ <https://lists.gnu.org/r/bug-gnulib/2018-04/msg00015.html>. */
+ FALLTHROUGH;
case S_MAGIC_NFS:
/* NFS provides usable dirent.d_type but not necessarily for all entries
of large directories, so as per <https://bugzilla.redhat.com/1252549>
--
2.14.3
From ff64329a046e76ba553c15373ed61bbed814d286 Mon Sep 17 00:00:00 2001
From: Paul Eggert <eggert@cs.ucla.edu>
Date: Wed, 11 Apr 2018 12:50:35 -0700
Subject: [PATCH 4/4] fts: fix bug in find across filesystems
This fixes a bug I introduced last summer.
Problem reported by Kamil Dudka in:
https://lists.gnu.org/r/bug-gnulib/2018-04/msg00033.html
* lib/fts.c (filesystem_type, dirent_inode_sort_may_be_useful)
(leaf_optimization):
New arg for file descriptor. All callers changed.
(fts_build): Check for whether inodes should be sorted
before closing the directory.
Upstream-commit: 81b8c0d3be98f5a77403599de3d06329b3e7673e
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
---
gl/lib/fts.c | 55 +++++++++++++++++++++++++++++++------------------------
1 file changed, 31 insertions(+), 24 deletions(-)
diff --git a/gl/lib/fts.c b/gl/lib/fts.c
index 508ceac..175f12a 100644
--- a/gl/lib/fts.c
+++ b/gl/lib/fts.c
@@ -725,11 +725,12 @@ dev_type_compare (void const *x, void const *y)
return ax->st_dev == ay->st_dev;
}
-/* Return the file system type of P, or 0 if not known.
+/* Return the file system type of P with file descriptor FD, or 0 if not known.
+ If FD is negative, P's file descriptor is unavailable.
Try to cache known values. */
static fsword
-filesystem_type (FTSENT const *p)
+filesystem_type (FTSENT const *p, int fd)
{
FTS *sp = p->fts_fts;
Hash_table *h = sp->fts_leaf_optimization_works_ht;
@@ -755,7 +756,7 @@ filesystem_type (FTSENT const *p)
}
/* Look-up failed. Query directly and cache the result. */
- if (fstatfs (p->fts_fts->fts_cwd_fd, &fs_buf) != 0)
+ if (fd < 0 || fstatfs (fd, &fs_buf) != 0)
return 0;
if (h)
@@ -777,12 +778,12 @@ filesystem_type (FTSENT const *p)
return fs_buf.f_type;
}
-/* Return false if it is easy to determine the file system type of the
- directory P, and sorting dirents on inode numbers is known not to
- improve traversal performance with that type of file system.
- Otherwise, return true. */
+/* Return true if sorting dirents on inode numbers is known to improve
+ traversal performance for the directory P with descriptor DIR_FD.
+ Return false otherwise. When in doubt, return true.
+ DIR_FD is negative if unavailable. */
static bool
-dirent_inode_sort_may_be_useful (FTSENT const *p)
+dirent_inode_sort_may_be_useful (FTSENT const *p, int dir_fd)
{
/* Skip the sort only if we can determine efficiently
that skipping it is the right thing to do.
@@ -790,7 +791,7 @@ dirent_inode_sort_may_be_useful (FTSENT const *p)
while the cost of *not* performing it can be O(N^2) with
a very large constant. */
- switch (filesystem_type (p))
+ switch (filesystem_type (p, dir_fd))
{
case S_MAGIC_CIFS:
case S_MAGIC_NFS:
@@ -804,16 +805,17 @@ dirent_inode_sort_may_be_useful (FTSENT const *p)
}
}
-/* Given an FTS entry P for a directory D,
+/* Given an FTS entry P for a directory with descriptor DIR_FD,
return true if it is both useful and valid to apply leaf optimization.
The optimization is useful only for file systems that lack usable
dirent.d_type info. The optimization is valid if an st_nlink value
of at least MIN_DIR_NLINK is an upper bound on the number of
- subdirectories of D, counting "." and ".." as subdirectories. */
+ subdirectories of D, counting "." and ".." as subdirectories.
+ DIR_FD is negative if unavailable. */
static enum leaf_optimization
-leaf_optimization (FTSENT const *p)
+leaf_optimization (FTSENT const *p, int dir_fd)
{
- switch (filesystem_type (p))
+ switch (filesystem_type (p, dir_fd))
{
/* List here the file system types that may lack usable dirent.d_type
info, yet for which the optimization does apply. */
@@ -850,12 +852,13 @@ leaf_optimization (FTSENT const *p)
#else
static bool
-dirent_inode_sort_may_be_useful (FTSENT const *p _GL_UNUSED)
+dirent_inode_sort_may_be_useful (FTSENT const *p _GL_UNUSED,
+ int dir_fd _GL_UNUSED)
{
return true;
}
static enum leaf_optimization
-leaf_optimization (FTSENT const *p _GL_UNUSED)
+leaf_optimization (FTSENT const *p _GL_UNUSED, int dir_fd _GL_UNUSED)
{
return NO_LEAF_OPTIMIZATION;
}
@@ -1049,7 +1052,7 @@ check_for_dir:
if (parent->fts_n_dirs_remaining == 0
&& ISSET(FTS_NOSTAT)
&& ISSET(FTS_PHYSICAL)
- && (leaf_optimization (parent)
+ && (leaf_optimization (parent, sp->fts_cwd_fd)
== NOSTAT_LEAF_OPTIMIZATION))
{
/* nothing more needed */
@@ -1334,6 +1337,7 @@ fts_build (register FTS *sp, int type)
int dir_fd;
FTSENT *cur = sp->fts_cur;
bool continue_readdir = !!cur->fts_dirp;
+ bool sort_by_inode = false;
size_t max_entries;
/* When cur->fts_dirp is non-NULL, that means we should
@@ -1427,7 +1431,7 @@ fts_build (register FTS *sp, int type)
&& ! (ISSET (FTS_NOSTAT) && ISSET (FTS_PHYSICAL)
&& ! ISSET (FTS_SEEDOT)
&& cur->fts_statp->st_nlink == MIN_DIR_NLINK
- && (leaf_optimization (cur)
+ && (leaf_optimization (cur, dir_fd)
!= NO_LEAF_OPTIMIZATION)));
if (descend || type == BREAD)
{
@@ -1588,6 +1592,15 @@ mem1: saved_errno = errno;
tail->fts_link = p;
tail = p;
}
+
+ /* If there are many entries, no sorting function has been
+ specified, and this file system is of a type that may be
+ slow with a large number of entries, arrange to sort the
+ directory entries on increasing inode numbers. */
+ if (nitems == _FTS_INODE_SORT_DIR_ENTRIES_THRESHOLD
+ && !sp->fts_compar)
+ sort_by_inode = dirent_inode_sort_may_be_useful (cur, dir_fd);
+
++nitems;
if (max_entries <= nitems) {
/* When there are too many dir entries, leave
@@ -1645,13 +1658,7 @@ mem1: saved_errno = errno;
return (NULL);
}
- /* If there are many entries, no sorting function has been specified,
- and this file system is of a type that may be slow with a large
- number of entries, then sort the directory entries on increasing
- inode numbers. */
- if (nitems > _FTS_INODE_SORT_DIR_ENTRIES_THRESHOLD
- && !sp->fts_compar
- && dirent_inode_sort_may_be_useful (cur)) {
+ if (sort_by_inode) {
sp->fts_compar = fts_compare_ino;
head = fts_sort (sp, head, nitems);
sp->fts_compar = NULL;
--
2.14.3

View File

@ -0,0 +1,142 @@
From 80cdfba079627e15129a926a133825b961d41e36 Mon Sep 17 00:00:00 2001
From: Paul Eggert <eggert@cs.ucla.edu>
Date: Mon, 5 Mar 2018 10:56:29 -0800
Subject: [PATCH] fflush: adjust to glibc 2.28 libio.h removal
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Problem reported by Daniel P. Berrangé in:
https://lists.gnu.org/r/bug-gnulib/2018-03/msg00000.html
* lib/fflush.c (clear_ungetc_buffer_preserving_position)
(disable_seek_optimization, rpl_fflush):
* lib/fpurge.c (fpurge):
* lib/freadahead.c (freadahead):
* lib/freading.c (freading):
* lib/fseeko.c (fseeko):
* lib/stdio-impl.h (_IO_IN_BACKUP) [_IO_EOF_SEEN]:
Define if not already defined.
Upstream-commit: 4af4a4a71827c0bc5e0ec67af23edef4f15cee8e
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
---
gl/lib/fflush.c | 6 +++---
gl/lib/fpurge.c | 2 +-
gl/lib/freadahead.c | 2 +-
gl/lib/freading.c | 2 +-
gl/lib/fseeko.c | 4 ++--
gl/lib/stdio-impl.h | 6 ++++++
6 files changed, 14 insertions(+), 8 deletions(-)
diff --git a/gl/lib/fflush.c b/gl/lib/fflush.c
index 5ae3e41..7a82470 100644
--- a/gl/lib/fflush.c
+++ b/gl/lib/fflush.c
@@ -33,7 +33,7 @@
#undef fflush
-#if defined _IO_ftrylockfile || __GNU_LIBRARY__ == 1 /* GNU libc, BeOS, Haiku, Linux libc5 */
+#if defined _IO_EOF_SEEN || __GNU_LIBRARY__ == 1 /* GNU libc, BeOS, Haiku, Linux libc5 */
/* Clear the stream's ungetc buffer, preserving the value of ftello (fp). */
static void
@@ -72,7 +72,7 @@ clear_ungetc_buffer (FILE *fp)
#endif
-#if ! (defined _IO_ftrylockfile || __GNU_LIBRARY__ == 1 /* GNU libc, BeOS, Haiku, Linux libc5 */)
+#if ! (defined _IO_EOF_SEEN || __GNU_LIBRARY__ == 1 /* GNU libc, BeOS, Haiku, Linux libc5 */)
# if (defined __sferror || defined __DragonFly__ || defined __ANDROID__) && defined __SNPT
/* FreeBSD, NetBSD, OpenBSD, DragonFly, Mac OS X, Cygwin, Android */
@@ -148,7 +148,7 @@ rpl_fflush (FILE *stream)
if (stream == NULL || ! freading (stream))
return fflush (stream);
-#if defined _IO_ftrylockfile || __GNU_LIBRARY__ == 1 /* GNU libc, BeOS, Haiku, Linux libc5 */
+#if defined _IO_EOF_SEEN || __GNU_LIBRARY__ == 1 /* GNU libc, BeOS, Haiku, Linux libc5 */
clear_ungetc_buffer_preserving_position (stream);
diff --git a/gl/lib/fpurge.c b/gl/lib/fpurge.c
index f313b22..ecdf82d 100644
--- a/gl/lib/fpurge.c
+++ b/gl/lib/fpurge.c
@@ -62,7 +62,7 @@ fpurge (FILE *fp)
/* Most systems provide FILE as a struct and the necessary bitmask in
<stdio.h>, because they need it for implementing getc() and putc() as
fast macros. */
-# if defined _IO_ftrylockfile || __GNU_LIBRARY__ == 1 /* GNU libc, BeOS, Haiku, Linux libc5 */
+# if defined _IO_EOF_SEEN || __GNU_LIBRARY__ == 1 /* GNU libc, BeOS, Haiku, Linux libc5 */
fp->_IO_read_end = fp->_IO_read_ptr;
fp->_IO_write_ptr = fp->_IO_write_base;
/* Avoid memory leak when there is an active ungetc buffer. */
diff --git a/gl/lib/freadahead.c b/gl/lib/freadahead.c
index 094daab..3f8101e 100644
--- a/gl/lib/freadahead.c
+++ b/gl/lib/freadahead.c
@@ -25,7 +25,7 @@
size_t
freadahead (FILE *fp)
{
-#if defined _IO_ftrylockfile || __GNU_LIBRARY__ == 1 /* GNU libc, BeOS, Haiku, Linux libc5 */
+#if defined _IO_EOF_SEEN || __GNU_LIBRARY__ == 1 /* GNU libc, BeOS, Haiku, Linux libc5 */
if (fp->_IO_write_ptr > fp->_IO_write_base)
return 0;
return (fp->_IO_read_end - fp->_IO_read_ptr)
diff --git a/gl/lib/freading.c b/gl/lib/freading.c
index 0512b19..8c48fe4 100644
--- a/gl/lib/freading.c
+++ b/gl/lib/freading.c
@@ -31,7 +31,7 @@ freading (FILE *fp)
/* Most systems provide FILE as a struct and the necessary bitmask in
<stdio.h>, because they need it for implementing getc() and putc() as
fast macros. */
-# if defined _IO_ftrylockfile || __GNU_LIBRARY__ == 1 /* GNU libc, BeOS, Haiku, Linux libc5 */
+# if defined _IO_EOF_SEEN || __GNU_LIBRARY__ == 1 /* GNU libc, BeOS, Haiku, Linux libc5 */
return ((fp->_flags & _IO_NO_WRITES) != 0
|| ((fp->_flags & (_IO_NO_READS | _IO_CURRENTLY_PUTTING)) == 0
&& fp->_IO_read_base != NULL));
diff --git a/gl/lib/fseeko.c b/gl/lib/fseeko.c
index 1c65d2a..9026408 100644
--- a/gl/lib/fseeko.c
+++ b/gl/lib/fseeko.c
@@ -47,7 +47,7 @@ fseeko (FILE *fp, off_t offset, int whence)
#endif
/* These tests are based on fpurge.c. */
-#if defined _IO_ftrylockfile || __GNU_LIBRARY__ == 1 /* GNU libc, BeOS, Haiku, Linux libc5 */
+#if defined _IO_EOF_SEEN || __GNU_LIBRARY__ == 1 /* GNU libc, BeOS, Haiku, Linux libc5 */
if (fp->_IO_read_end == fp->_IO_read_ptr
&& fp->_IO_write_ptr == fp->_IO_write_base
&& fp->_IO_save_base == NULL)
@@ -123,7 +123,7 @@ fseeko (FILE *fp, off_t offset, int whence)
return -1;
}
-#if defined _IO_ftrylockfile || __GNU_LIBRARY__ == 1 /* GNU libc, BeOS, Haiku, Linux libc5 */
+#if defined _IO_EOF_SEEN || __GNU_LIBRARY__ == 1 /* GNU libc, BeOS, Haiku, Linux libc5 */
fp->_flags &= ~_IO_EOF_SEEN;
fp->_offset = pos;
#elif defined __sferror || defined __DragonFly__ || defined __ANDROID__
diff --git a/gl/lib/stdio-impl.h b/gl/lib/stdio-impl.h
index 502d891..ea38ee2 100644
--- a/gl/lib/stdio-impl.h
+++ b/gl/lib/stdio-impl.h
@@ -18,6 +18,12 @@
the same implementation of stdio extension API, except that some fields
have different naming conventions, or their access requires some casts. */
+/* Glibc 2.28 made _IO_IN_BACKUP private. For now, work around this
+ problem by defining it ourselves. FIXME: Do not rely on glibc
+ internals. */
+#if !defined _IO_IN_BACKUP && defined _IO_EOF_SEEN
+# define _IO_IN_BACKUP 0x100
+#endif
/* BSD stdio derived implementations. */
--
2.16.2

View File

@ -0,0 +1,80 @@
From 80628047a6cc83f82e0c410a82b8f7facd9d50f2 Mon Sep 17 00:00:00 2001
From: Eric Blake <eblake@redhat.com>
Date: Wed, 14 Sep 2016 19:21:42 -0500
Subject: [PATCH] mountlist: include sysmacros.h for glibc
On Fedora rawhide (glibc 2.25), './gnulib-tool --test mountlist'
reports:
../../gllib/mountlist.c: In function 'read_file_system_list':
../../gllib/mountlist.c:534:13: warning: '__makedev_from_sys_types' is deprecated:
In the GNU C Library, `makedev' is defined by <sys/sysmacros.h>.
For historical compatibility, it is currently defined by
<sys/types.h> as well, but we plan to remove this soon.
To use `makedev', include <sys/sysmacros.h> directly.
If you did not intend to use a system-defined macro `makedev',
you should #undef it after including <sys/types.h>.
[-Wdeprecated-declarations]
me->me_dev = makedev (devmaj, devmin);
^~
In file included from /usr/include/features.h:397:0,
from /usr/include/sys/types.h:25,
from ./sys/types.h:28,
from ../../gllib/mountlist.h:23,
from ../../gllib/mountlist.c:20:
/usr/include/sys/sysmacros.h:89:1: note: declared here
__SYSMACROS_DEFINE_MAKEDEV (__SYSMACROS_FST_IMPL_TEMPL)
^
Fix it by including the right headers. We also need a fix to
autoconf's AC_HEADER_MAJOR, but that's a separate patch.
* m4/mountlist.m4 (gl_PREREQ_MOUTLIST_EXTRA): Include
AC_HEADER_MAJOR.
* lib/mountlist.c (includes): Use correct headers.
Signed-off-by: Eric Blake <eblake@redhat.com>
Upstream-commit: 4da63c5881f60f71999a943612da9112232b9161
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
---
gl/lib/mountlist.c | 6 ++++++
gl/m4/mountlist.m4 | 3 ++-
2 files changed, 8 insertions(+), 1 deletion(-)
diff --git a/gl/lib/mountlist.c b/gl/lib/mountlist.c
index c3d2852..0b6f92e 100644
--- a/gl/lib/mountlist.c
+++ b/gl/lib/mountlist.c
@@ -37,6 +37,12 @@
# include <sys/param.h>
#endif
+#if MAJOR_IN_MKDEV
+# include <sys/mkdev.h>
+#elif MAJOR_IN_SYSMACROS
+# include <sys/sysmacros.h>
+#endif
+
#if defined MOUNTED_GETFSSTAT /* OSF_1 and Darwin1.3.x */
# if HAVE_SYS_UCRED_H
# include <grp.h> /* needed on OSF V4.0 for definition of NGROUPS,
diff --git a/gl/m4/mountlist.m4 b/gl/m4/mountlist.m4
index ec58dc8..82b2dcb 100644
--- a/gl/m4/mountlist.m4
+++ b/gl/m4/mountlist.m4
@@ -1,4 +1,4 @@
-# serial 11
+# serial 12
dnl Copyright (C) 2002-2006, 2009-2015 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
@@ -15,5 +15,6 @@ AC_DEFUN([gl_PREREQ_MOUNTLIST_EXTRA],
[
dnl Note gl_LIST_MOUNTED_FILE_SYSTEMS checks for mntent.h, not sys/mntent.h.
AC_CHECK_HEADERS([sys/mntent.h])
+ AC_HEADER_MAJOR()dnl for use of makedev ()
gl_FSTYPENAME
])
--
2.16.2

View File

@ -0,0 +1,195 @@
From d844b7bbf3952998a906f21ba432aa62a3b9c7c6 Mon Sep 17 00:00:00 2001
From: Bernhard Voelker <mail@bernhard-voelker.de>
Date: Tue, 14 Jun 2016 20:49:42 +0200
Subject: [PATCH] Fix bug #48180: find: avoid segfault for internal '-noop'
option
The pseudo-option '-noop' was never meant to be exposed to the user
interface. If specified by the user, find(1) segfaulted.
Bug introduced in commit FINDUTILS_4_3_0-1-12-g6b8a4db.
* find/parser.c (struct parser_table): Rename the parser_name element of
the ARG_NOOP entry from 'noop' to '--noop', thus indicating its pure
internal character.
(found_parser): Return NULL when the user has passed the '---noop' option;
the caller does the error handling.
* find/testsuite/sv-48180-refuse-noop.sh: Add test.
* find/testsuite/Makefile.am (test_shell_progs): Reference the test.
* NEWS (Bug fixes): Document the fix.
Reported by Tavian Barnes <tavianator@tavianator.com> in
https://savannah.gnu.org/bugs/?48180
Upstream-commit: 595060f28eb5f658fa8d98970959c617fab0f078
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
---
find/parser.c | 6 +-
find/testsuite/Makefile.am | 3 +-
find/testsuite/sv-48180-refuse-noop.sh | 117 +++++++++++++++++++++++++++++++++
3 files changed, 124 insertions(+), 2 deletions(-)
create mode 100644 find/testsuite/sv-48180-refuse-noop.sh
diff --git a/find/parser.c b/find/parser.c
index 2d45349..697b2a2 100644
--- a/find/parser.c
+++ b/find/parser.c
@@ -321,7 +321,8 @@ static struct parser_table const parse_table[] =
*/
{ARG_TEST, "false", parse_false, pred_false}, /* GNU */
{ARG_TEST, "true", parse_true, pred_true }, /* GNU */
- {ARG_NOOP, "noop", NULL, pred_true }, /* GNU, internal use only */
+ /* Internal pseudo-option, therefore 3 minus: ---noop. */
+ {ARG_NOOP, "--noop", NULL, pred_true }, /* GNU, internal use only */
/* Various other cases that don't fit neatly into our macro scheme. */
{ARG_TEST, "help", parse_help, NULL}, /* GNU */
@@ -596,6 +597,9 @@ found_parser (const char *original_arg, const struct parser_table *entry)
*/
if (entry->type != ARG_POSITIONAL_OPTION)
{
+ if (entry->type == ARG_NOOP)
+ return NULL; /* internal use only, trap -noop here. */
+
/* Something other than -follow/-daystart.
* If this is an option, check if it followed
* a non-option and if so, issue a warning.
diff --git a/find/testsuite/Makefile.am b/find/testsuite/Makefile.am
index ab5dbe8..1371c70 100644
--- a/find/testsuite/Makefile.am
+++ b/find/testsuite/Makefile.am
@@ -259,7 +259,8 @@ test_escape_c.sh \
test_inode.sh \
sv-34079.sh \
sv-34976-execdir-fd-leak.sh \
-sv-48030-exec-plus-bug.sh
+sv-48030-exec-plus-bug.sh \
+sv-48180-refuse-noop.sh
EXTRA_DIST = $(EXTRA_DIST_EXP) $(EXTRA_DIST_XO) $(EXTRA_DIST_GOLDEN) \
$(test_shell_progs) binary_locations.sh checklists.py
diff --git a/find/testsuite/sv-48180-refuse-noop.sh b/find/testsuite/sv-48180-refuse-noop.sh
new file mode 100755
index 0000000..974f0f0
--- /dev/null
+++ b/find/testsuite/sv-48180-refuse-noop.sh
@@ -0,0 +1,117 @@
+#! /bin/sh
+# Copyright (C) 2016 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 <http://www.gnu.org/licenses/>.
+#
+
+# This test verifies that find refuses the internal -noop, ---noop option.
+# Between findutils-4.3.1 and 4.6, find dumped core ($? = 139).
+
+testname="$(basename $0)"
+
+. "${srcdir}"/binary_locations.sh
+
+die() {
+ echo "$@" >&2
+ exit 1
+}
+
+# This is used to simplify checking of the return value
+# which is useful when ensuring a command fails as desired.
+# I.e., just doing `command ... &&fail=1` will not catch
+# a segfault in command for example. With this helper you
+# instead check an explicit exit code like
+# returns_ 1 command ... || fail
+returns_ () {
+ # Disable tracing so it doesn't interfere with stderr of the wrapped command
+ { set +x; } 2>/dev/null
+
+ local exp_exit="$1"
+ shift
+ "$@"
+ test $? -eq $exp_exit && ret_=0 || ret_=1
+
+ set -x
+ { return $ret_; } 2>/dev/null
+}
+
+# Define the nicest compare available (borrowed from gnulib).
+if diff_out_=`exec 2>/dev/null; diff -u "$0" "$0" < /dev/null` \
+ && diff -u Makefile "$0" 2>/dev/null | grep '^[+]#!' >/dev/null; then
+ # diff accepts the -u option and does not (like AIX 7 'diff') produce an
+ # extra space on column 1 of every content line.
+ if test -z "$diff_out_"; then
+ compare () { diff -u "$@"; }
+ else
+ compare ()
+ {
+ if diff -u "$@" > diff.out; then
+ # No differences were found, but Solaris 'diff' produces output
+ # "No differences encountered". Hide this output.
+ rm -f diff.out
+ true
+ else
+ cat diff.out
+ rm -f diff.out
+ false
+ fi
+ }
+ fi
+elif diff_out_=`exec 2>/dev/null; diff -c "$0" "$0" < /dev/null`; then
+ if test -z "$diff_out_"; then
+ compare () { diff -c "$@"; }
+ else
+ compare ()
+ {
+ if diff -c "$@" > diff.out; then
+ # No differences were found, but AIX and HP-UX 'diff' produce output
+ # "No differences encountered" or "There are no differences between the
+ # files.". Hide this output.
+ rm -f diff.out
+ true
+ else
+ cat diff.out
+ rm -f diff.out
+ false
+ fi
+ }
+ fi
+elif cmp -s /dev/null /dev/null 2>/dev/null; then
+ compare () { cmp -s "$@"; }
+else
+ compare () { cmp "$@"; }
+fi
+
+set -x
+tmpdir="$(mktemp -d)" \
+ && cd "$tmpdir" \
+ || die "FAIL: failed to set up the test in ${tmpdir}"
+
+fail=0
+# Exercise both the previous name of the pseudo-option '-noop',
+# and the now renamed '---noop' option for both find executables.
+for exe in "${ftsfind}" "${oldfind}"; do
+ for opt in 'noop' '--noop'; do
+ out="${exe}${opt}.out"
+ err="${exe}${opt}.err"
+ returns_ 1 "$exe" "-${opt}" >"$out" 2> "$err" || fail=1
+ compare /dev/null "$out" || fail=1
+ grep "find: unknown predicate .-${opt}." "$err" \
+ || { cat "$err"; fail=1; }
+ done
+done
+
+cd ..
+rm -rf "$tmpdir" || exit 1
+exit $fail
--
2.5.5

View File

@ -0,0 +1,83 @@
From 1328926a705fdb4728c1f255dd368de928736d39 Mon Sep 17 00:00:00 2001
From: Kamil Dudka <kdudka@redhat.com>
Date: Fri, 25 Sep 2015 16:09:39 +0200
Subject: [PATCH 1/2] fts: introduce the FTS_NOLEAF flag
The flag is needed to implement the -noleaf option of find.
* lib/fts.c (link_count_optimize_ok): Implement the FTS_NOLEAF flag.
* lib/fts_.h (FTS_NOLEAF): New macro, shifted conflicting constants.
---
gl/lib/fts.c | 4 ++++
gl/lib/fts_.h | 12 +++++++++---
2 files changed, 13 insertions(+), 3 deletions(-)
diff --git a/gl/lib/fts.c b/gl/lib/fts.c
index d2d404f..808466f 100644
--- a/gl/lib/fts.c
+++ b/gl/lib/fts.c
@@ -736,6 +736,10 @@ filesystem_type (FTSENT const *p)
struct dev_type *ent;
struct statfs fs_buf;
+ if (ISSET(FTS_NOLEAF))
+ /* leaf optimization explicitly disabled by the FTS_NOLEAF flag */
+ return 0;
+
/* If we're not in CWDFD mode, don't bother with this optimization,
since the caller is not serious about performance. */
if (!ISSET (FTS_CWDFD))
diff --git a/gl/lib/fts_.h b/gl/lib/fts_.h
index 63d4b74..f1d519b 100644
--- a/gl/lib/fts_.h
+++ b/gl/lib/fts_.h
@@ -155,10 +155,16 @@ typedef struct {
from input path names during fts_open initialization. */
# define FTS_VERBATIM 0x1000
-# define FTS_OPTIONMASK 0x1fff /* valid user option mask */
+ /* Disable leaf optimization (which eliminates stat() calls during traversal,
+ based on the count of nested directories stored in stat.st_nlink of each
+ directory). Note that the optimization is by default enabled only for
+ selected file systems, and only if the FTS_CWDFD flag is set. */
+# define FTS_NOLEAF 0x2000
-# define FTS_NAMEONLY 0x2000 /* (private) child names only */
-# define FTS_STOP 0x4000 /* (private) unrecoverable error */
+# define FTS_OPTIONMASK 0x3fff /* valid user option mask */
+
+# define FTS_NAMEONLY 0x4000 /* (private) child names only */
+# define FTS_STOP 0x8000 /* (private) unrecoverable error */
int fts_options; /* fts_open options, global flags */
/* Map a directory's device number to a boolean. The boolean is
--
2.5.0
From c186934e6e37ddadf7511abb9b1045192757618e Mon Sep 17 00:00:00 2001
From: Kamil Dudka <kdudka@redhat.com>
Date: Fri, 25 Sep 2015 19:13:15 +0200
Subject: [PATCH 2/2] ftsfind: propagate the -noleaf option to FTS
* find/ftsfind.c (find): Propagate the -noleaf option to FTS.
---
find/ftsfind.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/find/ftsfind.c b/find/ftsfind.c
index 5159470..e34b672 100644
--- a/find/ftsfind.c
+++ b/find/ftsfind.c
@@ -559,6 +559,9 @@ find (char *arg)
if (options.stay_on_filesystem)
ftsoptions |= FTS_XDEV;
+ if (options.no_leaf_check)
+ ftsoptions |= FTS_NOLEAF;
+
p = fts_open (arglist, ftsoptions, NULL);
if (NULL == p)
{
--
2.5.0

View File

@ -0,0 +1,44 @@
From a8ff1e964b2b8cd0b60362c76bd92795cee6b3c3 Mon Sep 17 00:00:00 2001
From: Kamil Dudka <kdudka@redhat.com>
Date: Sun, 17 Apr 2016 22:36:13 +0200
Subject: [PATCH] doc: clarify exit status handling of -exec command {} +
* find/find.1 (-exec): Explain how exit status is propagated if the
-exec command {} + syntax is used.
(-execdir): Likewise.
Reported at https://bugzilla.redhat.com/1325049
Upstream-commit: ae424b959c5e9bd23f9f686cb34653bc4cd1270e
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
---
find/find.1 | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/find/find.1 b/find/find.1
index a36a0bc..c4aaf17 100644
--- a/find/find.1
+++ b/find/find.1
@@ -1069,6 +1069,9 @@ command line is built in much the same way that
.B xargs
builds its command lines. Only one instance of `{}' is allowed within
the command. The command is executed in the starting directory. If
+any invocation returns a non-zero value as exit status, then
+.B find
+returns a non-zero exit status. If
.B find
encounters an error, this can sometimes cause an
immediate exit, so some pending commands may not be run
@@ -1104,6 +1107,9 @@ appropriately-named file in a directory in which you will run
The same applies to having entries in
.B $PATH
which are empty or which are not absolute directory names. If
+any invocation returns a non-zero value as exit status, then
+.B find
+returns a non-zero exit status. If
.B find
encounters an error, this can sometimes cause an
immediate exit, so some pending commands may not be run
--
2.5.5

View File

@ -0,0 +1,35 @@
From 06a46ba755195810f2aeda01b12d1ccfe7c2dcfd Mon Sep 17 00:00:00 2001
From: Daiki Ueno <ueno@gnu.org>
Date: Mon, 28 Dec 2015 06:27:42 +0900
Subject: [PATCH] maint: fix operator precedence in mbrtowc test
This is a fix for test breakage introduced by commit 45228d96; the
equality expression must be parenthesized when negated with '!',
otherwise we always get:
test-mbrtowc.c:49: assertion 'ret == (size_t)(-2)' failed
* m4/mbrtowc.m4 (gl_MBRTOWC_EMPTY_INPUT): Negate the entire expression.
Upstream-commit: 1f63650823cebf52044df840c81062ccb52163a2
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
---
gl/m4/mbrtowc.m4 | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/gl/m4/mbrtowc.m4 b/gl/m4/mbrtowc.m4
index deb9f06..be2e9d6 100644
--- a/gl/m4/mbrtowc.m4
+++ b/gl/m4/mbrtowc.m4
@@ -569,7 +569,7 @@ changequote([,])dnl
int
main (void)
{
- return ! mbrtowc (&wc, "", 0, &mbs) == (size_t) -2;
+ return mbrtowc (&wc, "", 0, &mbs) != (size_t) -2;
}]])],
[gl_cv_func_mbrtowc_empty_input=yes],
[gl_cv_func_mbrtowc_empty_input=no],
--
2.5.0

View File

@ -0,0 +1,29 @@
From 129f23ce758620fade812baab811379ce8454048 Mon Sep 17 00:00:00 2001
From: rpm-build <rpm-build>
Date: Fri, 27 Jan 2017 11:44:41 +0100
Subject: [PATCH] test-lock: disable the rwlock test
It hangs indefinitely if the system rwlock implementation does not
prevent writer starvation (and glibc does not implement it).
Bug: http://www.mail-archive.com/bug-gnulib@gnu.org/msg33017.html
---
tests/test-lock.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tests/test-lock.c b/tests/test-lock.c
index a992f64..fd9c014 100644
--- a/tests/test-lock.c
+++ b/tests/test-lock.c
@@ -42,7 +42,7 @@
Uncomment some of these, to verify that all tests crash if no locking
is enabled. */
#define DO_TEST_LOCK 1
-#define DO_TEST_RWLOCK 1
+#define DO_TEST_RWLOCK 0
#define DO_TEST_RECURSIVE_LOCK 1
#define DO_TEST_ONCE 1
--
2.7.4

BIN
findutils-4.6.0.tar.gz Normal file

Binary file not shown.

152
findutils.spec Normal file
View File

@ -0,0 +1,152 @@
Name: findutils
Epoch: 2
Version: 4.6.0
Release: 3
Summary: The GNU Find Utilities
License: GPLv3+
URL: http://www.gnu.org/software/findutils/
Source0: https://ftp.gnu.org/pub/gnu/findutils/%{name}-%{version}.tar.gz
# prevent mbrtowc tests from failing (#1294016)
Patch0: findutils-4.6.0-mbrtowc-tests.patch
# do not build locate
Patch1: findutils-4.5.15-no-locate.patch
# fix build failure with glibc-2.28
# https://lists.gnu.org/r/bug-gnulib/2018-03/msg00000.html
Patch2: findutils-4.6.0-gnulib-fflush.patch
# add a new option -xautofs to find to not descend into directories on autofs
# file systems
Patch3: findutils-4.4.2-xautofs.patch
# eliminate compile-time warnings
Patch4: findutils-4.5.13-warnings.patch
# clarify exit status handling of -exec cmd {} + in find(1) man page (#1325049)
Patch5: findutils-4.6.0-man-exec.patch
# make sure that find -exec + passes all arguments (upstream bug #48030)
Patch6: findutils-4.6.0-exec-args.patch
# fix build failure with glibc-2.25+
Patch7: findutils-4.6.0-gnulib-makedev.patch
# avoid SIGSEGV in case the internal -noop option is used (#1346471)
Patch9: findutils-4.6.0-internal-noop.patch
# test-lock: disable the rwlock test
Patch10: findutils-4.6.0-test-lock.patch
# import gnulib's FTS module from upstream commit 281b825e (#1544429)
Patch11: findutils-4.6.0-fts-update.patch
# implement the -noleaf option of find (#1252549)
Patch12: findutils-4.6.0-leaf-opt.patch
#upstream patches
Patch6000: Remove-the-enable-id-cache-configure-option.patch
Patch6001: find-Fix-a-number-of-compiler-warnings-mostly-const-.patch
Patch6002: lib-Update-the-width-of-the-st_nlink-field-and-fix-s.patch
Patch6003: regexprops-Fix-compiler-warnings-and-update-copyrigh.patch
Patch6004: Fix-bug-48314-find-fix-type-option-regression-on-som.patch
Patch6005: maint-remove-ChangeLog-2013-from-distribution-tarbal.patch
Patch6006: find-handle-more-readdir-3-errors.patch
Patch6007: find-fix-memory-leak-in-mount-list-handling.patch
Patch6008: find-fix-printf-h-for-arguments-with-one-or-more-tra.patch
Patch6009: xargs-add-o-open-tty-option.patch
Patch6010: find-avoid-strftime-s-non-portable-F-specifier.patch
Patch6011: find-avoid-usage-in-more-error-cases.patch
Patch6012: find-give-helpful-hint-for-unquoted-patterns-errors.patch
Patch6013: find-avoid-buffer-overflow-with-printf-T.patch
Patch6014: regexprops-fix-dangling-reference-to-the-ed-regular-.patch
Patch6015: find-make-delete-honour-the-ignore_readdir_race-opti.patch
Patch6016: Shorten-output-of-qmark_chars-after-replacing-a-mult.patch
Patch6017: find-process-unreadable-directories-with-depth.patch
Patch6018: ftsfind.c-avoid-buffer-overflow-in-D-code.patch
Patch6019: find-fix-printf-Y-output-to-N-for-broken-links.patch
Patch6020: print.c-move-else-into-ifdef-S_ISLNK.patch
Patch6021: find-printf-Y-handle-ENOTDIR-also-as-broken-symlink.patch
Patch6022: find-improve-warning-diagnostic-for-the-name-iname-w.patch
Patch6023: find-make-pred_empty-safer-and-avoid-fd-leaks.patch
Buildrequires: gcc autoconf
Provides: /bin/find
Provides: bundled(gnulib)
%description
The GNU Find Utilities are the basic directory searching utilities of
the GNU operating system. These programs are typically used in
conjunction with other programs to provide modular and powerful
directory search and file locating capabilities to other commands.
The tools supplied with this package are:
find - search for files in a directory hierarchy
locate - list files in databases that match a pattern
updatedb - update a file name database
xargs - build and execute command lines from standard input
%package_help
%prep
%autosetup -n %{name}-%{version} -p1
# needed because of findutils-4.5.15-no-locate.patch
autoreconf -fiv
%build
%configure
%make_build
%check
make check
%install
%make_install
rm -f %{buildroot}%{_infodir}/dir
%find_lang %{name}
%pre
%preun help
if [ $1 = 0 ]; then
if [ -f %{_infodir}/find.info.gz ]; then
/sbin/install-info --delete %{_infodir}/find.info.gz %{_infodir}/dir || :
fi
fi
%post help
if [ -f %{_infodir}/find.info.gz ]; then
/sbin/install-info %{_infodir}/find.info.gz %{_infodir}/dir || :
fi
%postun
%files -f %{name}.lang
%doc AUTHORS NEWS README THANKS TODO
%license COPYING
%{_bindir}/find
%{_bindir}/xargs
%files help
%{_mandir}/man1/find.1*
%{_mandir}/man1/xargs.1*
%{_infodir}/find.info*
%{_infodir}/find-maint.info.gz
%changelog
* Tue Sep 24 2019 openEuler Buildteam <buildteam@openeuler.org> - 2:4.6.0-3
- Adjust requires
* Fri Sep 20 2019 openEuler Buildteam <buildteam@openeuler.org> - 2:4.6.0-2
- Delete redundant information
* Thu Aug 29 2019 openEuler Buildteam <buildteam@openeuler.org> - 2:4.6.0-1
- Package init

View File

@ -0,0 +1,41 @@
From c7344d33587bc5b781b958315c643284e2e9cf18 Mon Sep 17 00:00:00 2001
From: Bernhard Voelker <mail@bernhard-voelker.de>
Date: Sun, 8 Jul 2018 00:18:03 +0200
Subject: [PATCH 178/224] ftsfind.c: avoid buffer overflow in -D code
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Reported by GCC 8.1.1:
ftsfind.c: In function get_fts_info_name:
ftsfind.c:164:23: warning: %d directive writing between 1 and 11 bytes into a region of size 9 [-Wformat-overflow=]
sprintf (buf, "[%d]", info);
^~
ftsfind.c:164:7: note: sprintf output between 4 and 14 bytes into a destination of size 10
sprintf (buf, "[%d]", info);
^~~~~~~~~~~~~~~~~~~~~~~~~~~
* find/ftsfind.c (get_fts_info_name): Increase buffer from 10 to 14
to be able to hold the 11-char string representation of the %d format,
the surrounding '[' and ']', plus the terminating NULL character.
---
find/ftsfind.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/find/ftsfind.c b/find/ftsfind.c
index 607ea8d3..57804950 100644
--- a/find/ftsfind.c
+++ b/find/ftsfind.c
@@ -143,7 +143,7 @@ static void init_mounted_dev_list (void);
static const char *
get_fts_info_name (int info)
{
- static char buf[10];
+ static char buf[14];
switch (info)
{
HANDLECASE(FTS_D);
--
2.19.1

View File

@ -0,0 +1,89 @@
From 7ce6b131573accf4fbc4b2c26794fb90f6b1a44e Mon Sep 17 00:00:00 2001
From: James Youngman <jay@gnu.org>
Date: Sat, 2 Jan 2016 22:58:59 +0000
Subject: [PATCH 025/224] lib: Update the width of the st_nlink field and fix
some compiler warnings.
* lib/listfile.h (list_file): Make the relname parameter const.
* lib/listfile.c (list_file): Make the relname parameter const.
Remove the unused local variable inode_field_width. Update
nlink_width with the greatest width of the st_nlink field, and
print the field using the maximum width (as we do for other
fields).
---
lib/listfile.c | 27 ++++++++++++++++++++++++---
lib/listfile.h | 2 +-
2 files changed, 25 insertions(+), 4 deletions(-)
diff --git a/lib/listfile.c b/lib/listfile.c
index 4b7d4b22..c6c86091 100644
--- a/lib/listfile.c
+++ b/lib/listfile.c
@@ -111,7 +111,7 @@ static bool print_num(FILE *stream, unsigned long num, int *width)
void
list_file (const char *name,
int dir_fd,
- char *relname,
+ const char *relname,
const struct stat *statp,
time_t current_time,
int output_block_size,
@@ -126,7 +126,6 @@ list_file (const char *name,
bool output_good = true;
int chars_out;
int failed_at = 000;
- int inode_field_width;
#if HAVE_ST_DM_MODE
/* Cray DMF: look at the file's migrated, not real, status */
@@ -179,13 +178,35 @@ list_file (const char *name,
output_good = false;
failed_at = 250;
}
+ }
+ if (output_good)
+ {
/* modebuf includes the space between the mode and the number of links,
as the POSIX "optional alternate access method flag". */
- if (fprintf (stream, "%s%3lu ", modebuf, (unsigned long) statp->st_nlink) < 0)
+ if (fputs (modebuf, stream) < 0)
+ {
+ output_good = false;
+ failed_at = 275;
+ }
+ }
+ if (output_good)
+ {
+ /* This format used to end in a space, but the output of "ls"
+ has only one space between the link count and the owner 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);
+ if (chars_out < 0)
{
output_good = false;
failed_at = 300;
}
+ else
+ {
+ if (chars_out > nlink_width)
+ nlink_width = chars_out;
+ }
}
if (output_good)
diff --git a/lib/listfile.h b/lib/listfile.h
index 9ee71a2d..2e151659 100644
--- a/lib/listfile.h
+++ b/lib/listfile.h
@@ -19,5 +19,5 @@
#if !defined LISTFILE_H
# define LISTFILE_H
-void list_file (const char *name, int dir_fd, char *relname, const struct stat *statp, time_t current_time, int output_block_size, int literal_control_chars, FILE *stream);
+void list_file (const char *name, int dir_fd, const char *relname, const struct stat *statp, time_t current_time, int output_block_size, int literal_control_chars, FILE *stream);
#endif
--
2.19.1

View File

@ -0,0 +1,31 @@
From f70469712165524b6ba92bf5dc60ad9be70546cb Mon Sep 17 00:00:00 2001
From: Bernhard Voelker <mail@bernhard-voelker.de>
Date: Tue, 1 Nov 2016 16:34:31 +0100
Subject: [PATCH 078/224] maint: remove ChangeLog-2013 from distribution
tarball
* Makefile.am (EXTRA_DIST): Remove ChangeLog-2013, as its content is
shipped in the generated ChangeLog file.
Reported by Steve in
http://lists.gnu.org/archive/html/bug-findutils/2016-10/msg00000.html
---
Makefile.am | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Makefile.am b/Makefile.am
index 410ee3d5..c31e7f03 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -2,7 +2,7 @@ AUTOMAKE_OPTIONS=gnits
# readme-alpha
AM_CFLAGS = $(WARN_CFLAGS)
-EXTRA_DIST = COPYING ChangeLog ChangeLog-2013 TODO config.h.in stamp-h.in \
+EXTRA_DIST = COPYING ChangeLog TODO config.h.in stamp-h.in \
THANKS bootstrap \
tool-versions.txt README-hacking
DISTCLEANFILES = tool-versions.txt
--
2.19.1

View File

@ -0,0 +1,31 @@
From 88fc3a464476721c3f3631d56d441dff7c9e2479 Mon Sep 17 00:00:00 2001
From: Bernhard Voelker <mail@bernhard-voelker.de>
Date: Fri, 20 Jul 2018 10:27:56 +0200
Subject: [PATCH 183/224] print.c: move 'else' into #ifdef S_ISLNK
* find/print.c (do_fprintf): Move the 'else' statment into the #ifdef'ed
block to avoid compilation failure on systems without S_ISLNK (although
it seems nobody tried to build on such a platform since 2005).
Bug introduced in commit 'FINDUTILS_4_2_23-1-63-g238d9547'.
---
find/print.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/find/print.c b/find/print.c
index 545df96a..24bd9692 100644
--- a/find/print.c
+++ b/find/print.c
@@ -1205,8 +1205,8 @@ do_fprintf (struct format_val *dest,
checked_fprintf (dest, segment->text,
mode_to_filetype (sbuf.st_mode & S_IFMT));
}
-#endif /* S_ISLNK */
else
+#endif /* S_ISLNK */
{
checked_fprintf (dest, segment->text,
mode_to_filetype (stat_buf->st_mode & S_IFMT));
--
2.19.1

View File

@ -0,0 +1,87 @@
From c83e75f548369e38e8f4c369717000552a8a1cdf Mon Sep 17 00:00:00 2001
From: James Youngman <jay@gnu.org>
Date: Sun, 3 Jan 2016 23:20:54 +0000
Subject: [PATCH 030/224] regexprops: Fix compiler warnings and update
copyright years.
* lib/regexprops.c (newpara): Function parameter list should be
declared as void in the function definition, instead of leaving it
blank (C++ style). This fixes a GCC warning controlled by
-Wstrict-prototypes.
(beginenum): Likewise.
(endenum): Likewise.
(endtable): Likewise.
(copying): Update copyright years.
* doc/regexprops.texi: Update copyright years to match the output
of regexprops.c.
---
doc/regexprops.texi | 4 ++--
lib/regexprops.c | 12 ++++++------
2 files changed, 8 insertions(+), 8 deletions(-)
diff --git a/doc/regexprops.texi b/doc/regexprops.texi
index 537b64e0..897a492d 100644
--- a/doc/regexprops.texi
+++ b/doc/regexprops.texi
@@ -1,5 +1,5 @@
-@c Copyright (C) 1994, 1996, 1998, 2000, 2001, 2003, 2004, 2005, 2006,
-@c 2007, 2009, 2010, 2011 Free Software Foundation, Inc.
+@c Copyright (C) 1994, 1996, 1998, 2000-2007, 2009-2011,
+@c 2015-2016 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
diff --git a/lib/regexprops.c b/lib/regexprops.c
index 3409b4c4..2327a646 100644
--- a/lib/regexprops.c
+++ b/lib/regexprops.c
@@ -127,7 +127,7 @@ begintable_markup (char const *markup)
}
static void
-endtable ()
+endtable (void)
{
newline ();
directive ("@end table");
@@ -135,7 +135,7 @@ endtable ()
}
static void
-beginenum ()
+beginenum (void)
{
newline ();
directive ("@enumerate");
@@ -143,7 +143,7 @@ beginenum ()
}
static void
-endenum ()
+endenum (void)
{
newline ();
directive ("@end enumerate");
@@ -151,7 +151,7 @@ endenum ()
}
static void
-newpara ()
+newpara (void)
{
content ("\n\n");
}
@@ -453,8 +453,8 @@ copying (void)
{
static const char *copy_para[]=
{
- "Copyright (C) 1994, 1996, 1998, 2000, 2001, 2003, 2004, 2005, 2006,"
- ,"2007, 2009, 2010, 2011 Free Software Foundation, Inc."
+ "Copyright (C) 1994, 1996, 1998, 2000-2007, 2009-2011,"
+ ,"2015-2016 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.19.1

View File

@ -0,0 +1,970 @@
From e2c673cbcdc325a3a2e9dd02169bb4a42c61bc48 Mon Sep 17 00:00:00 2001
From: James Youngman <jay@gnu.org>
Date: Mon, 13 Nov 2017 22:37:55 +0000
Subject: [PATCH 144/224] regexprops: fix dangling reference to the `ed'
regular expression dialect.
* lib/regextype.c (regex_map): Permute the entries to list POSIX
dialects before other ones, so that we don't end up with a
dangling reference to `ed' regular expressions when
context=findutils. Remove trailing white space from the output.
* doc/regexprops.texi: Regenerate this file, so that we no longer
have a dangling reference to the `ed' dialect.
* doc/find.texi (Regular Expressions): Point out the difference
between Emacs regular expressions and findutils regular
expressions: in findutils "." will match newline.
* find/find.1: Likewise.
* locate/locate.1: Likewise. Also document the --regextype option.
---
doc/find.texi | 7 +-
doc/regexprops.texi | 376 ++++++++++++++++++++++++++++----------------
find/find.1 | 4 +-
lib/regexprops.c | 74 ++++-----
lib/regextype.c | 14 +-
locate/locate.1 | 14 +-
6 files changed, 306 insertions(+), 183 deletions(-)
diff --git a/doc/find.texi b/doc/find.texi
index 2731f0af..5573d29b 100644
--- a/doc/find.texi
+++ b/doc/find.texi
@@ -3917,8 +3917,11 @@ your locale setup affects the interpretation of regular expressions.
There are also several different types of regular expression, and
these are interpreted differently. Normally, the type of regular
-expression used by @code{find} and @code{locate} is the same as is
-used in GNU Emacs. Both programs provide an option which allows you
+expression used by @code{find} and @code{locate} is almost identical to
+that used in GNU Emacs. The single difference is that in @code{find}
+and @code{locate}, a @samp{.} will match a newline character.
+
+Both @code{find} and @code{locate} provide an option which allows you
to select an alternative regular expression syntax; for @code{find}
this is the @samp{-regextype} option, and for @code{locate} this is
the @samp{--regextype} option.
diff --git a/doc/regexprops.texi b/doc/regexprops.texi
index 8fee88ae..0229460e 100644
--- a/doc/regexprops.texi
+++ b/doc/regexprops.texi
@@ -11,15 +11,15 @@
@menu
* findutils-default regular expression syntax::
+* posix-awk regular expression syntax::
+* posix-basic regular expression syntax::
+* posix-egrep regular expression syntax::
+* posix-extended 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::
-* posix-basic regular expression syntax::
-* posix-egrep regular expression syntax::
-* posix-extended regular expression syntax::
@end menu
@node findutils-default regular expression syntax
@@ -44,6 +44,7 @@ matches a @samp{?}.
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:]]}.
+
GNU extensions are supported:
@enumerate
@@ -73,11 +74,10 @@ The alternation operator is @samp{\|}.
The character @samp{^} only represents the beginning of a string when it appears:
@enumerate
-@item
-At the beginning of a regular expression
+@item At the beginning of a regular expression
+
+@item After an open-group, signified by @samp{\(}
-@item After an open-group, signified by
-@samp{\(}
@item After the alternation operator @samp{\|}
@@ -89,8 +89,8 @@ The character @samp{$} only represents the end of a string when it appears:
@item At the end of a regular expression
-@item Before a close-group, signified by
-@samp{\)}
+@item Before a close-group, signified by @samp{\)}
+
@item Before the alternation operator @samp{\|}
@end enumerate
@@ -101,8 +101,8 @@ The character @samp{$} only represents the end of a string when it appears:
@item At the beginning of a regular expression
-@item After an open-group, signified by
-@samp{\(}
+@item After an open-group, signified by @samp{\(}
+
@item After the alternation operator @samp{\|}
@end enumerate
@@ -113,8 +113,8 @@ The character @samp{$} only represents the end of a string when it appears:
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
+@node posix-awk regular expression syntax
+@subsection @samp{posix-awk} regular expression syntax
The character @samp{.} matches any single character except the null character.
@@ -135,53 +135,57 @@ matches a @samp{?}.
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.
+
+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.
-@samp{*}, @samp{+} and @samp{?} are special at any point in a regular expression except:
+
+@samp{*}, @samp{+} and @samp{?} are special at any point in a regular expression except the following places, where they are not allowed:
@enumerate
@item At the beginning of a regular expression
-@item After an open-group, signified by
-@samp{(}
+@item After an open-group, signified by @samp{(}
+
@item After the alternation operator @samp{|}
@end enumerate
-
+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
+@node posix-basic regular expression syntax
+@subsection @samp{posix-basic} regular expression syntax
-The character @samp{.} matches any single character.
+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{+}
+indicates that the regular expression should match one or more occurrences of the previous atom or regexp.
@item \?
-matches a @samp{?}.
+indicates that the regular expression should match zero or one occurrence of the previous atom or regexp.
+@item + and ?
+match themselves.
+
@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
@@ -204,24 +208,59 @@ GNU extensions are supported:
@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{(}.
+Grouping is performed with backslashes followed by parentheses @samp{\(}, @samp{\)}. 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 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 character @samp{^} only represents the beginning of a string when it appears:
+@enumerate
-The characters @samp{*}, @samp{+} and @samp{?} are special anywhere in a regular expression.
+@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 character @samp{$} only represents the end of a string when it appears:
+@enumerate
+
+@item At the end of a regular expression
+
+@item Before a close-group, signified by @samp{\)}
+
+@item Before the alternation operator @samp{\|}
+
+@end enumerate
+
+
+@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
+
+
+Intervals are specified by @samp{\@{} and @samp{\@}}.
+Invalid intervals such as @samp{a\@{1z} are not accepted.
-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
+@node posix-egrep regular expression syntax
+@subsection @samp{posix-egrep} regular expression syntax
-The character @samp{.} matches any single character except newline.
+The character @samp{.} matches any single character.
@table @samp
@@ -237,7 +276,8 @@ 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 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
@@ -261,58 +301,27 @@ GNU extensions are supported:
@end enumerate
-Grouping is performed with backslashes followed by parentheses @samp{\(}, @samp{\)}. 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 character @samp{^} only represents the beginning of a string when it appears:
-@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 character @samp{$} only represents the end of a string when it appears:
-@enumerate
-
-@item At the end of a regular expression
-
-@item Before a close-group, signified by
-@samp{\)}
-@item Before the alternation operator @samp{\|}
-
-@end enumerate
-
-
-@samp{*}, @samp{+} and @samp{?} are special at any point in a regular expression except:
-@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{(}.
-@item At the beginning of a regular expression
+The alternation operator is @samp{|}.
-@item After an open-group, signified by
-@samp{\(}
-@item After the alternation operator @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.
-@end enumerate
+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 gnu-awk regular expression syntax
-@subsection @samp{gnu-awk} regular expression syntax
+@node posix-extended regular expression syntax
+@subsection @samp{posix-extended} regular expression syntax
-The character @samp{.} matches any single character.
+The character @samp{.} matches any single character except the null character.
@table @samp
@@ -328,7 +337,8 @@ 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.
+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
@@ -358,42 +368,101 @@ 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:
+
+@samp{*}, @samp{+} and @samp{?} are special at any point in a regular expression except the following places, where they are not allowed:
@enumerate
@item At the beginning of a regular expression
-@item After an open-group, signified by
-@samp{(}
+@item After an open-group, signified by @samp{(}
+
@item After the alternation operator @samp{|}
@end enumerate
-Intervals are specified by @samp{@{} and @samp{@}}. Invalid intervals are treated as literals, for example @samp{a@{1} is treated as @samp{a\@{1}
+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 grep regular expression syntax
-@subsection @samp{grep} regular expression syntax
+@node awk regular expression syntax
+@subsection @samp{awk} regular expression syntax
-The character @samp{.} matches any single character.
+The character @samp{.} matches any single character except the null character.
@table @samp
-@item \+
+@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
+This is a synonym for posix-egrep.
+@node emacs regular expression syntax
+@subsection @samp{emacs} regular expression syntax
+
+
+The character @samp{.} matches any single character except newline.
+
+
+@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 + and ?
-match themselves.
+@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.
+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:]]}.
+
GNU extensions are supported:
@enumerate
@@ -424,13 +493,10 @@ The alternation operator is @samp{\|}.
The character @samp{^} only represents the beginning of a string when it appears:
@enumerate
-@item
-At the beginning of a regular expression
+@item At the beginning of a regular expression
-@item After an open-group, signified by
-@samp{\(}
+@item After an open-group, signified by @samp{\(}
-@item After a newline
@item After the alternation operator @samp{\|}
@@ -442,39 +508,35 @@ The character @samp{$} only represents the end of a string when it appears:
@item At the end of a regular expression
-@item Before a close-group, signified by
-@samp{\)}
-@item Before a newline
+@item Before a close-group, signified by @samp{\)}
@item Before the alternation operator @samp{\|}
@end enumerate
-@samp{\*}, @samp{\+} and @samp{\?} are special at any point in a regular expression except:
+@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 a newline
+@item After an open-group, signified by @samp{\(}
@item After the alternation operator @samp{\|}
@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 posix-awk regular expression syntax
-@subsection @samp{posix-awk} regular expression syntax
+@node gnu-awk regular expression syntax
+@subsection @samp{gnu-awk} regular expression syntax
-The character @samp{.} matches any single character except the null character.
+The character @samp{.} matches any single character.
@table @samp
@@ -492,7 +554,28 @@ matches a @samp{?}.
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.
+
+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{(}.
@@ -500,51 +583,47 @@ 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 the following places, where they are not allowed:
+
+@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 an open-group, signified by @samp{(}
+
@item After the alternation operator @samp{|}
@end enumerate
-Intervals are specified by @samp{@{} and @samp{@}}. Invalid intervals are treated as literals, for example @samp{a@{1} is treated as @samp{a\@{1}
+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 posix-basic regular expression syntax
-@subsection @samp{posix-basic} regular expression syntax
-This is a synonym for ed.
-@node posix-egrep regular expression syntax
-@subsection @samp{posix-egrep} regular expression syntax
-This is a synonym for egrep.
-@node posix-extended regular expression syntax
-@subsection @samp{posix-extended} regular expression syntax
+@node grep regular expression syntax
+@subsection @samp{grep} regular expression syntax
-The character @samp{.} matches any single character except the null character.
+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{+}
+indicates that the regular expression should match one or more occurrences of the previous atom or regexp.
@item \?
-matches a @samp{?}.
+indicates that the regular expression should match zero or one occurrence of the previous atom or regexp.
+@item + and ?
+match themselves.
+
@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
@@ -567,25 +646,56 @@ GNU extensions are supported:
@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{(}.
+Grouping is performed with backslashes followed by parentheses @samp{\(}, @samp{\)}. 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 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 character @samp{^} only represents the beginning of a string when it appears:
+@enumerate
-@samp{*}, @samp{+} and @samp{?} are special at any point in a regular expression except the following places, where they are not allowed:
+@item At the beginning of a regular expression
+
+@item After an open-group, signified by @samp{\(}
+
+
+@item After a newline
+
+@item After the alternation operator @samp{\|}
+
+@end enumerate
+
+
+The character @samp{$} only represents the end of a string when it appears:
+@enumerate
+
+@item At the end of a regular expression
+
+@item Before a close-group, signified by @samp{\)}
+
+@item Before a newline
+
+@item Before the alternation operator @samp{\|}
+
+@end enumerate
+
+
+@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{|}
+@item After an open-group, signified by @samp{\(}
+
+@item After a newline
+
+@item After the alternation operator @samp{\|}
@end enumerate
-Intervals are specified by @samp{@{} and @samp{@}}. Invalid intervals such as @samp{a@{1z} are not accepted.
+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.
diff --git a/find/find.1 b/find/find.1
index 06ddfa5b..8b1320c1 100644
--- a/find/find.1
+++ b/find/find.1
@@ -879,8 +879,8 @@ on the whole path, not a search. For example, to match a file named
`./fubar3', you can use the regular expression `.*bar.' or `.*b.*3',
but not `f.*r3'. The regular expressions understood by
.B find
-are by default Emacs Regular Expressions, but this can be
-changed with the
+are by default Emacs Regular Expressions (except that `.' matches
+newline), but this can be changed with the
.B \-regextype
option.
diff --git a/lib/regexprops.c b/lib/regexprops.c
index fcbdd5db..b20b4a38 100644
--- a/lib/regexprops.c
+++ b/lib/regexprops.c
@@ -78,8 +78,12 @@ directive (const char *s)
static void
comment (const char *s)
{
- directive ("@c ");
- literal (s);
+ directive ("@c");
+ if (s[0])
+ {
+ literal (" ");
+ literal (s);
+ }
newline ();
}
@@ -175,7 +179,7 @@ describe_regex_syntax (int options)
content (" the null character");
}
- content (". ");
+ content (".");
newpara ();
if (!(options & RE_LIMITED_OPS))
@@ -185,25 +189,25 @@ describe_regex_syntax (int options)
{
enum_item ("\\+");
content ("indicates that the regular expression should match one"
- " or more occurrences of the previous atom or regexp. ");
+ " 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. ");
+ " 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. ");
+ " 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. ");
+ " or one occurrence of the previous atom or regexp.");
enum_item ("\\+");
literal ("matches a @samp{+}");
enum_item ("\\?");
- literal ("matches a @samp{?}. ");
+ literal ("matches a @samp{?}.");
}
endtable ();
}
@@ -226,15 +230,15 @@ describe_regex_syntax (int options)
if (options & RE_CHAR_CLASSES)
content ("Character classes are supported; for example "
- "@samp{[[:digit:]]} will match a single decimal digit. ");
+ "@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:]]}. ");
+ "instead of @samp{[[:digit:]]}.\n");
if (options & RE_HAT_LISTS_NOT_NEWLINE)
{
- literal ("Non-matching lists @samp{[^@dots{}]} do not ever match newline. ");
+ literal ("Non-matching lists @samp{[^@dots{}]} do not ever match newline.\n");
}
newpara ();
if (options & RE_NO_GNU_OPS)
@@ -242,7 +246,7 @@ describe_regex_syntax (int options)
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. ");
+ "@samp{w}, @samp{W}, @samp{<}, @samp{>}, @samp{b}, @samp{B}, @samp{`}, and @samp{'} respectively.\n");
}
else
{
@@ -276,7 +280,7 @@ describe_regex_syntax (int options)
if (options & RE_NO_BK_REFS)
{
- content ("A backslash followed by a digit matches that digit. ");
+ content ("A backslash followed by a digit matches that digit.");
}
else
{
@@ -285,7 +289,7 @@ describe_regex_syntax (int options)
literal ("@samp{(}");
else
literal ("@samp{\\(}");
- content (". ");
+ content (".");
}
@@ -293,29 +297,28 @@ 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 ();
if (options & RE_CONTEXT_INDEP_ANCHORS)
{
- literal ("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. ");
+ literal ("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.\n");
}
else
{
literal ("The character @samp{^} only represents the beginning of a string when it appears:");
beginenum ();
- enum_item ("\nAt the beginning of a regular expression");
- enum_item ("After an open-group, signified by ");
+ enum_item ("At the beginning of a regular expression");
if (options & RE_NO_BK_PARENS)
{
- literal ("@samp{(}");
+ enum_item ("After an open-group, signified by @samp{(}");
}
else
{
- literal ("@samp{\\(}");
+ enum_item ("After an open-group, signified by @samp{\\(}");
}
newline ();
if (!(options & RE_LIMITED_OPS))
@@ -334,14 +337,13 @@ describe_regex_syntax (int options)
literal ("The character @samp{$} only represents the end of a string when it appears:");
beginenum ();
enum_item ("At the end of a regular expression");
- enum_item ("Before a close-group, signified by ");
if (options & RE_NO_BK_PARENS)
{
- literal ("@samp{)}");
+ enum_item ("Before a close-group, signified by @samp{)}");
}
else
{
- literal ("@samp{\\)}");
+ enum_item ("Before a close-group, signified by @samp{\\)}");
}
if (!(options & RE_LIMITED_OPS))
{
@@ -361,7 +363,7 @@ describe_regex_syntax (int options)
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. ");
+ literal ("The characters @samp{*}, @samp{+} and @samp{?} are special anywhere in a regular expression.\n");
}
else
{
@@ -381,14 +383,13 @@ describe_regex_syntax (int options)
beginenum ();
enum_item ("At the beginning of a regular expression");
- enum_item ("After an open-group, signified by ");
if (options & RE_NO_BK_PARENS)
{
- literal ("@samp{(}");
+ enum_item ("After an open-group, signified by @samp{(}");
}
else
{
- literal ("@samp{\\(}");
+ enum_item ("After an open-group, signified by @samp{\\(}");
}
if (!(options & RE_LIMITED_OPS))
{
@@ -410,39 +411,38 @@ describe_regex_syntax (int options)
{
if (options & RE_NO_BK_BRACES)
{
- literal ("Intervals are specified by @samp{@{} and @samp{@}}. ");
+ 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. ");
+ literal ("Invalid intervals such as @samp{a@{1z} are not accepted.\n");
}
}
else
{
- literal ("Intervals are specified by @samp{\\@{} and @samp{\\@}}. ");
+ 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. ");
+ literal ("Invalid intervals such as @samp{a\\@{1z} are not accepted.\n");
}
}
-
}
newpara ();
if (options & RE_NO_POSIX_BACKTRACKING)
{
- content ("Matching succeeds as soon as the whole pattern is matched, meaning that the result may not be the longest possible match. ");
+ content ("Matching succeeds as soon as the whole pattern is matched, meaning that the result may not be the longest possible match.");
}
else
{
- content ("The longest possible match is returned; this applies to the regular expression as a whole and (subject to this constraint) to subexpressions within groups. ");
+ content ("The longest possible match is returned; this applies to the regular expression as a whole and (subject to this constraint) to subexpressions within groups.");
}
newpara ();
}
diff --git a/lib/regextype.c b/lib/regextype.c
index 8a7347dc..89416ebd 100644
--- a/lib/regextype.c
+++ b/lib/regextype.c
@@ -56,17 +56,19 @@ struct tagRegexTypeMap
struct tagRegexTypeMap regex_map[] =
{
{ "findutils-default", CONTEXT_FINDUTILS, RE_SYNTAX_EMACS|RE_DOT_NEWLINE },
+
+ { "posix-awk", CONTEXT_ALL, RE_SYNTAX_POSIX_AWK },
+ { "posix-basic", CONTEXT_ALL, RE_SYNTAX_POSIX_BASIC },
+ { "posix-egrep", CONTEXT_ALL, RE_SYNTAX_POSIX_EGREP },
+ { "posix-extended", CONTEXT_ALL, RE_SYNTAX_POSIX_EXTENDED },
+ { "posix-minimal-basic", CONTEXT_GENERIC, RE_SYNTAX_POSIX_MINIMAL_BASIC },
+
{ "awk", CONTEXT_ALL, RE_SYNTAX_AWK },
- { "egrep", CONTEXT_ALL, RE_SYNTAX_EGREP },
{ "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 },
- { "posix-basic", CONTEXT_ALL, RE_SYNTAX_POSIX_BASIC },
- { "posix-egrep", CONTEXT_ALL, RE_SYNTAX_POSIX_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 },
/* ,{ "posix-common", CONTEXT_GENERIC, _RE_SYNTAX_POSIX_COMMON } */
};
--
2.19.1

View File

@ -0,0 +1,250 @@
From 40cd25147b4461979c0d992299f2c101f9034f7a Mon Sep 17 00:00:00 2001
From: Bernhard Voelker <mail@bernhard-voelker.de>
Date: Tue, 6 Jun 2017 08:19:29 +0200
Subject: [PATCH 101/224] xargs: add -o, --open-tty option
This option is available in the xargs implementation of FreeBSD, NetBSD,
OpenBSD and in the Apple variant. Add it for compatibility.
* xargs/xargs.c (open_tty): Add static flag for the new option.
(longopts): Add member.
(main): Handle the 'o' case in the getopt_long() loop.
(prep_child_for_exec): Redirect stdin of the child to /dev/tty when
the -o option is given. Furthermore, move the just-opened file
descriptor to STDIN_FILENO.
(usage): Document the new option.
* bootstrap.conf (gnulib_modules): Add dup2.
* xargs/xargs.1 (SYNOPSIS): Replace the too-long list of options by
"[options]" - they are listed later anyway.
(OPTIONS): Document the new option.
(STANDARDS CONFORMANCE): Mention that the -o option is an extension.
* doc/find.texi (xargs options): Document the new option.
(Invoking the shell from xargs): Amend the explanation of the
redirection example with a note about the -o option.
(Viewing And Editing): Likewise.
(Error Messages From xargs): Add the message when dup2() fails.
(NEWS): Mention the new option.
Fixes http://savannah.gnu.org/bugs/?51151
---
NEWS | 4 ++++
bootstrap.conf | 1 +
doc/find.texi | 24 ++++++++++++++++++++++++
xargs/xargs.1 | 41 +++++++++++++----------------------------
xargs/xargs.c | 33 ++++++++++++++++++++++++++-------
5 files changed, 68 insertions(+), 35 deletions(-)
diff --git a/doc/find.texi b/doc/find.texi
index 24d8ef99..4516b64c 100644
--- a/doc/find.texi
+++ b/doc/find.texi
@@ -3746,6 +3746,17 @@ Use at most @var{max-args} arguments per command line. Fewer than
option) is exceeded, unless the @samp{-x} option is given, in which
case @code{xargs} will exit.
+@item --open-tty
+@itemx -o
+Reopen stdin 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.
+@example
+grep -lz PATTERN * | xargs -0o vi
+@end example
+
+
@item --interactive
@itemx -p
Prompt the user about whether to run each command line and read a line
@@ -3877,6 +3888,10 @@ Therefore instead of keeping a @code{sh} process around for no reason,
we just arrange for the subshell to exec Emacs, saving an extra
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}.
+
Sometimes, though, it can be helpful to keep the shell process around:
@example
@@ -4050,6 +4065,10 @@ protect the @code{$@@} against expansion by your interactive shell
nothing). The capitalised @samp{Emacs} on the command line is used as
@code{$0} by the shell that @code{xargs} launches.
+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}.
+
@node Archiving
@section Archiving
@@ -5564,6 +5583,11 @@ signals to increase or decrease the parallelism of its processing.
If you don't plan to send it those signals, this warning can be ignored
(though if you're a programmer, you may want to help us figure out
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.
+See the manual of the system call @code{dup2(2)}.
@end table
@node Error Messages From locate
diff --git a/xargs/xargs.1 b/xargs/xargs.1
index 68377868..f66dbc05 100644
--- a/xargs/xargs.1
+++ b/xargs/xargs.1
@@ -4,34 +4,7 @@ xargs \- build and execute command lines from standard input
.SH SYNOPSIS
.B xargs
.nh
-[\fB\-0prtx\fR]
-[\fB\-E \fIeof-str\fR]
-[\fB\-e\fR[\fIeof-str\fR]]
-[\fB\-\-eof\fR[=\fIeof-str\fR]]
-[\fB\-\-null\fR]
-[\fB\-d \fIdelimiter\fR]
-[\fB\-\-delimiter \fIdelimiter\fR]
-[\fB\-I \fIreplace-str\fR]
-[\fB\-i\fR[\fIreplace-str\fR]]
-[\fB\-\-replace\fR[=\fIreplace-str\fR]]
-[\fB\-l\fR[\fImax-lines\fR]]
-[\fB\-L \fImax-lines\fR]
-[\fB\-\-max\-lines\fR[=\fImax-lines\fR]]
-[\fB\-n \fImax-args\fR]
-[\fB\-\-max\-args\fR=\fImax-args\fR]
-[\fB\-s \fImax-chars\fR]
-[\fB\-\-max\-chars\fR=\fImax-chars\fR]
-[\fB\-P \fImax-procs\fR]
-[\fB\-\-max\-procs\fR=\fImax-procs\fR]
-[\fB\-\-process\-slot\-var\fR=\fIname\fR]
-[\fB\-\-interactive\fR]
-[\fB\-\-verbose\fR]
-[\fB\-\-exit\fR]
-[\fB\-\-no\-run\-if\-empty\fR]
-[\fB\-\-arg\-file\fR=\fIfile\fR]
-[\fB\-\-show\-limits\fR]
-[\fB\-\-version\fR]
-[\fB\-\-help\fR]
+[\fIoptions\fR]
[\fIcommand\fR [\fIinitial-arguments\fR]]
.hy
.SH DESCRIPTION
@@ -252,6 +225,15 @@ arrange for each process to produce a separate output file (or
otherwise use separate resources).
.TP
.PD
+.B \-o, \-\-open\-tty
+Reopen stdin as
+.I /dev/tty
+in the child process before executing the command. This is useful if
+you want
+.B xargs
+to run an interactive application.
+.TP
+.PD
.B \-p, \-\-interactive
Prompt the user about whether to run each command line and read a line
from the terminal. Only run the command line if the response starts
@@ -404,6 +386,9 @@ The \-l and \-i options appear in the 1997 version of the POSIX
standard, but do not appear in the 2004 version of the standard.
Therefore you should use \-L and \-I instead, respectively.
.P
+The \-o option is an extension to the POSIX standard for better
+compatibility with BSD.
+.P
The POSIX standard allows implementations to have a limit on the size
of arguments to the
.B exec
diff --git a/xargs/xargs.c b/xargs/xargs.c
index 5cf8c131..a2917e48 100644
--- a/xargs/xargs.c
+++ b/xargs/xargs.c
@@ -151,6 +151,9 @@ static volatile int child_error = EXIT_SUCCESS;
static volatile int original_exit_value;
+/* If true, open /dev/tty in the child process before executing the command. */
+static bool open_tty = false; /* option -o */
+
/* If true, print each command on stderr before executing it. */
static bool print_command = false; /* Option -t */
@@ -185,6 +188,7 @@ static struct option const longopts[] =
{"replace", optional_argument, NULL, 'I'},
{"max-lines", optional_argument, NULL, 'l'},
{"max-args", required_argument, NULL, 'n'},
+ {"open-tty", no_argument, NULL, 'o'},
{"interactive", no_argument, NULL, 'p'},
{"no-run-if-empty", no_argument, NULL, 'r'},
{"max-chars", required_argument, NULL, 's'},
@@ -509,7 +513,7 @@ main (int argc, char **argv)
bc_use_sensible_arg_max (&bc_ctl);
}
- while ((optc = getopt_long (argc, argv, "+0a:E:e::i::I:l::L:n:prs:txP:d:",
+ while ((optc = getopt_long (argc, argv, "+0a:E:e::i::I:l::L:n:oprs:txP:d:",
longopts, &option_index)) != -1)
{
switch (optc)
@@ -608,6 +612,10 @@ main (int argc, char **argv)
bc_ctl.exit_if_size_exceeded = true;
break;
+ case 'o':
+ open_tty = true;
+ break;
+
case 'p':
query_before_executing = true;
print_command = true;
@@ -1185,22 +1193,30 @@ prep_child_for_exec (void)
unsigned int slot = add_proc (0);
set_slot_var (slot);
- if (!keep_stdin)
+ if (!keep_stdin || open_tty)
{
- const char inputfile[] = "/dev/null";
- /* fprintf (stderr, "attaching stdin to /dev/null\n"); */
+ int fd;
+ const char *inputfile = open_tty ? "/dev/tty" : "/dev/null";
close (0);
- if (open (inputfile, O_RDONLY) < 0)
+ if ((fd = open (inputfile, O_RDONLY)) < 0)
{
- /* This is not entirely fatal, since
+ /* Treat a failure to open /dev/tty as fatal.
+ * The other case 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",
+ error (open_tty ? EXIT_FAILURE : 0, errno, "%s",
quotearg_n_style (0, locale_quoting_style, inputfile));
}
+ if (STDIN_FILENO < fd)
+ {
+ if (dup2(fd, STDIN_FILENO) != 0)
+ error (EXIT_FAILURE, errno,
+ _("failed to redirect standard input of the child process"));
+ close(fd);
+ }
}
}
@@ -1676,6 +1692,9 @@ usage (int status)
HTL (_(" -l[MAX-LINES] similar to -L but defaults to at most one non-\n"
" blank input line if MAX-LINES is not specified\n"));
HTL (_(" -n, --max-args=MAX-ARGS use at most MAX-ARGS arguments per command line\n"));
+ HTL (_(" -o, --open-tty Reopen stdin as /dev/tty in the child process\n"
+ " before executing the command; useful to run an\n"
+ " interactive application.\n"));
HTL (_(" -P, --max-procs=MAX-PROCS run at most MAX-PROCS processes at a time\n"));
HTL (_(" -p, --interactive prompt before running commands\n"));
HTL (_(" --process-slot-var=VAR set environment variable VAR in child processes\n"));
--
2.19.1