Changeset 3621 in MondoRescue for branches/3.3/mindi-busybox/findutils/find.c


Ignore:
Timestamp:
Dec 20, 2016, 4:07:32 PM (7 years ago)
Author:
Bruno Cornec
Message:

New 3?3 banch for incorporation of latest busybox 1.25. Changing minor version to handle potential incompatibilities.

Location:
branches/3.3
Files:
1 edited
1 copied

Legend:

Unmodified
Added
Removed
  • branches/3.3/mindi-busybox/findutils/find.c

    r3232 r3621  
    138138//config:     the files matched.
    139139//config:
     140//config:config FEATURE_FIND_EXEC_PLUS
     141//config:   bool "Enable -exec ... {} +"
     142//config:   default y
     143//config:   depends on FEATURE_FIND_EXEC
     144//config:   help
     145//config:     Support the 'find -exec ... {} +' option for executing commands
     146//config:     for all matched files at once.
     147//config:     Without this option, -exec + is a synonym for -exec ;
     148//config:     (IOW: it works correctly, but without expected speedup)
     149//config:
    140150//config:config FEATURE_FIND_USER
    141151//config:   bool "Enable -user: username/uid matching"
     
    232242
    233243//usage:#define find_trivial_usage
    234 //usage:       "[PATH]... [OPTIONS] [ACTIONS]"
     244//usage:       "[-HL] [PATH]... [OPTIONS] [ACTIONS]"
    235245//usage:#define find_full_usage "\n\n"
    236246//usage:       "Search for files and perform actions on them.\n"
    237247//usage:       "First failed action stops processing of current file.\n"
    238248//usage:       "Defaults: PATH is current directory, action is '-print'\n"
    239 //usage:     "\n    -follow     Follow symlinks"
     249//usage:     "\n    -L,-follow  Follow symlinks"
     250//usage:     "\n    -H      ...on command line only"
    240251//usage:    IF_FEATURE_FIND_XDEV(
    241252//usage:     "\n    -xdev       Don't descend directories on other filesystems"
     
    319330//usage:     "\n            file name. Fails if CMD exits with nonzero"
    320331//usage:    )
     332//usage:    IF_FEATURE_FIND_EXEC_PLUS(
     333//usage:     "\n    -exec CMD ARG + Run CMD with {} replaced by list of file names"
     334//usage:    )
    321335//usage:    IF_FEATURE_FIND_DELETE(
    322336//usage:     "\n    -delete     Delete current file/directory. Turns on -depth option"
     
    329343#include <fnmatch.h>
    330344#include "libbb.h"
     345#include "common_bufsiz.h"
    331346#if ENABLE_FEATURE_FIND_REGEX
    332347# include "xregex.h"
     
    337352#endif
    338353
    339 #define dbg(...) ((void)0)
    340 /* #define dbg(...) bb_error_msg(__VA_ARGS__) */
     354#if 1
     355# define dbg(...) ((void)0)
     356#else
     357# define dbg(...) bb_error_msg(__VA_ARGS__)
     358#endif
     359
    341360
    342361/* This is a NOEXEC applet. Be very careful! */
     
    375394IF_FEATURE_FIND_PRUNE(  ACTS(prune))
    376395IF_FEATURE_FIND_DELETE( ACTS(delete))
    377 IF_FEATURE_FIND_EXEC(   ACTS(exec,  char **exec_argv; unsigned *subst_count; int exec_argc;))
     396IF_FEATURE_FIND_EXEC(   ACTS(exec,
     397                char **exec_argv; /* -exec ARGS */
     398                unsigned *subst_count;
     399                int exec_argc; /* count of ARGS */
     400                IF_FEATURE_FIND_EXEC_PLUS(
     401                    /*
     402                     * filelist is NULL if "exec ;"
     403                     * non-NULL if "exec +"
     404                     */
     405                    char **filelist;
     406                    int filelist_idx;
     407                    int file_len;
     408                )
     409                ))
    378410IF_FEATURE_FIND_GROUP(  ACTS(group, gid_t gid;))
    379411IF_FEATURE_FIND_LINKS(  ACTS(links, char links_char; int links_count;))
     
    389421    smallint xdev_on;
    390422    recurse_flags_t recurse_flags;
     423    IF_FEATURE_FIND_EXEC_PLUS(unsigned max_argv_len;)
    391424} FIX_ALIASING;
    392 #define G (*(struct globals*)&bb_common_bufsiz1)
     425#define G (*(struct globals*)bb_common_bufsiz1)
    393426#define INIT_G() do { \
    394     struct G_sizecheck { \
    395         char G_sizecheck[sizeof(G) > COMMON_BUFSIZE ? -1 : 1]; \
    396     }; \
     427    setup_common_bufsiz(); \
     428    BUILD_BUG_ON(sizeof(G) > COMMON_BUFSIZE); \
    397429    /* we have to zero it out because of NOEXEC */ \
    398430    memset(&G, 0, sizeof(G)); \
    399431    IF_FEATURE_FIND_MAXDEPTH(G.minmaxdepth[1] = INT_MAX;) \
     432    IF_FEATURE_FIND_EXEC_PLUS(G.max_argv_len = bb_arg_max() - 2048;) \
    400433    G.need_print = 1; \
    401434    G.recurse_flags = ACTION_RECURSE; \
    402435} while (0)
    403 
    404 #if ENABLE_FEATURE_FIND_EXEC
    405 static unsigned count_subst(const char *str)
    406 {
    407     unsigned count = 0;
    408     while ((str = strstr(str, "{}")) != NULL) {
    409         count++;
    410         str++;
    411     }
    412     return count;
    413 }
    414 
    415 
    416 static char* subst(const char *src, unsigned count, const char* filename)
    417 {
    418     char *buf, *dst, *end;
    419     size_t flen = strlen(filename);
    420     /* we replace each '{}' with filename: growth by strlen-2 */
    421     buf = dst = xmalloc(strlen(src) + count*(flen-2) + 1);
    422     while ((end = strstr(src, "{}"))) {
    423         memcpy(dst, src, end - src);
    424         dst += end - src;
    425         src = end + 2;
    426         memcpy(dst, filename, flen);
    427         dst += flen;
    428     }
    429     strcpy(dst, src);
    430     return buf;
    431 }
    432 #endif
    433436
    434437/* Return values of ACTFs ('action functions') are a bit mask:
     
    482485}
    483486
    484 
    485487#if !FNM_CASEFOLD
    486488static char *strcpy_upcase(char *dst, const char *src)
     
    557559ACTF(perm)
    558560{
    559     /* -perm +mode: at least one of perm_mask bits are set */
    560     if (ap->perm_char == '+')
     561    /* -perm [+/]mode: at least one of perm_mask bits are set */
     562    if (ap->perm_char == '+' || ap->perm_char == '/')
    561563        return (statbuf->st_mode & ap->perm_mask) != 0;
    562564    /* -perm -mode: all of perm_mask are set */
     
    606608#endif
    607609#if ENABLE_FEATURE_FIND_EXEC
    608 ACTF(exec)
     610static int do_exec(action_exec *ap, const char *fileName)
    609611{
    610612    int i, rc;
    611 #if ENABLE_USE_PORTABLE_CODE
    612     char **argv = alloca(sizeof(char*) * (ap->exec_argc + 1));
    613 #else /* gcc 4.3.1 generates smaller code: */
    614     char *argv[ap->exec_argc + 1];
    615 #endif
    616     for (i = 0; i < ap->exec_argc; i++)
    617         argv[i] = subst(ap->exec_argv[i], ap->subst_count[i], fileName);
    618     argv[i] = NULL; /* terminate the list */
     613# if ENABLE_FEATURE_FIND_EXEC_PLUS
     614    int size = ap->exec_argc + ap->filelist_idx + 1;
     615# else
     616    int size = ap->exec_argc + 1;
     617# endif
     618# if ENABLE_USE_PORTABLE_CODE
     619    char **argv = alloca(sizeof(char*) * size);
     620# else /* gcc 4.3.1 generates smaller code: */
     621    char *argv[size];
     622# endif
     623    char **pp = argv;
     624
     625    for (i = 0; i < ap->exec_argc; i++) {
     626        const char *arg = ap->exec_argv[i];
     627
     628# if ENABLE_FEATURE_FIND_EXEC_PLUS
     629        if (ap->filelist) {
     630            /* Handling "-exec +"
     631             * Only one exec_argv[i] has substitution in it.
     632             * Expand that one exec_argv[i] into file list.
     633             */
     634            if (ap->subst_count[i] == 0) {
     635                *pp++ = xstrdup(arg);
     636            } else {
     637                int j = 0;
     638                while (ap->filelist[j]) {
     639                    /* 2nd arg here should be ap->subst_count[i], but it is always 1: */
     640                    *pp++ = xmalloc_substitute_string(arg, 1, "{}", ap->filelist[j]);
     641                    free(ap->filelist[j]);
     642                    j++;
     643                }
     644            }
     645        } else
     646# endif
     647        {
     648            /* Handling "-exec ;" */
     649            *pp++ = xmalloc_substitute_string(arg, ap->subst_count[i], "{}", fileName);
     650        }
     651    }
     652    *pp = NULL; /* terminate the list */
     653
     654# if ENABLE_FEATURE_FIND_EXEC_PLUS
     655    if (ap->filelist) {
     656        ap->filelist[0] = NULL;
     657        ap->filelist_idx = 0;
     658        ap->file_len = 0;
     659    }
     660# endif
    619661
    620662    rc = spawn_and_wait(argv);
     
    627669    return rc == 0; /* return 1 if exitcode 0 */
    628670}
     671ACTF(exec)
     672{
     673# if ENABLE_FEATURE_FIND_EXEC_PLUS
     674    if (ap->filelist) {
     675        int rc;
     676
     677        ap->filelist = xrealloc_vector(ap->filelist, 8, ap->filelist_idx);
     678        ap->filelist[ap->filelist_idx++] = xstrdup(fileName);
     679        ap->file_len += strlen(fileName) + sizeof(char*) + 1;
     680        /* If we have lots of files already, exec the command */
     681        rc = 1;
     682        if (ap->file_len >= G.max_argv_len)
     683            rc = do_exec(ap, NULL);
     684        return rc;
     685    }
     686# endif
     687    return do_exec(ap, fileName);
     688}
     689# if ENABLE_FEATURE_FIND_EXEC_PLUS
     690static int flush_exec_plus(void)
     691{
     692    action *ap;
     693    action **app;
     694    action ***appp = G.actions;
     695    while ((app = *appp++) != NULL) {
     696        while ((ap = *app++) != NULL) {
     697            if (ap->f == (action_fp)func_exec) {
     698                action_exec *ae = (void*)ap;
     699                if (ae->filelist_idx != 0) {
     700                    int rc = do_exec(ae, NULL);
     701#  if ENABLE_FEATURE_FIND_NOT
     702                    if (ap->invert) rc = !rc;
     703#  endif
     704                    if (rc == 0)
     705                        return 1;
     706                }
     707            }
     708        }
     709    }
     710    return 0;
     711}
     712# endif
    629713#endif
    630714#if ENABLE_FEATURE_FIND_USER
     
    685769    int rc;
    686770    if (S_ISDIR(statbuf->st_mode)) {
    687         rc = rmdir(fileName);
     771        /* "find . -delete" skips rmdir(".") */
     772        rc = 0;
     773        if (NOT_LONE_CHAR(fileName, '.'))
     774            rc = rmdir(fileName);
    688775    } else {
    689776        rc = unlink(fileName);
     
    798885
    799886    if (mask == 0 || type[1] != '\0')
    800         bb_error_msg_and_die(bb_msg_invalid_arg, type, "-type");
     887        bb_error_msg_and_die(bb_msg_invalid_arg_to, type, "-type");
    801888
    802889    return mask;
     
    812899        str++;
    813900    return str;
     901}
     902#endif
     903
     904/* Say no to GCCism */
     905#define USE_NESTED_FUNCTION 0
     906
     907#if !USE_NESTED_FUNCTION
     908struct pp_locals {
     909    action*** appp;
     910    unsigned cur_group;
     911    unsigned cur_action;
     912    IF_FEATURE_FIND_NOT( bool invert_flag; )
     913};
     914static action* alloc_action(struct pp_locals *ppl, int sizeof_struct, action_fp f)
     915{
     916    action *ap = xzalloc(sizeof_struct);
     917    action **app;
     918    action ***group = &ppl->appp[ppl->cur_group];
     919    *group = app = xrealloc(*group, (ppl->cur_action+2) * sizeof(ppl->appp[0][0]));
     920    app[ppl->cur_action++] = ap;
     921    app[ppl->cur_action] = NULL;
     922    ap->f = f;
     923    IF_FEATURE_FIND_NOT( ap->invert = ppl->invert_flag; )
     924    IF_FEATURE_FIND_NOT( ppl->invert_flag = 0; )
     925    return ap;
    814926}
    815927#endif
     
    9011013    ;
    9021014
     1015#if !USE_NESTED_FUNCTION
     1016    struct pp_locals ppl;
     1017#define appp        (ppl.appp       )
     1018#define cur_group   (ppl.cur_group  )
     1019#define cur_action  (ppl.cur_action )
     1020#define invert_flag (ppl.invert_flag)
     1021#define ALLOC_ACTION(name) (action_##name*)alloc_action(&ppl, sizeof(action_##name), (action_fp) func_##name)
     1022#else
    9031023    action*** appp;
    904     unsigned cur_group = 0;
    905     unsigned cur_action = 0;
    906     IF_FEATURE_FIND_NOT( bool invert_flag = 0; )
     1024    unsigned cur_group;
     1025    unsigned cur_action;
     1026    IF_FEATURE_FIND_NOT( bool invert_flag; )
    9071027
    9081028    /* This is the only place in busybox where we use nested function.
     
    9131033    {
    9141034        action *ap;
    915         appp[cur_group] = xrealloc(appp[cur_group], (cur_action+2) * sizeof(*appp));
     1035        appp[cur_group] = xrealloc(appp[cur_group], (cur_action+2) * sizeof(appp[0][0]));
    9161036        appp[cur_group][cur_action++] = ap = xzalloc(sizeof_struct);
    9171037        appp[cur_group][cur_action] = NULL;
     
    9211041        return ap;
    9221042    }
    923 
    9241043#define ALLOC_ACTION(name) (action_##name*)alloc_action(sizeof(action_##name), (action_fp) func_##name)
    925 
     1044#endif
     1045
     1046    cur_group = 0;
     1047    cur_action = 0;
     1048    IF_FEATURE_FIND_NOT( invert_flag = 0; )
    9261049    appp = xzalloc(2 * sizeof(appp[0])); /* appp[0],[1] == NULL */
    9271050
     
    9491072        /* Options */
    9501073        if (parm == OPT_FOLLOW) {
    951                         dbg("follow enabled: %d", __LINE__);
    952                         G.recurse_flags |= ACTION_FOLLOWLINKS | ACTION_DANGLING_OK;
     1074            dbg("follow enabled: %d", __LINE__);
     1075            G.recurse_flags |= ACTION_FOLLOWLINKS | ACTION_DANGLING_OK;
    9531076        }
    9541077#if ENABLE_FEATURE_FIND_XDEV
     
    9881111            /* start new OR group */
    9891112            cur_group++;
    990             appp = xrealloc(appp, (cur_group+2) * sizeof(*appp));
     1113            appp = xrealloc(appp, (cur_group+2) * sizeof(appp[0]));
    9911114            /*appp[cur_group] = NULL; - already NULL */
    9921115            appp[cur_group+1] = NULL;
     
    10311154            int i;
    10321155            action_exec *ap;
     1156            IF_FEATURE_FIND_EXEC_PLUS(int all_subst = 0;)
    10331157            dbg("%d", __LINE__);
    10341158            G.need_print = 0;
     
    10431167                // find -exec echo Foo ">{}<" "+"
    10441168                // executes "echo Foo FILENAME1 FILENAME2 FILENAME3...".
    1045                 // TODO (so far we treat "+" just like ";")
    10461169                if ((argv[0][0] == ';' || argv[0][0] == '+')
    10471170                 && argv[0][1] == '\0'
    10481171                ) {
     1172# if ENABLE_FEATURE_FIND_EXEC_PLUS
     1173                    if (argv[0][0] == '+')
     1174                        ap->filelist = xzalloc(sizeof(ap->filelist[0]));
     1175# endif
    10491176                    break;
    10501177                }
     
    10561183            ap->subst_count = xmalloc(ap->exec_argc * sizeof(int));
    10571184            i = ap->exec_argc;
    1058             while (i--)
    1059                 ap->subst_count[i] = count_subst(ap->exec_argv[i]);
     1185            while (i--) {
     1186                ap->subst_count[i] = count_strstr(ap->exec_argv[i], "{}");
     1187                IF_FEATURE_FIND_EXEC_PLUS(all_subst += ap->subst_count[i];)
     1188            }
     1189# if ENABLE_FEATURE_FIND_EXEC_PLUS
     1190            /*
     1191             * coreutils expects {} to appear only once in "-exec +"
     1192             */
     1193            if (all_subst != 1 && ap->filelist)
     1194                bb_error_msg_and_die("only one '{}' allowed for -exec +");
     1195# endif
    10601196        }
    10611197#endif
     
    11201256 *              Symbolic modes use mode 0 as a point of departure.
    11211257 * -perm -BITS  All of the BITS are set in file's mode.
    1122  * -perm +BITS  At least one of the BITS is set in file's mode.
     1258 * -perm [+/]BITS  At least one of the BITS is set in file's mode.
    11231259 */
    11241260        else if (parm == PARM_perm) {
     
    11271263            ap = ALLOC_ACTION(perm);
    11281264            ap->perm_char = arg1[0];
    1129             arg1 = plus_minus_num(arg1);
     1265            arg1 = (arg1[0] == '/' ? arg1+1 : plus_minus_num(arg1));
    11301266            /*ap->perm_mask = 0; - ALLOC_ACTION did it */
    1131             if (!bb_parse_mode(arg1, &ap->perm_mask))
     1267            ap->perm_mask = bb_parse_mode(arg1, ap->perm_mask);
     1268            if (ap->perm_mask == (mode_t)-1)
    11321269                bb_error_msg_and_die("invalid mode '%s'", arg1);
    11331270        }
     
    12461383    return appp;
    12471384#undef ALLOC_ACTION
     1385#undef appp
     1386#undef cur_action
     1387#undef invert_flag
    12481388}
    12491389
     
    12521392{
    12531393    int i, firstopt, status = EXIT_SUCCESS;
     1394    char **past_HLP, *saved;
    12541395
    12551396    INIT_G();
    12561397
    1257     argv++;
     1398    /* "find -type f" + getopt("+HLP") => disaster.
     1399     * Need to avoid getopt running into a non-HLP option.
     1400     * Do this by temporarily storing NULL there:
     1401     */
     1402    past_HLP = argv;
     1403    for (;;) {
     1404        saved = *++past_HLP;
     1405        if (!saved)
     1406            break;
     1407        if (saved[0] != '-')
     1408            break;
     1409        if (!saved[1])
     1410            break; /* it is "-" */
     1411        if ((saved+1)[strspn(saved+1, "HLP")] != '\0')
     1412            break;
     1413    }
     1414    *past_HLP = NULL;
     1415    /* "+": stop on first non-option */
     1416    i = getopt32(argv, "+HLP");
     1417    if (i & (1<<0))
     1418        G.recurse_flags |= ACTION_FOLLOWLINKS_L0 | ACTION_DANGLING_OK;
     1419    if (i & (1<<1))
     1420        G.recurse_flags |= ACTION_FOLLOWLINKS | ACTION_DANGLING_OK;
     1421    /* -P is default and is ignored */
     1422    argv = past_HLP; /* same result as "argv += optind;" */
     1423    *past_HLP = saved;
     1424
    12581425    for (firstopt = 0; argv[firstopt]; firstopt++) {
    12591426        if (argv[firstopt][0] == '-')
     
    12981465                0)              /* depth */
    12991466        ) {
    1300             status = EXIT_FAILURE;
    1301         }
    1302     }
    1303 
     1467            status |= EXIT_FAILURE;
     1468        }
     1469    }
     1470
     1471    IF_FEATURE_FIND_EXEC_PLUS(status |= flush_exec_plus();)
    13041472    return status;
    13051473}
Note: See TracChangeset for help on using the changeset viewer.