hi, could you give a few word why you need that feature ? btw: Why you choose a linked list ? It seems more simple to make a strin for all
re, wh Am 11.06.2014 23:07, schrieb Bartosz Golaszewski: > This patch implements the missing feature in find. It's configurable > and doesn't add any bloat when configured out. > > With new feature compiled: > function old new delta > scheduled_exec - 237 +237 > parse_params 1561 1647 +86 > .rodata 150765 150842 +77 > func_exec 187 235 +48 > packed_usage 29441 29484 +43 > llist_size - 16 +16 > ------------------------------------------------------------------------------ > (add/remove: 2/0 grow/shrink: 4/0 up/down: 507/0) Total: 507 bytes > text data bss dec hex filename > 815295 4123 9504 828922 ca5fa busybox_old > 815759 4123 9504 829386 ca7ca busybox_unstripped > > without it: > function old new delta > parse_params 1561 1556 -5 > ------------------------------------------------------------------------------ > (add/remove: 0/0 grow/shrink: 0/1 up/down: 0/-5) Total: -5 bytes > text data bss dec hex filename > 815295 4123 9504 828922 ca5fa busybox_old > 815290 4123 9504 828917 ca5f5 busybox_unstripped > > Signed-off-by: Bartosz Golaszewski <[email protected]> > --- > findutils/find.c | 132 > ++++++++++++++++++++++++++++++++++++++++++++++--------- > 1 file changed, 112 insertions(+), 20 deletions(-) > > diff --git a/findutils/find.c b/findutils/find.c > index 6d34f4d..fa24dea 100644 > --- a/findutils/find.c > +++ b/findutils/find.c > @@ -137,6 +137,14 @@ > //config: Support the 'find -exec' option for executing commands based > upon > //config: the files matched. > //config: > +//config:config FEATURE_FIND_EXEC_PLUS > +//config: bool "Enable -exec ... {} +" > +//config: default y > +//config: depends on FEATURE_FIND_EXEC > +//config: help > +//config: Support the 'find -exec ... {} +' option for executing > commands > +//config: for all matched files at once. > +//config: > //config:config FEATURE_FIND_USER > //config: bool "Enable -user: username/uid matching" > //config: default y > @@ -319,6 +327,10 @@ > //usage: "\n -exec CMD ARG ; Run CMD with all instances of {} > replaced by" > //usage: "\n file name. Fails if CMD exits with > nonzero" > //usage: ) > +//usage: IF_FEATURE_FIND_EXEC_PLUS( > +//usage: "\n -exec CMD ARG + Same as above except that all file > names are appended" > +//usage: "\n at the end of the exec action" > +//usage: ) > //usage: IF_FEATURE_FIND_DELETE( > //usage: "\n -delete Delete current file/directory. Turns on > -depth option" > //usage: ) > @@ -375,7 +387,12 @@ IF_FEATURE_FIND_CONTEXT(ACTS(context, security_context_t > context;)) > IF_FEATURE_FIND_PAREN( ACTS(paren, action ***subexpr;)) > IF_FEATURE_FIND_PRUNE( ACTS(prune)) > IF_FEATURE_FIND_DELETE( ACTS(delete)) > -IF_FEATURE_FIND_EXEC( ACTS(exec, char **exec_argv; unsigned *subst_count; > int exec_argc;)) > +IF_FEATURE_FIND_EXEC( ACTS(exec, > + char **exec_argv; > + unsigned *subst_count; > + int exec_argc; > + IF_FEATURE_FIND_EXEC_PLUS(int all_at_once;) > + )) > IF_FEATURE_FIND_GROUP( ACTS(group, gid_t gid;)) > IF_FEATURE_FIND_LINKS( ACTS(links, char links_char; int links_count;)) > > @@ -389,6 +406,10 @@ struct globals { > smallint need_print; > smallint xdev_on; > recurse_flags_t recurse_flags; > +#if ENABLE_FEATURE_FIND_EXEC_PLUS > + llist_t *exec_all_acts; > + llist_t *found_files; > +#endif > } FIX_ALIASING; > #define G (*(struct globals*)&bb_common_bufsiz1) > #define INIT_G() do { \ > @@ -452,6 +473,48 @@ static int exec_actions(action ***appp, const char > *fileName, const struct stat > return rc ^ TRUE; /* restore TRUE bit */ > } > > +#if ENABLE_FEATURE_FIND_EXEC_PLUS > +static int scheduled_exec(void) > +{ > + /* Execute all scheduled '-exec +' actions. Expect > + * the {} to be at the end of the command. > + */ > + llist_t *actlist = G.exec_all_acts; > + int rc = 0; > + > + while (actlist) { > + action_exec *ap; > + llist_t *filelist; > + size_t num_files; > + char **argv; > + int i; > + > + ap = (action_exec*)actlist->data; > + filelist = G.found_files; > + num_files = llist_size(filelist); > + if (num_files == 0) > + return 0; > + > + argv = alloca((ap->exec_argc + num_files) * sizeof(char*)); > + for (i = 0; i < (ap->exec_argc - 1); i++) > + argv[i] = ap->exec_argv[i]; > + while (filelist) { > + argv[i++] = filelist->data; > + filelist = filelist->link; > + } > + argv[i] = NULL; > + > + rc = spawn_and_wait(argv); > + if (rc < 0) > + bb_simple_perror_msg(argv[0]); > + > + actlist = actlist->link; > + } > + > + /* Return 1 if spawn_and_wait() failed. */ > + return rc != 0; > +} > +#endif /* ENABLE_FEATURE_FIND_EXEC_PLUS */ > > #if !FNM_CASEFOLD > static char *strcpy_upcase(char *dst, const char *src) > @@ -578,24 +641,33 @@ ACTF(inum) > #if ENABLE_FEATURE_FIND_EXEC > ACTF(exec) > { > - int i, rc; > +#if ENABLE_FEATURE_FIND_EXEC_PLUS > + if (ap->all_at_once) { > + llist_add_to_end(&G.found_files, xstrdup(fileName)); > + return 0; > + } else { > +#endif /* ENABLE_FEATURE_FIND_EXEC_PLUS */ > + int i, rc; > #if ENABLE_USE_PORTABLE_CODE > - char **argv = alloca(sizeof(char*) * (ap->exec_argc + 1)); > + char **argv = alloca(sizeof(char*) * (ap->exec_argc + 1)); > #else /* gcc 4.3.1 generates smaller code: */ > - char *argv[ap->exec_argc + 1]; > + char *argv[ap->exec_argc + 1]; > #endif > - for (i = 0; i < ap->exec_argc; i++) > - argv[i] = xmalloc_substitute_string(ap->exec_argv[i], > ap->subst_count[i], "{}", fileName); > - argv[i] = NULL; /* terminate the list */ > + for (i = 0; i < ap->exec_argc; i++) > + argv[i] = xmalloc_substitute_string(ap->exec_argv[i], > ap->subst_count[i], "{}", fileName); > + argv[i] = NULL; /* terminate the list */ > > - rc = spawn_and_wait(argv); > - if (rc < 0) > - bb_simple_perror_msg(argv[0]); > + rc = spawn_and_wait(argv); > + if (rc < 0) > + bb_simple_perror_msg(argv[0]); > > - i = 0; > - while (argv[i]) > - free(argv[i++]); > - return rc == 0; /* return 1 if exitcode 0 */ > + i = 0; > + while (argv[i]) > + free(argv[i++]); > + return rc == 0; /* return 1 if exitcode 0 */ > +#if ENABLE_FEATURE_FIND_EXEC_PLUS > + } > +#endif /* ENABLE_FEATURE_FIND_EXEC_PLUS */ > } > #endif > #if ENABLE_FEATURE_FIND_USER > @@ -1037,6 +1109,7 @@ static action*** parse_params(char **argv) > else if (parm == PARM_exec) { > int i; > action_exec *ap; > + IF_FEATURE_FIND_EXEC_PLUS(int all_subst = 0;) > dbg("%d", __LINE__); > G.need_print = 0; > ap = ALLOC_ACTION(exec); > @@ -1049,10 +1122,11 @@ static action*** parse_params(char **argv) > // executes "echo Foo >FILENAME<", > // find -exec echo Foo ">{}<" "+" > // executes "echo Foo FILENAME1 FILENAME2 > FILENAME3...". > - // TODO (so far we treat "+" just like ";") > - if ((argv[0][0] == ';' || argv[0][0] == '+') > - && argv[0][1] == '\0' > - ) { > + if ((argv[0][0] == ';' > + IF_FEATURE_FIND_EXEC_PLUS(|| argv[0][0] > == '+') > + ) && argv[0][1] == '\0' ) { > + IF_FEATURE_FIND_EXEC_PLUS( > + ap->all_at_once = (argv[0][0] > == '+' ? 1 : 0);) > break; > } > argv++; > @@ -1062,8 +1136,22 @@ static action*** parse_params(char **argv) > bb_error_msg_and_die(bb_msg_requires_arg, arg); > ap->subst_count = xmalloc(ap->exec_argc * sizeof(int)); > i = ap->exec_argc; > - while (i--) > - ap->subst_count[i] = > count_strstr(ap->exec_argv[i], "{}"); > + while (i--) { > + IF_FEATURE_FIND_EXEC_PLUS(all_subst +=) > + ap->subst_count[i] = > count_strstr(ap->exec_argv[i], "{}"); > + } > +#if ENABLE_FEATURE_FIND_EXEC_PLUS > + /* coreutils expects {} to apear only once at the end > of the > + * '-exec +' command. > + */ > + if (ap->all_at_once && all_subst > 1) > + bb_error_msg_and_die("only one '{}' allowed for > -exec +"); > + if (ap->subst_count[ap->exec_argc-1] != 1) > + bb_error_msg_and_die(bb_msg_requires_arg, > "-exec"); > + /* Schedule execution of '-exec +' for later. */ > + if (ap->all_at_once) > + llist_add_to_end(&G.exec_all_acts, ap); > +#endif /* ENABLE_FEATURE_FIND_EXEC_PLUS */ > } > #endif > #if ENABLE_FEATURE_FIND_PAREN > @@ -1335,8 +1423,12 @@ int find_main(int argc UNUSED_PARAM, char **argv) > 0) /* depth */ > ) { > status = EXIT_FAILURE; > + goto out; > } > } > > + IF_FEATURE_FIND_EXEC_PLUS(status = scheduled_exec();) > + > +out: > return status; > } _______________________________________________ busybox mailing list [email protected] http://lists.busybox.net/mailman/listinfo/busybox
