aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMaksym Kryzhanovskyy <xmaks@email.cz>2011-05-23 03:39:48 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2011-05-23 03:39:48 +0200
commiteeed2306fceacf2baea77712b309b4fa40e671b6 (patch)
tree0341610654d6c7329a9541d9c5541a3db77b6df2
parente6df7e261ec430de6f9e9cd9a0eb0d997b553d68 (diff)
downloadbusybox-w32-eeed2306fceacf2baea77712b309b4fa40e671b6.tar.gz
busybox-w32-eeed2306fceacf2baea77712b309b4fa40e671b6.tar.bz2
busybox-w32-eeed2306fceacf2baea77712b309b4fa40e671b6.zip
fuser: code shrink
function old new delta scan_proc_net_or_maps - 427 +427 scan_recursive - 380 +380 search_dev_inode 74 71 -3 add_pid 39 - -39 scan_link 46 - -46 scan_dir_links 76 - -76 scan_pid_maps 222 - -222 fuser_main 871 297 -574 ------------------------------------------------------------------------------ (add/remove: 2/4 grow/shrink: 0/2 up/down: 807/-960) Total: -153 bytes Signed-off-by: Maksym Kryzhanovskyy <xmaks@email.cz> Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r--procps/fuser.c386
1 files changed, 190 insertions, 196 deletions
diff --git a/procps/fuser.c b/procps/fuser.c
index 7837ff883..2a7c3106e 100644
--- a/procps/fuser.c
+++ b/procps/fuser.c
@@ -37,33 +37,18 @@ typedef struct inode_list {
37 dev_t dev; 37 dev_t dev;
38} inode_list; 38} inode_list;
39 39
40typedef struct pid_list {
41 struct pid_list *next;
42 pid_t pid;
43} pid_list;
44
45
46struct globals { 40struct globals {
47 pid_list *pid_list_head; 41 int recursion_depth;
42 pid_t mypid;
48 inode_list *inode_list_head; 43 inode_list *inode_list_head;
44 smallint kill_failed;
45 int killsig;
49} FIX_ALIASING; 46} FIX_ALIASING;
50#define G (*(struct globals*)&bb_common_bufsiz1) 47#define G (*(struct globals*)&bb_common_bufsiz1)
51#define INIT_G() do { } while (0) 48#define INIT_G() do { \
52 49 G.mypid = getpid(); \
53 50 G.killsig = SIGKILL; \
54static void add_pid(const pid_t pid) 51} while (0)
55{
56 pid_list **curr = &G.pid_list_head;
57
58 while (*curr) {
59 if ((*curr)->pid == pid)
60 return;
61 curr = &(*curr)->next;
62 }
63
64 *curr = xzalloc(sizeof(pid_list));
65 (*curr)->pid = pid;
66}
67 52
68static void add_inode(const struct stat *st) 53static void add_inode(const struct stat *st)
69{ 54{
@@ -83,48 +68,7 @@ static void add_inode(const struct stat *st)
83 (*curr)->inode = st->st_ino; 68 (*curr)->inode = st->st_ino;
84} 69}
85 70
86static void scan_proc_net(const char *path, unsigned port) 71static smallint search_dev_inode(const struct stat *st)
87{
88 char line[MAX_LINE + 1];
89 long long uint64_inode;
90 unsigned tmp_port;
91 FILE *f;
92 struct stat st;
93 int fd;
94
95 /* find socket dev */
96 st.st_dev = 0;
97 fd = socket(AF_INET, SOCK_DGRAM, 0);
98 if (fd >= 0) {
99 fstat(fd, &st);
100 close(fd);
101 }
102
103 f = fopen_for_read(path);
104 if (!f)
105 return;
106
107 while (fgets(line, MAX_LINE, f)) {
108 char addr[68];
109 if (sscanf(line, "%*d: %64[0-9A-Fa-f]:%x %*x:%*x %*x %*x:%*x "
110 "%*x:%*x %*x %*d %*d %llu",
111 addr, &tmp_port, &uint64_inode) == 3
112 ) {
113 int len = strlen(addr);
114 if (len == 8 && (option_mask32 & OPT_IP6))
115 continue;
116 if (len > 8 && (option_mask32 & OPT_IP4))
117 continue;
118 if (tmp_port == port) {
119 st.st_ino = uint64_inode;
120 add_inode(&st);
121 }
122 }
123 }
124 fclose(f);
125}
126
127static int search_dev_inode(const struct stat *st)
128{ 72{
129 inode_list *ilist = G.inode_list_head; 73 inode_list *ilist = G.inode_list_head;
130 74
@@ -140,130 +84,202 @@ static int search_dev_inode(const struct stat *st)
140 return 0; 84 return 0;
141} 85}
142 86
143static void scan_pid_maps(const char *fname, pid_t pid) 87enum {
88 PROC_NET = 0,
89 PROC_DIR,
90 PROC_DIR_LINKS,
91 PROC_SUBDIR_LINKS,
92};
93
94static smallint scan_proc_net_or_maps(const char *path, unsigned port)
144{ 95{
145 FILE *file; 96 FILE *f;
146 char line[MAX_LINE + 1]; 97 char line[MAX_LINE + 1], addr[68];
147 int major, minor; 98 int major, minor, r;
148 long long uint64_inode; 99 long long uint64_inode;
149 struct stat st; 100 unsigned tmp_port;
101 smallint retval;
102 struct stat statbuf;
103 const char *fmt;
104 void *fag, *sag;
150 105
151 file = fopen_for_read(fname); 106 f = fopen_for_read(path);
152 if (!file) 107 if (!f)
153 return; 108 return 0;
154 109
155 while (fgets(line, MAX_LINE, file)) { 110 if (G.recursion_depth == PROC_NET) {
156 if (sscanf(line, "%*s %*s %*s %x:%x %llu", &major, &minor, &uint64_inode) != 3) 111 int fd;
157 continue;
158 st.st_ino = uint64_inode;
159 if (major == 0 && minor == 0 && st.st_ino == 0)
160 continue;
161 st.st_dev = makedev(major, minor);
162 if (search_dev_inode(&st))
163 add_pid(pid);
164 }
165 fclose(file);
166}
167 112
168static void scan_link(const char *lname, pid_t pid) 113 /* find socket dev */
169{ 114 statbuf.st_dev = 0;
170 struct stat st; 115 fd = socket(AF_INET, SOCK_DGRAM, 0);
116 if (fd >= 0) {
117 fstat(fd, &statbuf);
118 close(fd);
119 }
171 120
172 if (stat(lname, &st) >= 0) { 121 fmt = "%*d: %64[0-9A-Fa-f]:%x %*x:%*x %*x "
173 if (search_dev_inode(&st)) 122 "%*x:%*x %*x:%*x %*x %*d %*d %llu";
174 add_pid(pid); 123 fag = addr;
124 sag = &tmp_port;
125 } else {
126 fmt = "%*s %*s %*s %x:%x %llu";
127 fag = &major;
128 sag = &minor;
175 } 129 }
176}
177
178static void scan_dir_links(const char *dname, pid_t pid)
179{
180 DIR *d;
181 struct dirent *de;
182 char *lname;
183
184 d = opendir(dname);
185 if (!d)
186 return;
187 130
188 while ((de = readdir(d)) != NULL) { 131 retval = 0;
189 lname = concat_subpath_file(dname, de->d_name); 132 while (fgets(line, MAX_LINE, f)) {
190 if (lname == NULL) 133 r = sscanf(line, fmt, fag, sag, &uint64_inode);
134 if (r != 3)
191 continue; 135 continue;
192 scan_link(lname, pid); 136
193 free(lname); 137 statbuf.st_ino = uint64_inode;
138 if (G.recursion_depth == PROC_NET) {
139 r = strlen(addr);
140 if (r == 8 && (option_mask32 & OPT_IP6))
141 continue;
142 if (r > 8 && (option_mask32 & OPT_IP4))
143 continue;
144 if (tmp_port == port)
145 add_inode(&statbuf);
146 } else {
147 if (major != 0 && minor != 0 && statbuf.st_ino != 0) {
148 statbuf.st_dev = makedev(major, minor);
149 retval = search_dev_inode(&statbuf);
150 if (retval)
151 break;
152 }
153 }
194 } 154 }
195 closedir(d); 155 fclose(f);
156
157 return retval;
196} 158}
197 159
198/* NB: does chdir internally */ 160static smallint scan_recursive(const char *path)
199static void scan_proc_pids(void)
200{ 161{
201 DIR *d; 162 DIR *d;
202 struct dirent *de; 163 struct dirent *d_ent;
203 pid_t pid; 164 smallint stop_scan;
204 165 smallint retval;
205 xchdir("/proc"); 166
206 d = opendir("/proc"); 167 d = opendir(path);
207 if (!d) 168 if (d == NULL)
208 return; 169 return 0;
209 170
210 while ((de = readdir(d)) != NULL) { 171 G.recursion_depth++;
211 pid = (pid_t)bb_strtou(de->d_name, NULL, 10); 172 retval = 0;
212 if (errno) 173 stop_scan = 0;
213 continue; 174 while (!stop_scan && (d_ent = readdir(d)) != NULL) {
214 if (chdir(de->d_name) < 0) 175 struct stat statbuf;
215 continue; 176 pid_t pid;
216 scan_link("cwd", pid); 177 char *subpath;
217 scan_link("exe", pid); 178
218 scan_link("root", pid); 179 subpath = concat_subpath_file(path, d_ent->d_name);
219 180 if (subpath == NULL)
220 scan_dir_links("fd", pid); 181 continue; /* . or .. */
221 scan_dir_links("lib", pid); 182
222 scan_dir_links("mmap", pid); 183 switch (G.recursion_depth) {
184 case PROC_DIR:
185 pid = (pid_t)bb_strtou(d_ent->d_name, NULL, 10);
186 if (errno != 0
187 || pid == G.mypid
188 /* "this PID doesn't use specified FILEs or PORT/PROTO": */
189 || scan_recursive(subpath) == 0
190 ) {
191 break;
192 }
193 if (option_mask32 & OPT_KILL) {
194 if (kill(pid, G.killsig) != 0) {
195 bb_perror_msg("kill pid %s", d_ent->d_name);
196 G.kill_failed = 1;
197 }
198 }
199 if (!(option_mask32 & OPT_SILENT))
200 printf("%s ", d_ent->d_name);
201 retval = 1;
202 break;
223 203
224 scan_pid_maps("maps", pid); 204 case PROC_DIR_LINKS:
225 xchdir("/proc"); 205 switch (
206 index_in_substrings(
207 "cwd" "\0" "exe" "\0"
208 "root" "\0" "fd" "\0"
209 "lib" "\0" "mmap" "\0"
210 "maps" "\0",
211 d_ent->d_name
212 )
213 ) {
214 enum {
215 CWD_LINK,
216 EXE_LINK,
217 ROOT_LINK,
218 FD_DIR_LINKS,
219 LIB_DIR_LINKS,
220 MMAP_DIR_LINKS,
221 MAPS,
222 };
223 case CWD_LINK:
224 case EXE_LINK:
225 case ROOT_LINK:
226 goto scan_link;
227 case FD_DIR_LINKS:
228 case LIB_DIR_LINKS:
229 case MMAP_DIR_LINKS:
230 stop_scan = scan_recursive(subpath);
231 if (stop_scan)
232 retval = stop_scan;
233 break;
234 case MAPS:
235 stop_scan = scan_proc_net_or_maps(subpath, 0);
236 if (stop_scan)
237 retval = stop_scan;
238 default:
239 break;
240 }
241 break;
242 case PROC_SUBDIR_LINKS:
243 scan_link:
244 if (stat(subpath, &statbuf) < 0)
245 break;
246 stop_scan = search_dev_inode(&statbuf);
247 if (stop_scan)
248 retval = stop_scan;
249 default:
250 break;
251 }
252 free(subpath);
226 } 253 }
227 closedir(d); 254 closedir(d);
255 G.recursion_depth--;
256 return retval;
228} 257}
229 258
230int fuser_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 259int fuser_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
231int fuser_main(int argc UNUSED_PARAM, char **argv) 260int fuser_main(int argc UNUSED_PARAM, char **argv)
232{ 261{
233 pid_list *plist;
234 pid_t mypid;
235 char **pp; 262 char **pp;
236 struct stat st; 263
237 unsigned port; 264 INIT_G();
238 int opt; 265
239 int exitcode;
240 int killsig;
241/*
242fuser [OPTIONS] FILE or PORT/PROTO
243Find processes which use FILEs or PORTs
244 -m Find processes which use same fs as FILEs
245 -4 Search only IPv4 space
246 -6 Search only IPv6 space
247 -s Don't display PIDs
248 -k Kill found processes
249 -SIGNAL Signal to send (default: KILL)
250*/
251 /* Handle -SIGNAL. Oh my... */ 266 /* Handle -SIGNAL. Oh my... */
252 killsig = SIGKILL; /* yes, the default is not SIGTERM */
253 pp = argv; 267 pp = argv;
254 while (*++pp) { 268 while (*++pp) {
269 int sig;
255 char *arg = *pp; 270 char *arg = *pp;
271
256 if (arg[0] != '-') 272 if (arg[0] != '-')
257 continue; 273 continue;
258 if (arg[1] == '-' && arg[2] == '\0') /* "--" */ 274 if (arg[1] == '-' && arg[2] == '\0') /* "--" */
259 break; 275 break;
260 if ((arg[1] == '4' || arg[1] == '6') && arg[2] == '\0') 276 if ((arg[1] == '4' || arg[1] == '6') && arg[2] == '\0')
261 continue; /* it's "-4" or "-6" */ 277 continue; /* it's "-4" or "-6" */
262 opt = get_signum(&arg[1]); 278 sig = get_signum(&arg[1]);
263 if (opt < 0) 279 if (sig < 0)
264 continue; 280 continue;
265 /* "-SIGNAL" option found. Remove it and bail out */ 281 /* "-SIGNAL" option found. Remove it and bail out */
266 killsig = opt; 282 G.killsig = sig;
267 do { 283 do {
268 pp[0] = arg = pp[1]; 284 pp[0] = arg = pp[1];
269 pp++; 285 pp++;
@@ -272,57 +288,35 @@ Find processes which use FILEs or PORTs
272 } 288 }
273 289
274 opt_complementary = "-1"; /* at least one param */ 290 opt_complementary = "-1"; /* at least one param */
275 opt = getopt32(argv, OPTION_STRING); 291 getopt32(argv, OPTION_STRING);
276 argv += optind; 292 argv += optind;
277 293
278 pp = argv; 294 pp = argv;
279 while (*pp) { 295 while (*pp) {
280 /* parse net arg */ 296 /* parse net arg */
281 char path[20], tproto[5]; 297 unsigned port;
282 if (sscanf(*pp, "%u/%4s", &port, tproto) != 2) 298 char path[sizeof("/proc/net/TCP6")];
283 goto file; 299
284 sprintf(path, "/proc/net/%s", tproto); 300 strcpy(path, "/proc/net/");
285 if (access(path, R_OK) != 0) { /* PORT/PROTO */ 301 if (sscanf(*pp, "%u/%4s", &port, path + sizeof("/proc/net/")-1) == 2
286 scan_proc_net(path, port); 302 && access(path, R_OK) != 0
287 } else { /* FILE */ 303 ) {
288 file: 304 /* PORT/PROTO */
289 xstat(*pp, &st); 305 scan_proc_net_or_maps(path, port);
290 add_inode(&st); 306 } else {
307 /* FILE */
308 struct stat statbuf;
309 xstat(*pp, &statbuf);
310 add_inode(&statbuf);
291 } 311 }
292 pp++; 312 pp++;
293 } 313 }
294 314
295 scan_proc_pids(); /* changes dir to "/proc" */ 315 if (scan_recursive("/proc")) {
296 316 if (!(option_mask32 & OPT_SILENT))
297 mypid = getpid(); 317 bb_putchar('\n');
298 plist = G.pid_list_head; 318 return G.kill_failed;
299 while (1) {
300 if (!plist)
301 return EXIT_FAILURE;
302 if (plist->pid != mypid)
303 break;
304 plist = plist->next;
305 }
306
307 exitcode = EXIT_SUCCESS;
308 do {
309 if (plist->pid != mypid) {
310 if (opt & OPT_KILL) {
311 if (kill(plist->pid, killsig) != 0) {
312 bb_perror_msg("kill pid %u", (unsigned)plist->pid);
313 exitcode = EXIT_FAILURE;
314 }
315 }
316 if (!(opt & OPT_SILENT)) {
317 printf("%u ", (unsigned)plist->pid);
318 }
319 }
320 plist = plist->next;
321 } while (plist);
322
323 if (!(opt & (OPT_SILENT))) {
324 bb_putchar('\n');
325 } 319 }
326 320
327 return exitcode; 321 return EXIT_FAILURE;
328} 322}