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

Reply via email to