mirror of
https://github.com/sheumann/hush.git
synced 2025-01-11 23:29:51 +00:00
modutils/*: rewrite by Timo Teras <timo.teras AT iki.fi>
- a lot faster (linear algorithmic complexity, smaller memory foot print) - a lot smaller (the old code was overly complicated) - loading of aliases is now module-init-tools compliant - blacklisting is done correctly (-b option added) - module argument quoting done right - depmod now correctly generates modules.symbols and modules.alias add/remove: 16/21 grow/shrink: 4/6 up/down: 6930/-9316 Total: -2386 bytes text data bss dec hex filename 806039 592 6680 813311 c68ff busybox_old 803498 592 6676 810766 c5f0e busybox_unstripped
This commit is contained in:
parent
4f3209b9d4
commit
ba1315d0fb
@ -2569,12 +2569,17 @@
|
||||
"[-knqrsv] MODULE [symbol=value...]"
|
||||
#define modprobe_full_usage "\n\n" \
|
||||
"Options:" \
|
||||
USE_FEATURE_2_4_MODULES( \
|
||||
"\n -k Make module autoclean-able" \
|
||||
) \
|
||||
"\n -n Dry run" \
|
||||
"\n -q Quiet" \
|
||||
"\n -r Remove module (stacks) or do autoclean" \
|
||||
"\n -s Report via syslog instead of stderr" \
|
||||
"\n -v Verbose" \
|
||||
USE_FEATURE_MODPROBE_BLACKLIST( \
|
||||
"\n -b Apply blacklist to module names too" \
|
||||
)
|
||||
|
||||
#define modprobe_notes_usage \
|
||||
"modprobe can (un)load a stack of modules, passing each module options (when\n" \
|
||||
|
@ -90,7 +90,6 @@ void FAST_FUNC llist_free(llist_t *elm, void (*freeit) (void *data))
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef UNUSED
|
||||
/* Reverse list order. */
|
||||
llist_t* FAST_FUNC llist_rev(llist_t *list)
|
||||
{
|
||||
@ -105,4 +104,3 @@ llist_t* FAST_FUNC llist_rev(llist_t *list)
|
||||
}
|
||||
return rev;
|
||||
}
|
||||
#endif
|
||||
|
@ -5,6 +5,20 @@
|
||||
|
||||
menu "Linux Module Utilities"
|
||||
|
||||
config DEFAULT_MODULES_DIR
|
||||
string "Default directory containing modules"
|
||||
default "/lib/modules"
|
||||
help
|
||||
Directory that contains kernel modules.
|
||||
Defaults to "/lib/modules"
|
||||
|
||||
config DEFAULT_DEPMOD_FILE
|
||||
string "Default name of modules.dep"
|
||||
default "modules.dep"
|
||||
help
|
||||
Filename that contains kernel modules dependencies.
|
||||
Defaults to "modules.dep"
|
||||
|
||||
config MODPROBE_SMALL
|
||||
bool "Simplified modutils"
|
||||
default n
|
||||
@ -54,37 +68,6 @@ config FEATURE_MODPROBE_SMALL_CHECK_ALREADY_LOADED
|
||||
Check if the module is already loaded.
|
||||
N.B. It's racy.
|
||||
|
||||
config DEPMOD
|
||||
bool "depmod"
|
||||
default n
|
||||
depends on !MODPROBE_SMALL
|
||||
help
|
||||
depmod generates modules.dep (FIXME: elaborate)
|
||||
|
||||
config FEATURE_DEPMOD_PRUNE_FANCY
|
||||
bool "Fancy dependency pruning"
|
||||
default n
|
||||
depends on DEPMOD
|
||||
help
|
||||
By default modules.dep contains all dependencies as listed by
|
||||
the modules.
|
||||
If you enable this option then we remove implied modules from
|
||||
the dependencies.
|
||||
This makes depmod somewhat bigger but generates a smaller
|
||||
modules.dep file.
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
config FEATURE_DEPMOD_ALIAS
|
||||
bool "Alias support"
|
||||
default n
|
||||
depends on DEPMOD
|
||||
help
|
||||
By default modules.dep does not contain alias information.
|
||||
Enable this to emit aliases of the form:
|
||||
|
||||
alias pcmcia:m*c*f03fn*pfn*pa*pb*pc*pd* parport_cs
|
||||
|
||||
config INSMOD
|
||||
bool "insmod"
|
||||
default n
|
||||
@ -92,55 +75,6 @@ config INSMOD
|
||||
help
|
||||
insmod is used to load specified modules in the running kernel.
|
||||
|
||||
config FEATURE_INSMOD_VERSION_CHECKING
|
||||
bool "Module version checking"
|
||||
default n
|
||||
depends on INSMOD && FEATURE_2_4_MODULES
|
||||
help
|
||||
Support checking of versions for modules. This is used to
|
||||
ensure that the kernel and module are made for each other.
|
||||
|
||||
config FEATURE_INSMOD_KSYMOOPS_SYMBOLS
|
||||
bool "Add module symbols to kernel symbol table"
|
||||
default n
|
||||
depends on INSMOD && FEATURE_2_4_MODULES
|
||||
help
|
||||
By adding module symbols to the kernel symbol table, Oops messages
|
||||
occuring within kernel modules can be properly debugged. By enabling
|
||||
this feature, module symbols will always be added to the kernel symbol
|
||||
table for properly debugging support. If you are not interested in
|
||||
Oops messages from kernel modules, say N.
|
||||
|
||||
config FEATURE_INSMOD_LOADINKMEM
|
||||
bool "In kernel memory optimization (uClinux only)"
|
||||
default n
|
||||
depends on INSMOD && FEATURE_2_4_MODULES
|
||||
help
|
||||
This is a special uClinux only memory optimization that lets insmod
|
||||
load the specified kernel module directly into kernel space, reducing
|
||||
memory usage by preventing the need for two copies of the module
|
||||
being loaded into memory.
|
||||
|
||||
config FEATURE_INSMOD_LOAD_MAP
|
||||
bool "Enable load map (-m) option"
|
||||
default n
|
||||
depends on INSMOD && ( FEATURE_2_4_MODULES || FEATURE_2_6_MODULES )
|
||||
help
|
||||
Enabling this, one would be able to get a load map
|
||||
output on stdout. This makes kernel module debugging
|
||||
easier.
|
||||
If you don't plan to debug kernel modules, you
|
||||
don't need this option.
|
||||
|
||||
config FEATURE_INSMOD_LOAD_MAP_FULL
|
||||
bool "Symbols in load map"
|
||||
default y
|
||||
depends on FEATURE_INSMOD_LOAD_MAP
|
||||
help
|
||||
Without this option, -m will only output section
|
||||
load map. With this option, -m will also output
|
||||
symbols load map.
|
||||
|
||||
config RMMOD
|
||||
bool "rmmod"
|
||||
default n
|
||||
@ -156,12 +90,13 @@ config LSMOD
|
||||
lsmod is used to display a list of loaded modules.
|
||||
|
||||
config FEATURE_LSMOD_PRETTY_2_6_OUTPUT
|
||||
bool "Pretty output for 2.6.x Linux kernels"
|
||||
bool "Pretty output"
|
||||
default n
|
||||
depends on LSMOD
|
||||
help
|
||||
This option makes output format of lsmod adjusted to
|
||||
the format of module-init-tools for Linux kernel 2.6.
|
||||
Increases size somewhat.
|
||||
|
||||
config MODPROBE
|
||||
bool "modprobe"
|
||||
@ -174,38 +109,11 @@ config MODPROBE
|
||||
Note that in the state, modprobe does not understand multiple
|
||||
module options from the configuration file. See option below.
|
||||
|
||||
config FEATURE_MODPROBE_MULTIPLE_OPTIONS
|
||||
bool
|
||||
prompt "Multiple options parsing"
|
||||
default y
|
||||
depends on MODPROBE
|
||||
help
|
||||
Allow modprobe to understand more than one option to pass to
|
||||
modules.
|
||||
|
||||
This is a WIP, while waiting for a common argument parsing
|
||||
common amongst all BB applets (shell, modprobe, etc...) and
|
||||
adds around 600 bytes on x86, 700 bytes on ARM. The code is
|
||||
biggish and uggly, but just works.
|
||||
|
||||
Saying Y here is not a bad idea if you're not that short
|
||||
on storage capacity.
|
||||
|
||||
config FEATURE_MODPROBE_FANCY_ALIAS
|
||||
bool
|
||||
prompt "Fancy alias parsing"
|
||||
default y
|
||||
depends on MODPROBE && FEATURE_2_6_MODULES
|
||||
help
|
||||
Say 'y' here to enable parsing of aliases with underscore/dash
|
||||
mismatch between module name and file name, along with bus-specific
|
||||
aliases (such as pci:... or usb:... aliases).
|
||||
|
||||
config FEATURE_MODPROBE_BLACKLIST
|
||||
bool
|
||||
prompt "Blacklist support"
|
||||
default n
|
||||
depends on MODPROBE && FEATURE_2_6_MODULES
|
||||
depends on MODPROBE
|
||||
help
|
||||
Say 'y' here to enable support for the 'blacklist' command in
|
||||
modprobe.conf. This prevents the alias resolver to resolve
|
||||
@ -213,60 +121,110 @@ config FEATURE_MODPROBE_BLACKLIST
|
||||
hardware autodetection scripts to load modules like evdev, frame
|
||||
buffer drivers etc.
|
||||
|
||||
config DEPMOD
|
||||
bool "depmod"
|
||||
default n
|
||||
depends on !MODPROBE_SMALL
|
||||
help
|
||||
depmod generates modules.dep (and potentially modules.alias
|
||||
and modules.symbols) that contain dependency information
|
||||
for modprobe.
|
||||
|
||||
comment "Options common to multiple modutils"
|
||||
depends on INSMOD || RMMOD || MODPROBE || LSMOD || DEPMOD
|
||||
|
||||
config FEATURE_2_4_MODULES
|
||||
bool "Support version 2.2/2.4 Linux kernels"
|
||||
default n
|
||||
depends on INSMOD || RMMOD || LSMOD
|
||||
help
|
||||
Support module loading for 2.2.x and 2.4.x Linux kernels.
|
||||
This increases size considerably. Say N unless you plan
|
||||
to run ancient kernels.
|
||||
|
||||
config FEATURE_INSMOD_VERSION_CHECKING
|
||||
bool "Enable module version checking"
|
||||
default n
|
||||
depends on FEATURE_2_4_MODULES && (INSMOD || MODPROBE)
|
||||
help
|
||||
Support checking of versions for modules. This is used to
|
||||
ensure that the kernel and module are made for each other.
|
||||
|
||||
config FEATURE_INSMOD_KSYMOOPS_SYMBOLS
|
||||
bool "Add module symbols to kernel symbol table"
|
||||
default n
|
||||
depends on FEATURE_2_4_MODULES && (INSMOD || MODPROBE)
|
||||
help
|
||||
By adding module symbols to the kernel symbol table, Oops messages
|
||||
occuring within kernel modules can be properly debugged. By enabling
|
||||
this feature, module symbols will always be added to the kernel symbol
|
||||
table for properly debugging support. If you are not interested in
|
||||
Oops messages from kernel modules, say N.
|
||||
|
||||
config FEATURE_INSMOD_LOADINKMEM
|
||||
bool "In kernel memory optimization (uClinux only)"
|
||||
default n
|
||||
depends on FEATURE_2_4_MODULES && (INSMOD || MODPROBE)
|
||||
help
|
||||
This is a special uClinux only memory optimization that lets insmod
|
||||
load the specified kernel module directly into kernel space, reducing
|
||||
memory usage by preventing the need for two copies of the module
|
||||
being loaded into memory.
|
||||
|
||||
config FEATURE_INSMOD_LOAD_MAP
|
||||
bool "Enable insmod load map (-m) option"
|
||||
default n
|
||||
depends on FEATURE_2_4_MODULES && INSMOD
|
||||
help
|
||||
Enabling this, one would be able to get a load map
|
||||
output on stdout. This makes kernel module debugging
|
||||
easier.
|
||||
If you don't plan to debug kernel modules, you
|
||||
don't need this option.
|
||||
|
||||
config FEATURE_INSMOD_LOAD_MAP_FULL
|
||||
bool "Symbols in load map"
|
||||
default y
|
||||
depends on FEATURE_INSMOD_LOAD_MAP && !MODPROBE_SMALL
|
||||
help
|
||||
Without this option, -m will only output section
|
||||
load map. With this option, -m will also output
|
||||
symbols load map.
|
||||
|
||||
config FEATURE_CHECK_TAINTED_MODULE
|
||||
# Simulate indentation
|
||||
bool "Support tainted module checking with new kernels"
|
||||
default y
|
||||
depends on INSMOD || LSMOD
|
||||
depends on !MODPROBE_SMALL
|
||||
help
|
||||
Support checking for tainted modules. These are usually binary
|
||||
only modules that will make the linux-kernel list ignore your
|
||||
support request.
|
||||
This option is required to support GPLONLY modules.
|
||||
|
||||
config FEATURE_2_4_MODULES
|
||||
# Simulate indentation
|
||||
bool "Support version 2.2.x to 2.4.x Linux kernels"
|
||||
config FEATURE_MODUTILS_ALIAS
|
||||
bool "Support for module.aliases file"
|
||||
default y
|
||||
depends on INSMOD || RMMOD || MODPROBE
|
||||
depends on DEPMOD || MODPROBE
|
||||
help
|
||||
Support module loading for 2.2.x and 2.4.x Linux kernels.
|
||||
Generate and parse modules.alias containing aliases for bus
|
||||
identifiers:
|
||||
alias pcmcia:m*c*f03fn*pfn*pa*pb*pc*pd* parport_cs
|
||||
|
||||
Note:
|
||||
This is automatically enabled if 2.6 modules are not enabled.
|
||||
and aliases for logical modules names e.g.:
|
||||
alias padlock_aes aes
|
||||
alias aes_i586 aes
|
||||
alias aes_generic aes
|
||||
|
||||
config FEATURE_2_6_MODULES
|
||||
# Simulate indentation
|
||||
bool "Support version 2.6.x Linux kernels"
|
||||
Say Y if unsure.
|
||||
|
||||
config FEATURE_MODUTILS_SYMBOLS
|
||||
bool "Support for module.symbols file"
|
||||
default y
|
||||
depends on INSMOD || RMMOD || MODPROBE
|
||||
depends on DEPMOD || MODPROBE
|
||||
help
|
||||
Support module loading for newer 2.6.x Linux kernels.
|
||||
Generate and parse modules.symbols containing aliases for
|
||||
symbol_request() kernel calls, such as:
|
||||
alias symbol:usb_sg_init usbcore
|
||||
|
||||
config DEFAULT_MODULES_DIR
|
||||
# Simulate indentation
|
||||
string "Default directory containing modules"
|
||||
default "/lib/modules"
|
||||
depends on INSMOD || RMMOD || MODPROBE || MODPROBE_SMALL || DEPMOD
|
||||
help
|
||||
Directory that contains kernel modules.
|
||||
Defaults to "/lib/modules"
|
||||
|
||||
config DEFAULT_DEPMOD_FILE
|
||||
# Simulate indentation
|
||||
string "Default name of modules.dep"
|
||||
default "modules.dep"
|
||||
depends on INSMOD || RMMOD || MODPROBE || MODPROBE_SMALL || DEPMOD
|
||||
help
|
||||
Filename that contains kernel modules dependencies.
|
||||
Defaults to "modules.dep"
|
||||
|
||||
config FEATURE_QUERY_MODULE_INTERFACE
|
||||
bool
|
||||
default y
|
||||
depends on FEATURE_2_4_MODULES && !FEATURE_2_6_MODULES
|
||||
Say Y if unsure.
|
||||
|
||||
endmenu
|
||||
|
@ -5,9 +5,10 @@
|
||||
# Licensed under the GPL v2, see the file LICENSE in this tarball.
|
||||
|
||||
lib-y:=
|
||||
lib-$(CONFIG_DEPMOD) += depmod.o
|
||||
lib-$(CONFIG_INSMOD) += insmod.o
|
||||
lib-$(CONFIG_LSMOD) += lsmod.o
|
||||
lib-$(CONFIG_MODPROBE) += modprobe.o
|
||||
lib-$(CONFIG_MODPROBE_SMALL) += modprobe-small.o
|
||||
lib-$(CONFIG_RMMOD) += rmmod.o
|
||||
lib-$(CONFIG_DEPMOD) += depmod.o modutils.o
|
||||
lib-$(CONFIG_INSMOD) += insmod.o modutils.o
|
||||
lib-$(CONFIG_LSMOD) += lsmod.o modutils.o
|
||||
lib-$(CONFIG_MODPROBE) += modprobe.o modutils.o
|
||||
lib-$(CONFIG_RMMOD) += rmmod.o modutils.o
|
||||
lib-$(CONFIG_FEATURE_2_4_MODULES) += modutils-24.o
|
||||
|
@ -2,6 +2,8 @@
|
||||
/*
|
||||
* depmod - generate modules.dep
|
||||
* Copyright (c) 2008 Bernhard Fischer
|
||||
* Copyrihgt (c) 2008 Timo Teras <timo.teras@iki.fi>
|
||||
* Copyright (c) 2008 Vladimir Dronnikov
|
||||
*
|
||||
* Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
|
||||
*/
|
||||
@ -10,6 +12,8 @@
|
||||
#define _GNU_SOURCE
|
||||
#include <libbb.h>
|
||||
#include <sys/utsname.h> /* uname() */
|
||||
#include "modutils.h"
|
||||
|
||||
/*
|
||||
* Theory of operation:
|
||||
* - iterate over all modules and record their full path
|
||||
@ -17,105 +21,15 @@
|
||||
* for each depends, look through our list of full paths and emit if found
|
||||
*/
|
||||
|
||||
typedef struct dep_lst_t {
|
||||
char *name;
|
||||
typedef struct module_info {
|
||||
struct module_info *next;
|
||||
char *name, *modname;
|
||||
llist_t *dependencies;
|
||||
llist_t *aliases;
|
||||
struct dep_lst_t *next;
|
||||
} dep_lst_t;
|
||||
llist_t *symbols;
|
||||
struct module_info *dnext, *dprev;
|
||||
} module_info;
|
||||
|
||||
struct globals {
|
||||
dep_lst_t *lst; /* modules without their corresponding extension */
|
||||
};
|
||||
#define G (*(struct globals*)&bb_common_bufsiz1)
|
||||
/* We have to zero it out because of NOEXEC */
|
||||
#define INIT_G() memset(&G, 0, sizeof(G))
|
||||
|
||||
static char* find_keyword(void *the_module, size_t len, const char * const word)
|
||||
{
|
||||
char *ptr = the_module;
|
||||
do {
|
||||
/* search for the first char in word */
|
||||
ptr = memchr(ptr, *word, len - (ptr - (char*)the_module));
|
||||
if (ptr == NULL) /* no occurance left, done */
|
||||
return NULL;
|
||||
if (!strncmp(ptr, word, strlen(word))) {
|
||||
ptr += strlen(word);
|
||||
break;
|
||||
}
|
||||
++ptr;
|
||||
} while (1);
|
||||
return ptr;
|
||||
}
|
||||
static int FAST_FUNC fileAction(const char *fname, struct stat *sb,
|
||||
void UNUSED_PARAM *data, int UNUSED_PARAM depth)
|
||||
{
|
||||
size_t len = sb->st_size;
|
||||
void *the_module;
|
||||
char *ptr;
|
||||
int fd;
|
||||
char *depends, *deps;
|
||||
dep_lst_t *this;
|
||||
|
||||
if (strrstr(fname, ".ko") == NULL) /* not a module */
|
||||
goto skip;
|
||||
|
||||
/*XXX: FIXME: does not handle compressed modules!
|
||||
* There should be a function that looks at the extension and sets up
|
||||
* open_transformer for us.
|
||||
*/
|
||||
fd = xopen(fname, O_RDONLY);
|
||||
the_module = mmap(NULL, len, PROT_READ, MAP_SHARED
|
||||
#if defined MAP_POPULATE
|
||||
|MAP_POPULATE
|
||||
#endif
|
||||
, fd, 0);
|
||||
close(fd);
|
||||
if (the_module == MAP_FAILED)
|
||||
bb_perror_msg_and_die("mmap");
|
||||
|
||||
this = xzalloc(sizeof(dep_lst_t));
|
||||
this->name = xstrdup(fname);
|
||||
this->next = G.lst;
|
||||
G.lst = this;
|
||||
//bb_info_msg("fname='%s'", fname);
|
||||
ptr = find_keyword(the_module, len, "depends=");
|
||||
if (!*ptr)
|
||||
goto d_none;
|
||||
deps = depends = xstrdup(ptr);
|
||||
//bb_info_msg(" depends='%s'", depends);
|
||||
while (deps) {
|
||||
ptr = strsep(&deps, ",");
|
||||
//bb_info_msg("[%s] -> '%s'", fname, (char*)ptr);
|
||||
llist_add_to_end(&this->dependencies, xstrdup(ptr));
|
||||
}
|
||||
free(depends);
|
||||
d_none:
|
||||
if (ENABLE_FEATURE_DEPMOD_ALIAS)
|
||||
{
|
||||
size_t pos = 0;
|
||||
do {
|
||||
ptr = find_keyword(the_module + pos, len - pos, "alias=");
|
||||
if (ptr) {
|
||||
//bb_info_msg("[%s] alias '%s'", fname, (char*)ptr);
|
||||
llist_add_to_end(&this->aliases, xstrdup(ptr));
|
||||
} else
|
||||
break;
|
||||
pos = (ptr - (char*)the_module);
|
||||
} while (1);
|
||||
}
|
||||
munmap(the_module, sb->st_size);
|
||||
skip:
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
int depmod_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
|
||||
int depmod_main(int argc UNUSED_PARAM, char **argv)
|
||||
{
|
||||
int ret;
|
||||
size_t moddir_base_len = 0; /* length of the "-b basedir" */
|
||||
char *moddir_base = NULL, *moddir, *system_map, *chp;
|
||||
FILE *filedes = stdout;
|
||||
enum {
|
||||
ARG_a = (1<<0), /* All modules, ignore mods in argv */
|
||||
ARG_A = (1<<1), /* Only emit .ko that are newer than modules.dep file */
|
||||
@ -124,165 +38,177 @@ int depmod_main(int argc UNUSED_PARAM, char **argv)
|
||||
ARG_F = (1<<4), /* System.map that contains the symbols */
|
||||
ARG_n = (1<<5) /* dry-run, print to stdout only */
|
||||
};
|
||||
INIT_G();
|
||||
|
||||
getopt32(argv, "aAb:eF:n", &moddir_base, &system_map);
|
||||
static int FAST_FUNC parse_module(const char *fname, struct stat *sb,
|
||||
void *data, int UNUSED_PARAM depth)
|
||||
{
|
||||
module_info **first = (module_info **) data;
|
||||
char *image, *ptr;
|
||||
module_info *info;
|
||||
size_t len = sb->st_size;
|
||||
|
||||
if (strrstr(fname, ".ko") == NULL)
|
||||
return TRUE;
|
||||
|
||||
image = (char *) xmalloc_open_zipped_read_close(fname, &len);
|
||||
info = xzalloc(sizeof(module_info));
|
||||
|
||||
info->next = *first;
|
||||
*first = info;
|
||||
|
||||
info->dnext = info->dprev = info;
|
||||
info->name = xstrdup(fname);
|
||||
info->modname = filename2modname(fname, NULL);
|
||||
for (ptr = image; ptr < image + len - 10; ptr++) {
|
||||
if (strncmp(ptr, "depends=", 8) == 0) {
|
||||
char *u;
|
||||
|
||||
ptr += 8;
|
||||
for (u = ptr; *u; u++)
|
||||
if (*u == '-')
|
||||
*u = '_';
|
||||
ptr += string_to_llist(ptr, &info->dependencies, ",");
|
||||
} else if (ENABLE_FEATURE_MODUTILS_ALIAS &&
|
||||
strncmp(ptr, "alias=", 6) == 0) {
|
||||
llist_add_to(&info->aliases, xstrdup(ptr + 6));
|
||||
ptr += strlen(ptr);
|
||||
} else if (ENABLE_FEATURE_MODUTILS_SYMBOLS &&
|
||||
strncmp(ptr, "__ksymtab_", 10) == 0) {
|
||||
ptr += 10;
|
||||
if (strncmp(ptr, "gpl", 3) == 0 ||
|
||||
strcmp(ptr, "strings") == 0)
|
||||
continue;
|
||||
llist_add_to(&info->symbols, xstrdup(ptr));
|
||||
ptr += strlen(ptr);
|
||||
}
|
||||
}
|
||||
free(image);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static module_info *find_module(module_info *modules, const char *modname)
|
||||
{
|
||||
module_info *m;
|
||||
|
||||
for (m = modules; m != NULL; m = m->next)
|
||||
if (strcmp(m->modname, modname) == 0)
|
||||
return m;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void order_dep_list(module_info *modules, module_info *start,
|
||||
llist_t *add)
|
||||
{
|
||||
module_info *m;
|
||||
llist_t *n;
|
||||
|
||||
for (n = add; n != NULL; n = n->link) {
|
||||
m = find_module(modules, n->data);
|
||||
if (m == NULL)
|
||||
continue;
|
||||
|
||||
/* unlink current entry */
|
||||
m->dnext->dprev = m->dprev;
|
||||
m->dprev->dnext = m->dnext;
|
||||
|
||||
/* and add it to tail */
|
||||
m->dnext = start;
|
||||
m->dprev = start->dprev;
|
||||
start->dprev->dnext = m;
|
||||
start->dprev = m;
|
||||
|
||||
/* recurse */
|
||||
order_dep_list(modules, start, m->dependencies);
|
||||
}
|
||||
}
|
||||
|
||||
int depmod_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
|
||||
int depmod_main(int argc UNUSED_PARAM, char **argv)
|
||||
{
|
||||
module_info *modules = NULL, *m, *dep;
|
||||
char *moddir_base = (char *)CONFIG_DEFAULT_MODULES_DIR;
|
||||
int tmp;
|
||||
|
||||
getopt32(argv, "aAb:eF:n", &moddir_base, NULL);
|
||||
argv += optind;
|
||||
|
||||
/* If a version is provided, then that kernel version’s module directory
|
||||
/* goto modules location */
|
||||
|
||||
/* If a version is provided, then that kernel version's module directory
|
||||
* is used, rather than the current kernel version (as returned by
|
||||
* "uname -r"). */
|
||||
if (*argv && (sscanf(*argv, "%d.%d.%d", &ret, &ret, &ret) == 3)) {
|
||||
moddir = concat_path_file(CONFIG_DEFAULT_MODULES_DIR, *argv++);
|
||||
xchdir(moddir_base);
|
||||
if (*argv && (sscanf(*argv, "%d.%d.%d", &tmp, &tmp, &tmp) == 3)) {
|
||||
xchdir(*argv++);
|
||||
} else {
|
||||
struct utsname uts;
|
||||
if (uname(&uts) < 0)
|
||||
bb_simple_perror_msg_and_die("uname");
|
||||
moddir = concat_path_file(CONFIG_DEFAULT_MODULES_DIR, uts.release);
|
||||
uname(&uts);
|
||||
xchdir(uts.release);
|
||||
}
|
||||
/* If no modules are given on the command-line, -a is on per default. */
|
||||
option_mask32 |= *argv == NULL;
|
||||
|
||||
if (option_mask32 & ARG_b) {
|
||||
moddir_base_len = strlen(moddir_base) + 1;
|
||||
xchdir(moddir_base);
|
||||
}
|
||||
|
||||
if (!(option_mask32 & ARG_n)) { /* --dry-run */
|
||||
chp = concat_path_file(moddir, CONFIG_DEFAULT_DEPMOD_FILE);
|
||||
filedes = xfopen_for_write(chp);
|
||||
if (ENABLE_FEATURE_CLEAN_UP)
|
||||
free(chp);
|
||||
}
|
||||
ret = EXIT_SUCCESS;
|
||||
/* Scan modules */
|
||||
moddir_base = xrealloc_getcwd_or_warn(NULL);
|
||||
do {
|
||||
chp = option_mask32 & ARG_a ? moddir : (*argv + moddir_base_len);
|
||||
|
||||
if (!recursive_action(chp,
|
||||
ACTION_RECURSE, /* flags */
|
||||
fileAction, /* file action */
|
||||
NULL, /* dir action */
|
||||
NULL, /* user data */
|
||||
0)) { /* depth */
|
||||
ret = EXIT_FAILURE;
|
||||
}
|
||||
} while (!(option_mask32 & ARG_a) && *++argv);
|
||||
|
||||
{
|
||||
dep_lst_t *mods = G.lst;
|
||||
|
||||
/* Fixup the module names in the depends list */
|
||||
while (mods) {
|
||||
llist_t *deps = NULL, *old_deps = mods->dependencies;
|
||||
|
||||
while (old_deps) {
|
||||
dep_lst_t *all = G.lst;
|
||||
char *longname = NULL;
|
||||
char *shortname = llist_pop(&old_deps);
|
||||
|
||||
while (all) {
|
||||
char *nam =
|
||||
xstrdup(bb_get_last_path_component_nostrip(all->name));
|
||||
char *tmp = strrstr(nam, ".ko");
|
||||
|
||||
*tmp = '\0';
|
||||
if (!strcmp(nam, shortname)) {
|
||||
recursive_action((option_mask32 & ARG_a) ? moddir_base : *argv,
|
||||
ACTION_RECURSE, parse_module, NULL, &modules, 0);
|
||||
} while (!(option_mask32 & ARG_a) && *(++argv));
|
||||
if (ENABLE_FEATURE_CLEAN_UP)
|
||||
free(nam);
|
||||
longname = all->name;
|
||||
break;
|
||||
free(moddir_base);
|
||||
|
||||
/* Generate dependency and alias files */
|
||||
if (!(option_mask32 & ARG_n))
|
||||
freopen(CONFIG_DEFAULT_DEPMOD_FILE, "w", stdout);
|
||||
for (m = modules; m != NULL; m = m->next) {
|
||||
printf("%s:", m->name);
|
||||
|
||||
order_dep_list(modules, m, m->dependencies);
|
||||
while (m->dnext != m) {
|
||||
dep = m->dnext;
|
||||
printf(" %s", dep->name);
|
||||
|
||||
/* unlink current entry */
|
||||
dep->dnext->dprev = dep->dprev;
|
||||
dep->dprev->dnext = dep->dnext;
|
||||
dep->dnext = dep->dprev = dep;
|
||||
}
|
||||
free(nam);
|
||||
all = all->next;
|
||||
}
|
||||
llist_add_to_end(&deps, longname);
|
||||
}
|
||||
mods->dependencies = deps;
|
||||
mods = mods->next;
|
||||
puts("");
|
||||
}
|
||||
|
||||
#if ENABLE_FEATURE_DEPMOD_PRUNE_FANCY
|
||||
/* modprobe allegedly wants dependencies without duplicates, i.e.
|
||||
* mod1: mod2 mod3
|
||||
* mod2: mod3
|
||||
* mod3:
|
||||
* implies that mod1 directly depends on mod2 and _not_ mod3 as mod3 is
|
||||
* already implicitely pulled in via mod2. This leaves us with:
|
||||
* mod1: mod2
|
||||
* mod2: mod3
|
||||
* mod3:
|
||||
*/
|
||||
mods = G.lst;
|
||||
while (mods) {
|
||||
llist_t *deps = mods->dependencies;
|
||||
while (deps) {
|
||||
dep_lst_t *all = G.lst;
|
||||
while (all) {
|
||||
if (!strcmp(all->name, deps->data)) {
|
||||
llist_t *implied = all->dependencies;
|
||||
while (implied) {
|
||||
/* XXX:FIXME: erm, it would be nicer to just
|
||||
* llist_unlink(&mods->dependencies, implied) */
|
||||
llist_t *prune = mods->dependencies;
|
||||
while (prune) {
|
||||
if (!strcmp(implied->data, prune->data))
|
||||
break;
|
||||
prune = prune->link;
|
||||
}
|
||||
//if (prune) bb_info_msg("[%s] '%s' implies '%s', removing", mods->name, all->name, implied->data);
|
||||
llist_unlink(&mods->dependencies, prune);
|
||||
implied = implied->link;
|
||||
#if ENABLE_FEATURE_MODUTILS_ALIAS
|
||||
if (!(option_mask32 & ARG_n))
|
||||
freopen("modules.alias", "w", stdout);
|
||||
for (m = modules; m != NULL; m = m->next) {
|
||||
while (m->aliases) {
|
||||
printf("alias %s %s\n",
|
||||
(char*)llist_pop(&m->aliases),
|
||||
m->modname);
|
||||
}
|
||||
}
|
||||
all = all->next;
|
||||
#endif
|
||||
#if ENABLE_FEATURE_MODUTILS_SYMBOLS
|
||||
if (!(option_mask32 & ARG_n))
|
||||
freopen("modules.symbols", "w", stdout);
|
||||
for (m = modules; m != NULL; m = m->next) {
|
||||
while (m->symbols) {
|
||||
printf("alias symbol:%s %s\n",
|
||||
(char*)llist_pop(&m->symbols),
|
||||
m->modname);
|
||||
}
|
||||
deps = deps->link;
|
||||
}
|
||||
mods = mods->next;
|
||||
}
|
||||
#endif
|
||||
|
||||
mods = G.lst;
|
||||
/* Finally print them. */
|
||||
while (mods) {
|
||||
fprintf(filedes, "%s:", mods->name);
|
||||
/* If we did not resolve all modules, then it's likely that we just did
|
||||
* not see the names of all prerequisites (which will be NULL in this
|
||||
* case). */
|
||||
while (mods->dependencies) {
|
||||
char *the_dep = llist_pop(&mods->dependencies);
|
||||
if (the_dep)
|
||||
fprintf(filedes, " %s", the_dep);
|
||||
}
|
||||
fprintf(filedes, "\n");
|
||||
if (ENABLE_FEATURE_DEPMOD_ALIAS)
|
||||
{
|
||||
char *shortname =
|
||||
xstrdup(bb_get_last_path_component_nostrip(mods->name));
|
||||
char *tmp = strrstr(shortname, ".ko");
|
||||
|
||||
*tmp = '\0';
|
||||
|
||||
while (mods->aliases) {
|
||||
fprintf(filedes, "alias %s %s\n",
|
||||
(char*)llist_pop(&mods->aliases),
|
||||
shortname);
|
||||
}
|
||||
free(shortname);
|
||||
}
|
||||
mods = mods->next;
|
||||
}
|
||||
}
|
||||
|
||||
if (ENABLE_FEATURE_CLEAN_UP) {
|
||||
fclose_if_not_stdin(filedes);
|
||||
free(moddir);
|
||||
while (G.lst) {
|
||||
dep_lst_t *old = G.lst;
|
||||
G.lst = G.lst->next;
|
||||
while (modules) {
|
||||
module_info *old = modules;
|
||||
modules = modules->next;
|
||||
free(old->name);
|
||||
free(old->modname);
|
||||
free(old);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
4271
modutils/insmod.c
4271
modutils/insmod.c
File diff suppressed because it is too large
Load Diff
221
modutils/lsmod.c
221
modutils/lsmod.c
@ -3,192 +3,77 @@
|
||||
* Mini lsmod implementation for busybox
|
||||
*
|
||||
* Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org>
|
||||
*
|
||||
* Modified by Alcove, Julien Gaulmin <julien.gaulmin@alcove.fr> and
|
||||
* Nicolas Ferre <nicolas.ferre@alcove.fr> to support pre 2.1 kernels
|
||||
* (which lack the query_module() interface).
|
||||
* Copyright (C) 2008 by Vladimir Dronnikov <dronnikov@gmail.com>
|
||||
*
|
||||
* Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
|
||||
*/
|
||||
|
||||
#include "libbb.h"
|
||||
|
||||
|
||||
#if !ENABLE_FEATURE_CHECK_TAINTED_MODULE
|
||||
static void check_tainted(void) { bb_putchar('\n'); }
|
||||
#else
|
||||
#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)
|
||||
#if ENABLE_FEATURE_CHECK_TAINTED_MODULE
|
||||
enum {
|
||||
TAINT_PROPRIETORY_MODULE = (1 << 0),
|
||||
TAINT_FORCED_MODULE = (1 << 1),
|
||||
TAINT_UNSAFE_SMP = (1 << 2),
|
||||
};
|
||||
|
||||
static void check_tainted(void)
|
||||
{
|
||||
int tainted;
|
||||
FILE *f;
|
||||
|
||||
tainted = 0;
|
||||
f = fopen_for_read(TAINT_FILENAME);
|
||||
if (f) {
|
||||
fscanf(f, "%d", &tainted);
|
||||
fclose(f);
|
||||
int tainted = 0;
|
||||
char *buf = xmalloc_open_read_close("/proc/sys/kernel/tainted", NULL);
|
||||
if (buf) {
|
||||
tainted = atoi(buf);
|
||||
if (ENABLE_FEATURE_CLEAN_UP)
|
||||
free(buf);
|
||||
}
|
||||
|
||||
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 {
|
||||
printf(" Not tainted\n");
|
||||
puts(" Not tainted");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ENABLE_FEATURE_QUERY_MODULE_INTERFACE
|
||||
|
||||
struct module_info
|
||||
{
|
||||
unsigned long addr;
|
||||
unsigned long size;
|
||||
unsigned long flags;
|
||||
long usecount;
|
||||
};
|
||||
|
||||
|
||||
int query_module(const char *name, int which, void *buf, size_t bufsize, size_t *ret);
|
||||
|
||||
enum {
|
||||
/* Values for query_module's which. */
|
||||
QM_MODULES = 1,
|
||||
QM_DEPS = 2,
|
||||
QM_REFS = 3,
|
||||
QM_SYMBOLS = 4,
|
||||
QM_INFO = 5,
|
||||
|
||||
/* Bits of module.flags. */
|
||||
NEW_MOD_RUNNING = 1,
|
||||
NEW_MOD_DELETED = 2,
|
||||
NEW_MOD_AUTOCLEAN = 4,
|
||||
NEW_MOD_VISITED = 8,
|
||||
NEW_MOD_USED_ONCE = 16,
|
||||
NEW_MOD_INITIALIZING = 64
|
||||
};
|
||||
|
||||
int lsmod_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
|
||||
int lsmod_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
|
||||
{
|
||||
struct module_info info;
|
||||
char *module_names, *mn, *deps, *dn;
|
||||
size_t bufsize, depsize, nmod, count, i, j;
|
||||
|
||||
module_names = deps = NULL;
|
||||
bufsize = depsize = 0;
|
||||
while (query_module(NULL, QM_MODULES, module_names, bufsize, &nmod)) {
|
||||
if (errno != ENOSPC) bb_perror_msg_and_die("QM_MODULES");
|
||||
module_names = xmalloc(bufsize = nmod);
|
||||
}
|
||||
|
||||
deps = xmalloc(depsize = 256);
|
||||
printf("Module\t\t\tSize Used by");
|
||||
check_tainted();
|
||||
|
||||
for (i = 0, mn = module_names; i < nmod; mn += strlen(mn) + 1, i++) {
|
||||
if (query_module(mn, QM_INFO, &info, sizeof(info), &count)) {
|
||||
if (errno == ENOENT) {
|
||||
/* The module was removed out from underneath us. */
|
||||
continue;
|
||||
}
|
||||
/* else choke */
|
||||
bb_perror_msg_and_die("module %s: QM_INFO", mn);
|
||||
}
|
||||
while (query_module(mn, QM_REFS, deps, depsize, &count)) {
|
||||
if (errno == ENOENT) {
|
||||
/* The module was removed out from underneath us. */
|
||||
continue;
|
||||
} else if (errno != ENOSPC)
|
||||
bb_perror_msg_and_die("module %s: QM_REFS", mn);
|
||||
deps = xrealloc(deps, count);
|
||||
}
|
||||
printf("%-20s%8lu%4ld", mn, info.size, info.usecount);
|
||||
if (info.flags & NEW_MOD_DELETED)
|
||||
printf(" (deleted)");
|
||||
else if (info.flags & NEW_MOD_INITIALIZING)
|
||||
printf(" (initializing)");
|
||||
else if (!(info.flags & NEW_MOD_RUNNING))
|
||||
printf(" (uninitialized)");
|
||||
else {
|
||||
if (info.flags & NEW_MOD_AUTOCLEAN)
|
||||
printf(" (autoclean) ");
|
||||
if (!(info.flags & NEW_MOD_USED_ONCE))
|
||||
printf(" (unused)");
|
||||
}
|
||||
if (count)
|
||||
printf(" [");
|
||||
for (j = 0, dn = deps; j < count; dn += strlen(dn) + 1, j++) {
|
||||
printf("%s%s", dn, (j==count-1)? "":" ");
|
||||
}
|
||||
if (count)
|
||||
bb_putchar(']');
|
||||
|
||||
bb_putchar('\n');
|
||||
}
|
||||
|
||||
#if ENABLE_FEATURE_CLEAN_UP
|
||||
free(module_names);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else /* CONFIG_FEATURE_QUERY_MODULE_INTERFACE */
|
||||
|
||||
int lsmod_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
|
||||
int lsmod_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
|
||||
{
|
||||
FILE *file = xfopen_for_read("/proc/modules");
|
||||
|
||||
printf("Module Size Used by");
|
||||
check_tainted();
|
||||
#if ENABLE_FEATURE_LSMOD_PRETTY_2_6_OUTPUT
|
||||
{
|
||||
char *line;
|
||||
while ((line = xmalloc_fgets(file)) != NULL) {
|
||||
char *tok;
|
||||
|
||||
tok = strtok(line, " \t");
|
||||
printf("%-19s", tok);
|
||||
tok = strtok(NULL, " \t\n");
|
||||
printf(" %8s", tok);
|
||||
tok = strtok(NULL, " \t\n");
|
||||
/* Null if no module unloading support. */
|
||||
if (tok) {
|
||||
printf(" %s", tok);
|
||||
tok = strtok(NULL, "\n");
|
||||
if (!tok)
|
||||
tok = (char*)"";
|
||||
/* New-style has commas, or -. If so,
|
||||
truncate (other fields might follow). */
|
||||
else if (strchr(tok, ',')) {
|
||||
tok = strtok(tok, "\t ");
|
||||
/* Strip trailing comma. */
|
||||
if (tok[strlen(tok)-1] == ',')
|
||||
tok[strlen(tok)-1] = '\0';
|
||||
} else if (tok[0] == '-'
|
||||
&& (tok[1] == '\0' || isspace(tok[1]))
|
||||
) {
|
||||
tok = (char*)"";
|
||||
}
|
||||
printf(" %s", tok);
|
||||
}
|
||||
bb_putchar('\n');
|
||||
free(line);
|
||||
}
|
||||
fclose(file);
|
||||
}
|
||||
#else
|
||||
xprint_and_close_file(file);
|
||||
#endif /* CONFIG_FEATURE_2_6_MODULES */
|
||||
static void check_tainted(void) { putchar('\n'); }
|
||||
#endif
|
||||
|
||||
int lsmod_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
|
||||
int lsmod_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
|
||||
{
|
||||
#if ENABLE_FEATURE_LSMOD_PRETTY_2_6_OUTPUT
|
||||
char *token[4];
|
||||
parser_t *parser = config_open("/proc/modules");
|
||||
printf("Module Size Used by"); //vda!
|
||||
check_tainted();
|
||||
|
||||
if (ENABLE_FEATURE_2_4_MODULES
|
||||
&& get_linux_version_code() < KERNEL_VERSION(2,6,0)
|
||||
) {
|
||||
while (config_read(parser, token, 4, 3, "# \t", PARSE_NORMAL)) {
|
||||
if (token[3] != NULL && token[3][0] == '[') {
|
||||
token[3]++;
|
||||
token[3][strlen(token[3])-1] = '\0';
|
||||
} else
|
||||
token[3] = (char *) "";
|
||||
printf("%-19s %8s %2s %s\n", token[0], token[1], token[2], token[3]);
|
||||
}
|
||||
} else {
|
||||
while (config_read(parser, token, 4, 4, "# \t", PARSE_NORMAL & ~PARSE_GREEDY)) {
|
||||
// N.B. token[3] is either '-' (module is not used by others)
|
||||
// or comma-separated list ended by comma
|
||||
// so trimming the trailing char is just what we need!
|
||||
token[3][strlen(token[3])-1] = '\0';
|
||||
printf("%-19s %8s %2s %s\n", token[0], token[1], token[2], token[3]);
|
||||
}
|
||||
}
|
||||
if (ENABLE_FEATURE_CLEAN_UP)
|
||||
config_close(parser);
|
||||
#else
|
||||
check_tainted();
|
||||
xprint_and_close_file(xfopen_for_read("/proc/modules"));
|
||||
#endif
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_FEATURE_QUERY_MODULE_INTERFACE */
|
||||
|
1127
modutils/modprobe.c
1127
modutils/modprobe.c
File diff suppressed because it is too large
Load Diff
3936
modutils/modutils-24.c
Normal file
3936
modutils/modutils-24.c
Normal file
File diff suppressed because it is too large
Load Diff
141
modutils/modutils.c
Normal file
141
modutils/modutils.c
Normal file
@ -0,0 +1,141 @@
|
||||
/*
|
||||
* Common modutils related functions for busybox
|
||||
*
|
||||
* Copyright (C) 2008 by Timo Teras <timo.teras@iki.fi>
|
||||
*
|
||||
* Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
|
||||
*/
|
||||
|
||||
#include "modutils.h"
|
||||
|
||||
#ifdef __UCLIBC__
|
||||
extern int init_module(void *module, unsigned long len, const char *options);
|
||||
extern int delete_module(const char *module, unsigned int flags);
|
||||
#else
|
||||
# include <sys/syscall.h>
|
||||
# define init_module(mod, len, opts) syscall(__NR_init_module, mod, len, opts)
|
||||
# define delete_module(mod, flags) syscall(__NR_delete_module, mod, flags)
|
||||
#endif
|
||||
|
||||
USE_FEATURE_2_4_MODULES(char *insmod_outputname);
|
||||
|
||||
/*
|
||||
a libbb candidate from ice age!
|
||||
*/
|
||||
llist_t FAST_FUNC *llist_find(llist_t *first, const char *str)
|
||||
{
|
||||
while (first != NULL) {
|
||||
if (strcmp(first->data, str) == 0)
|
||||
return first;
|
||||
first = first->link;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void FAST_FUNC replace(char *s, char what, char with)
|
||||
{
|
||||
while (*s) {
|
||||
if (what == *s)
|
||||
*s = with;
|
||||
++s;
|
||||
}
|
||||
}
|
||||
|
||||
char * FAST_FUNC replace_underscores(char *s)
|
||||
{
|
||||
replace(s, '-', '_');
|
||||
return s;
|
||||
}
|
||||
|
||||
int FAST_FUNC string_to_llist(char *string, llist_t **llist, const char *delim)
|
||||
{
|
||||
char *tok;
|
||||
int len = 0;
|
||||
|
||||
while ((tok = strsep(&string, delim)) != NULL) {
|
||||
if (tok[0] == '\0')
|
||||
continue;
|
||||
llist_add_to_end(llist, xstrdup(tok));
|
||||
len += strlen(tok);
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
char * FAST_FUNC filename2modname(const char *filename, char *modname)
|
||||
{
|
||||
int i;
|
||||
char *from;
|
||||
|
||||
if (filename == NULL)
|
||||
return NULL;
|
||||
if (modname == NULL)
|
||||
modname = xmalloc(MODULE_NAME_LEN);
|
||||
from = bb_get_last_path_component_nostrip(filename);
|
||||
for (i = 0; i < MODULE_NAME_LEN && from[i] != '\0' && from[i] != '.'; i++)
|
||||
modname[i] = (from[i] == '-') ? '_' : from[i];
|
||||
modname[i] = 0;
|
||||
|
||||
return modname;
|
||||
}
|
||||
|
||||
const char * FAST_FUNC moderror(int err)
|
||||
{
|
||||
switch (err) {
|
||||
case -1:
|
||||
return "no such module";
|
||||
case ENOEXEC:
|
||||
return "invalid module format";
|
||||
case ENOENT:
|
||||
return "unknown symbol in module, or unknown parameter";
|
||||
case ESRCH:
|
||||
return "module has wrong symbol version";
|
||||
case ENOSYS:
|
||||
return "kernel does not support requested operation";
|
||||
default:
|
||||
return strerror(err);
|
||||
}
|
||||
}
|
||||
|
||||
char * FAST_FUNC parse_cmdline_module_options(char **argv)
|
||||
{
|
||||
char *options;
|
||||
int optlen;
|
||||
|
||||
options = xzalloc(1);
|
||||
optlen = 0;
|
||||
while (*++argv) {
|
||||
options = xrealloc(options, optlen + 2 + strlen(*argv) + 2);
|
||||
/* Spaces handled by "" pairs, but no way of escaping quotes */
|
||||
optlen += sprintf(options + optlen, (strchr(*argv,' ') ? "\"%s\" " : "%s "), *argv);
|
||||
}
|
||||
return options;
|
||||
}
|
||||
|
||||
int FAST_FUNC bb_init_module(const char *filename, const char *options)
|
||||
{
|
||||
size_t len = MAXINT(ssize_t);
|
||||
char *image;
|
||||
int rc = ENOENT;
|
||||
|
||||
#if ENABLE_FEATURE_2_4_MODULES
|
||||
if (get_linux_version_code() < KERNEL_VERSION(2,6,0))
|
||||
return bb_init_module_24(filename, options);
|
||||
#endif
|
||||
|
||||
/* Use the 2.6 way */
|
||||
image = (char *) xmalloc_open_zipped_read_close(filename, &len);
|
||||
if (image) {
|
||||
if (init_module(image, len, options) != 0)
|
||||
rc = errno;
|
||||
else
|
||||
rc = 0;
|
||||
free(image);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int FAST_FUNC bb_delete_module(const char *module, unsigned int flags)
|
||||
{
|
||||
return delete_module(module, flags);
|
||||
}
|
68
modutils/modutils.h
Normal file
68
modutils/modutils.h
Normal file
@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Common modutils related functions for busybox
|
||||
*
|
||||
* Copyright (C) 2008 by Timo Teras <timo.teras@iki.fi>
|
||||
*
|
||||
* Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
|
||||
*/
|
||||
|
||||
#ifndef __MODUTILS_H__
|
||||
#define __MODUTILS_H__
|
||||
|
||||
#include "libbb.h"
|
||||
#include <stdio.h>
|
||||
|
||||
#if __GNUC_PREREQ(4,1)
|
||||
# pragma GCC visibility push(hidden)
|
||||
#endif
|
||||
|
||||
/* As defined in linux/include/linux/module.h */
|
||||
#define MODULE_NAME_LEN 64
|
||||
|
||||
const char *moderror(int err) FAST_FUNC;
|
||||
llist_t *llist_find(llist_t *first, const char *str) FAST_FUNC;
|
||||
void replace(char *s, char what, char with) FAST_FUNC;
|
||||
char *replace_underscores(char *s) FAST_FUNC;
|
||||
int string_to_llist(char *string, llist_t **llist, const char *delim) FAST_FUNC ;
|
||||
char *filename2modname(const char *filename, char *modname) FAST_FUNC;
|
||||
char *parse_cmdline_module_options(char **argv) FAST_FUNC;
|
||||
|
||||
#define INSMOD_OPTS "vq" USE_FEATURE_2_4_MODULES("sLo:fkx") \
|
||||
USE_FEATURE_INSMOD_LOAD_MAP("m")
|
||||
#define INSMOD_ARGS USE_FEATURE_2_4_MODULES(, &insmod_outputname)
|
||||
|
||||
enum {
|
||||
INSMOD_OPT_VERBOSE = 0x0001,
|
||||
INSMOD_OPT_SILENT = 0x0002,
|
||||
INSMOD_OPT_SYSLOG = 0x0004 * ENABLE_FEATURE_2_4_MODULES,
|
||||
INSMOD_OPT_LOCK = 0x0008 * ENABLE_FEATURE_2_4_MODULES,
|
||||
INSMOD_OPT_OUTPUTNAME = 0x0010 * ENABLE_FEATURE_2_4_MODULES,
|
||||
INSMOD_OPT_FORCE = 0x0020 * ENABLE_FEATURE_2_4_MODULES,
|
||||
INSMOD_OPT_KERNELD = 0x0040 * ENABLE_FEATURE_2_4_MODULES,
|
||||
INSMOD_OPT_NO_EXPORT = 0x0080 * ENABLE_FEATURE_2_4_MODULES,
|
||||
INSMOD_OPT_PRINT_MAP = 0x0100 * ENABLE_FEATURE_INSMOD_LOAD_MAP,
|
||||
#if ENABLE_FEATURE_2_4_MODULES
|
||||
#if ENABLE_FEATURE_INSMOD_LOAD_MAP
|
||||
INSMOD_OPT_UNUSED = 0x0200,
|
||||
#else /* ENABLE_FEATURE_INSMOD_LOAD_MAP */
|
||||
INSMOD_OPT_UNUSED = 0x0100
|
||||
#endif
|
||||
#else /* ENABLE_FEATURE_2_4_MODULES */
|
||||
INSMOD_OPT_UNUSED = 0x0004
|
||||
#endif
|
||||
};
|
||||
|
||||
int FAST_FUNC bb_init_module(const char *module, const char *options);
|
||||
int FAST_FUNC bb_delete_module(const char *module, unsigned int flags);
|
||||
|
||||
#if ENABLE_FEATURE_2_4_MODULES
|
||||
extern char *insmod_outputname;
|
||||
|
||||
int FAST_FUNC bb_init_module_24(const char *module, const char *options);
|
||||
#endif
|
||||
|
||||
#if __GNUC_PREREQ(4,1)
|
||||
# pragma GCC visibility pop
|
||||
#endif
|
||||
|
||||
#endif
|
@ -3,98 +3,45 @@
|
||||
* Mini rmmod implementation for busybox
|
||||
*
|
||||
* Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org>
|
||||
* Copyright (C) 2008 Timo Teras <timo.teras@iki.fi>
|
||||
*
|
||||
* Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
|
||||
*/
|
||||
|
||||
#include "libbb.h"
|
||||
|
||||
#ifdef __UCLIBC__
|
||||
extern int delete_module(const char *module, unsigned int flags);
|
||||
#else
|
||||
# include <sys/syscall.h>
|
||||
# define delete_module(mod, flags) syscall(__NR_delete_module, mod, flags)
|
||||
#endif
|
||||
|
||||
#if ENABLE_FEATURE_2_6_MODULES
|
||||
static void filename2modname(char *modname, const char *afterslash)
|
||||
{
|
||||
unsigned int i;
|
||||
int kr_chk = 1;
|
||||
|
||||
if (ENABLE_FEATURE_2_4_MODULES
|
||||
&& get_linux_version_code() <= KERNEL_VERSION(2,6,0))
|
||||
kr_chk = 0;
|
||||
|
||||
/* Convert to underscores, stop at first . */
|
||||
for (i = 0; afterslash[i] && afterslash[i] != '.'; i++) {
|
||||
if (kr_chk && (afterslash[i] == '-'))
|
||||
modname[i] = '_';
|
||||
else
|
||||
modname[i] = afterslash[i];
|
||||
}
|
||||
modname[i] = '\0';
|
||||
}
|
||||
#else
|
||||
void filename2modname(char *modname, const char *afterslash);
|
||||
#endif
|
||||
|
||||
// There really should be a header file for this...
|
||||
|
||||
int query_module(const char *name, int which, void *buf,
|
||||
size_t bufsize, size_t *ret);
|
||||
#include "modutils.h"
|
||||
|
||||
int rmmod_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
|
||||
int rmmod_main(int argc, char **argv)
|
||||
int rmmod_main(int argc UNUSED_PARAM, char **argv)
|
||||
{
|
||||
int n, ret = EXIT_SUCCESS;
|
||||
int n;
|
||||
unsigned int flags = O_NONBLOCK|O_EXCL;
|
||||
|
||||
#define misc_buf bb_common_bufsiz1
|
||||
|
||||
/* Parse command line. */
|
||||
n = getopt32(argv, "wfa");
|
||||
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 */
|
||||
/* 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 (delete_module(NULL, flags) != 0) {
|
||||
if (errno == EFAULT)
|
||||
return ret;
|
||||
if (bb_delete_module(NULL, flags) != 0 && errno != EFAULT)
|
||||
bb_perror_msg_and_die("rmmod");
|
||||
}
|
||||
pnmod = nmod;
|
||||
// the 1 here is QM_MODULES.
|
||||
if (ENABLE_FEATURE_QUERY_MODULE_INTERFACE && query_module(NULL,
|
||||
1, misc_buf, sizeof(misc_buf),
|
||||
&nmod))
|
||||
{
|
||||
bb_perror_msg_and_die("QM_MODULES");
|
||||
}
|
||||
}
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
if (optind == argc)
|
||||
if (!*argv)
|
||||
bb_show_usage();
|
||||
|
||||
for (n = optind; n < argc; n++) {
|
||||
if (ENABLE_FEATURE_2_6_MODULES) {
|
||||
filename2modname(misc_buf, bb_basename(argv[n]));
|
||||
while (*argv) {
|
||||
char modname[MODULE_NAME_LEN];
|
||||
filename2modname(bb_basename(*argv++), modname);
|
||||
if (bb_delete_module(modname, flags))
|
||||
bb_error_msg_and_die("cannot unload '%s': %s",
|
||||
modname, moderror(errno));
|
||||
}
|
||||
|
||||
if (delete_module(ENABLE_FEATURE_2_6_MODULES ? misc_buf : argv[n], flags)) {
|
||||
bb_simple_perror_msg(argv[n]);
|
||||
ret = EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user