Changeset 3232 in MondoRescue for branches/3.2/mindi-busybox/findutils/find.c


Ignore:
Timestamp:
Jan 1, 2014, 12:47:38 AM (10 years ago)
Author:
Bruno Cornec
Message:
  • Update mindi-busybox to 1.21.1
File:
1 edited

Legend:

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

    r2725 r3232  
    5454 */
    5555
    56 //applet:IF_FIND(APPLET_NOEXEC(find, find, _BB_DIR_USR_BIN, _BB_SUID_DROP, find))
    57 
    58 //kbuild:lib-$(CONFIG_FIND) += find.o
    59 
    6056//config:config FIND
    6157//config:   bool "find"
     
    113109//config:
    114110//config:config FEATURE_FIND_MAXDEPTH
    115 //config:   bool "Enable -maxdepth N"
    116 //config:   default y
    117 //config:   depends on FIND
    118 //config:   help
    119 //config:     This option enables -maxdepth N option.
     111//config:   bool "Enable -mindepth N and -maxdepth N"
     112//config:   default y
     113//config:   depends on FIND
     114//config:   help
     115//config:     This option enables -mindepth N and -maxdepth N option.
    120116//config:
    121117//config:config FEATURE_FIND_NEWER
     
    125121//config:   help
    126122//config:     Support the 'find -newer' option for finding any files which have
    127 //config:     a modified time that is more recent than the specified FILE.
     123//config:     modification time that is more recent than the specified FILE.
    128124//config:
    129125//config:config FEATURE_FIND_INUM
     
    231227//config:     Support the 'find -links' option for matching number of links.
    232228
     229//applet:IF_FIND(APPLET_NOEXEC(find, find, BB_DIR_USR_BIN, BB_SUID_DROP, find))
     230
     231//kbuild:lib-$(CONFIG_FIND) += find.o
     232
     233//usage:#define find_trivial_usage
     234//usage:       "[PATH]... [OPTIONS] [ACTIONS]"
     235//usage:#define find_full_usage "\n\n"
     236//usage:       "Search for files and perform actions on them.\n"
     237//usage:       "First failed action stops processing of current file.\n"
     238//usage:       "Defaults: PATH is current directory, action is '-print'\n"
     239//usage:     "\n    -follow     Follow symlinks"
     240//usage:    IF_FEATURE_FIND_XDEV(
     241//usage:     "\n    -xdev       Don't descend directories on other filesystems"
     242//usage:    )
     243//usage:    IF_FEATURE_FIND_MAXDEPTH(
     244//usage:     "\n    -maxdepth N Descend at most N levels. -maxdepth 0 applies"
     245//usage:     "\n            actions to command line arguments only"
     246//usage:     "\n    -mindepth N Don't act on first N levels"
     247//usage:    )
     248//usage:    IF_FEATURE_FIND_DEPTH(
     249//usage:     "\n    -depth      Act on directory *after* traversing it"
     250//usage:    )
     251//usage:     "\n"
     252//usage:     "\nActions:"
     253//usage:    IF_FEATURE_FIND_PAREN(
     254//usage:     "\n    ( ACTIONS ) Group actions for -o / -a"
     255//usage:    )
     256//usage:    IF_FEATURE_FIND_NOT(
     257//usage:     "\n    ! ACT       Invert ACT's success/failure"
     258//usage:    )
     259//usage:     "\n    ACT1 [-a] ACT2  If ACT1 fails, stop, else do ACT2"
     260//usage:     "\n    ACT1 -o ACT2    If ACT1 succeeds, stop, else do ACT2"
     261//usage:     "\n            Note: -a has higher priority than -o"
     262//usage:     "\n    -name PATTERN   Match file name (w/o directory name) to PATTERN"
     263//usage:     "\n    -iname PATTERN  Case insensitive -name"
     264//usage:    IF_FEATURE_FIND_PATH(
     265//usage:     "\n    -path PATTERN   Match path to PATTERN"
     266//usage:     "\n    -ipath PATTERN  Case insensitive -path"
     267//usage:    )
     268//usage:    IF_FEATURE_FIND_REGEX(
     269//usage:     "\n    -regex PATTERN  Match path to regex PATTERN"
     270//usage:    )
     271//usage:    IF_FEATURE_FIND_TYPE(
     272//usage:     "\n    -type X     File type is X (one of: f,d,l,b,c,...)"
     273//usage:    )
     274//usage:    IF_FEATURE_FIND_PERM(
     275//usage:     "\n    -perm MASK  At least one mask bit (+MASK), all bits (-MASK),"
     276//usage:     "\n            or exactly MASK bits are set in file's mode"
     277//usage:    )
     278//usage:    IF_FEATURE_FIND_MTIME(
     279//usage:     "\n    -mtime DAYS mtime is greater than (+N), less than (-N),"
     280//usage:     "\n            or exactly N days in the past"
     281//usage:    )
     282//usage:    IF_FEATURE_FIND_MMIN(
     283//usage:     "\n    -mmin MINS  mtime is greater than (+N), less than (-N),"
     284//usage:     "\n            or exactly N minutes in the past"
     285//usage:    )
     286//usage:    IF_FEATURE_FIND_NEWER(
     287//usage:     "\n    -newer FILE mtime is more recent than FILE's"
     288//usage:    )
     289//usage:    IF_FEATURE_FIND_INUM(
     290//usage:     "\n    -inum N     File has inode number N"
     291//usage:    )
     292//usage:    IF_FEATURE_FIND_USER(
     293//usage:     "\n    -user NAME/ID   File is owned by given user"
     294//usage:    )
     295//usage:    IF_FEATURE_FIND_GROUP(
     296//usage:     "\n    -group NAME/ID  File is owned by given group"
     297//usage:    )
     298//usage:    IF_FEATURE_FIND_SIZE(
     299//usage:     "\n    -size N[bck]    File size is N (c:bytes,k:kbytes,b:512 bytes(def.))"
     300//usage:     "\n            +/-N: file size is bigger/smaller than N"
     301//usage:    )
     302//usage:    IF_FEATURE_FIND_LINKS(
     303//usage:     "\n    -links N    Number of links is greater than (+N), less than (-N),"
     304//usage:     "\n            or exactly N"
     305//usage:    )
     306//usage:    IF_FEATURE_FIND_CONTEXT(
     307//usage:     "\n    -context CTX    File has specified security context"
     308//usage:    )
     309//usage:    IF_FEATURE_FIND_PRUNE(
     310//usage:     "\n    -prune      If current file is directory, don't descend into it"
     311//usage:    )
     312//usage:     "\nIf none of the following actions is specified, -print is assumed"
     313//usage:     "\n    -print      Print file name"
     314//usage:    IF_FEATURE_FIND_PRINT0(
     315//usage:     "\n    -print0     Print file name, NUL terminated"
     316//usage:    )
     317//usage:    IF_FEATURE_FIND_EXEC(
     318//usage:     "\n    -exec CMD ARG ; Run CMD with all instances of {} replaced by"
     319//usage:     "\n            file name. Fails if CMD exits with nonzero"
     320//usage:    )
     321//usage:    IF_FEATURE_FIND_DELETE(
     322//usage:     "\n    -delete     Delete current file/directory. Turns on -depth option"
     323//usage:    )
     324//usage:
     325//usage:#define find_example_usage
     326//usage:       "$ find / -name passwd\n"
     327//usage:       "/etc/passwd\n"
     328
    233329#include <fnmatch.h>
    234330#include "libbb.h"
    235331#if ENABLE_FEATURE_FIND_REGEX
    236 #include "xregex.h"
    237 #endif
     332# include "xregex.h"
     333#endif
     334/* GNUism: */
     335#ifndef FNM_CASEFOLD
     336# define FNM_CASEFOLD 0
     337#endif
     338
     339#define dbg(...) ((void)0)
     340/* #define dbg(...) bb_error_msg(__VA_ARGS__) */
    238341
    239342/* This is a NOEXEC applet. Be very careful! */
     
    257360                        ACTS(print)
    258361                        ACTS(name,  const char *pattern; bool iname;)
    259 IF_FEATURE_FIND_PATH(   ACTS(path,  const char *pattern;))
     362IF_FEATURE_FIND_PATH(   ACTS(path,  const char *pattern; bool ipath;))
    260363IF_FEATURE_FIND_REGEX(  ACTS(regex, regex_t compiled_pattern;))
    261364IF_FEATURE_FIND_PRINT0( ACTS(print0))
     
    279382    IF_FEATURE_FIND_XDEV(dev_t *xdev_dev;)
    280383    IF_FEATURE_FIND_XDEV(int xdev_count;)
     384#if ENABLE_FEATURE_FIND_MAXDEPTH
     385    int minmaxdepth[2];
     386#endif
    281387    action ***actions;
    282     bool need_print;
     388    smallint need_print;
     389    smallint xdev_on;
    283390    recurse_flags_t recurse_flags;
    284391} FIX_ALIASING;
     
    289396    }; \
    290397    /* we have to zero it out because of NOEXEC */ \
    291     memset(&G, 0, offsetof(struct globals, need_print)); \
     398    memset(&G, 0, sizeof(G)); \
     399    IF_FEATURE_FIND_MAXDEPTH(G.minmaxdepth[1] = INT_MAX;) \
    292400    G.need_print = 1; \
    293401    G.recurse_flags = ACTION_RECURSE; \
     
    365473            if (ap->invert) rc ^= TRUE;
    366474#endif
     475            dbg("grp %d action %d rc:0x%x", cur_group, cur_action, rc);
    367476            if (rc & TRUE) /* current group failed, try next */
    368477                break;
    369478        }
    370479    }
     480    dbg("returning:0x%x", rc ^ TRUE);
    371481    return rc ^ TRUE; /* restore TRUE bit */
    372482}
    373483
     484
     485#if !FNM_CASEFOLD
     486static char *strcpy_upcase(char *dst, const char *src)
     487{
     488    char *d = dst;
     489    while (1) {
     490        unsigned char ch = *src++;
     491        if (ch >= 'a' && ch <= 'z')
     492            ch -= ('a' - 'A');
     493        *d++ = ch;
     494        if (ch == '\0')
     495            break;
     496    }
     497    return dst;
     498}
     499#endif
    374500
    375501ACTF(name)
     
    388514     * find -name '*foo' should match .foo too:
    389515     */
     516#if FNM_CASEFOLD
    390517    return fnmatch(ap->pattern, tmp, (ap->iname ? FNM_CASEFOLD : 0)) == 0;
     518#else
     519    if (ap->iname)
     520        tmp = strcpy_upcase(alloca(strlen(tmp) + 1), tmp);
     521    return fnmatch(ap->pattern, tmp, 0) == 0;
     522#endif
    391523}
    392524
     
    394526ACTF(path)
    395527{
     528# if FNM_CASEFOLD
     529    return fnmatch(ap->pattern, fileName, (ap->ipath ? FNM_CASEFOLD : 0)) == 0;
     530# else
     531    if (ap->ipath)
     532        fileName = strcpy_upcase(alloca(strlen(fileName) + 1), fileName);
    396533    return fnmatch(ap->pattern, fileName, 0) == 0;
     534# endif
    397535}
    398536#endif
     
    587725static int FAST_FUNC fileAction(const char *fileName,
    588726        struct stat *statbuf,
    589         void *userData IF_NOT_FEATURE_FIND_MAXDEPTH(UNUSED_PARAM),
     727        void *userData UNUSED_PARAM,
    590728        int depth IF_NOT_FEATURE_FIND_MAXDEPTH(UNUSED_PARAM))
    591729{
    592730    int r;
     731    int same_fs = 1;
     732
     733#if ENABLE_FEATURE_FIND_XDEV
     734    if (S_ISDIR(statbuf->st_mode) && G.xdev_count) {
     735        int i;
     736        for (i = 0; i < G.xdev_count; i++) {
     737            if (G.xdev_dev[i] == statbuf->st_dev)
     738                goto found;
     739        }
     740        //bb_error_msg("'%s': not same fs", fileName);
     741        same_fs = 0;
     742 found: ;
     743    }
     744#endif
     745
    593746#if ENABLE_FEATURE_FIND_MAXDEPTH
    594 #define minmaxdepth ((int*)userData)
    595 
    596     if (depth < minmaxdepth[0])
    597         return TRUE; /* skip this, continue recursing */
    598     if (depth > minmaxdepth[1])
     747    if (depth < G.minmaxdepth[0]) {
     748        if (same_fs)
     749            return TRUE; /* skip this, continue recursing */
     750        return SKIP; /* stop recursing */
     751    }
     752    if (depth > G.minmaxdepth[1])
    599753        return SKIP; /* stop recursing */
    600754#endif
     
    607761#if ENABLE_FEATURE_FIND_MAXDEPTH
    608762    if (S_ISDIR(statbuf->st_mode)) {
    609         if (depth == minmaxdepth[1])
     763        if (depth == G.minmaxdepth[1])
    610764            return SKIP;
    611765    }
    612766#endif
    613 #if ENABLE_FEATURE_FIND_XDEV
    614767    /* -xdev stops on mountpoints, but AFTER mountpoit itself
    615768     * is processed as usual */
    616     if (S_ISDIR(statbuf->st_mode)) {
    617         if (G.xdev_count) {
    618             int i;
    619             for (i = 0; i < G.xdev_count; i++) {
    620                 if (G.xdev_dev[i] == statbuf->st_dev)
    621                     goto found;
    622             }
    623             return SKIP;
    624  found: ;
    625         }
    626     }
    627 #endif
     769    if (!same_fs) {
     770        return SKIP;
     771    }
    628772
    629773    /* Cannot return 0: our caller, recursive_action(),
    630774     * will perror() and skip dirs (if called on dir) */
    631775    return (r & SKIP) ? SKIP : TRUE;
    632 #undef minmaxdepth
    633776}
    634777
     
    675818{
    676819    enum {
     820                            OPT_FOLLOW     ,
     821    IF_FEATURE_FIND_XDEV(   OPT_XDEV       ,)
     822    IF_FEATURE_FIND_DEPTH(  OPT_DEPTH      ,)
    677823                            PARM_a         ,
    678824                            PARM_o         ,
     
    685831                            PARM_print     ,
    686832    IF_FEATURE_FIND_PRINT0( PARM_print0    ,)
    687     IF_FEATURE_FIND_DEPTH(  PARM_depth     ,)
    688833    IF_FEATURE_FIND_PRUNE(  PARM_prune     ,)
    689834    IF_FEATURE_FIND_DELETE( PARM_delete    ,)
    690835    IF_FEATURE_FIND_EXEC(   PARM_exec      ,)
    691836    IF_FEATURE_FIND_PAREN(  PARM_char_brace,)
    692     /* All options starting from here require argument */
     837    /* All options/actions starting from here require argument */
    693838                            PARM_name      ,
    694839                            PARM_iname     ,
    695840    IF_FEATURE_FIND_PATH(   PARM_path      ,)
     841#if ENABLE_DESKTOP
     842    /* -wholename is a synonym for -path */
     843    /* We support it because Linux kernel's "make tags" uses it */
     844    IF_FEATURE_FIND_PATH(   PARM_wholename ,)
     845#endif
     846    IF_FEATURE_FIND_PATH(   PARM_ipath     ,)
    696847    IF_FEATURE_FIND_REGEX(  PARM_regex     ,)
    697848    IF_FEATURE_FIND_TYPE(   PARM_type      ,)
     
    706857    IF_FEATURE_FIND_CONTEXT(PARM_context   ,)
    707858    IF_FEATURE_FIND_LINKS(  PARM_links     ,)
     859    IF_FEATURE_FIND_MAXDEPTH(OPT_MINDEPTH,OPT_MAXDEPTH,)
    708860    };
    709861
    710862    static const char params[] ALIGN1 =
    711                              "-a\0"
    712                              "-o\0"
     863                            "-follow\0"
     864    IF_FEATURE_FIND_XDEV(   "-xdev\0"                 )
     865    IF_FEATURE_FIND_DEPTH(  "-depth\0"                )
     866                            "-a\0"
     867                            "-o\0"
    713868    IF_FEATURE_FIND_NOT(    "!\0"       )
    714869#if ENABLE_DESKTOP
    715                              "-and\0"
    716                              "-or\0"
    717     IF_FEATURE_FIND_NOT(     "-not\0"    )
    718 #endif
    719                              "-print\0"
     870                            "-and\0"
     871                            "-or\0"
     872    IF_FEATURE_FIND_NOT(    "-not\0"    )
     873#endif
     874                            "-print\0"
    720875    IF_FEATURE_FIND_PRINT0( "-print0\0" )
    721     IF_FEATURE_FIND_DEPTH(  "-depth\0"  )
    722876    IF_FEATURE_FIND_PRUNE(  "-prune\0"  )
    723877    IF_FEATURE_FIND_DELETE( "-delete\0" )
    724878    IF_FEATURE_FIND_EXEC(   "-exec\0"   )
    725879    IF_FEATURE_FIND_PAREN(  "(\0"       )
    726     /* All options starting from here require argument */
    727                              "-name\0"
    728                              "-iname\0"
     880    /* All options/actions starting from here require argument */
     881                            "-name\0"
     882                            "-iname\0"
    729883    IF_FEATURE_FIND_PATH(   "-path\0"   )
     884#if ENABLE_DESKTOP
     885    IF_FEATURE_FIND_PATH(   "-wholename\0")
     886#endif
     887    IF_FEATURE_FIND_PATH(   "-ipath\0"  )
    730888    IF_FEATURE_FIND_REGEX(  "-regex\0"  )
    731889    IF_FEATURE_FIND_TYPE(   "-type\0"   )
     
    740898    IF_FEATURE_FIND_CONTEXT("-context\0")
    741899    IF_FEATURE_FIND_LINKS(  "-links\0"  )
    742                              ;
     900    IF_FEATURE_FIND_MAXDEPTH("-mindepth\0""-maxdepth\0")
     901    ;
    743902
    744903    action*** appp;
     
    767926    appp = xzalloc(2 * sizeof(appp[0])); /* appp[0],[1] == NULL */
    768927
    769 /* Actions have side effects and return a true or false value
    770  * We implement: -print, -print0, -exec
    771  *
    772  * The rest are tests.
    773  *
    774  * Tests and actions are grouped by operators
     928    while (*argv) {
     929        const char *arg = argv[0];
     930        int parm = index_in_strings(params, arg);
     931        const char *arg1 = argv[1];
     932
     933        dbg("arg:'%s' arg1:'%s' parm:%d PARM_type:%d", arg, arg1, parm, PARM_type);
     934
     935        if (parm >= PARM_name) {
     936            /* All options/actions starting from -name require argument */
     937            if (!arg1)
     938                bb_error_msg_and_die(bb_msg_requires_arg, arg);
     939            argv++;
     940        }
     941
     942        /* We can use big switch() here, but on i386
     943         * it doesn't give smaller code. Other arches? */
     944
     945/* Options always return true. They always take effect
     946 * rather than being processed only when their place in the
     947 * expression is reached.
     948 */
     949        /* Options */
     950        if (parm == OPT_FOLLOW) {
     951                        dbg("follow enabled: %d", __LINE__);
     952                        G.recurse_flags |= ACTION_FOLLOWLINKS | ACTION_DANGLING_OK;
     953        }
     954#if ENABLE_FEATURE_FIND_XDEV
     955        else if (parm == OPT_XDEV) {
     956            dbg("%d", __LINE__);
     957            G.xdev_on = 1;
     958        }
     959#endif
     960#if ENABLE_FEATURE_FIND_MAXDEPTH
     961        else if (parm == OPT_MINDEPTH || parm == OPT_MINDEPTH + 1) {
     962            dbg("%d", __LINE__);
     963            G.minmaxdepth[parm - OPT_MINDEPTH] = xatoi_positive(arg1);
     964        }
     965#endif
     966#if ENABLE_FEATURE_FIND_DEPTH
     967        else if (parm == OPT_DEPTH) {
     968            dbg("%d", __LINE__);
     969            G.recurse_flags |= ACTION_DEPTHFIRST;
     970        }
     971#endif
     972/* Actions are grouped by operators
    775973 * ( expr )              Force precedence
    776974 * ! expr                True if expr is false
     
    781979 * We implement: (), -a, -o
    782980 */
    783     while (*argv) {
    784         const char *arg = argv[0];
    785         int parm = index_in_strings(params, arg);
    786         const char *arg1 = argv[1];
    787 
    788         if (parm >= PARM_name) {
    789             /* All options starting from -name require argument */
    790             if (!arg1)
    791                 bb_error_msg_and_die(bb_msg_requires_arg, arg);
    792             argv++;
    793         }
    794 
    795         /* We can use big switch() here, but on i386
    796          * it doesn't give smaller code. Other arches? */
    797 
    798     /* --- Operators --- */
    799         if (parm == PARM_a IF_DESKTOP(|| parm == PARM_and)) {
     981        /* Operators */
     982        else if (parm == PARM_a IF_DESKTOP(|| parm == PARM_and)) {
     983            dbg("%d", __LINE__);
    800984            /* no further special handling required */
    801985        }
    802986        else if (parm == PARM_o IF_DESKTOP(|| parm == PARM_or)) {
     987            dbg("%d", __LINE__);
    803988            /* start new OR group */
    804989            cur_group++;
     
    812997            /* also handles "find ! ! -name 'foo*'" */
    813998            invert_flag ^= 1;
    814         }
    815 #endif
    816 
    817     /* --- Tests and actions --- */
     999            dbg("invert_flag:%d", invert_flag);
     1000        }
     1001#endif
     1002        /* Actions */
    8181003        else if (parm == PARM_print) {
     1004            dbg("%d", __LINE__);
    8191005            G.need_print = 0;
    820             /* GNU find ignores '!' here: "find ! -print" */
    821             IF_FEATURE_FIND_NOT( invert_flag = 0; )
    8221006            (void) ALLOC_ACTION(print);
    8231007        }
    8241008#if ENABLE_FEATURE_FIND_PRINT0
    8251009        else if (parm == PARM_print0) {
     1010            dbg("%d", __LINE__);
    8261011            G.need_print = 0;
    827             IF_FEATURE_FIND_NOT( invert_flag = 0; )
    8281012            (void) ALLOC_ACTION(print0);
    829         }
    830 #endif
    831 #if ENABLE_FEATURE_FIND_DEPTH
    832         else if (parm == PARM_depth) {
    833             G.recurse_flags |= ACTION_DEPTHFIRST;
    8341013        }
    8351014#endif
    8361015#if ENABLE_FEATURE_FIND_PRUNE
    8371016        else if (parm == PARM_prune) {
    838             IF_FEATURE_FIND_NOT( invert_flag = 0; )
     1017            dbg("%d", __LINE__);
    8391018            (void) ALLOC_ACTION(prune);
    8401019        }
     
    8421021#if ENABLE_FEATURE_FIND_DELETE
    8431022        else if (parm == PARM_delete) {
     1023            dbg("%d", __LINE__);
    8441024            G.need_print = 0;
    8451025            G.recurse_flags |= ACTION_DEPTHFIRST;
     
    8511031            int i;
    8521032            action_exec *ap;
     1033            dbg("%d", __LINE__);
    8531034            G.need_print = 0;
    854             IF_FEATURE_FIND_NOT( invert_flag = 0; )
    8551035            ap = ALLOC_ACTION(exec);
    8561036            ap->exec_argv = ++argv; /* first arg after -exec */
     
    8601040                    bb_error_msg_and_die(bb_msg_requires_arg, "-exec");
    8611041                // find -exec echo Foo ">{}<" ";"
    862                 // executes "echo Foo <filename>",
     1042                // executes "echo Foo >FILENAME<",
    8631043                // find -exec echo Foo ">{}<" "+"
    864                 // executes "echo Foo <filename1> <filename2> <filename3>...".
     1044                // executes "echo Foo FILENAME1 FILENAME2 FILENAME3...".
    8651045                // TODO (so far we treat "+" just like ";")
    8661046                if ((argv[0][0] == ';' || argv[0][0] == '+')
     
    8861066            unsigned nested = 1;
    8871067
     1068            dbg("%d", __LINE__);
    8881069            endarg = argv;
    8891070            while (1) {
     
    9051086        else if (parm == PARM_name || parm == PARM_iname) {
    9061087            action_name *ap;
     1088            dbg("%d", __LINE__);
    9071089            ap = ALLOC_ACTION(name);
    9081090            ap->pattern = arg1;
     
    9101092        }
    9111093#if ENABLE_FEATURE_FIND_PATH
    912         else if (parm == PARM_path) {
     1094        else if (parm == PARM_path IF_DESKTOP(|| parm == PARM_wholename) || parm == PARM_ipath) {
    9131095            action_path *ap;
     1096            dbg("%d", __LINE__);
    9141097            ap = ALLOC_ACTION(path);
    9151098            ap->pattern = arg1;
     1099            ap->ipath = (parm == PARM_ipath);
    9161100        }
    9171101#endif
     
    9191103        else if (parm == PARM_regex) {
    9201104            action_regex *ap;
     1105            dbg("%d", __LINE__);
    9211106            ap = ALLOC_ACTION(regex);
    9221107            xregcomp(&ap->compiled_pattern, arg1, 0 /*cflags*/);
     
    9281113            ap = ALLOC_ACTION(type);
    9291114            ap->type_mask = find_type(arg1);
     1115            dbg("created:type mask:%x", ap->type_mask);
    9301116        }
    9311117#endif
    9321118#if ENABLE_FEATURE_FIND_PERM
    933 /* -perm mode   File's permission bits are exactly mode (octal or symbolic).
     1119/* -perm BITS   File's mode bits are exactly BITS (octal or symbolic).
    9341120 *              Symbolic modes use mode 0 as a point of departure.
    935  * -perm -mode  All of the permission bits mode are set for the file.
    936  * -perm +mode  Any of the permission bits mode are set for the file.
     1121 * -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.
    9371123 */
    9381124        else if (parm == PARM_perm) {
    9391125            action_perm *ap;
     1126            dbg("%d", __LINE__);
    9401127            ap = ALLOC_ACTION(perm);
    9411128            ap->perm_char = arg1[0];
     
    9491136        else if (parm == PARM_mtime) {
    9501137            action_mtime *ap;
     1138            dbg("%d", __LINE__);
    9511139            ap = ALLOC_ACTION(mtime);
    9521140            ap->mtime_char = arg1[0];
     
    9571145        else if (parm == PARM_mmin) {
    9581146            action_mmin *ap;
     1147            dbg("%d", __LINE__);
    9591148            ap = ALLOC_ACTION(mmin);
    9601149            ap->mmin_char = arg1[0];
     
    9661155            struct stat stat_newer;
    9671156            action_newer *ap;
     1157            dbg("%d", __LINE__);
    9681158            ap = ALLOC_ACTION(newer);
    9691159            xstat(arg1, &stat_newer);
     
    9741164        else if (parm == PARM_inum) {
    9751165            action_inum *ap;
     1166            dbg("%d", __LINE__);
    9761167            ap = ALLOC_ACTION(inum);
    9771168            ap->inode_num = xatoul(arg1);
     
    9811172        else if (parm == PARM_user) {
    9821173            action_user *ap;
     1174            dbg("%d", __LINE__);
    9831175            ap = ALLOC_ACTION(user);
    9841176            ap->uid = bb_strtou(arg1, NULL, 10);
     
    9901182        else if (parm == PARM_group) {
    9911183            action_group *ap;
     1184            dbg("%d", __LINE__);
    9921185            ap = ALLOC_ACTION(group);
    9931186            ap->gid = bb_strtou(arg1, NULL, 10);
     
    10181211            };
    10191212            action_size *ap;
     1213            dbg("%d", __LINE__);
    10201214            ap = ALLOC_ACTION(size);
    10211215            ap->size_char = arg1[0];
     
    10261220        else if (parm == PARM_context) {
    10271221            action_context *ap;
     1222            dbg("%d", __LINE__);
    10281223            ap = ALLOC_ACTION(context);
    10291224            /*ap->context = NULL; - ALLOC_ACTION did it */
     
    10361231        else if (parm == PARM_links) {
    10371232            action_links *ap;
     1233            dbg("%d", __LINE__);
    10381234            ap = ALLOC_ACTION(links);
    10391235            ap->links_char = arg1[0];
     
    10471243        argv++;
    10481244    }
     1245    dbg("exiting %s", __func__);
    10491246    return appp;
    10501247#undef ALLOC_ACTION
    10511248}
    10521249
    1053 //usage:#define find_trivial_usage
    1054 //usage:       "[PATH]... [EXPRESSION]"
    1055 //usage:#define find_full_usage "\n\n"
    1056 //usage:       "Search for files. The default PATH is the current directory,\n"
    1057 //usage:       "default EXPRESSION is '-print'\n"
    1058 //usage:     "\nEXPRESSION may consist of:"
    1059 //usage:     "\n    -follow     Follow symlinks"
    1060 //usage:    IF_FEATURE_FIND_XDEV(
    1061 //usage:     "\n    -xdev       Don't descend directories on other filesystems"
    1062 //usage:    )
    1063 //usage:    IF_FEATURE_FIND_MAXDEPTH(
    1064 //usage:     "\n    -maxdepth N Descend at most N levels. -maxdepth 0 applies"
    1065 //usage:     "\n            tests/actions to command line arguments only"
    1066 //usage:    )
    1067 //usage:     "\n    -mindepth N Don't act on first N levels"
    1068 //usage:     "\n    -name PATTERN   File name (w/o directory name) matches PATTERN"
    1069 //usage:     "\n    -iname PATTERN  Case insensitive -name"
    1070 //usage:    IF_FEATURE_FIND_PATH(
    1071 //usage:     "\n    -path PATTERN   Path matches PATTERN"
    1072 //usage:    )
    1073 //usage:    IF_FEATURE_FIND_REGEX(
    1074 //usage:     "\n    -regex PATTERN  Path matches regex PATTERN"
    1075 //usage:    )
    1076 //usage:    IF_FEATURE_FIND_TYPE(
    1077 //usage:     "\n    -type X     File type is X (X is one of: f,d,l,b,c,...)"
    1078 //usage:    )
    1079 //usage:    IF_FEATURE_FIND_PERM(
    1080 //usage:     "\n    -perm NNN   Permissions match any of (+NNN), all of (-NNN),"
    1081 //usage:     "\n            or exactly NNN"
    1082 //usage:    )
    1083 //usage:    IF_FEATURE_FIND_MTIME(
    1084 //usage:     "\n    -mtime DAYS Modified time is greater than (+N), less than (-N),"
    1085 //usage:     "\n            or exactly N days"
    1086 //usage:    )
    1087 //usage:    IF_FEATURE_FIND_MMIN(
    1088 //usage:     "\n    -mmin MINS  Modified time is greater than (+N), less than (-N),"
    1089 //usage:     "\n            or exactly N minutes"
    1090 //usage:    )
    1091 //usage:    IF_FEATURE_FIND_NEWER(
    1092 //usage:     "\n    -newer FILE Modified time is more recent than FILE's"
    1093 //usage:    )
    1094 //usage:    IF_FEATURE_FIND_INUM(
    1095 //usage:     "\n    -inum N     File has inode number N"
    1096 //usage:    )
    1097 //usage:    IF_FEATURE_FIND_USER(
    1098 //usage:     "\n    -user NAME  File is owned by user NAME (numeric user ID allowed)"
    1099 //usage:    )
    1100 //usage:    IF_FEATURE_FIND_GROUP(
    1101 //usage:     "\n    -group NAME File belongs to group NAME (numeric group ID allowed)"
    1102 //usage:    )
    1103 //usage:    IF_FEATURE_FIND_DEPTH(
    1104 //usage:     "\n    -depth      Process directory name after traversing it"
    1105 //usage:    )
    1106 //usage:    IF_FEATURE_FIND_SIZE(
    1107 //usage:     "\n    -size N[bck]    File size is N (c:bytes,k:kbytes,b:512 bytes(def.))"
    1108 //usage:     "\n            +/-N: file size is bigger/smaller than N"
    1109 //usage:    )
    1110 //usage:    IF_FEATURE_FIND_LINKS(
    1111 //usage:     "\n    -links N    Number of links is greater than (+N), less than (-N),"
    1112 //usage:     "\n            or exactly N"
    1113 //usage:    )
    1114 //usage:     "\n    -print      Print (default and assumed)"
    1115 //usage:    IF_FEATURE_FIND_PRINT0(
    1116 //usage:     "\n    -print0     Delimit output with null characters rather than"
    1117 //usage:     "\n            newlines"
    1118 //usage:    )
    1119 //usage:    IF_FEATURE_FIND_CONTEXT(
    1120 //usage:     "\n    -context    File has specified security context"
    1121 //usage:    )
    1122 //usage:    IF_FEATURE_FIND_EXEC(
    1123 //usage:     "\n    -exec CMD ARG ; Run CMD with all instances of {} replaced by the"
    1124 //usage:     "\n            matching files"
    1125 //usage:    )
    1126 //usage:    IF_FEATURE_FIND_PRUNE(
    1127 //usage:     "\n    -prune      Stop traversing current subtree"
    1128 //usage:    )
    1129 //usage:    IF_FEATURE_FIND_DELETE(
    1130 //usage:     "\n    -delete     Delete files, turns on -depth option"
    1131 //usage:    )
    1132 //usage:    IF_FEATURE_FIND_PAREN(
    1133 //usage:     "\n    (EXPR)      Group an expression"
    1134 //usage:    )
    1135 //usage:
    1136 //usage:#define find_example_usage
    1137 //usage:       "$ find / -name passwd\n"
    1138 //usage:       "/etc/passwd\n"
    1139 
    11401250int find_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
    11411251int find_main(int argc UNUSED_PARAM, char **argv)
    11421252{
    1143     static const char options[] ALIGN1 =
    1144                       "-follow\0"
    1145 IF_FEATURE_FIND_XDEV(    "-xdev\0"    )
    1146 IF_FEATURE_FIND_MAXDEPTH("-mindepth\0""-maxdepth\0")
    1147                       ;
    1148     enum {
    1149                       OPT_FOLLOW,
    1150 IF_FEATURE_FIND_XDEV(    OPT_XDEV    ,)
    1151 IF_FEATURE_FIND_MAXDEPTH(OPT_MINDEPTH,)
    1152     };
    1153 
    1154     char *arg;
    1155     char **argp;
    11561253    int i, firstopt, status = EXIT_SUCCESS;
    1157 #if ENABLE_FEATURE_FIND_MAXDEPTH
    1158     int minmaxdepth[2] = { 0, INT_MAX };
    1159 #else
    1160 #define minmaxdepth NULL
    1161 #endif
    11621254
    11631255    INIT_G();
    11641256
    1165     for (firstopt = 1; argv[firstopt]; firstopt++) {
     1257    argv++;
     1258    for (firstopt = 0; argv[firstopt]; firstopt++) {
    11661259        if (argv[firstopt][0] == '-')
    11671260            break;
    11681261        if (ENABLE_FEATURE_FIND_NOT && LONE_CHAR(argv[firstopt], '!'))
    11691262            break;
    1170 #if ENABLE_FEATURE_FIND_PAREN
    1171         if (LONE_CHAR(argv[firstopt], '('))
     1263        if (ENABLE_FEATURE_FIND_PAREN && LONE_CHAR(argv[firstopt], '('))
    11721264            break;
    1173 #endif
    1174     }
    1175     if (firstopt == 1) {
    1176         argv[0] = (char*)".";
    1177         argv--;
     1265    }
     1266    if (firstopt == 0) {
     1267        *--argv = (char*)".";
    11781268        firstopt++;
    11791269    }
    11801270
    1181 /* All options always return true. They always take effect
    1182  * rather than being processed only when their place in the
    1183  * expression is reached.
    1184  * We implement: -follow, -xdev, -maxdepth
    1185  */
    1186     /* Process options, and replace then with -a */
    1187     /* (-a will be ignored by recursive parser later) */
    1188     argp = &argv[firstopt];
    1189     while ((arg = argp[0])) {
    1190         int opt = index_in_strings(options, arg);
    1191         if (opt == OPT_FOLLOW) {
    1192             G.recurse_flags |= ACTION_FOLLOWLINKS | ACTION_DANGLING_OK;
    1193             argp[0] = (char*)"-a";
    1194         }
     1271    G.actions = parse_params(&argv[firstopt]);
     1272    argv[firstopt] = NULL;
     1273
    11951274#if ENABLE_FEATURE_FIND_XDEV
    1196         if (opt == OPT_XDEV) {
    1197             struct stat stbuf;
    1198             if (!G.xdev_count) {
    1199                 G.xdev_count = firstopt - 1;
    1200                 G.xdev_dev = xzalloc(G.xdev_count * sizeof(G.xdev_dev[0]));
    1201                 for (i = 1; i < firstopt; i++) {
    1202                     /* not xstat(): shouldn't bomb out on
    1203                      * "find not_exist exist -xdev" */
    1204                     if (stat(argv[i], &stbuf) == 0)
    1205                         G.xdev_dev[i-1] = stbuf.st_dev;
    1206                     /* else G.xdev_dev[i-1] stays 0 and
    1207                      * won't match any real device dev_t */
    1208                 }
    1209             }
    1210             argp[0] = (char*)"-a";
    1211         }
    1212 #endif
    1213 #if ENABLE_FEATURE_FIND_MAXDEPTH
    1214         if (opt == OPT_MINDEPTH || opt == OPT_MINDEPTH + 1) {
    1215             if (!argp[1])
    1216                 bb_show_usage();
    1217             minmaxdepth[opt - OPT_MINDEPTH] = xatoi_positive(argp[1]);
    1218             argp[0] = (char*)"-a";
    1219             argp[1] = (char*)"-a";
    1220             argp++;
    1221         }
    1222 #endif
    1223         argp++;
    1224     }
    1225 
    1226     G.actions = parse_params(&argv[firstopt]);
    1227 
    1228     for (i = 1; i < firstopt; i++) {
     1275    if (G.xdev_on) {
     1276        struct stat stbuf;
     1277
     1278        G.xdev_count = firstopt;
     1279        G.xdev_dev = xzalloc(G.xdev_count * sizeof(G.xdev_dev[0]));
     1280        for (i = 0; argv[i]; i++) {
     1281            /* not xstat(): shouldn't bomb out on
     1282             * "find not_exist exist -xdev" */
     1283            if (stat(argv[i], &stbuf) == 0)
     1284                G.xdev_dev[i] = stbuf.st_dev;
     1285            /* else G.xdev_dev[i] stays 0 and
     1286             * won't match any real device dev_t
     1287             */
     1288        }
     1289    }
     1290#endif
     1291
     1292    for (i = 0; argv[i]; i++) {
    12291293        if (!recursive_action(argv[i],
    12301294                G.recurse_flags,/* flags */
    12311295                fileAction,     /* file action */
    12321296                fileAction,     /* dir action */
    1233 #if ENABLE_FEATURE_FIND_MAXDEPTH
    1234                 minmaxdepth,    /* user data */
    1235 #else
    12361297                NULL,           /* user data */
    1237 #endif
    1238                 0))             /* depth */
     1298                0)              /* depth */
     1299        ) {
    12391300            status = EXIT_FAILURE;
    1240     }
     1301        }
     1302    }
     1303
    12411304    return status;
    12421305}
Note: See TracChangeset for help on using the changeset viewer.