aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2011-02-12 20:27:13 +0100
committerDenys Vlasenko <vda.linux@googlemail.com>2011-02-12 20:27:13 +0100
commit053c12e0de30afbc19019ffa9b0cb01edc44539f (patch)
treea573a561be65b767e05a7a0e7912aa9f4c7d8d36
parent805f2453d02e9d5cbbbd5c37c6659691e1697630 (diff)
downloadbusybox-w32-053c12e0de30afbc19019ffa9b0cb01edc44539f.tar.gz
busybox-w32-053c12e0de30afbc19019ffa9b0cb01edc44539f.tar.bz2
busybox-w32-053c12e0de30afbc19019ffa9b0cb01edc44539f.zip
find: remove the hack we use to parse options first, replace with simpler code
text data bss dec hex filename 867764 438 7552 875754 d5cea busybox_old 867629 438 7552 875619 d5c63 busybox_unstripped function old new delta parse_params 1377 1440 +63 static.params 151 192 +41 static.options 42 57 +15 fileAction 151 153 +2 find_main 466 267 -199 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 4/1 up/down: 121/-199) Total: -78 bytes Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r--findutils/find.c212
1 files changed, 91 insertions, 121 deletions
diff --git a/findutils/find.c b/findutils/find.c
index 65467ae9c..52ac7b0b3 100644
--- a/findutils/find.c
+++ b/findutils/find.c
@@ -374,8 +374,12 @@ IF_FEATURE_FIND_LINKS( ACTS(links, char links_char; int links_count;))
374struct globals { 374struct globals {
375 IF_FEATURE_FIND_XDEV(dev_t *xdev_dev;) 375 IF_FEATURE_FIND_XDEV(dev_t *xdev_dev;)
376 IF_FEATURE_FIND_XDEV(int xdev_count;) 376 IF_FEATURE_FIND_XDEV(int xdev_count;)
377#if ENABLE_FEATURE_FIND_MAXDEPTH
378 int minmaxdepth[2];
379#endif
377 action ***actions; 380 action ***actions;
378 bool need_print; 381 smallint need_print;
382 smallint xdev_on;
379 recurse_flags_t recurse_flags; 383 recurse_flags_t recurse_flags;
380} FIX_ALIASING; 384} FIX_ALIASING;
381#define G (*(struct globals*)&bb_common_bufsiz1) 385#define G (*(struct globals*)&bb_common_bufsiz1)
@@ -384,7 +388,8 @@ struct globals {
384 char G_sizecheck[sizeof(G) > COMMON_BUFSIZE ? -1 : 1]; \ 388 char G_sizecheck[sizeof(G) > COMMON_BUFSIZE ? -1 : 1]; \
385 }; \ 389 }; \
386 /* we have to zero it out because of NOEXEC */ \ 390 /* we have to zero it out because of NOEXEC */ \
387 memset(&G, 0, offsetof(struct globals, need_print)); \ 391 memset(&G, 0, sizeof(G)); \
392 IF_FEATURE_FIND_MAXDEPTH(G.minmaxdepth[1] = INT_MAX;) \
388 G.need_print = 1; \ 393 G.need_print = 1; \
389 G.recurse_flags = ACTION_RECURSE; \ 394 G.recurse_flags = ACTION_RECURSE; \
390} while (0) 395} while (0)
@@ -682,16 +687,15 @@ ACTF(links)
682 687
683static int FAST_FUNC fileAction(const char *fileName, 688static int FAST_FUNC fileAction(const char *fileName,
684 struct stat *statbuf, 689 struct stat *statbuf,
685 void *userData IF_NOT_FEATURE_FIND_MAXDEPTH(UNUSED_PARAM), 690 void *userData UNUSED_PARAM,
686 int depth IF_NOT_FEATURE_FIND_MAXDEPTH(UNUSED_PARAM)) 691 int depth IF_NOT_FEATURE_FIND_MAXDEPTH(UNUSED_PARAM))
687{ 692{
688 int r; 693 int r;
689#if ENABLE_FEATURE_FIND_MAXDEPTH
690#define minmaxdepth ((int*)userData)
691 694
692 if (depth < minmaxdepth[0]) 695#if ENABLE_FEATURE_FIND_MAXDEPTH
696 if (depth < G.minmaxdepth[0])
693 return TRUE; /* skip this, continue recursing */ 697 return TRUE; /* skip this, continue recursing */
694 if (depth > minmaxdepth[1]) 698 if (depth > G.minmaxdepth[1])
695 return SKIP; /* stop recursing */ 699 return SKIP; /* stop recursing */
696#endif 700#endif
697 701
@@ -702,7 +706,7 @@ static int FAST_FUNC fileAction(const char *fileName,
702 706
703#if ENABLE_FEATURE_FIND_MAXDEPTH 707#if ENABLE_FEATURE_FIND_MAXDEPTH
704 if (S_ISDIR(statbuf->st_mode)) { 708 if (S_ISDIR(statbuf->st_mode)) {
705 if (depth == minmaxdepth[1]) 709 if (depth == G.minmaxdepth[1])
706 return SKIP; 710 return SKIP;
707 } 711 }
708#endif 712#endif
@@ -725,7 +729,6 @@ static int FAST_FUNC fileAction(const char *fileName,
725 /* Cannot return 0: our caller, recursive_action(), 729 /* Cannot return 0: our caller, recursive_action(),
726 * will perror() and skip dirs (if called on dir) */ 730 * will perror() and skip dirs (if called on dir) */
727 return (r & SKIP) ? SKIP : TRUE; 731 return (r & SKIP) ? SKIP : TRUE;
728#undef minmaxdepth
729} 732}
730 733
731 734
@@ -770,6 +773,9 @@ static const char* plus_minus_num(const char* str)
770static action*** parse_params(char **argv) 773static action*** parse_params(char **argv)
771{ 774{
772 enum { 775 enum {
776 OPT_FOLLOW ,
777 IF_FEATURE_FIND_XDEV( OPT_XDEV ,)
778 IF_FEATURE_FIND_DEPTH( OPT_DEPTH ,)
773 PARM_a , 779 PARM_a ,
774 PARM_o , 780 PARM_o ,
775 IF_FEATURE_FIND_NOT( PARM_char_not ,) 781 IF_FEATURE_FIND_NOT( PARM_char_not ,)
@@ -784,7 +790,7 @@ static action*** parse_params(char **argv)
784 IF_FEATURE_FIND_DELETE( PARM_delete ,) 790 IF_FEATURE_FIND_DELETE( PARM_delete ,)
785 IF_FEATURE_FIND_EXEC( PARM_exec ,) 791 IF_FEATURE_FIND_EXEC( PARM_exec ,)
786 IF_FEATURE_FIND_PAREN( PARM_char_brace,) 792 IF_FEATURE_FIND_PAREN( PARM_char_brace,)
787 /* All options starting from here require argument */ 793 /* All options/actions starting from here require argument */
788 PARM_name , 794 PARM_name ,
789 PARM_iname , 795 PARM_iname ,
790 IF_FEATURE_FIND_PATH( PARM_path ,) 796 IF_FEATURE_FIND_PATH( PARM_path ,)
@@ -800,24 +806,28 @@ static action*** parse_params(char **argv)
800 IF_FEATURE_FIND_SIZE( PARM_size ,) 806 IF_FEATURE_FIND_SIZE( PARM_size ,)
801 IF_FEATURE_FIND_CONTEXT(PARM_context ,) 807 IF_FEATURE_FIND_CONTEXT(PARM_context ,)
802 IF_FEATURE_FIND_LINKS( PARM_links ,) 808 IF_FEATURE_FIND_LINKS( PARM_links ,)
809 IF_FEATURE_FIND_MAXDEPTH(OPT_MINDEPTH,OPT_MAXDEPTH,)
803 }; 810 };
804 811
805 static const char params[] ALIGN1 = 812 static const char params[] ALIGN1 =
806 "-a\0" 813 "-follow\0"
807 "-o\0" 814 IF_FEATURE_FIND_XDEV( "-xdev\0" )
815 IF_FEATURE_FIND_DEPTH( "-depth\0" )
816 "-a\0"
817 "-o\0"
808 IF_FEATURE_FIND_NOT( "!\0" ) 818 IF_FEATURE_FIND_NOT( "!\0" )
809#if ENABLE_DESKTOP 819#if ENABLE_DESKTOP
810 "-and\0" 820 "-and\0"
811 "-or\0" 821 "-or\0"
812 IF_FEATURE_FIND_NOT( "-not\0" ) 822 IF_FEATURE_FIND_NOT( "-not\0" )
813#endif 823#endif
814 "-print\0" 824 "-print\0"
815 IF_FEATURE_FIND_PRINT0( "-print0\0" ) 825 IF_FEATURE_FIND_PRINT0( "-print0\0" )
816 IF_FEATURE_FIND_PRUNE( "-prune\0" ) 826 IF_FEATURE_FIND_PRUNE( "-prune\0" )
817 IF_FEATURE_FIND_DELETE( "-delete\0" ) 827 IF_FEATURE_FIND_DELETE( "-delete\0" )
818 IF_FEATURE_FIND_EXEC( "-exec\0" ) 828 IF_FEATURE_FIND_EXEC( "-exec\0" )
819 IF_FEATURE_FIND_PAREN( "(\0" ) 829 IF_FEATURE_FIND_PAREN( "(\0" )
820 /* All options starting from here require argument */ 830 /* All options/actions starting from here require argument */
821 "-name\0" 831 "-name\0"
822 "-iname\0" 832 "-iname\0"
823 IF_FEATURE_FIND_PATH( "-path\0" ) 833 IF_FEATURE_FIND_PATH( "-path\0" )
@@ -833,6 +843,7 @@ static action*** parse_params(char **argv)
833 IF_FEATURE_FIND_SIZE( "-size\0" ) 843 IF_FEATURE_FIND_SIZE( "-size\0" )
834 IF_FEATURE_FIND_CONTEXT("-context\0") 844 IF_FEATURE_FIND_CONTEXT("-context\0")
835 IF_FEATURE_FIND_LINKS( "-links\0" ) 845 IF_FEATURE_FIND_LINKS( "-links\0" )
846 IF_FEATURE_FIND_MAXDEPTH("-mindepth\0""-maxdepth\0")
836 ; 847 ;
837 848
838 action*** appp; 849 action*** appp;
@@ -860,27 +871,13 @@ static action*** parse_params(char **argv)
860 871
861 appp = xzalloc(2 * sizeof(appp[0])); /* appp[0],[1] == NULL */ 872 appp = xzalloc(2 * sizeof(appp[0])); /* appp[0],[1] == NULL */
862 873
863/* Actions have side effects and return a true or false value
864 * We implement: -print, -print0, -exec
865 *
866 * The rest are tests.
867 *
868 * Tests and actions are grouped by operators
869 * ( expr ) Force precedence
870 * ! expr True if expr is false
871 * -not expr Same as ! expr
872 * expr1 [-a[nd]] expr2 And; expr2 is not evaluated if expr1 is false
873 * expr1 -o[r] expr2 Or; expr2 is not evaluated if expr1 is true
874 * expr1 , expr2 List; both expr1 and expr2 are always evaluated
875 * We implement: (), -a, -o
876 */
877 while (*argv) { 874 while (*argv) {
878 const char *arg = argv[0]; 875 const char *arg = argv[0];
879 int parm = index_in_strings(params, arg); 876 int parm = index_in_strings(params, arg);
880 const char *arg1 = argv[1]; 877 const char *arg1 = argv[1];
881 878
882 if (parm >= PARM_name) { 879 if (parm >= PARM_name) {
883 /* All options starting from -name require argument */ 880 /* All options/actions starting from -name require argument */
884 if (!arg1) 881 if (!arg1)
885 bb_error_msg_and_die(bb_msg_requires_arg, arg); 882 bb_error_msg_and_die(bb_msg_requires_arg, arg);
886 argv++; 883 argv++;
@@ -889,8 +886,37 @@ static action*** parse_params(char **argv)
889 /* We can use big switch() here, but on i386 886 /* We can use big switch() here, but on i386
890 * it doesn't give smaller code. Other arches? */ 887 * it doesn't give smaller code. Other arches? */
891 888
892 /* --- Operators --- */ 889/* Options always return true. They always take effect
893 if (parm == PARM_a IF_DESKTOP(|| parm == PARM_and)) { 890 * rather than being processed only when their place in the
891 * expression is reached.
892 */
893 /* Options */
894#if ENABLE_FEATURE_FIND_XDEV
895 if (parm == OPT_XDEV) {
896 G.xdev_on = 1;
897 }
898#endif
899#if ENABLE_FEATURE_FIND_MAXDEPTH
900 else if (parm == OPT_MINDEPTH || parm == OPT_MINDEPTH + 1) {
901 G.minmaxdepth[parm - OPT_MINDEPTH] = xatoi_positive(arg1);
902 }
903#endif
904#if ENABLE_FEATURE_FIND_DEPTH
905 else if (parm == OPT_DEPTH) {
906 G.recurse_flags |= ACTION_DEPTHFIRST;
907 }
908#endif
909/* Actions are grouped by operators
910 * ( expr ) Force precedence
911 * ! expr True if expr is false
912 * -not expr Same as ! expr
913 * expr1 [-a[nd]] expr2 And; expr2 is not evaluated if expr1 is false
914 * expr1 -o[r] expr2 Or; expr2 is not evaluated if expr1 is true
915 * expr1 , expr2 List; both expr1 and expr2 are always evaluated
916 * We implement: (), -a, -o
917 */
918 /* Operators */
919 else if (parm == PARM_a IF_DESKTOP(|| parm == PARM_and)) {
894 /* no further special handling required */ 920 /* no further special handling required */
895 } 921 }
896 else if (parm == PARM_o IF_DESKTOP(|| parm == PARM_or)) { 922 else if (parm == PARM_o IF_DESKTOP(|| parm == PARM_or)) {
@@ -907,8 +933,7 @@ static action*** parse_params(char **argv)
907 invert_flag ^= 1; 933 invert_flag ^= 1;
908 } 934 }
909#endif 935#endif
910 936 /* Actions */
911 /* --- Tests and actions --- */
912 else if (parm == PARM_print) { 937 else if (parm == PARM_print) {
913 G.need_print = 0; 938 G.need_print = 0;
914 (void) ALLOC_ACTION(print); 939 (void) ALLOC_ACTION(print);
@@ -1014,10 +1039,10 @@ static action*** parse_params(char **argv)
1014 } 1039 }
1015#endif 1040#endif
1016#if ENABLE_FEATURE_FIND_PERM 1041#if ENABLE_FEATURE_FIND_PERM
1017/* -perm mode File's permission bits are exactly mode (octal or symbolic). 1042/* -perm BITS File's mode bits are exactly BITS (octal or symbolic).
1018 * Symbolic modes use mode 0 as a point of departure. 1043 * Symbolic modes use mode 0 as a point of departure.
1019 * -perm -mode All of the permission bits mode are set for the file. 1044 * -perm -BITS All of the BITS are set in file's mode.
1020 * -perm +mode Any of the permission bits mode are set for the file. 1045 * -perm +BITS At least one of the BITS is set in file's mode.
1021 */ 1046 */
1022 else if (parm == PARM_perm) { 1047 else if (parm == PARM_perm) {
1023 action_perm *ap; 1048 action_perm *ap;
@@ -1137,111 +1162,56 @@ static action*** parse_params(char **argv)
1137int find_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 1162int find_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
1138int find_main(int argc UNUSED_PARAM, char **argv) 1163int find_main(int argc UNUSED_PARAM, char **argv)
1139{ 1164{
1140 static const char options[] ALIGN1 =
1141 "-follow\0"
1142IF_FEATURE_FIND_XDEV( "-xdev\0" )
1143IF_FEATURE_FIND_MAXDEPTH("-mindepth\0""-maxdepth\0")
1144IF_FEATURE_FIND_DEPTH( "-depth\0" )
1145 ;
1146 enum {
1147 OPT_FOLLOW,
1148IF_FEATURE_FIND_XDEV( OPT_XDEV ,)
1149IF_FEATURE_FIND_MAXDEPTH(OPT_MINDEPTH,)
1150IF_FEATURE_FIND_DEPTH( OPT_DEPTH ,)
1151 };
1152
1153 char *arg;
1154 char **argp;
1155 int i, firstopt, status = EXIT_SUCCESS; 1165 int i, firstopt, status = EXIT_SUCCESS;
1156#if ENABLE_FEATURE_FIND_MAXDEPTH
1157 int minmaxdepth[2] = { 0, INT_MAX };
1158#else
1159#define minmaxdepth NULL
1160#endif
1161 1166
1162 INIT_G(); 1167 INIT_G();
1163 1168
1164 for (firstopt = 1; argv[firstopt]; firstopt++) { 1169 argv++;
1170 for (firstopt = 0; argv[firstopt]; firstopt++) {
1165 if (argv[firstopt][0] == '-') 1171 if (argv[firstopt][0] == '-')
1166 break; 1172 break;
1167 if (ENABLE_FEATURE_FIND_NOT && LONE_CHAR(argv[firstopt], '!')) 1173 if (ENABLE_FEATURE_FIND_NOT && LONE_CHAR(argv[firstopt], '!'))
1168 break; 1174 break;
1169#if ENABLE_FEATURE_FIND_PAREN 1175 if (ENABLE_FEATURE_FIND_PAREN && LONE_CHAR(argv[firstopt], '('))
1170 if (LONE_CHAR(argv[firstopt], '('))
1171 break; 1176 break;
1172#endif
1173 } 1177 }
1174 if (firstopt == 1) { 1178 if (firstopt == 0) {
1175 argv[0] = (char*)"."; 1179 *--argv = (char*)".";
1176 argv--;
1177 firstopt++; 1180 firstopt++;
1178 } 1181 }
1179 1182
1180/* All options always return true. They always take effect 1183 G.actions = parse_params(&argv[firstopt]);
1181 * rather than being processed only when their place in the 1184 argv[firstopt] = NULL;
1182 * expression is reached. 1185
1183 * We implement: -follow, -xdev, -mindepth, -maxdepth, -depth
1184 */
1185 /* Process options, and replace them with -a */
1186 /* (-a will be ignored by recursive parser later) */
1187 argp = &argv[firstopt];
1188 while ((arg = argp[0]) != NULL) {
1189 int opt = index_in_strings(options, arg);
1190 if (opt == OPT_FOLLOW) {
1191 G.recurse_flags |= ACTION_FOLLOWLINKS | ACTION_DANGLING_OK;
1192 argp[0] = (char*)"-a";
1193 }
1194#if ENABLE_FEATURE_FIND_XDEV 1186#if ENABLE_FEATURE_FIND_XDEV
1195 if (opt == OPT_XDEV) { 1187 if (G.xdev_on) {
1196 struct stat stbuf; 1188 struct stat stbuf;
1197 if (!G.xdev_count) { 1189
1198 G.xdev_count = firstopt - 1; 1190 G.xdev_count = firstopt;
1199 G.xdev_dev = xzalloc(G.xdev_count * sizeof(G.xdev_dev[0])); 1191 G.xdev_dev = xzalloc(G.xdev_count * sizeof(G.xdev_dev[0]));
1200 for (i = 1; i < firstopt; i++) { 1192 for (i = 0; argv[i]; i++) {
1201 /* not xstat(): shouldn't bomb out on 1193 /* not xstat(): shouldn't bomb out on
1202 * "find not_exist exist -xdev" */ 1194 * "find not_exist exist -xdev" */
1203 if (stat(argv[i], &stbuf) == 0) 1195 if (stat(argv[i], &stbuf) == 0)
1204 G.xdev_dev[i-1] = stbuf.st_dev; 1196 G.xdev_dev[i] = stbuf.st_dev;
1205 /* else G.xdev_dev[i-1] stays 0 and 1197 /* else G.xdev_dev[i] stays 0 and
1206 * won't match any real device dev_t */ 1198 * won't match any real device dev_t
1207 } 1199 */
1208 }
1209 argp[0] = (char*)"-a";
1210 }
1211#endif
1212#if ENABLE_FEATURE_FIND_MAXDEPTH
1213 if (opt == OPT_MINDEPTH || opt == OPT_MINDEPTH + 1) {
1214 if (!argp[1])
1215 bb_show_usage();
1216 minmaxdepth[opt - OPT_MINDEPTH] = xatoi_positive(argp[1]);
1217 argp[0] = (char*)"-a";
1218 argp++;
1219 argp[0] = (char*)"-a";
1220 }
1221#endif
1222#if ENABLE_FEATURE_FIND_DEPTH
1223 if (opt == OPT_DEPTH) {
1224 G.recurse_flags |= ACTION_DEPTHFIRST;
1225 argp[0] = (char*)"-a";
1226 } 1200 }
1227#endif
1228 argp++;
1229 } 1201 }
1202#endif
1230 1203
1231 G.actions = parse_params(&argv[firstopt]); 1204 for (i = 0; argv[i]; i++) {
1232
1233 for (i = 1; i < firstopt; i++) {
1234 if (!recursive_action(argv[i], 1205 if (!recursive_action(argv[i],
1235 G.recurse_flags,/* flags */ 1206 G.recurse_flags,/* flags */
1236 fileAction, /* file action */ 1207 fileAction, /* file action */
1237 fileAction, /* dir action */ 1208 fileAction, /* dir action */
1238#if ENABLE_FEATURE_FIND_MAXDEPTH
1239 minmaxdepth, /* user data */
1240#else
1241 NULL, /* user data */ 1209 NULL, /* user data */
1242#endif 1210 0) /* depth */
1243 0)) /* depth */ 1211 ) {
1244 status = EXIT_FAILURE; 1212 status = EXIT_FAILURE;
1213 }
1245 } 1214 }
1215
1246 return status; 1216 return status;
1247} 1217}