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

📄 modprobe.c

📁 用于linux2.6内核支持模块的插入和卸载
💻 C
📖 第 1 页 / 共 3 页
字号:
/* modprobe.c: insert a module into the kernel, intelligently.    Copyright (C) 2001  Rusty Russell.    Copyright (C) 2002, 2003  Rusty Russell, IBM Corporation.    This program is free software; you can redistribute it and/or modify    it under the terms of the GNU General Public License as published by    the Free Software Foundation; either version 2 of the License, or    (at your option) any later version.    This program is distributed in the hope that it will be useful,    but WITHOUT ANY WARRANTY; without even the implied warranty of    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    GNU General Public License for more details.    You should have received a copy of the GNU General Public License    along with this program; if not, write to the Free Software    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA*/#define _GNU_SOURCE /* asprintf */#include <sys/utsname.h>#include <sys/types.h>#include <sys/stat.h>#include <sys/mman.h>#include <fcntl.h>#include <stdarg.h>#include <stdio.h>#include <stdlib.h>#include <ctype.h>#include <string.h>#include <errno.h>#include <unistd.h>#include <dirent.h>#include <limits.h>#include <elf.h>#include <getopt.h>#include <fnmatch.h>#include <asm/unistd.h>#include <sys/wait.h>#include <syslog.h>#define streq(a,b) (strcmp((a),(b)) == 0)#include "zlibsupport.h"#include "list.h"#include "backwards_compat.c"extern long init_module(void *, unsigned long, const char *);extern long delete_module(const char *, unsigned int);struct module {	struct list_head list;	char *modname;	char filename[0];};#ifndef MODULE_DIR#define MODULE_DIR "/lib/modules"#endiftypedef void (*errfn_t)(const char *fmt, ...);/* Do we use syslog or stderr for messages? */static int log;static void message(const char *prefix, const char *fmt, va_list *arglist){	char *buf, *buf2;	vasprintf(&buf, fmt, *arglist);	asprintf(&buf2, "%s%s", prefix, buf);	if (log)		syslog(LOG_NOTICE, buf2);	else		fprintf(stderr, "%s", buf2);	free(buf2);	free(buf);}static void warn(const char *fmt, ...){	va_list arglist;	va_start(arglist, fmt);	message("WARNING: ", fmt, &arglist);	va_end(arglist);}static void fatal(const char *fmt, ...){	va_list arglist;	va_start(arglist, fmt);	message("FATAL: ", fmt, &arglist);	va_end(arglist);	exit(1);}static void grammar(const char *cmd, const char *filename, unsigned int line){	warn("%s line %u: ignoring bad line starting with '%s'\n",	     filename, line, cmd);}static 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 NOFAIL(ptr)	do_nofail((ptr), __FILE__, __LINE__, #ptr)static void print_usage(const char *progname){	fprintf(stderr,		"Usage: %s [-v] [-V] [-C config-file] [-n] [-i] [-q] [-o <modname>] <modname> [parameters...]\n"		"%s -r [-n] [-i] [-v] <modulename> ...\n"		"%s -l -t <dirname> [ -a <modulename> ...]\n",		progname, progname, progname);	exit(1);}static int fgetc_wrapped(FILE *file, unsigned int *linenum){	for (;;) {	  	int ch = fgetc(file);		if (ch != '\\')			return ch;		ch = fgetc(file);		if (ch != '\n')			return ch;		if (linenum)			(*linenum)++;	}}static char *getline_wrapped(FILE *file, unsigned int *linenum){	int size = 1024;	int i = 0;	char *buf = NOFAIL(malloc(size));	for(;;) {		int ch = fgetc_wrapped(file, linenum);		if (i == size) {			size *= 2;			buf = NOFAIL(realloc(buf, size));		}		if (ch < 0 && i == 0) {			free(buf);			return NULL;		}		if (ch < 0 || ch == '\n') {			if (linenum)				(*linenum)++;			buf[i] = '\0';			return NOFAIL(realloc(buf, i+1));		}		buf[i++] = ch;	}}static struct module *find_module(const char *filename, struct list_head *list){	struct module *i;	list_for_each_entry(i, list, list) {		if (strcmp(i->filename, filename) == 0)			return i;	}	return NULL;}/* Convert filename to the module name.  Works if filename == modname, too. */static void filename2modname(char *modname, const char *filename){	const char *afterslash;	unsigned int i;	afterslash = strrchr(filename, '/');	if (!afterslash)		afterslash = filename;	else		afterslash++;	/* Convert to underscores, stop at first . */	for (i = 0; afterslash[i] && afterslash[i] != '.'; i++) {		if (afterslash[i] == '-')			modname[i] = '_';		else			modname[i] = afterslash[i];	}	modname[i] = '\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);}/* Compare len chars of a to b, with _ and - equivalent. */static int modname_equal(const char *a, const char *b, unsigned int len){	unsigned int i;	if (strlen(b) != len)		return 0;	for (i = 0; i < len; i++) {		if ((a[i] == '_' || a[i] == '-')		    && (b[i] == '_' || b[i] == '-'))			continue;		if (a[i] != b[i])			return 0;	}	return 1;}/* Fills in list of modules if this is the line we want. */static int add_modules_dep_line(char *line,				const char *name,				struct list_head *list){	char *ptr;	int len;	char *modname;	/* Ignore lines without : or which start with a # */	ptr = index(line, ':');	if (ptr == NULL || line[strspn(line, "\t ")] == '#')		return 0;	/* Is this the module we are looking for? */	*ptr = '\0';	if (strrchr(line, '/'))		modname = strrchr(line, '/') + 1;	else		modname = line;	len = strlen(modname);	if (strchr(modname, '.'))		len = strchr(modname, '.') - modname;	if (!modname_equal(modname, name, len))		return 0;	/* Create the list. */	add_module(line, ptr - line, list);	ptr++;	for(;;) {		char *dep_start;		ptr += strspn(ptr, " \t");		if (*ptr == '\0')			break;		dep_start = ptr;		ptr += strcspn(ptr, " \t");		add_module(dep_start, ptr - dep_start, list);	}	return 1;}static void read_depends(const char *dirname,			 const char *start_name,			 struct list_head *list){	char *modules_dep_name;	char *line;	FILE *modules_dep;	int done = 0;	asprintf(&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));	/* Stop at first line, as we can have duplicates (eg. symlinks           from boot/ */	while (!done && (line = getline_wrapped(modules_dep, NULL)) != NULL) {		done = add_modules_dep_line(line, start_name, list);		free(line);	}	fclose(modules_dep);	free(modules_dep_name);}/* We use error numbers in a loose translation... */static const char *insert_moderror(int err){	switch (err) {	case ENOEXEC:		return "Invalid module format";	case ENOENT:		return "Unknown symbol in module, or unknown parameter (see dmesg)";	case ENOSYS:		return "Kernel does not have module support";	default:		return strerror(err);	}}static const char *remove_moderror(int err){	switch (err) {	case ENOENT:		return "No such module";	case ENOSYS:		return "Kernel does not have module unloading support";	default:		return strerror(err);	}}/* Is module in /proc/modules?  If so, fill in usecount if not NULL.    0 means no, 1 means yes, -1 means unknown. */static int module_in_kernel(const char *modname, int *usecount){	FILE *proc_modules;	char *line;	/* Might not be mounted yet.  Don't fail. */	proc_modules = fopen("/proc/modules", "r");	if (!proc_modules)		return -1;	while ((line = getline_wrapped(proc_modules, NULL)) != NULL) {		char *entry = strtok(line, " \n");		if (entry && strcmp(entry, modname) == 0) {			/* If it exists, usecount is the third entry. */			if (usecount) {				entry = strtok(NULL, " \n");				if (entry				    && (entry = strtok(NULL, " \n")) != NULL)					*usecount = atoi(entry);			}			free(line);			fclose(proc_modules);			return 1;		}		free(line);	}	fclose(proc_modules);	return 0;}static void replace_modname(struct module *module,			    void *mem, unsigned long len,			    const char *oldname, const char *newname){	char *p;	/* 64 - sizeof(unsigned long) - 1 */	if (strlen(newname) > 55)		fatal("New name %s is too long\n", newname);	/* Find where it is in the module structure.  Don't assume layout! */	for (p = mem; p < (char *)mem + len - strlen(oldname); p++) {		if (memcmp(p, oldname, strlen(oldname)) == 0) {			strcpy(p, newname);			return;		}	}	warn("Could not find old name in %s to replace!\n", module->filename);}static void *get_section32(void *file,			   unsigned long size,			   const char *name,			   unsigned long *secsize){	Elf32_Ehdr *hdr = file;	Elf32_Shdr *sechdrs = file + hdr->e_shoff;	const char *secnames;	unsigned int i;	/* Too short? */	if (size < sizeof(*hdr))		return NULL;	if (size < hdr->e_shoff + hdr->e_shnum * sizeof(sechdrs[0]))		return NULL;	if (size < sechdrs[hdr->e_shstrndx].sh_offset)		return NULL;			secnames = file + sechdrs[hdr->e_shstrndx].sh_offset;	for (i = 1; i < hdr->e_shnum; i++)		if (strcmp(secnames + sechdrs[i].sh_name, name) == 0) {			*secsize = sechdrs[i].sh_size;			return file + sechdrs[i].sh_offset;		}	return NULL;}static void *get_section64(void *file,			   unsigned long size,			   const char *name,			   unsigned long *secsize){	Elf64_Ehdr *hdr = file;	Elf64_Shdr *sechdrs = file + hdr->e_shoff;	const char *secnames;	unsigned int i;	/* Too short? */	if (size < sizeof(*hdr))		return NULL;	if (size < hdr->e_shoff + hdr->e_shnum * sizeof(sechdrs[0]))		return NULL;	if (size < sechdrs[hdr->e_shstrndx].sh_offset)		return NULL;			secnames = file + sechdrs[hdr->e_shstrndx].sh_offset;	for (i = 1; i < hdr->e_shnum; i++)		if (strcmp(secnames + sechdrs[i].sh_name, name) == 0) {			*secsize = sechdrs[i].sh_size;			return file + sechdrs[i].sh_offset;		}	return NULL;}static int elf_ident(void *mod, unsigned long size){	/* "\177ELF" <byte> where byte = 001 for 32-bit, 002 for 64 */	char *ident = mod;	if (size < EI_CLASS || memcmp(mod, ELFMAG, SELFMAG) != 0)		return ELFCLASSNONE;	return ident[EI_CLASS];}static void *get_section(void *file,			 unsigned long size,			 const char *name,			 unsigned long *secsize){	switch (elf_ident(file, size)) {

⌨️ 快捷键说明

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