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; |
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) |
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; |
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) { |
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 */ |
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); |
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 |
|
|
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; |
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 == '+') |
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. */ |
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 |
|
|
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)); |
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 |
} |
} |
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 |
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; |
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); |
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(); |
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], '!')) |
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++; |
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 |