⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 depmod.c

📁 用于linux2.6内核支持模块的插入和卸载
💻 C
📖 第 1 页 / 共 2 页
字号:
/* New simplified depmod without backwards compat stuff and not   requiring ksyms.   (C) 2002 Rusty Russell IBM Corporation */#include <stdarg.h>#include <stdio.h>#include <stdlib.h>#include <getopt.h>#include <string.h>#include <errno.h>#include <unistd.h>#include <elf.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <dirent.h>#include <sys/utsname.h>#include <sys/mman.h>#include "zlibsupport.h"#include "depmod.h"#include "moduleops.h"#include "tables.h"#include "testing.h"/* I hate strcmp. */#define streq(a,b) (strcmp((a),(b)) == 0)#ifndef MODULE_DIR#define MODULE_DIR "/lib/modules/"#endifstatic int verbose;static unsigned int skipchars;void fatal(const char *fmt, ...){	va_list arglist;	fprintf(stderr, "FATAL: ");	va_start(arglist, fmt);	vfprintf(stderr, fmt, arglist);	va_end(arglist);	exit(1);}void warn(const char *fmt, ...){	va_list arglist;	fprintf(stderr, "WARNING: ");	va_start(arglist, fmt);	vfprintf(stderr, fmt, arglist);	va_end(arglist);}void *do_nofail(void *ptr, const char *file, int line, const char *expr){	if (!ptr) {		fatal("Memory allocation failure %s line %d: %s.\n",		      file, line, expr);	}	return ptr;}#define SYMBOL_HASH_SIZE 1024struct symbol{	struct symbol *next;	struct module *owner;	char name[0];};static struct symbol *symbolhash[SYMBOL_HASH_SIZE];/* This is based on the hash agorithm from gdbm, via tdb */static inline unsigned int tdb_hash(const char *name){	unsigned value;	/* Used to compute the hash value.  */	unsigned   i;	/* Used to cycle through random values. */	/* Set the initial value from the key size. */	for (value = 0x238F13AF * strlen(name), i=0; name[i]; i++)		value = (value + (((unsigned char *)name)[i] << (i*5 % 24)));	return (1103515243 * value + 12345);}void add_symbol(const char *name, struct module *owner){	unsigned int hash;	struct symbol *new = NOFAIL(malloc(sizeof *new + strlen(name) + 1));	new->owner = owner;	strcpy(new->name, name);	hash = tdb_hash(name) % SYMBOL_HASH_SIZE;	new->next = symbolhash[hash];	symbolhash[hash] = new;}static int print_unknown;struct module *find_symbol(const char *name, const char *modname, int weak){	struct symbol *s;	/* For our purposes, .foo matches foo.  PPC64 needs this. */	if (name[0] == '.')		name++;	for (s = symbolhash[tdb_hash(name) % SYMBOL_HASH_SIZE]; s; s=s->next) {		if (streq(s->name, name))			return s->owner;	}	if (print_unknown && !weak)		warn("%s needs unknown symbol %s\n", modname, name);	return NULL;}void add_dep(struct module *mod, struct module *depends_on){	unsigned int i;	for (i = 0; i < mod->num_deps; i++)		if (mod->deps[i] == depends_on)			return;	mod->deps = realloc(mod->deps, sizeof(mod->deps[0])*(mod->num_deps+1));	mod->deps[mod->num_deps++] = depends_on;}static void load_system_map(const char *filename){	FILE *system_map;	char line[10240];	system_map = fopen(filename, "r");	if (!system_map)		fatal("Could not open '%s': %s\n", filename, strerror(errno));	/* eg. c0294200 R __ksymtab_devfs_alloc_devnum */	while (fgets(line, sizeof(line)-1, system_map)) {		char *ptr;		/* Snip \n */		ptr = strchr(line, '\n');		*ptr = '\0';		ptr = strchr(line, ' ');		if (!ptr || !(ptr = strchr(ptr + 1, ' ')))			continue;		/* Covers gpl-only and normal symbols. */		if (strncmp(ptr+1, "__ksymtab_", strlen("__ksymtab_")) == 0)			add_symbol(ptr+1+strlen("__ksymtab_"), NULL);	}	/* __this_module is magic inserted by kernel loader. */	add_symbol("__this_module", NULL);	/* On S390, this is faked up too */	add_symbol("_GLOBAL_OFFSET_TABLE_", NULL);}static struct option options[] = { { "all", 0, NULL, 'a' },				   { "quick", 0, NULL, 'A' },				   { "basedir", 1, NULL, 'b' },				   { "errsyms", 0, NULL, 'e' },				   { "filesyms", 1, NULL, 'F' },				   { "help", 0, NULL, 'h' },				   { "show", 0, NULL, 'n' },				   { "dry-run", 0, NULL, 'n' },				   { "quiet", 0, NULL, 'q' },				   { "root", 0, NULL, 'r' },				   { "unresolved-error", 0, NULL, 'u' },				   { "verbose", 0, NULL, 'v' },				   { "version", 0, NULL, 'V' },				   /* Obsolete, but we need to parse it. */				   { "config", 1, NULL, 'C' },				   { NULL, 0, NULL, 0 } };/* Version number or module name?  Don't assume extension. */static int is_version_number(const char *version){	unsigned int dummy;	return (sscanf(version, "%u.%u.%u", &dummy, &dummy, &dummy) == 3);}static int old_module_version(const char *version){	/* Expect three part version. */	unsigned int major, sub, minor;	sscanf(version, "%u.%u.%u", &major, &sub, &minor);	if (major > 2) return 0;	if (major < 2) return 1;	/* 2.x */	if (sub > 5) return 0;	if (sub < 5) return 1;	/* 2.5.x */	if (minor >= 48) return 0;	return 1;}static void exec_old_depmod(char *argv[]){	char *sep;	char pathname[strlen(argv[0])+1];	char oldname[strlen("depmod") + strlen(argv[0]) + sizeof(".old")];	memset(pathname, 0, strlen(argv[0])+1);	sep = strrchr(argv[0], '/');	if (sep)		memcpy(pathname, argv[0], sep - argv[0]+1);	sprintf(oldname, "%s%s.old", pathname, "depmod");	/* Recursion detection: we need an env var since we can't	   change argv[0] (as older modutils uses it to determine	   behavior). */	if (getenv("MODULE_RECURSE"))		return;	setenv("MODULE_RECURSE", "y", 0);	execvp(oldname, argv);	fprintf(stderr,		"Version requires old depmod, but couldn't run %s: %s\n",		oldname, strerror(errno));	exit(2);}static void print_usage(const char *name){	fprintf(stderr,	"%s " VERSION " -- part of " PACKAGE "\n"	"%s -[aA] [-n -e -v -q -V -r -u]\n"	"      [-b basedirectory] [forced_version]\n"	"depmod [-n -e -v -q -r -u] [-F kernelsyms] module1.o module2.o ...\n"	"If no arguments (except options) are given, \"depmod -a\" is assumed\n"	"\n"	"depmod will output a dependancy list suitable for the modprobe utility.\n"	"\n"	"\n"	"Options:\n"	"\t-a, --all            Probe all modules\n"	"\t-n, --show           Write the dependency file on stdout only\n"	"\t-V, --version        Print the release version\n"	"\t-h, --help           Print this usage message\n"	"\n"	"The following options are useful for people managing distributions:\n"	"\t-b basedirectory\n"	"\t    --basedir basedirectory    Use an image of a module tree.\n"	"\t-F kernelsyms\n"	"\t    --filesyms kernelsyms      Use the file instead of the\n"	"\t                               current kernel symbols.\n",	"depmod", "depmod");}static int ends_in(const char *name, const char *ext){	unsigned int namelen, extlen;	/* Grab lengths */	namelen = strlen(name);	extlen = strlen(ext);	if (namelen < extlen) return 0;	if (streq(name + namelen - extlen, ext))		return 1;	return 0;}static struct module *grab_module(const char *dirname,				  const char *filename,				  struct module *next){	struct module *new;	new = NOFAIL(malloc(sizeof(*new)			    + strlen(dirname) + 1 + strlen(filename) + 1));	sprintf(new->pathname, "%s/%s", dirname, filename);	INIT_LIST_HEAD(&new->dep_list);	new->data = grab_file(new->pathname, &new->len);	if (!new->data) {		warn("Can't read module %s: %s\n",		     new->pathname, strerror(errno));		goto fail_data;	}	/* "\177ELF" <byte> where byte = 001 for 32-bit, 002 for 64 */	if (memcmp(new->data, ELFMAG, SELFMAG) != 0) {		warn("Module %s is not an elf object\n", new->pathname);		goto fail;	}	switch (((char *)new->data)[EI_CLASS]) {	case ELFCLASS32:		new->ops = &mod_ops32;		break;	case ELFCLASS64:		new->ops = &mod_ops64;		break;	default:		warn("Module %s has elf unknown identifier %i\n",		     new->pathname, ((char *)new->data)[EI_CLASS]);		goto fail;	}	new->ops->load_symbols(new);	new->ops->fetch_tables(new);	new->next = next;	return new;fail:	release_file(new->data, new->len);fail_data:	free(new);	return next;}struct module_traverse{	struct module_traverse *prev;	struct module *mod;};static int in_loop(struct module *mod, const struct module_traverse *traverse){	const struct module_traverse *i;	for (i = traverse; i; i = i->prev) {		if (i->mod == mod)			return 1;	}	return 0;}static char *basename(const char *name){	const char *base = strrchr(name, '/');	if (base) return (char *)base + 1;	return (char *)name;}/* Assume we are doing all the modules, so only report each loop once. */static void report_loop(const struct module *mod,			const struct module_traverse *traverse){	const struct module_traverse *i;	/* Check that start is least alphabetically.  eg.  a depends	   on b depends on a will get reported for a, not b.  */	for (i = traverse->prev; i->prev; i = i->prev) {		if (strcmp(mod->pathname, i->mod->pathname) > 0)			return;	}	/* Is start in the loop?  If not, don't report now. eg. a	   depends on b which depends on c which depends on b.  Don't	   report when generating depends for a. */	if (mod != i->mod)		return;	warn("Loop detected: %s ", mod->pathname);	for (i = traverse->prev; i->prev; i = i->prev)		fprintf(stderr, "needs %s ", basename(i->mod->pathname));	fprintf(stderr, "which needs %s again!\n", basename(mod->pathname));}/* This is damn slow, but loops actually happen, and we don't want to   just exit() and leave the user without any modules. */static int has_dep_loop(struct module *module, struct module_traverse *prev){	unsigned int i;	struct module_traverse traverse = { .prev = prev, .mod = module };	if (in_loop(module, prev)) {		report_loop(module, &traverse);		return 1;	}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -