Changeset 2725 in MondoRescue for branches/2.2.9/mindi-busybox/procps/fuser.c


Ignore:
Timestamp:
Feb 25, 2011, 9:26:54 PM (13 years ago)
Author:
Bruno Cornec
Message:
  • Update mindi-busybox to 1.18.3 to avoid problems with the tar command which is now failing on recent versions with busybox 1.7.3
File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/2.2.9/mindi-busybox/procps/fuser.c

    r1765 r2725  
    55 * Copyright 2004 Tony J. White
    66 *
    7  * May be distributed under the conditions of the
    8  * GNU Library General Public License
     7 * Licensed under GPLv2, see file LICENSE in this source tree.
    98 */
    109
    1110#include "libbb.h"
    1211
    13 #define FUSER_PROC_DIR "/proc"
    14 #define FUSER_MAX_LINE 255
    15 
    16 #define FUSER_OPT_MOUNT  1
    17 #define FUSER_OPT_KILL   2
    18 #define FUSER_OPT_SILENT 4
    19 #define FUSER_OPT_IP6    8
    20 #define FUSER_OPT_IP4    16
     12#define MAX_LINE 255
     13
     14#define OPTION_STRING "mks64"
     15enum {
     16    OPT_MOUNT  = (1 << 0),
     17    OPT_KILL   = (1 << 1),
     18    OPT_SILENT = (1 << 2),
     19    OPT_IP6    = (1 << 3),
     20    OPT_IP4    = (1 << 4),
     21};
    2122
    2223typedef struct inode_list {
     24    struct inode_list *next;
    2325    ino_t inode;
    2426    dev_t dev;
    25     struct inode_list *next;
    2627} inode_list;
    2728
    2829typedef struct pid_list {
     30    struct pid_list *next;
    2931    pid_t pid;
    30     struct pid_list *next;
    3132} pid_list;
    3233
    33 static int fuser_option(char *option)
    34 {
    35     int opt = 0;
    36 
    37     if (!option[0])
    38         return 0;
    39     if (option[0] != '-')
    40         return 0;
    41     ++option;
    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     }
    52     return opt;
    53 }
    54 
    55 static int fuser_file_to_dev_inode(const char *filename,
    56      dev_t *dev, ino_t *inode)
    57 {
    58     struct stat f_stat;
    59     if ((stat(filename, &f_stat)) < 0)
    60         return 0;
    61     *inode = f_stat.st_ino;
    62     *dev = f_stat.st_dev;
    63     return 1;
    64 }
    65 
    66 static int fuser_find_socket_dev(dev_t *dev)
    67 {
    68     int fd = socket(PF_INET, SOCK_DGRAM,0);
    69     struct stat buf;
    70 
    71     if (fd >= 0 && (fstat(fd, &buf)) == 0) {
    72         *dev = buf.st_dev;
     34
     35struct globals {
     36    pid_list *pid_list_head;
     37    inode_list *inode_list_head;
     38};
     39#define G (*(struct globals*)&bb_common_bufsiz1)
     40#define INIT_G() do { } while (0)
     41
     42
     43static void add_pid(const pid_t pid)
     44{
     45    pid_list **curr = &G.pid_list_head;
     46
     47    while (*curr) {
     48        if ((*curr)->pid == pid)
     49            return;
     50        curr = &(*curr)->next;
     51    }
     52
     53    *curr = xzalloc(sizeof(pid_list));
     54    (*curr)->pid = pid;
     55}
     56
     57static void add_inode(const struct stat *st)
     58{
     59    inode_list **curr = &G.inode_list_head;
     60
     61    while (*curr) {
     62        if ((*curr)->dev == st->st_dev
     63         && (*curr)->inode == st->st_ino
     64        ) {
     65            return;
     66        }
     67        curr = &(*curr)->next;
     68    }
     69
     70    *curr = xzalloc(sizeof(inode_list));
     71    (*curr)->dev = st->st_dev;
     72    (*curr)->inode = st->st_ino;
     73}
     74
     75static void scan_proc_net(const char *path, unsigned port)
     76{
     77    char line[MAX_LINE + 1];
     78    long long uint64_inode;
     79    unsigned tmp_port;
     80    FILE *f;
     81    struct stat st;
     82    int fd;
     83
     84    /* find socket dev */
     85    st.st_dev = 0;
     86    fd = socket(AF_INET, SOCK_DGRAM, 0);
     87    if (fd >= 0) {
     88        fstat(fd, &st);
    7389        close(fd);
    74         return 1;
    75     }
    76     return 0;
    77 }
    78 
    79 static int fuser_parse_net_arg(const char *filename,
    80     const char **proto, int *port)
    81 {
    82     char path[sizeof(FUSER_PROC_DIR)+12], tproto[5];
    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) {
    101         if (curr->pid == pid)
    102             return 1;
    103         last = curr;
    104         curr = curr->next;
    105     }
    106     curr = xzalloc(sizeof(pid_list));
    107     last->next = curr;
    108     curr->pid = pid;
    109     /*curr->next = NULL;*/
    110     return 1;
    111 }
    112 
    113 static int fuser_add_inode(inode_list *ilist, dev_t dev, ino_t inode)
    114 {
    115     inode_list *curr = NULL, *last = NULL;
    116 
    117     if (!ilist->inode && !ilist->dev) {
    118         ilist->dev = dev;
    119         ilist->inode = inode;
    120     }
    121     curr = ilist;
    122     while (curr != NULL) {
    123         if (curr->inode == inode && curr->dev == dev)
    124             return 1;
    125         last = curr;
    126         curr = curr->next;
    127     }
    128     curr = xzalloc(sizeof(inode_list));
    129     last->next = curr;
    130     curr->dev = dev;
    131     curr->inode = inode;
    132     /*curr->next = NULL;*/
    133     return 1;
    134 }
    135 
    136 static int fuser_scan_proc_net(int opts, const char *proto,
    137     int port, inode_list *ilist)
    138 {
    139     char path[sizeof(FUSER_PROC_DIR)+12], line[FUSER_MAX_LINE+1];
    140     char addr[128];
    141     ino_t tmp_inode;
    142     dev_t tmp_dev;
    143     long long uint64_inode;
    144     int tmp_port;
    145     FILE *f;
    146 
    147     if (!fuser_find_socket_dev(&tmp_dev))
    148         tmp_dev = 0;
    149     sprintf(path, FUSER_PROC_DIR "/net/%s", proto);
    150 
    151     f = fopen(path, "r");
     90    }
     91
     92    f = fopen_for_read(path);
    15293    if (!f)
    153         return 0;
    154     while (fgets(line, FUSER_MAX_LINE, f)) {
     94        return;
     95
     96    while (fgets(line, MAX_LINE, f)) {
     97        char addr[68];
    15598        if (sscanf(line, "%*d: %64[0-9A-Fa-f]:%x %*x:%*x %*x %*x:%*x "
    15699                "%*x:%*x %*x %*d %*d %llu",
    157100                addr, &tmp_port, &uint64_inode) == 3
    158101        ) {
    159             if (strlen(addr) == 8 && (opts & FUSER_OPT_IP6))
     102            int len = strlen(addr);
     103            if (len == 8 && (option_mask32 & OPT_IP6))
    160104                continue;
    161             if (strlen(addr) > 8 && (opts & FUSER_OPT_IP4))
     105            if (len > 8 && (option_mask32 & OPT_IP4))
    162106                continue;
    163107            if (tmp_port == port) {
    164                 tmp_inode = uint64_inode;
    165                 fuser_add_inode(ilist, tmp_dev, tmp_inode);
     108                st.st_ino = uint64_inode;
     109                add_inode(&st);
    166110            }
    167111        }
    168112    }
    169113    fclose(f);
    170     return 1;
    171 }
    172 
    173 static int fuser_search_dev_inode(int opts, inode_list *ilist,
    174     dev_t dev, ino_t inode)
    175 {
    176     inode_list *curr;
    177     curr = ilist;
    178 
    179     while (curr) {
    180         if ((opts & FUSER_OPT_MOUNT) && curr->dev == dev)
    181             return 1;
    182         if (curr->inode == inode && curr->dev == dev)
    183             return 1;
    184         curr = curr->next;
     114}
     115
     116static int search_dev_inode(const struct stat *st)
     117{
     118    inode_list *ilist = G.inode_list_head;
     119
     120    while (ilist) {
     121        if (ilist->dev == st->st_dev) {
     122            if (option_mask32 & OPT_MOUNT)
     123                return 1;
     124            if (ilist->inode == st->st_ino)
     125                return 1;
     126        }
     127        ilist = ilist->next;
    185128    }
    186129    return 0;
    187130}
    188131
    189 static int fuser_scan_pid_maps(int opts, const char *fname, pid_t pid,
    190     inode_list *ilist, pid_list *plist)
     132static void scan_pid_maps(const char *fname, pid_t pid)
    191133{
    192134    FILE *file;
    193     char line[FUSER_MAX_LINE + 1];
     135    char line[MAX_LINE + 1];
    194136    int major, minor;
    195     ino_t inode;
    196137    long long uint64_inode;
    197     dev_t dev;
    198 
    199     file = fopen(fname, "r");
     138    struct stat st;
     139
     140    file = fopen_for_read(fname);
    200141    if (!file)
    201         return 0;
    202     while (fgets(line, FUSER_MAX_LINE, file)) {
     142        return;
     143
     144    while (fgets(line, MAX_LINE, file)) {
    203145        if (sscanf(line, "%*s %*s %*s %x:%x %llu", &major, &minor, &uint64_inode) != 3)
    204146            continue;
    205         inode = uint64_inode;
    206         if (major == 0 && minor == 0 && inode == 0)
    207             continue;
    208         dev = makedev(major, minor);
    209         if (fuser_search_dev_inode(opts, ilist, dev, inode)) {
    210             fuser_add_pid(plist, pid);
    211         }
     147        st.st_ino = uint64_inode;
     148        if (major == 0 && minor == 0 && st.st_ino == 0)
     149            continue;
     150        st.st_dev = makedev(major, minor);
     151        if (search_dev_inode(&st))
     152            add_pid(pid);
    212153    }
    213154    fclose(file);
    214     return 1;
    215 }
    216 
    217 static int fuser_scan_link(int opts, const char *lname, pid_t pid,
    218     inode_list *ilist, pid_list *plist)
    219 {
    220     ino_t inode;
    221     dev_t dev;
    222 
    223     if (!fuser_file_to_dev_inode(lname, &dev, &inode))
    224         return 0;
    225     if (fuser_search_dev_inode(opts, ilist, dev, inode))
    226         fuser_add_pid(plist, pid);
    227     return 1;
    228 }
    229 
    230 static int fuser_scan_dir_links(int opts, const char *dname, pid_t pid,
    231     inode_list *ilist, pid_list *plist)
     155}
     156
     157static void scan_link(const char *lname, pid_t pid)
     158{
     159    struct stat st;
     160
     161    if (stat(lname, &st) >= 0) {
     162        if (search_dev_inode(&st))
     163            add_pid(pid);
     164    }
     165}
     166
     167static void scan_dir_links(const char *dname, pid_t pid)
    232168{
    233169    DIR *d;
     
    237173    d = opendir(dname);
    238174    if (!d)
    239         return 0;
     175        return;
     176
    240177    while ((de = readdir(d)) != NULL) {
    241178        lname = concat_subpath_file(dname, de->d_name);
    242179        if (lname == NULL)
    243180            continue;
    244         fuser_scan_link(opts, lname, pid, ilist, plist);
     181        scan_link(lname, pid);
    245182        free(lname);
    246183    }
    247184    closedir(d);
    248     return 1;
    249 }
    250 
    251 static int fuser_scan_proc_pids(int opts, inode_list *ilist, pid_list *plist)
     185}
     186
     187/* NB: does chdir internally */
     188static void scan_proc_pids(void)
    252189{
    253190    DIR *d;
    254191    struct dirent *de;
    255192    pid_t pid;
    256     char *dname;
    257 
    258     d = opendir(FUSER_PROC_DIR);
     193
     194    xchdir("/proc");
     195    d = opendir("/proc");
    259196    if (!d)
    260         return 0;
     197        return;
     198
    261199    while ((de = readdir(d)) != NULL) {
    262         pid = (pid_t)atoi(de->d_name);
    263         if (!pid)
    264             continue;
    265         dname = concat_subpath_file(FUSER_PROC_DIR, de->d_name);
    266         if (chdir(dname) < 0) {
    267             free(dname);
    268             continue;
    269         }
    270         free(dname);
    271         fuser_scan_link(opts, "cwd", pid, ilist, plist);
    272         fuser_scan_link(opts, "exe", pid, ilist, plist);
    273         fuser_scan_link(opts, "root", pid, ilist, plist);
    274         fuser_scan_dir_links(opts, "fd", pid, ilist, plist);
    275         fuser_scan_dir_links(opts, "lib", pid, ilist, plist);
    276         fuser_scan_dir_links(opts, "mmap", pid, ilist, plist);
    277         fuser_scan_pid_maps(opts, "maps", pid, ilist, plist);
    278         chdir("..");
     200        pid = (pid_t)bb_strtou(de->d_name, NULL, 10);
     201        if (errno)
     202            continue;
     203        if (chdir(de->d_name) < 0)
     204            continue;
     205        scan_link("cwd", pid);
     206        scan_link("exe", pid);
     207        scan_link("root", pid);
     208
     209        scan_dir_links("fd", pid);
     210        scan_dir_links("lib", pid);
     211        scan_dir_links("mmap", pid);
     212
     213        scan_pid_maps("maps", pid);
     214        xchdir("/proc");
    279215    }
    280216    closedir(d);
    281     return 1;
    282 }
    283 
    284 static int fuser_print_pid_list(pid_list *plist)
    285 {
    286     pid_list *curr = plist;
    287 
    288     if (plist == NULL)
    289         return 0;
    290     while (curr != NULL) {
    291         if (curr->pid > 0)
    292             printf("%d ", curr->pid);
    293         curr = curr->next;
    294     }
    295     puts("");
    296     return 1;
    297 }
    298 
    299 static int fuser_kill_pid_list(pid_list *plist, int sig)
    300 {
    301     pid_list *curr = plist;
    302     pid_t mypid = getpid();
    303     int success = 1;
    304 
    305     if (plist == NULL)
    306         return 0;
    307     while (curr != NULL) {
    308         if (curr->pid > 0 && curr->pid != mypid) {
    309             if (kill(curr->pid, sig) != 0) {
    310                 bb_perror_msg("kill pid '%d'", curr->pid);
    311                 success = 0;
     217}
     218
     219int fuser_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
     220int fuser_main(int argc UNUSED_PARAM, char **argv)
     221{
     222    pid_list *plist;
     223    pid_t mypid;
     224    char **pp;
     225    struct stat st;
     226    unsigned port;
     227    int opt;
     228    int exitcode;
     229    int killsig;
     230/*
     231fuser [OPTIONS] FILE or PORT/PROTO
     232Find processes which use FILEs or PORTs
     233        -m      Find processes which use same fs as FILEs
     234        -4      Search only IPv4 space
     235        -6      Search only IPv6 space
     236        -s      Don't display PIDs
     237        -k      Kill found processes
     238        -SIGNAL Signal to send (default: KILL)
     239*/
     240    /* Handle -SIGNAL. Oh my... */
     241    killsig = SIGKILL; /* yes, the default is not SIGTERM */
     242    pp = argv;
     243    while (*++pp) {
     244        char *arg = *pp;
     245        if (arg[0] != '-')
     246            continue;
     247        if (arg[1] == '-' && arg[2] == '\0') /* "--" */
     248            break;
     249        if ((arg[1] == '4' || arg[1] == '6') && arg[2] == '\0')
     250            continue; /* it's "-4" or "-6" */
     251        opt = get_signum(&arg[1]);
     252        if (opt < 0)
     253            continue;
     254        /* "-SIGNAL" option found. Remove it and bail out */
     255        killsig = opt;
     256        do {
     257            pp[0] = arg = pp[1];
     258            pp++;
     259        } while (arg);
     260        break;
     261    }
     262
     263    opt_complementary = "-1"; /* at least one param */
     264    opt = getopt32(argv, OPTION_STRING);
     265    argv += optind;
     266
     267    pp = argv;
     268    while (*pp) {
     269        /* parse net arg */
     270        char path[20], tproto[5];
     271        if (sscanf(*pp, "%u/%4s", &port, tproto) != 2)
     272            goto file;
     273        sprintf(path, "/proc/net/%s", tproto);
     274        if (access(path, R_OK) != 0) { /* PORT/PROTO */
     275            scan_proc_net(path, port);
     276        } else { /* FILE */
     277 file:
     278            xstat(*pp, &st);
     279            add_inode(&st);
     280        }
     281        pp++;
     282    }
     283
     284    scan_proc_pids(); /* changes dir to "/proc" */
     285
     286    mypid = getpid();
     287    plist = G.pid_list_head;
     288    while (1) {
     289        if (!plist)
     290            return EXIT_FAILURE;
     291        if (plist->pid != mypid)
     292            break;
     293        plist = plist->next;
     294    }
     295
     296    exitcode = EXIT_SUCCESS;
     297    do {
     298        if (plist->pid != mypid) {
     299            if (opt & OPT_KILL) {
     300                if (kill(plist->pid, killsig) != 0) {
     301                    bb_perror_msg("kill pid %u", (unsigned)plist->pid);
     302                    exitcode = EXIT_FAILURE;
     303                }
    312304            }
    313         }
    314         curr = curr->next;
    315     }
    316     return success;
    317 }
    318 
    319 int fuser_main(int argc, char **argv);
    320 int fuser_main(int argc, char **argv)
    321 {
    322     /*static -- huh???*/ int opt = 0; /* FUSER_OPT_ */
    323 
    324     int port, i, optn;
    325     int* fni; /* file name indexes of argv */
    326     int fnic = 0;  /* file name index count */
    327     const char *proto;
    328     dev_t dev;
    329     ino_t inode;
    330     pid_list *pids;
    331     inode_list *inodes;
    332     int killsig = SIGTERM;
    333     int success = 1;
    334 
    335     if (argc < 2)
    336         bb_show_usage();
    337 
    338     fni = xmalloc(sizeof(int));
    339     for (i = 1; i < argc; i++) {
    340         optn = fuser_option(argv[i]);
    341         if (optn)
    342             opt |= optn;
    343         else if (argv[i][0] == '-') {
    344             killsig = get_signum(argv[i]+1);
    345             if (killsig < 0)
    346                 killsig = SIGTERM;
    347         } else {
    348             fni = xrealloc(fni, sizeof(int) * (fnic+2));
    349             fni[fnic++] = i;
    350         }
    351     }
    352 
    353     if (!fnic)
    354         return 1;
    355 
    356     inodes = xmalloc(sizeof(inode_list));
    357     for (i = 0; i < fnic; i++) {
    358         if (fuser_parse_net_arg(argv[fni[i]], &proto, &port)) {
    359             fuser_scan_proc_net(opt, proto, port, inodes);
    360         } else {
    361             if (!fuser_file_to_dev_inode(argv[fni[i]], &dev, &inode)) {
    362                 if (ENABLE_FEATURE_CLEAN_UP)
    363                     free(inodes);
    364                 bb_perror_msg_and_die("cannot open '%s'", argv[fni[i]]);
     305            if (!(opt & OPT_SILENT)) {
     306                printf("%u ", (unsigned)plist->pid);
    365307            }
    366             fuser_add_inode(inodes, dev, inode);
    367         }
    368     }
    369     pids = xmalloc(sizeof(pid_list));
    370     success = fuser_scan_proc_pids(opt, inodes, pids);
    371     /* if the first pid in the list is 0, none have been found */
    372     if (pids->pid == 0)
    373         success = 0;
    374     if (success) {
    375         if (opt & FUSER_OPT_KILL) {
    376             success = fuser_kill_pid_list(pids, killsig);
    377         } else if (!(opt & FUSER_OPT_SILENT)) {
    378             success = fuser_print_pid_list(pids);
    379         }
    380     }
    381     if (ENABLE_FEATURE_CLEAN_UP) {
    382         free(pids);
    383         free(inodes);
    384     }
    385     /* return 0 on (success == 1) 1 otherwise */
    386     return (success != 1);
    387 }
     308        }
     309        plist = plist->next;
     310    } while (plist);
     311
     312    if (!(opt & (OPT_SILENT))) {
     313        bb_putchar('\n');
     314    }
     315
     316    return exitcode;
     317}
Note: See TracChangeset for help on using the changeset viewer.