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/modutils/modprobe.c

    r1765 r2725  
    33 * Modprobe written from scratch for BusyBox
    44 *
    5  * Copyright (c) 2002 by Robert Griebl, griebl@gmx.de
    6  * Copyright (c) 2003 by Andrew Dennison, andrew.dennison@motec.com.au
    7  * Copyright (c) 2005 by Jim Bauer, jfbauer@nfr.com
     5 * Copyright (c) 2008 Timo Teras <timo.teras@iki.fi>
     6 * Copyright (c) 2008 Vladimir Dronnikov
    87 *
    9  * Portions Copyright (c) 2005 by Yann E. MORIN, yann.morin.1998@anciens.enib.fr
    10  *
    11  * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
    12 */
     8 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
     9 */
     10
     11//applet:IF_MODPROBE(APPLET(modprobe, _BB_DIR_SBIN, _BB_SUID_DROP))
     12
     13//usage:#if !ENABLE_MODPROBE_SMALL
     14//usage:#define modprobe_notes_usage
     15//usage:    "modprobe can (un)load a stack of modules, passing each module options (when\n"
     16//usage:    "loading). modprobe uses a configuration file to determine what option(s) to\n"
     17//usage:    "pass each module it loads.\n"
     18//usage:    "\n"
     19//usage:    "The configuration file is searched (in this order):\n"
     20//usage:    "\n"
     21//usage:    "    /etc/modprobe.conf (2.6 only)\n"
     22//usage:    "    /etc/modules.conf\n"
     23//usage:    "    /etc/conf.modules (deprecated)\n"
     24//usage:    "\n"
     25//usage:    "They all have the same syntax (see below). If none is present, it is\n"
     26//usage:    "_not_ an error; each loaded module is then expected to load without\n"
     27//usage:    "options. Once a file is found, the others are tested for.\n"
     28//usage:    "\n"
     29//usage:    "/etc/modules.conf entry format:\n"
     30//usage:    "\n"
     31//usage:    "  alias <alias_name> <mod_name>\n"
     32//usage:    "    Makes it possible to modprobe alias_name, when there is no such module.\n"
     33//usage:    "    It makes sense if your mod_name is long, or you want a more representative\n"
     34//usage:    "    name for that module (eg. 'scsi' in place of 'aha7xxx').\n"
     35//usage:    "    This makes it also possible to use a different set of options (below) for\n"
     36//usage:    "    the module and the alias.\n"
     37//usage:    "    A module can be aliased more than once.\n"
     38//usage:    "\n"
     39//usage:    "  options <mod_name|alias_name> <symbol=value...>\n"
     40//usage:    "    When loading module mod_name (or the module aliased by alias_name), pass\n"
     41//usage:    "    the \"symbol=value\" pairs as option to that module.\n"
     42//usage:    "\n"
     43//usage:    "Sample /etc/modules.conf file:\n"
     44//usage:    "\n"
     45//usage:    "  options tulip irq=3\n"
     46//usage:    "  alias tulip tulip2\n"
     47//usage:    "  options tulip2 irq=4 io=0x308\n"
     48//usage:    "\n"
     49//usage:    "Other functionality offered by 'classic' modprobe is not available in\n"
     50//usage:    "this implementation.\n"
     51//usage:    "\n"
     52//usage:    "If module options are present both in the config file, and on the command line,\n"
     53//usage:    "then the options from the command line will be passed to the module _after_\n"
     54//usage:    "the options from the config file. That way, you can have defaults in the config\n"
     55//usage:    "file, and override them for a specific usage from the command line.\n"
     56//usage:#define modprobe_example_usage
     57//usage:       "(with the above /etc/modules.conf):\n\n"
     58//usage:       "$ modprobe tulip\n"
     59//usage:       "   will load the module 'tulip' with default option 'irq=3'\n\n"
     60//usage:       "$ modprobe tulip irq=5\n"
     61//usage:       "   will load the module 'tulip' with option 'irq=5', thus overriding the default\n\n"
     62//usage:       "$ modprobe tulip2\n"
     63//usage:       "   will load the module 'tulip' with default options 'irq=4 io=0x308',\n"
     64//usage:       "   which are the default for alias 'tulip2'\n\n"
     65//usage:       "$ modprobe tulip2 irq=8\n"
     66//usage:       "   will load the module 'tulip' with default options 'irq=4 io=0x308 irq=8',\n"
     67//usage:       "   which are the default for alias 'tulip2' overridden by the option 'irq=8'\n\n"
     68//usage:       "   from the command line\n\n"
     69//usage:       "$ modprobe tulip2 irq=2 io=0x210\n"
     70//usage:       "   will load the module 'tulip' with default options 'irq=4 io=0x308 irq=4 io=0x210',\n"
     71//usage:       "   which are the default for alias 'tulip2' overridden by the options 'irq=2 io=0x210'\n\n"
     72//usage:       "   from the command line\n"
     73//usage:
     74//usage:#define modprobe_trivial_usage
     75//usage:    "[-alrqvs"
     76//usage:    IF_FEATURE_MODPROBE_BLACKLIST("b")
     77//usage:    "] MODULE [symbol=value]..."
     78//usage:#define modprobe_full_usage "\n\n"
     79//usage:       "Options:"
     80//usage:     "\n    -a  Load multiple MODULEs"
     81//usage:     "\n    -l  List (MODULE is a pattern)"
     82//usage:     "\n    -r  Remove MODULE (stacks) or do autoclean"
     83//usage:     "\n    -q  Quiet"
     84//usage:     "\n    -v  Verbose"
     85//usage:     "\n    -s  Log to syslog"
     86//usage:    IF_FEATURE_MODPROBE_BLACKLIST(
     87//usage:     "\n    -b  Apply blacklist to module names too"
     88//usage:    )
     89//usage:#endif /* !ENABLE_MODPROBE_SMALL */
    1390
    1491#include "libbb.h"
     92#include "modutils.h"
    1593#include <sys/utsname.h>
    1694#include <fnmatch.h>
    1795
    18 struct mod_opt_t {  /* one-way list of options to pass to a module */
    19     char *  m_opt_val;
    20     struct mod_opt_t * m_next;
     96//#define DBG(fmt, ...) bb_error_msg("%s: " fmt, __func__, ## __VA_ARGS__)
     97#define DBG(...) ((void)0)
     98
     99/* Note that unlike older versions of modules.dep/depmod (busybox and m-i-t),
     100 * we expect the full dependency list to be specified in modules.dep.
     101 * Older versions would only export the direct dependency list.
     102 */
     103
     104/* Note that usage text doesn't document various 2.4 options
     105 * we pull in through INSMOD_OPTS define */
     106
     107#define MODPROBE_COMPLEMENTARY "q-v:v-q:l--ar:a--lr:r--al"
     108#define MODPROBE_OPTS  "alr" IF_FEATURE_MODPROBE_BLACKLIST("b")
     109//#define MODPROBE_COMPLEMENTARY "q-v:v-q:l--acr:a--lr:r--al"
     110//#define MODPROBE_OPTS  "acd:lnrt:C:" IF_FEATURE_MODPROBE_BLACKLIST("b")
     111enum {
     112    MODPROBE_OPT_INSERT_ALL = (INSMOD_OPT_UNUSED << 0), /* a */
     113    //MODPROBE_OPT_DUMP_ONLY= (INSMOD_OPT_UNUSED << x), /* c */
     114    //MODPROBE_OPT_DIRNAME  = (INSMOD_OPT_UNUSED << x), /* d */
     115    MODPROBE_OPT_LIST_ONLY  = (INSMOD_OPT_UNUSED << 1), /* l */
     116    //MODPROBE_OPT_SHOW_ONLY= (INSMOD_OPT_UNUSED << x), /* n */
     117    MODPROBE_OPT_REMOVE     = (INSMOD_OPT_UNUSED << 2), /* r */
     118    //MODPROBE_OPT_RESTRICT = (INSMOD_OPT_UNUSED << x), /* t */
     119    //MODPROBE_OPT_VERONLY  = (INSMOD_OPT_UNUSED << x), /* V */
     120    //MODPROBE_OPT_CONFIGFILE=(INSMOD_OPT_UNUSED << x), /* C */
     121    MODPROBE_OPT_BLACKLIST  = (INSMOD_OPT_UNUSED << 3) * ENABLE_FEATURE_MODPROBE_BLACKLIST,
    21122};
    22123
    23 struct dep_t {  /* one-way list of dependency rules */
    24     /* a dependency rule */
    25     char *  m_name;                         /* the module name*/
    26     char *  m_path;                         /* the module file path */
    27     struct mod_opt_t *  m_options;          /* the module options */
    28 
    29     int     m_isalias  : 1;                 /* the module is an alias */
    30     int     m_reserved : 15;                /* stuffin' */
    31 
    32     int     m_depcnt   : 16;                /* the number of dependable module(s) */
    33     char ** m_deparr;                       /* the list of dependable module(s) */
    34 
    35     struct dep_t * m_next;                  /* the next dependency rule */
     124#define MODULE_FLAG_LOADED              0x0001
     125#define MODULE_FLAG_NEED_DEPS           0x0002
     126/* "was seen in modules.dep": */
     127#define MODULE_FLAG_FOUND_IN_MODDEP     0x0004
     128#define MODULE_FLAG_BLACKLISTED         0x0008
     129
     130struct module_entry { /* I'll call it ME. */
     131    unsigned flags;
     132    char *modname; /* stripped of /path/, .ext and s/-/_/g */
     133    const char *probed_name; /* verbatim as seen on cmdline */
     134    char *options; /* options from config files */
     135    llist_t *realnames; /* strings. if this module is an alias, */
     136    /* real module name is one of these. */
     137//Can there really be more than one? Example from real kernel?
     138    llist_t *deps; /* strings. modules we depend on */
    36139};
    37140
    38 struct mod_list_t { /* two-way list of modules to process */
    39     /* a module description */
    40     const char * m_name;
    41     char * m_path;
    42     struct mod_opt_t * m_options;
    43 
    44     struct mod_list_t * m_prev;
    45     struct mod_list_t * m_next;
    46 };
    47 
    48 
    49 static struct dep_t *depend;
    50 
    51 #define main_options "acdklnqrst:vVC:"
    52 #define INSERT_ALL     1        /* a */
    53 #define DUMP_CONF_EXIT 2        /* c */
    54 #define D_OPT_IGNORED  4        /* d */
    55 #define AUTOCLEAN_FLG  8        /* k */
    56 #define LIST_ALL       16       /* l */
    57 #define SHOW_ONLY      32       /* n */
    58 #define QUIET          64       /* q */
    59 #define REMOVE_OPT     128      /* r */
    60 #define DO_SYSLOG      256      /* s */
    61 #define RESTRICT_DIR   512      /* t */
    62 #define VERBOSE        1024     /* v */
    63 #define VERSION_ONLY   2048     /* V */
    64 #define CONFIG_FILE    4096     /* C */
    65 
    66 #define autoclean       (main_opts & AUTOCLEAN_FLG)
    67 #define show_only       (main_opts & SHOW_ONLY)
    68 #define quiet           (main_opts & QUIET)
    69 #define remove_opt      (main_opts & REMOVE_OPT)
    70 #define do_syslog       (main_opts & DO_SYSLOG)
    71 #define verbose         (main_opts & VERBOSE)
    72 
    73 static int main_opts;
    74 
    75 static int parse_tag_value(char *buffer, char **ptag, char **pvalue)
    76 {
    77     char *tag, *value;
    78 
    79     buffer = skip_whitespace(buffer);
    80     tag = value = buffer;
    81     while (!isspace(*value))
    82         if (!*value) return 0;
    83         else value++;
    84     *value++ = 0;
    85     value = skip_whitespace(value);
    86     if (!*value) return 0;
    87 
    88     *ptag = tag;
    89     *pvalue = value;
    90 
    91     return 1;
    92 }
    93 
    94 /*
    95  * This function appends an option to a list
    96  */
    97 static struct mod_opt_t *append_option(struct mod_opt_t *opt_list, char *opt)
    98 {
    99     struct mod_opt_t *ol = opt_list;
    100 
    101     if (ol) {
    102         while (ol->m_next) {
    103             ol = ol->m_next;
    104         }
    105         ol->m_next = xmalloc(sizeof(struct mod_opt_t));
    106         ol = ol->m_next;
    107     } else {
    108         ol = opt_list = xmalloc(sizeof(struct mod_opt_t));
    109     }
    110 
    111     ol->m_opt_val = xstrdup(opt);
    112     ol->m_next = NULL;
    113 
    114     return opt_list;
    115 }
    116 
    117 #if ENABLE_FEATURE_MODPROBE_MULTIPLE_OPTIONS
    118 /* static char* parse_command_string(char* src, char **dst);
    119  *   src: pointer to string containing argument
    120  *   dst: pointer to where to store the parsed argument
    121  *   return value: the pointer to the first char after the parsed argument,
    122  *                 NULL if there was no argument parsed (only trailing spaces).
    123  *   Note that memory is allocated with xstrdup when a new argument was
    124  *   parsed. Don't forget to free it!
    125  */
    126 #define ARG_EMPTY      0x00
    127 #define ARG_IN_DQUOTES 0x01
    128 #define ARG_IN_SQUOTES 0x02
    129 static char *parse_command_string(char *src, char **dst)
    130 {
    131     int opt_status = ARG_EMPTY;
    132     char* tmp_str;
    133 
    134     /* Dumb you, I have nothing to do... */
    135     if (src == NULL) return src;
    136 
    137     /* Skip leading spaces */
    138     while (*src == ' ') {
    139         src++;
    140     }
    141     /* Is the end of string reached? */
    142     if (*src == '\0') {
     141struct globals {
     142    llist_t *db; /* MEs of all modules ever seen (caching for speed) */
     143    llist_t *probes; /* MEs of module(s) requested on cmdline */
     144    char *cmdline_mopts; /* module options from cmdline */
     145    int num_unresolved_deps;
     146    /* bool. "Did we have 'symbol:FOO' requested on cmdline?" */
     147    smallint need_symbols;
     148} FIX_ALIASING;
     149#define G (*(struct globals*)&bb_common_bufsiz1)
     150#define INIT_G() do { } while (0)
     151
     152
     153static int read_config(const char *path);
     154
     155static char *gather_options_str(char *opts, const char *append)
     156{
     157    /* Speed-optimized. We call gather_options_str many times. */
     158    if (append) {
     159        if (opts == NULL) {
     160            opts = xstrdup(append);
     161        } else {
     162            int optlen = strlen(opts);
     163            opts = xrealloc(opts, optlen + strlen(append) + 2);
     164            sprintf(opts + optlen, " %s", append);
     165        }
     166    }
     167    return opts;
     168}
     169
     170static struct module_entry *helper_get_module(const char *module, int create)
     171{
     172    char modname[MODULE_NAME_LEN];
     173    struct module_entry *e;
     174    llist_t *l;
     175
     176    filename2modname(module, modname);
     177    for (l = G.db; l != NULL; l = l->link) {
     178        e = (struct module_entry *) l->data;
     179        if (strcmp(e->modname, modname) == 0)
     180            return e;
     181    }
     182    if (!create)
    143183        return NULL;
    144     }
    145     /* Reached the start of an argument
    146      * By the way, we duplicate a little too much
    147      * here but what is too much is freed later. */
    148     *dst = tmp_str = xstrdup(src);
    149     /* Get to the end of that argument */
    150     while (*tmp_str != '\0'
    151      && (*tmp_str != ' ' || (opt_status & (ARG_IN_DQUOTES | ARG_IN_SQUOTES)))
     184
     185    e = xzalloc(sizeof(*e));
     186    e->modname = xstrdup(modname);
     187    llist_add_to(&G.db, e);
     188
     189    return e;
     190}
     191static struct module_entry *get_or_add_modentry(const char *module)
     192{
     193    return helper_get_module(module, 1);
     194}
     195static struct module_entry *get_modentry(const char *module)
     196{
     197    return helper_get_module(module, 0);
     198}
     199
     200static void add_probe(const char *name)
     201{
     202    struct module_entry *m;
     203
     204    m = get_or_add_modentry(name);
     205    if (!(option_mask32 & MODPROBE_OPT_REMOVE)
     206     && (m->flags & MODULE_FLAG_LOADED)
    152207    ) {
    153         switch (*tmp_str) {
    154         case '\'':
    155             if (opt_status & ARG_IN_DQUOTES) {
    156                 /* Already in double quotes, keep current char as is */
    157             } else {
    158                 /* shift left 1 char, until end of string: get rid of the opening/closing quotes */
    159                 memmove(tmp_str, tmp_str + 1, strlen(tmp_str));
    160                 /* mark me: we enter or leave single quotes */
    161                 opt_status ^= ARG_IN_SQUOTES;
    162                 /* Back one char, as we need to re-scan the new char there. */
    163                 tmp_str--;
    164             }
    165             break;
    166         case '"':
    167             if (opt_status & ARG_IN_SQUOTES) {
    168                 /* Already in single quotes, keep current char as is */
    169             } else {
    170                 /* shift left 1 char, until end of string: get rid of the opening/closing quotes */
    171                 memmove(tmp_str, tmp_str + 1, strlen(tmp_str));
    172                 /* mark me: we enter or leave double quotes */
    173                 opt_status ^= ARG_IN_DQUOTES;
    174                 /* Back one char, as we need to re-scan the new char there. */
    175                 tmp_str--;
    176             }
    177             break;
    178         case '\\':
    179             if (opt_status & ARG_IN_SQUOTES) {
    180                 /* Between single quotes: keep as is. */
    181             } else {
    182                 switch (*(tmp_str+1)) {
    183                 case 'a':
    184                 case 'b':
    185                 case 't':
    186                 case 'n':
    187                 case 'v':
    188                 case 'f':
    189                 case 'r':
    190                 case '0':
    191                     /* We escaped a special character. For now, keep
    192                      * both the back-slash and the following char. */
    193                     tmp_str++; src++;
    194                     break;
    195                 default:
    196                     /* We escaped a space or a single or double quote,
    197                      * or a back-slash, or a non-escapable char. Remove
    198                      * the '\' and keep the new current char as is. */
    199                     memmove(tmp_str, tmp_str + 1, strlen(tmp_str));
    200                     break;
     208        DBG("skipping %s, it is already loaded", name);
     209        return;
     210    }
     211
     212    DBG("queuing %s", name);
     213    m->probed_name = name;
     214    m->flags |= MODULE_FLAG_NEED_DEPS;
     215    llist_add_to_end(&G.probes, m);
     216    G.num_unresolved_deps++;
     217    if (ENABLE_FEATURE_MODUTILS_SYMBOLS
     218     && strncmp(m->modname, "symbol:", 7) == 0
     219    ) {
     220        G.need_symbols = 1;
     221    }
     222}
     223
     224static int FAST_FUNC config_file_action(const char *filename,
     225                    struct stat *statbuf UNUSED_PARAM,
     226                    void *userdata UNUSED_PARAM,
     227                    int depth UNUSED_PARAM)
     228{
     229    char *tokens[3];
     230    parser_t *p;
     231    struct module_entry *m;
     232    int rc = TRUE;
     233
     234    if (bb_basename(filename)[0] == '.')
     235        goto error;
     236
     237    p = config_open2(filename, fopen_for_read);
     238    if (p == NULL) {
     239        rc = FALSE;
     240        goto error;
     241    }
     242
     243    while (config_read(p, tokens, 3, 2, "# \t", PARSE_NORMAL)) {
     244//Use index_in_strings?
     245        if (strcmp(tokens[0], "alias") == 0) {
     246            /* alias <wildcard> <modulename> */
     247            llist_t *l;
     248            char wildcard[MODULE_NAME_LEN];
     249            char *rmod;
     250
     251            if (tokens[2] == NULL)
     252                continue;
     253            filename2modname(tokens[1], wildcard);
     254
     255            for (l = G.probes; l != NULL; l = l->link) {
     256                m = (struct module_entry *) l->data;
     257                if (fnmatch(wildcard, m->modname, 0) != 0)
     258                    continue;
     259                rmod = filename2modname(tokens[2], NULL);
     260                llist_add_to(&m->realnames, rmod);
     261
     262                if (m->flags & MODULE_FLAG_NEED_DEPS) {
     263                    m->flags &= ~MODULE_FLAG_NEED_DEPS;
     264                    G.num_unresolved_deps--;
     265                }
     266
     267                m = get_or_add_modentry(rmod);
     268                if (!(m->flags & MODULE_FLAG_NEED_DEPS)) {
     269                    m->flags |= MODULE_FLAG_NEED_DEPS;
     270                    G.num_unresolved_deps++;
    201271                }
    202272            }
     273        } else if (strcmp(tokens[0], "options") == 0) {
     274            /* options <modulename> <option...> */
     275            if (tokens[2] == NULL)
     276                continue;
     277            m = get_or_add_modentry(tokens[1]);
     278            m->options = gather_options_str(m->options, tokens[2]);
     279        } else if (strcmp(tokens[0], "include") == 0) {
     280            /* include <filename> */
     281            read_config(tokens[1]);
     282        } else if (ENABLE_FEATURE_MODPROBE_BLACKLIST
     283         && strcmp(tokens[0], "blacklist") == 0
     284        ) {
     285            /* blacklist <modulename> */
     286            get_or_add_modentry(tokens[1])->flags |= MODULE_FLAG_BLACKLISTED;
     287        }
     288    }
     289    config_close(p);
     290 error:
     291    return rc;
     292}
     293
     294static int read_config(const char *path)
     295{
     296    return recursive_action(path, ACTION_RECURSE | ACTION_QUIET,
     297                config_file_action, NULL, NULL, 1);
     298}
     299
     300static const char *humanly_readable_name(struct module_entry *m)
     301{
     302    /* probed_name may be NULL. modname always exists. */
     303    return m->probed_name ? m->probed_name : m->modname;
     304}
     305
     306static char *parse_and_add_kcmdline_module_options(char *options, const char *modulename)
     307{
     308    char *kcmdline_buf;
     309    char *kcmdline;
     310    char *kptr;
     311    int len;
     312
     313    kcmdline_buf = xmalloc_open_read_close("/proc/cmdline", NULL);
     314    if (!kcmdline_buf)
     315        return options;
     316
     317    kcmdline = kcmdline_buf;
     318    len = strlen(modulename);
     319    while ((kptr = strsep(&kcmdline, "\n\t ")) != NULL) {
     320        if (strncmp(modulename, kptr, len) != 0)
     321            continue;
     322        kptr += len;
     323        if (*kptr != '.')
     324            continue;
     325        /* It is "modulename.xxxx" */
     326        kptr++;
     327        if (strchr(kptr, '=') != NULL) {
     328            /* It is "modulename.opt=[val]" */
     329            options = gather_options_str(options, kptr);
     330        }
     331    }
     332    free(kcmdline_buf);
     333
     334    return options;
     335}
     336
     337/* Return: similar to bb_init_module:
     338 * 0 on success,
     339 * -errno on open/read error,
     340 * errno on init_module() error
     341 */
     342/* NB: INSMOD_OPT_SILENT bit suppresses ONLY non-existent modules,
     343 * not deleted ones (those are still listed in modules.dep).
     344 * module-init-tools version 3.4:
     345 * # modprobe bogus
     346 * FATAL: Module bogus not found. [exitcode 1]
     347 * # modprobe -q bogus            [silent, exitcode still 1]
     348 * but:
     349 * # rm kernel/drivers/net/dummy.ko
     350 * # modprobe -q dummy
     351 * FATAL: Could not open '/lib/modules/xxx/kernel/drivers/net/dummy.ko': No such file or directory
     352 * [exitcode 1]
     353 */
     354static int do_modprobe(struct module_entry *m)
     355{
     356    struct module_entry *m2 = m2; /* for compiler */
     357    char *fn, *options;
     358    int rc, first;
     359    llist_t *l;
     360
     361    if (!(m->flags & MODULE_FLAG_FOUND_IN_MODDEP)) {
     362        if (!(option_mask32 & INSMOD_OPT_SILENT))
     363            bb_error_msg("module %s not found in modules.dep",
     364                humanly_readable_name(m));
     365        return -ENOENT;
     366    }
     367    DBG("do_modprob'ing %s", m->modname);
     368
     369    if (!(option_mask32 & MODPROBE_OPT_REMOVE))
     370        m->deps = llist_rev(m->deps);
     371
     372    for (l = m->deps; l != NULL; l = l->link)
     373        DBG("dep: %s", l->data);
     374
     375    first = 1;
     376    rc = 0;
     377    while (m->deps) {
     378        rc = 0;
     379        fn = llist_pop(&m->deps); /* we leak it */
     380        m2 = get_or_add_modentry(fn);
     381
     382        if (option_mask32 & MODPROBE_OPT_REMOVE) {
     383            /* modprobe -r */
     384            if (m2->flags & MODULE_FLAG_LOADED) {
     385                rc = bb_delete_module(m2->modname, O_EXCL);
     386                if (rc) {
     387                    if (first) {
     388                        bb_error_msg("can't unload module %s: %s",
     389                            humanly_readable_name(m2),
     390                            moderror(rc));
     391                        break;
     392                    }
     393                } else {
     394                    m2->flags &= ~MODULE_FLAG_LOADED;
     395                }
     396            }
     397            /* do not error out if *deps* fail to unload */
     398            first = 0;
     399            continue;
     400        }
     401
     402        if (m2->flags & MODULE_FLAG_LOADED) {
     403            DBG("%s is already loaded, skipping", fn);
     404            continue;
     405        }
     406
     407        options = m2->options;
     408        m2->options = NULL;
     409        options = parse_and_add_kcmdline_module_options(options, m2->modname);
     410        if (m == m2)
     411            options = gather_options_str(options, G.cmdline_mopts);
     412        rc = bb_init_module(fn, options);
     413        DBG("loaded %s '%s', rc:%d", fn, options, rc);
     414        if (rc == EEXIST)
     415            rc = 0;
     416        free(options);
     417        if (rc) {
     418            bb_error_msg("can't load module %s (%s): %s",
     419                humanly_readable_name(m2),
     420                fn,
     421                moderror(rc)
     422            );
    203423            break;
    204         /* Any other char that is special shall appear here.
    205          * Example: $ starts a variable
    206         case '$':
    207             do_variable_expansion();
    208             break;
    209          * */
    210         default:
    211             /* any other char is kept as is. */
    212             break;
    213         }
    214         tmp_str++; /* Go to next char */
    215         src++; /* Go to next char to find the end of the argument. */
    216     }
    217     /* End of string, but still no ending quote */
    218     if (opt_status & (ARG_IN_DQUOTES | ARG_IN_SQUOTES)) {
    219         bb_error_msg_and_die("unterminated (single or double) quote in options list: %s", src);
    220     }
    221     *tmp_str++ = '\0';
    222     *dst = xrealloc(*dst, (tmp_str - *dst));
    223     return src;
    224 }
    225 #else
    226 #define parse_command_string(src, dst)  (0)
    227 #endif /* ENABLE_FEATURE_MODPROBE_MULTIPLE_OPTIONS */
    228 
    229 /*
    230  * This function reads aliases and default module options from a configuration file
    231  * (/etc/modprobe.conf syntax). It supports includes (only files, no directories).
    232  */
    233 static void include_conf(struct dep_t **first, struct dep_t **current, char *buffer, int buflen, int fd)
    234 {
    235     int continuation_line = 0;
    236 
    237     // alias parsing is not 100% correct (no correct handling of continuation lines within an alias)!
    238 
    239     while (reads(fd, buffer, buflen)) {
    240         int l;
    241         char *p;
    242 
    243         p = strchr(buffer, '#');
    244         if (p)
    245             *p = 0;
    246 
    247         l = strlen(buffer);
    248 
    249         while (l && isspace(buffer[l-1])) {
    250             buffer[l-1] = 0;
    251             l--;
    252         }
    253 
    254         if (l == 0) {
    255             continuation_line = 0;
    256             continue;
    257         }
    258 
    259         if (!continuation_line) {
    260             if ((strncmp(buffer, "alias", 5) == 0) && isspace(buffer[5])) {
    261                 char *alias, *mod;
    262 
    263                 if (parse_tag_value(buffer + 6, &alias, &mod)) {
    264                     /* handle alias as a module dependent on the aliased module */
    265                     if (!*current) {
    266                         (*first) = (*current) = xzalloc(sizeof(struct dep_t));
    267                     } else {
    268                         (*current)->m_next = xzalloc(sizeof(struct dep_t));
    269                         (*current) = (*current)->m_next;
    270                     }
    271                     (*current)->m_name  = xstrdup(alias);
    272                     (*current)->m_isalias = 1;
    273 
    274                     if ((strcmp(mod, "off") == 0) || (strcmp(mod, "null") == 0)) {
    275                         (*current)->m_depcnt = 0;
    276                         (*current)->m_deparr = 0;
    277                     } else {
    278                         (*current)->m_depcnt  = 1;
    279                         (*current)->m_deparr  = xmalloc(1 * sizeof(char *));
    280                         (*current)->m_deparr[0] = xstrdup(mod);
    281                     }
    282                     (*current)->m_next    = 0;
    283                 }
    284             } else if ((strncmp(buffer, "options", 7) == 0) && isspace(buffer[7])) {
    285                 char *mod, *opt;
    286 
    287                 /* split the line in the module/alias name, and options */
    288                 if (parse_tag_value(buffer + 8, &mod, &opt)) {
    289                     struct dep_t *dt;
    290 
    291                     /* find the corresponding module */
    292                     for (dt = *first; dt; dt = dt->m_next) {
    293                         if (strcmp(dt->m_name, mod) == 0)
    294                             break;
    295                     }
    296                     if (dt) {
    297                         if (ENABLE_FEATURE_MODPROBE_MULTIPLE_OPTIONS) {
    298                             char* new_opt = NULL;
    299                             while ((opt = parse_command_string(opt, &new_opt))) {
    300                                 dt->m_options = append_option(dt->m_options, new_opt);
    301                             }
    302                         } else {
    303                             dt->m_options = append_option(dt->m_options, opt);
    304                         }
     424        }
     425        m2->flags |= MODULE_FLAG_LOADED;
     426    }
     427
     428    return rc;
     429}
     430
     431static void load_modules_dep(void)
     432{
     433    struct module_entry *m;
     434    char *colon, *tokens[2];
     435    parser_t *p;
     436
     437    /* Modprobe does not work at all without modules.dep,
     438     * even if the full module name is given. Returning error here
     439     * was making us later confuse user with this message:
     440     * "module /full/path/to/existing/file/module.ko not found".
     441     * It's better to die immediately, with good message.
     442     * xfopen_for_read provides that. */
     443    p = config_open2(CONFIG_DEFAULT_DEPMOD_FILE, xfopen_for_read);
     444
     445    while (G.num_unresolved_deps
     446     && config_read(p, tokens, 2, 1, "# \t", PARSE_NORMAL)
     447    ) {
     448        colon = last_char_is(tokens[0], ':');
     449        if (colon == NULL)
     450            continue;
     451        *colon = 0;
     452
     453        m = get_modentry(tokens[0]);
     454        if (m == NULL)
     455            continue;
     456
     457        /* Optimization... */
     458        if ((m->flags & MODULE_FLAG_LOADED)
     459         && !(option_mask32 & MODPROBE_OPT_REMOVE)
     460        ) {
     461            DBG("skip deps of %s, it's already loaded", tokens[0]);
     462            continue;
     463        }
     464
     465        m->flags |= MODULE_FLAG_FOUND_IN_MODDEP;
     466        if ((m->flags & MODULE_FLAG_NEED_DEPS) && (m->deps == NULL)) {
     467            G.num_unresolved_deps--;
     468            llist_add_to(&m->deps, xstrdup(tokens[0]));
     469            if (tokens[1])
     470                string_to_llist(tokens[1], &m->deps, " \t");
     471        } else
     472            DBG("skipping dep line");
     473    }
     474    config_close(p);
     475}
     476
     477int modprobe_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
     478int modprobe_main(int argc UNUSED_PARAM, char **argv)
     479{
     480    struct utsname uts;
     481    int rc;
     482    unsigned opt;
     483    struct module_entry *me;
     484
     485    opt_complementary = MODPROBE_COMPLEMENTARY;
     486    opt = getopt32(argv, INSMOD_OPTS MODPROBE_OPTS INSMOD_ARGS);
     487    argv += optind;
     488
     489    /* Goto modules location */
     490    xchdir(CONFIG_DEFAULT_MODULES_DIR);
     491    uname(&uts);
     492    xchdir(uts.release);
     493
     494    if (opt & MODPROBE_OPT_LIST_ONLY) {
     495        char name[MODULE_NAME_LEN];
     496        char *colon, *tokens[2];
     497        parser_t *p = config_open2(CONFIG_DEFAULT_DEPMOD_FILE, xfopen_for_read);
     498
     499        while (config_read(p, tokens, 2, 1, "# \t", PARSE_NORMAL)) {
     500            colon = last_char_is(tokens[0], ':');
     501            if (!colon)
     502                continue;
     503            *colon = '\0';
     504            filename2modname(tokens[0], name);
     505            if (!argv[0])
     506                puts(tokens[0]);
     507            else {
     508                int i;
     509                for (i = 0; argv[i]; i++) {
     510                    if (fnmatch(argv[i], name, 0) == 0) {
     511                        puts(tokens[0]);
    305512                    }
    306513                }
    307             } else if ((strncmp(buffer, "include", 7) == 0) && isspace(buffer[7])) {
    308                 int fdi; char *filename;
    309 
    310                 filename = skip_whitespace(buffer + 8);
    311 
    312                 if ((fdi = open(filename, O_RDONLY)) >= 0) {
    313                     include_conf(first, current, buffer, buflen, fdi);
    314                     close(fdi);
    315                 }
    316514            }
    317515        }
    318     }
    319 }
    320 
    321 /*
    322  * This function builds a list of dependency rules from /lib/modules/`uname -r`/modules.dep.
    323  * It then fills every modules and aliases with their default options, found by parsing
    324  * modprobe.conf (or modules.conf, or conf.modules).
    325  */
    326 static struct dep_t *build_dep(void)
    327 {
    328     int fd;
    329     struct utsname un;
    330     struct dep_t *first = 0;
    331     struct dep_t *current = 0;
    332     char buffer[2048];
    333     char *filename;
    334     int continuation_line = 0;
    335     int k_version;
    336 
    337     if (uname(&un))
    338         bb_error_msg_and_die("can't determine kernel version");
    339 
    340     k_version = 0;
    341     if (un.release[0] == '2') {
    342         k_version = un.release[2] - '0';
    343     }
    344 
    345     filename = xasprintf("/lib/modules/%s/modules.dep", un.release);
    346     fd = open(filename, O_RDONLY);
    347     if (ENABLE_FEATURE_CLEAN_UP)
    348         free(filename);
    349     if (fd < 0) {
    350         /* Ok, that didn't work.  Fall back to looking in /lib/modules */
    351         fd = open("/lib/modules/modules.dep", O_RDONLY);
    352         if (fd < 0) {
    353             return 0;
    354         }
    355     }
    356 
    357     while (reads(fd, buffer, sizeof(buffer))) {
    358         int l = strlen(buffer);
    359         char *p = 0;
    360 
    361         while (l > 0 && isspace(buffer[l-1])) {
    362             buffer[l-1] = 0;
    363             l--;
    364         }
    365 
    366         if (l == 0) {
    367             continuation_line = 0;
    368             continue;
    369         }
    370 
    371         /* Is this a new module dep description? */
    372         if (!continuation_line) {
    373             /* find the dep beginning */
    374             char *col = strchr(buffer, ':');
    375             char *dot = col;
    376 
    377             if (col) {
    378                 /* This line is a dep description */
    379                 const char *mods;
    380                 char *modpath;
    381                 char *mod;
    382 
    383                 /* Find the beginning of the module file name */
    384                 *col = 0;
    385                 mods = bb_basename(buffer);
    386 
    387                 /* find the path of the module */
    388                 modpath = strchr(buffer, '/'); /* ... and this is the path */
    389                 if (!modpath)
    390                     modpath = buffer; /* module with no path */
    391                 /* find the end of the module name in the file name */
    392                 if (ENABLE_FEATURE_2_6_MODULES &&
    393                      (k_version > 4) && (*(col-3) == '.') &&
    394                     (*(col-2) == 'k') && (*(col-1) == 'o'))
    395                     dot = col - 3;
    396                 else
    397                     if ((*(col-2) == '.') && (*(col-1) == 'o'))
    398                         dot = col - 2;
    399 
    400                 mod = xstrndup(mods, dot - mods);
    401 
    402                 /* enqueue new module */
    403                 if (!current) {
    404                     first = current = xmalloc(sizeof(struct dep_t));
    405                 } else {
    406                     current->m_next = xmalloc(sizeof(struct dep_t));
    407                     current = current->m_next;
    408                 }
    409                 current->m_name    = mod;
    410                 current->m_path    = xstrdup(modpath);
    411                 current->m_options = NULL;
    412                 current->m_isalias = 0;
    413                 current->m_depcnt  = 0;
    414                 current->m_deparr  = 0;
    415                 current->m_next    = 0;
    416 
    417                 p = col + 1;
    418             } else
    419                 /* this line is not a dep description */
    420                 p = 0;
    421         } else
    422             /* It's a dep description continuation */
    423             p = buffer;
    424 
    425         while (p && *p && isblank(*p))
    426             p++;
    427 
    428         /* p points to the first dependable module; if NULL, no dependable module */
    429         if (p && *p) {
    430             char *end = &buffer[l-1];
    431             const char *deps;
    432             char *dep;
    433             char *next;
    434             int ext = 0;
    435 
    436             while (isblank(*end) || (*end == '\\'))
    437                 end--;
    438 
    439             do {
    440                 /* search the end of the dependency */
    441                 next = strchr(p, ' ');
    442                 if (next) {
    443                     *next = 0;
    444                     next--;
    445                 } else
    446                     next = end;
    447 
    448                 /* find the beginning of the module file name */
    449                 deps = bb_basename(p);
    450                 if (deps == p) {
    451                     while (isblank(*deps))
    452                         deps++;
    453                 }
    454 
    455                 /* find the end of the module name in the file name */
    456                 if (ENABLE_FEATURE_2_6_MODULES
    457                  && (k_version > 4) && (*(next-2) == '.')
    458                  && (*(next-1) == 'k') && (*next == 'o'))
    459                     ext = 3;
    460                 else
    461                     if ((*(next-1) == '.') && (*next == 'o'))
    462                         ext = 2;
    463 
    464                 /* Cope with blank lines */
    465                 if ((next-deps-ext+1) <= 0)
    466                     continue;
    467                 dep = xstrndup(deps, next - deps - ext + 1);
    468 
    469                 /* Add the new dependable module name */
    470                 current->m_depcnt++;
    471                 current->m_deparr = xrealloc(current->m_deparr,
    472                         sizeof(char *) * current->m_depcnt);
    473                 current->m_deparr[current->m_depcnt - 1] = dep;
    474 
    475                 p = next + 2;
    476             } while (next < end);
    477         }
    478 
    479         /* is there other dependable module(s) ? */
    480         if (buffer[l-1] == '\\')
    481             continuation_line = 1;
    482         else
    483             continuation_line = 0;
    484     }
    485     close(fd);
    486 
    487     /*
    488      * First parse system-specific options and aliases
    489      * as they take precedence over the kernel ones.
    490      * >=2.6: we only care about modprobe.conf
    491      * <=2.4: we care about modules.conf and conf.modules
    492      */
    493     if (ENABLE_FEATURE_2_6_MODULES
    494      && (fd = open("/etc/modprobe.conf", O_RDONLY)) < 0)
    495         if (ENABLE_FEATURE_2_4_MODULES
    496          && (fd = open("/etc/modules.conf", O_RDONLY)) < 0)
    497             if (ENABLE_FEATURE_2_4_MODULES)
    498                 fd = open("/etc/conf.modules", O_RDONLY);
    499 
    500     if (fd >= 0) {
    501         include_conf(&first, &current, buffer, sizeof(buffer), fd);
    502         close(fd);
    503     }
    504 
    505     /* Only 2.6 has a modules.alias file */
    506     if (ENABLE_FEATURE_2_6_MODULES) {
    507         /* Parse kernel-declared module aliases */
    508         filename = xasprintf("/lib/modules/%s/modules.alias", un.release);
    509         fd = open(filename, O_RDONLY);
    510         if (fd < 0) {
    511             /* Ok, that didn't work.  Fall back to looking in /lib/modules */
    512             fd = open("/lib/modules/modules.alias", O_RDONLY);
    513         }
    514         if (ENABLE_FEATURE_CLEAN_UP)
    515             free(filename);
    516 
    517         if (fd >= 0) {
    518             include_conf(&first, &current, buffer, sizeof(buffer), fd);
    519             close(fd);
    520         }
    521 
    522         /* Parse kernel-declared symbol aliases */
    523         filename = xasprintf("/lib/modules/%s/modules.symbols", un.release);
    524         fd = open(filename, O_RDONLY);
    525         if (fd < 0) {
    526             /* Ok, that didn't work.  Fall back to looking in /lib/modules */
    527             fd = open("/lib/modules/modules.symbols", O_RDONLY);
    528         }
    529         if (ENABLE_FEATURE_CLEAN_UP)
    530             free(filename);
    531 
    532         if (fd >= 0) {
    533             include_conf(&first, &current, buffer, sizeof(buffer), fd);
    534             close(fd);
    535         }
    536     }
    537 
    538     return first;
    539 }
    540 
    541 /* return 1 = loaded, 0 = not loaded, -1 = can't tell */
    542 static int already_loaded(const char *name)
    543 {
    544     int fd, ret = 0;
    545     char buffer[4096];
    546 
    547     fd = open("/proc/modules", O_RDONLY);
    548     if (fd < 0)
    549         return -1;
    550 
    551     while (reads(fd, buffer, sizeof(buffer))) {
    552         char *p;
    553 
    554         p = strchr (buffer, ' ');
    555         if (p) {
    556             const char *n;
    557 
    558             // Truncate buffer at first space and check for matches, with
    559             // the idiosyncrasy that _ and - are interchangeable because the
    560             // 2.6 kernel does weird things.
    561 
    562             *p = 0;
    563             for (p = buffer, n = name; ; p++, n++) {
    564                 if (*p != *n) {
    565                     if ((*p == '_' || *p == '-') && (*n == '_' || *n == '-'))
    566                         continue;
    567                     break;
    568                 }
    569                 // If we made it to the end, that's a match.
    570                 if (!*p) {
    571                     ret = 1;
    572                     goto done;
    573                 }
     516        return EXIT_SUCCESS;
     517    }
     518
     519    /* Yes, for some reason -l ignores -s... */
     520    if (opt & INSMOD_OPT_SYSLOG)
     521        logmode = LOGMODE_SYSLOG;
     522
     523    if (!argv[0]) {
     524        if (opt & MODPROBE_OPT_REMOVE) {
     525            /* "modprobe -r" (w/o params).
     526             * "If name is NULL, all unused modules marked
     527             * autoclean will be removed".
     528             */
     529            if (bb_delete_module(NULL, O_NONBLOCK | O_EXCL) != 0)
     530                bb_perror_msg_and_die("rmmod");
     531        }
     532        return EXIT_SUCCESS;
     533    }
     534
     535    /* Retrieve module names of already loaded modules */
     536    {
     537        char *s;
     538        parser_t *parser = config_open2("/proc/modules", fopen_for_read);
     539        while (config_read(parser, &s, 1, 1, "# \t", PARSE_NORMAL & ~PARSE_GREEDY))
     540            get_or_add_modentry(s)->flags |= MODULE_FLAG_LOADED;
     541        config_close(parser);
     542    }
     543
     544    if (opt & (MODPROBE_OPT_INSERT_ALL | MODPROBE_OPT_REMOVE)) {
     545        /* Each argument is a module name */
     546        do {
     547            DBG("adding module %s", *argv);
     548            add_probe(*argv++);
     549        } while (*argv);
     550    } else {
     551        /* First argument is module name, rest are parameters */
     552        DBG("probing just module %s", *argv);
     553        add_probe(argv[0]);
     554        G.cmdline_mopts = parse_cmdline_module_options(argv);
     555    }
     556
     557    /* Happens if all requested modules are already loaded */
     558    if (G.probes == NULL)
     559        return EXIT_SUCCESS;
     560
     561    read_config("/etc/modprobe.conf");
     562    read_config("/etc/modprobe.d");
     563    if (ENABLE_FEATURE_MODUTILS_SYMBOLS && G.need_symbols)
     564        read_config("modules.symbols");
     565    load_modules_dep();
     566    if (ENABLE_FEATURE_MODUTILS_ALIAS && G.num_unresolved_deps) {
     567        read_config("modules.alias");
     568        load_modules_dep();
     569    }
     570
     571    rc = 0;
     572    while ((me = llist_pop(&G.probes)) != NULL) {
     573        if (me->realnames == NULL) {
     574            DBG("probing by module name");
     575            /* This is not an alias. Literal names are blacklisted
     576             * only if '-b' is given.
     577             */
     578            if (!(opt & MODPROBE_OPT_BLACKLIST)
     579             || !(me->flags & MODULE_FLAG_BLACKLISTED)
     580            ) {
     581                rc |= do_modprobe(me);
    574582            }
    575         }
    576     }
    577 done:
    578     close (fd);
    579     return ret;
    580 }
    581 
    582 static int mod_process(const struct mod_list_t *list, int do_insert)
    583 {
    584     int rc = 0;
    585     char **argv = NULL;
    586     struct mod_opt_t *opts;
    587     int argc_malloc; /* never used when CONFIG_FEATURE_CLEAN_UP not defined */
    588     int argc;
    589 
    590     while (list) {
    591         argc = 0;
    592         if (ENABLE_FEATURE_CLEAN_UP)
    593             argc_malloc = 0;
    594         /* If CONFIG_FEATURE_CLEAN_UP is not defined, then we leak memory
    595          * each time we allocate memory for argv.
    596          * But it is (quite) small amounts of memory that leak each
    597          * time a module is loaded,  and it is reclaimed when modprobe
    598          * exits anyway (even when standalone shell?).
    599          * This could become a problem when loading a module with LOTS of
    600          * dependencies, with LOTS of options for each dependencies, with
    601          * very little memory on the target... But in that case, the module
    602          * would not load because there is no more memory, so there's no
    603          * problem. */
    604         /* enough for minimal insmod (5 args + NULL) or rmmod (3 args + NULL) */
    605         argv = xmalloc(6 * sizeof(char*));
    606         if (do_insert) {
    607             if (already_loaded(list->m_name) != 1) {
    608                 argv[argc++] = (char*)"insmod";
    609                 if (ENABLE_FEATURE_2_4_MODULES) {
    610                     if (do_syslog)
    611                         argv[argc++] = (char*)"-s";
    612                     if (autoclean)
    613                         argv[argc++] = (char*)"-k";
    614                     if (quiet)
    615                         argv[argc++] = (char*)"-q";
    616                     else if (verbose) /* verbose and quiet are mutually exclusive */
    617                         argv[argc++] = (char*)"-v";
    618                 }
    619                 argv[argc++] = list->m_path;
    620                 if (ENABLE_FEATURE_CLEAN_UP)
    621                     argc_malloc = argc;
    622                 opts = list->m_options;
    623                 while (opts) {
    624                     /* Add one more option */
    625                     argc++;
    626                     argv = xrealloc(argv,(argc + 1)* sizeof(char*));
    627                     argv[argc-1] = opts->m_opt_val;
    628                     opts = opts->m_next;
    629                 }
     583            continue;
     584        }
     585
     586        /* Probe all real names for the alias */
     587        do {
     588            char *realname = llist_pop(&me->realnames);
     589            struct module_entry *m2;
     590
     591            DBG("probing alias %s by realname %s", me->modname, realname);
     592            m2 = get_or_add_modentry(realname);
     593            if (!(m2->flags & MODULE_FLAG_BLACKLISTED)
     594             && (!(m2->flags & MODULE_FLAG_LOADED)
     595                || (opt & MODPROBE_OPT_REMOVE))
     596            ) {
     597//TODO: we can pass "me" as 2nd param to do_modprobe,
     598//and make do_modprobe emit more meaningful error messages
     599//with alias name included, not just module name alias resolves to.
     600                rc |= do_modprobe(m2);
    630601            }
    631         } else {
    632             /* modutils uses short name for removal */
    633             if (already_loaded(list->m_name) != 0) {
    634                 argv[argc++] = (char*)"rmmod";
    635                 if (do_syslog)
    636                     argv[argc++] = (char*)"-s";
    637                 argv[argc++] = (char*)list->m_name;
    638                 if (ENABLE_FEATURE_CLEAN_UP)
    639                     argc_malloc = argc;
    640             }
    641         }
    642         argv[argc] = NULL;
    643 
    644         if (argc) {
    645             if (verbose) {
    646                 printf("%s module %s\n", do_insert?"Loading":"Unloading", list->m_name);
    647             }
    648             if (!show_only) {
    649                 int rc2 = wait4pid(spawn(argv));
    650 
    651                 if (do_insert) {
    652                     rc = rc2; /* only last module matters */
    653                 } else if (!rc2) {
    654                     rc = 0; /* success if remove any mod */
    655                 }
    656             }
    657             if (ENABLE_FEATURE_CLEAN_UP) {
    658                 /* the last value in the array has index == argc, but
    659                  * it is the terminating NULL, so we must not free it. */
    660                 while (argc_malloc < argc) {
    661                     free(argv[argc_malloc++]);
    662                 }
    663             }
    664         }
    665         if (ENABLE_FEATURE_CLEAN_UP) {
    666             free(argv);
    667             argv = NULL;
    668         }
    669         list = do_insert ? list->m_prev : list->m_next;
    670     }
    671     return (show_only) ? 0 : rc;
    672 }
    673 
    674 /*
    675  * Check the matching between a pattern and a module name.
    676  * We need this as *_* is equivalent to *-*, even in pattern matching.
    677  */
    678 static int check_pattern(const char* pat_src, const char* mod_src)
    679 {
    680     int ret;
    681 
    682     if (ENABLE_FEATURE_MODPROBE_FANCY_ALIAS) {
    683         char* pat;
    684         char* mod;
    685         char* p;
    686 
    687         pat = xstrdup(pat_src);
    688         mod = xstrdup(mod_src);
    689 
    690         for (p = pat; (p = strchr(p, '-')); *p++ = '_');
    691         for (p = mod; (p = strchr(p, '-')); *p++ = '_');
    692 
    693         ret = fnmatch(pat, mod, 0);
    694 
    695         if (ENABLE_FEATURE_CLEAN_UP) {
    696             free(pat);
    697             free(mod);
    698         }
    699 
    700         return ret;
    701     } else {
    702         return fnmatch(pat_src, mod_src, 0);
    703     }
    704 }
    705 
    706 /*
    707  * Builds the dependency list (aka stack) of a module.
    708  * head: the highest module in the stack (last to insmod, first to rmmod)
    709  * tail: the lowest module in the stack (first to insmod, last to rmmod)
    710  */
    711 static void check_dep(char *mod, struct mod_list_t **head, struct mod_list_t **tail)
    712 {
    713     struct mod_list_t *find;
    714     struct dep_t *dt;
    715     struct mod_opt_t *opt = 0;
    716     char *path = 0;
    717 
    718     /* Search for the given module name amongst all dependency rules.
    719      * The module name in a dependency rule can be a shell pattern,
    720      * so try to match the given module name against such a pattern.
    721      * Of course if the name in the dependency rule is a plain string,
    722      * then we consider it a pattern, and matching will still work. */
    723     for (dt = depend; dt; dt = dt->m_next) {
    724         if (check_pattern(dt->m_name, mod) == 0) {
    725             break;
    726         }
    727     }
    728 
    729     if (!dt) {
    730         bb_error_msg("module %s not found", mod);
    731         return;
    732     }
    733 
    734     // resolve alias names
    735     while (dt->m_isalias) {
    736         if (dt->m_depcnt == 1) {
    737             struct dep_t *adt;
    738 
    739             for (adt = depend; adt; adt = adt->m_next) {
    740                 if (check_pattern(adt->m_name, dt->m_deparr[0]) == 0)
    741                     break;
    742             }
    743             if (adt) {
    744                 /* This is the module we are aliased to */
    745                 struct mod_opt_t *opts = dt->m_options;
    746                 /* Option of the alias are appended to the options of the module */
    747                 while (opts) {
    748                     adt->m_options = append_option(adt->m_options, opts->m_opt_val);
    749                     opts = opts->m_next;
    750                 }
    751                 dt = adt;
    752             } else {
    753                 bb_error_msg("module %s not found", mod);
    754                 return;
    755             }
    756         } else {
    757             bb_error_msg("bad alias %s", dt->m_name);
    758             return;
    759         }
    760     }
    761 
    762     mod = dt->m_name;
    763     path = dt->m_path;
    764     opt = dt->m_options;
    765 
    766     // search for duplicates
    767     for (find = *head; find; find = find->m_next) {
    768         if (!strcmp(mod, find->m_name)) {
    769             // found ->dequeue it
    770 
    771             if (find->m_prev)
    772                 find->m_prev->m_next = find->m_next;
    773             else
    774                 *head = find->m_next;
    775 
    776             if (find->m_next)
    777                 find->m_next->m_prev = find->m_prev;
    778             else
    779                 *tail = find->m_prev;
    780 
    781             break; // there can be only one duplicate
    782         }
    783     }
    784 
    785     if (!find) { // did not find a duplicate
    786         find = xmalloc(sizeof(struct mod_list_t));
    787         find->m_name = mod;
    788         find->m_path = path;
    789         find->m_options = opt;
    790     }
    791 
    792     // enqueue at tail
    793     if (*tail)
    794         (*tail)->m_next = find;
    795     find->m_prev = *tail;
    796     find->m_next = 0;
    797 
    798     if (!*head)
    799         *head = find;
    800     *tail = find;
    801 
    802     if (dt) {
    803         int i;
    804 
    805         /* Add all dependable module for that new module */
    806         for (i = 0; i < dt->m_depcnt; i++)
    807             check_dep(dt->m_deparr[i], head, tail);
    808     }
    809 }
    810 
    811 static int mod_insert(char *mod, int argc, char **argv)
    812 {
    813     struct mod_list_t *tail = NULL;
    814     struct mod_list_t *head = NULL;
    815     int rc;
    816 
    817     // get dep list for module mod
    818     check_dep(mod, &head, &tail);
    819 
    820     rc = 1;
    821     if (head && tail) {
    822         if (argc) {
    823             int i;
    824             // append module args
    825             for (i = 0; i < argc; i++)
    826                 head->m_options = append_option(head->m_options, argv[i]);
    827         }
    828 
    829         // process tail ---> head
    830         rc = mod_process(tail, 1);
    831         if (rc) {
    832             /*
    833              * In case of using udev, multiple instances of modprobe can be
    834              * spawned to load the same module (think of two same usb devices,
    835              * for example; or cold-plugging at boot time). Thus we shouldn't
    836              * fail if the module was loaded, and not by us.
    837              */
    838             if (already_loaded(mod))
    839                 rc = 0;
    840         }
    841     }
    842     return rc;
    843 }
    844 
    845 static int mod_remove(char *mod)
    846 {
    847     int rc;
    848     static const struct mod_list_t rm_a_dummy = { "-a", NULL, NULL, NULL, NULL };
    849 
    850     struct mod_list_t *head = NULL;
    851     struct mod_list_t *tail = NULL;
    852 
    853     if (mod)
    854         check_dep(mod, &head, &tail);
    855     else  // autoclean
    856         head = tail = (struct mod_list_t*) &rm_a_dummy;
    857 
    858     rc = 1;
    859     if (head && tail)
    860         rc = mod_process(head, 0);  // process head ---> tail
    861     return rc;
    862 }
    863 
    864 int modprobe_main(int argc, char** argv);
    865 int modprobe_main(int argc, char** argv)
    866 {
    867     int rc = EXIT_SUCCESS;
    868     char *unused;
    869 
    870     opt_complementary = "?V-:q-v:v-q";
    871     main_opts = getopt32(argv, "acdklnqrst:vVC:",
    872                             &unused, &unused);
    873     if (main_opts & (DUMP_CONF_EXIT | LIST_ALL))
    874         return EXIT_SUCCESS;
    875     if (main_opts & (RESTRICT_DIR | CONFIG_FILE))
    876         bb_error_msg_and_die("-t and -C not supported");
    877 
    878     depend = build_dep();
    879 
    880     if (!depend)
    881         bb_error_msg_and_die("cannot parse modules.dep");
    882 
    883     if (remove_opt) {
    884         do {
    885             if (mod_remove(optind < argc ?
    886                         argv[optind] : NULL)) {
    887                 bb_error_msg("failed to remove module %s",
    888                         argv[optind]);
    889                 rc = EXIT_FAILURE;
    890             }
    891         } while (++optind < argc);
    892     } else {
    893         if (optind >= argc)
    894             bb_error_msg_and_die("no module or pattern provided");
    895 
    896         if (mod_insert(argv[optind], argc - optind - 1, argv + optind + 1))
    897             bb_error_msg_and_die("failed to load module %s", argv[optind]);
    898     }
    899 
    900     /* Here would be a good place to free up memory allocated during the dependencies build. */
    901 
    902     return rc;
    903 }
     602            free(realname);
     603        } while (me->realnames != NULL);
     604    }
     605
     606    return (rc != 0);
     607}
Note: See TracChangeset for help on using the changeset viewer.