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