aboutsummaryrefslogtreecommitdiff
path: root/usr.bin/find
diff options
context:
space:
mode:
authorJilles Tjoelker <jilles@FreeBSD.org>2014-04-12 22:36:26 +0000
committerJilles Tjoelker <jilles@FreeBSD.org>2014-04-12 22:36:26 +0000
commit7a79617cc15ccab1d91b9e27b01d54104f71f4e7 (patch)
treeb025d3252093a31ed23ae4720ab00cb625bfa5dc /usr.bin/find
parent1efb0053e4837383f8ac05cc1e2d1727acde5bec (diff)
downloadsrc-7a79617cc15ccab1d91b9e27b01d54104f71f4e7.tar.gz
src-7a79617cc15ccab1d91b9e27b01d54104f71f4e7.zip
find: Correctly propagate -exec/-execdir ... {} + exit status.
As per POSIX, the -exec ... {} + primary always returns true, but a non-zero exit status causes find to return a non-zero exit status itself. GNU does the same, and also for -execdir ... {} +. It does not make much sense to return false from the primary only when the child process happens to be run. The behaviour for -exec/-execdir ... ; remains unchanged: the primary returns true or false depending on the exit status, and find's exit status is unaffected.
Notes
Notes: svn path=/head/; revision=264387
Diffstat (limited to 'usr.bin/find')
-rw-r--r--usr.bin/find/extern.h1
-rw-r--r--usr.bin/find/find.114
-rw-r--r--usr.bin/find/find.c11
-rw-r--r--usr.bin/find/function.c8
-rw-r--r--usr.bin/find/main.c1
5 files changed, 28 insertions, 7 deletions
diff --git a/usr.bin/find/extern.h b/usr.bin/find/extern.h
index 90b9b29d265e..3afe6e4f7d15 100644
--- a/usr.bin/find/extern.h
+++ b/usr.bin/find/extern.h
@@ -118,6 +118,7 @@ extern int ftsoptions, ignore_readdir_race, isdeprecated, isdepth, isoutput;
extern int issort, isxargs;
extern int mindepth, maxdepth;
extern int regexp_flags;
+extern int exitstatus;
extern time_t now;
extern int dotfd;
extern FTS *tree;
diff --git a/usr.bin/find/find.1 b/usr.bin/find/find.1
index 1abe8251fac2..db808b156131 100644
--- a/usr.bin/find/find.1
+++ b/usr.bin/find/find.1
@@ -31,7 +31,7 @@
.\" @(#)find.1 8.7 (Berkeley) 5/9/95
.\" $FreeBSD$
.\"
-.Dd January 5, 2014
+.Dd April 12, 2014
.Dt FIND 1
.Os
.Sh NAME
@@ -384,6 +384,12 @@ is replaced with as many pathnames as possible for each invocation of
.Ar utility .
This behaviour is similar to that of
.Xr xargs 1 .
+The primary always returns true;
+if at least one invocation of
+.Ar utility
+returns a non-zero exit status,
+.Nm
+will return a non-zero exit status.
.It Ic -execdir Ar utility Oo Ar argument ... Oc Li \&;
The
.Ic -execdir
@@ -406,6 +412,12 @@ is replaced with as many pathnames as possible for each invocation of
.Ar utility .
This behaviour is similar to that of
.Xr xargs 1 .
+The primary always returns true;
+if at least one invocation of
+.Ar utility
+returns a non-zero exit status,
+.Nm
+will return a non-zero exit status.
.It Ic -flags Oo Cm - Ns | Ns Cm + Oc Ns Ar flags , Ns Ar notflags
The flags are specified using symbolic names (see
.Xr chflags 1 ) .
diff --git a/usr.bin/find/find.c b/usr.bin/find/find.c
index e59773f49d93..3e5d56b0217b 100644
--- a/usr.bin/find/find.c
+++ b/usr.bin/find/find.c
@@ -175,13 +175,14 @@ find_execute(PLAN *plan, char *paths[])
{
FTSENT *entry;
PLAN *p;
- int e, rval;
+ int e;
tree = fts_open(paths, ftsoptions, (issort ? find_compare : NULL));
if (tree == NULL)
err(1, "ftsopen");
- for (rval = 0; errno = 0, (entry = fts_read(tree)) != NULL;) {
+ exitstatus = 0;
+ while (errno = 0, (entry = fts_read(tree)) != NULL) {
if (maxdepth != -1 && entry->fts_level >= maxdepth) {
if (fts_set(tree, entry, FTS_SKIP))
err(1, "%s", entry->fts_path);
@@ -206,7 +207,7 @@ find_execute(PLAN *plan, char *paths[])
(void)fflush(stdout);
warnx("%s: %s",
entry->fts_path, strerror(entry->fts_errno));
- rval = 1;
+ exitstatus = 1;
continue;
#ifdef FTS_W
case FTS_W:
@@ -217,7 +218,7 @@ find_execute(PLAN *plan, char *paths[])
if (isxargs && strpbrk(entry->fts_path, BADCH)) {
(void)fflush(stdout);
warnx("%s: illegal path", entry->fts_path);
- rval = 1;
+ exitstatus = 1;
continue;
}
@@ -235,5 +236,5 @@ find_execute(PLAN *plan, char *paths[])
finish_execplus();
if (e && (!ignore_readdir_race || e != ENOENT))
errc(1, e, "fts_read");
- return (rval);
+ return (exitstatus);
}
diff --git a/usr.bin/find/function.c b/usr.bin/find/function.c
index 32c8220f54e0..01394062d911 100644
--- a/usr.bin/find/function.c
+++ b/usr.bin/find/function.c
@@ -671,7 +671,13 @@ doexec: if ((plan->flags & F_NEEDOK) && !queryuser(plan->e_argv))
plan->e_psize = plan->e_pbsize;
}
pid = waitpid(pid, &status, 0);
- return (pid != -1 && WIFEXITED(status) && !WEXITSTATUS(status));
+ if (pid != -1 && WIFEXITED(status) && !WEXITSTATUS(status))
+ return (1);
+ if (plan->flags & F_EXECPLUS) {
+ exitstatus = 1;
+ return (1);
+ }
+ return (0);
}
/*
diff --git a/usr.bin/find/main.c b/usr.bin/find/main.c
index 3a0377fa13c3..bcbeed56f600 100644
--- a/usr.bin/find/main.c
+++ b/usr.bin/find/main.c
@@ -72,6 +72,7 @@ int issort; /* do hierarchies in lexicographical order */
int isxargs; /* don't permit xargs delimiting chars */
int mindepth = -1, maxdepth = -1; /* minimum and maximum depth */
int regexp_flags = REG_BASIC; /* use the "basic" regexp by default*/
+int exitstatus;
static void usage(void);