insmod: code shrink, stop exporting insmod_ng_main.
authorDenis Vlasenko <vda.linux@googlemail.com>
Fri, 2 Nov 2007 23:31:10 +0000 (23:31 -0000)
committerDenis Vlasenko <vda.linux@googlemail.com>
Fri, 2 Nov 2007 23:31:10 +0000 (23:31 -0000)
function                                             old     new   delta
add_ksymoops_symbols                                   -     421    +421
static.section_names                                  20      40     +20
lsmod_main                                           425     424      -1
set_tainted                                          153     150      -3
main_opts                                              4       -      -4
obj_symbol_patch                                      47      42      -5
obj_string_patch                                     144     139      -5
already_loaded                                       144     138      -6
check_dep                                            348     341      -7
append_option                                         75      68      -7
obj_allocate_commons                                 515     501     -14
new_process_module_arguments                        1039    1018     -21
arch_new_symbol                                       31       9     -22
check_module_name_match                               85      61     -24
obj_create_alloced_section                           164     136     -28
include_conf                                         930     902     -28
modprobe_main                                       1643    1535    -108
obj_load                                             924     777    -147
insmod_ng_main                                       245       -    -245
insmod_main                                         4122    3794    -328
------------------------------------------------------------------------------
(add/remove: 1/2 grow/shrink: 1/16 up/down: 441/-1003)       Total: -562 bytes
   text    data     bss     dec     hex filename
 776020     974    9420  786414   bffee busybox_old
 775384     974    9420  785778   bfd72 busybox_unstripped

libbb/xreadlink.c
modutils/insmod.c
modutils/lsmod.c
modutils/modprobe.c

index 4d87b944d6d8489351c6462aa7236847d0408451..98b795f56b1651322acbc462ad515b0e6f5e672a 100644 (file)
@@ -18,7 +18,8 @@ char *xmalloc_readlink(const char *path)
        int bufsize = 0, readsize = 0;
 
        do {
-               buf = xrealloc(buf, bufsize += GROWBY);
+               bufsize += GROWBY;
+               buf = xrealloc(buf, bufsize);
                readsize = readlink(path, buf, bufsize);
                if (readsize == -1) {
                        free(buf);
index 6f3b7d0f46383441d086129e19481bc1515cf6b2..df75abbfaf853bd86b356214c468173bbfa87472 100644 (file)
 #define ENABLE_FEATURE_2_4_MODULES 1
 #endif
 
-#if !ENABLE_FEATURE_2_4_MODULES
-#define insmod_ng_main insmod_main
-#endif
+/*
+ * Big piece of 2.4-specific code
+ */
+#if ENABLE_FEATURE_2_4_MODULES
 
 #if ENABLE_FEATURE_2_6_MODULES
-extern int insmod_ng_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
+static int insmod_ng_main(int argc, char **argv);
 #endif
 
-
-#if ENABLE_FEATURE_2_4_MODULES
-
-
 #if ENABLE_FEATURE_INSMOD_LOADINKMEM
 #define LOADBITS 0
 #else
 #define LOADBITS 1
 #endif
 
-
 /* Alpha */
 #if defined(__alpha__)
 #define MATCH_MACHINE(x) (x == EM_ALPHA)
@@ -627,13 +623,13 @@ static struct obj_section *obj_create_alloced_section_first(struct obj_file *f,
 
 static void *obj_extend_section(struct obj_section *sec, unsigned long more);
 
-static int obj_string_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
+static void obj_string_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
                     const char *string);
 
-static int obj_symbol_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
+static void obj_symbol_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
                     struct obj_symbol *sym);
 
-static int obj_check_undefineds(struct obj_file *f);
+static void obj_check_undefineds(struct obj_file *f);
 
 static void obj_allocate_commons(struct obj_file *f);
 
@@ -788,7 +784,6 @@ static size_t nksyms;
 static struct external_module *ext_modules;
 static int n_ext_modules;
 static int n_ext_modules_used;
-extern int delete_module(const char *);
 
 static char *m_filename;
 static char *m_fullName;
@@ -801,19 +796,16 @@ static int check_module_name_match(const char *filename, struct stat *statbuf,
                                void *userdata, int depth)
 {
        char *fullname = (char *) userdata;
+       char *tmp;
 
        if (fullname[0] == '\0')
                return FALSE;
-       else {
-               char *tmp, *tmp1 = xstrdup(filename);
-               tmp = bb_get_last_path_component_nostrip(tmp1);
-               if (strcmp(tmp, fullname) == 0) {
-                       free(tmp1);
-                       /* Stop searching if we find a match */
-                       m_filename = xstrdup(filename);
-                       return FALSE;
-               }
-               free(tmp1);
+
+       tmp = bb_get_last_path_component_nostrip(filename);
+       if (strcmp(tmp, fullname) == 0) {
+               /* Stop searching if we find a match */
+               m_filename = xstrdup(filename);
+               return FALSE;
        }
        return TRUE;
 }
@@ -824,25 +816,19 @@ static int check_module_name_match(const char *filename, struct stat *statbuf,
 static struct obj_file *arch_new_file(void)
 {
        struct arch_file *f;
-       f = xmalloc(sizeof(*f));
-
-       memset(f, 0, sizeof(*f));
-
-       return &f->root;
+       f = xzalloc(sizeof(*f));
+       return &f->root; /* it's a first member */
 }
 
 static struct obj_section *arch_new_section(void)
 {
-       return xmalloc(sizeof(struct obj_section));
+       return xzalloc(sizeof(struct obj_section));
 }
 
 static struct obj_symbol *arch_new_symbol(void)
 {
        struct arch_symbol *sym;
-       sym = xmalloc(sizeof(*sym));
-
-       memset(sym, 0, sizeof(*sym));
-
+       sym = xzalloc(sizeof(*sym));
        return &sym->root;
 }
 
@@ -2210,7 +2196,6 @@ static struct obj_section *obj_create_alloced_section(struct obj_file *f,
        f->sections = xrealloc(f->sections, (newidx + 1) * sizeof(sec));
        f->sections[newidx] = sec = arch_new_section();
 
-       memset(sec, 0, sizeof(*sec));
        sec->header.sh_type = SHT_PROGBITS;
        sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
        sec->header.sh_size = size;
@@ -2236,7 +2221,6 @@ static struct obj_section *obj_create_alloced_section_first(struct obj_file *f,
        f->sections = xrealloc(f->sections, (newidx + 1) * sizeof(sec));
        f->sections[newidx] = sec = arch_new_section();
 
-       memset(sec, 0, sizeof(*sec));
        sec->header.sh_type = SHT_PROGBITS;
        sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
        sec->header.sh_size = size;
@@ -2398,7 +2382,7 @@ static char *get_modinfo_value(struct obj_file *f, const char *key)
 /*======================================================================*/
 /* Functions relating to module loading after 2.1.18.  */
 
-static int
+static void
 new_process_module_arguments(struct obj_file *f, int argc, char **argv)
 {
        while (argc > 0) {
@@ -2408,7 +2392,8 @@ new_process_module_arguments(struct obj_file *f, int argc, char **argv)
                int min, max, n;
 
                p = *argv;
-               if ((q = strchr(p, '=')) == NULL) {
+               q = strchr(p, '=');
+               if (q == NULL) {
                        argc--;
                        continue;
                }
@@ -2421,8 +2406,7 @@ new_process_module_arguments(struct obj_file *f, int argc, char **argv)
                p = get_modinfo_value(f, key);
                key += 5;
                if (p == NULL) {
-                       bb_error_msg("invalid parameter %s", key);
-                       return 0;
+                       bb_error_msg_and_die("invalid parameter %s", key);
                }
 
 #ifdef SYMBOL_PREFIX
@@ -2436,8 +2420,7 @@ new_process_module_arguments(struct obj_file *f, int argc, char **argv)
 
                /* Also check that the parameter was not resolved from the kernel.  */
                if (sym == NULL || sym->secidx > SHN_HIRESERVE) {
-                       bb_error_msg("symbol for parameter %s not found", key);
-                       return 0;
+                       bb_error_msg_and_die("symbol for parameter %s not found", key);
                }
 
                if (isdigit(*p)) {
@@ -2463,11 +2446,10 @@ new_process_module_arguments(struct obj_file *f, int argc, char **argv)
 
                                        str = alloca(strlen(q));
                                        for (r = str, q++; *q != '"'; ++q, ++r) {
-                                               if (*q == '\0') {
-                                                       bb_error_msg("improperly terminated string argument for %s",
+                                               if (*q == '\0')
+                                                       bb_error_msg_and_die("improperly terminated string argument for %s",
                                                                        key);
-                                                       return 0;
-                                               } else if (*q == '\\')
+                                               if (*q == '\\')
                                                        switch (*++q) {
                                                        case 'a':
                                                                *r = '\a';
@@ -2513,8 +2495,9 @@ new_process_module_arguments(struct obj_file *f, int argc, char **argv)
                                                        default:
                                                                *r = *q;
                                                                break;
-                                                       } else
-                                                               *r = *q;
+                                                       }
+                                               else
+                                                       *r = *q;
                                        }
                                        *r = '\0';
                                        ++q;
@@ -2558,17 +2541,15 @@ new_process_module_arguments(struct obj_file *f, int argc, char **argv)
                                        /* Get the size of each member */
                                        /* Probably we should do that outside the loop ? */
                                        if (!isdigit(*(p + 1))) {
-                                               bb_error_msg("parameter type 'c' for %s must be followed by"
+                                               bb_error_msg_and_die("parameter type 'c' for %s must be followed by"
                                                                " the maximum size", key);
-                                               return 0;
                                        }
                                        charssize = strtoul(p + 1, (char **) NULL, 10);
 
                                        /* Check length */
                                        if (strlen(str) >= charssize) {
-                                               bb_error_msg("string too long for %s (max %ld)", key,
+                                               bb_error_msg_and_die("string too long for %s (max %ld)", key,
                                                                charssize - 1);
-                                               return 0;
                                        }
 
                                        /* Copy to location */
@@ -2595,12 +2576,10 @@ new_process_module_arguments(struct obj_file *f, int argc, char **argv)
                                        break;
 
                                default:
-                                       bb_error_msg("unknown parameter type '%c' for %s", *p, key);
-                                       return 0;
+                                       bb_error_msg_and_die("unknown parameter type '%c' for %s", *p, key);
                                }
                        }
-
-retry_end_of_value:
+ retry_end_of_value:
                        switch (*q) {
                        case '\0':
                                goto end_of_arg;
@@ -2614,28 +2593,23 @@ retry_end_of_value:
 
                        case ',':
                                if (++n > max) {
-                                       bb_error_msg("too many values for %s (max %d)", key, max);
-                                       return 0;
+                                       bb_error_msg_and_die("too many values for %s (max %d)", key, max);
                                }
                                ++q;
                                break;
 
                        default:
-                               bb_error_msg("invalid argument syntax for %s", key);
-                               return 0;
+                               bb_error_msg_and_die("invalid argument syntax for %s", key);
                        }
                }
-
-end_of_arg:
+ end_of_arg:
                if (n < min) {
-                       bb_error_msg("too few values for %s (min %d)", key, min);
-                       return 0;
+                       bb_error_msg_and_die("too few values for %s (min %d)", key, min);
                }
 
-               argc--, argv++;
+               argc--;
+               argv++;
        }
-
-       return 1;
 }
 
 #if ENABLE_FEATURE_INSMOD_VERSION_CHECKING
@@ -2644,8 +2618,7 @@ static int new_is_module_checksummed(struct obj_file *f)
        const char *p = get_modinfo_value(f, "using_checksums");
        if (p)
                return xatoi(p);
-       else
-               return 0;
+       return 0;
 }
 
 /* Get the module's kernel version in the canonical integer form.  */
@@ -2679,7 +2652,7 @@ new_get_module_version(struct obj_file *f, char str[STRVERSIONLEN])
 
 /* Fetch the loaded modules, and all currently exported symbols.  */
 
-static int new_get_kernel_symbols(void)
+static void new_get_kernel_symbols(void)
 {
        char *module_names, *mn;
        struct external_module *modules, *m;
@@ -2688,15 +2661,17 @@ static int new_get_kernel_symbols(void)
 
        /* Collect the loaded modules.  */
 
-       module_names = xmalloc(bufsize = 256);
-retry_modules_load:
+       bufsize = 256;
+       module_names = xmalloc(bufsize);
+
+ retry_modules_load:
        if (query_module(NULL, QM_MODULES, module_names, bufsize, &ret)) {
                if (errno == ENOSPC && bufsize < ret) {
-                       module_names = xrealloc(module_names, bufsize = ret);
+                       bufsize = ret;
+                       module_names = xrealloc(module_names, bufsize);
                        goto retry_modules_load;
                }
-               bb_perror_msg("QM_MODULES");
-               return 0;
+               bb_perror_msg_and_die("QM_MODULES");
        }
 
        n_ext_modules = nmod = ret;
@@ -2715,23 +2690,23 @@ retry_modules_load:
                                        /* The module was removed out from underneath us.  */
                                        continue;
                                }
-                               bb_perror_msg("query_module: QM_INFO: %s", mn);
-                               return 0;
+                               bb_perror_msg_and_die("query_module: QM_INFO: %s", mn);
                        }
 
-                       syms = xmalloc(bufsize = 1024);
-retry_mod_sym_load:
+                       bufsize = 1024;
+                       syms = xmalloc(bufsize);
+ retry_mod_sym_load:
                        if (query_module(mn, QM_SYMBOLS, syms, bufsize, &ret)) {
                                switch (errno) {
                                        case ENOSPC:
-                                               syms = xrealloc(syms, bufsize = ret);
+                                               bufsize = ret;
+                                               syms = xrealloc(syms, bufsize);
                                                goto retry_mod_sym_load;
                                        case ENOENT:
                                                /* The module was removed out from underneath us.  */
                                                continue;
                                        default:
-                                               bb_perror_msg("query_module: QM_SYMBOLS: %s", mn);
-                                               return 0;
+                                               bb_perror_msg_and_die("query_module: QM_SYMBOLS: %s", mn);
                                }
                        }
                        nsyms = ret;
@@ -2750,14 +2725,13 @@ retry_mod_sym_load:
        /* Collect the kernel's symbols.  */
 
        syms = xmalloc(bufsize = 16 * 1024);
-retry_kern_sym_load:
+ retry_kern_sym_load:
        if (query_module(NULL, QM_SYMBOLS, syms, bufsize, &ret)) {
                if (errno == ENOSPC && bufsize < ret) {
                        syms = xrealloc(syms, bufsize = ret);
                        goto retry_kern_sym_load;
                }
-               bb_perror_msg("kernel: QM_SYMBOLS");
-               return 0;
+               bb_perror_msg_and_die("kernel: QM_SYMBOLS");
        }
        nksyms = nsyms = ret;
        ksyms = syms;
@@ -2765,7 +2739,6 @@ retry_kern_sym_load:
        for (j = 0, s = syms; j < nsyms; ++j, ++s) {
                s->name += (unsigned long) syms;
        }
-       return 1;
 }
 
 
@@ -2786,7 +2759,7 @@ static int new_is_kernel_checksummed(void)
 }
 
 
-static int new_create_this_module(struct obj_file *f, const char *m_name)
+static void  new_create_this_module(struct obj_file *f, const char *m_name)
 {
        struct obj_section *sec;
 
@@ -2800,8 +2773,6 @@ static int new_create_this_module(struct obj_file *f, const char *m_name)
 
        obj_string_patch(f, sec->idx, offsetof(struct new_module, name),
                        m_name);
-
-       return 1;
 }
 
 #if ENABLE_FEATURE_INSMOD_KSYMOOPS_SYMBOLS
@@ -2985,7 +2956,7 @@ new_init_module(const char *m_name, struct obj_file *f, unsigned long m_size)
 
 /*======================================================================*/
 
-static int
+static void
 obj_string_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
                                 const char *string)
 {
@@ -3010,11 +2981,9 @@ obj_string_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
                loc = obj_extend_section(strsec, len);
        }
        memcpy(loc, string, len);
-
-       return 1;
 }
 
-static int
+static void 
 obj_symbol_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
                                 struct obj_symbol *sym)
 {
@@ -3026,14 +2995,11 @@ obj_symbol_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
        p->reloc_offset = offset;
        p->sym = sym;
        f->symbol_patches = p;
-
-       return 1;
 }
 
-static int obj_check_undefineds(struct obj_file *f)
+static void obj_check_undefineds(struct obj_file *f)
 {
-       unsigned long i;
-       int ret = 1;
+       unsigned i;
 
        for (i = 0; i < HASH_BUCKETS; ++i) {
                struct obj_symbol *sym;
@@ -3043,15 +3009,11 @@ static int obj_check_undefineds(struct obj_file *f)
                                        sym->secidx = SHN_ABS;
                                        sym->value = 0;
                                } else {
-                                       if (!flag_quiet) {
-                                               bb_error_msg("unresolved symbol %s", sym->name);
-                                       }
-                                       ret = 0;
+                                       if (!flag_quiet)
+                                               bb_error_msg_and_die("unresolved symbol %s", sym->name);
                                }
                        }
        }
-
-       return ret;
 }
 
 static void obj_allocate_commons(struct obj_file *f)
@@ -3114,7 +3076,6 @@ static void obj_allocate_commons(struct obj_file *f)
                        f->sections[i] = sec = arch_new_section();
                        f->header.e_shnum = i + 1;
 
-                       memset(sec, 0, sizeof(*sec));
                        sec->header.sh_type = SHT_PROGBITS;
                        sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
                        sec->name = ".bss";
@@ -3347,44 +3308,38 @@ static struct obj_file *obj_load(FILE * fp, int loadprogbits)
        /* Read the file header.  */
 
        f = arch_new_file();
-       memset(f, 0, sizeof(*f));
        f->symbol_cmp = strcmp;
        f->symbol_hash = obj_elf_hash;
        f->load_order_search_start = &f->load_order;
 
        fseek(fp, 0, SEEK_SET);
        if (fread(&f->header, sizeof(f->header), 1, fp) != 1) {
-               bb_perror_msg("error reading ELF header");
-               return NULL;
+               bb_perror_msg_and_die("error reading ELF header");
        }
 
        if (f->header.e_ident[EI_MAG0] != ELFMAG0
                        || f->header.e_ident[EI_MAG1] != ELFMAG1
                        || f->header.e_ident[EI_MAG2] != ELFMAG2
                        || f->header.e_ident[EI_MAG3] != ELFMAG3) {
-               bb_error_msg("not an ELF file");
-               return NULL;
+               bb_error_msg_and_die("not an ELF file");
        }
        if (f->header.e_ident[EI_CLASS] != ELFCLASSM
                        || f->header.e_ident[EI_DATA] != (BB_BIG_ENDIAN
                                ? ELFDATA2MSB : ELFDATA2LSB)
                        || f->header.e_ident[EI_VERSION] != EV_CURRENT
                        || !MATCH_MACHINE(f->header.e_machine)) {
-               bb_error_msg("ELF file not for this architecture");
-               return NULL;
+               bb_error_msg_and_die("ELF file not for this architecture");
        }
        if (f->header.e_type != ET_REL) {
-               bb_error_msg("ELF file not a relocatable object");
-               return NULL;
+               bb_error_msg_and_die("ELF file not a relocatable object");
        }
 
        /* Read the section headers.  */
 
        if (f->header.e_shentsize != sizeof(ElfW(Shdr))) {
-               bb_error_msg("section header size mismatch: %lu != %lu",
+               bb_error_msg_and_die("section header size mismatch: %lu != %lu",
                                (unsigned long) f->header.e_shentsize,
                                (unsigned long) sizeof(ElfW(Shdr)));
-               return NULL;
        }
 
        shnum = f->header.e_shnum;
@@ -3394,8 +3349,7 @@ static struct obj_file *obj_load(FILE * fp, int loadprogbits)
        section_headers = alloca(sizeof(ElfW(Shdr)) * shnum);
        fseek(fp, f->header.e_shoff, SEEK_SET);
        if (fread(section_headers, sizeof(ElfW(Shdr)), shnum, fp) != shnum) {
-               bb_perror_msg("error reading ELF section headers");
-               return NULL;
+               bb_perror_msg_and_die("error reading ELF section headers");
        }
 
        /* Read the section data.  */
@@ -3404,7 +3358,6 @@ static struct obj_file *obj_load(FILE * fp, int loadprogbits)
                struct obj_section *sec;
 
                f->sections[i] = sec = arch_new_section();
-               memset(sec, 0, sizeof(*sec));
 
                sec->header = section_headers[i];
                sec->idx = i;
@@ -3431,8 +3384,7 @@ static struct obj_file *obj_load(FILE * fp, int loadprogbits)
                                        sec->contents = xmalloc(sec->header.sh_size);
                                        fseek(fp, sec->header.sh_offset, SEEK_SET);
                                        if (fread(sec->contents, sec->header.sh_size, 1, fp) != 1) {
-                                               bb_perror_msg("error reading ELF section data");
-                                               return NULL;
+                                               bb_perror_msg_and_die("error reading ELF section data");
                                        }
                                } else {
                                        sec->contents = NULL;
@@ -3441,14 +3393,11 @@ static struct obj_file *obj_load(FILE * fp, int loadprogbits)
 
 #if SHT_RELM == SHT_REL
                        case SHT_RELA:
-                               bb_error_msg("RELA relocations not supported on this architecture");
-                               return NULL;
+                               bb_error_msg_and_die("RELA relocations not supported on this architecture");
 #else
                        case SHT_REL:
-                               bb_error_msg("REL relocations not supported on this architecture");
-                               return NULL;
+                               bb_error_msg_and_die("REL relocations not supported on this architecture");
 #endif
-
                        default:
                                if (sec->header.sh_type >= SHT_LOPROC) {
                                        /* Assume processor specific section types are debug
@@ -3458,9 +3407,8 @@ static struct obj_file *obj_load(FILE * fp, int loadprogbits)
                                        break;
                                }
 
-                               bb_error_msg("can't handle sections of type %ld",
+                               bb_error_msg_and_die("can't handle sections of type %ld",
                                                (long) sec->header.sh_type);
-                               return NULL;
                        }
                }
        }
@@ -3494,10 +3442,9 @@ static struct obj_file *obj_load(FILE * fp, int loadprogbits)
                                ElfW(Sym) * sym;
 
                                if (sec->header.sh_entsize != sizeof(ElfW(Sym))) {
-                                       bb_error_msg("symbol size mismatch: %lu != %lu",
+                                       bb_error_msg_and_die("symbol size mismatch: %lu != %lu",
                                                        (unsigned long) sec->header.sh_entsize,
                                                        (unsigned long) sizeof(ElfW(Sym)));
-                                       return NULL;
                                }
 
                                nsym = sec->header.sh_size / sizeof(ElfW(Sym));
@@ -3528,7 +3475,6 @@ static struct obj_file *obj_load(FILE * fp, int loadprogbits)
                                         */
                                        val |= sym->st_other & 4;
 #endif
-
                                        obj_add_symbol(f, name, j, sym->st_info, sym->st_shndx,
                                                        val, sym->st_size);
                                }
@@ -3537,10 +3483,9 @@ static struct obj_file *obj_load(FILE * fp, int loadprogbits)
 
                case SHT_RELM:
                        if (sec->header.sh_entsize != sizeof(ElfW(RelM))) {
-                               bb_error_msg("relocation entry size mismatch: %lu != %lu",
+                               bb_error_msg_and_die("relocation entry size mismatch: %lu != %lu",
                                                (unsigned long) sec->header.sh_entsize,
                                                (unsigned long) sizeof(ElfW(RelM)));
-                               return NULL;
                        }
                        break;
                        /* XXX  Relocation code from modutils-2.3.19 is not here.
@@ -3638,8 +3583,9 @@ static int obj_gpl_license(struct obj_file *f, const char **license)
                                }
                                return 2;
                        }
-                       if (strchr(ptr, '\0'))
-                               ptr = strchr(ptr, '\0') + 1;
+                       ptr = strchr(ptr, '\0');
+                       if (ptr)
+                               ptr++;
                        else
                                ptr = endptr;
                }
@@ -3648,12 +3594,12 @@ static int obj_gpl_license(struct obj_file *f, const char **license)
 }
 
 #define TAINT_FILENAME                  "/proc/sys/kernel/tainted"
-#define TAINT_PROPRIETORY_MODULE        (1<<0)
-#define TAINT_FORCED_MODULE             (1<<1)
-#define TAINT_UNSAFE_SMP                (1<<2)
+#define TAINT_PROPRIETORY_MODULE        (1 << 0)
+#define TAINT_FORCED_MODULE             (1 << 1)
+#define TAINT_UNSAFE_SMP                (1 << 2)
 #define TAINT_URL                       "http://www.tux.org/lkml/#export-tainted"
 
-static void set_tainted(struct obj_file *f, int fd, char *m_name,
+static void set_tainted(int fd, char *m_name,
                int kernel_has_tainted, int taint, const char *text1, const char *text2)
 {
        static smallint printed_info;
@@ -3703,22 +3649,22 @@ static void check_tainted_module(struct obj_file *f, char *m_name)
                case 0:
                        break;
                case 1:
-                       set_tainted(f, fd, m_name, kernel_has_tainted, TAINT_PROPRIETORY_MODULE, "no license", "");
+                       set_tainted(fd, m_name, kernel_has_tainted, TAINT_PROPRIETORY_MODULE, "no license", "");
                        break;
                case 2:
                        /* The module has a non-GPL license so we pretend that the
                         * kernel always has a taint flag to get a warning even on
                         * kernels without the proc flag.
                         */
-                       set_tainted(f, fd, m_name, 1, TAINT_PROPRIETORY_MODULE, "non-GPL license - ", ptr);
+                       set_tainted(fd, m_name, 1, TAINT_PROPRIETORY_MODULE, "non-GPL license - ", ptr);
                        break;
                default:
-                       set_tainted(f, fd, m_name, 1, TAINT_PROPRIETORY_MODULE, "Unexpected return from obj_gpl_license", "");
+                       set_tainted(fd, m_name, 1, TAINT_PROPRIETORY_MODULE, "Unexpected return from obj_gpl_license", "");
                        break;
        }
 
        if (flag_force_load)
-               set_tainted(f, fd, m_name, 1, TAINT_FORCED_MODULE, "forced load", "");
+               set_tainted(fd, m_name, 1, TAINT_FORCED_MODULE, "forced load", "");
 
        if (fd >= 0)
                close(fd);
@@ -3752,15 +3698,7 @@ add_ksymoops_symbols(struct obj_file *f, const char *filename,
                                 const char *m_name)
 {
        static const char symprefix[] ALIGN1 = "__insmod_";
-
-       struct obj_section *sec;
-       struct obj_symbol *sym;
-       char *name, *absolute_filename;
-       char str[STRVERSIONLEN], real[PATH_MAX];
-       int i, l, lm_name, lfilename, use_ksymtab, version;
-       struct stat statbuf;
-
-       static const char *section_names[] = {
+       static const char section_names[][8] = {
                ".text",
                ".rodata",
                ".data",
@@ -3768,12 +3706,18 @@ add_ksymoops_symbols(struct obj_file *f, const char *filename,
                ".sbss"
        };
 
-       if (realpath(filename, real)) {
-               absolute_filename = xstrdup(real);
-       } else {
-               bb_perror_msg("cannot get realpath for %s", filename);
+       struct obj_section *sec;
+       struct obj_symbol *sym;
+       char *name, *absolute_filename;
+       char str[STRVERSIONLEN];
+       int i, l, lm_name, lfilename, use_ksymtab, version;
+       struct stat statbuf;
+
+       /* WARNING: was using realpath, but replaced by readlink to stop using
+        * lots of stack. But here it seems to be able to cause problems? */
+       absolute_filename = xmalloc_readlink(filename);
+       if (!absolute_filename)
                absolute_filename = xstrdup(filename);
-       }
 
        lm_name = strlen(m_name);
        lfilename = strlen(absolute_filename);
@@ -3791,22 +3735,22 @@ add_ksymoops_symbols(struct obj_file *f, const char *filename,
                 * is 0xffffff, decimal 16777215.  putting all three fields in
                 * one symbol is less readable but saves kernel space.
                 */
-               l = sizeof(symprefix)                 /* "__insmod_" */
-                       lm_name+                                /* module name */
-                       2+                                      /* "_O" */
-                       lfilename+                              /* object filename */
-                       2+                                      /* "_M" */
-                       2*sizeof(statbuf.st_mtime)+             /* mtime in hex */
-                       2+                                      /* "_V" */
-                       8+                                      /* version in dec */
-                       1;                                      /* nul */
+               l = sizeof(symprefix) +                 /* "__insmod_" */
+                       lm_name +                       /* module name */
+                       2 +                             /* "_O" */
+                       lfilename +                     /* object filename */
+                       2 +                             /* "_M" */
+                       2 * sizeof(statbuf.st_mtime) +  /* mtime in hex */
+                       2 +                             /* "_V" */
+                       8 +                             /* version in dec */
+                       1;                              /* nul */
                name = xmalloc(l);
                if (stat(absolute_filename, &statbuf) != 0)
                        statbuf.st_mtime = 0;
                version = get_module_version(f, str);   /* -1 if not found */
                snprintf(name, l, "%s%s_O%s_M%0*lX_V%d",
                                symprefix, m_name, absolute_filename,
-                               (int)(2*sizeof(statbuf.st_mtime)), statbuf.st_mtime,
+                               (int)(2 * sizeof(statbuf.st_mtime)), statbuf.st_mtime,
                                version);
                sym = obj_add_symbol(f, name, -1,
                                ELF_ST_INFO(STB_GLOBAL, STT_NOTYPE),
@@ -3819,11 +3763,11 @@ add_ksymoops_symbols(struct obj_file *f, const char *filename,
        /* record where the persistent data is going, same address as previous symbol */
 
        if (f->persist) {
-               l = sizeof(symprefix)         /* "__insmod_" */
-                       lm_name               /* module name */
-                       2                     /* "_P" */
-                       strlen(f->persist)    /* data store */
-                       1;                      /* nul */
+               l = sizeof(symprefix) +         /* "__insmod_" */
+                       lm_name +               /* module name */
+                       2 +                     /* "_P" */
+                       strlen(f->persist) +    /* data store */
+                       1;                      /* nul */
                name = xmalloc(l);
                snprintf(name, l, "%s%s_P%s",
                                symprefix, m_name, f->persist);
@@ -3838,13 +3782,13 @@ add_ksymoops_symbols(struct obj_file *f, const char *filename,
        for (i = 0; i < ARRAY_SIZE(section_names); ++i) {
                sec = obj_find_section(f, section_names[i]);
                if (sec && sec->header.sh_size) {
-                       l = sizeof(symprefix)         /* "__insmod_" */
-                               lm_name               /* module name */
-                               2                     /* "_S" */
-                               strlen(sec->name)     /* section name */
-                               2                     /* "_L" */
-                               8                     /* length in dec */
-                               1;                      /* nul */
+                       l = sizeof(symprefix) +         /* "__insmod_" */
+                               lm_name +               /* module name */
+                               2 +                     /* "_S" */
+                               strlen(sec->name) +     /* section name */
+                               2 +                     /* "_L" */
+                               8 +                     /* length in dec */
+                               1;                      /* nul */
                        name = xmalloc(l);
                        snprintf(name, l, "%s%s_S%s_L%ld",
                                        symprefix, m_name, sec->name,
@@ -3891,9 +3835,10 @@ static void print_load_map(struct obj_file *f)
 #if ENABLE_FEATURE_INSMOD_LOAD_MAP_FULL
        /* Quick reference which section indicies are loaded.  */
 
-       loaded = alloca(sizeof(int) * (i = f->header.e_shnum));
+       i = f->header.e_shnum;
+       loaded = alloca(sizeof(int) * i);
        while (--i >= 0)
-               loaded[i] = (f->sections[i]->header.sh_flags & SHF_ALLOC) != 0;
+               loaded[i] = ((f->sections[i]->header.sh_flags & SHF_ALLOC) != 0);
 
        /* Collect the symbols we'll be listing.  */
 
@@ -3963,7 +3908,7 @@ int insmod_main(int argc, char **argv)
        ElfW(Addr) m_addr;
        struct obj_file *f;
        struct stat st;
-       char *m_name = 0;
+       char *m_name = NULL;
        int exit_status = EXIT_FAILURE;
        int m_has_modinfo;
 #if ENABLE_FEATURE_INSMOD_VERSION_CHECKING
@@ -4027,7 +3972,7 @@ int insmod_main(int argc, char **argv)
                m_name = tmp;
        } else {
                free(tmp1);
-               tmp1 = 0;       /* flag for free(m_name) before exit() */
+               tmp1 = NULL;       /* flag for free(m_name) before exit() */
        }
 
        /* Get a filedesc for the module.  Check that we have a complete path */
@@ -4039,7 +3984,6 @@ int insmod_main(int argc, char **argv)
                if (k_version) {        /* uname succeedd */
                        char *module_dir;
                        char *tmdn;
-                       char real_module_dir[FILENAME_MAX];
 
                        tmdn = concat_path_file(_PATH_MODULES, myuname.release);
                        /* Jump through hoops in case /lib/modules/`uname -r`
@@ -4047,36 +3991,37 @@ int insmod_main(int argc, char **argv)
                         * follow symlinks, but we do want to follow the
                         * /lib/modules/`uname -r` dir, So resolve it ourselves
                         * if it is a link... */
-                       if (realpath(tmdn, real_module_dir) == NULL)
-                               module_dir = tmdn;
-                       else
-                               module_dir = real_module_dir;
+                       module_dir = xmalloc_readlink(tmdn);
+                       if (!module_dir)
+                               module_dir = xstrdup(tmdn);
                        recursive_action(module_dir, ACTION_RECURSE,
-                                       check_module_name_match, 0, m_fullName, 0);
+                                       check_module_name_match, NULL, m_fullName, 0);
+                       free(module_dir);
                        free(tmdn);
                }
 
                /* Check if we have found anything yet */
                if (!m_filename || ((fp = fopen(m_filename, "r")) == NULL)) {
-                       char module_dir[FILENAME_MAX];
+                       int r;
+                       char *module_dir;
 
                        free(m_filename);
                        m_filename = NULL;
-                       if (realpath(_PATH_MODULES, module_dir) == NULL)
-                               strcpy(module_dir, _PATH_MODULES);
+                       module_dir = xmalloc_readlink(_PATH_MODULES);
+                       if (!module_dir)
+                               module_dir = xstrdup(_PATH_MODULES);
                        /* No module found under /lib/modules/`uname -r`, this
                         * time cast the net a bit wider.  Search /lib/modules/ */
-                       if (!recursive_action(module_dir, ACTION_RECURSE,
-                                                   check_module_name_match, 0, m_fullName, 0)
+                       r = recursive_action(module_dir, ACTION_RECURSE,
+                                       check_module_name_match, NULL, m_fullName, 0);
+                       if (r)
+                               bb_error_msg_and_die("%s: module not found", m_fullName);
+                       free(module_dir);
+                       if (m_filename == NULL
+                        || ((fp = fopen(m_filename, "r")) == NULL)
                        ) {
-                               if (m_filename == 0
-                                || ((fp = fopen(m_filename, "r")) == NULL)
-                               ) {
-                                       bb_error_msg("%s: module not found", m_fullName);
-                                       goto out;
-                               }
-                       } else
                                bb_error_msg_and_die("%s: module not found", m_fullName);
+                       }
                }
        } else
                m_filename = xstrdup(arg1);
@@ -4093,8 +4038,6 @@ int insmod_main(int argc, char **argv)
 #endif
 
        f = obj_load(fp, LOADBITS);
-       if (f == NULL)
-               bb_perror_msg_and_die("cannot load the module");
 
        if (get_modinfo_value(f, "kernel_version") == NULL)
                m_has_modinfo = 0;
@@ -4109,9 +4052,8 @@ int insmod_main(int argc, char **argv)
                if (m_has_modinfo) {
                        m_version = new_get_module_version(f, m_strversion);
                        if (m_version == -1) {
-                               bb_error_msg("cannot find the kernel version the module was "
+                               bb_error_msg_and_die("cannot find the kernel version the module was "
                                                "compiled for");
-                               goto out;
                        }
                }
 
@@ -4128,14 +4070,10 @@ int insmod_main(int argc, char **argv)
        k_crcs = 0;
 #endif /* FEATURE_INSMOD_VERSION_CHECKING */
 
-       if (!query_module(NULL, 0, NULL, 0, NULL)) {
-               if (!new_get_kernel_symbols())
-                       goto out;
-               k_crcs = new_is_kernel_checksummed();
-       } else {
-               bb_error_msg("not configured to support old kernels");
-               goto out;
-       }
+       if (query_module(NULL, 0, NULL, 0, NULL))
+               bb_error_msg_and_die("not configured to support old kernels");
+       new_get_kernel_symbols();
+       k_crcs = new_is_kernel_checksummed();
 
 #if ENABLE_FEATURE_INSMOD_VERSION_CHECKING
        m_crcs = 0;
@@ -4151,22 +4089,15 @@ int insmod_main(int argc, char **argv)
 
        /* Allocate common symbols, symbol tables, and string tables.  */
 
-       if (!new_create_this_module(f, m_name)) {
-               goto out;
-       }
-
-       if (!obj_check_undefineds(f)) {
-               goto out;
-       }
+       new_create_this_module(f, m_name);
+       obj_check_undefineds(f);
        obj_allocate_commons(f);
        check_tainted_module(f, m_name);
 
        /* done with the module name, on to the optional var=value arguments */
        ++optind;
        if (optind < argc) {
-               if (!new_process_module_arguments(f, argc - optind, argv + optind)) {
-                       goto out;
-               }
+               new_process_module_arguments(f, argc - optind, argv + optind);
        }
 
        arch_create_got(f);
@@ -4181,22 +4112,18 @@ int insmod_main(int argc, char **argv)
        /* Find current size of the module */
        m_size = obj_load_size(f);
 
-
        m_addr = create_module(m_name, m_size);
        if (m_addr == -1) switch (errno) {
                case EEXIST:
-                       bb_error_msg("a module named %s already exists", m_name);
-                       goto out;
+                       bb_error_msg_and_die("a module named %s already exists", m_name);
                case ENOMEM:
-                       bb_error_msg("can't allocate kernel memory for module; needed %lu bytes",
+                       bb_error_msg_and_die("can't allocate kernel memory for module; needed %lu bytes",
                                        m_size);
-                       goto out;
                default:
-                       bb_perror_msg("create_module: %s", m_name);
-                       goto out;
+                       bb_perror_msg_and_die("create_module: %s", m_name);
        }
 
-#if  !LOADBITS
+#if !LOADBITS
        /*
         * the PROGBITS section was not loaded by the obj_load
         * now we can load them directly into the kernel memory
@@ -4222,7 +4149,7 @@ int insmod_main(int argc, char **argv)
 
        exit_status = EXIT_SUCCESS;
 
-out:
+ out:
 #if ENABLE_FEATURE_CLEAN_UP
        if (fp)
                fclose(fp);
@@ -4234,8 +4161,10 @@ out:
        return exit_status;
 }
 
-
-#endif
+#endif /* ENABLE_FEATURE_2_4_MODULES */
+/*
+ * End of big piece of 2.4-specific code
+ */
 
 
 #if ENABLE_FEATURE_2_6_MODULES
@@ -4249,20 +4178,24 @@ static const char *moderror(int err)
 {
        switch (err) {
        case ENOEXEC:
-               return "Invalid module format";
+               return "invalid module format";
        case ENOENT:
-               return "Unknown symbol in module";
+               return "unknown symbol in module";
        case ESRCH:
-               return "Module has wrong symbol version";
+               return "module has wrong symbol version";
        case EINVAL:
-               return "Invalid parameters";
+               return "invalid parameters";
        default:
                return strerror(err);
        }
 }
 
-int insmod_ng_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
-int insmod_ng_main(int argc, char **argv)
+#if !ENABLE_FEATURE_2_4_MODULES
+int insmod_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
+int insmod_main(int argc, char **argv)
+#else
+static int insmod_ng_main(int argc, char **argv)
+#endif
 {
        long ret;
        size_t len;
index 70146814cdee746ee83b7a8b2e62d902d4b93951..f1f78ff9f660796dfc89209267dbb49eb1bae841 100644 (file)
@@ -28,17 +28,17 @@ static void check_tainted(void)
        FILE *f;
 
        tainted = 0;
-       if ((f = fopen(TAINT_FILENAME, "r"))) {
+       f = fopen(TAINT_FILENAME, "r");
+       if (f) {
                fscanf(f, "%d", &tainted);
                fclose(f);
        }
-       if (f && tainted) {
+       if (tainted) {
                printf("    Tainted: %c%c%c\n",
                                tainted & TAINT_PROPRIETORY_MODULE      ? 'P' : 'G',
                                tainted & TAINT_FORCED_MODULE           ? 'F' : ' ',
                                tainted & TAINT_UNSAFE_SMP              ? 'S' : ' ');
-       }
-       else {
+       } else {
                printf("    Not tainted\n");
        }
 }
@@ -147,7 +147,7 @@ int lsmod_main(int argc, char **argv)
 
        printf("Module                  Size  Used by");
        check_tainted();
-#if defined(CONFIG_FEATURE_LSMOD_PRETTY_2_6_OUTPUT)
+#if ENABLE_FEATURE_LSMOD_PRETTY_2_6_OUTPUT
        {
                char *line;
                while ((line = xmalloc_fgets(file)) != NULL) {
index a67ddea9b59e382a618670eb1d1f3e5c8b0aba70..f7d193a055de96627bf2367ffcb7187f5df575e5 100644 (file)
@@ -15,6 +15,8 @@
 #include <sys/utsname.h>
 #include <fnmatch.h>
 
+#define line_buffer bb_common_bufsiz1
+
 struct mod_opt_t {     /* one-way list of options to pass to a module */
        char *  m_opt_val;
        struct mod_opt_t * m_next;
@@ -48,7 +50,7 @@ struct mod_list_t {   /* two-way list of modules to process */
 
 static struct dep_t *depend;
 
-#define main_options "acdklnqrst:vVC:"
+#define MAIN_OPT_STR "acdklnqrst:vVC:"
 #define INSERT_ALL     1        /* a */
 #define DUMP_CONF_EXIT 2        /* c */
 #define D_OPT_IGNORED  4        /* d */
@@ -63,14 +65,12 @@ static struct dep_t *depend;
 #define VERSION_ONLY   2048     /* V */
 #define CONFIG_FILE    4096     /* C */
 
-#define autoclean       (main_opts & AUTOCLEAN_FLG)
-#define show_only       (main_opts & SHOW_ONLY)
-#define quiet           (main_opts & QUIET)
-#define remove_opt      (main_opts & REMOVE_OPT)
-#define do_syslog       (main_opts & DO_SYSLOG)
-#define verbose         (main_opts & VERBOSE)
-
-static int main_opts;
+#define autoclean       (option_mask32 & AUTOCLEAN_FLG)
+#define show_only       (option_mask32 & SHOW_ONLY)
+#define quiet           (option_mask32 & QUIET)
+#define remove_opt      (option_mask32 & REMOVE_OPT)
+#define do_syslog       (option_mask32 & DO_SYSLOG)
+#define verbose         (option_mask32 & VERBOSE)
 
 static int parse_tag_value(char *buffer, char **ptag, char **pvalue)
 {
@@ -78,12 +78,15 @@ static int parse_tag_value(char *buffer, char **ptag, char **pvalue)
 
        buffer = skip_whitespace(buffer);
        tag = value = buffer;
-       while (!isspace(*value))
-               if (!*value) return 0;
-               else value++;
-       *value++ = 0;
+       while (!isspace(*value)) {
+               if (!*value)
+                       return 0;
+               value++;
+       }
+       *value++ = '\0';
        value = skip_whitespace(value);
-       if (!*value) return 0;
+       if (!*value)
+               return 0;
 
        *ptag = tag;
        *pvalue = value;
@@ -102,14 +105,14 @@ static struct mod_opt_t *append_option(struct mod_opt_t *opt_list, char *opt)
                while (ol->m_next) {
                        ol = ol->m_next;
                }
-               ol->m_next = xmalloc(sizeof(struct mod_opt_t));
+               ol->m_next = xzalloc(sizeof(struct mod_opt_t));
                ol = ol->m_next;
        } else {
-               ol = opt_list = xmalloc(sizeof(struct mod_opt_t));
+               ol = opt_list = xzalloc(sizeof(struct mod_opt_t));
        }
 
        ol->m_opt_val = xstrdup(opt);
-       ol->m_next = NULL;
+       /*ol->m_next = NULL; - done by xzalloc*/
 
        return opt_list;
 }
@@ -190,7 +193,8 @@ static char *parse_command_string(char *src, char **dst)
                                case '0':
                                        /* We escaped a special character. For now, keep
                                         * both the back-slash and the following char. */
-                                       tmp_str++; src++;
+                                       tmp_str++;
+                                       src++;
                                        break;
                                default:
                                        /* We escaped a space or a single or double quote,
@@ -242,12 +246,12 @@ static void include_conf(struct dep_t **first, struct dep_t **current, char *buf
 
                p = strchr(buffer, '#');
                if (p)
-                       *p = 0;
+                       *p = '\0';
 
                l = strlen(buffer);
 
                while (l && isspace(buffer[l-1])) {
-                       buffer[l-1] = 0;
+                       buffer[l-1] = '\0';
                        l--;
                }
 
@@ -256,66 +260,68 @@ static void include_conf(struct dep_t **first, struct dep_t **current, char *buf
                        continue;
                }
 
-               if (!continuation_line) {
-                       if ((strncmp(buffer, "alias", 5) == 0) && isspace(buffer[5])) {
-                               char *alias, *mod;
+               if (continuation_line)
+                       continue;
 
-                               if (parse_tag_value(buffer + 6, &alias, &mod)) {
-                                       /* handle alias as a module dependent on the aliased module */
-                                       if (!*current) {
-                                               (*first) = (*current) = xzalloc(sizeof(struct dep_t));
-                                       } else {
-                                               (*current)->m_next = xzalloc(sizeof(struct dep_t));
-                                               (*current) = (*current)->m_next;
-                                       }
-                                       (*current)->m_name  = xstrdup(alias);
-                                       (*current)->m_isalias = 1;
+               if ((strncmp(buffer, "alias", 5) == 0) && isspace(buffer[5])) {
+                       char *alias, *mod;
 
-                                       if ((strcmp(mod, "off") == 0) || (strcmp(mod, "null") == 0)) {
-                                               (*current)->m_depcnt = 0;
-                                               (*current)->m_deparr = 0;
-                                       } else {
-                                               (*current)->m_depcnt  = 1;
-                                               (*current)->m_deparr  = xmalloc(1 * sizeof(char *));
-                                               (*current)->m_deparr[0] = xstrdup(mod);
-                                       }
-                                       (*current)->m_next    = 0;
+                       if (parse_tag_value(buffer + 6, &alias, &mod)) {
+                               /* handle alias as a module dependent on the aliased module */
+                               if (!*current) {
+                                       (*first) = (*current) = xzalloc(sizeof(struct dep_t));
+                               } else {
+                                       (*current)->m_next = xzalloc(sizeof(struct dep_t));
+                                       (*current) = (*current)->m_next;
                                }
-                       } else if ((strncmp(buffer, "options", 7) == 0) && isspace(buffer[7])) {
-                               char *mod, *opt;
-
-                               /* split the line in the module/alias name, and options */
-                               if (parse_tag_value(buffer + 8, &mod, &opt)) {
-                                       struct dep_t *dt;
+                               (*current)->m_name = xstrdup(alias);
+                               (*current)->m_isalias = 1;
 
-                                       /* find the corresponding module */
-                                       for (dt = *first; dt; dt = dt->m_next) {
-                                               if (strcmp(dt->m_name, mod) == 0)
-                                                       break;
-                                       }
-                                       if (dt) {
-                                               if (ENABLE_FEATURE_MODPROBE_MULTIPLE_OPTIONS) {
-                                                       char* new_opt = NULL;
-                                                       while ((opt = parse_command_string(opt, &new_opt))) {
-                                                               dt->m_options = append_option(dt->m_options, new_opt);
-                                                       }
-                                               } else {
-                                                       dt->m_options = append_option(dt->m_options, opt);
-                                               }
-                                       }
+                               if ((strcmp(mod, "off") == 0) || (strcmp(mod, "null") == 0)) {
+                                       /*(*current)->m_depcnt = 0; - done by xzalloc */
+                                       /*(*current)->m_deparr = 0;*/
+                               } else {
+                                       (*current)->m_depcnt = 1;
+                                       (*current)->m_deparr = xmalloc(sizeof(char *));
+                                       (*current)->m_deparr[0] = xstrdup(mod);
                                }
-                       } else if ((strncmp(buffer, "include", 7) == 0) && isspace(buffer[7])) {
-                               int fdi; char *filename;
+                               /*(*current)->m_next = NULL; - done by xzalloc */
+                       }
+               } else if ((strncmp(buffer, "options", 7) == 0) && isspace(buffer[7])) {
+                       char *mod, *opt;
 
-                               filename = skip_whitespace(buffer + 8);
+                       /* split the line in the module/alias name, and options */
+                       if (parse_tag_value(buffer + 8, &mod, &opt)) {
+                               struct dep_t *dt;
 
-                               if ((fdi = open(filename, O_RDONLY)) >= 0) {
-                                       include_conf(first, current, buffer, buflen, fdi);
-                                       close(fdi);
+                               /* find the corresponding module */
+                               for (dt = *first; dt; dt = dt->m_next) {
+                                       if (strcmp(dt->m_name, mod) == 0)
+                                               break;
                                }
+                               if (dt) {
+                                       if (ENABLE_FEATURE_MODPROBE_MULTIPLE_OPTIONS) {
+                                               char* new_opt = NULL;
+                                               while ((opt = parse_command_string(opt, &new_opt))) {
+                                                       dt->m_options = append_option(dt->m_options, new_opt);
+                                               }
+                                       } else {
+                                               dt->m_options = append_option(dt->m_options, opt);
+                                       }
+                               }
+                       }
+               } else if ((strncmp(buffer, "include", 7) == 0) && isspace(buffer[7])) {
+                       int fdi;
+                       char *filename;
+
+                       filename = skip_whitespace(buffer + 8);
+                       fdi = open(filename, O_RDONLY);
+                       if (fdi >= 0) {
+                               include_conf(first, current, buffer, buflen, fdi);
+                               close(fdi);
                        }
                }
-       }
+       } /* while (reads(...)) */
 }
 
 /*
@@ -327,9 +333,8 @@ static struct dep_t *build_dep(void)
 {
        int fd;
        struct utsname un;
-       struct dep_t *first = 0;
-       struct dep_t *current = 0;
-       char buffer[2048];
+       struct dep_t *first = NULL;
+       struct dep_t *current = NULL;
        char *filename;
        int continuation_line = 0;
        int k_version;
@@ -350,16 +355,16 @@ static struct dep_t *build_dep(void)
                /* Ok, that didn't work.  Fall back to looking in /lib/modules */
                fd = open("/lib/modules/modules.dep", O_RDONLY);
                if (fd < 0) {
-                       return 0;
+                       bb_error_msg_and_die("cannot parse modules.dep");
                }
        }
 
-       while (reads(fd, buffer, sizeof(buffer))) {
-               int l = strlen(buffer);
+       while (reads(fd, line_buffer, sizeof(line_buffer))) {
+               int l = strlen(line_buffer);
                char *p = 0;
 
-               while (l > 0 && isspace(buffer[l-1])) {
-                       buffer[l-1] = 0;
+               while (l > 0 && isspace(line_buffer[l-1])) {
+                       line_buffer[l-1] = '\0';
                        l--;
                }
 
@@ -371,7 +376,7 @@ static struct dep_t *build_dep(void)
                /* Is this a new module dep description? */
                if (!continuation_line) {
                        /* find the dep beginning */
-                       char *col = strchr(buffer, ':');
+                       char *col = strchr(line_buffer, ':');
                        char *dot = col;
 
                        if (col) {
@@ -381,53 +386,52 @@ static struct dep_t *build_dep(void)
                                char *mod;
 
                                /* Find the beginning of the module file name */
-                               *col = 0;
-                               mods = bb_basename(buffer);
+                               *col = '\0';
+                               mods = bb_basename(line_buffer);
 
                                /* find the path of the module */
-                               modpath = strchr(buffer, '/'); /* ... and this is the path */
+                               modpath = strchr(line_buffer, '/'); /* ... and this is the path */
                                if (!modpath)
-                                       modpath = buffer; /* module with no path */
+                                       modpath = line_buffer; /* module with no path */
                                /* find the end of the module name in the file name */
                                if (ENABLE_FEATURE_2_6_MODULES &&
-                                    (k_version > 4) && (*(col-3) == '.') &&
-                                   (*(col-2) == 'k') && (*(col-1) == 'o'))
+                                   (k_version > 4) && (col[-3] == '.') &&
+                                   (col[-2] == 'k') && (col[-1] == 'o'))
                                        dot = col - 3;
-                               else
-                                       if ((*(col-2) == '.') && (*(col-1) == 'o'))
-                                               dot = col - 2;
+                               else if ((col[-2] == '.') && (col[-1] == 'o'))
+                                       dot = col - 2;
 
                                mod = xstrndup(mods, dot - mods);
 
                                /* enqueue new module */
                                if (!current) {
-                                       first = current = xmalloc(sizeof(struct dep_t));
+                                       first = current = xzalloc(sizeof(struct dep_t));
                                } else {
-                                       current->m_next = xmalloc(sizeof(struct dep_t));
+                                       current->m_next = xzalloc(sizeof(struct dep_t));
                                        current = current->m_next;
                                }
-                               current->m_name    = mod;
-                               current->m_path    = xstrdup(modpath);
-                               current->m_options = NULL;
-                               current->m_isalias = 0;
-                               current->m_depcnt  = 0;
-                               current->m_deparr  = 0;
-                               current->m_next    = 0;
+                               current->m_name = mod;
+                               current->m_path = xstrdup(modpath);
+                               /*current->m_options = NULL; - xzalloc did it*/
+                               /*current->m_isalias = 0;*/
+                               /*current->m_depcnt = 0;*/
+                               /*current->m_deparr = 0;*/
+                               /*current->m_next = 0;*/
 
                                p = col + 1;
                        } else
                                /* this line is not a dep description */
-                               p = 0;
+                               p = NULL;
                } else
                        /* It's a dep description continuation */
-                       p = buffer;
+                       p = line_buffer;
 
                while (p && *p && isblank(*p))
                        p++;
 
                /* p points to the first dependable module; if NULL, no dependable module */
                if (p && *p) {
-                       char *end = &buffer[l-1];
+                       char *end = &line_buffer[l-1];
                        const char *deps;
                        char *dep;
                        char *next;
@@ -440,7 +444,7 @@ static struct dep_t *build_dep(void)
                                /* search the end of the dependency */
                                next = strchr(p, ' ');
                                if (next) {
-                                       *next = 0;
+                                       *next = '\0';
                                        next--;
                                } else
                                        next = end;
@@ -454,12 +458,11 @@ static struct dep_t *build_dep(void)
 
                                /* find the end of the module name in the file name */
                                if (ENABLE_FEATURE_2_6_MODULES
-                                && (k_version > 4) && (*(next-2) == '.')
-                                && (*(next-1) == 'k') && (*next == 'o'))
+                                && (k_version > 4) && (next[-2] == '.')
+                                && (next[-1] == 'k') && (next[0] == 'o'))
                                        ext = 3;
-                               else
-                                       if ((*(next-1) == '.') && (*next == 'o'))
-                                               ext = 2;
+                               else if ((next[-1] == '.') && (next[0] == 'o'))
+                                       ext = 2;
 
                                /* Cope with blank lines */
                                if ((next-deps-ext+1) <= 0)
@@ -477,11 +480,8 @@ static struct dep_t *build_dep(void)
                }
 
                /* is there other dependable module(s) ? */
-               if (buffer[l-1] == '\\')
-                       continuation_line = 1;
-               else
-                       continuation_line = 0;
-       }
+               continuation_line = (line_buffer[l-1] == '\\');
+       } /* while (reads(...)) */
        close(fd);
 
        /*
@@ -498,7 +498,7 @@ static struct dep_t *build_dep(void)
                                fd = open("/etc/conf.modules", O_RDONLY);
 
        if (fd >= 0) {
-               include_conf(&first, &current, buffer, sizeof(buffer), fd);
+               include_conf(&first, &current, line_buffer, sizeof(line_buffer), fd);
                close(fd);
        }
 
@@ -515,7 +515,7 @@ static struct dep_t *build_dep(void)
                        free(filename);
 
                if (fd >= 0) {
-                       include_conf(&first, &current, buffer, sizeof(buffer), fd);
+                       include_conf(&first, &current, line_buffer, sizeof(line_buffer), fd);
                        close(fd);
                }
 
@@ -530,7 +530,7 @@ static struct dep_t *build_dep(void)
                        free(filename);
 
                if (fd >= 0) {
-                       include_conf(&first, &current, buffer, sizeof(buffer), fd);
+                       include_conf(&first, &current, line_buffer, sizeof(line_buffer), fd);
                        close(fd);
                }
        }
@@ -542,16 +542,15 @@ static struct dep_t *build_dep(void)
 static int already_loaded(const char *name)
 {
        int fd, ret = 0;
-       char buffer[4096];
 
        fd = open("/proc/modules", O_RDONLY);
        if (fd < 0)
                return -1;
 
-       while (reads(fd, buffer, sizeof(buffer))) {
+       while (reads(fd, line_buffer, sizeof(line_buffer))) {
                char *p;
 
-               p = strchr (buffer, ' ');
+               p = strchr(line_buffer, ' ');
                if (p) {
                        const char *n;
 
@@ -559,8 +558,8 @@ static int already_loaded(const char *name)
                        // the idiosyncrasy that _ and - are interchangeable because the
                        // 2.6 kernel does weird things.
 
-                       *p = 0;
-                       for (p = buffer, n = name; ; p++, n++) {
+                       *p = '\0';
+                       for (p = line_buffer, n = name; ; p++, n++) {
                                if (*p != *n) {
                                        if ((*p == '_' || *p == '-') && (*n == '_' || *n == '-'))
                                                continue;
@@ -574,8 +573,8 @@ static int already_loaded(const char *name)
                        }
                }
        }
-done:
-       close (fd);
+ done:
+       close(fd);
        return ret;
 }
 
@@ -623,7 +622,7 @@ static int mod_process(const struct mod_list_t *list, int do_insert)
                                while (opts) {
                                        /* Add one more option */
                                        argc++;
-                                       argv = xrealloc(argv,(argc + 1)* sizeof(char*));
+                                       argv = xrealloc(argv, (argc + 1) * sizeof(char*));
                                        argv[argc-1] = opts->m_opt_val;
                                        opts = opts->m_next;
                                }
@@ -698,9 +697,8 @@ static int check_pattern(const char* pat_src, const char* mod_src)
                }
 
                return ret;
-       } else {
-               return fnmatch(pat_src, mod_src, 0);
        }
+       return fnmatch(pat_src, mod_src, 0);
 }
 
 /*
@@ -712,8 +710,8 @@ static void check_dep(char *mod, struct mod_list_t **head, struct mod_list_t **t
 {
        struct mod_list_t *find;
        struct dep_t *dt;
-       struct mod_opt_t *opt = 0;
-       char *path = 0;
+       struct mod_opt_t *opt = NULL;
+       char *path = NULL;
 
        /* Search for the given module name amongst all dependency rules.
         * The module name in a dependency rule can be a shell pattern,
@@ -765,8 +763,8 @@ static void check_dep(char *mod, struct mod_list_t **head, struct mod_list_t **t
 
        // search for duplicates
        for (find = *head; find; find = find->m_next) {
-               if (!strcmp(mod, find->m_name)) {
-                       // found ->dequeue it
+               if (strcmp(mod, find->m_name) == 0) {
+                       // found -> dequeue it
 
                        if (find->m_prev)
                                find->m_prev->m_next = find->m_next;
@@ -783,7 +781,7 @@ static void check_dep(char *mod, struct mod_list_t **head, struct mod_list_t **t
        }
 
        if (!find) { // did not find a duplicate
-               find = xmalloc(sizeof(struct mod_list_t));
+               find = xzalloc(sizeof(struct mod_list_t));
                find->m_name = mod;
                find->m_path = path;
                find->m_options = opt;
@@ -793,7 +791,7 @@ static void check_dep(char *mod, struct mod_list_t **head, struct mod_list_t **t
        if (*tail)
                (*tail)->m_next = find;
        find->m_prev = *tail;
-       find->m_next = 0;
+       /*find->m_next = NULL; - xzalloc did it */
 
        if (!*head)
                *head = find;
@@ -868,11 +866,11 @@ int modprobe_main(int argc, char **argv)
        char *unused;
 
        opt_complementary = "?V-:q-v:v-q";
-       main_opts = getopt32(argv, "acdklnqrst:vVC:",
-                                                       &unused, &unused);
-       if (main_opts & (DUMP_CONF_EXIT | LIST_ALL))
+       getopt32(argv, MAIN_OPT_STR, &unused, &unused);
+
+       if (option_mask32 & (DUMP_CONF_EXIT | LIST_ALL))
                return EXIT_SUCCESS;
-       if (main_opts & (RESTRICT_DIR | CONFIG_FILE))
+       if (option_mask32 & (RESTRICT_DIR | CONFIG_FILE))
                bb_error_msg_and_die("-t and -C not supported");
 
        depend = build_dep();
@@ -882,8 +880,8 @@ int modprobe_main(int argc, char **argv)
 
        if (remove_opt) {
                do {
-                       if (mod_remove(optind < argc ?
-                                               argv[optind] : NULL)) {
+                       /* argv[optind] can be NULL here */
+                       if (mod_remove(argv[optind])) {
                                bb_error_msg("failed to remove module %s",
                                                argv[optind]);
                                rc = EXIT_FAILURE;