Hi Denis,

the first patch is from the previous message. The second is for the fuser 
applet. Please review and consider usage.

Max


------------------------------------------------------------------------------
function                                             old     new   delta
scan_recursive                                         -     591    +591
.rodata                                           146746  146829     +83
search_dev_inode                                      56      53      -3
add_pid                                               51       -     -51
scan_link                                             52       -     -52
scan_dir_links                                       106       -    -106
iostat_main                                         2519    2329    -190
scan_pid_maps                                        230       -    -230
fuser_main                                           907     614    -293
------------------------------------------------------------------------------
(add/remove: 1/4 grow/shrink: 1/3 up/down: 674/-925)         Total: -251 bytes
   text    data     bss     dec     hex filename
 923380    4122    9568  937070   e4c6e busybox_old
 923001    4122    9568  936691   e4af3 busybox_unstripped
diff --git a/procps/iostat.c b/procps/iostat.c
index 06a33eb..6e2af22 100644
--- a/procps/iostat.c
+++ b/procps/iostat.c
@@ -59,18 +59,12 @@ struct stats_dev {
 	unsigned long wr_ops;
 };
 
-/* List of devices entered on the command line */
-struct device_list {
-	char dname[MAX_DEVICE_NAME];
-};
-
 /* Globals. Sort by size and access frequency. */
 struct globals {
 	smallint show_all;
-	unsigned devlist_i;             /* Index to the list of devices */
 	unsigned total_cpus;            /* Number of CPUs */
 	unsigned clk_tck;               /* Number of clock ticks per second */
-	struct device_list *dlist;
+	llist_t *dev_list;              /* List of devices entered on the command line */
 	struct stats_dev *saved_stats_dev;
 	struct tm tmtime;
 };
@@ -289,37 +283,6 @@ static int is_partition(const char *dev)
 	return ((dev[0] - 's') | (dev[1] - 'd') | (dev[2] - 'a')) == 0 && isdigit(dev[3]);
 }
 
-/*
- * Return number of numbers on cmdline.
- * Reasonable values are only 0 (no interval/count specified),
- * 1 (interval specified) and 2 (both interval and count specified)
- */
-static int numbers_on_cmdline(int argc, char *argv[])
-{
-	int sum = 0;
-
-	if (isdigit(argv[argc-1][0]))
-		sum++;
-	if (argc > 2 && isdigit(argv[argc-2][0]))
-		sum++;
-
-	return sum;
-}
-
-static int is_dev_in_dlist(const char *dev)
-{
-	int i;
-
-	/* Go through the device list */
-	for (i = 0; i < G.devlist_i; i++)
-		if (strcmp(G.dlist[i].dname, dev) == 0)
-			/* Found a match */
-			return 1;
-
-	/* No match found */
-	return 0;
-}
-
 static void do_disk_statistics(cputime_t itv)
 {
 	FILE *fp;
@@ -356,7 +319,7 @@ static void do_disk_statistics(cputime_t itv)
 			break;
 		}
 
-		if (!G.devlist_i && !is_partition(sd.dname)) {
+		if (!G.dev_list && !is_partition(sd.dname)) {
 			/* User didn't specify device */
 			if (!G.show_all && !sd.rd_ops && !sd.wr_ops) {
 				/* Don't print unused device */
@@ -367,7 +330,7 @@ static void do_disk_statistics(cputime_t itv)
 			i++;
 		} else {
 			/* Is device in device list? */
-			if (is_dev_in_dlist(sd.dname)) {
+			if (llist_find_str(G.dev_list, sd.dname)) {
 				/* Print current statistics */
 				print_stats_dev_struct(&G.saved_stats_dev[i], &sd, itv);
 				G.saved_stats_dev[i] = sd;
@@ -389,28 +352,6 @@ static void dev_report(cputime_t itv)
 	do_disk_statistics(itv);
 }
 
-static void save_to_devlist(const char *dname)
-{
-	int i;
-	struct device_list *tmp = G.dlist;
-
-	if (strncmp(dname, "/dev/", 5) == 0)
-		/* We'll ignore prefix '/dev/' */
-		dname += 5;
-
-	/* Go through the list */
-	for (i = 0; i < G.devlist_i; i++, tmp++)
-		if (strcmp(tmp->dname, dname) == 0)
-			/* Already in the list */
-			return;
-
-	/* Add device name to the list */
-	strncpy(tmp->dname, dname, MAX_DEVICE_NAME - 1);
-
-	/* Update device list index */
-	G.devlist_i++;
-}
-
 static unsigned get_number_of_devices(void)
 {
 	FILE *fp;
@@ -440,18 +381,6 @@ static unsigned get_number_of_devices(void)
 	return n;
 }
 
-static int number_of_ALL_on_cmdline(char **argv)
-{
-	int alls = 0;
-
-	/* Iterate over cmd line arguments, count "ALL" */
-	while (*argv)
-		if (strcmp(*argv++, "ALL") == 0)
-			alls++;
-
-	return alls;
-}
-
 //usage:#define iostat_trivial_usage
 //usage:       "[-c] [-d] [-t] [-z] [-k|-m] [ALL|BLOCKDEV...] [INTERVAL [COUNT]]"
 //usage:#define iostat_full_usage "\n\n"
@@ -467,7 +396,7 @@ static int number_of_ALL_on_cmdline(char **argv)
 int iostat_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
 int iostat_main(int argc, char **argv)
 {
-	int opt, dev_num;
+	int opt, dev_num = 0;
 	unsigned interval = 0;
 	int count;
 	cputime_t global_uptime[2] = { 0 };
@@ -498,20 +427,26 @@ int iostat_main(int argc, char **argv)
 	argv += optind;
 	argc -= optind;
 
-	dev_num = argc - numbers_on_cmdline(argc, argv);
-	/* We don't want to allocate space for 'ALL' */
-	dev_num -= number_of_ALL_on_cmdline(argv);
-	if (dev_num > 0)
-		/* Make space for device list */
-		G.dlist = xzalloc(sizeof(G.dlist[0]) * dev_num);
-
 	/* Store device names into device list */
 	while (*argv && !isdigit(*argv[0])) {
-		if (strcmp(*argv, "ALL") != 0)
-			/* If not ALL, save device name */
-			save_to_devlist(*argv);
-		else
+		if (strcmp(*argv, "ALL") == 0) {
 			G.show_all = 1;
+		} else {
+			char *dev_name = *argv;
+			if (strncmp(dev_name, "/dev/", 5) == 0) {
+				/* We'll ignore prefix '/dev/' */
+				dev_name += 5;
+			}
+			// maybe not necessary
+			if (strlen(dev_name) > MAX_DEVICE_NAME - 1) {
+				dev_name[MAX_DEVICE_NAME - 1] = '\0';
+			}
+			if (llist_find_str(G.dev_list, dev_name) == NULL) {
+				llist_add_to(&G.dev_list, dev_name);
+				//llist_add_to_end(&G.dev_list, dev_name);
+				dev_num++;
+			}
+		}
 		argv++;
 	}
 
@@ -585,9 +520,9 @@ int iostat_main(int argc, char **argv)
 	bb_putchar('\n');
 
 	if (ENABLE_FEATURE_CLEAN_UP) {
-		free(&G);
-		free(G.dlist);
+		llist_free(G.dev_list, NULL);
 		free(G.saved_stats_dev);
+		free(&G);
 	}
 
 	return EXIT_SUCCESS;
diff --git a/procps/fuser.c b/procps/fuser.c
index a1b93d7..c4fe058 100644
--- a/procps/fuser.c
+++ b/procps/fuser.c
@@ -9,15 +9,30 @@
 
 #include "libbb.h"
 
+#define OPTION_STRING "mks64"
+
 #define MAX_LINE 255
 
-#define OPTION_STRING "mks64"
 enum {
 	OPT_MOUNT  = (1 << 0),
 	OPT_KILL   = (1 << 1),
 	OPT_SILENT = (1 << 2),
 	OPT_IP6    = (1 << 3),
 	OPT_IP4    = (1 << 4),
+
+	SCAN_PROC_DIR = 1,
+	SCAN_PROC_DIR_LINKS,
+	SCAN_PROC_SUBDIR_LINKS,
+
+	CWD_LINK = 0,
+	EXE_LINK,
+	ROOT_LINK,
+
+	FD_DIR_LINKS,
+	LIB_DIR_LINKS,
+	MMAP_DIR_LINKS,
+
+	MAPS,
 };
 
 typedef struct inode_list {
@@ -26,33 +41,17 @@ typedef struct inode_list {
 	dev_t dev;
 } inode_list;
 
-typedef struct pid_list {
-	struct pid_list *next;
-	pid_t pid;
-} pid_list;
-
-
 struct globals {
-	pid_list *pid_list_head;
 	inode_list *inode_list_head;
+	int subpath_depth, killsig;
+	smallint kill_fail;
+	pid_t mypid;
 } FIX_ALIASING;
 #define G (*(struct globals*)&bb_common_bufsiz1)
-#define INIT_G() do { } while (0)
-
-
-static void add_pid(const pid_t pid)
-{
-	pid_list **curr = &G.pid_list_head;
-
-	while (*curr) {
-		if ((*curr)->pid == pid)
-			return;
-		curr = &(*curr)->next;
-	}
-
-	*curr = xzalloc(sizeof(pid_list));
-	(*curr)->pid = pid;
-}
+#define INIT_G() do { \
+	G.killsig = SIGKILL; \
+	G.mypid = getpid(); \
+} while (0)
 
 static void add_inode(const struct stat *st)
 {
@@ -72,6 +71,22 @@ static void add_inode(const struct stat *st)
 	(*curr)->inode = st->st_ino;
 }
 
+static smallint search_dev_inode(const struct stat *st)
+{
+	inode_list *ilist = G.inode_list_head;
+
+	while (ilist) {
+		if (ilist->dev == st->st_dev) {
+			if (option_mask32 & OPT_MOUNT)
+				return 1;
+			if (ilist->inode == st->st_ino)
+				return 1;
+		}
+		ilist = ilist->next;
+	}
+	return 0;
+}
+
 static void scan_proc_net(const char *path, unsigned port)
 {
 	char line[MAX_LINE + 1];
@@ -113,120 +128,125 @@ static void scan_proc_net(const char *path, unsigned port)
 	fclose(f);
 }
 
-static int search_dev_inode(const struct stat *st)
-{
-	inode_list *ilist = G.inode_list_head;
-
-	while (ilist) {
-		if (ilist->dev == st->st_dev) {
-			if (option_mask32 & OPT_MOUNT)
-				return 1;
-			if (ilist->inode == st->st_ino)
-				return 1;
-		}
-		ilist = ilist->next;
-	}
-	return 0;
-}
-
-static void scan_pid_maps(const char *fname, pid_t pid)
-{
-	FILE *file;
-	char line[MAX_LINE + 1];
-	int major, minor;
-	long long uint64_inode;
-	struct stat st;
-
-	file = fopen_for_read(fname);
-	if (!file)
-		return;
-
-	while (fgets(line, MAX_LINE, file)) {
-		if (sscanf(line, "%*s %*s %*s %x:%x %llu", &major, &minor, &uint64_inode) != 3)
-			continue;
-		st.st_ino = uint64_inode;
-		if (major == 0 && minor == 0 && st.st_ino == 0)
-			continue;
-		st.st_dev = makedev(major, minor);
-		if (search_dev_inode(&st))
-			add_pid(pid);
-	}
-	fclose(file);
-}
-
-static void scan_link(const char *lname, pid_t pid)
-{
-	struct stat st;
-
-	if (stat(lname, &st) >= 0) {
-		if (search_dev_inode(&st))
-			add_pid(pid);
-	}
-}
-
-static void scan_dir_links(const char *dname, pid_t pid)
-{
-	DIR *d;
-	struct dirent *de;
-	char *lname;
-
-	d = opendir(dname);
-	if (!d)
-		return;
-
-	while ((de = readdir(d)) != NULL) {
-		lname = concat_subpath_file(dname, de->d_name);
-		if (lname == NULL)
-			continue;
-		scan_link(lname, pid);
-		free(lname);
-	}
-	closedir(d);
-}
-
-/* NB: does chdir internally */
-static void scan_proc_pids(void)
+static smallint scan_recursive(const char *path)
 {
+	smallint retval, stop;
 	DIR *d;
+	FILE *f;
 	struct dirent *de;
+	char *subpath;
 	pid_t pid;
+	struct stat st;
 
-	xchdir("/proc");
-	d = opendir("/proc");
-	if (!d)
-		return;
-
-	while ((de = readdir(d)) != NULL) {
-		pid = (pid_t)bb_strtou(de->d_name, NULL, 10);
-		if (errno)
-			continue;
-		if (chdir(de->d_name) < 0)
-			continue;
-		scan_link("cwd", pid);
-		scan_link("exe", pid);
-		scan_link("root", pid);
-
-		scan_dir_links("fd", pid);
-		scan_dir_links("lib", pid);
-		scan_dir_links("mmap", pid);
-
-		scan_pid_maps("maps", pid);
-		xchdir("/proc");
+	retval = stop = 0;
+	d = opendir(path);
+	if (d != NULL) {
+		G.subpath_depth++;
+		while (!stop && (de = readdir(d)) != NULL) {
+			subpath = concat_subpath_file(path, de->d_name);
+			if (subpath != NULL) {
+				switch (G.subpath_depth) {
+				case SCAN_PROC_DIR:
+					pid = (pid_t)bb_strtou(de->d_name, NULL, 10);
+					if (errno == 0 && pid != G.mypid) {
+						// search the pid directory
+						// >SCAN_PROC_DIR_LINKS
+						if (scan_recursive(subpath)) {
+							if (option_mask32 & OPT_KILL) {
+								if (kill(pid, G.killsig) != 0) {
+									bb_perror_msg("kill pid %s", de->d_name);
+									G.kill_fail = 1;
+								}
+							}
+							if (!(option_mask32 & OPT_SILENT)) {
+								printf("%s ", de->d_name);
+							}
+							retval = 1;
+						}
+					}
+					break;
+				case SCAN_PROC_DIR_LINKS:
+					switch (
+					  index_in_substrings(
+					    "cwd"  "\0" "exe"  "\0"
+					    "root" "\0" "fd"   "\0"
+					    "lib"  "\0" "mmap" "\0"
+					    "maps" "\0", de->d_name
+					  )
+					) {
+					case CWD_LINK:
+					case EXE_LINK:
+					case ROOT_LINK:
+						goto scan_links;
+					case FD_DIR_LINKS:
+					case LIB_DIR_LINKS:
+					case MMAP_DIR_LINKS:
+						// search the `fd', `lib' or `mmap' subdirectories
+						// >SCAN_PROC_SUBDIR_LINKS
+						if (scan_recursive(subpath)) {
+							retval = stop = 1;
+						}
+						break;
+					case MAPS:
+						f = fopen_for_read(subpath);
+						if (f != NULL) {
+							char line[MAX_LINE + 1];
+							int major, minor;
+							long long uint64_inode;
+
+							while (fgets(line, MAX_LINE, f)) {
+								if (sscanf(line, "%*s %*s %*s %x:%x %llu",
+								  &major, &minor, &uint64_inode) != 3
+								) {
+									continue;
+								}
+								st.st_ino = uint64_inode;
+								if (major == 0 && minor == 0 && st.st_ino == 0)
+									continue;
+								st.st_dev = makedev(major, minor);
+								if (search_dev_inode(&st)) {
+									// match found, going up
+									retval = stop = 1;
+									break;
+								}
+							}
+							fclose(f);
+						}
+						break;
+					default:
+						break;
+					}
+					break;
+				case SCAN_PROC_SUBDIR_LINKS:
+  scan_links:
+					if (!(stat(subpath, &st) < 0)) {
+						if (search_dev_inode(&st)) {
+							// match found, going up
+							retval = stop = 1;
+						}
+					}
+					break;
+				default:
+					break;
+				}
+				free(subpath);
+			}
+		}
+		G.subpath_depth--;
+		closedir(d);
 	}
-	closedir(d);
+	return retval;
 }
 
 int fuser_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
 int fuser_main(int argc UNUSED_PARAM, char **argv)
 {
-	pid_list *plist;
-	pid_t mypid;
 	char **pp;
 	struct stat st;
 	unsigned port;
 	int opt;
-	int exitcode;
-	int killsig;
+
+	INIT_G();
 /*
 fuser [OPTIONS] FILE or PORT/PROTO
 Find processes which use FILEs or PORTs
@@ -237,8 +257,6 @@ Find processes which use FILEs or PORTs
         -k      Kill found processes
         -SIGNAL Signal to send (default: KILL)
 */
-	/* Handle -SIGNAL. Oh my... */
-	killsig = SIGKILL; /* yes, the default is not SIGTERM */
 	pp = argv;
 	while (*++pp) {
 		char *arg = *pp;
@@ -252,7 +270,7 @@ Find processes which use FILEs or PORTs
 		if (opt < 0)
 			continue;
 		/* "-SIGNAL" option found. Remove it and bail out */
-		killsig = opt;
+		G.killsig = opt;
 		do {
 			pp[0] = arg = pp[1];
 			pp++;
@@ -281,37 +299,14 @@ Find processes which use FILEs or PORTs
 		pp++;
 	}
 
-	scan_proc_pids(); /* changes dir to "/proc" */
-
-	mypid = getpid();
-	plist = G.pid_list_head;
-	while (1) {
-		if (!plist)
-			return EXIT_FAILURE;
-		if (plist->pid != mypid)
-			break;
-		plist = plist->next;
-	}
-
-	exitcode = EXIT_SUCCESS;
-	do {
-		if (plist->pid != mypid) {
-			if (opt & OPT_KILL) {
-				if (kill(plist->pid, killsig) != 0) {
-					bb_perror_msg("kill pid %u", (unsigned)plist->pid);
-					exitcode = EXIT_FAILURE;
-				}
-			}
-			if (!(opt & OPT_SILENT)) {
-				printf("%u ", (unsigned)plist->pid);
-			}
+	if (scan_recursive("/proc")) {
+		if (!(opt & (OPT_SILENT))) {
+			bb_putchar('\n');
+		}
+		if (!G.kill_fail) {
+			return EXIT_SUCCESS;
 		}
-		plist = plist->next;
-	} while (plist);
-
-	if (!(opt & (OPT_SILENT))) {
-		bb_putchar('\n');
 	}
-
-	return exitcode;
+	return EXIT_FAILURE;
 }
+
_______________________________________________
busybox mailing list
[email protected]
http://lists.busybox.net/mailman/listinfo/busybox

Reply via email to