?? modprobe.c
字號:
case ELFCLASS32: return get_section32(file, size, name, secsize); case ELFCLASS64: return get_section64(file, size, name, secsize); default: return NULL; }}static void rename_module(struct module *module, void *mod, unsigned long len, const char *newname){ void *modstruct; unsigned long modstruct_len; /* Old-style */ modstruct = get_section(mod, len, ".gnu.linkonce.this_module", &modstruct_len); /* New-style */ if (!modstruct) modstruct = get_section(mod, len, "__module", &modstruct_len); if (!modstruct) warn("Could not find module name to change in %s\n", module->filename); else replace_modname(module, modstruct, modstruct_len, module->modname, newname);}/* Kernel told to ignore these sections if SHF_ALLOC not set. */static void invalidate_section32(void *mod, const char *secname){ Elf32_Ehdr *hdr = mod; Elf32_Shdr *sechdrs = mod + hdr->e_shoff; const char *secnames = mod + sechdrs[hdr->e_shstrndx].sh_offset; unsigned int i; for (i = 1; i < hdr->e_shnum; i++) if (strcmp(secnames+sechdrs[i].sh_name, secname) == 0) sechdrs[i].sh_flags &= ~SHF_ALLOC;}static void invalidate_section64(void *mod, const char *secname){ Elf64_Ehdr *hdr = mod; Elf64_Shdr *sechdrs = mod + hdr->e_shoff; const char *secnames = mod + sechdrs[hdr->e_shstrndx].sh_offset; unsigned int i; for (i = 1; i < hdr->e_shnum; i++) if (strcmp(secnames+sechdrs[i].sh_name, secname) == 0) sechdrs[i].sh_flags &= ~(unsigned long long)SHF_ALLOC;}static void strip_section(struct module *module, void *mod, unsigned long len, const char *secname){ switch (elf_ident(mod, len)) { case ELFCLASS32: invalidate_section32(mod, secname); break; case ELFCLASS64: invalidate_section64(mod, secname); break; default: warn("Unknown module format in %s: not forcing version\n", module->filename); }}static const char *next_string(const char *string, unsigned long *secsize){ /* Skip non-zero chars */ while (string[0]) { string++; if ((*secsize)-- <= 1) return NULL; } /* Skip any zero padding. */ while (!string[0]) { string++; if ((*secsize)-- <= 1) return NULL; } return string;}static void clear_magic(struct module *module, void *mod, unsigned long len){ const char *p; unsigned long modlen; /* Old-style: __vermagic section */ strip_section(module, mod, len, "__vermagic"); /* New-style: in .modinfo section */ for (p = get_section(mod, len, ".modinfo", &modlen); p; p = next_string(p, &modlen)) { if (strncmp(p, "vermagic=", strlen("vermagic=")) == 0) { memset((char *)p, 0, strlen(p)); return; } }}struct module_options{ struct module_options *next; char *modulename; char *options;};struct module_command{ struct module_command *next; char *modulename; char *command;};/* Link in a new option line from the config file. */static struct module_options *add_options(const char *modname, const char *option, struct module_options *options){ struct module_options *new; char *tab; new = NOFAIL(malloc(sizeof(*new))); new->modulename = NOFAIL(strdup(modname)); new->options = NOFAIL(strdup(option)); /* We can handle tabs, kernel can't. */ for (tab = strchr(new->options, '\t'); tab; tab = strchr(tab, '\t')) *tab = ' '; new->next = options; return new;}/* Link in a new install line from the config file. */static struct module_command *add_command(const char *modname, const char *command, struct module_command *commands){ struct module_command *new; new = NOFAIL(malloc(sizeof(*new))); new->modulename = NOFAIL(strdup(modname)); new->command = NOFAIL(strdup(command)); new->next = commands; return new;}/* Find install commands if any. */static const char *find_command(const char *modname, const struct module_command *commands){ while (commands) { if (fnmatch(commands->modulename, modname, 0) == 0) return commands->command; commands = commands->next; } return NULL;}static char *append_option(char *options, const char *newoption){ options = NOFAIL(realloc(options, strlen(options) + 1 + strlen(newoption) + 1)); if (strlen(options)) strcat(options, " "); strcat(options, newoption); return options;}/* Add to options */static char *add_extra_options(const char *modname, char *optstring, const struct module_options *options){ while (options) { if (strcmp(options->modulename, modname) == 0) optstring = append_option(optstring, options->options); options = options->next; } return optstring;}/* If we don't flush, then child processes print before we do */static void verbose_printf(int verbose, const char *fmt, ...){ va_list arglist; if (verbose) { va_start(arglist, fmt); vprintf(fmt, arglist); fflush(stdout); va_end(arglist); }}/* Do an install/remove command. */static void do_command(const char *modname, const char *command, int verbose, int dry_run, errfn_t error, const char *type){ int ret; verbose_printf(verbose, "%s %s\n", type, command); if (dry_run) return; setenv("MODPROBE_MODULE", modname, 1); ret = system(command); if (ret == -1 || WEXITSTATUS(ret)) error("Error running %s command for %s\n", type, modname);}/* Actually do the insert. Frees second arg. */static void insmod(struct list_head *list, char *optstring, const char *newname, int first_time, errfn_t error, int dry_run, int verbose, const struct module_options *options, const struct module_command *commands, int ignore_commands, int ignore_proc, int strip_vermagic, int strip_modversion){ int ret; unsigned long len; void *map; const char *command; struct module *mod = list_entry(list->next, struct module, list); /* Take us off the list. */ list_del(&mod->list); /* Do things we (or parent) depend on first, but don't die if * they fail. */ if (!list_empty(list)) { insmod(list, NOFAIL(strdup("")), NULL, 0, warn, dry_run, verbose, options, commands, 0, ignore_proc, strip_vermagic, strip_modversion); } /* Don't do ANYTHING if already in kernel. */ if (!ignore_proc && module_in_kernel(newname ?: mod->modname, NULL) == 1) goto exists_error; command = find_command(mod->modname, commands); if (command && !ignore_commands) { do_command(mod->modname, command, verbose, dry_run, error, "install"); goto out_optstring; } map = grab_file(mod->filename, &len); if (!map) { error("Could not open '%s': %s\n", mod->filename, strerror(errno)); goto out_optstring; } /* Rename it? */ if (newname) rename_module(mod, map, len, newname); if (strip_modversion) strip_section(mod, map, len, "__versions"); if (strip_vermagic) clear_magic(mod, map, len); /* Config file might have given more options */ optstring = add_extra_options(mod->modname, optstring, options); verbose_printf(verbose, "insmod %s %s\n", mod->filename, optstring); if (dry_run) goto out; ret = init_module(map, len, optstring); if (ret != 0) { if (errno == EEXIST) goto exists_error; error("Error inserting %s (%s): %s\n", mod->modname, mod->filename, insert_moderror(errno)); } out: release_file(map, len); out_optstring: free(optstring); return;exists_error: if (first_time) error("Module %s already in kernel.\n", newname ?: mod->modname); goto out_optstring;}/* Do recursive removal. */static void rmmod(struct list_head *list, int first_time, errfn_t error, int dry_run, int verbose, struct module_command *commands, int ignore_commands, int ignore_inuse){ const char *command; unsigned int usecount = 0; struct module *mod = list_entry(list->next, struct module, list); /* Take first one off the list. */ list_del(&mod->list); command = find_command(mod->modname, commands); if (command && !ignore_commands) { do_command(mod->modname, command, verbose, dry_run, error, "remove"); goto remove_rest; } if (module_in_kernel(mod->modname, &usecount) == 0) goto nonexistent_module; if (usecount != 0) { if (!ignore_inuse) error("Module %s is in use.\n", mod->modname); goto remove_rest; } verbose_printf(verbose, "rmmod %s\n", mod->filename); if (dry_run) goto remove_rest; if (delete_module(mod->modname, O_EXCL) != 0) { if (errno == ENOENT) goto nonexistent_module; error("Error removing %s (%s): %s\n", mod->modname, mod->filename, remove_moderror(errno)); } remove_rest: /* Now do things we depend. */ if (!list_empty(list)) rmmod(list, 0, warn, dry_run, verbose, commands, 0, 1); return;nonexistent_module: if (first_time) fatal("Module %s is not in kernel.\n", mod->modname); goto remove_rest;}/* Does path contain directory(s) subpath? */static int type_matches(const char *path, const char *subpath){ char *subpath_with_slashes; int ret; asprintf(&subpath_with_slashes, "/%s/", subpath); NOFAIL(subpath_with_slashes); ret = (strstr(path, subpath_with_slashes) != NULL); free(subpath_with_slashes); return ret;}static char *underscores(char *string){ if (string) { unsigned int i; for (i = 0; string[i]; i++) if (string[i] == '-') string[i] = '_'; } return string;}static int do_wildcard(const char *dirname, const char *type, const char *wildcard){ char modules_dep_name[strlen(dirname) + sizeof("modules.dep") + 1]; char *line, *wcard; FILE *modules_dep; /* Canonicalize wildcard */ wcard = strdup(wildcard); underscores(wcard); sprintf(modules_dep_name, "%s/%s", dirname, "modules.dep"); modules_dep = fopen(modules_dep_name, "r"); if (!modules_dep) fatal("Could not load %s: %s\n", modules_dep_name, strerror(errno)); while ((line = getline_wrapped(modules_dep, NULL)) != NULL) { char *ptr; /* Ignore lines without : or which start with a # */ ptr = strchr(line, ':'); if (ptr == NULL || line[strspn(line, "\t ")] == '#') goto next; *ptr = '\0'; /* "type" must match complete directory component(s). */ if (!type || type_matches(line, type)) { char modname[strlen(line)+1]; filename2modname(modname, line); if (fnmatch(wcard, modname, 0) == 0) printf("%s\n", line); } next: free(line); } free(wcard); return 0;}static char *strsep_skipspace(char **string, char *delim){ if (!*string) return NULL; *string += strspn(*string, delim); return strsep(string, delim);}/* FIXME: Maybe should be extended to "alias a b [and|or c]...". --RR *//* Simple format, ignore lines starting with #, one command per line. Returns NULL or resolved alias. */static char *read_config(const char *filename, int mustload, const char *name, int dump_only,
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -