Magellan Linux

Diff of /trunk/mkinitrd-magellan/busybox/findutils/find.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 983 by niro, Fri Apr 24 18:33:46 2009 UTC revision 984 by niro, Sun May 30 11:32:42 2010 UTC
# Line 62  Line 62 
62  /* This is a NOEXEC applet. Be very careful! */  /* This is a NOEXEC applet. Be very careful! */
63    
64    
65  USE_FEATURE_FIND_XDEV(static dev_t *xdev_dev;)  typedef int (*action_fp)(const char *fileName, const struct stat *statbuf, void *) FAST_FUNC;
 USE_FEATURE_FIND_XDEV(static int xdev_count;)  
   
 typedef int (*action_fp)(const char *fileName, struct stat *statbuf, void *);  
66    
67  typedef struct {  typedef struct {
68   action_fp f;   action_fp f;
# Line 73  typedef struct { Line 70  typedef struct {
70   bool invert;   bool invert;
71  #endif  #endif
72  } action;  } action;
73  #define ACTS(name, arg...) typedef struct { action a; arg; } action_##name;  
74  #define ACTF(name)         static int func_##name(const char *fileName UNUSED_PARAM, \  #define ACTS(name, ...) typedef struct { action a; __VA_ARGS__ } action_##name;
75                                                    struct stat *statbuf UNUSED_PARAM, \  #define ACTF(name) \
76                                                    action_##name* ap UNUSED_PARAM)   static int FAST_FUNC func_##name(const char *fileName UNUSED_PARAM, \
77                           ACTS(print)   const struct stat *statbuf UNUSED_PARAM, \
78                           ACTS(name,  const char *pattern; bool iname;)   action_##name* ap UNUSED_PARAM)
79  USE_FEATURE_FIND_PATH(   ACTS(path,  const char *pattern;))  
80  USE_FEATURE_FIND_REGEX(  ACTS(regex, regex_t compiled_pattern;))                          ACTS(print)
81  USE_FEATURE_FIND_PRINT0( ACTS(print0))                          ACTS(name,  const char *pattern; bool iname;)
82  USE_FEATURE_FIND_TYPE(   ACTS(type,  int type_mask;))  IF_FEATURE_FIND_PATH(   ACTS(path,  const char *pattern;))
83  USE_FEATURE_FIND_PERM(   ACTS(perm,  char perm_char; mode_t perm_mask;))  IF_FEATURE_FIND_REGEX(  ACTS(regex, regex_t compiled_pattern;))
84  USE_FEATURE_FIND_MTIME(  ACTS(mtime, char mtime_char; unsigned mtime_days;))  IF_FEATURE_FIND_PRINT0( ACTS(print0))
85  USE_FEATURE_FIND_MMIN(   ACTS(mmin,  char mmin_char; unsigned mmin_mins;))  IF_FEATURE_FIND_TYPE(   ACTS(type,  int type_mask;))
86  USE_FEATURE_FIND_NEWER(  ACTS(newer, time_t newer_mtime;))  IF_FEATURE_FIND_PERM(   ACTS(perm,  char perm_char; mode_t perm_mask;))
87  USE_FEATURE_FIND_INUM(   ACTS(inum,  ino_t inode_num;))  IF_FEATURE_FIND_MTIME(  ACTS(mtime, char mtime_char; unsigned mtime_days;))
88  USE_FEATURE_FIND_USER(   ACTS(user,  uid_t uid;))  IF_FEATURE_FIND_MMIN(   ACTS(mmin,  char mmin_char; unsigned mmin_mins;))
89  USE_FEATURE_FIND_SIZE(   ACTS(size,  char size_char; off_t size;))  IF_FEATURE_FIND_NEWER(  ACTS(newer, time_t newer_mtime;))
90  USE_FEATURE_FIND_CONTEXT(ACTS(context, security_context_t context;))  IF_FEATURE_FIND_INUM(   ACTS(inum,  ino_t inode_num;))
91  USE_FEATURE_FIND_PAREN(  ACTS(paren, action ***subexpr;))  IF_FEATURE_FIND_USER(   ACTS(user,  uid_t uid;))
92  USE_FEATURE_FIND_PRUNE(  ACTS(prune))  IF_FEATURE_FIND_SIZE(   ACTS(size,  char size_char; off_t size;))
93  USE_FEATURE_FIND_DELETE( ACTS(delete))  IF_FEATURE_FIND_CONTEXT(ACTS(context, security_context_t context;))
94  USE_FEATURE_FIND_EXEC(   ACTS(exec,  char **exec_argv; unsigned *subst_count; int exec_argc;))  IF_FEATURE_FIND_PAREN(  ACTS(paren, action ***subexpr;))
95  USE_FEATURE_FIND_GROUP(  ACTS(group, gid_t gid;))  IF_FEATURE_FIND_PRUNE(  ACTS(prune))
96    IF_FEATURE_FIND_DELETE( ACTS(delete))
97  static action ***actions;  IF_FEATURE_FIND_EXEC(   ACTS(exec,  char **exec_argv; unsigned *subst_count; int exec_argc;))
98  static bool need_print = 1;  IF_FEATURE_FIND_GROUP(  ACTS(group, gid_t gid;))
99  static int recurse_flags = ACTION_RECURSE;  IF_FEATURE_FIND_LINKS(  ACTS(links, char links_char; int links_count;))
100    
101    struct globals {
102     IF_FEATURE_FIND_XDEV(dev_t *xdev_dev;)
103     IF_FEATURE_FIND_XDEV(int xdev_count;)
104     action ***actions;
105     bool need_print;
106     recurse_flags_t recurse_flags;
107    };
108    #define G (*(struct globals*)&bb_common_bufsiz1)
109    #define INIT_G() do { \
110     struct G_sizecheck { \
111     char G_sizecheck[sizeof(G) > COMMON_BUFSIZE ? -1 : 1]; \
112     }; \
113     /* we have to zero it out because of NOEXEC */ \
114     memset(&G, 0, offsetof(struct globals, need_print)); \
115     G.need_print = 1; \
116     G.recurse_flags = ACTION_RECURSE; \
117    } while (0)
118    
119  #if ENABLE_FEATURE_FIND_EXEC  #if ENABLE_FEATURE_FIND_EXEC
120  static unsigned count_subst(const char *str)  static unsigned count_subst(const char *str)
# Line 136  static char* subst(const char *src, unsi Line 151  static char* subst(const char *src, unsi
151   * bit 0=1: matched successfully (TRUE)   * bit 0=1: matched successfully (TRUE)
152   */   */
153    
154  static int exec_actions(action ***appp, const char *fileName, struct stat *statbuf)  static int exec_actions(action ***appp, const char *fileName, const struct stat *statbuf)
155  {  {
156   int cur_group;   int cur_group;
157   int cur_action;   int cur_action;
# Line 161  static int exec_actions(action ***appp, Line 176  static int exec_actions(action ***appp,
176   * On return, bit is restored.  */   * On return, bit is restored.  */
177    
178   cur_group = -1;   cur_group = -1;
179   while ((app = appp[++cur_group])) {   while ((app = appp[++cur_group]) != NULL) {
180   rc &= ~TRUE; /* 'success' so far, clear TRUE bit */   rc &= ~TRUE; /* 'success' so far, clear TRUE bit */
181   cur_action = -1;   cur_action = -1;
182   while (1) {   while (1) {
# Line 273  ACTF(inum) Line 288  ACTF(inum)
288  ACTF(exec)  ACTF(exec)
289  {  {
290   int i, rc;   int i, rc;
291    #if ENABLE_USE_PORTABLE_CODE
292     char **argv = alloca(sizeof(char*) * (ap->exec_argc + 1));
293    #else /* gcc 4.3.1 generates smaller code: */
294   char *argv[ap->exec_argc + 1];   char *argv[ap->exec_argc + 1];
295    #endif
296   for (i = 0; i < ap->exec_argc; i++)   for (i = 0; i < ap->exec_argc; i++)
297   argv[i] = subst(ap->exec_argv[i], ap->subst_count[i], fileName);   argv[i] = subst(ap->exec_argv[i], ap->subst_count[i], fileName);
298   argv[i] = NULL; /* terminate the list */   argv[i] = NULL; /* terminate the list */
# Line 360  ACTF(context) Line 379  ACTF(context)
379   security_context_t con;   security_context_t con;
380   int rc;   int rc;
381    
382   if (recurse_flags & ACTION_FOLLOWLINKS) {   if (G.recurse_flags & ACTION_FOLLOWLINKS) {
383   rc = getfilecon(fileName, &con);   rc = getfilecon(fileName, &con);
384   } else {   } else {
385   rc = lgetfilecon(fileName, &con);   rc = lgetfilecon(fileName, &con);
# Line 372  ACTF(context) Line 391  ACTF(context)
391   return rc == 0;   return rc == 0;
392  }  }
393  #endif  #endif
394    #if ENABLE_FEATURE_FIND_LINKS
395    ACTF(links)
396    {
397     switch(ap->links_char) {
398     case '-' : return (statbuf->st_nlink <  ap->links_count);
399     case '+' : return (statbuf->st_nlink >  ap->links_count);
400     default:   return (statbuf->st_nlink == ap->links_count);
401     }
402    }
403    #endif
404    
405  static int FAST_FUNC fileAction(const char *fileName,  static int FAST_FUNC fileAction(const char *fileName,
406   struct stat *statbuf,   struct stat *statbuf,
407   void *userData SKIP_FEATURE_FIND_MAXDEPTH(UNUSED_PARAM),   void *userData IF_NOT_FEATURE_FIND_MAXDEPTH(UNUSED_PARAM),
408   int depth SKIP_FEATURE_FIND_MAXDEPTH(UNUSED_PARAM))   int depth IF_NOT_FEATURE_FIND_MAXDEPTH(UNUSED_PARAM))
409  {  {
410   int i;   int r;
411  #if ENABLE_FEATURE_FIND_MAXDEPTH  #if ENABLE_FEATURE_FIND_MAXDEPTH
412   int maxdepth = (int)(ptrdiff_t)userData;  #define minmaxdepth ((int*)userData)
413    
414   if (depth > maxdepth) return SKIP;   if (depth < minmaxdepth[0])
415     return TRUE; /* skip this, continue recursing */
416     if (depth > minmaxdepth[1])
417     return SKIP; /* stop recursing */
418  #endif  #endif
419    
420     r = exec_actions(G.actions, fileName, statbuf);
421     /* Had no explicit -print[0] or -exec? then print */
422     if ((r & TRUE) && G.need_print)
423     puts(fileName);
424    
425    #if ENABLE_FEATURE_FIND_MAXDEPTH
426     if (S_ISDIR(statbuf->st_mode)) {
427     if (depth == minmaxdepth[1])
428     return SKIP;
429     }
430    #endif
431  #if ENABLE_FEATURE_FIND_XDEV  #if ENABLE_FEATURE_FIND_XDEV
432   if (S_ISDIR(statbuf->st_mode) && xdev_count) {   /* -xdev stops on mountpoints, but AFTER mountpoit itself
433   for (i = 0; i < xdev_count; i++) {   * is processed as usual */
434   if (xdev_dev[i] == statbuf->st_dev)   if (S_ISDIR(statbuf->st_mode)) {
435   break;   if (G.xdev_count) {
436   }   int i;
437   if (i == xdev_count)   for (i = 0; i < G.xdev_count; i++) {
438     if (G.xdev_dev[i] == statbuf->st_dev)
439     goto found;
440     }
441   return SKIP;   return SKIP;
442     found: ;
443     }
444   }   }
445  #endif  #endif
446   i = exec_actions(actions, fileName, statbuf);  
  /* Had no explicit -print[0] or -exec? then print */  
  if ((i & TRUE) && need_print)  
  puts(fileName);  
447   /* Cannot return 0: our caller, recursive_action(),   /* Cannot return 0: our caller, recursive_action(),
448   * will perror() and skip dirs (if called on dir) */   * will perror() and skip dirs (if called on dir) */
449   return (i & SKIP) ? SKIP : TRUE;   return (r & SKIP) ? SKIP : TRUE;
450    #undef minmaxdepth
451  }  }
452    
453    
# Line 426  static int find_type(const char *type) Line 471  static int find_type(const char *type)
471   else if (*type == 's')   else if (*type == 's')
472   mask = S_IFSOCK;   mask = S_IFSOCK;
473    
474   if (mask == 0 || *(type + 1) != '\0')   if (mask == 0 || type[1] != '\0')
475   bb_error_msg_and_die(bb_msg_invalid_arg, type, "-type");   bb_error_msg_and_die(bb_msg_invalid_arg, type, "-type");
476    
477   return mask;   return mask;
# Line 435  static int find_type(const char *type) Line 480  static int find_type(const char *type)
480    
481  #if ENABLE_FEATURE_FIND_PERM \  #if ENABLE_FEATURE_FIND_PERM \
482   || ENABLE_FEATURE_FIND_MTIME || ENABLE_FEATURE_FIND_MMIN \   || ENABLE_FEATURE_FIND_MTIME || ENABLE_FEATURE_FIND_MMIN \
483   || ENABLE_FEATURE_FIND_SIZE   || ENABLE_FEATURE_FIND_SIZE  || ENABLE_FEATURE_FIND_LINKS
484  static const char* plus_minus_num(const char* str)  static const char* plus_minus_num(const char* str)
485  {  {
486   if (*str == '-' || *str == '+')   if (*str == '-' || *str == '+')
# Line 447  static const char* plus_minus_num(const Line 492  static const char* plus_minus_num(const
492  static action*** parse_params(char **argv)  static action*** parse_params(char **argv)
493  {  {
494   enum {   enum {
495                           PARM_a         ,                          PARM_a         ,
496                           PARM_o         ,                          PARM_o         ,
497   USE_FEATURE_FIND_NOT( PARM_char_not  ,)   IF_FEATURE_FIND_NOT( PARM_char_not  ,)
498  #if ENABLE_DESKTOP  #if ENABLE_DESKTOP
499                           PARM_and       ,                          PARM_and       ,
500                           PARM_or        ,                          PARM_or        ,
501   USE_FEATURE_FIND_NOT(    PARM_not       ,)   IF_FEATURE_FIND_NOT(    PARM_not       ,)
502  #endif  #endif
503                           PARM_print     ,                          PARM_print     ,
504   USE_FEATURE_FIND_PRINT0( PARM_print0    ,)   IF_FEATURE_FIND_PRINT0( PARM_print0    ,)
505   USE_FEATURE_FIND_DEPTH(  PARM_depth     ,)   IF_FEATURE_FIND_DEPTH(  PARM_depth     ,)
506   USE_FEATURE_FIND_PRUNE(  PARM_prune     ,)   IF_FEATURE_FIND_PRUNE(  PARM_prune     ,)
507   USE_FEATURE_FIND_DELETE( PARM_delete    ,)   IF_FEATURE_FIND_DELETE( PARM_delete    ,)
508   USE_FEATURE_FIND_EXEC(   PARM_exec      ,)   IF_FEATURE_FIND_EXEC(   PARM_exec      ,)
509   USE_FEATURE_FIND_PAREN(  PARM_char_brace,)   IF_FEATURE_FIND_PAREN(  PARM_char_brace,)
510   /* All options starting from here require argument */   /* All options starting from here require argument */
511                           PARM_name      ,                          PARM_name      ,
512                           PARM_iname     ,                          PARM_iname     ,
513   USE_FEATURE_FIND_PATH(   PARM_path      ,)   IF_FEATURE_FIND_PATH(   PARM_path      ,)
514   USE_FEATURE_FIND_REGEX(  PARM_regex     ,)   IF_FEATURE_FIND_REGEX(  PARM_regex     ,)
515   USE_FEATURE_FIND_TYPE(   PARM_type      ,)   IF_FEATURE_FIND_TYPE(   PARM_type      ,)
516   USE_FEATURE_FIND_PERM(   PARM_perm      ,)   IF_FEATURE_FIND_PERM(   PARM_perm      ,)
517   USE_FEATURE_FIND_MTIME(  PARM_mtime     ,)   IF_FEATURE_FIND_MTIME(  PARM_mtime     ,)
518   USE_FEATURE_FIND_MMIN(   PARM_mmin      ,)   IF_FEATURE_FIND_MMIN(   PARM_mmin      ,)
519   USE_FEATURE_FIND_NEWER(  PARM_newer     ,)   IF_FEATURE_FIND_NEWER(  PARM_newer     ,)
520   USE_FEATURE_FIND_INUM(   PARM_inum      ,)   IF_FEATURE_FIND_INUM(   PARM_inum      ,)
521   USE_FEATURE_FIND_USER(   PARM_user      ,)   IF_FEATURE_FIND_USER(   PARM_user      ,)
522   USE_FEATURE_FIND_GROUP(  PARM_group     ,)   IF_FEATURE_FIND_GROUP(  PARM_group     ,)
523   USE_FEATURE_FIND_SIZE(   PARM_size      ,)   IF_FEATURE_FIND_SIZE(   PARM_size      ,)
524   USE_FEATURE_FIND_CONTEXT(PARM_context   ,)   IF_FEATURE_FIND_CONTEXT(PARM_context   ,)
525     IF_FEATURE_FIND_LINKS(  PARM_links     ,)
526   };   };
527    
528   static const char params[] ALIGN1 =   static const char params[] ALIGN1 =
529                           "-a\0"                           "-a\0"
530                           "-o\0"                           "-o\0"
531   USE_FEATURE_FIND_NOT(    "!\0"       )   IF_FEATURE_FIND_NOT(    "!\0"       )
532  #if ENABLE_DESKTOP  #if ENABLE_DESKTOP
533                           "-and\0"                           "-and\0"
534                           "-or\0"                           "-or\0"
535   USE_FEATURE_FIND_NOT( "-not\0"    )   IF_FEATURE_FIND_NOT( "-not\0"    )
536  #endif  #endif
537                           "-print\0"                           "-print\0"
538   USE_FEATURE_FIND_PRINT0( "-print0\0" )   IF_FEATURE_FIND_PRINT0( "-print0\0" )
539   USE_FEATURE_FIND_DEPTH(  "-depth\0"  )   IF_FEATURE_FIND_DEPTH(  "-depth\0"  )
540   USE_FEATURE_FIND_PRUNE(  "-prune\0"  )   IF_FEATURE_FIND_PRUNE(  "-prune\0"  )
541   USE_FEATURE_FIND_DELETE( "-delete\0" )   IF_FEATURE_FIND_DELETE( "-delete\0" )
542   USE_FEATURE_FIND_EXEC(   "-exec\0"   )   IF_FEATURE_FIND_EXEC(   "-exec\0"   )
543   USE_FEATURE_FIND_PAREN(  "(\0"       )   IF_FEATURE_FIND_PAREN(  "(\0"       )
544   /* All options starting from here require argument */   /* All options starting from here require argument */
545                           "-name\0"                           "-name\0"
546                           "-iname\0"                           "-iname\0"
547   USE_FEATURE_FIND_PATH(   "-path\0"   )   IF_FEATURE_FIND_PATH(   "-path\0"   )
548   USE_FEATURE_FIND_REGEX(  "-regex\0"  )   IF_FEATURE_FIND_REGEX(  "-regex\0"  )
549   USE_FEATURE_FIND_TYPE(   "-type\0"   )   IF_FEATURE_FIND_TYPE(   "-type\0"   )
550   USE_FEATURE_FIND_PERM(   "-perm\0"   )   IF_FEATURE_FIND_PERM(   "-perm\0"   )
551   USE_FEATURE_FIND_MTIME(  "-mtime\0"  )   IF_FEATURE_FIND_MTIME(  "-mtime\0"  )
552   USE_FEATURE_FIND_MMIN(   "-mmin\0"   )   IF_FEATURE_FIND_MMIN(   "-mmin\0"   )
553   USE_FEATURE_FIND_NEWER(  "-newer\0"  )   IF_FEATURE_FIND_NEWER(  "-newer\0"  )
554   USE_FEATURE_FIND_INUM(   "-inum\0"   )   IF_FEATURE_FIND_INUM(   "-inum\0"   )
555   USE_FEATURE_FIND_USER(   "-user\0"   )   IF_FEATURE_FIND_USER(   "-user\0"   )
556   USE_FEATURE_FIND_GROUP(  "-group\0"  )   IF_FEATURE_FIND_GROUP(  "-group\0"  )
557   USE_FEATURE_FIND_SIZE(   "-size\0"   )   IF_FEATURE_FIND_SIZE(   "-size\0"   )
558   USE_FEATURE_FIND_CONTEXT("-context\0")   IF_FEATURE_FIND_CONTEXT("-context\0")
559     IF_FEATURE_FIND_LINKS(  "-links\0"  )
560                           ;                           ;
561    
562   action*** appp;   action*** appp;
563   unsigned cur_group = 0;   unsigned cur_group = 0;
564   unsigned cur_action = 0;   unsigned cur_action = 0;
565   USE_FEATURE_FIND_NOT( bool invert_flag = 0; )   IF_FEATURE_FIND_NOT( bool invert_flag = 0; )
566    
567   /* This is the only place in busybox where we use nested function.   /* This is the only place in busybox where we use nested function.
568   * So far more standard alternatives were bigger. */   * So far more standard alternatives were bigger. */
# Line 528  static action*** parse_params(char **arg Line 575  static action*** parse_params(char **arg
575   appp[cur_group][cur_action++] = ap = xmalloc(sizeof_struct);   appp[cur_group][cur_action++] = ap = xmalloc(sizeof_struct);
576   appp[cur_group][cur_action] = NULL;   appp[cur_group][cur_action] = NULL;
577   ap->f = f;   ap->f = f;
578   USE_FEATURE_FIND_NOT( ap->invert = invert_flag; )   IF_FEATURE_FIND_NOT( ap->invert = invert_flag; )
579   USE_FEATURE_FIND_NOT( invert_flag = 0; )   IF_FEATURE_FIND_NOT( invert_flag = 0; )
580   return ap;   return ap;
581   }   }
582    
# Line 567  static action*** parse_params(char **arg Line 614  static action*** parse_params(char **arg
614   * it doesn't give smaller code. Other arches? */   * it doesn't give smaller code. Other arches? */
615    
616   /* --- Operators --- */   /* --- Operators --- */
617   if (parm == PARM_a USE_DESKTOP(|| parm == PARM_and)) {   if (parm == PARM_a IF_DESKTOP(|| parm == PARM_and)) {
618   /* no further special handling required */   /* no further special handling required */
619   }   }
620   else if (parm == PARM_o USE_DESKTOP(|| parm == PARM_or)) {   else if (parm == PARM_o IF_DESKTOP(|| parm == PARM_or)) {
621   /* start new OR group */   /* start new OR group */
622   cur_group++;   cur_group++;
623   appp = xrealloc(appp, (cur_group+2) * sizeof(*appp));   appp = xrealloc(appp, (cur_group+2) * sizeof(*appp));
# Line 579  static action*** parse_params(char **arg Line 626  static action*** parse_params(char **arg
626   cur_action = 0;   cur_action = 0;
627   }   }
628  #if ENABLE_FEATURE_FIND_NOT  #if ENABLE_FEATURE_FIND_NOT
629   else if (parm == PARM_char_not USE_DESKTOP(|| parm == PARM_not)) {   else if (parm == PARM_char_not IF_DESKTOP(|| parm == PARM_not)) {
630   /* also handles "find ! ! -name 'foo*'" */   /* also handles "find ! ! -name 'foo*'" */
631   invert_flag ^= 1;   invert_flag ^= 1;
632   }   }
# Line 587  static action*** parse_params(char **arg Line 634  static action*** parse_params(char **arg
634    
635   /* --- Tests and actions --- */   /* --- Tests and actions --- */
636   else if (parm == PARM_print) {   else if (parm == PARM_print) {
637   need_print = 0;   G.need_print = 0;
638   /* GNU find ignores '!' here: "find ! -print" */   /* GNU find ignores '!' here: "find ! -print" */
639   USE_FEATURE_FIND_NOT( invert_flag = 0; )   IF_FEATURE_FIND_NOT( invert_flag = 0; )
640   (void) ALLOC_ACTION(print);   (void) ALLOC_ACTION(print);
641   }   }
642  #if ENABLE_FEATURE_FIND_PRINT0  #if ENABLE_FEATURE_FIND_PRINT0
643   else if (parm == PARM_print0) {   else if (parm == PARM_print0) {
644   need_print = 0;   G.need_print = 0;
645   USE_FEATURE_FIND_NOT( invert_flag = 0; )   IF_FEATURE_FIND_NOT( invert_flag = 0; )
646   (void) ALLOC_ACTION(print0);   (void) ALLOC_ACTION(print0);
647   }   }
648  #endif  #endif
649  #if ENABLE_FEATURE_FIND_DEPTH  #if ENABLE_FEATURE_FIND_DEPTH
650   else if (parm == PARM_depth) {   else if (parm == PARM_depth) {
651   recurse_flags |= ACTION_DEPTHFIRST;   G.recurse_flags |= ACTION_DEPTHFIRST;
652   }   }
653  #endif  #endif
654  #if ENABLE_FEATURE_FIND_PRUNE  #if ENABLE_FEATURE_FIND_PRUNE
655   else if (parm == PARM_prune) {   else if (parm == PARM_prune) {
656   USE_FEATURE_FIND_NOT( invert_flag = 0; )   IF_FEATURE_FIND_NOT( invert_flag = 0; )
657   (void) ALLOC_ACTION(prune);   (void) ALLOC_ACTION(prune);
658   }   }
659  #endif  #endif
660  #if ENABLE_FEATURE_FIND_DELETE  #if ENABLE_FEATURE_FIND_DELETE
661   else if (parm == PARM_delete) {   else if (parm == PARM_delete) {
662   need_print = 0;   G.need_print = 0;
663   recurse_flags |= ACTION_DEPTHFIRST;   G.recurse_flags |= ACTION_DEPTHFIRST;
664   (void) ALLOC_ACTION(delete);   (void) ALLOC_ACTION(delete);
665   }   }
666  #endif  #endif
# Line 621  static action*** parse_params(char **arg Line 668  static action*** parse_params(char **arg
668   else if (parm == PARM_exec) {   else if (parm == PARM_exec) {
669   int i;   int i;
670   action_exec *ap;   action_exec *ap;
671   need_print = 0;   G.need_print = 0;
672   USE_FEATURE_FIND_NOT( invert_flag = 0; )   IF_FEATURE_FIND_NOT( invert_flag = 0; )
673   ap = ALLOC_ACTION(exec);   ap = ALLOC_ACTION(exec);
674   ap->exec_argv = ++argv; /* first arg after -exec */   ap->exec_argv = ++argv; /* first arg after -exec */
675   ap->exec_argc = 0;   ap->exec_argc = 0;
# Line 777  static action*** parse_params(char **arg Line 824  static action*** parse_params(char **arg
824   { "", 512 },   { "", 512 },
825   { "b", 512 },   { "b", 512 },
826   { "k", 1024 },   { "k", 1024 },
827   { }   { "", 0 }
828   };   };
829   action_size *ap;   action_size *ap;
830   ap = ALLOC_ACTION(size);   ap = ALLOC_ACTION(size);
# Line 795  static action*** parse_params(char **arg Line 842  static action*** parse_params(char **arg
842   bb_simple_perror_msg(arg1);   bb_simple_perror_msg(arg1);
843   }   }
844  #endif  #endif
845    #if ENABLE_FEATURE_FIND_LINKS
846     else if (parm == PARM_links) {
847     action_links *ap;
848     ap = ALLOC_ACTION(links);
849     ap->links_char = arg1[0];
850     ap->links_count = xatoul(plus_minus_num(arg1));
851     }
852    #endif
853   else {   else {
854   bb_error_msg("unrecognized: %s", arg);   bb_error_msg("unrecognized: %s", arg);
855   bb_show_usage();   bb_show_usage();
# Line 807  static action*** parse_params(char **arg Line 862  static action*** parse_params(char **arg
862    
863    
864  int find_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;  int find_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
865  int find_main(int argc, char **argv)  int find_main(int argc UNUSED_PARAM, char **argv)
866  {  {
867   static const char options[] ALIGN1 =   static const char options[] ALIGN1 =
868                    "-follow\0"                    "-follow\0"
869  USE_FEATURE_FIND_XDEV(    "-xdev\0"    )  IF_FEATURE_FIND_XDEV(    "-xdev\0"    )
870  USE_FEATURE_FIND_MAXDEPTH("-maxdepth\0")  IF_FEATURE_FIND_MAXDEPTH("-mindepth\0""-maxdepth\0")
871                    ;                    ;
872   enum {   enum {
873                    OPT_FOLLOW,                    OPT_FOLLOW,
874  USE_FEATURE_FIND_XDEV(    OPT_XDEV    ,)  IF_FEATURE_FIND_XDEV(    OPT_XDEV    ,)
875  USE_FEATURE_FIND_MAXDEPTH(OPT_MAXDEPTH,)  IF_FEATURE_FIND_MAXDEPTH(OPT_MINDEPTH,)
876   };   };
877    
878   char *arg;   char *arg;
879   char **argp;   char **argp;
880   int i, firstopt, status = EXIT_SUCCESS;   int i, firstopt, status = EXIT_SUCCESS;
881  #if ENABLE_FEATURE_FIND_MAXDEPTH  #if ENABLE_FEATURE_FIND_MAXDEPTH
882   int maxdepth = INT_MAX;   int minmaxdepth[2] = { 0, INT_MAX };
883    #else
884    #define minmaxdepth NULL
885  #endif  #endif
886    
887   for (firstopt = 1; firstopt < argc; firstopt++) {   INIT_G();
888    
889     for (firstopt = 1; argv[firstopt]; firstopt++) {
890   if (argv[firstopt][0] == '-')   if (argv[firstopt][0] == '-')
891   break;   break;
892   if (ENABLE_FEATURE_FIND_NOT && LONE_CHAR(argv[firstopt], '!'))   if (ENABLE_FEATURE_FIND_NOT && LONE_CHAR(argv[firstopt], '!'))
# Line 854  USE_FEATURE_FIND_MAXDEPTH(OPT_MAXDEPTH,) Line 913  USE_FEATURE_FIND_MAXDEPTH(OPT_MAXDEPTH,)
913   while ((arg = argp[0])) {   while ((arg = argp[0])) {
914   int opt = index_in_strings(options, arg);   int opt = index_in_strings(options, arg);
915   if (opt == OPT_FOLLOW) {   if (opt == OPT_FOLLOW) {
916   recurse_flags |= ACTION_FOLLOWLINKS;   G.recurse_flags |= ACTION_FOLLOWLINKS | ACTION_DANGLING_OK;
917   argp[0] = (char*)"-a";   argp[0] = (char*)"-a";
918   }   }
919  #if ENABLE_FEATURE_FIND_XDEV  #if ENABLE_FEATURE_FIND_XDEV
920   if (opt == OPT_XDEV) {   if (opt == OPT_XDEV) {
921   struct stat stbuf;   struct stat stbuf;
922   if (!xdev_count) {   if (!G.xdev_count) {
923   xdev_count = firstopt - 1;   G.xdev_count = firstopt - 1;
924   xdev_dev = xmalloc(xdev_count * sizeof(dev_t));   G.xdev_dev = xzalloc(G.xdev_count * sizeof(G.xdev_dev[0]));
925   for (i = 1; i < firstopt; i++) {   for (i = 1; i < firstopt; i++) {
926   /* not xstat(): shouldn't bomb out on   /* not xstat(): shouldn't bomb out on
927   * "find not_exist exist -xdev" */   * "find not_exist exist -xdev" */
928   if (stat(argv[i], &stbuf))   if (stat(argv[i], &stbuf) == 0)
929   stbuf.st_dev = -1L;   G.xdev_dev[i-1] = stbuf.st_dev;
930   xdev_dev[i-1] = stbuf.st_dev;   /* else G.xdev_dev[i-1] stays 0 and
931     * won't match any real device dev_t */
932   }   }
933   }   }
934   argp[0] = (char*)"-a";   argp[0] = (char*)"-a";
935   }   }
936  #endif  #endif
937  #if ENABLE_FEATURE_FIND_MAXDEPTH  #if ENABLE_FEATURE_FIND_MAXDEPTH
938   if (opt == OPT_MAXDEPTH) {   if (opt == OPT_MINDEPTH || opt == OPT_MINDEPTH + 1) {
939   if (!argp[1])   if (!argp[1])
940   bb_show_usage();   bb_show_usage();
941   maxdepth = xatoi_u(argp[1]);   minmaxdepth[opt - OPT_MINDEPTH] = xatoi_u(argp[1]);
942   argp[0] = (char*)"-a";   argp[0] = (char*)"-a";
943   argp[1] = (char*)"-a";   argp[1] = (char*)"-a";
944   argp++;   argp++;
# Line 887  USE_FEATURE_FIND_MAXDEPTH(OPT_MAXDEPTH,) Line 947  USE_FEATURE_FIND_MAXDEPTH(OPT_MAXDEPTH,)
947   argp++;   argp++;
948   }   }
949    
950   actions = parse_params(&argv[firstopt]);   G.actions = parse_params(&argv[firstopt]);
951    
952   for (i = 1; i < firstopt; i++) {   for (i = 1; i < firstopt; i++) {
953   if (!recursive_action(argv[i],   if (!recursive_action(argv[i],
954   recurse_flags,  /* flags */   G.recurse_flags,/* flags */
955   fileAction,     /* file action */   fileAction,     /* file action */
956   fileAction,     /* dir action */   fileAction,     /* dir action */
957  #if ENABLE_FEATURE_FIND_MAXDEPTH  #if ENABLE_FEATURE_FIND_MAXDEPTH
958   /* double cast suppresses   minmaxdepth,    /* user data */
  * "cast to ptr from int of different size" */  
  (void*)(ptrdiff_t)maxdepth,/* user data */  
959  #else  #else
960   NULL,           /* user data */   NULL,           /* user data */
961  #endif  #endif

Legend:
Removed from v.983  
changed lines
  Added in v.984