Date: Sat, 26 Mar 2005 20:38:50 +0100 (CET) From: Jilles Tjoelker <jilles@stack.nl> To: FreeBSD-gnats-submit@FreeBSD.org Subject: bin/79263: find -exec {} + fails with -or and ! Message-ID: <20050326193850.98BBF1CD4B@turtle.stack.nl> Resent-Message-ID: <200503261940.j2QJe3Wa019400@freefall.freebsd.org>
next in thread | raw e-mail | index | archive | help
>Number: 79263 >Category: bin >Synopsis: find -exec {} + fails with -or and ! >Confidential: no >Severity: serious >Priority: medium >Responsible: freebsd-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: sw-bug >Submitter-Id: current-users >Arrival-Date: Sat Mar 26 19:40:03 GMT 2005 >Closed-Date: >Last-Modified: >Originator: Jilles Tjoelker >Release: FreeBSD 5.3-RELEASE-p5 i386 >Organization: MCGV Stack >Environment: System: FreeBSD turtle.stack.nl 5.3-RELEASE-p5 FreeBSD 5.3-RELEASE-p5 #7: Thu Mar 10 11:12:03 CET 2005 marcolz@snail.stack.nl:/usr/obj/usr/src/sys/SNAIL i386 find(1) in HEAD is almost the same. >Description: The last (possibly only) execution of -exec {} + is not done if the -exec primary is not on the top-level -and sequence, e.g. inside a ! or -or. >How-To-Repeat: Simple not-so-practical example (/home/jilles/tmp/find is the patched version of /usr/src/usr.bin/find): jilles@jaguar /home/jilles/tmp% find find \! -exec echo {} + (no output) jilles@jaguar /home/jilles/tmp% find/find find \! -exec echo {} + find find/option.c find/extern.h find/find.1 find/find.c find/find.h find/function.c find/getdate.y find/ls.c find/main.c find/misc.c find/operator.c find/Makefile find/find.o find/function.o find/ls.o find/main.o find/misc.o find/operator.o find/option.o find/getdate.c find/getdate.o find/find find/find.1.gz (expected output) Practical example (searching through a Subversion checkout): jilles@jaguar /home/jilles/src/svn/hyperion% find . \( -name .svn -prune \) -o -type f -exec grep -i silence /dev/null {} + (no output) jilles@jaguar /home/jilles/src/svn/hyperion% ~/tmp/find/find . \( -name .svn -prune \) -o -type f -exec grep -i silence /dev/null {} + (expected output, snipped here) In comparison: jilles@jaguar /home/jilles/src/svn/hyperion% find . \( -name .svn -prune \) -o -type f -print0 | xargs -0 grep -i silence /dev/null gives the expected output, even without the patch. >Fix: Patch included. Create a separate linked list of all active -exec {} + primaries and do the last execution for all at termination. --- find.patch begins here --- diff -ur /usr/src/usr.bin/find/extern.h find/extern.h --- /usr/src/usr.bin/find/extern.h Thu Jul 29 05:29:44 2004 +++ find/extern.h Sat Mar 26 20:11:04 2005 @@ -49,6 +49,7 @@ void printlong(char *, char *, struct stat *); int queryuser(char **); OPTION *lookup_option(const char *); +void finish_execplus(void); creat_f c_Xmin; creat_f c_Xtime; diff -ur /usr/src/usr.bin/find/find.c find/find.c --- /usr/src/usr.bin/find/find.c Fri May 28 19:17:15 2004 +++ find/find.c Sat Mar 26 20:09:23 2005 @@ -231,10 +231,7 @@ */ for (p = plan; p && (p->execute)(p, entry); p = p->next); } - /* Finish any pending -exec ... {} + functions. */ - for (p = plan; p != NULL; p = p->next) - if (p->execute == f_exec && p->flags & F_EXECPLUS) - (p->execute)(p, NULL); + finish_execplus(); if (errno) err(1, "fts_read"); return (rval); diff -ur /usr/src/usr.bin/find/find.h find/find.h --- /usr/src/usr.bin/find/find.h Fri May 28 19:17:15 2004 +++ find/find.h Sat Mar 26 19:55:31 2005 @@ -103,6 +103,7 @@ int _e_psize; /* number of bytes of args. */ int _e_pbsize; /* base num. of bytes of args */ int _e_psizemax; /* max num. of bytes of args */ + struct _plandata *_e_next;/* next F_EXECPLUS in tree */ } ex; char *_a_data[2]; /* array of char pointers */ char *_c_data; /* char pointer */ @@ -133,6 +134,7 @@ #define e_psize p_un.ex._e_psize #define e_pbsize p_un.ex._e_pbsize #define e_psizemax p_un.ex._e_psizemax +#define e_next p_un.ex._e_next typedef struct _option { const char *name; /* option name */ Only in find: find.o diff -ur /usr/src/usr.bin/find/function.c find/function.c --- /usr/src/usr.bin/find/function.c Thu Jul 29 05:33:55 2004 +++ find/function.c Sat Mar 26 20:11:06 2005 @@ -76,6 +76,8 @@ extern char **environ; +static PLAN *lastexecplus = NULL; + #define COMPARE(a, b) do { \ switch (plan->flags & F_ELG_MASK) { \ case F_EQUAL: \ @@ -704,6 +706,8 @@ new->e_psizemax = argmax; new->e_pbsize = 0; cnt += new->e_pnummax + 1; + new->e_next = lastexecplus; + lastexecplus = new; } if ((new->e_argv = malloc(cnt * sizeof(char *))) == NULL) err(1, NULL); @@ -745,6 +749,19 @@ done: *argvp = argv + 1; return new; +} + +/* Finish any pending -exec ... {} + functions. */ +void +finish_execplus() +{ + PLAN *p; + + p = lastexecplus; + while (p != NULL) { + (p->execute)(p, NULL); + p = p->e_next; + } } int --- find.patch ends here --- >Release-Note: >Audit-Trail: >Unformatted:
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20050326193850.98BBF1CD4B>