Changeset 3621 in MondoRescue for branches/3.3/mindi-busybox/modutils


Ignore:
Timestamp:
Dec 20, 2016, 4:07:32 PM (7 years ago)
Author:
Bruno Cornec
Message:

New 3?3 banch for incorporation of latest busybox 1.25. Changing minor version to handle potential incompatibilities.

Location:
branches/3.3
Files:
10 edited
1 copied

Legend:

Unmodified
Added
Removed
  • branches/3.3/mindi-busybox/modutils/Config.src

    r3232 r3621  
    3939      - depmod generates modules.dep.bb
    4040
    41       As of 2008-07, this code is experimental. It is 14kb smaller
    42       than "non-small" modutils.
    43 
    4441config FEATURE_MODPROBE_SMALL_OPTIONS_ON_CMDLINE
    4542    bool "Accept module options on modprobe command line"
  • branches/3.3/mindi-busybox/modutils/depmod.c

    r3232 r3621  
    2222 */
    2323
    24 typedef struct module_info {
    25     struct module_info *next;
    26     char *name, *modname;
    27     llist_t *dependencies;
    28     llist_t *aliases;
    29     llist_t *symbols;
    30     struct module_info *dnext, *dprev;
    31 } module_info;
    32 
    3324static int FAST_FUNC parse_module(const char *fname, struct stat *sb UNUSED_PARAM,
    3425                void *data, int depth UNUSED_PARAM)
    3526{
    36     char modname[MODULE_NAME_LEN];
    37     module_info **first = (module_info **) data;
     27    module_db *modules = data;
    3828    char *image, *ptr;
    39     module_info *info;
     29    module_entry *e;
     30
    4031    /* Arbitrary. Was sb->st_size, but that breaks .gz etc */
    4132    size_t len = (64*1024*1024 - 4096);
     
    4536
    4637    image = xmalloc_open_zipped_read_close(fname, &len);
    47     info = xzalloc(sizeof(*info));
    48 
    49     info->next = *first;
    50     *first = info;
    51 
    52     info->dnext = info->dprev = info;
    53     info->name = xstrdup(fname + 2); /* skip "./" */
    54     info->modname = xstrdup(filename2modname(fname, modname));
     38
     39    e = moddb_get_or_create(modules, bb_get_last_path_component_nostrip(fname));
     40    e->name = xstrdup(fname + 2); /* skip "./" */
     41
    5542    for (ptr = image; ptr < image + len - 10; ptr++) {
    56         if (strncmp(ptr, "depends=", 8) == 0) {
     43        if (is_prefixed_with(ptr, "depends=")) {
    5744            char *u;
    5845
     
    6148                if (*u == '-')
    6249                    *u = '_';
    63             ptr += string_to_llist(ptr, &info->dependencies, ",");
     50            ptr += string_to_llist(ptr, &e->deps, ",");
    6451        } else if (ENABLE_FEATURE_MODUTILS_ALIAS
    65          && strncmp(ptr, "alias=", 6) == 0
     52         && is_prefixed_with(ptr, "alias=")
    6653        ) {
    67             llist_add_to(&info->aliases, xstrdup(ptr + 6));
     54            llist_add_to(&e->aliases, xstrdup(ptr + 6));
    6855            ptr += strlen(ptr);
    6956        } else if (ENABLE_FEATURE_MODUTILS_SYMBOLS
    70          && strncmp(ptr, "__ksymtab_", 10) == 0
     57         && is_prefixed_with(ptr, "__ksymtab_")
    7158        ) {
    7259            ptr += 10;
    73             if (strncmp(ptr, "gpl", 3) == 0
     60            if (is_prefixed_with(ptr, "gpl")
    7461             || strcmp(ptr, "strings") == 0
    7562            ) {
    7663                continue;
    7764            }
    78             llist_add_to(&info->symbols, xstrdup(ptr));
     65            llist_add_to(&e->symbols, xstrdup(ptr));
    7966            ptr += strlen(ptr);
    8067        }
     
    8572}
    8673
    87 static module_info *find_module(module_info *modules, const char *modname)
    88 {
    89     module_info *m;
    90 
    91     for (m = modules; m != NULL; m = m->next)
    92         if (strcmp(m->modname, modname) == 0)
    93             return m;
    94     return NULL;
    95 }
    96 
    97 static void order_dep_list(module_info *modules, module_info *start,
    98             llist_t *add)
    99 {
    100     module_info *m;
     74static void order_dep_list(module_db *modules, module_entry *start, llist_t *add)
     75{
     76    module_entry *m;
    10177    llist_t *n;
    10278
    10379    for (n = add; n != NULL; n = n->link) {
    104         m = find_module(modules, n->data);
     80        m = moddb_get(modules, n->data);
    10581        if (m == NULL)
    10682            continue;
     
    11793
    11894        /* recurse */
    119         order_dep_list(modules, start, m->dependencies);
     95        order_dep_list(modules, start, m->deps);
    12096    }
    12197}
     
    183159int depmod_main(int argc UNUSED_PARAM, char **argv)
    184160{
    185     module_info *modules, *m, *dep;
     161    module_db modules;
     162    module_entry *m, *dep;
    186163    const char *moddir_base = "/";
    187164    char *moddir, *version;
    188165    struct utsname uts;
     166    unsigned i;
    189167    int tmp;
    190168
     
    210188
    211189    /* Scan modules */
    212     modules = NULL;
     190    memset(&modules, 0, sizeof(modules));
    213191    if (*argv) {
    214192        do {
     
    223201    if (!(option_mask32 & OPT_n))
    224202        xfreopen_write(CONFIG_DEFAULT_DEPMOD_FILE, stdout);
    225     for (m = modules; m != NULL; m = m->next) {
     203
     204    moddb_foreach_module(&modules, m, i) {
    226205        printf("%s:", m->name);
    227206
    228         order_dep_list(modules, m, m->dependencies);
     207        order_dep_list(&modules, m, m->deps);
    229208        while (m->dnext != m) {
    230209            dep = m->dnext;
     
    242221    if (!(option_mask32 & OPT_n))
    243222        xfreopen_write("modules.alias", stdout);
    244     for (m = modules; m != NULL; m = m->next) {
    245         const char *fname = bb_basename(m->name);
    246         int fnlen = strchrnul(fname, '.') - fname;
     223    moddb_foreach_module(&modules, m, i) {
    247224        while (m->aliases) {
    248             /* Last word can well be m->modname instead,
    249              * but depmod from module-init-tools 3.4
    250              * uses module basename, i.e., no s/-/_/g.
    251              * (pathname and .ko.* are still stripped)
    252              * Mimicking that... */
    253             printf("alias %s %.*s\n",
     225            /*
     226             * Last word used to be a basename
     227             * (filename with path and .ko.* stripped)
     228             * at the time of module-init-tools 3.4.
     229             * kmod v.12 uses module name, i.e., s/-/_/g.
     230             */
     231            printf("alias %s %s\n",
    254232                (char*)llist_pop(&m->aliases),
    255                 fnlen, fname);
     233                m->modname);
    256234        }
    257235    }
     
    260238    if (!(option_mask32 & OPT_n))
    261239        xfreopen_write("modules.symbols", stdout);
    262     for (m = modules; m != NULL; m = m->next) {
    263         const char *fname = bb_basename(m->name);
    264         int fnlen = strchrnul(fname, '.') - fname;
     240    moddb_foreach_module(&modules, m, i) {
    265241        while (m->symbols) {
    266             printf("alias symbol:%s %.*s\n",
     242            printf("alias symbol:%s %s\n",
    267243                (char*)llist_pop(&m->symbols),
    268                 fnlen, fname);
     244                m->modname);
    269245        }
    270246    }
    271247#endif
    272248
    273     if (ENABLE_FEATURE_CLEAN_UP) {
    274         while (modules) {
    275             module_info *old = modules;
    276             modules = modules->next;
    277             free(old->name);
    278             free(old->modname);
    279             free(old);
    280         }
    281     }
     249    if (ENABLE_FEATURE_CLEAN_UP)
     250        moddb_free(&modules);
    282251
    283252    return EXIT_SUCCESS;
  • branches/3.3/mindi-busybox/modutils/insmod.c

    r3232 r3621  
    2222//usage:    "[SYMBOL=VALUE]..."
    2323//usage:#define insmod_full_usage "\n\n"
    24 //usage:       "Load the specified kernel modules into the kernel"
     24//usage:       "Load kernel module"
    2525//usage:    IF_FEATURE_2_4_MODULES( "\n"
    2626//usage:     "\n    -f  Force module to load into the wrong kernel version"
  • branches/3.3/mindi-busybox/modutils/modinfo.c

    r3232 r3621  
    66 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
    77 */
    8 
    9 //applet:IF_MODINFO(APPLET(modinfo, BB_DIR_SBIN, BB_SUID_DROP))
    10 
    11 //kbuild:lib-$(CONFIG_MODINFO) += modinfo.o modutils.o
    12 
    138//config:config MODINFO
    149//config:   bool "modinfo"
     
    1813//config:     Show information about a Linux Kernel module
    1914
     15//applet:IF_MODINFO(APPLET(modinfo, BB_DIR_SBIN, BB_SUID_DROP))
     16
     17//kbuild:lib-$(CONFIG_MODINFO) += modinfo.o modutils.o
     18
    2019#include <fnmatch.h>
    2120#include <sys/utsname.h> /* uname() */
     
    2322#include "modutils.h"
    2423
     24static const char *const shortcuts[] = {
     25    "filename", // -n
     26    "author",   // -a
     27    "description",  // -d
     28    "license",  // -l
     29    "parm",     // -p
     30    "version",  // the rest has no shortcut options
     31    "alias",
     32    "srcversion",
     33    "depends",
     34    "uts_release",
     35    "intree",
     36    "vermagic",
     37    "firmware",
     38};
    2539
    2640enum {
    27     OPT_TAGS = (1 << 12) - 1, /* shortcut count */
    28     OPT_F = (1 << 12), /* field name */
    29     OPT_0 = (1 << 13), /* \0 as separator */
     41    OPT_0 = (1 << 0), /* \0 as separator */
     42    OPT_F = (1 << 1), /* field name */
     43    /* first bits are for -nadlp options, the rest are for
     44     * fields not selectable with "shortcut" options
     45     */
     46    OPT_n = (1 << 2),
     47    OPT_TAGS = ((1 << ARRAY_SIZE(shortcuts)) - 1) << 2,
    3048};
    3149
    32 struct modinfo_env {
    33     char *field;
    34     int tags;
    35 };
    36 
    37 static int display(const char *data, const char *pattern, int flag)
     50static void display(const char *data, const char *pattern)
    3851{
    39     if (flag) {
     52    int flag = option_mask32 >> 1; /* shift out -0 bit */
     53    if (flag & (flag-1)) {
     54        /* more than one field to show: print "FIELD:" pfx */
    4055        int n = printf("%s:", pattern);
    4156        while (n++ < 16)
    4257            bb_putchar(' ');
    4358    }
    44     return printf("%s%c", data, (option_mask32 & OPT_0) ? '\0' : '\n');
     59    printf("%s%c", data, (option_mask32 & OPT_0) ? '\0' : '\n');
    4560}
    4661
    4762static void modinfo(const char *path, const char *version,
    48             const struct modinfo_env *env)
     63            const char *field)
    4964{
    50     static const char *const shortcuts[] = {
    51         "filename",
    52         "license",
    53         "author",
    54         "description",
    55         "version",
    56         "alias",
    57         "srcversion",
    58         "depends",
    59         "uts_release",
    60         "vermagic",
    61         "parm",
    62         "firmware",
    63     };
    6465    size_t len;
    65     int j, length;
     66    int j;
    6667    char *ptr, *the_module;
    67     const char *field = env->field;
    68     int tags = env->tags;
     68    char *allocated;
     69    int tags = option_mask32;
    6970
    70     if (tags & 1) { /* filename */
    71         display(path, shortcuts[0], 1 != tags);
    72     }
    73 
     71    allocated = NULL;
    7472    len = MAXINT(ssize_t);
    7573    the_module = xmalloc_open_zipped_read_close(path, &len);
     
    7876            return;
    7977        /* Newer depmod puts relative paths in modules.dep */
    80         path = xasprintf("%s/%s/%s", CONFIG_DEFAULT_MODULES_DIR, version, path);
     78        path = allocated = xasprintf("%s/%s/%s", CONFIG_DEFAULT_MODULES_DIR, version, path);
    8179        the_module = xmalloc_open_zipped_read_close(path, &len);
    82         free((char*)path);
    83         if (!the_module)
    84             return;
     80        if (!the_module) {
     81            bb_error_msg("module '%s' not found", path);
     82            goto ret;
     83        }
    8584    }
    8685
    87     if (field)
    88         tags |= OPT_F;
    89     for (j = 1; (1<<j) & (OPT_TAGS + OPT_F); j++) {
     86    for (j = 1; (1<<j) & (OPT_TAGS|OPT_F); j++) {
    9087        const char *pattern;
    9188
    9289        if (!((1<<j) & tags))
    9390            continue;
     91
    9492        pattern = field;
    9593        if ((1<<j) & OPT_TAGS)
    96             pattern = shortcuts[j];
    97         length = strlen(pattern);
     94            pattern = shortcuts[j-2];
     95
     96        if (strcmp(pattern, shortcuts[0]) == 0) {
     97            /* "-n" or "-F filename" */
     98            display(path, shortcuts[0]);
     99            continue;
     100        }
     101
    98102        ptr = the_module;
    99103        while (1) {
     104            char *after_pattern;
     105
    100106            ptr = memchr(ptr, *pattern, len - (ptr - (char*)the_module));
    101107            if (ptr == NULL) /* no occurance left, done */
    102108                break;
    103             if (strncmp(ptr, pattern, length) == 0 && ptr[length] == '=') {
     109            after_pattern = is_prefixed_with(ptr, pattern);
     110            if (after_pattern && *after_pattern == '=') {
    104111                /* field prefixes are 0x80 or 0x00 */
    105                 if ((ptr[-1] & 0x7F) == '\0') {
    106                     ptr += length + 1;
    107                     ptr += display(ptr, pattern, (1<<j) != tags);
     112                if ((ptr[-1] & 0x7F) == 0x00) {
     113                    ptr = after_pattern + 1;
     114                    display(ptr, pattern);
     115                    ptr += strlen(ptr);
    108116                }
    109117            }
     
    112120    }
    113121    free(the_module);
     122 ret:
     123    free(allocated);
    114124}
    115125
    116126//usage:#define modinfo_trivial_usage
    117 //usage:       "[-adlp0] [-F keyword] MODULE"
     127//usage:       "[-adlpn0] [-F keyword] MODULE"
    118128//usage:#define modinfo_full_usage "\n\n"
    119129//usage:       "    -a      Shortcut for '-F author'"
     
    121131//usage:     "\n    -l      Shortcut for '-F license'"
    122132//usage:     "\n    -p      Shortcut for '-F parm'"
     133////usage:     "\n  -n      Shortcut for '-F filename'"
    123134//usage:     "\n    -F keyword  Keyword to look for"
    124135//usage:     "\n    -0      Separate output with NULs"
     
    129140int modinfo_main(int argc UNUSED_PARAM, char **argv)
    130141{
    131     struct modinfo_env env;
     142    const char *field;
    132143    char name[MODULE_NAME_LEN];
    133144    struct utsname uts;
     
    137148    unsigned i;
    138149
    139     env.field = NULL;
     150    field = NULL;
    140151    opt_complementary = "-1"; /* minimum one param */
    141     opts = getopt32(argv, "nladvAsDumpF:0", &env.field);
    142     env.tags = opts & OPT_TAGS ? opts & OPT_TAGS : OPT_TAGS;
     152    opts = getopt32(argv, "0F:nadlp", &field);
     153    /* If no field selected, show all */
     154    if (!(opts & (OPT_TAGS|OPT_F)))
     155        option_mask32 |= OPT_TAGS;
    143156    argv += optind;
    144157
     
    154167            continue;
    155168        *colon = '\0';
    156         filename2modname(tokens[0], name);
     169        filename2modname(bb_basename(tokens[0]), name);
    157170        for (i = 0; argv[i]; i++) {
    158171            if (fnmatch(argv[i], name, 0) == 0) {
    159                 modinfo(tokens[0], uts.release, &env);
     172                modinfo(tokens[0], uts.release, field);
    160173                argv[i] = (char *) "";
    161174            }
     
    167180    for (i = 0; argv[i]; i++) {
    168181        if (argv[i][0]) {
    169             modinfo(argv[i], uts.release, &env);
     182            modinfo(argv[i], uts.release, field);
    170183        }
    171184    }
  • branches/3.3/mindi-busybox/modutils/modprobe-small.c

    r3232 r3621  
    1010
    1111//applet:IF_MODPROBE_SMALL(APPLET(modprobe, BB_DIR_SBIN, BB_SUID_DROP))
    12 //applet:IF_MODPROBE_SMALL(APPLET_ODDNAME(depmod, modprobe, BB_DIR_SBIN, BB_SUID_DROP, modprobe))
    13 //applet:IF_MODPROBE_SMALL(APPLET_ODDNAME(insmod, modprobe, BB_DIR_SBIN, BB_SUID_DROP, modprobe))
    14 //applet:IF_MODPROBE_SMALL(APPLET_ODDNAME(lsmod, modprobe, BB_DIR_SBIN, BB_SUID_DROP, modprobe))
    15 //applet:IF_MODPROBE_SMALL(APPLET_ODDNAME(rmmod, modprobe, BB_DIR_SBIN, BB_SUID_DROP, modprobe))
     12//applet:IF_MODPROBE_SMALL(APPLET_ODDNAME(depmod, modprobe, BB_DIR_SBIN, BB_SUID_DROP, depmod))
     13//applet:IF_MODPROBE_SMALL(APPLET_ODDNAME(insmod, modprobe, BB_DIR_SBIN, BB_SUID_DROP, insmod))
     14//applet:IF_MODPROBE_SMALL(APPLET_ODDNAME(lsmod, modprobe, BB_DIR_SBIN, BB_SUID_DROP, lsmod))
     15//applet:IF_MODPROBE_SMALL(APPLET_ODDNAME(rmmod, modprobe, BB_DIR_SBIN, BB_SUID_DROP, rmmod))
    1616
    1717#include "libbb.h"
     
    2222extern int init_module(void *module, unsigned long len, const char *options);
    2323extern int delete_module(const char *module, unsigned flags);
    24 extern int query_module(const char *name, int which, void *buf, size_t bufsize, size_t *ret);
     24/* linux/include/linux/module.h has limit of 64 chars on module names */
     25#undef MODULE_NAME_LEN
     26#define MODULE_NAME_LEN 64
    2527
    2628
     
    4446    char *aliases;
    4547    char *deps;
     48    smallint open_read_failed;
    4649} module_info;
    4750
     
    114117static char* find_keyword(char *ptr, size_t len, const char *word)
    115118{
    116     int wlen;
    117 
    118119    if (!ptr) /* happens if xmalloc_open_zipped_read_close cannot read it */
    119120        return NULL;
    120121
    121     wlen = strlen(word);
    122     len -= wlen - 1;
     122    len -= strlen(word) - 1;
    123123    while ((ssize_t)len > 0) {
    124124        char *old = ptr;
     125        char *after_word;
     126
    125127        /* search for the first char in word */
    126         ptr = memchr(ptr, *word, len);
     128        ptr = memchr(ptr, word[0], len);
    127129        if (ptr == NULL) /* no occurance left, done */
    128130            break;
    129         if (strncmp(ptr, word, wlen) == 0)
    130             return ptr + wlen; /* found, return ptr past it */
     131        after_word = is_prefixed_with(ptr, word);
     132        if (after_word)
     133            return after_word; /* found, return ptr past it */
    131134        ++ptr;
    132135        len -= (ptr - old);
     
    142145        ++s;
    143146    }
     147}
     148
     149static char *filename2modname(const char *filename, char *modname)
     150{
     151    int i;
     152    const char *from;
     153
     154    // Disabled since otherwise "modprobe dir/name" would work
     155    // as if it is "modprobe name". It is unclear why
     156    // 'basenamization' was here in the first place.
     157    //from = bb_get_last_path_component_nostrip(filename);
     158    from = filename;
     159    for (i = 0; i < (MODULE_NAME_LEN-1) && from[i] != '\0' && from[i] != '.'; i++)
     160        modname[i] = (from[i] == '-') ? '_' : from[i];
     161    modname[i] = '\0';
     162
     163    return modname;
     164}
     165
     166static int pathname_matches_modname(const char *pathname, const char *modname)
     167{
     168    int r;
     169    char name[MODULE_NAME_LEN];
     170    filename2modname(bb_get_last_path_component_nostrip(pathname), name);
     171    r = (strcmp(name, modname) == 0);
     172    return r;
    144173}
    145174
     
    195224}
    196225
    197 static void parse_module(module_info *info, const char *pathname)
     226/* Returns !0 if open/read was unsuccessful */
     227static int parse_module(module_info *info, const char *pathname)
    198228{
    199229    char *module_image;
     
    204234
    205235    /* Read (possibly compressed) module */
     236    errno = 0;
    206237    len = 64 * 1024 * 1024; /* 64 Mb at most */
    207238    module_image = xmalloc_open_zipped_read_close(pathname, &len);
     
    213244    pos = 0;
    214245    while (1) {
     246        unsigned start = stringbuf_idx;
    215247        ptr = find_keyword(module_image + pos, len - pos, "alias=");
    216248        if (!ptr) {
     
    229261        append(ptr);
    230262        appendc(' ');
     263        /*
     264         * Don't add redundant aliases, such as:
     265         * libcrc32c.ko symbol:crc32c symbol:crc32c
     266         */
     267        if (start) { /* "if we aren't the first alias" */
     268            char *found, *last;
     269            stringbuf[stringbuf_idx] = '\0';
     270            last = stringbuf + start;
     271            /*
     272             * String at last-1 is " symbol:crc32c "
     273             * (with both leading and trailing spaces).
     274             */
     275            if (strncmp(stringbuf, last, stringbuf_idx - start) == 0)
     276                /* First alias matches us */
     277                found = stringbuf;
     278            else
     279                /* Does any other alias match? */
     280                found = strstr(stringbuf, last-1);
     281            if (found < last-1) {
     282                /* There is absolutely the same string before us */
     283                dbg2_error_msg("redundant:'%s'", last);
     284                stringbuf_idx = start;
     285                goto skip;
     286            }
     287        }
    231288 skip:
    232289        pos = (ptr - module_image);
     
    245302        append(ptr);
    246303    }
     304    free(module_image);
    247305    info->deps = copy_stringbuf();
    248306
    249     free(module_image);
    250 }
    251 
    252 static int pathname_matches_modname(const char *pathname, const char *modname)
    253 {
    254     const char *fname = bb_get_last_path_component_nostrip(pathname);
    255     const char *suffix = strrstr(fname, ".ko");
    256 //TODO: can do without malloc?
    257     char *name = xstrndup(fname, suffix - fname);
    258     int r;
    259     replace(name, '-', '_');
    260     r = (strcmp(name, modname) == 0);
    261     free(name);
    262     return r;
     307    info->open_read_failed = (module_image == NULL);
     308    return info->open_read_failed;
    263309}
    264310
     
    291337    dbg1_error_msg("'%s' module name matches", pathname);
    292338    module_found_idx = cur;
    293     parse_module(&modinfo[cur], pathname);
     339    if (parse_module(&modinfo[cur], pathname) != 0)
     340        return TRUE; /* failed to open/read it, no point in trying loading */
    294341
    295342    if (!(option_mask32 & OPT_r)) {
     
    422469}
    423470
    424 static module_info* find_alias(const char *alias)
     471static module_info** find_alias(const char *alias)
    425472{
    426473    int i;
    427474    int dep_bb_fd;
    428     module_info *result;
     475    int infoidx;
     476    module_info **infovec;
    429477    dbg1_error_msg("find_alias('%s')", alias);
    430478
     
    439487                parse_module(&modinfo[i], modinfo[i].pathname);
    440488            }
    441             return &modinfo[i];
     489            infovec = xzalloc(2 * sizeof(infovec[0]));
     490            infovec[0] = &modinfo[i];
     491            return infovec;
    442492        }
    443493        i++;
     
    452502    /* Scan all module bodies, extract modinfo (it contains aliases) */
    453503    i = 0;
    454     result = NULL;
     504    infoidx = 0;
     505    infovec = NULL;
    455506    while (modinfo[i].pathname) {
    456507        char *desc, *s;
    457508        if (!modinfo[i].aliases) {
    458509            parse_module(&modinfo[i], modinfo[i].pathname);
    459         }
    460         if (result) {
    461             i++;
    462             continue;
    463510        }
    464511        /* "alias1 symbol:sym1 alias2 symbol:sym2" */
     
    473520                dbg1_error_msg("found alias '%s' in module '%s'",
    474521                        alias, modinfo[i].pathname);
    475                 result = &modinfo[i];
     522                infovec = xrealloc_vector(infovec, 1, infoidx);
     523                infovec[infoidx++] = &modinfo[i];
    476524                break;
    477525            }
    478526        }
    479527        free(desc);
    480         if (result && dep_bb_fd < 0)
    481             return result;
    482528        i++;
    483529    }
     
    488534    }
    489535
    490     dbg1_error_msg("find_alias '%s' returns %p", alias, result);
    491     return result;
     536    dbg1_error_msg("find_alias '%s' returns %d results", alias, infoidx);
     537    return infovec;
    492538}
    493539
     
    496542static int already_loaded(const char *name)
    497543{
    498     int ret = 0;
    499     char *s;
    500     parser_t *parser = config_open2("/proc/modules", xfopen_for_read);
    501     while (config_read(parser, &s, 1, 1, "# \t", PARSE_NORMAL & ~PARSE_GREEDY)) {
    502         if (strcmp(s, name) == 0) {
    503             ret = 1;
    504             break;
    505         }
    506     }
    507     config_close(parser);
    508     return ret;
     544    int ret;
     545    char *line;
     546    FILE *fp;
     547
     548    ret = 5 * 2;
     549 again:
     550    fp = fopen_for_read("/proc/modules");
     551    if (!fp)
     552        return 0;
     553    while ((line = xmalloc_fgetline(fp)) != NULL) {
     554        char *live;
     555        char *after_name;
     556
     557        // Examples from kernel 3.14.6:
     558        //pcspkr 12718 0 - Live 0xffffffffa017e000
     559        //snd_timer 28690 2 snd_seq,snd_pcm, Live 0xffffffffa025e000
     560        //i915 801405 2 - Live 0xffffffffa0096000
     561        after_name = is_prefixed_with(line, name);
     562        if (!after_name || *after_name != ' ') {
     563            free(line);
     564            continue;
     565        }
     566        live = strstr(line, " Live");
     567        free(line);
     568        if (!live) {
     569            /* State can be Unloading, Loading, or Live.
     570             * modprobe must not return prematurely if we see "Loading":
     571             * it can cause further programs to assume load completed,
     572             * but it did not (yet)!
     573             * Wait up to 5*20 ms for it to resolve.
     574             */
     575            ret -= 2;
     576            if (ret == 0)
     577                break;  /* huh? report as "not loaded" */
     578            fclose(fp);
     579            usleep(20*1000);
     580            goto again;
     581        }
     582        ret = 1;
     583        break;
     584    }
     585    fclose(fp);
     586
     587    return ret & 1;
    509588}
    510589#else
    511 #define already_loaded(name) is_rmmod
     590#define already_loaded(name) 0
    512591#endif
     592
     593static int rmmod(const char *filename)
     594{
     595    int r;
     596    char modname[MODULE_NAME_LEN];
     597
     598    filename2modname(filename, modname);
     599    r = delete_module(modname, O_NONBLOCK | O_EXCL);
     600    dbg1_error_msg("delete_module('%s', O_NONBLOCK | O_EXCL):%d", modname, r);
     601    if (r != 0 && !(option_mask32 & OPT_q)) {
     602        bb_perror_msg("remove '%s'", modname);
     603    }
     604    return r;
     605}
    513606
    514607/*
     
    522615#define cmdline_options ""
    523616#endif
    524 static void process_module(char *name, const char *cmdline_options)
     617static int process_module(char *name, const char *cmdline_options)
    525618{
    526619    char *s, *deps, *options;
     620    module_info **infovec;
    527621    module_info *info;
    528     int is_rmmod = (option_mask32 & OPT_r) != 0;
     622    int infoidx;
     623    int is_remove = (option_mask32 & OPT_r) != 0;
     624    int exitcode = EXIT_SUCCESS;
     625
    529626    dbg1_error_msg("process_module('%s','%s')", name, cmdline_options);
    530627
    531628    replace(name, '-', '_');
    532629
    533     dbg1_error_msg("already_loaded:%d is_rmmod:%d", already_loaded(name), is_rmmod);
    534     if (already_loaded(name) != is_rmmod) {
     630    dbg1_error_msg("already_loaded:%d is_remove:%d", already_loaded(name), is_remove);
     631
     632    if (applet_name[0] == 'r') {
     633        /* rmmod.
     634         * Does not remove dependencies, no need to scan, just remove.
     635         * (compat note: this allows and strips .ko suffix)
     636         */
     637        rmmod(name);
     638        return EXIT_SUCCESS;
     639    }
     640
     641    /*
     642     * We used to have "is_remove != already_loaded(name)" check here, but
     643     *  modprobe -r pci:v00008086d00007010sv00000000sd00000000bc01sc01i80
     644     * won't unload modules (there are more than one)
     645     * which have this alias.
     646     */
     647    if (!is_remove && already_loaded(name)) {
    535648        dbg1_error_msg("nothing to do for '%s'", name);
    536         return;
     649        return EXIT_SUCCESS;
    537650    }
    538651
    539652    options = NULL;
    540     if (!is_rmmod) {
     653    if (!is_remove) {
    541654        char *opt_filename = xasprintf("/etc/modules/%s", name);
    542655        options = xmalloc_open_read_close(opt_filename, NULL);
     
    561674        /* Scan module directory. This is done only once.
    562675         * It will attempt module load, and will exit(EXIT_SUCCESS)
    563          * on success. */
     676         * on success.
     677         */
    564678        module_found_idx = -1;
    565679        recursive_action(".",
     
    568682            NULL, /* dir action */
    569683            name, /* user data */
    570             0); /* depth */
     684            0 /* depth */
     685        );
    571686        dbg1_error_msg("dirscan complete");
    572         /* Module was not found, or load failed, or is_rmmod */
     687        /* Module was not found, or load failed, or is_remove */
    573688        if (module_found_idx >= 0) { /* module was found */
    574             info = &modinfo[module_found_idx];
     689            infovec = xzalloc(2 * sizeof(infovec[0]));
     690            infovec[0] = &modinfo[module_found_idx];
    575691        } else { /* search for alias, not a plain module name */
    576             info = find_alias(name);
     692            infovec = find_alias(name);
    577693        }
    578694    } else {
    579         info = find_alias(name);
    580     }
    581 
    582 // Problem here: there can be more than one module
    583 // for the given alias. For example,
    584 // "pci:v00008086d00007010sv00000000sd00000000bc01sc01i80" matches
    585 // ata_piix because it has an alias "pci:v00008086d00007010sv*sd*bc*sc*i*"
    586 // and ata_generic, it has an alias "alias=pci:v*d*sv*sd*bc01sc01i*"
    587 // Standard modprobe would load them both.
    588 // In this code, find_alias() returns only the first matching module.
    589 
    590     /* rmmod? unload it by name */
    591     if (is_rmmod) {
    592         if (delete_module(name, O_NONBLOCK | O_EXCL) != 0) {
    593             if (!(option_mask32 & OPT_q))
    594                 bb_perror_msg("remove '%s'", name);
    595             goto ret;
    596         }
    597 
    598         if (applet_name[0] == 'r') {
    599             /* rmmod: do not remove dependencies, exit */
    600             goto ret;
    601         }
    602 
     695        infovec = find_alias(name);
     696    }
     697
     698    if (!infovec) {
     699        /* both dirscan and find_alias found nothing */
     700        if (!is_remove && applet_name[0] != 'd') /* it wasn't rmmod or depmod */
     701            bb_error_msg("module '%s' not found", name);
     702//TODO: _and_die()? or should we continue (un)loading modules listed on cmdline?
     703        goto ret;
     704    }
     705
     706    /* There can be more than one module for the given alias. For example,
     707     * "pci:v00008086d00007010sv00000000sd00000000bc01sc01i80" matches
     708     * ata_piix because it has alias "pci:v00008086d00007010sv*sd*bc*sc*i*"
     709     * and ata_generic, it has alias "pci:v*d*sv*sd*bc01sc01i*"
     710     * Standard modprobe loads them both. We achieve it by returning
     711     * a *list* of modinfo pointers from find_alias().
     712     */
     713
     714    /* modprobe -r? unload module(s) */
     715    if (is_remove) {
     716        infoidx = 0;
     717        while ((info = infovec[infoidx++]) != NULL) {
     718            int r = rmmod(bb_get_last_path_component_nostrip(info->pathname));
     719            if (r != 0) {
     720                goto ret; /* error */
     721            }
     722        }
    603723        /* modprobe -r: we do not stop here -
    604724         * continue to unload modules on which the module depends:
     
    609729    }
    610730
    611     if (!info) {
    612         /* both dirscan and find_alias found nothing */
    613         if (!is_rmmod && applet_name[0] != 'd') /* it wasn't rmmod or depmod */
    614             bb_error_msg("module '%s' not found", name);
    615 //TODO: _and_die()? or should we continue (un)loading modules listed on cmdline?
    616         goto ret;
    617     }
    618 
    619     /* Iterate thru dependencies, trying to (un)load them */
    620     deps = str_2_list(info->deps);
    621     for (s = deps; *s; s += strlen(s) + 1) {
    622         //if (strcmp(name, s) != 0) // N.B. do loops exist?
    623         dbg1_error_msg("recurse on dep '%s'", s);
    624         process_module(s, NULL);
    625         dbg1_error_msg("recurse on dep '%s' done", s);
    626     }
    627     free(deps);
    628 
    629     /* modprobe -> load it */
    630     if (!is_rmmod) {
    631         if (!options || strstr(options, "blacklist") == NULL) {
    632             errno = 0;
    633             if (load_module(info->pathname, options) != 0) {
    634                 if (EEXIST != errno) {
    635                     bb_error_msg("'%s': %s",
    636                         info->pathname,
    637                         moderror(errno));
    638                 } else {
    639                     dbg1_error_msg("'%s': %s",
    640                         info->pathname,
    641                         moderror(errno));
    642                 }
     731    infoidx = 0;
     732    while ((info = infovec[infoidx++]) != NULL) {
     733        /* Iterate thru dependencies, trying to (un)load them */
     734        deps = str_2_list(info->deps);
     735        for (s = deps; *s; s += strlen(s) + 1) {
     736            //if (strcmp(name, s) != 0) // N.B. do loops exist?
     737            dbg1_error_msg("recurse on dep '%s'", s);
     738            process_module(s, NULL);
     739            dbg1_error_msg("recurse on dep '%s' done", s);
     740        }
     741        free(deps);
     742
     743        if (is_remove)
     744            continue;
     745
     746        /* We are modprobe: load it */
     747        if (options && strstr(options, "blacklist")) {
     748            dbg1_error_msg("'%s': blacklisted", info->pathname);
     749            continue;
     750        }
     751        if (info->open_read_failed) {
     752            /* We already tried it, didn't work. Don't try load again */
     753            exitcode = EXIT_FAILURE;
     754            continue;
     755        }
     756        errno = 0;
     757        if (load_module(info->pathname, options) != 0) {
     758            if (EEXIST != errno) {
     759                bb_error_msg("'%s': %s",
     760                    info->pathname,
     761                    moderror(errno));
     762            } else {
     763                dbg1_error_msg("'%s': %s",
     764                    info->pathname,
     765                    moderror(errno));
    643766            }
    644         } else {
    645             dbg1_error_msg("'%s': blacklisted", info->pathname);
     767            exitcode = EXIT_FAILURE;
    646768        }
    647769    }
    648770 ret:
     771    free(infovec);
    649772    free(options);
    650 //TODO: return load attempt result from process_module.
    651 //If dep didn't load ok, continuing makes little sense.
     773
     774    return exitcode;
    652775}
    653776#undef cmdline_options
     
    704827//usage:#if ENABLE_MODPROBE_SMALL
    705828
    706 //// Note: currently, help system shows modprobe --help text for all aliased cmds
    707 //// (see APPLET_ODDNAME macro definition).
    708 //// All other help texts defined below are not used. FIXME?
    709 
    710829//usage:#define depmod_trivial_usage NOUSAGE_STR
    711830//usage:#define depmod_full_usage ""
     
    721840//usage:    "[SYMBOL=VALUE]..."
    722841//usage:#define insmod_full_usage "\n\n"
    723 //usage:       "Load the specified kernel modules into the kernel"
     842//usage:       "Load kernel module"
    724843//usage:    IF_FEATURE_2_4_MODULES( "\n"
    725844//usage:     "\n    -f  Force module to load into the wrong kernel version"
     
    746865
    747866//usage:#define modprobe_trivial_usage
    748 //usage:    "[-qfwrsv] MODULE [symbol=value]..."
     867//usage:    "[-qfwrsv] MODULE [SYMBOL=VALUE]..."
    749868//usage:#define modprobe_full_usage "\n\n"
    750869//usage:       "    -r  Remove MODULE (stacks) or do autoclean"
     
    760879int modprobe_main(int argc UNUSED_PARAM, char **argv)
    761880{
     881    int exitcode;
    762882    struct utsname uts;
    763883    char applet0 = applet_name[0];
     
    831951
    832952#if ENABLE_FEATURE_MODPROBE_SMALL_OPTIONS_ON_CMDLINE
    833     /* If not rmmod, parse possible module options given on command line.
     953    /* If not rmmod/-r, parse possible module options given on command line.
    834954     * insmod/modprobe takes one module name, the rest are parameters. */
    835955    options = NULL;
    836     if ('r' != applet0) {
     956    if (!(option_mask32 & OPT_r)) {
    837957        char **arg = argv;
    838958        while (*++arg) {
     
    845965    }
    846966#else
    847     if ('r' != applet0)
     967    if (!(option_mask32 & OPT_r))
    848968        argv[1] = NULL;
    849969#endif
     
    865985                    *argv, moderror(errno));
    866986        }
    867         return 0;
     987        return EXIT_SUCCESS;
    868988    }
    869989
    870990    /* Try to load modprobe.dep.bb */
    871     load_dep_bb();
     991    if ('r' != applet0) { /* not rmmod */
     992        load_dep_bb();
     993    }
    872994
    873995    /* Load/remove modules.
    874      * Only rmmod loops here, modprobe has only argv[0] */
     996     * Only rmmod/modprobe -r loops here, insmod/modprobe has only argv[0] */
     997    exitcode = EXIT_SUCCESS;
    875998    do {
    876         process_module(*argv, options);
     999        exitcode |= process_module(*argv, options);
    8771000    } while (*++argv);
    8781001
     
    8801003        IF_FEATURE_MODPROBE_SMALL_OPTIONS_ON_CMDLINE(free(options);)
    8811004    }
    882     return EXIT_SUCCESS;
    883 }
     1005    return exitcode;
     1006}
  • branches/3.3/mindi-busybox/modutils/modprobe.c

    r3232 r3621  
    1616#include <fnmatch.h>
    1717
    18 //#define DBG(fmt, ...) bb_error_msg("%s: " fmt, __func__, ## __VA_ARGS__)
     18#if 1
    1919#define DBG(...) ((void)0)
     20#else
     21#define DBG(fmt, ...) bb_error_msg("%s: " fmt, __func__, ## __VA_ARGS__)
     22#endif
    2023
    2124/* Note that unlike older versions of modules.dep/depmod (busybox and m-i-t),
     
    8891//usage:#define modprobe_trivial_usage
    8992//usage:    "[-alrqvsD" IF_FEATURE_MODPROBE_BLACKLIST("b") "]"
    90 //usage:    " MODULE [symbol=value]..."
     93//usage:    " MODULE [SYMBOL=VALUE]..."
    9194//usage:#define modprobe_full_usage "\n\n"
    9295//usage:       "    -a  Load multiple MODULEs"
     
    148151#define MODULE_FLAG_BLACKLISTED         0x0008
    149152
    150 struct module_entry { /* I'll call it ME. */
    151     unsigned flags;
    152     char *modname; /* stripped of /path/, .ext and s/-/_/g */
    153     const char *probed_name; /* verbatim as seen on cmdline */
    154     char *options; /* options from config files */
    155     llist_t *realnames; /* strings. if this module is an alias, */
    156     /* real module name is one of these. */
    157 //Can there really be more than one? Example from real kernel?
    158     llist_t *deps; /* strings. modules we depend on */
    159 };
    160 
    161 #define DB_HASH_SIZE 256
    162 
    163153struct globals {
    164154    llist_t *probes; /* MEs of module(s) requested on cmdline */
     
    168158    smallint need_symbols;
    169159    struct utsname uts;
    170     llist_t *db[DB_HASH_SIZE]; /* MEs of all modules ever seen (caching for speed) */
     160    module_db db;
    171161} FIX_ALIASING;
    172162#define G (*ptr_to_globals)
    173163#define INIT_G() do { \
    174         SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \
     164    SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \
    175165} while (0)
    176166
     
    193183}
    194184
    195 /* These three functions called many times, optimizing for speed.
    196  * Users reported minute-long delays when they runn iptables repeatedly
    197  * (iptables use modprobe to install needed kernel modules).
    198  */
    199 static struct module_entry *helper_get_module(const char *module, int create)
    200 {
    201     char modname[MODULE_NAME_LEN];
    202     struct module_entry *e;
    203     llist_t *l;
    204     unsigned i;
    205     unsigned hash;
    206 
    207     filename2modname(module, modname);
    208 
    209     hash = 0;
    210     for (i = 0; modname[i]; i++)
    211         hash = ((hash << 5) + hash) + modname[i];
    212     hash %= DB_HASH_SIZE;
    213 
    214     for (l = G.db[hash]; l; l = l->link) {
    215         e = (struct module_entry *) l->data;
    216         if (strcmp(e->modname, modname) == 0)
    217             return e;
    218     }
    219     if (!create)
    220         return NULL;
    221 
    222     e = xzalloc(sizeof(*e));
    223     e->modname = xstrdup(modname);
    224     llist_add_to(&G.db[hash], e);
    225 
    226     return e;
    227 }
    228 static ALWAYS_INLINE struct module_entry *get_or_add_modentry(const char *module)
    229 {
    230     return helper_get_module(module, 1);
    231 }
    232 static ALWAYS_INLINE struct module_entry *get_modentry(const char *module)
    233 {
    234     return helper_get_module(module, 0);
     185static struct module_entry *get_or_add_modentry(const char *module)
     186{
     187    return moddb_get_or_create(&G.db, module);
    235188}
    236189
     
    253206    G.num_unresolved_deps++;
    254207    if (ENABLE_FEATURE_MODUTILS_SYMBOLS
    255      && strncmp(m->modname, "symbol:", 7) == 0
     208     && is_prefixed_with(m->modname, "symbol:")
    256209    ) {
    257210        G.need_symbols = 1;
     
    262215                    struct stat *statbuf UNUSED_PARAM,
    263216                    void *userdata UNUSED_PARAM,
    264                     int depth UNUSED_PARAM)
     217                    int depth)
    265218{
    266219    char *tokens[3];
     
    268221    struct module_entry *m;
    269222    int rc = TRUE;
    270 
    271     if (bb_basename(filename)[0] == '.')
     223    const char *base, *ext;
     224
     225    /* Skip files that begin with a "." */
     226    base = bb_basename(filename);
     227    if (base[0] == '.')
    272228        goto error;
     229
     230    /* In dir recursion, skip files that do not end with a ".conf"
     231     * depth==0: read_config("modules.{symbols,alias}") must work,
     232     * "include FILE_NOT_ENDING_IN_CONF" must work too.
     233     */
     234    if (depth != 0) {
     235        ext = strrchr(base, '.');
     236        if (ext == NULL || strcmp(ext + 1, "conf"))
     237            goto error;
     238    }
    273239
    274240    p = config_open2(filename, fopen_for_read);
     
    315281            m->options = gather_options_str(m->options, tokens[2]);
    316282        } else if (strcmp(tokens[0], "include") == 0) {
    317             /* include <filename> */
     283            /* include <filename>/<dirname> (yes, directories also must work) */
    318284            read_config(tokens[1]);
    319285        } else if (ENABLE_FEATURE_MODPROBE_BLACKLIST
     
    332298{
    333299    return recursive_action(path, ACTION_RECURSE | ACTION_QUIET,
    334                 config_file_action, NULL, NULL, 1);
     300                config_file_action, NULL, NULL,
     301                /*depth:*/ 0);
    335302}
    336303
     
    339306    /* probed_name may be NULL. modname always exists. */
    340307    return m->probed_name ? m->probed_name : m->modname;
     308}
     309
     310/* Like strsep(&stringp, "\n\t ") but quoted text goes to single token
     311 * even if it contains whitespace.
     312 */
     313static char *strsep_quotes(char **stringp)
     314{
     315    char *s, *start = *stringp;
     316
     317    if (!start)
     318        return NULL;
     319
     320    for (s = start; ; s++) {
     321        switch (*s) {
     322        case '"':
     323            s = strchrnul(s + 1, '"'); /* find trailing quote */
     324            if (*s != '\0')
     325                s++; /* skip trailing quote */
     326            /* fall through */
     327        case '\0':
     328        case '\n':
     329        case '\t':
     330        case ' ':
     331            if (*s != '\0') {
     332                *s = '\0';
     333                *stringp = s + 1;
     334            } else {
     335                *stringp = NULL;
     336            }
     337            return start;
     338        }
     339    }
    341340}
    342341
     
    346345    char *kcmdline;
    347346    char *kptr;
    348     int len;
    349347
    350348    kcmdline_buf = xmalloc_open_read_close("/proc/cmdline", NULL);
     
    353351
    354352    kcmdline = kcmdline_buf;
    355     len = strlen(modulename);
    356     while ((kptr = strsep(&kcmdline, "\n\t ")) != NULL) {
    357         if (strncmp(modulename, kptr, len) != 0)
    358             continue;
    359         kptr += len;
    360         if (*kptr != '.')
     353    while ((kptr = strsep_quotes(&kcmdline)) != NULL) {
     354        char *after_modulename = is_prefixed_with(kptr, modulename);
     355        if (!after_modulename || *after_modulename != '.')
    361356            continue;
    362357        /* It is "modulename.xxxx" */
    363         kptr++;
     358        kptr = after_modulename + 1;
    364359        if (strchr(kptr, '=') != NULL) {
    365360            /* It is "modulename.opt=[val]" */
     
    418413        rc = 0;
    419414        fn = llist_pop(&m->deps); /* we leak it */
    420         m2 = get_or_add_modentry(fn);
     415        m2 = get_or_add_modentry(bb_get_last_path_component_nostrip(fn));
    421416
    422417        if (option_mask32 & OPT_REMOVE) {
     
    426421                if (rc) {
    427422                    if (first) {
    428                         bb_error_msg("can't unload module %s: %s",
    429                             humanly_readable_name(m2),
    430                             moderror(rc));
     423                        bb_perror_msg("can't unload module '%s'",
     424                            humanly_readable_name(m2));
    431425                        break;
    432426                    }
     
    500494        if (colon == NULL)
    501495            continue;
    502         *colon = 0;
    503 
    504         m = get_modentry(tokens[0]);
     496        *colon = '\0';
     497
     498        m = moddb_get(&G.db, bb_get_last_path_component_nostrip(tokens[0]));
    505499        if (m == NULL)
    506500            continue;
     
    547541    if (opt & OPT_LIST_ONLY) {
    548542        int i;
    549         char name[MODULE_NAME_LEN];
    550543        char *colon, *tokens[2];
    551544        parser_t *p = config_open2(CONFIG_DEFAULT_DEPMOD_FILE, xfopen_for_read);
     
    559552                continue;
    560553            *colon = '\0';
    561             filename2modname(tokens[0], name);
    562554            if (!argv[0])
    563555                puts(tokens[0]);
    564556            else {
     557                char name[MODULE_NAME_LEN];
     558                filename2modname(
     559                    bb_get_last_path_component_nostrip(tokens[0]),
     560                    name
     561                );
    565562                for (i = 0; argv[i]; i++) {
    566563                    if (fnmatch(argv[i], name, 0) == 0) {
     
    584581             */
    585582            if (bb_delete_module(NULL, O_NONBLOCK | O_EXCL) != 0)
    586                 bb_perror_msg_and_die("rmmod");
     583                bb_perror_nomsg_and_die();
    587584        }
    588585        return EXIT_SUCCESS;
     
    660657    }
    661658
     659    if (ENABLE_FEATURE_CLEAN_UP)
     660        moddb_free(&G.db);
     661
    662662    return (rc != 0);
    663663}
  • branches/3.3/mindi-busybox/modutils/modutils-24.c

    r3232 r3621  
    22562256         * their references.
    22572257         */
    2258         if (strncmp((char *)s->name, "GPLONLY_", 8) == 0) {
     2258        if (is_prefixed_with((char *)s->name, "GPLONLY_")) {
    22592259#if ENABLE_FEATURE_CHECK_TAINTED_MODULE
    22602260            if (gpl)
  • branches/3.3/mindi-busybox/modutils/modutils.c

    r3232 r3621  
    1717#endif
    1818
     19static module_entry *helper_get_module(module_db *db, const char *module, int create)
     20{
     21    char modname[MODULE_NAME_LEN];
     22    struct module_entry *e;
     23    unsigned i, hash;
     24
     25    filename2modname(module, modname);
     26
     27    hash = 0;
     28    for (i = 0; modname[i]; i++)
     29        hash = ((hash << 5) + hash) + modname[i];
     30    hash %= MODULE_HASH_SIZE;
     31
     32    for (e = db->buckets[hash]; e; e = e->next)
     33        if (strcmp(e->modname, modname) == 0)
     34            return e;
     35    if (!create)
     36        return NULL;
     37
     38    e = xzalloc(sizeof(*e));
     39    e->modname = xstrdup(modname);
     40    e->next = db->buckets[hash];
     41    db->buckets[hash] = e;
     42    IF_DEPMOD(e->dnext = e->dprev = e;)
     43
     44    return e;
     45}
     46module_entry* FAST_FUNC moddb_get(module_db *db, const char *module)
     47{
     48    return helper_get_module(db, module, 0);
     49}
     50module_entry* FAST_FUNC moddb_get_or_create(module_db *db, const char *module)
     51{
     52    return helper_get_module(db, module, 1);
     53}
     54
     55void FAST_FUNC moddb_free(module_db *db)
     56{
     57    module_entry *e, *n;
     58    unsigned i;
     59
     60    for (i = 0; i < MODULE_HASH_SIZE; i++) {
     61        for (e = db->buckets[i]; e; e = n) {
     62            n = e->next;
     63            free(e->name);
     64            free(e->modname);
     65            free(e);
     66        }
     67    }
     68}
     69
    1970void FAST_FUNC replace(char *s, char what, char with)
    2071{
     
    4899char* FAST_FUNC filename2modname(const char *filename, char *modname)
    49100{
     101    char local_modname[MODULE_NAME_LEN];
    50102    int i;
    51     char *from;
     103    const char *from;
    52104
    53105    if (filename == NULL)
    54106        return NULL;
    55107    if (modname == NULL)
    56         modname = xmalloc(MODULE_NAME_LEN);
    57     from = bb_get_last_path_component_nostrip(filename);
     108        modname = local_modname;
     109    // Disabled since otherwise "modprobe dir/name" would work
     110    // as if it is "modprobe name". It is unclear why
     111    // 'basenamization' was here in the first place.
     112    //from = bb_get_last_path_component_nostrip(filename);
     113    from = filename;
    58114    for (i = 0; i < (MODULE_NAME_LEN-1) && from[i] != '\0' && from[i] != '.'; i++)
    59115        modname[i] = (from[i] == '-') ? '_' : from[i];
    60116    modname[i] = '\0';
     117
     118    if (modname == local_modname)
     119        return xstrdup(modname);
    61120
    62121    return modname;
     
    183242}
    184243
     244/* Note: not suitable for delete_module() errnos.
     245 * For them, probably only EWOULDBLOCK needs explaining:
     246 * "Other modules depend on us". So far we don't do such
     247 * translation and don't use moderror() for removal errors.
     248 */
    185249const char* FAST_FUNC moderror(int err)
    186250{
  • branches/3.3/mindi-busybox/modutils/modutils.h

    r3232 r3621  
    1717 * internally for the maximum alias name length, which can be quite long */
    1818#define MODULE_NAME_LEN 256
     19#define MODULE_HASH_SIZE 256
     20
     21typedef struct module_entry {
     22    struct module_entry *next;
     23    char *name, *modname;
     24    llist_t *deps;
     25    IF_MODPROBE(
     26        llist_t *realnames;
     27        unsigned flags;
     28        const char *probed_name; /* verbatim as seen on cmdline */
     29        char *options; /* options from config files */
     30    )
     31    IF_DEPMOD(
     32        llist_t *aliases;
     33        llist_t *symbols;
     34        struct module_entry *dnext, *dprev;
     35    )
     36} module_entry;
     37
     38typedef struct module_db {
     39    module_entry *buckets[MODULE_HASH_SIZE];
     40} module_db;
     41
     42#define moddb_foreach_module(db, module, index) \
     43    for ((index) = 0; (index) < MODULE_HASH_SIZE; (index)++) \
     44        for (module = (db)->buckets[index]; module; module = module->next)
     45
     46module_entry *moddb_get(module_db *db, const char *s) FAST_FUNC;
     47module_entry *moddb_get_or_create(module_db *db, const char *s) FAST_FUNC;
     48void moddb_free(module_db *db) FAST_FUNC;
    1949
    2050void replace(char *s, char what, char with) FAST_FUNC;
  • branches/3.3/mindi-busybox/modutils/rmmod.c

    r3232 r3621  
    2929int rmmod_main(int argc UNUSED_PARAM, char **argv)
    3030{
    31     int n;
     31    int n, err;
    3232    unsigned flags = O_NONBLOCK | O_EXCL;
    3333
     
    4141    if (n & 4) {
    4242        /* Unload _all_ unused modules via NULL delete_module() call */
    43         if (bb_delete_module(NULL, flags) != 0 && errno != EFAULT)
     43        err = bb_delete_module(NULL, flags);
     44        if (err && err != EFAULT)
    4445            bb_perror_msg_and_die("rmmod");
    4546        return EXIT_SUCCESS;
     
    5960        else
    6061            filename2modname(bname, modname);
    61         if (bb_delete_module(modname, flags))
    62             bb_error_msg_and_die("can't unload '%s': %s",
    63                     modname, moderror(errno));
     62        err = bb_delete_module(modname, flags);
     63        if (err)
     64            bb_perror_msg_and_die("can't unload module '%s'",
     65                    modname);
    6466    }
    6567
Note: See TracChangeset for help on using the changeset viewer.