/* These three functions called many times, optimizing for speed. * Users reported minute-long delays when they runn iptables repeatedly * (iptables use modprobe to install needed kernel modules). */ static struct module_entry *helper_get_module(const char *module, int create) { char modname[MODULE_NAME_LEN]; struct module_entry *e; llist_t *l; unsigned i; unsigned hash; filename2modname(module, modname); hash = 0; for (i = 0; modname[i]; i++) hash = ((hash << 5) + hash) + modname[i]; hash %= DB_HASH_SIZE; for (l = G.db[hash]; l; l = l->link) { e = (struct module_entry *) l->data; if (strcmp(e->modname, modname) == 0) return e; } if (!create) return NULL; e = xzalloc(sizeof(*e)); e->modname = xstrdup(modname); llist_add_to(&G.db[hash], e); return e; }
static int pathname_matches_modname(const char *pathname, const char *modname) { int r; char name[MODULE_NAME_LEN]; filename2modname(bb_get_last_path_component_nostrip(pathname), name); r = (strcmp(name, modname) == 0); return r; }
int modinfo_main(int argc UNUSED_PARAM, char **argv) { struct modinfo_env env; char name[MODULE_NAME_LEN]; struct utsname uts; parser_t *parser; char *colon, *tokens[2]; unsigned opts; unsigned i; env.field = NULL; opt_complementary = "-1"; /* minimum one param */ opts = getopt32(argv, "fdalvpF:0", &env.field); env.tags = opts & OPT_TAGS ? opts & OPT_TAGS : OPT_TAGS; argv += optind; uname(&uts); parser = config_open2( xasprintf("%s/%s/%s", CONFIG_DEFAULT_MODULES_DIR, uts.release, CONFIG_DEFAULT_DEPMOD_FILE), fopen_for_read ); if (!parser) { parser = config_open2( xasprintf("%s/%s", CONFIG_DEFAULT_MODULES_DIR, CONFIG_DEFAULT_DEPMOD_FILE), xfopen_for_read ); } while (config_read(parser, tokens, 2, 1, "# \t", PARSE_NORMAL)) { colon = last_char_is(tokens[0], ':'); if (colon == NULL) continue; *colon = '\0'; filename2modname(tokens[0], name); for (i = 0; argv[i]; i++) { if (fnmatch(argv[i], name, 0) == 0) { modinfo(tokens[0], uts.release, &env); argv[i] = (char *) ""; } } } if (ENABLE_FEATURE_CLEAN_UP) config_close(parser); for (i = 0; argv[i]; i++) { if (argv[i][0]) { modinfo(argv[i], uts.release, &env); } } return 0; }
static void add_module(char *filename, int namelen, struct list_head *list) { struct module *mod; /* If it's a duplicate: move it to the end, so it gets inserted where it is *first* required. */ mod = find_module(filename, list); if (mod) list_del(&mod->list); else { /* No match. Create a new module. */ mod = NOFAIL(malloc(sizeof(struct module) + namelen + 1)); memcpy(mod->filename, filename, namelen); mod->filename[namelen] = '\0'; mod->modname = NOFAIL(malloc(namelen + 1)); filename2modname(mod->modname, mod->filename); } list_add_tail(&mod->list, list); }
int rmmod_main(int argc UNUSED_PARAM, char **argv) { int n, err; unsigned flags = O_NONBLOCK | O_EXCL; /* Parse command line. */ n = getopt32(argv, "wfas"); // -s ignored argv += optind; if (n & 1) // --wait flags &= ~O_NONBLOCK; if (n & 2) // --force flags |= O_TRUNC; if (n & 4) { /* Unload _all_ unused modules via NULL delete_module() call */ err = bb_delete_module(NULL, flags); if (err && err != EFAULT) bb_perror_msg_and_die("rmmod"); return EXIT_SUCCESS; } if (!*argv) bb_show_usage(); n = ENABLE_FEATURE_2_4_MODULES && get_linux_version_code() < KERNEL_VERSION(2,6,0); while (*argv) { char modname[MODULE_NAME_LEN]; const char *bname; bname = bb_basename(*argv++); if (n) safe_strncpy(modname, bname, MODULE_NAME_LEN); else filename2modname(bname, modname); err = bb_delete_module(modname, flags); if (err) bb_perror_msg_and_die("can't unload module '%s'", modname); } return EXIT_SUCCESS; }
static int rmmod(int log, int verbose, const char *path, int flags) { long ret; char name[strlen(path) + 1]; filename2modname(name, path); if ((flags & O_NONBLOCK) && !(flags & O_TRUNC)) { if (check_usage(log, name) != 0) return 1; } info(log, "rmmod %s, wait=%s%s\n", name, (flags & O_NONBLOCK) ? "no" : "yes", (flags & O_TRUNC) ? " force" : ""); ret = delete_module(name, flags); if (ret != 0) error(log, "Removing '%s': %s\n", name, strerror(errno)); return ret; }
static struct module_entry *helper_get_module(const char *module, int create) { char modname[MODULE_NAME_LEN]; struct module_entry *e; llist_t *l; filename2modname(module, modname); for (l = G.db; l != NULL; l = l->link) { e = (struct module_entry *) l->data; if (strcmp(e->modname, modname) == 0) return e; } if (!create) return NULL; e = xzalloc(sizeof(*e)); e->modname = xstrdup(modname); llist_add_to(&G.db, e); return e; }
extern int rmmod_main(int argc, char **argv) { int n, ret = EXIT_SUCCESS; unsigned int flags = O_NONBLOCK|O_EXCL; #ifdef CONFIG_FEATURE_QUERY_MODULE_INTERFACE /* bb_common_bufsiz1 hold the module names which we ignore but must get */ size_t bufsize = sizeof(bb_common_bufsiz1); #endif /* Parse command line. */ n = bb_getopt_ulflags(argc, argv, "wfa"); if((n & 1)) // --wait flags &= ~O_NONBLOCK; if((n & 2)) // --force flags |= O_TRUNC; if((n & 4)) { /* Unload _all_ unused modules via NULL delete_module() call */ /* until the number of modules does not change */ size_t nmod = 0; /* number of modules */ size_t pnmod = -1; /* previous number of modules */ while (nmod != pnmod) { if (syscall(__NR_delete_module, NULL, flags) != 0) { if (errno==EFAULT) return(ret); bb_perror_msg_and_die("rmmod"); } pnmod = nmod; #ifdef CONFIG_FEATURE_QUERY_MODULE_INTERFACE /* 1 == QM_MODULES */ if (my_query_module(NULL, 1, &bb_common_bufsiz1, &bufsize, &nmod)) { bb_perror_msg_and_die("QM_MODULES"); } #endif } return EXIT_SUCCESS; } if (optind == argc) bb_show_usage(); for (n = optind; n < argc; n++) { #ifdef CONFIG_FEATURE_2_6_MODULES const char *afterslash; char *module_name; afterslash = strrchr(argv[n], '/'); if (!afterslash) afterslash = argv[n]; else afterslash++; module_name = alloca(strlen(afterslash) + 1); filename2modname(module_name, afterslash); #else #define module_name argv[n] #endif if (syscall(__NR_delete_module, module_name, flags) != 0) { bb_perror_msg("%s", argv[n]); ret = EXIT_FAILURE; } } return(ret); }