diff options
| author | Denis Vlasenko <vda.linux@googlemail.com> | 2008-03-17 08:44:58 +0000 |
|---|---|---|
| committer | Denis Vlasenko <vda.linux@googlemail.com> | 2008-03-17 08:44:58 +0000 |
| commit | afc4113ed747330c7f0cc281618bf3e19579810d (patch) | |
| tree | 19f473eec85cd12174b4ba59fb0a807559366c18 | |
| parent | cdf62770af9e8bf7d5bb2344ddef8acb3216cfe2 (diff) | |
| download | busybox-w32-afc4113ed747330c7f0cc281618bf3e19579810d.tar.gz busybox-w32-afc4113ed747330c7f0cc281618bf3e19579810d.tar.bz2 busybox-w32-afc4113ed747330c7f0cc281618bf3e19579810d.zip | |
fuser: bugfixes and shrink. It was assuming that xmalloc zeroes returned area!
function old new delta
scan_dir_links - 106 +106
add_inode - 89 +89
scan_link - 78 +78
file_to_dev_inode - 64 +64
search_dev_inode - 63 +63
add_pid - 39 +39
packed_usage 23948 23928 -20
fuser_add_pid 49 - -49
fuser_file_to_dev_inode 64 - -64
fuser_search_dev_inode 77 - -77
fuser_scan_link 91 - -91
fuser_scan_dir_links 108 - -108
fuser_add_inode 124 - -124
fuser_main 1450 1243 -207
------------------------------------------------------------------------------
(add/remove: 6/6 grow/shrink: 0/2 up/down: 439/-740) Total: -301 bytes
text data bss dec hex filename
798327 658 7428 806413 c4e0d busybox_old
797988 658 7428 806074 c4cba busybox_unstripped
| -rw-r--r-- | include/usage.h | 23 | ||||
| -rw-r--r-- | procps/fuser.c | 400 |
2 files changed, 191 insertions, 232 deletions
diff --git a/include/usage.h b/include/usage.h index fdf96d256..2a49454a1 100644 --- a/include/usage.h +++ b/include/usage.h | |||
| @@ -757,7 +757,7 @@ USE_FEATURE_BRCTL_FANCY("\n" \ | |||
| 757 | #define dos2unix_full_usage \ | 757 | #define dos2unix_full_usage \ |
| 758 | "Convert FILE from dos to unix format.\n" \ | 758 | "Convert FILE from dos to unix format.\n" \ |
| 759 | "When no file is given, use stdin/stdout.\n" \ | 759 | "When no file is given, use stdin/stdout.\n" \ |
| 760 | "\nOptions:\n" \ | 760 | "\nOptions:" \ |
| 761 | "\n -u dos2unix" \ | 761 | "\n -u dos2unix" \ |
| 762 | "\n -d unix2dos" | 762 | "\n -d unix2dos" |
| 763 | 763 | ||
| @@ -1024,7 +1024,7 @@ USE_FEATURE_BRCTL_FANCY("\n" \ | |||
| 1024 | "[-C CYLINDERS] [-H HEADS] [-S SECTORS] [-b SSZ] DISK" | 1024 | "[-C CYLINDERS] [-H HEADS] [-S SECTORS] [-b SSZ] DISK" |
| 1025 | #define fdisk_full_usage \ | 1025 | #define fdisk_full_usage \ |
| 1026 | "Change partition table\n" \ | 1026 | "Change partition table\n" \ |
| 1027 | "\nOptions:\n" \ | 1027 | "\nOptions:" \ |
| 1028 | "\n -u Start and End are in sectors (instead of cylinders)" \ | 1028 | "\n -u Start and End are in sectors (instead of cylinders)" \ |
| 1029 | "\n -l Show partition table for each DISK, then exit" \ | 1029 | "\n -l Show partition table for each DISK, then exit" \ |
| 1030 | USE_FEATURE_FDISK_BLKSIZE( \ | 1030 | USE_FEATURE_FDISK_BLKSIZE( \ |
| @@ -1213,13 +1213,14 @@ USE_FEATURE_BRCTL_FANCY("\n" \ | |||
| 1213 | #define fuser_trivial_usage \ | 1213 | #define fuser_trivial_usage \ |
| 1214 | "[options] FILE or PORT/PROTO" | 1214 | "[options] FILE or PORT/PROTO" |
| 1215 | #define fuser_full_usage \ | 1215 | #define fuser_full_usage \ |
| 1216 | "Options:\n" \ | 1216 | "Find processes which use FILEs or PORTs\n" \ |
| 1217 | " -m Show all processes on the same mounted fs\n" \ | 1217 | "\nOptions:" \ |
| 1218 | " -s Don't print or kill anything\n" \ | 1218 | "\n -m Find processes which use same fs as FILEs" \ |
| 1219 | " -4 Search only IPv4 space\n" \ | 1219 | "\n -4 Search only IPv4 space" \ |
| 1220 | " -6 Search only IPv6 space\n" \ | 1220 | "\n -6 Search only IPv6 space" \ |
| 1221 | " -k Kill all processes that match\n" \ | 1221 | "\n -s Silent: just exit with 0 if any processes are found" \ |
| 1222 | " -SIGNAL Signal to send (default: TERM)" | 1222 | "\n -k Kill found processes (otherwise display PIDs)" \ |
| 1223 | "\n -SIGNAL Signal to send (default: TERM)" | ||
| 1223 | 1224 | ||
| 1224 | #define getenforce_trivial_usage | 1225 | #define getenforce_trivial_usage |
| 1225 | #define getenforce_full_usage | 1226 | #define getenforce_full_usage |
| @@ -4093,7 +4094,7 @@ USE_FEATURE_BRCTL_FANCY("\n" \ | |||
| 4093 | "[flags] FILESYSTEM|DIRECTORY" | 4094 | "[flags] FILESYSTEM|DIRECTORY" |
| 4094 | #define umount_full_usage \ | 4095 | #define umount_full_usage \ |
| 4095 | "Unmount file systems" \ | 4096 | "Unmount file systems" \ |
| 4096 | "\n\nOptions:\n" \ | 4097 | "\n\nOptions:" \ |
| 4097 | USE_FEATURE_UMOUNT_ALL( \ | 4098 | USE_FEATURE_UMOUNT_ALL( \ |
| 4098 | "\n -a Unmount all file systems" USE_FEATURE_MTAB_SUPPORT(" in /etc/mtab")) \ | 4099 | "\n -a Unmount all file systems" USE_FEATURE_MTAB_SUPPORT(" in /etc/mtab")) \ |
| 4099 | USE_FEATURE_MTAB_SUPPORT( \ | 4100 | USE_FEATURE_MTAB_SUPPORT( \ |
| @@ -4168,7 +4169,7 @@ USE_FEATURE_BRCTL_FANCY("\n" \ | |||
| 4168 | #define unix2dos_full_usage \ | 4169 | #define unix2dos_full_usage \ |
| 4169 | "Convert FILE from unix to dos format.\n" \ | 4170 | "Convert FILE from unix to dos format.\n" \ |
| 4170 | "When no file is given, use stdin/stdout.\n" \ | 4171 | "When no file is given, use stdin/stdout.\n" \ |
| 4171 | "\nOptions:\n" \ | 4172 | "\nOptions:" \ |
| 4172 | "\n -u dos2unix" \ | 4173 | "\n -u dos2unix" \ |
| 4173 | "\n -d unix2dos" | 4174 | "\n -d unix2dos" |
| 4174 | 4175 | ||
diff --git a/procps/fuser.c b/procps/fuser.c index 36d634d91..d625b16ab 100644 --- a/procps/fuser.c +++ b/procps/fuser.c | |||
| @@ -10,187 +10,148 @@ | |||
| 10 | 10 | ||
| 11 | #include "libbb.h" | 11 | #include "libbb.h" |
| 12 | 12 | ||
| 13 | #define FUSER_PROC_DIR "/proc" | 13 | #define MAX_LINE 255 |
| 14 | #define FUSER_MAX_LINE 255 | ||
| 15 | 14 | ||
| 16 | #define FUSER_OPT_MOUNT 1 | 15 | #define OPTION_STRING "mks64" |
| 17 | #define FUSER_OPT_KILL 2 | 16 | enum { |
| 18 | #define FUSER_OPT_SILENT 4 | 17 | OPT_MOUNT = (1 << 0), |
| 19 | #define FUSER_OPT_IP6 8 | 18 | OPT_KILL = (1 << 1), |
| 20 | #define FUSER_OPT_IP4 16 | 19 | OPT_SILENT = (1 << 2), |
| 20 | OPT_IP6 = (1 << 3), | ||
| 21 | OPT_IP4 = (1 << 4), | ||
| 22 | }; | ||
| 21 | 23 | ||
| 22 | typedef struct inode_list { | 24 | typedef struct inode_list { |
| 25 | struct inode_list *next; | ||
| 23 | ino_t inode; | 26 | ino_t inode; |
| 24 | dev_t dev; | 27 | dev_t dev; |
| 25 | struct inode_list *next; | ||
| 26 | } inode_list; | 28 | } inode_list; |
| 27 | 29 | ||
| 28 | typedef struct pid_list { | 30 | typedef struct pid_list { |
| 29 | pid_t pid; | ||
| 30 | struct pid_list *next; | 31 | struct pid_list *next; |
| 32 | pid_t pid; | ||
| 31 | } pid_list; | 33 | } pid_list; |
| 32 | 34 | ||
| 33 | static int fuser_option(char *option) | 35 | static dev_t find_socket_dev(void) |
| 34 | { | 36 | { |
| 35 | int opt = 0; | 37 | int fd = socket(AF_INET, SOCK_DGRAM, 0); |
| 36 | 38 | if (fd >= 0) { | |
| 37 | if (!option[0]) | 39 | struct stat buf; |
| 38 | return 0; | 40 | int r = fstat(fd, &buf); |
| 39 | if (option[0] != '-') | 41 | close(fd); |
| 40 | return 0; | 42 | if (r == 0) |
| 41 | ++option; | 43 | return buf.st_dev; |
| 42 | while (*option != '\0') { | ||
| 43 | if (*option == 'm') opt |= FUSER_OPT_MOUNT; | ||
| 44 | else if (*option == 'k') opt |= FUSER_OPT_KILL; | ||
| 45 | else if (*option == 's') opt |= FUSER_OPT_SILENT; | ||
| 46 | else if (*option == '6') opt |= FUSER_OPT_IP6; | ||
| 47 | else if (*option == '4') opt |= FUSER_OPT_IP4; | ||
| 48 | else | ||
| 49 | bb_error_msg_and_die("unsupported option '%c'", *option); | ||
| 50 | ++option; | ||
| 51 | } | 44 | } |
| 52 | return opt; | 45 | return 0; |
| 53 | } | 46 | } |
| 54 | 47 | ||
| 55 | static int fuser_file_to_dev_inode(const char *filename, | 48 | static int file_to_dev_inode(const char *filename, dev_t *dev, ino_t *inode) |
| 56 | dev_t *dev, ino_t *inode) | ||
| 57 | { | 49 | { |
| 58 | struct stat f_stat; | 50 | struct stat f_stat; |
| 59 | if ((stat(filename, &f_stat)) < 0) | 51 | if (stat(filename, &f_stat)) |
| 60 | return 0; | 52 | return 0; |
| 61 | *inode = f_stat.st_ino; | 53 | *inode = f_stat.st_ino; |
| 62 | *dev = f_stat.st_dev; | 54 | *dev = f_stat.st_dev; |
| 63 | return 1; | 55 | return 1; |
| 64 | } | 56 | } |
| 65 | 57 | ||
| 66 | static int fuser_find_socket_dev(dev_t *dev) | 58 | static char *parse_net_arg(const char *arg, unsigned *port) |
| 67 | { | 59 | { |
| 68 | int fd = socket(PF_INET, SOCK_DGRAM,0); | 60 | char path[12], tproto[5]; |
| 69 | struct stat buf; | 61 | |
| 70 | 62 | if (sscanf(arg, "%u/%4s", port, tproto) != 2) | |
| 71 | if (fd >= 0 && (fstat(fd, &buf)) == 0) { | 63 | return NULL; |
| 72 | *dev = buf.st_dev; | 64 | sprintf(path, "net/%s", tproto); |
| 73 | close(fd); | 65 | if (access(path, R_OK) != 0) |
| 74 | return 1; | 66 | return NULL; |
| 75 | } | 67 | return xstrdup(tproto); |
| 76 | return 0; | ||
| 77 | } | 68 | } |
| 78 | 69 | ||
| 79 | static int fuser_parse_net_arg(const char *filename, | 70 | static pid_list *add_pid(pid_list *plist, pid_t pid) |
| 80 | const char **proto, int *port) | ||
| 81 | { | 71 | { |
| 82 | char path[sizeof(FUSER_PROC_DIR)+12], tproto[5]; | 72 | pid_list *curr = plist; |
| 83 | |||
| 84 | if ((sscanf(filename, "%d/%4s", port, tproto)) != 2) | ||
| 85 | return 0; | ||
| 86 | sprintf(path, FUSER_PROC_DIR "/net/%s", tproto); | ||
| 87 | if ((access(path, R_OK)) != 0) | ||
| 88 | return 0; | ||
| 89 | *proto = xstrdup(tproto); | ||
| 90 | return 1; | ||
| 91 | } | ||
| 92 | |||
| 93 | static int fuser_add_pid(pid_list *plist, pid_t pid) | ||
| 94 | { | ||
| 95 | pid_list *curr = NULL, *last = NULL; | ||
| 96 | |||
| 97 | if (plist->pid == 0) | ||
| 98 | plist->pid = pid; | ||
| 99 | curr = plist; | ||
| 100 | while (curr != NULL) { | 73 | while (curr != NULL) { |
| 101 | if (curr->pid == pid) | 74 | if (curr->pid == pid) |
| 102 | return 1; | 75 | return plist; |
| 103 | last = curr; | ||
| 104 | curr = curr->next; | 76 | curr = curr->next; |
| 105 | } | 77 | } |
| 106 | curr = xzalloc(sizeof(pid_list)); | 78 | curr = xmalloc(sizeof(pid_list)); |
| 107 | last->next = curr; | ||
| 108 | curr->pid = pid; | 79 | curr->pid = pid; |
| 109 | /*curr->next = NULL;*/ | 80 | curr->next = plist; |
| 110 | return 1; | 81 | return curr; |
| 111 | } | 82 | } |
| 112 | 83 | ||
| 113 | static int fuser_add_inode(inode_list *ilist, dev_t dev, ino_t inode) | 84 | static inode_list *add_inode(inode_list *ilist, dev_t dev, ino_t inode) |
| 114 | { | 85 | { |
| 115 | inode_list *curr = NULL, *last = NULL; | 86 | inode_list *curr = ilist; |
| 116 | |||
| 117 | if (!ilist->inode && !ilist->dev) { | ||
| 118 | ilist->dev = dev; | ||
| 119 | ilist->inode = inode; | ||
| 120 | } | ||
| 121 | curr = ilist; | ||
| 122 | while (curr != NULL) { | 87 | while (curr != NULL) { |
| 123 | if (curr->inode == inode && curr->dev == dev) | 88 | if (curr->inode == inode && curr->dev == dev) |
| 124 | return 1; | 89 | return ilist; |
| 125 | last = curr; | ||
| 126 | curr = curr->next; | 90 | curr = curr->next; |
| 127 | } | 91 | } |
| 128 | curr = xzalloc(sizeof(inode_list)); | 92 | curr = xmalloc(sizeof(inode_list)); |
| 129 | last->next = curr; | ||
| 130 | curr->dev = dev; | 93 | curr->dev = dev; |
| 131 | curr->inode = inode; | 94 | curr->inode = inode; |
| 132 | /*curr->next = NULL;*/ | 95 | curr->next = ilist; |
| 133 | return 1; | 96 | return curr; |
| 134 | } | 97 | } |
| 135 | 98 | ||
| 136 | static int fuser_scan_proc_net(int opts, const char *proto, | 99 | static inode_list *scan_proc_net(const char *proto, |
| 137 | int port, inode_list *ilist) | 100 | unsigned port, inode_list *ilist) |
| 138 | { | 101 | { |
| 139 | char path[sizeof(FUSER_PROC_DIR)+12], line[FUSER_MAX_LINE+1]; | 102 | char path[12], line[MAX_LINE + 1]; |
| 140 | char addr[128]; | 103 | char addr[128]; |
| 141 | ino_t tmp_inode; | 104 | ino_t tmp_inode; |
| 142 | dev_t tmp_dev; | 105 | dev_t tmp_dev; |
| 143 | long long uint64_inode; | 106 | long long uint64_inode; |
| 144 | int tmp_port; | 107 | unsigned tmp_port; |
| 145 | FILE *f; | 108 | FILE *f; |
| 146 | 109 | ||
| 147 | if (!fuser_find_socket_dev(&tmp_dev)) | 110 | tmp_dev = find_socket_dev(); |
| 148 | tmp_dev = 0; | ||
| 149 | sprintf(path, FUSER_PROC_DIR "/net/%s", proto); | ||
| 150 | 111 | ||
| 112 | sprintf(path, "net/%s", proto); | ||
| 151 | f = fopen(path, "r"); | 113 | f = fopen(path, "r"); |
| 152 | if (!f) | 114 | if (!f) |
| 153 | return 0; | 115 | return ilist; |
| 154 | while (fgets(line, FUSER_MAX_LINE, f)) { | 116 | |
| 117 | while (fgets(line, MAX_LINE, f)) { | ||
| 155 | if (sscanf(line, "%*d: %64[0-9A-Fa-f]:%x %*x:%*x %*x %*x:%*x " | 118 | if (sscanf(line, "%*d: %64[0-9A-Fa-f]:%x %*x:%*x %*x %*x:%*x " |
| 156 | "%*x:%*x %*x %*d %*d %llu", | 119 | "%*x:%*x %*x %*d %*d %llu", |
| 157 | addr, &tmp_port, &uint64_inode) == 3 | 120 | addr, &tmp_port, &uint64_inode) == 3 |
| 158 | ) { | 121 | ) { |
| 159 | if (strlen(addr) == 8 && (opts & FUSER_OPT_IP6)) | 122 | if (strlen(addr) == 8 && (option_mask32 & OPT_IP6)) |
| 160 | continue; | 123 | continue; |
| 161 | if (strlen(addr) > 8 && (opts & FUSER_OPT_IP4)) | 124 | if (strlen(addr) > 8 && (option_mask32 & OPT_IP4)) |
| 162 | continue; | 125 | continue; |
| 163 | if (tmp_port == port) { | 126 | if (tmp_port == port) { |
| 164 | tmp_inode = uint64_inode; | 127 | tmp_inode = uint64_inode; |
| 165 | fuser_add_inode(ilist, tmp_dev, tmp_inode); | 128 | ilist = add_inode(ilist, tmp_dev, tmp_inode); |
| 166 | } | 129 | } |
| 167 | } | 130 | } |
| 168 | } | 131 | } |
| 169 | fclose(f); | 132 | fclose(f); |
| 170 | return 1; | 133 | return ilist; |
| 171 | } | 134 | } |
| 172 | 135 | ||
| 173 | static int fuser_search_dev_inode(int opts, inode_list *ilist, | 136 | static int search_dev_inode(inode_list *ilist, dev_t dev, ino_t inode) |
| 174 | dev_t dev, ino_t inode) | ||
| 175 | { | 137 | { |
| 176 | inode_list *curr; | 138 | while (ilist) { |
| 177 | curr = ilist; | 139 | if (ilist->dev == dev) { |
| 178 | 140 | if (option_mask32 & OPT_MOUNT) | |
| 179 | while (curr) { | 141 | return 1; |
| 180 | if ((opts & FUSER_OPT_MOUNT) && curr->dev == dev) | 142 | if (ilist->inode == inode) |
| 181 | return 1; | 143 | return 1; |
| 182 | if (curr->inode == inode && curr->dev == dev) | 144 | } |
| 183 | return 1; | 145 | ilist = ilist->next; |
| 184 | curr = curr->next; | ||
| 185 | } | 146 | } |
| 186 | return 0; | 147 | return 0; |
| 187 | } | 148 | } |
| 188 | 149 | ||
| 189 | static int fuser_scan_pid_maps(int opts, const char *fname, pid_t pid, | 150 | static pid_list *scan_pid_maps(const char *fname, pid_t pid, |
| 190 | inode_list *ilist, pid_list *plist) | 151 | inode_list *ilist, pid_list *plist) |
| 191 | { | 152 | { |
| 192 | FILE *file; | 153 | FILE *file; |
| 193 | char line[FUSER_MAX_LINE + 1]; | 154 | char line[MAX_LINE + 1]; |
| 194 | int major, minor; | 155 | int major, minor; |
| 195 | ino_t inode; | 156 | ino_t inode; |
| 196 | long long uint64_inode; | 157 | long long uint64_inode; |
| @@ -198,37 +159,36 @@ static int fuser_scan_pid_maps(int opts, const char *fname, pid_t pid, | |||
| 198 | 159 | ||
| 199 | file = fopen(fname, "r"); | 160 | file = fopen(fname, "r"); |
| 200 | if (!file) | 161 | if (!file) |
| 201 | return 0; | 162 | return plist; |
| 202 | while (fgets(line, FUSER_MAX_LINE, file)) { | 163 | while (fgets(line, MAX_LINE, file)) { |
| 203 | if (sscanf(line, "%*s %*s %*s %x:%x %llu", &major, &minor, &uint64_inode) != 3) | 164 | if (sscanf(line, "%*s %*s %*s %x:%x %llu", &major, &minor, &uint64_inode) != 3) |
| 204 | continue; | 165 | continue; |
| 205 | inode = uint64_inode; | 166 | inode = uint64_inode; |
| 206 | if (major == 0 && minor == 0 && inode == 0) | 167 | if (major == 0 && minor == 0 && inode == 0) |
| 207 | continue; | 168 | continue; |
| 208 | dev = makedev(major, minor); | 169 | dev = makedev(major, minor); |
| 209 | if (fuser_search_dev_inode(opts, ilist, dev, inode)) { | 170 | if (search_dev_inode(ilist, dev, inode)) |
| 210 | fuser_add_pid(plist, pid); | 171 | plist = add_pid(plist, pid); |
| 211 | } | ||
| 212 | } | 172 | } |
| 213 | fclose(file); | 173 | fclose(file); |
| 214 | return 1; | 174 | return plist; |
| 215 | } | 175 | } |
| 216 | 176 | ||
| 217 | static int fuser_scan_link(int opts, const char *lname, pid_t pid, | 177 | static pid_list *scan_link(const char *lname, pid_t pid, |
| 218 | inode_list *ilist, pid_list *plist) | 178 | inode_list *ilist, pid_list *plist) |
| 219 | { | 179 | { |
| 220 | ino_t inode; | 180 | ino_t inode; |
| 221 | dev_t dev; | 181 | dev_t dev; |
| 222 | 182 | ||
| 223 | if (!fuser_file_to_dev_inode(lname, &dev, &inode)) | 183 | if (!file_to_dev_inode(lname, &dev, &inode)) |
| 224 | return 0; | 184 | return plist; |
| 225 | if (fuser_search_dev_inode(opts, ilist, dev, inode)) | 185 | if (search_dev_inode(ilist, dev, inode)) |
| 226 | fuser_add_pid(plist, pid); | 186 | plist = add_pid(plist, pid); |
| 227 | return 1; | 187 | return plist; |
| 228 | } | 188 | } |
| 229 | 189 | ||
| 230 | static int fuser_scan_dir_links(int opts, const char *dname, pid_t pid, | 190 | static pid_list *scan_dir_links(const char *dname, pid_t pid, |
| 231 | inode_list *ilist, pid_list *plist) | 191 | inode_list *ilist, pid_list *plist) |
| 232 | { | 192 | { |
| 233 | DIR *d; | 193 | DIR *d; |
| 234 | struct dirent *de; | 194 | struct dirent *de; |
| @@ -236,82 +196,72 @@ static int fuser_scan_dir_links(int opts, const char *dname, pid_t pid, | |||
| 236 | 196 | ||
| 237 | d = opendir(dname); | 197 | d = opendir(dname); |
| 238 | if (!d) | 198 | if (!d) |
| 239 | return 0; | 199 | return plist; |
| 240 | while ((de = readdir(d)) != NULL) { | 200 | while ((de = readdir(d)) != NULL) { |
| 241 | lname = concat_subpath_file(dname, de->d_name); | 201 | lname = concat_subpath_file(dname, de->d_name); |
| 242 | if (lname == NULL) | 202 | if (lname == NULL) |
| 243 | continue; | 203 | continue; |
| 244 | fuser_scan_link(opts, lname, pid, ilist, plist); | 204 | plist = scan_link(lname, pid, ilist, plist); |
| 245 | free(lname); | 205 | free(lname); |
| 246 | } | 206 | } |
| 247 | closedir(d); | 207 | closedir(d); |
| 248 | return 1; | 208 | return plist; |
| 249 | } | 209 | } |
| 250 | 210 | ||
| 251 | static int fuser_scan_proc_pids(int opts, inode_list *ilist, pid_list *plist) | 211 | static pid_list *scan_proc_pids(inode_list *ilist) |
| 252 | { | 212 | { |
| 253 | DIR *d; | 213 | DIR *d; |
| 254 | struct dirent *de; | 214 | struct dirent *de; |
| 255 | pid_t pid; | 215 | pid_t pid; |
| 256 | char *dname; | 216 | pid_list *plist; |
| 257 | 217 | ||
| 258 | d = opendir(FUSER_PROC_DIR); | 218 | d = opendir("."); |
| 259 | if (!d) | 219 | if (!d) |
| 260 | return 0; | 220 | return NULL; |
| 221 | |||
| 222 | plist = NULL; | ||
| 261 | while ((de = readdir(d)) != NULL) { | 223 | while ((de = readdir(d)) != NULL) { |
| 262 | pid = (pid_t)atoi(de->d_name); | 224 | pid = (pid_t)bb_strtou(de->d_name, NULL, 10); |
| 263 | if (!pid) | 225 | if (errno) |
| 264 | continue; | 226 | continue; |
| 265 | dname = concat_subpath_file(FUSER_PROC_DIR, de->d_name); | 227 | if (chdir(de->d_name) < 0) |
| 266 | if (chdir(dname) < 0) { | ||
| 267 | free(dname); | ||
| 268 | continue; | 228 | continue; |
| 269 | } | 229 | plist = scan_link("cwd", pid, ilist, plist); |
| 270 | free(dname); | 230 | plist = scan_link("exe", pid, ilist, plist); |
| 271 | fuser_scan_link(opts, "cwd", pid, ilist, plist); | 231 | plist = scan_link("root", pid, ilist, plist); |
| 272 | fuser_scan_link(opts, "exe", pid, ilist, plist); | 232 | plist = scan_dir_links("fd", pid, ilist, plist); |
| 273 | fuser_scan_link(opts, "root", pid, ilist, plist); | 233 | plist = scan_dir_links("lib", pid, ilist, plist); |
| 274 | fuser_scan_dir_links(opts, "fd", pid, ilist, plist); | 234 | plist = scan_dir_links("mmap", pid, ilist, plist); |
| 275 | fuser_scan_dir_links(opts, "lib", pid, ilist, plist); | 235 | plist = scan_pid_maps("maps", pid, ilist, plist); |
| 276 | fuser_scan_dir_links(opts, "mmap", pid, ilist, plist); | 236 | xchdir("/proc"); |
| 277 | fuser_scan_pid_maps(opts, "maps", pid, ilist, plist); | ||
| 278 | chdir(".."); | ||
| 279 | } | 237 | } |
| 280 | closedir(d); | 238 | closedir(d); |
| 281 | return 1; | 239 | return plist; |
| 282 | } | 240 | } |
| 283 | 241 | ||
| 284 | static int fuser_print_pid_list(pid_list *plist) | 242 | static int print_pid_list(pid_list *plist) |
| 285 | { | 243 | { |
| 286 | pid_list *curr = plist; | 244 | while (plist != NULL) { |
| 287 | 245 | printf("%u ", (unsigned)plist->pid); | |
| 288 | if (plist == NULL) | 246 | plist = plist->next; |
| 289 | return 0; | ||
| 290 | while (curr != NULL) { | ||
| 291 | if (curr->pid > 0) | ||
| 292 | printf("%d ", curr->pid); | ||
| 293 | curr = curr->next; | ||
| 294 | } | 247 | } |
| 295 | bb_putchar('\n'); | 248 | bb_putchar('\n'); |
| 296 | return 1; | 249 | return 1; |
| 297 | } | 250 | } |
| 298 | 251 | ||
| 299 | static int fuser_kill_pid_list(pid_list *plist, int sig) | 252 | static int kill_pid_list(pid_list *plist, int sig) |
| 300 | { | 253 | { |
| 301 | pid_list *curr = plist; | ||
| 302 | pid_t mypid = getpid(); | 254 | pid_t mypid = getpid(); |
| 303 | int success = 1; | 255 | int success = 1; |
| 304 | 256 | ||
| 305 | if (plist == NULL) | 257 | while (plist != NULL) { |
| 306 | return 0; | 258 | if (plist->pid != mypid) { |
| 307 | while (curr != NULL) { | 259 | if (kill(plist->pid, sig) != 0) { |
| 308 | if (curr->pid > 0 && curr->pid != mypid) { | 260 | bb_perror_msg("kill pid %u", (unsigned)plist->pid); |
| 309 | if (kill(curr->pid, sig) != 0) { | ||
| 310 | bb_perror_msg("kill pid '%d'", curr->pid); | ||
| 311 | success = 0; | 261 | success = 0; |
| 312 | } | 262 | } |
| 313 | } | 263 | } |
| 314 | curr = curr->next; | 264 | plist = plist->next; |
| 315 | } | 265 | } |
| 316 | return success; | 266 | return success; |
| 317 | } | 267 | } |
| @@ -319,69 +269,77 @@ static int fuser_kill_pid_list(pid_list *plist, int sig) | |||
| 319 | int fuser_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 269 | int fuser_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
| 320 | int fuser_main(int argc, char **argv) | 270 | int fuser_main(int argc, char **argv) |
| 321 | { | 271 | { |
| 322 | /*static -- huh???*/ int opt = 0; /* FUSER_OPT_ */ | 272 | pid_list *plist; |
| 323 | 273 | inode_list *ilist; | |
| 324 | int port, i, optn; | 274 | char **pp; |
| 325 | int* fni; /* file name indexes of argv */ | ||
| 326 | int fnic = 0; /* file name index count */ | ||
| 327 | const char *proto; | ||
| 328 | dev_t dev; | 275 | dev_t dev; |
| 329 | ino_t inode; | 276 | ino_t inode; |
| 330 | pid_list *pids; | 277 | unsigned port; |
| 331 | inode_list *inodes; | 278 | int opt; |
| 332 | int killsig = SIGTERM; | 279 | int success; |
| 333 | int success = 1; | 280 | int killsig; |
| 334 | 281 | /* | |
| 335 | if (argc < 2) | 282 | fuser [options] FILEs or PORT/PROTOs |
| 336 | bb_show_usage(); | 283 | Find processes which use FILEs or PORTs |
| 337 | 284 | -m Find processes which use same fs as FILEs | |
| 338 | fni = xmalloc(sizeof(int)); | 285 | -4 Search only IPv4 space |
| 339 | for (i = 1; i < argc; i++) { | 286 | -6 Search only IPv6 space |
| 340 | optn = fuser_option(argv[i]); | 287 | -s Silent: just exit with 0 if any processes are found |
| 341 | if (optn) | 288 | -k Kill found processes (otherwise display PIDs) |
| 342 | opt |= optn; | 289 | -SIGNAL Signal to send (default: TERM) |
| 343 | else if (argv[i][0] == '-') { | 290 | */ |
| 344 | killsig = get_signum(argv[i]+1); | 291 | /* Handle -SIGNAL. Oh my... */ |
| 345 | if (killsig < 0) | 292 | killsig = SIGTERM; |
| 346 | killsig = SIGTERM; | 293 | pp = argv; |
| 347 | } else { | 294 | while (*++pp) { |
| 348 | fni = xrealloc(fni, sizeof(int) * (fnic+2)); | 295 | char *arg = *pp; |
| 349 | fni[fnic++] = i; | 296 | if (arg[0] != '-') |
| 350 | } | 297 | continue; |
| 298 | if (arg[1] == '-' && arg[2] == '\0') /* "--" */ | ||
| 299 | break; | ||
| 300 | if ((arg[1] == '4' || arg[1] == '6') && arg[2] == '\0') | ||
| 301 | continue; /* it's "-4" or "-6" */ | ||
| 302 | opt = get_signum(&arg[1]); | ||
| 303 | if (opt < 0) | ||
| 304 | continue; | ||
| 305 | /* "-SIGNAL" option found. Remove it and bail out */ | ||
| 306 | killsig = opt; | ||
| 307 | do { | ||
| 308 | pp[0] = arg = pp[1]; | ||
| 309 | pp++; | ||
| 310 | } while (arg); | ||
| 311 | break; | ||
| 351 | } | 312 | } |
| 352 | 313 | ||
| 353 | if (!fnic) | 314 | opt = getopt32(argv, OPTION_STRING); |
| 354 | return 1; | 315 | argv += optind; |
| 355 | 316 | ||
| 356 | inodes = xmalloc(sizeof(inode_list)); | 317 | xchdir("/proc"); |
| 357 | for (i = 0; i < fnic; i++) { | 318 | |
| 358 | if (fuser_parse_net_arg(argv[fni[i]], &proto, &port)) { | 319 | ilist = NULL; |
| 359 | fuser_scan_proc_net(opt, proto, port, inodes); | 320 | pp = argv; |
| 360 | } else { | 321 | while (*pp) { |
| 361 | if (!fuser_file_to_dev_inode(argv[fni[i]], &dev, &inode)) { | 322 | char *proto = parse_net_arg(*pp, &port); |
| 362 | if (ENABLE_FEATURE_CLEAN_UP) | 323 | if (proto) { /* PORT/PROTO */ |
| 363 | free(inodes); | 324 | ilist = scan_proc_net(proto, port, ilist); |
| 364 | bb_perror_msg_and_die("cannot open '%s'", argv[fni[i]]); | 325 | free(proto); |
| 365 | } | 326 | } else { /* FILE */ |
| 366 | fuser_add_inode(inodes, dev, inode); | 327 | if (!file_to_dev_inode(*pp, &dev, &inode)) |
| 328 | bb_perror_msg_and_die("can't open %s", *pp); | ||
| 329 | ilist = add_inode(ilist, dev, inode); | ||
| 367 | } | 330 | } |
| 331 | pp++; | ||
| 368 | } | 332 | } |
| 369 | pids = xmalloc(sizeof(pid_list)); | 333 | |
| 370 | success = fuser_scan_proc_pids(opt, inodes, pids); | 334 | plist = scan_proc_pids(ilist); |
| 371 | /* if the first pid in the list is 0, none have been found */ | 335 | |
| 372 | if (pids->pid == 0) | 336 | if (!plist) |
| 373 | success = 0; | 337 | return EXIT_FAILURE; |
| 374 | if (success) { | 338 | success = 1; |
| 375 | if (opt & FUSER_OPT_KILL) { | 339 | if (opt & OPT_KILL) { |
| 376 | success = fuser_kill_pid_list(pids, killsig); | 340 | success = kill_pid_list(plist, killsig); |
| 377 | } else if (!(opt & FUSER_OPT_SILENT)) { | 341 | } else if (!(opt & OPT_SILENT)) { |
| 378 | success = fuser_print_pid_list(pids); | 342 | success = print_pid_list(plist); |
| 379 | } | ||
| 380 | } | ||
| 381 | if (ENABLE_FEATURE_CLEAN_UP) { | ||
| 382 | free(pids); | ||
| 383 | free(inodes); | ||
| 384 | } | 343 | } |
| 385 | /* return 0 on (success == 1) 1 otherwise */ | 344 | return (success != 1); /* 0 == success */ |
| 386 | return (success != 1); | ||
| 387 | } | 345 | } |
