Changeset 3232 in MondoRescue for branches/3.2/mindi-busybox/findutils/find.c
- Timestamp:
- Jan 1, 2014, 12:47:38 AM (10 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/3.2/mindi-busybox/findutils/find.c
r2725 r3232 54 54 */ 55 55 56 //applet:IF_FIND(APPLET_NOEXEC(find, find, _BB_DIR_USR_BIN, _BB_SUID_DROP, find))57 58 //kbuild:lib-$(CONFIG_FIND) += find.o59 60 56 //config:config FIND 61 57 //config: bool "find" … … 113 109 //config: 114 110 //config:config FEATURE_FIND_MAXDEPTH 115 //config: bool "Enable -m axdepth N"116 //config: default y 117 //config: depends on FIND 118 //config: help 119 //config: This option enables -m axdepth 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. 120 116 //config: 121 117 //config:config FEATURE_FIND_NEWER … … 125 121 //config: help 126 122 //config: Support the 'find -newer' option for finding any files which have 127 //config: a modifiedtime that is more recent than the specified FILE.123 //config: modification time that is more recent than the specified FILE. 128 124 //config: 129 125 //config:config FEATURE_FIND_INUM … … 231 227 //config: Support the 'find -links' option for matching number of links. 232 228 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 233 329 #include <fnmatch.h> 234 330 #include "libbb.h" 235 331 #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__) */ 238 341 239 342 /* This is a NOEXEC applet. Be very careful! */ … … 257 360 ACTS(print) 258 361 ACTS(name, const char *pattern; bool iname;) 259 IF_FEATURE_FIND_PATH( ACTS(path, const char *pattern; ))362 IF_FEATURE_FIND_PATH( ACTS(path, const char *pattern; bool ipath;)) 260 363 IF_FEATURE_FIND_REGEX( ACTS(regex, regex_t compiled_pattern;)) 261 364 IF_FEATURE_FIND_PRINT0( ACTS(print0)) … … 279 382 IF_FEATURE_FIND_XDEV(dev_t *xdev_dev;) 280 383 IF_FEATURE_FIND_XDEV(int xdev_count;) 384 #if ENABLE_FEATURE_FIND_MAXDEPTH 385 int minmaxdepth[2]; 386 #endif 281 387 action ***actions; 282 bool need_print; 388 smallint need_print; 389 smallint xdev_on; 283 390 recurse_flags_t recurse_flags; 284 391 } FIX_ALIASING; … … 289 396 }; \ 290 397 /* 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;) \ 292 400 G.need_print = 1; \ 293 401 G.recurse_flags = ACTION_RECURSE; \ … … 365 473 if (ap->invert) rc ^= TRUE; 366 474 #endif 475 dbg("grp %d action %d rc:0x%x", cur_group, cur_action, rc); 367 476 if (rc & TRUE) /* current group failed, try next */ 368 477 break; 369 478 } 370 479 } 480 dbg("returning:0x%x", rc ^ TRUE); 371 481 return rc ^ TRUE; /* restore TRUE bit */ 372 482 } 373 483 484 485 #if !FNM_CASEFOLD 486 static 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 374 500 375 501 ACTF(name) … … 388 514 * find -name '*foo' should match .foo too: 389 515 */ 516 #if FNM_CASEFOLD 390 517 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 391 523 } 392 524 … … 394 526 ACTF(path) 395 527 { 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); 396 533 return fnmatch(ap->pattern, fileName, 0) == 0; 534 # endif 397 535 } 398 536 #endif … … 587 725 static int FAST_FUNC fileAction(const char *fileName, 588 726 struct stat *statbuf, 589 void *userData IF_NOT_FEATURE_FIND_MAXDEPTH(UNUSED_PARAM),727 void *userData UNUSED_PARAM, 590 728 int depth IF_NOT_FEATURE_FIND_MAXDEPTH(UNUSED_PARAM)) 591 729 { 592 730 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 593 746 #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]) 599 753 return SKIP; /* stop recursing */ 600 754 #endif … … 607 761 #if ENABLE_FEATURE_FIND_MAXDEPTH 608 762 if (S_ISDIR(statbuf->st_mode)) { 609 if (depth == minmaxdepth[1])763 if (depth == G.minmaxdepth[1]) 610 764 return SKIP; 611 765 } 612 766 #endif 613 #if ENABLE_FEATURE_FIND_XDEV614 767 /* -xdev stops on mountpoints, but AFTER mountpoit itself 615 768 * 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 } 628 772 629 773 /* Cannot return 0: our caller, recursive_action(), 630 774 * will perror() and skip dirs (if called on dir) */ 631 775 return (r & SKIP) ? SKIP : TRUE; 632 #undef minmaxdepth633 776 } 634 777 … … 675 818 { 676 819 enum { 820 OPT_FOLLOW , 821 IF_FEATURE_FIND_XDEV( OPT_XDEV ,) 822 IF_FEATURE_FIND_DEPTH( OPT_DEPTH ,) 677 823 PARM_a , 678 824 PARM_o , … … 685 831 PARM_print , 686 832 IF_FEATURE_FIND_PRINT0( PARM_print0 ,) 687 IF_FEATURE_FIND_DEPTH( PARM_depth ,)688 833 IF_FEATURE_FIND_PRUNE( PARM_prune ,) 689 834 IF_FEATURE_FIND_DELETE( PARM_delete ,) 690 835 IF_FEATURE_FIND_EXEC( PARM_exec ,) 691 836 IF_FEATURE_FIND_PAREN( PARM_char_brace,) 692 /* All options starting from here require argument */837 /* All options/actions starting from here require argument */ 693 838 PARM_name , 694 839 PARM_iname , 695 840 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 ,) 696 847 IF_FEATURE_FIND_REGEX( PARM_regex ,) 697 848 IF_FEATURE_FIND_TYPE( PARM_type ,) … … 706 857 IF_FEATURE_FIND_CONTEXT(PARM_context ,) 707 858 IF_FEATURE_FIND_LINKS( PARM_links ,) 859 IF_FEATURE_FIND_MAXDEPTH(OPT_MINDEPTH,OPT_MAXDEPTH,) 708 860 }; 709 861 710 862 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" 713 868 IF_FEATURE_FIND_NOT( "!\0" ) 714 869 #if ENABLE_DESKTOP 715 716 717 IF_FEATURE_FIND_NOT( 718 #endif 719 870 "-and\0" 871 "-or\0" 872 IF_FEATURE_FIND_NOT( "-not\0" ) 873 #endif 874 "-print\0" 720 875 IF_FEATURE_FIND_PRINT0( "-print0\0" ) 721 IF_FEATURE_FIND_DEPTH( "-depth\0" )722 876 IF_FEATURE_FIND_PRUNE( "-prune\0" ) 723 877 IF_FEATURE_FIND_DELETE( "-delete\0" ) 724 878 IF_FEATURE_FIND_EXEC( "-exec\0" ) 725 879 IF_FEATURE_FIND_PAREN( "(\0" ) 726 /* All options starting from here require argument */727 728 880 /* All options/actions starting from here require argument */ 881 "-name\0" 882 "-iname\0" 729 883 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" ) 730 888 IF_FEATURE_FIND_REGEX( "-regex\0" ) 731 889 IF_FEATURE_FIND_TYPE( "-type\0" ) … … 740 898 IF_FEATURE_FIND_CONTEXT("-context\0") 741 899 IF_FEATURE_FIND_LINKS( "-links\0" ) 742 ; 900 IF_FEATURE_FIND_MAXDEPTH("-mindepth\0""-maxdepth\0") 901 ; 743 902 744 903 action*** appp; … … 767 926 appp = xzalloc(2 * sizeof(appp[0])); /* appp[0],[1] == NULL */ 768 927 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 775 973 * ( expr ) Force precedence 776 974 * ! expr True if expr is false … … 781 979 * We implement: (), -a, -o 782 980 */ 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__); 800 984 /* no further special handling required */ 801 985 } 802 986 else if (parm == PARM_o IF_DESKTOP(|| parm == PARM_or)) { 987 dbg("%d", __LINE__); 803 988 /* start new OR group */ 804 989 cur_group++; … … 812 997 /* also handles "find ! ! -name 'foo*'" */ 813 998 invert_flag ^= 1; 814 }815 #endif 816 817 /* --- Tests and actions ---*/999 dbg("invert_flag:%d", invert_flag); 1000 } 1001 #endif 1002 /* Actions */ 818 1003 else if (parm == PARM_print) { 1004 dbg("%d", __LINE__); 819 1005 G.need_print = 0; 820 /* GNU find ignores '!' here: "find ! -print" */821 IF_FEATURE_FIND_NOT( invert_flag = 0; )822 1006 (void) ALLOC_ACTION(print); 823 1007 } 824 1008 #if ENABLE_FEATURE_FIND_PRINT0 825 1009 else if (parm == PARM_print0) { 1010 dbg("%d", __LINE__); 826 1011 G.need_print = 0; 827 IF_FEATURE_FIND_NOT( invert_flag = 0; )828 1012 (void) ALLOC_ACTION(print0); 829 }830 #endif831 #if ENABLE_FEATURE_FIND_DEPTH832 else if (parm == PARM_depth) {833 G.recurse_flags |= ACTION_DEPTHFIRST;834 1013 } 835 1014 #endif 836 1015 #if ENABLE_FEATURE_FIND_PRUNE 837 1016 else if (parm == PARM_prune) { 838 IF_FEATURE_FIND_NOT( invert_flag = 0; )1017 dbg("%d", __LINE__); 839 1018 (void) ALLOC_ACTION(prune); 840 1019 } … … 842 1021 #if ENABLE_FEATURE_FIND_DELETE 843 1022 else if (parm == PARM_delete) { 1023 dbg("%d", __LINE__); 844 1024 G.need_print = 0; 845 1025 G.recurse_flags |= ACTION_DEPTHFIRST; … … 851 1031 int i; 852 1032 action_exec *ap; 1033 dbg("%d", __LINE__); 853 1034 G.need_print = 0; 854 IF_FEATURE_FIND_NOT( invert_flag = 0; )855 1035 ap = ALLOC_ACTION(exec); 856 1036 ap->exec_argv = ++argv; /* first arg after -exec */ … … 860 1040 bb_error_msg_and_die(bb_msg_requires_arg, "-exec"); 861 1041 // find -exec echo Foo ">{}<" ";" 862 // executes "echo Foo <filename>",1042 // executes "echo Foo >FILENAME<", 863 1043 // find -exec echo Foo ">{}<" "+" 864 // executes "echo Foo <filename1> <filename2> <filename3>...".1044 // executes "echo Foo FILENAME1 FILENAME2 FILENAME3...". 865 1045 // TODO (so far we treat "+" just like ";") 866 1046 if ((argv[0][0] == ';' || argv[0][0] == '+') … … 886 1066 unsigned nested = 1; 887 1067 1068 dbg("%d", __LINE__); 888 1069 endarg = argv; 889 1070 while (1) { … … 905 1086 else if (parm == PARM_name || parm == PARM_iname) { 906 1087 action_name *ap; 1088 dbg("%d", __LINE__); 907 1089 ap = ALLOC_ACTION(name); 908 1090 ap->pattern = arg1; … … 910 1092 } 911 1093 #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) { 913 1095 action_path *ap; 1096 dbg("%d", __LINE__); 914 1097 ap = ALLOC_ACTION(path); 915 1098 ap->pattern = arg1; 1099 ap->ipath = (parm == PARM_ipath); 916 1100 } 917 1101 #endif … … 919 1103 else if (parm == PARM_regex) { 920 1104 action_regex *ap; 1105 dbg("%d", __LINE__); 921 1106 ap = ALLOC_ACTION(regex); 922 1107 xregcomp(&ap->compiled_pattern, arg1, 0 /*cflags*/); … … 928 1113 ap = ALLOC_ACTION(type); 929 1114 ap->type_mask = find_type(arg1); 1115 dbg("created:type mask:%x", ap->type_mask); 930 1116 } 931 1117 #endif 932 1118 #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). 934 1120 * 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. 937 1123 */ 938 1124 else if (parm == PARM_perm) { 939 1125 action_perm *ap; 1126 dbg("%d", __LINE__); 940 1127 ap = ALLOC_ACTION(perm); 941 1128 ap->perm_char = arg1[0]; … … 949 1136 else if (parm == PARM_mtime) { 950 1137 action_mtime *ap; 1138 dbg("%d", __LINE__); 951 1139 ap = ALLOC_ACTION(mtime); 952 1140 ap->mtime_char = arg1[0]; … … 957 1145 else if (parm == PARM_mmin) { 958 1146 action_mmin *ap; 1147 dbg("%d", __LINE__); 959 1148 ap = ALLOC_ACTION(mmin); 960 1149 ap->mmin_char = arg1[0]; … … 966 1155 struct stat stat_newer; 967 1156 action_newer *ap; 1157 dbg("%d", __LINE__); 968 1158 ap = ALLOC_ACTION(newer); 969 1159 xstat(arg1, &stat_newer); … … 974 1164 else if (parm == PARM_inum) { 975 1165 action_inum *ap; 1166 dbg("%d", __LINE__); 976 1167 ap = ALLOC_ACTION(inum); 977 1168 ap->inode_num = xatoul(arg1); … … 981 1172 else if (parm == PARM_user) { 982 1173 action_user *ap; 1174 dbg("%d", __LINE__); 983 1175 ap = ALLOC_ACTION(user); 984 1176 ap->uid = bb_strtou(arg1, NULL, 10); … … 990 1182 else if (parm == PARM_group) { 991 1183 action_group *ap; 1184 dbg("%d", __LINE__); 992 1185 ap = ALLOC_ACTION(group); 993 1186 ap->gid = bb_strtou(arg1, NULL, 10); … … 1018 1211 }; 1019 1212 action_size *ap; 1213 dbg("%d", __LINE__); 1020 1214 ap = ALLOC_ACTION(size); 1021 1215 ap->size_char = arg1[0]; … … 1026 1220 else if (parm == PARM_context) { 1027 1221 action_context *ap; 1222 dbg("%d", __LINE__); 1028 1223 ap = ALLOC_ACTION(context); 1029 1224 /*ap->context = NULL; - ALLOC_ACTION did it */ … … 1036 1231 else if (parm == PARM_links) { 1037 1232 action_links *ap; 1233 dbg("%d", __LINE__); 1038 1234 ap = ALLOC_ACTION(links); 1039 1235 ap->links_char = arg1[0]; … … 1047 1243 argv++; 1048 1244 } 1245 dbg("exiting %s", __func__); 1049 1246 return appp; 1050 1247 #undef ALLOC_ACTION 1051 1248 } 1052 1249 1053 //usage:#define find_trivial_usage1054 //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_usage1137 //usage: "$ find / -name passwd\n"1138 //usage: "/etc/passwd\n"1139 1140 1250 int find_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 1141 1251 int find_main(int argc UNUSED_PARAM, char **argv) 1142 1252 { 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;1156 1253 int i, firstopt, status = EXIT_SUCCESS; 1157 #if ENABLE_FEATURE_FIND_MAXDEPTH1158 int minmaxdepth[2] = { 0, INT_MAX };1159 #else1160 #define minmaxdepth NULL1161 #endif1162 1254 1163 1255 INIT_G(); 1164 1256 1165 for (firstopt = 1; argv[firstopt]; firstopt++) { 1257 argv++; 1258 for (firstopt = 0; argv[firstopt]; firstopt++) { 1166 1259 if (argv[firstopt][0] == '-') 1167 1260 break; 1168 1261 if (ENABLE_FEATURE_FIND_NOT && LONE_CHAR(argv[firstopt], '!')) 1169 1262 break; 1170 #if ENABLE_FEATURE_FIND_PAREN 1171 if (LONE_CHAR(argv[firstopt], '(')) 1263 if (ENABLE_FEATURE_FIND_PAREN && LONE_CHAR(argv[firstopt], '(')) 1172 1264 break; 1173 #endif 1174 } 1175 if (firstopt == 1) { 1176 argv[0] = (char*)"."; 1177 argv--; 1265 } 1266 if (firstopt == 0) { 1267 *--argv = (char*)"."; 1178 1268 firstopt++; 1179 1269 } 1180 1270 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 1195 1274 #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++) { 1229 1293 if (!recursive_action(argv[i], 1230 1294 G.recurse_flags,/* flags */ 1231 1295 fileAction, /* file action */ 1232 1296 fileAction, /* dir action */ 1233 #if ENABLE_FEATURE_FIND_MAXDEPTH1234 minmaxdepth, /* user data */1235 #else1236 1297 NULL, /* user data */ 1237 #endif 1238 0)) /* depth */1298 0) /* depth */ 1299 ) { 1239 1300 status = EXIT_FAILURE; 1240 } 1301 } 1302 } 1303 1241 1304 return status; 1242 1305 }
Note:
See TracChangeset
for help on using the changeset viewer.