[git commit] libbb: shrink recursive_action() by reducing memory pressure

Denys Vlasenko vda.linux at googlemail.com
Thu Oct 1 19:52:16 UTC 2020


commit: https://git.busybox.net/busybox/commit/?id=689d0650ab63425adaea26afe347015a204958ee
branch: https://git.busybox.net/busybox/commit/?id=refs/heads/master

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 at googlemail.com>
---
 archival/tar.c                     |  9 ++---
 coreutils/chmod.c                  | 13 +++----
 coreutils/chown.c                  |  9 +++--
 debianutils/run_parts.c            | 10 +++---
 editors/diff.c                     | 22 ++++++------
 findutils/find.c                   | 17 +++++----
 findutils/grep.c                   | 13 ++++---
 include/libbb.h                    | 16 ++++++---
 libbb/recursive_action.c           | 72 +++++++++++++++++++++++---------------
 modutils/depmod.c                  | 12 ++++---
 modutils/modprobe-small.c          |  3 +-
 modutils/modprobe.c                | 14 ++++----
 networking/netstat.c               | 28 +++++++--------
 selinux/chcon.c                    |  8 ++---
 selinux/setfiles.c                 |  8 ++---
 util-linux/lspci.c                 | 11 +++---
 util-linux/lsusb.c                 | 10 +++---
 util-linux/mdev.c                  | 20 +++++------
 util-linux/volume_id/get_devname.c | 14 ++++----
 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)
 #  define exclude_file(excluded_files, file) 0
 # endif
 
-static int FAST_FUNC writeFileToTarball(const char *fileName, struct stat *statbuf,
-			void *userData, int depth UNUSED_PARAM)
+static int FAST_FUNC writeFileToTarball(struct recursive_state *state,
+		const char *fileName,
+		struct stat *statbuf)
 {
-	struct TarBallInfo *tbInfo = (struct TarBallInfo *) userData;
+	struct TarBallInfo *tbInfo = (struct TarBallInfo *) state->userData;
 	const char *header_name;
 	int inputFileFd = -1;
 
@@ -700,7 +701,7 @@ static NOINLINE int writeTarFile(
 	/* Read the directory/files and iterate over them one at a time */
 	while (filelist) {
 		if (!recursive_action(filelist->data, recurseFlags,
-				writeFileToTarball, writeFileToTarball, tbInfo, 0)
+				writeFileToTarball, writeFileToTarball, tbInfo)
 		) {
 			errorFlag = TRUE;
 		}
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 @@
  * symbolic links encountered during recursive directory traversals.
  */
 
-static int FAST_FUNC fileAction(const char *fileName, struct stat *statbuf, void* param, int depth)
+static int FAST_FUNC fileAction(struct recursive_state *state,
+		const char *fileName,
+		struct stat *statbuf)
 {
 	mode_t newmode;
 
 	/* match coreutils behavior */
-	if (depth == 0) {
+	if (state->depth == 0) {
 		/* statbuf holds lstat result, but we need stat (follow link) */
 		if (stat(fileName, statbuf))
 			goto err;
@@ -79,9 +81,9 @@ static int FAST_FUNC fileAction(const char *fileName, struct stat *statbuf, void
 			return TRUE;
 	}
 
-	newmode = bb_parse_mode((char *)param, statbuf->st_mode);
+	newmode = bb_parse_mode((char *)state->userData, statbuf->st_mode);
 	if (newmode == (mode_t)-1)
-		bb_error_msg_and_die("invalid mode '%s'", (char *)param);
+		bb_error_msg_and_die("invalid mode '%s'", (char *)state->userData);
 
 	if (chmod(fileName, newmode) == 0) {
 		if (OPT_VERBOSE
@@ -136,8 +138,7 @@ int chmod_main(int argc UNUSED_PARAM, char **argv)
 			OPT_RECURSE,    // recurse
 			fileAction,     // file action
 			fileAction,     // dir action
-			smode,          // user data
-			0)              // depth
+			smode)          // user data
 		) {
 			retval = EXIT_FAILURE;
 		}
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 {
 	chown_fptr chown_func;
 };
 
-static int FAST_FUNC fileAction(const char *fileName, struct stat *statbuf,
-		void *vparam, int depth UNUSED_PARAM)
+static int FAST_FUNC fileAction(struct recursive_state *state UNUSED_PARAM,
+		const char *fileName, struct stat *statbuf)
 {
-#define param  (*(struct param_t*)vparam)
+#define param  (*(struct param_t*)state->userData)
 #define opt option_mask32
 	uid_t u = (param.ugid.uid == (uid_t)-1L) ? statbuf->st_uid : param.ugid.uid;
 	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)
 				flags,          /* flags */
 				fileAction,     /* file action */
 				fileAction,     /* dir action */
-				&param,         /* user data */
-				0)              /* depth */
+				&param)         /* user data */
 		) {
 			retval = EXIT_FAILURE;
 		}
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)
 	return (option_mask32 & OPT_r) ? -r : r;
 }
 
-static int FAST_FUNC act(const char *file, struct stat *statbuf, void *args UNUSED_PARAM, int depth)
+static int FAST_FUNC act(struct recursive_state *state,
+		const char *file, struct stat *statbuf)
 {
-	if (depth == 0)
+	if (state->depth == 0)
 		return TRUE;
 
-	if (depth == 1
+	if (state->depth == 1
 	 && (  !(statbuf->st_mode & (S_IFREG | S_IFLNK))
 	    || invalid_name(file)
 	    || (!(option_mask32 & OPT_l) && access(file, X_OK) != 0))
@@ -199,8 +200,7 @@ int run_parts_main(int argc UNUSED_PARAM, char **argv)
 			ACTION_RECURSE|ACTION_FOLLOWLINKS,
 			act,            /* file action */
 			act,            /* dir action */
-			NULL,           /* user data */
-			0               /* depth */
+			NULL            /* user data */
 	);
 
 	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 {
 };
 
 /* This function adds a filename to dl, the directory listing. */
-static int FAST_FUNC add_to_dirlist(const char *filename,
-		struct stat *sb UNUSED_PARAM,
-		void *userdata, int depth UNUSED_PARAM)
+static int FAST_FUNC add_to_dirlist(struct recursive_state *state,
+		const char *filename,
+		struct stat *sb UNUSED_PARAM)
 {
-	struct dlist *const l = userdata;
+	struct dlist *const l = state->userData;
 	const char *file = filename + l->len;
 	while (*file == '/')
 		file++;
@@ -820,12 +820,12 @@ static int FAST_FUNC add_to_dirlist(const char *filename,
 /* If recursion is not set, this function adds the directory
  * to the list and prevents recursive_action from recursing into it.
  */
-static int FAST_FUNC skip_dir(const char *filename,
-		struct stat *sb, void *userdata,
-		int depth)
+static int FAST_FUNC skip_dir(struct recursive_state *state,
+		const char *filename,
+		struct stat *sb)
 {
-	if (!(option_mask32 & FLAG(r)) && depth) {
-		add_to_dirlist(filename, sb, userdata, depth);
+	if (!(option_mask32 & FLAG(r)) && state->depth) {
+		add_to_dirlist(state, filename, sb);
 		return SKIP;
 	}
 	if (!(option_mask32 & FLAG(N))) {
@@ -833,7 +833,7 @@ static int FAST_FUNC skip_dir(const char *filename,
 		 * which do not exist on the "other side".
 		 * Testcase: diff -r /tmp /
 		 * (it would recurse deep into /proc without this code) */
-		struct dlist *const l = userdata;
+		struct dlist *const l = state->userData;
 		filename += l->len;
 		if (filename[0]) {
 			struct stat osb;
@@ -868,7 +868,7 @@ static void diffdir(char *p[2], const char *s_start)
 		 * add_to_dirlist will remove it. */
 		list[i].len = strlen(p[i]);
 		recursive_action(p[i], ACTION_RECURSE | ACTION_FOLLOWLINKS,
-				add_to_dirlist, skip_dir, &list[i], 0);
+				add_to_dirlist, skip_dir, &list[i]);
 		/* Sort dl alphabetically.
 		 * GNU diff does this ignoring any number of trailing dots.
 		 * 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)
 }
 #endif
 
-static int FAST_FUNC fileAction(const char *fileName,
-		struct stat *statbuf,
-		void *userData UNUSED_PARAM,
-		int depth IF_NOT_FEATURE_FIND_MAXDEPTH(UNUSED_PARAM))
+static int FAST_FUNC fileAction(
+		struct recursive_state *state IF_NOT_FEATURE_FIND_MAXDEPTH(UNUSED_PARAM),
+		const char *fileName,
+		struct stat *statbuf)
 {
 	int r;
 	int same_fs = 1;
@@ -911,12 +911,12 @@ static int FAST_FUNC fileAction(const char *fileName,
 #endif
 
 #if ENABLE_FEATURE_FIND_MAXDEPTH
-	if (depth < G.minmaxdepth[0]) {
+	if (state->depth < G.minmaxdepth[0]) {
 		if (same_fs)
 			return TRUE; /* skip this, continue recursing */
 		return SKIP; /* stop recursing */
 	}
-	if (depth > G.minmaxdepth[1])
+	if (state->depth > G.minmaxdepth[1])
 		return SKIP; /* stop recursing */
 #endif
 
@@ -927,7 +927,7 @@ static int FAST_FUNC fileAction(const char *fileName,
 
 #if ENABLE_FEATURE_FIND_MAXDEPTH
 	if (S_ISDIR(statbuf->st_mode)) {
-		if (depth == G.minmaxdepth[1])
+		if (state->depth == G.minmaxdepth[1])
 			return SKIP;
 	}
 #endif
@@ -1570,8 +1570,7 @@ int find_main(int argc UNUSED_PARAM, char **argv)
 				G.recurse_flags,/* flags */
 				fileAction,     /* file action */
 				fileAction,     /* dir action */
-				NULL,           /* user data */
-				0)              /* depth */
+				NULL)           /* user data */
 		) {
 			G.exitstatus |= EXIT_FAILURE;
 		}
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)
 		llist_add_to(lst, new_grep_list_data(p, 0));
 }
 
-static int FAST_FUNC file_action_grep(const char *filename,
-			struct stat *statbuf,
-			void* matched,
-			int depth UNUSED_PARAM)
+static int FAST_FUNC file_action_grep(struct recursive_state *state UNUSED_PARAM,
+		const char *filename,
+		struct stat *statbuf)
 {
 	FILE *file;
 
@@ -686,7 +685,7 @@ static int FAST_FUNC file_action_grep(const char *filename,
 		return 0;
 	}
 	cur_file = filename;
-	*(int*)matched |= grep_file(file);
+	*(int*)state->userData |= grep_file(file);
 	fclose(file);
 	return 1;
 }
@@ -702,8 +701,8 @@ static int grep_dir(const char *dir)
 		| 0,
 		/* fileAction= */ file_action_grep,
 		/* dirAction= */ NULL,
-		/* userData= */ &matched,
-		0);
+		/* userData= */ &matched
+	);
 	return matched;
 }
 
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 {
 	ACTION_DANGLING_OK    = (1 << 5),
 };
 typedef uint8_t recurse_flags_t;
-extern int recursive_action(const char *fileName, unsigned flags,
-	int FAST_FUNC (*fileAction)(const char *fileName, struct stat* statbuf, void* userData, int depth),
-	int FAST_FUNC (*dirAction)(const char *fileName, struct stat* statbuf, void* userData, int depth),
-	void* userData, unsigned depth) FAST_FUNC;
+typedef struct recursive_state {
+	unsigned flags;
+	unsigned depth;
+	void *userData;
+	int FAST_FUNC (*fileAction)(struct recursive_state *state, const char *fileName, struct stat* statbuf);
+	int FAST_FUNC  (*dirAction)(struct recursive_state *state, const char *fileName, struct stat* statbuf);
+} recursive_state_t;
+int recursive_action(const char *fileName, unsigned flags,
+	int FAST_FUNC (*fileAction)(struct recursive_state *state, const char *fileName, struct stat* statbuf),
+	int FAST_FUNC  (*dirAction)(struct recursive_state *state, const char *fileName, struct stat* statbuf),
+	void *userData
+) FAST_FUNC;
 
 extern int device_open(const char *device, int mode) FAST_FUNC;
 enum { 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 @@
  * is so stinking huge.
  */
 
-static int FAST_FUNC true_action(const char *fileName UNUSED_PARAM,
-		struct stat *statbuf UNUSED_PARAM,
-		void* userData UNUSED_PARAM,
-		int depth UNUSED_PARAM)
+static int FAST_FUNC true_action(struct recursive_state *state UNUSED_PARAM,
+		const char *fileName UNUSED_PARAM,
+		struct stat *statbuf UNUSED_PARAM)
 {
 	return TRUE;
 }
@@ -65,12 +64,7 @@ static int FAST_FUNC true_action(const char *fileName UNUSED_PARAM,
  * 1: stat(statbuf). Calls dirAction and optionally recurse on link to dir.
  */
 
-int FAST_FUNC recursive_action(const char *fileName,
-		unsigned flags,
-		int FAST_FUNC (*fileAction)(const char *fileName, struct stat *statbuf, void* userData, int depth),
-		int FAST_FUNC (*dirAction)(const char *fileName, struct stat *statbuf, void* userData, int depth),
-		void* userData,
-		unsigned depth)
+static int recursive_action1(recursive_state_t *state, const char *fileName)
 {
 	struct stat statbuf;
 	unsigned follow;
@@ -78,24 +72,21 @@ int FAST_FUNC recursive_action(const char *fileName,
 	DIR *dir;
 	struct dirent *next;
 
-	if (!fileAction) fileAction = true_action;
-	if (!dirAction) dirAction = true_action;
-
 	follow = ACTION_FOLLOWLINKS;
-	if (depth == 0)
+	if (state->depth == 0)
 		follow = ACTION_FOLLOWLINKS | ACTION_FOLLOWLINKS_L0;
-	follow &= flags;
+	follow &= state->flags;
 	status = (follow ? stat : lstat)(fileName, &statbuf);
 	if (status < 0) {
 #ifdef DEBUG_RECURS_ACTION
-		bb_error_msg("status=%d flags=%x", status, flags);
+		bb_error_msg("status=%d flags=%x", status, state->flags);
 #endif
-		if ((flags & ACTION_DANGLING_OK)
+		if ((state->flags & ACTION_DANGLING_OK)
 		 && errno == ENOENT
 		 && lstat(fileName, &statbuf) == 0
 		) {
 			/* Dangling link */
-			return fileAction(fileName, &statbuf, userData, depth);
+			return state->fileAction(state, fileName, &statbuf);
 		}
 		goto done_nak_warn;
 	}
@@ -103,20 +94,20 @@ int FAST_FUNC recursive_action(const char *fileName,
 	/* If S_ISLNK(m), then we know that !S_ISDIR(m).
 	 * Then we can skip checking first part: if it is true, then
 	 * (!dir) is also true! */
-	if ( /* (!(flags & ACTION_FOLLOWLINKS) && S_ISLNK(statbuf.st_mode)) || */
+	if ( /* (!(state->flags & ACTION_FOLLOWLINKS) && S_ISLNK(statbuf.st_mode)) || */
 	 !S_ISDIR(statbuf.st_mode)
 	) {
-		return fileAction(fileName, &statbuf, userData, depth);
+		return state->fileAction(state, fileName, &statbuf);
 	}
 
 	/* It's a directory (or a link to one, and followLinks is set) */
 
-	if (!(flags & ACTION_RECURSE)) {
-		return dirAction(fileName, &statbuf, userData, depth);
+	if (!(state->flags & ACTION_RECURSE)) {
+		return state->dirAction(state, fileName, &statbuf);
 	}
 
-	if (!(flags & ACTION_DEPTHFIRST)) {
-		status = dirAction(fileName, &statbuf, userData, depth);
+	if (!(state->flags & ACTION_DEPTHFIRST)) {
+		status = state->dirAction(state, fileName, &statbuf);
 		if (status == FALSE)
 			goto done_nak_warn;
 		if (status == SKIP)
@@ -140,11 +131,13 @@ int FAST_FUNC recursive_action(const char *fileName,
 			continue;
 
 		/* process every file (NB: ACTION_RECURSE is set in flags) */
-		s = recursive_action(nextFile, flags, fileAction, dirAction,
-						userData, depth + 1);
+		state->depth++;
+		s = recursive_action1(state, nextFile);
 		if (s == FALSE)
 			status = FALSE;
 		free(nextFile);
+		state->depth--;
+
 //#define RECURSE_RESULT_ABORT -1
 //		if (s == RECURSE_RESULT_ABORT) {
 //			closedir(dir);
@@ -153,15 +146,36 @@ int FAST_FUNC recursive_action(const char *fileName,
 	}
 	closedir(dir);
 
-	if (flags & ACTION_DEPTHFIRST) {
-		if (!dirAction(fileName, &statbuf, userData, depth))
+	if (state->flags & ACTION_DEPTHFIRST) {
+		if (!state->dirAction(state, fileName, &statbuf))
 			goto done_nak_warn;
 	}
 
 	return status;
 
  done_nak_warn:
-	if (!(flags & ACTION_QUIET))
+	if (!(state->flags & ACTION_QUIET))
 		bb_simple_perror_msg(fileName);
 	return FALSE;
 }
+
+int FAST_FUNC recursive_action(const char *fileName,
+		unsigned flags,
+		int FAST_FUNC (*fileAction)(struct recursive_state *state, const char *fileName, struct stat* statbuf),
+		int FAST_FUNC  (*dirAction)(struct recursive_state *state, const char *fileName, struct stat* statbuf),
+		void *userData)
+{
+	/* Keeping a part of variables of recusive descent in a "state structure"
+	 * instead of passing ALL of them down as parameters of recursive_action1()
+	 * relieves register pressure, both in recursive_action1()
+	 * and in every file/dirAction().
+	 */
+	recursive_state_t state;
+	state.flags = flags;
+	state.depth = 0;
+	state.userData = userData;
+	state.fileAction = fileAction ? fileAction : true_action;
+	state.dirAction  =  dirAction ?  dirAction : true_action;
+
+	return recursive_action1(&state, fileName);
+}
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 @@
  *   for each depends, look through our list of full paths and emit if found
  */
 
-static int FAST_FUNC parse_module(const char *fname, struct stat *sb UNUSED_PARAM,
-				void *data, int depth UNUSED_PARAM)
+static int FAST_FUNC parse_module(struct recursive_state *state,
+		const char *fname,
+		struct stat *sb UNUSED_PARAM)
 {
-	module_db *modules = data;
+	module_db *modules = state->userData;
 	char *image, *ptr;
 	module_entry *e;
 
@@ -201,11 +202,12 @@ int depmod_main(int argc UNUSED_PARAM, char **argv)
 	memset(&modules, 0, sizeof(modules));
 	if (*argv) {
 		do {
-			parse_module(*argv, /*sb (unused):*/ NULL, &modules, 0);
+			recursive_action(*argv, 0 /* no ACTION_RECURSE! */,
+				parse_module, NULL, &modules);
 		} while (*++argv);
 	} else {
 		recursive_action(".", ACTION_RECURSE,
-				parse_module, NULL, &modules, 0);
+				parse_module, NULL, &modules);
 	}
 
 	/* 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)
 			ACTION_RECURSE, /* flags */
 			fileAction, /* file action */
 			NULL, /* dir action */
-			name, /* user data */
-			0 /* depth */
+			name /* user data */
 		);
 		dbg1_error_msg("dirscan complete");
 		/* 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)
 	}
 }
 
-static int FAST_FUNC config_file_action(const char *filename,
-					struct stat *statbuf UNUSED_PARAM,
-					void *userdata UNUSED_PARAM,
-					int depth)
+static int FAST_FUNC config_file_action(struct recursive_state *state,
+		const char *filename,
+		struct stat *statbuf UNUSED_PARAM)
 {
 	char *tokens[3];
 	parser_t *p;
@@ -255,7 +254,7 @@ static int FAST_FUNC config_file_action(const char *filename,
 	 * that we shouldn't recurse into /etc/modprobe.d/dir/
 	 * _subdirectories_:
 	 */
-	if (depth > 1)
+	if (state->depth > 1)
 		return SKIP; /* stop recursing */
 //TODO: instead, can use dirAction in recursive_action() to SKIP dirs
 //on depth == 1 level. But that's more code...
@@ -264,7 +263,7 @@ static int FAST_FUNC config_file_action(const char *filename,
 	 * depth==0: read_config("modules.{symbols,alias}") must work,
 	 * "include FILE_NOT_ENDING_IN_CONF" must work too.
 	 */
-	if (depth != 0) {
+	if (state->depth != 0) {
 		if (!is_suffixed_with(base, ".conf"))
 			goto error;
 	}
@@ -329,8 +328,7 @@ static int FAST_FUNC config_file_action(const char *filename,
 static int read_config(const char *path)
 {
 	return recursive_action(path, ACTION_RECURSE | ACTION_QUIET,
-				config_file_action, NULL, NULL,
-				/*depth:*/ 0);
+				config_file_action, NULL, NULL);
 }
 
 static 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)
 	return inode;
 }
 
-static int FAST_FUNC add_to_prg_cache_if_socket(const char *fileName,
-		struct stat *statbuf UNUSED_PARAM,
-		void *pid_slash_progname,
-		int depth UNUSED_PARAM)
+static int FAST_FUNC add_to_prg_cache_if_socket(struct recursive_state *state,
+		const char *fileName,
+		struct stat *statbuf UNUSED_PARAM)
 {
 	char *linkname;
 	long inode;
@@ -284,16 +283,17 @@ static int FAST_FUNC add_to_prg_cache_if_socket(const char *fileName,
 	if (linkname != NULL) {
 		inode = extract_socket_inode(linkname);
 		free(linkname);
-		if (inode >= 0)
-			prg_cache_add(inode, (char *)pid_slash_progname);
+		if (inode >= 0) {
+			char *pid_slash_progname = state->userData;
+			prg_cache_add(inode, pid_slash_progname);
+		}
 	}
 	return TRUE;
 }
 
-static int FAST_FUNC dir_act(const char *fileName,
-		struct stat *statbuf UNUSED_PARAM,
-		void *userData UNUSED_PARAM,
-		int depth)
+static int FAST_FUNC dir_act(struct recursive_state *state,
+		const char *fileName,
+		struct stat *statbuf UNUSED_PARAM)
 {
 	const char *pid;
 	char *pid_slash_progname;
@@ -301,7 +301,7 @@ static int FAST_FUNC dir_act(const char *fileName,
 	char cmdline_buf[512];
 	int n, len;
 
-	if (depth == 0) /* "/proc" itself */
+	if (state->depth == 0) /* "/proc" itself */
 		return TRUE; /* continue looking one level below /proc */
 
 	pid = fileName + sizeof("/proc/")-1; /* point after "/proc/" */
@@ -321,8 +321,8 @@ static int FAST_FUNC dir_act(const char *fileName,
 			ACTION_RECURSE | ACTION_QUIET,
 			add_to_prg_cache_if_socket,
 			NULL,
-			(void *)pid_slash_progname,
-			0);
+			(void *)pid_slash_progname
+	);
 	free(pid_slash_progname);
 
 	if (!n)
@@ -337,7 +337,7 @@ static void prg_cache_load(void)
 
 	prg_cache_loaded = 1;
 	load_ok = recursive_action("/proc", ACTION_RECURSE | ACTION_QUIET,
-				NULL, dir_act, NULL, 0);
+				NULL, dir_act, NULL);
 	if (load_ok)
 		return;
 
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;
 static char *range = NULL;
 static char *specified_context = NULL;
 
-static int FAST_FUNC change_filedir_context(
+static int FAST_FUNC change_filedir_context(struct recursive_state *state UNUSED_PARAM,
 		const char *fname,
-		struct stat *stbuf UNUSED_PARAM,
-		void *userData UNUSED_PARAM,
-		int depth UNUSED_PARAM)
+		struct stat *stbuf UNUSED_PARAM)
 {
 	context_t context = NULL;
 	security_context_t file_context = NULL;
@@ -207,7 +205,7 @@ int chcon_main(int argc UNUSED_PARAM, char **argv)
 					((option_mask32 & OPT_RECURSIVE) ? ACTION_RECURSE : 0),
 					change_filedir_context,
 					change_filedir_context,
-					NULL, 0) != TRUE)
+					NULL) != TRUE)
 			errors = 1;
 	}
 	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)
  * This function is called by recursive_action on each file during
  * the directory traversal.
  */
-static int FAST_FUNC apply_spec(
+static int FAST_FUNC apply_spec(struct recursive_state *state UNUSED_PARAM,
 		const char *file,
-		struct stat *sb,
-		void *userData UNUSED_PARAM,
-		int depth UNUSED_PARAM)
+		struct stat *sb)
 {
 	if (!follow_mounts) {
 		/* setfiles does not process across different mount points */
@@ -535,7 +533,7 @@ static int process_one(char *name)
 				ACTION_RECURSE,
 				apply_spec,
 				apply_spec,
-				NULL, 0) != TRUE
+				NULL) != TRUE
 		) {
 			bb_error_msg("error while labeling %s", name);
 			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 {
 /*
  * PCI_SLOT_NAME PCI_CLASS: PCI_VID:PCI_DID [PCI_SUBSYS_VID:PCI_SUBSYS_DID] [DRIVER]
  */
-static int FAST_FUNC fileAction(
+static int FAST_FUNC fileAction(struct recursive_state *state UNUSED_PARAM,
 		const char *fileName,
-		struct stat *statbuf UNUSED_PARAM,
-		void *userData UNUSED_PARAM,
-		int depth UNUSED_PARAM)
+		struct stat *statbuf UNUSED_PARAM)
 {
 	parser_t *parser;
 	char *tokens[3];
@@ -117,8 +115,7 @@ int lspci_main(int argc UNUSED_PARAM, char **argv)
 			ACTION_RECURSE,
 			fileAction,
 			NULL, /* dirAction */
-			NULL, /* userData */
-			0 /* depth */);
-
+			NULL /* userData */
+	);
 	return EXIT_SUCCESS;
 }
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 @@
 
 #include "libbb.h"
 
-static int FAST_FUNC fileAction(
+static int FAST_FUNC fileAction(struct recursive_state *state UNUSED_PARAM,
 		const char *fileName,
-		struct stat *statbuf UNUSED_PARAM,
-		void *userData UNUSED_PARAM,
-		int depth UNUSED_PARAM)
+		struct stat *statbuf UNUSED_PARAM)
 {
 	parser_t *parser;
 	char *tokens[4];
@@ -80,8 +78,8 @@ int lsusb_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
 			ACTION_RECURSE,
 			fileAction,
 			NULL, /* dirAction */
-			NULL, /* userData */
-			0 /* depth */);
+			NULL /* userData */
+	);
 
 	return EXIT_SUCCESS;
 }
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)
 /* File callback for /sys/ traversal.
  * We act only on "/sys/.../dev" (pseudo)file
  */
-static int FAST_FUNC fileAction(const char *fileName,
-		struct stat *statbuf UNUSED_PARAM,
-		void *userData,
-		int depth UNUSED_PARAM)
+static int FAST_FUNC fileAction(struct recursive_state *state,
+		const char *fileName,
+		struct stat *statbuf UNUSED_PARAM)
 {
 	size_t len = strlen(fileName) - 4; /* can't underflow */
-	char *path = userData;	/* char array[PATH_MAX + SCRATCH_SIZE] */
+	char *path = state->userData;	/* char array[PATH_MAX + SCRATCH_SIZE] */
 	char subsys[PATH_MAX];
 	int res;
 
@@ -888,12 +887,11 @@ static int FAST_FUNC fileAction(const char *fileName,
 }
 
 /* Directory callback for /sys/ traversal */
-static int FAST_FUNC dirAction(const char *fileName UNUSED_PARAM,
-		struct stat *statbuf UNUSED_PARAM,
-		void *userData UNUSED_PARAM,
-		int depth)
+static int FAST_FUNC dirAction(struct recursive_state *state,
+		const char *fileName UNUSED_PARAM,
+		struct stat *statbuf UNUSED_PARAM)
 {
-	return (depth >= MAX_SYSFS_DEPTH ? SKIP : TRUE);
+	return (state->depth >= MAX_SYSFS_DEPTH ? SKIP : TRUE);
 }
 
 /* For the full gory details, see linux/Documentation/firmware_class/README
@@ -1149,7 +1147,7 @@ static void initial_scan(char *temp)
 	/* Create all devices from /sys/dev hierarchy */
 	recursive_action("/sys/dev",
 			 ACTION_RECURSE | ACTION_FOLLOWLINKS,
-			 fileAction, dirAction, temp, 0);
+			 fileAction, dirAction, temp);
 }
 
 #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
  * add a cache entry for this device.
  * If device node does not exist, it will be temporarily created. */
 static int FAST_FUNC
-uuidcache_check_device(const char *device,
-		struct stat *statbuf,
-		void *userData UNUSED_PARAM,
-		int depth UNUSED_PARAM)
+uuidcache_check_device(struct recursive_state *state UNUSED_PARAM,
+		const char *device,
+		struct stat *statbuf)
 {
 	/* note: this check rejects links to devices, among other nodes */
 	if (!S_ISBLK(statbuf->st_mode)
@@ -145,12 +144,13 @@ uuidcache_init(int scan_devices)
 	 * This is unacceptably complex. Let's just scan /dev.
 	 * (Maybe add scanning of /sys/block/XXX/dev for devices
 	 * somehow not having their /dev/XXX entries created?) */
-	if (scan_devices)
+	if (scan_devices) {
 		recursive_action("/dev", ACTION_RECURSE,
 			uuidcache_check_device, /* file_action */
 			NULL, /* dir_action */
-			NULL, /* userData */
-			0 /* depth */);
+			NULL /* userData */
+		);
+	}
 
 	return uuidCache;
 }


More information about the busybox-cvs mailing list