aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2020-10-01 21:52:16 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2020-10-01 21:52:16 +0200
commit689d0650ab63425adaea26afe347015a204958ee (patch)
tree9c2e10b952cad6804359bc10ccc963ff138fc3d4
parent3c3928fc658bddacd4e540589868bc28a8e4ca0a (diff)
downloadbusybox-w32-689d0650ab63425adaea26afe347015a204958ee.tar.gz
busybox-w32-689d0650ab63425adaea26afe347015a204958ee.tar.bz2
busybox-w32-689d0650ab63425adaea26afe347015a204958ee.zip
libbb: shrink recursive_action() by reducing memory pressure
function old new delta recursive_action1 - 316 +316 file_action_grep 161 164 +3 add_to_prg_cache_if_socket 202 205 +3 depmod_main 509 511 +2 writeFileToTarball 488 489 +1 parse_module 281 282 +1 fileAction 207 208 +1 act 189 190 +1 add_to_dirlist 65 64 -1 writeTarFile 196 194 -2 uuidcache_init 47 45 -2 uuidcache_check_device 109 107 -2 true_action 8 6 -2 run_parts_main 310 308 -2 netstat_main 534 532 -2 lsusb_main 29 27 -2 lspci_main 45 43 -2 initial_scan 138 136 -2 grep_main 845 843 -2 find_main 482 480 -2 config_file_action 437 435 -2 chmod_main 142 140 -2 dirAction 14 10 -4 diff_main 1544 1540 -4 chown_main 154 148 -6 skip_dir 136 129 -7 dir_act 191 184 -7 recursive_action 453 69 -384 ------------------------------------------------------------------------------ (add/remove: 1/0 grow/shrink: 7/20 up/down: 328/-439) Total: -111 bytes Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r--archival/tar.c9
-rw-r--r--coreutils/chmod.c13
-rw-r--r--coreutils/chown.c9
-rw-r--r--debianutils/run_parts.c10
-rw-r--r--editors/diff.c22
-rw-r--r--findutils/find.c17
-rw-r--r--findutils/grep.c13
-rw-r--r--include/libbb.h16
-rw-r--r--libbb/recursive_action.c72
-rw-r--r--modutils/depmod.c12
-rw-r--r--modutils/modprobe-small.c3
-rw-r--r--modutils/modprobe.c14
-rw-r--r--networking/netstat.c28
-rw-r--r--selinux/chcon.c8
-rw-r--r--selinux/setfiles.c8
-rw-r--r--util-linux/lspci.c11
-rw-r--r--util-linux/lsusb.c10
-rw-r--r--util-linux/mdev.c20
-rw-r--r--util-linux/volume_id/get_devname.c14
19 files changed, 159 insertions, 150 deletions
diff --git a/archival/tar.c b/archival/tar.c
index 4f2564813..93184cc2a 100644
--- a/archival/tar.c
+++ b/archival/tar.c
@@ -491,10 +491,11 @@ static int exclude_file(const llist_t *excluded_files, const char *file)
491# define exclude_file(excluded_files, file) 0 491# define exclude_file(excluded_files, file) 0
492# endif 492# endif
493 493
494static int FAST_FUNC writeFileToTarball(const char *fileName, struct stat *statbuf, 494static int FAST_FUNC writeFileToTarball(struct recursive_state *state,
495 void *userData, int depth UNUSED_PARAM) 495 const char *fileName,
496 struct stat *statbuf)
496{ 497{
497 struct TarBallInfo *tbInfo = (struct TarBallInfo *) userData; 498 struct TarBallInfo *tbInfo = (struct TarBallInfo *) state->userData;
498 const char *header_name; 499 const char *header_name;
499 int inputFileFd = -1; 500 int inputFileFd = -1;
500 501
@@ -700,7 +701,7 @@ static NOINLINE int writeTarFile(
700 /* Read the directory/files and iterate over them one at a time */ 701 /* Read the directory/files and iterate over them one at a time */
701 while (filelist) { 702 while (filelist) {
702 if (!recursive_action(filelist->data, recurseFlags, 703 if (!recursive_action(filelist->data, recurseFlags,
703 writeFileToTarball, writeFileToTarball, tbInfo, 0) 704 writeFileToTarball, writeFileToTarball, tbInfo)
704 ) { 705 ) {
705 errorFlag = TRUE; 706 errorFlag = TRUE;
706 } 707 }
diff --git a/coreutils/chmod.c b/coreutils/chmod.c
index 27e9b6b86..d2988c490 100644
--- a/coreutils/chmod.c
+++ b/coreutils/chmod.c
@@ -65,12 +65,14 @@
65 * symbolic links encountered during recursive directory traversals. 65 * symbolic links encountered during recursive directory traversals.
66 */ 66 */
67 67
68static int FAST_FUNC fileAction(const char *fileName, struct stat *statbuf, void* param, int depth) 68static int FAST_FUNC fileAction(struct recursive_state *state,
69 const char *fileName,
70 struct stat *statbuf)
69{ 71{
70 mode_t newmode; 72 mode_t newmode;
71 73
72 /* match coreutils behavior */ 74 /* match coreutils behavior */
73 if (depth == 0) { 75 if (state->depth == 0) {
74 /* statbuf holds lstat result, but we need stat (follow link) */ 76 /* statbuf holds lstat result, but we need stat (follow link) */
75 if (stat(fileName, statbuf)) 77 if (stat(fileName, statbuf))
76 goto err; 78 goto err;
@@ -79,9 +81,9 @@ static int FAST_FUNC fileAction(const char *fileName, struct stat *statbuf, void
79 return TRUE; 81 return TRUE;
80 } 82 }
81 83
82 newmode = bb_parse_mode((char *)param, statbuf->st_mode); 84 newmode = bb_parse_mode((char *)state->userData, statbuf->st_mode);
83 if (newmode == (mode_t)-1) 85 if (newmode == (mode_t)-1)
84 bb_error_msg_and_die("invalid mode '%s'", (char *)param); 86 bb_error_msg_and_die("invalid mode '%s'", (char *)state->userData);
85 87
86 if (chmod(fileName, newmode) == 0) { 88 if (chmod(fileName, newmode) == 0) {
87 if (OPT_VERBOSE 89 if (OPT_VERBOSE
@@ -136,8 +138,7 @@ int chmod_main(int argc UNUSED_PARAM, char **argv)
136 OPT_RECURSE, // recurse 138 OPT_RECURSE, // recurse
137 fileAction, // file action 139 fileAction, // file action
138 fileAction, // dir action 140 fileAction, // dir action
139 smode, // user data 141 smode) // user data
140 0) // depth
141 ) { 142 ) {
142 retval = EXIT_FAILURE; 143 retval = EXIT_FAILURE;
143 } 144 }
diff --git a/coreutils/chown.c b/coreutils/chown.c
index a1c5c0224..ffccc6cce 100644
--- a/coreutils/chown.c
+++ b/coreutils/chown.c
@@ -97,10 +97,10 @@ struct param_t {
97 chown_fptr chown_func; 97 chown_fptr chown_func;
98}; 98};
99 99
100static int FAST_FUNC fileAction(const char *fileName, struct stat *statbuf, 100static int FAST_FUNC fileAction(struct recursive_state *state UNUSED_PARAM,
101 void *vparam, int depth UNUSED_PARAM) 101 const char *fileName, struct stat *statbuf)
102{ 102{
103#define param (*(struct param_t*)vparam) 103#define param (*(struct param_t*)state->userData)
104#define opt option_mask32 104#define opt option_mask32
105 uid_t u = (param.ugid.uid == (uid_t)-1L) ? statbuf->st_uid : param.ugid.uid; 105 uid_t u = (param.ugid.uid == (uid_t)-1L) ? statbuf->st_uid : param.ugid.uid;
106 gid_t g = (param.ugid.gid == (gid_t)-1L) ? statbuf->st_gid : param.ugid.gid; 106 gid_t g = (param.ugid.gid == (gid_t)-1L) ? statbuf->st_gid : param.ugid.gid;
@@ -159,8 +159,7 @@ int chown_main(int argc UNUSED_PARAM, char **argv)
159 flags, /* flags */ 159 flags, /* flags */
160 fileAction, /* file action */ 160 fileAction, /* file action */
161 fileAction, /* dir action */ 161 fileAction, /* dir action */
162 &param, /* user data */ 162 &param) /* user data */
163 0) /* depth */
164 ) { 163 ) {
165 retval = EXIT_FAILURE; 164 retval = EXIT_FAILURE;
166 } 165 }
diff --git a/debianutils/run_parts.c b/debianutils/run_parts.c
index 196e0640d..585a4b58f 100644
--- a/debianutils/run_parts.c
+++ b/debianutils/run_parts.c
@@ -131,12 +131,13 @@ static int bb_alphasort(const void *p1, const void *p2)
131 return (option_mask32 & OPT_r) ? -r : r; 131 return (option_mask32 & OPT_r) ? -r : r;
132} 132}
133 133
134static int FAST_FUNC act(const char *file, struct stat *statbuf, void *args UNUSED_PARAM, int depth) 134static int FAST_FUNC act(struct recursive_state *state,
135 const char *file, struct stat *statbuf)
135{ 136{
136 if (depth == 0) 137 if (state->depth == 0)
137 return TRUE; 138 return TRUE;
138 139
139 if (depth == 1 140 if (state->depth == 1
140 && ( !(statbuf->st_mode & (S_IFREG | S_IFLNK)) 141 && ( !(statbuf->st_mode & (S_IFREG | S_IFLNK))
141 || invalid_name(file) 142 || invalid_name(file)
142 || (!(option_mask32 & OPT_l) && access(file, X_OK) != 0)) 143 || (!(option_mask32 & OPT_l) && access(file, X_OK) != 0))
@@ -199,8 +200,7 @@ int run_parts_main(int argc UNUSED_PARAM, char **argv)
199 ACTION_RECURSE|ACTION_FOLLOWLINKS, 200 ACTION_RECURSE|ACTION_FOLLOWLINKS,
200 act, /* file action */ 201 act, /* file action */
201 act, /* dir action */ 202 act, /* dir action */
202 NULL, /* user data */ 203 NULL /* user data */
203 0 /* depth */
204 ); 204 );
205 205
206 if (!names) 206 if (!names)
diff --git a/editors/diff.c b/editors/diff.c
index dc40ab4f1..280091756 100644
--- a/editors/diff.c
+++ b/editors/diff.c
@@ -803,11 +803,11 @@ struct dlist {
803}; 803};
804 804
805/* This function adds a filename to dl, the directory listing. */ 805/* This function adds a filename to dl, the directory listing. */
806static int FAST_FUNC add_to_dirlist(const char *filename, 806static int FAST_FUNC add_to_dirlist(struct recursive_state *state,
807 struct stat *sb UNUSED_PARAM, 807 const char *filename,
808 void *userdata, int depth UNUSED_PARAM) 808 struct stat *sb UNUSED_PARAM)
809{ 809{
810 struct dlist *const l = userdata; 810 struct dlist *const l = state->userData;
811 const char *file = filename + l->len; 811 const char *file = filename + l->len;
812 while (*file == '/') 812 while (*file == '/')
813 file++; 813 file++;
@@ -820,12 +820,12 @@ static int FAST_FUNC add_to_dirlist(const char *filename,
820/* If recursion is not set, this function adds the directory 820/* If recursion is not set, this function adds the directory
821 * to the list and prevents recursive_action from recursing into it. 821 * to the list and prevents recursive_action from recursing into it.
822 */ 822 */
823static int FAST_FUNC skip_dir(const char *filename, 823static int FAST_FUNC skip_dir(struct recursive_state *state,
824 struct stat *sb, void *userdata, 824 const char *filename,
825 int depth) 825 struct stat *sb)
826{ 826{
827 if (!(option_mask32 & FLAG(r)) && depth) { 827 if (!(option_mask32 & FLAG(r)) && state->depth) {
828 add_to_dirlist(filename, sb, userdata, depth); 828 add_to_dirlist(state, filename, sb);
829 return SKIP; 829 return SKIP;
830 } 830 }
831 if (!(option_mask32 & FLAG(N))) { 831 if (!(option_mask32 & FLAG(N))) {
@@ -833,7 +833,7 @@ static int FAST_FUNC skip_dir(const char *filename,
833 * which do not exist on the "other side". 833 * which do not exist on the "other side".
834 * Testcase: diff -r /tmp / 834 * Testcase: diff -r /tmp /
835 * (it would recurse deep into /proc without this code) */ 835 * (it would recurse deep into /proc without this code) */
836 struct dlist *const l = userdata; 836 struct dlist *const l = state->userData;
837 filename += l->len; 837 filename += l->len;
838 if (filename[0]) { 838 if (filename[0]) {
839 struct stat osb; 839 struct stat osb;
@@ -868,7 +868,7 @@ static void diffdir(char *p[2], const char *s_start)
868 * add_to_dirlist will remove it. */ 868 * add_to_dirlist will remove it. */
869 list[i].len = strlen(p[i]); 869 list[i].len = strlen(p[i]);
870 recursive_action(p[i], ACTION_RECURSE | ACTION_FOLLOWLINKS, 870 recursive_action(p[i], ACTION_RECURSE | ACTION_FOLLOWLINKS,
871 add_to_dirlist, skip_dir, &list[i], 0); 871 add_to_dirlist, skip_dir, &list[i]);
872 /* Sort dl alphabetically. 872 /* Sort dl alphabetically.
873 * GNU diff does this ignoring any number of trailing dots. 873 * GNU diff does this ignoring any number of trailing dots.
874 * We don't, so for us dotted files almost always are 874 * We don't, so for us dotted files almost always are
diff --git a/findutils/find.c b/findutils/find.c
index 9a2c61b75..e2947afb4 100644
--- a/findutils/find.c
+++ b/findutils/find.c
@@ -889,10 +889,10 @@ ACTF(links)
889} 889}
890#endif 890#endif
891 891
892static int FAST_FUNC fileAction(const char *fileName, 892static int FAST_FUNC fileAction(
893 struct stat *statbuf, 893 struct recursive_state *state IF_NOT_FEATURE_FIND_MAXDEPTH(UNUSED_PARAM),
894 void *userData UNUSED_PARAM, 894 const char *fileName,
895 int depth IF_NOT_FEATURE_FIND_MAXDEPTH(UNUSED_PARAM)) 895 struct stat *statbuf)
896{ 896{
897 int r; 897 int r;
898 int same_fs = 1; 898 int same_fs = 1;
@@ -911,12 +911,12 @@ static int FAST_FUNC fileAction(const char *fileName,
911#endif 911#endif
912 912
913#if ENABLE_FEATURE_FIND_MAXDEPTH 913#if ENABLE_FEATURE_FIND_MAXDEPTH
914 if (depth < G.minmaxdepth[0]) { 914 if (state->depth < G.minmaxdepth[0]) {
915 if (same_fs) 915 if (same_fs)
916 return TRUE; /* skip this, continue recursing */ 916 return TRUE; /* skip this, continue recursing */
917 return SKIP; /* stop recursing */ 917 return SKIP; /* stop recursing */
918 } 918 }
919 if (depth > G.minmaxdepth[1]) 919 if (state->depth > G.minmaxdepth[1])
920 return SKIP; /* stop recursing */ 920 return SKIP; /* stop recursing */
921#endif 921#endif
922 922
@@ -927,7 +927,7 @@ static int FAST_FUNC fileAction(const char *fileName,
927 927
928#if ENABLE_FEATURE_FIND_MAXDEPTH 928#if ENABLE_FEATURE_FIND_MAXDEPTH
929 if (S_ISDIR(statbuf->st_mode)) { 929 if (S_ISDIR(statbuf->st_mode)) {
930 if (depth == G.minmaxdepth[1]) 930 if (state->depth == G.minmaxdepth[1])
931 return SKIP; 931 return SKIP;
932 } 932 }
933#endif 933#endif
@@ -1570,8 +1570,7 @@ int find_main(int argc UNUSED_PARAM, char **argv)
1570 G.recurse_flags,/* flags */ 1570 G.recurse_flags,/* flags */
1571 fileAction, /* file action */ 1571 fileAction, /* file action */
1572 fileAction, /* dir action */ 1572 fileAction, /* dir action */
1573 NULL, /* user data */ 1573 NULL) /* user data */
1574 0) /* depth */
1575 ) { 1574 ) {
1576 G.exitstatus |= EXIT_FAILURE; 1575 G.exitstatus |= EXIT_FAILURE;
1577 } 1576 }
diff --git a/findutils/grep.c b/findutils/grep.c
index 0892a713a..10cca83e7 100644
--- a/findutils/grep.c
+++ b/findutils/grep.c
@@ -656,10 +656,9 @@ static void load_pattern_list(llist_t **lst, char *pattern)
656 llist_add_to(lst, new_grep_list_data(p, 0)); 656 llist_add_to(lst, new_grep_list_data(p, 0));
657} 657}
658 658
659static int FAST_FUNC file_action_grep(const char *filename, 659static int FAST_FUNC file_action_grep(struct recursive_state *state UNUSED_PARAM,
660 struct stat *statbuf, 660 const char *filename,
661 void* matched, 661 struct stat *statbuf)
662 int depth UNUSED_PARAM)
663{ 662{
664 FILE *file; 663 FILE *file;
665 664
@@ -686,7 +685,7 @@ static int FAST_FUNC file_action_grep(const char *filename,
686 return 0; 685 return 0;
687 } 686 }
688 cur_file = filename; 687 cur_file = filename;
689 *(int*)matched |= grep_file(file); 688 *(int*)state->userData |= grep_file(file);
690 fclose(file); 689 fclose(file);
691 return 1; 690 return 1;
692} 691}
@@ -702,8 +701,8 @@ static int grep_dir(const char *dir)
702 | 0, 701 | 0,
703 /* fileAction= */ file_action_grep, 702 /* fileAction= */ file_action_grep,
704 /* dirAction= */ NULL, 703 /* dirAction= */ NULL,
705 /* userData= */ &matched, 704 /* userData= */ &matched
706 0); 705 );
707 return matched; 706 return matched;
708} 707}
709 708
diff --git a/include/libbb.h b/include/libbb.h
index 8b84d13a0..1b7c0b83a 100644
--- a/include/libbb.h
+++ b/include/libbb.h
@@ -441,10 +441,18 @@ enum {
441 ACTION_DANGLING_OK = (1 << 5), 441 ACTION_DANGLING_OK = (1 << 5),
442}; 442};
443typedef uint8_t recurse_flags_t; 443typedef uint8_t recurse_flags_t;
444extern int recursive_action(const char *fileName, unsigned flags, 444typedef struct recursive_state {
445 int FAST_FUNC (*fileAction)(const char *fileName, struct stat* statbuf, void* userData, int depth), 445 unsigned flags;
446 int FAST_FUNC (*dirAction)(const char *fileName, struct stat* statbuf, void* userData, int depth), 446 unsigned depth;
447 void* userData, unsigned depth) FAST_FUNC; 447 void *userData;
448 int FAST_FUNC (*fileAction)(struct recursive_state *state, const char *fileName, struct stat* statbuf);
449 int FAST_FUNC (*dirAction)(struct recursive_state *state, const char *fileName, struct stat* statbuf);
450} recursive_state_t;
451int recursive_action(const char *fileName, unsigned flags,
452 int FAST_FUNC (*fileAction)(struct recursive_state *state, const char *fileName, struct stat* statbuf),
453 int FAST_FUNC (*dirAction)(struct recursive_state *state, const char *fileName, struct stat* statbuf),
454 void *userData
455) FAST_FUNC;
448 456
449extern int device_open(const char *device, int mode) FAST_FUNC; 457extern int device_open(const char *device, int mode) FAST_FUNC;
450enum { GETPTY_BUFSIZE = 16 }; /* more than enough for "/dev/ttyXXX" */ 458enum { GETPTY_BUFSIZE = 16 }; /* more than enough for "/dev/ttyXXX" */
diff --git a/libbb/recursive_action.c b/libbb/recursive_action.c
index 0831ecc3a..b1c4bfad7 100644
--- a/libbb/recursive_action.c
+++ b/libbb/recursive_action.c
@@ -21,10 +21,9 @@
21 * is so stinking huge. 21 * is so stinking huge.
22 */ 22 */
23 23
24static int FAST_FUNC true_action(const char *fileName UNUSED_PARAM, 24static int FAST_FUNC true_action(struct recursive_state *state UNUSED_PARAM,
25 struct stat *statbuf UNUSED_PARAM, 25 const char *fileName UNUSED_PARAM,
26 void* userData UNUSED_PARAM, 26 struct stat *statbuf UNUSED_PARAM)
27 int depth UNUSED_PARAM)
28{ 27{
29 return TRUE; 28 return TRUE;
30} 29}
@@ -65,12 +64,7 @@ static int FAST_FUNC true_action(const char *fileName UNUSED_PARAM,
65 * 1: stat(statbuf). Calls dirAction and optionally recurse on link to dir. 64 * 1: stat(statbuf). Calls dirAction and optionally recurse on link to dir.
66 */ 65 */
67 66
68int FAST_FUNC recursive_action(const char *fileName, 67static int recursive_action1(recursive_state_t *state, const char *fileName)
69 unsigned flags,
70 int FAST_FUNC (*fileAction)(const char *fileName, struct stat *statbuf, void* userData, int depth),
71 int FAST_FUNC (*dirAction)(const char *fileName, struct stat *statbuf, void* userData, int depth),
72 void* userData,
73 unsigned depth)
74{ 68{
75 struct stat statbuf; 69 struct stat statbuf;
76 unsigned follow; 70 unsigned follow;
@@ -78,24 +72,21 @@ int FAST_FUNC recursive_action(const char *fileName,
78 DIR *dir; 72 DIR *dir;
79 struct dirent *next; 73 struct dirent *next;
80 74
81 if (!fileAction) fileAction = true_action;
82 if (!dirAction) dirAction = true_action;
83
84 follow = ACTION_FOLLOWLINKS; 75 follow = ACTION_FOLLOWLINKS;
85 if (depth == 0) 76 if (state->depth == 0)
86 follow = ACTION_FOLLOWLINKS | ACTION_FOLLOWLINKS_L0; 77 follow = ACTION_FOLLOWLINKS | ACTION_FOLLOWLINKS_L0;
87 follow &= flags; 78 follow &= state->flags;
88 status = (follow ? stat : lstat)(fileName, &statbuf); 79 status = (follow ? stat : lstat)(fileName, &statbuf);
89 if (status < 0) { 80 if (status < 0) {
90#ifdef DEBUG_RECURS_ACTION 81#ifdef DEBUG_RECURS_ACTION
91 bb_error_msg("status=%d flags=%x", status, flags); 82 bb_error_msg("status=%d flags=%x", status, state->flags);
92#endif 83#endif
93 if ((flags & ACTION_DANGLING_OK) 84 if ((state->flags & ACTION_DANGLING_OK)
94 && errno == ENOENT 85 && errno == ENOENT
95 && lstat(fileName, &statbuf) == 0 86 && lstat(fileName, &statbuf) == 0
96 ) { 87 ) {
97 /* Dangling link */ 88 /* Dangling link */
98 return fileAction(fileName, &statbuf, userData, depth); 89 return state->fileAction(state, fileName, &statbuf);
99 } 90 }
100 goto done_nak_warn; 91 goto done_nak_warn;
101 } 92 }
@@ -103,20 +94,20 @@ int FAST_FUNC recursive_action(const char *fileName,
103 /* If S_ISLNK(m), then we know that !S_ISDIR(m). 94 /* If S_ISLNK(m), then we know that !S_ISDIR(m).
104 * Then we can skip checking first part: if it is true, then 95 * Then we can skip checking first part: if it is true, then
105 * (!dir) is also true! */ 96 * (!dir) is also true! */
106 if ( /* (!(flags & ACTION_FOLLOWLINKS) && S_ISLNK(statbuf.st_mode)) || */ 97 if ( /* (!(state->flags & ACTION_FOLLOWLINKS) && S_ISLNK(statbuf.st_mode)) || */
107 !S_ISDIR(statbuf.st_mode) 98 !S_ISDIR(statbuf.st_mode)
108 ) { 99 ) {
109 return fileAction(fileName, &statbuf, userData, depth); 100 return state->fileAction(state, fileName, &statbuf);
110 } 101 }
111 102
112 /* It's a directory (or a link to one, and followLinks is set) */ 103 /* It's a directory (or a link to one, and followLinks is set) */
113 104
114 if (!(flags & ACTION_RECURSE)) { 105 if (!(state->flags & ACTION_RECURSE)) {
115 return dirAction(fileName, &statbuf, userData, depth); 106 return state->dirAction(state, fileName, &statbuf);
116 } 107 }
117 108
118 if (!(flags & ACTION_DEPTHFIRST)) { 109 if (!(state->flags & ACTION_DEPTHFIRST)) {
119 status = dirAction(fileName, &statbuf, userData, depth); 110 status = state->dirAction(state, fileName, &statbuf);
120 if (status == FALSE) 111 if (status == FALSE)
121 goto done_nak_warn; 112 goto done_nak_warn;
122 if (status == SKIP) 113 if (status == SKIP)
@@ -140,11 +131,13 @@ int FAST_FUNC recursive_action(const char *fileName,
140 continue; 131 continue;
141 132
142 /* process every file (NB: ACTION_RECURSE is set in flags) */ 133 /* process every file (NB: ACTION_RECURSE is set in flags) */
143 s = recursive_action(nextFile, flags, fileAction, dirAction, 134 state->depth++;
144 userData, depth + 1); 135 s = recursive_action1(state, nextFile);
145 if (s == FALSE) 136 if (s == FALSE)
146 status = FALSE; 137 status = FALSE;
147 free(nextFile); 138 free(nextFile);
139 state->depth--;
140
148//#define RECURSE_RESULT_ABORT -1 141//#define RECURSE_RESULT_ABORT -1
149// if (s == RECURSE_RESULT_ABORT) { 142// if (s == RECURSE_RESULT_ABORT) {
150// closedir(dir); 143// closedir(dir);
@@ -153,15 +146,36 @@ int FAST_FUNC recursive_action(const char *fileName,
153 } 146 }
154 closedir(dir); 147 closedir(dir);
155 148
156 if (flags & ACTION_DEPTHFIRST) { 149 if (state->flags & ACTION_DEPTHFIRST) {
157 if (!dirAction(fileName, &statbuf, userData, depth)) 150 if (!state->dirAction(state, fileName, &statbuf))
158 goto done_nak_warn; 151 goto done_nak_warn;
159 } 152 }
160 153
161 return status; 154 return status;
162 155
163 done_nak_warn: 156 done_nak_warn:
164 if (!(flags & ACTION_QUIET)) 157 if (!(state->flags & ACTION_QUIET))
165 bb_simple_perror_msg(fileName); 158 bb_simple_perror_msg(fileName);
166 return FALSE; 159 return FALSE;
167} 160}
161
162int FAST_FUNC recursive_action(const char *fileName,
163 unsigned flags,
164 int FAST_FUNC (*fileAction)(struct recursive_state *state, const char *fileName, struct stat* statbuf),
165 int FAST_FUNC (*dirAction)(struct recursive_state *state, const char *fileName, struct stat* statbuf),
166 void *userData)
167{
168 /* Keeping a part of variables of recusive descent in a "state structure"
169 * instead of passing ALL of them down as parameters of recursive_action1()
170 * relieves register pressure, both in recursive_action1()
171 * and in every file/dirAction().
172 */
173 recursive_state_t state;
174 state.flags = flags;
175 state.depth = 0;
176 state.userData = userData;
177 state.fileAction = fileAction ? fileAction : true_action;
178 state.dirAction = dirAction ? dirAction : true_action;
179
180 return recursive_action1(&state, fileName);
181}
diff --git a/modutils/depmod.c b/modutils/depmod.c
index 318e7cdc7..bb42bbefe 100644
--- a/modutils/depmod.c
+++ b/modutils/depmod.c
@@ -32,10 +32,11 @@
32 * for each depends, look through our list of full paths and emit if found 32 * for each depends, look through our list of full paths and emit if found
33 */ 33 */
34 34
35static int FAST_FUNC parse_module(const char *fname, struct stat *sb UNUSED_PARAM, 35static int FAST_FUNC parse_module(struct recursive_state *state,
36 void *data, int depth UNUSED_PARAM) 36 const char *fname,
37 struct stat *sb UNUSED_PARAM)
37{ 38{
38 module_db *modules = data; 39 module_db *modules = state->userData;
39 char *image, *ptr; 40 char *image, *ptr;
40 module_entry *e; 41 module_entry *e;
41 42
@@ -201,11 +202,12 @@ int depmod_main(int argc UNUSED_PARAM, char **argv)
201 memset(&modules, 0, sizeof(modules)); 202 memset(&modules, 0, sizeof(modules));
202 if (*argv) { 203 if (*argv) {
203 do { 204 do {
204 parse_module(*argv, /*sb (unused):*/ NULL, &modules, 0); 205 recursive_action(*argv, 0 /* no ACTION_RECURSE! */,
206 parse_module, NULL, &modules);
205 } while (*++argv); 207 } while (*++argv);
206 } else { 208 } else {
207 recursive_action(".", ACTION_RECURSE, 209 recursive_action(".", ACTION_RECURSE,
208 parse_module, NULL, &modules, 0); 210 parse_module, NULL, &modules);
209 } 211 }
210 212
211 /* Generate dependency and alias files */ 213 /* Generate dependency and alias files */
diff --git a/modutils/modprobe-small.c b/modutils/modprobe-small.c
index a94b0b9a6..18cfac481 100644
--- a/modutils/modprobe-small.c
+++ b/modutils/modprobe-small.c
@@ -751,8 +751,7 @@ static int process_module(char *name, const char *cmdline_options)
751 ACTION_RECURSE, /* flags */ 751 ACTION_RECURSE, /* flags */
752 fileAction, /* file action */ 752 fileAction, /* file action */
753 NULL, /* dir action */ 753 NULL, /* dir action */
754 name, /* user data */ 754 name /* user data */
755 0 /* depth */
756 ); 755 );
757 dbg1_error_msg("dirscan complete"); 756 dbg1_error_msg("dirscan complete");
758 /* Module was not found, or load failed, or is_remove */ 757 /* Module was not found, or load failed, or is_remove */
diff --git a/modutils/modprobe.c b/modutils/modprobe.c
index 70c45903a..eeeff7609 100644
--- a/modutils/modprobe.c
+++ b/modutils/modprobe.c
@@ -235,10 +235,9 @@ static void add_probe(const char *name)
235 } 235 }
236} 236}
237 237
238static int FAST_FUNC config_file_action(const char *filename, 238static int FAST_FUNC config_file_action(struct recursive_state *state,
239 struct stat *statbuf UNUSED_PARAM, 239 const char *filename,
240 void *userdata UNUSED_PARAM, 240 struct stat *statbuf UNUSED_PARAM)
241 int depth)
242{ 241{
243 char *tokens[3]; 242 char *tokens[3];
244 parser_t *p; 243 parser_t *p;
@@ -255,7 +254,7 @@ static int FAST_FUNC config_file_action(const char *filename,
255 * that we shouldn't recurse into /etc/modprobe.d/dir/ 254 * that we shouldn't recurse into /etc/modprobe.d/dir/
256 * _subdirectories_: 255 * _subdirectories_:
257 */ 256 */
258 if (depth > 1) 257 if (state->depth > 1)
259 return SKIP; /* stop recursing */ 258 return SKIP; /* stop recursing */
260//TODO: instead, can use dirAction in recursive_action() to SKIP dirs 259//TODO: instead, can use dirAction in recursive_action() to SKIP dirs
261//on depth == 1 level. But that's more code... 260//on depth == 1 level. But that's more code...
@@ -264,7 +263,7 @@ static int FAST_FUNC config_file_action(const char *filename,
264 * depth==0: read_config("modules.{symbols,alias}") must work, 263 * depth==0: read_config("modules.{symbols,alias}") must work,
265 * "include FILE_NOT_ENDING_IN_CONF" must work too. 264 * "include FILE_NOT_ENDING_IN_CONF" must work too.
266 */ 265 */
267 if (depth != 0) { 266 if (state->depth != 0) {
268 if (!is_suffixed_with(base, ".conf")) 267 if (!is_suffixed_with(base, ".conf"))
269 goto error; 268 goto error;
270 } 269 }
@@ -329,8 +328,7 @@ static int FAST_FUNC config_file_action(const char *filename,
329static int read_config(const char *path) 328static int read_config(const char *path)
330{ 329{
331 return recursive_action(path, ACTION_RECURSE | ACTION_QUIET, 330 return recursive_action(path, ACTION_RECURSE | ACTION_QUIET,
332 config_file_action, NULL, NULL, 331 config_file_action, NULL, NULL);
333 /*depth:*/ 0);
334} 332}
335 333
336static const char *humanly_readable_name(struct module_entry *m) 334static const char *humanly_readable_name(struct module_entry *m)
diff --git a/networking/netstat.c b/networking/netstat.c
index 936610f89..3ab7b0d21 100644
--- a/networking/netstat.c
+++ b/networking/netstat.c
@@ -272,10 +272,9 @@ static long extract_socket_inode(const char *lname)
272 return inode; 272 return inode;
273} 273}
274 274
275static int FAST_FUNC add_to_prg_cache_if_socket(const char *fileName, 275static int FAST_FUNC add_to_prg_cache_if_socket(struct recursive_state *state,
276 struct stat *statbuf UNUSED_PARAM, 276 const char *fileName,
277 void *pid_slash_progname, 277 struct stat *statbuf UNUSED_PARAM)
278 int depth UNUSED_PARAM)
279{ 278{
280 char *linkname; 279 char *linkname;
281 long inode; 280 long inode;
@@ -284,16 +283,17 @@ static int FAST_FUNC add_to_prg_cache_if_socket(const char *fileName,
284 if (linkname != NULL) { 283 if (linkname != NULL) {
285 inode = extract_socket_inode(linkname); 284 inode = extract_socket_inode(linkname);
286 free(linkname); 285 free(linkname);
287 if (inode >= 0) 286 if (inode >= 0) {
288 prg_cache_add(inode, (char *)pid_slash_progname); 287 char *pid_slash_progname = state->userData;
288 prg_cache_add(inode, pid_slash_progname);
289 }
289 } 290 }
290 return TRUE; 291 return TRUE;
291} 292}
292 293
293static int FAST_FUNC dir_act(const char *fileName, 294static int FAST_FUNC dir_act(struct recursive_state *state,
294 struct stat *statbuf UNUSED_PARAM, 295 const char *fileName,
295 void *userData UNUSED_PARAM, 296 struct stat *statbuf UNUSED_PARAM)
296 int depth)
297{ 297{
298 const char *pid; 298 const char *pid;
299 char *pid_slash_progname; 299 char *pid_slash_progname;
@@ -301,7 +301,7 @@ static int FAST_FUNC dir_act(const char *fileName,
301 char cmdline_buf[512]; 301 char cmdline_buf[512];
302 int n, len; 302 int n, len;
303 303
304 if (depth == 0) /* "/proc" itself */ 304 if (state->depth == 0) /* "/proc" itself */
305 return TRUE; /* continue looking one level below /proc */ 305 return TRUE; /* continue looking one level below /proc */
306 306
307 pid = fileName + sizeof("/proc/")-1; /* point after "/proc/" */ 307 pid = fileName + sizeof("/proc/")-1; /* point after "/proc/" */
@@ -321,8 +321,8 @@ static int FAST_FUNC dir_act(const char *fileName,
321 ACTION_RECURSE | ACTION_QUIET, 321 ACTION_RECURSE | ACTION_QUIET,
322 add_to_prg_cache_if_socket, 322 add_to_prg_cache_if_socket,
323 NULL, 323 NULL,
324 (void *)pid_slash_progname, 324 (void *)pid_slash_progname
325 0); 325 );
326 free(pid_slash_progname); 326 free(pid_slash_progname);
327 327
328 if (!n) 328 if (!n)
@@ -337,7 +337,7 @@ static void prg_cache_load(void)
337 337
338 prg_cache_loaded = 1; 338 prg_cache_loaded = 1;
339 load_ok = recursive_action("/proc", ACTION_RECURSE | ACTION_QUIET, 339 load_ok = recursive_action("/proc", ACTION_RECURSE | ACTION_QUIET,
340 NULL, dir_act, NULL, 0); 340 NULL, dir_act, NULL);
341 if (load_ok) 341 if (load_ok)
342 return; 342 return;
343 343
diff --git a/selinux/chcon.c b/selinux/chcon.c
index afe7f713d..9b13679b8 100644
--- a/selinux/chcon.c
+++ b/selinux/chcon.c
@@ -62,11 +62,9 @@ static char *type = NULL;
62static char *range = NULL; 62static char *range = NULL;
63static char *specified_context = NULL; 63static char *specified_context = NULL;
64 64
65static int FAST_FUNC change_filedir_context( 65static int FAST_FUNC change_filedir_context(struct recursive_state *state UNUSED_PARAM,
66 const char *fname, 66 const char *fname,
67 struct stat *stbuf UNUSED_PARAM, 67 struct stat *stbuf UNUSED_PARAM)
68 void *userData UNUSED_PARAM,
69 int depth UNUSED_PARAM)
70{ 68{
71 context_t context = NULL; 69 context_t context = NULL;
72 security_context_t file_context = NULL; 70 security_context_t file_context = NULL;
@@ -207,7 +205,7 @@ int chcon_main(int argc UNUSED_PARAM, char **argv)
207 ((option_mask32 & OPT_RECURSIVE) ? ACTION_RECURSE : 0), 205 ((option_mask32 & OPT_RECURSIVE) ? ACTION_RECURSE : 0),
208 change_filedir_context, 206 change_filedir_context,
209 change_filedir_context, 207 change_filedir_context,
210 NULL, 0) != TRUE) 208 NULL) != TRUE)
211 errors = 1; 209 errors = 1;
212 } 210 }
213 return errors; 211 return errors;
diff --git a/selinux/setfiles.c b/selinux/setfiles.c
index 55bfb4d02..a617b95d8 100644
--- a/selinux/setfiles.c
+++ b/selinux/setfiles.c
@@ -463,11 +463,9 @@ static int restore(const char *file)
463 * This function is called by recursive_action on each file during 463 * This function is called by recursive_action on each file during
464 * the directory traversal. 464 * the directory traversal.
465 */ 465 */
466static int FAST_FUNC apply_spec( 466static int FAST_FUNC apply_spec(struct recursive_state *state UNUSED_PARAM,
467 const char *file, 467 const char *file,
468 struct stat *sb, 468 struct stat *sb)
469 void *userData UNUSED_PARAM,
470 int depth UNUSED_PARAM)
471{ 469{
472 if (!follow_mounts) { 470 if (!follow_mounts) {
473 /* setfiles does not process across different mount points */ 471 /* setfiles does not process across different mount points */
@@ -535,7 +533,7 @@ static int process_one(char *name)
535 ACTION_RECURSE, 533 ACTION_RECURSE,
536 apply_spec, 534 apply_spec,
537 apply_spec, 535 apply_spec,
538 NULL, 0) != TRUE 536 NULL) != TRUE
539 ) { 537 ) {
540 bb_error_msg("error while labeling %s", name); 538 bb_error_msg("error while labeling %s", name);
541 goto err; 539 goto err;
diff --git a/util-linux/lspci.c b/util-linux/lspci.c
index 2f0b5fab9..c22cbcc1e 100644
--- a/util-linux/lspci.c
+++ b/util-linux/lspci.c
@@ -37,11 +37,9 @@ enum {
37/* 37/*
38 * PCI_SLOT_NAME PCI_CLASS: PCI_VID:PCI_DID [PCI_SUBSYS_VID:PCI_SUBSYS_DID] [DRIVER] 38 * PCI_SLOT_NAME PCI_CLASS: PCI_VID:PCI_DID [PCI_SUBSYS_VID:PCI_SUBSYS_DID] [DRIVER]
39 */ 39 */
40static int FAST_FUNC fileAction( 40static int FAST_FUNC fileAction(struct recursive_state *state UNUSED_PARAM,
41 const char *fileName, 41 const char *fileName,
42 struct stat *statbuf UNUSED_PARAM, 42 struct stat *statbuf UNUSED_PARAM)
43 void *userData UNUSED_PARAM,
44 int depth UNUSED_PARAM)
45{ 43{
46 parser_t *parser; 44 parser_t *parser;
47 char *tokens[3]; 45 char *tokens[3];
@@ -117,8 +115,7 @@ int lspci_main(int argc UNUSED_PARAM, char **argv)
117 ACTION_RECURSE, 115 ACTION_RECURSE,
118 fileAction, 116 fileAction,
119 NULL, /* dirAction */ 117 NULL, /* dirAction */
120 NULL, /* userData */ 118 NULL /* userData */
121 0 /* depth */); 119 );
122
123 return EXIT_SUCCESS; 120 return EXIT_SUCCESS;
124} 121}
diff --git a/util-linux/lsusb.c b/util-linux/lsusb.c
index 64a00eee2..9abb748ce 100644
--- a/util-linux/lsusb.c
+++ b/util-linux/lsusb.c
@@ -24,11 +24,9 @@
24 24
25#include "libbb.h" 25#include "libbb.h"
26 26
27static int FAST_FUNC fileAction( 27static int FAST_FUNC fileAction(struct recursive_state *state UNUSED_PARAM,
28 const char *fileName, 28 const char *fileName,
29 struct stat *statbuf UNUSED_PARAM, 29 struct stat *statbuf UNUSED_PARAM)
30 void *userData UNUSED_PARAM,
31 int depth UNUSED_PARAM)
32{ 30{
33 parser_t *parser; 31 parser_t *parser;
34 char *tokens[4]; 32 char *tokens[4];
@@ -80,8 +78,8 @@ int lsusb_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
80 ACTION_RECURSE, 78 ACTION_RECURSE,
81 fileAction, 79 fileAction,
82 NULL, /* dirAction */ 80 NULL, /* dirAction */
83 NULL, /* userData */ 81 NULL /* userData */
84 0 /* depth */); 82 );
85 83
86 return EXIT_SUCCESS; 84 return EXIT_SUCCESS;
87} 85}
diff --git a/util-linux/mdev.c b/util-linux/mdev.c
index f42bebc20..59dbcf0cd 100644
--- a/util-linux/mdev.c
+++ b/util-linux/mdev.c
@@ -845,13 +845,12 @@ static ssize_t readlink2(char *buf, size_t bufsize)
845/* File callback for /sys/ traversal. 845/* File callback for /sys/ traversal.
846 * We act only on "/sys/.../dev" (pseudo)file 846 * We act only on "/sys/.../dev" (pseudo)file
847 */ 847 */
848static int FAST_FUNC fileAction(const char *fileName, 848static int FAST_FUNC fileAction(struct recursive_state *state,
849 struct stat *statbuf UNUSED_PARAM, 849 const char *fileName,
850 void *userData, 850 struct stat *statbuf UNUSED_PARAM)
851 int depth UNUSED_PARAM)
852{ 851{
853 size_t len = strlen(fileName) - 4; /* can't underflow */ 852 size_t len = strlen(fileName) - 4; /* can't underflow */
854 char *path = userData; /* char array[PATH_MAX + SCRATCH_SIZE] */ 853 char *path = state->userData; /* char array[PATH_MAX + SCRATCH_SIZE] */
855 char subsys[PATH_MAX]; 854 char subsys[PATH_MAX];
856 int res; 855 int res;
857 856
@@ -888,12 +887,11 @@ static int FAST_FUNC fileAction(const char *fileName,
888} 887}
889 888
890/* Directory callback for /sys/ traversal */ 889/* Directory callback for /sys/ traversal */
891static int FAST_FUNC dirAction(const char *fileName UNUSED_PARAM, 890static int FAST_FUNC dirAction(struct recursive_state *state,
892 struct stat *statbuf UNUSED_PARAM, 891 const char *fileName UNUSED_PARAM,
893 void *userData UNUSED_PARAM, 892 struct stat *statbuf UNUSED_PARAM)
894 int depth)
895{ 893{
896 return (depth >= MAX_SYSFS_DEPTH ? SKIP : TRUE); 894 return (state->depth >= MAX_SYSFS_DEPTH ? SKIP : TRUE);
897} 895}
898 896
899/* For the full gory details, see linux/Documentation/firmware_class/README 897/* For the full gory details, see linux/Documentation/firmware_class/README
@@ -1149,7 +1147,7 @@ static void initial_scan(char *temp)
1149 /* Create all devices from /sys/dev hierarchy */ 1147 /* Create all devices from /sys/dev hierarchy */
1150 recursive_action("/sys/dev", 1148 recursive_action("/sys/dev",
1151 ACTION_RECURSE | ACTION_FOLLOWLINKS, 1149 ACTION_RECURSE | ACTION_FOLLOWLINKS,
1152 fileAction, dirAction, temp, 0); 1150 fileAction, dirAction, temp);
1153} 1151}
1154 1152
1155#if ENABLE_FEATURE_MDEV_DAEMON 1153#if ENABLE_FEATURE_MDEV_DAEMON
diff --git a/util-linux/volume_id/get_devname.c b/util-linux/volume_id/get_devname.c
index 34f5d119f..00cfb2826 100644
--- a/util-linux/volume_id/get_devname.c
+++ b/util-linux/volume_id/get_devname.c
@@ -102,10 +102,9 @@ uuidcache_addentry(char *device, /*int major, int minor,*/ char *label, char *uu
102 * add a cache entry for this device. 102 * add a cache entry for this device.
103 * If device node does not exist, it will be temporarily created. */ 103 * If device node does not exist, it will be temporarily created. */
104static int FAST_FUNC 104static int FAST_FUNC
105uuidcache_check_device(const char *device, 105uuidcache_check_device(struct recursive_state *state UNUSED_PARAM,
106 struct stat *statbuf, 106 const char *device,
107 void *userData UNUSED_PARAM, 107 struct stat *statbuf)
108 int depth UNUSED_PARAM)
109{ 108{
110 /* note: this check rejects links to devices, among other nodes */ 109 /* note: this check rejects links to devices, among other nodes */
111 if (!S_ISBLK(statbuf->st_mode) 110 if (!S_ISBLK(statbuf->st_mode)
@@ -145,12 +144,13 @@ uuidcache_init(int scan_devices)
145 * This is unacceptably complex. Let's just scan /dev. 144 * This is unacceptably complex. Let's just scan /dev.
146 * (Maybe add scanning of /sys/block/XXX/dev for devices 145 * (Maybe add scanning of /sys/block/XXX/dev for devices
147 * somehow not having their /dev/XXX entries created?) */ 146 * somehow not having their /dev/XXX entries created?) */
148 if (scan_devices) 147 if (scan_devices) {
149 recursive_action("/dev", ACTION_RECURSE, 148 recursive_action("/dev", ACTION_RECURSE,
150 uuidcache_check_device, /* file_action */ 149 uuidcache_check_device, /* file_action */
151 NULL, /* dir_action */ 150 NULL, /* dir_action */
152 NULL, /* userData */ 151 NULL /* userData */
153 0 /* depth */); 152 );
153 }
154 154
155 return uuidCache; 155 return uuidCache;
156} 156}