mirror of
https://github.com/sheumann/hush.git
synced 2025-01-27 06:34:03 +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...]"
|
"[-knqrsv] MODULE [symbol=value...]"
|
||||||
#define modprobe_full_usage "\n\n" \
|
#define modprobe_full_usage "\n\n" \
|
||||||
"Options:" \
|
"Options:" \
|
||||||
|
USE_FEATURE_2_4_MODULES( \
|
||||||
"\n -k Make module autoclean-able" \
|
"\n -k Make module autoclean-able" \
|
||||||
|
) \
|
||||||
"\n -n Dry run" \
|
"\n -n Dry run" \
|
||||||
"\n -q Quiet" \
|
"\n -q Quiet" \
|
||||||
"\n -r Remove module (stacks) or do autoclean" \
|
"\n -r Remove module (stacks) or do autoclean" \
|
||||||
"\n -s Report via syslog instead of stderr" \
|
"\n -s Report via syslog instead of stderr" \
|
||||||
"\n -v Verbose" \
|
"\n -v Verbose" \
|
||||||
|
USE_FEATURE_MODPROBE_BLACKLIST( \
|
||||||
|
"\n -b Apply blacklist to module names too" \
|
||||||
|
)
|
||||||
|
|
||||||
#define modprobe_notes_usage \
|
#define modprobe_notes_usage \
|
||||||
"modprobe can (un)load a stack of modules, passing each module options (when\n" \
|
"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. */
|
/* Reverse list order. */
|
||||||
llist_t* FAST_FUNC llist_rev(llist_t *list)
|
llist_t* FAST_FUNC llist_rev(llist_t *list)
|
||||||
{
|
{
|
||||||
@ -105,4 +104,3 @@ llist_t* FAST_FUNC llist_rev(llist_t *list)
|
|||||||
}
|
}
|
||||||
return rev;
|
return rev;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
@ -5,6 +5,20 @@
|
|||||||
|
|
||||||
menu "Linux Module Utilities"
|
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
|
config MODPROBE_SMALL
|
||||||
bool "Simplified modutils"
|
bool "Simplified modutils"
|
||||||
default n
|
default n
|
||||||
@ -54,37 +68,6 @@ config FEATURE_MODPROBE_SMALL_CHECK_ALREADY_LOADED
|
|||||||
Check if the module is already loaded.
|
Check if the module is already loaded.
|
||||||
N.B. It's racy.
|
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
|
config INSMOD
|
||||||
bool "insmod"
|
bool "insmod"
|
||||||
default n
|
default n
|
||||||
@ -92,55 +75,6 @@ config INSMOD
|
|||||||
help
|
help
|
||||||
insmod is used to load specified modules in the running kernel.
|
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
|
config RMMOD
|
||||||
bool "rmmod"
|
bool "rmmod"
|
||||||
default n
|
default n
|
||||||
@ -156,12 +90,13 @@ config LSMOD
|
|||||||
lsmod is used to display a list of loaded modules.
|
lsmod is used to display a list of loaded modules.
|
||||||
|
|
||||||
config FEATURE_LSMOD_PRETTY_2_6_OUTPUT
|
config FEATURE_LSMOD_PRETTY_2_6_OUTPUT
|
||||||
bool "Pretty output for 2.6.x Linux kernels"
|
bool "Pretty output"
|
||||||
default n
|
default n
|
||||||
depends on LSMOD
|
depends on LSMOD
|
||||||
help
|
help
|
||||||
This option makes output format of lsmod adjusted to
|
This option makes output format of lsmod adjusted to
|
||||||
the format of module-init-tools for Linux kernel 2.6.
|
the format of module-init-tools for Linux kernel 2.6.
|
||||||
|
Increases size somewhat.
|
||||||
|
|
||||||
config MODPROBE
|
config MODPROBE
|
||||||
bool "modprobe"
|
bool "modprobe"
|
||||||
@ -174,38 +109,11 @@ config MODPROBE
|
|||||||
Note that in the state, modprobe does not understand multiple
|
Note that in the state, modprobe does not understand multiple
|
||||||
module options from the configuration file. See option below.
|
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
|
config FEATURE_MODPROBE_BLACKLIST
|
||||||
bool
|
bool
|
||||||
prompt "Blacklist support"
|
prompt "Blacklist support"
|
||||||
default n
|
default n
|
||||||
depends on MODPROBE && FEATURE_2_6_MODULES
|
depends on MODPROBE
|
||||||
help
|
help
|
||||||
Say 'y' here to enable support for the 'blacklist' command in
|
Say 'y' here to enable support for the 'blacklist' command in
|
||||||
modprobe.conf. This prevents the alias resolver to resolve
|
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
|
hardware autodetection scripts to load modules like evdev, frame
|
||||||
buffer drivers etc.
|
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"
|
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
|
config FEATURE_CHECK_TAINTED_MODULE
|
||||||
# Simulate indentation
|
|
||||||
bool "Support tainted module checking with new kernels"
|
bool "Support tainted module checking with new kernels"
|
||||||
default y
|
default y
|
||||||
depends on INSMOD || LSMOD
|
depends on !MODPROBE_SMALL
|
||||||
help
|
help
|
||||||
Support checking for tainted modules. These are usually binary
|
Support checking for tainted modules. These are usually binary
|
||||||
only modules that will make the linux-kernel list ignore your
|
only modules that will make the linux-kernel list ignore your
|
||||||
support request.
|
support request.
|
||||||
This option is required to support GPLONLY modules.
|
This option is required to support GPLONLY modules.
|
||||||
|
|
||||||
config FEATURE_2_4_MODULES
|
config FEATURE_MODUTILS_ALIAS
|
||||||
# Simulate indentation
|
bool "Support for module.aliases file"
|
||||||
bool "Support version 2.2.x to 2.4.x Linux kernels"
|
|
||||||
default y
|
default y
|
||||||
depends on INSMOD || RMMOD || MODPROBE
|
depends on DEPMOD || MODPROBE
|
||||||
help
|
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:
|
and aliases for logical modules names e.g.:
|
||||||
This is automatically enabled if 2.6 modules are not enabled.
|
alias padlock_aes aes
|
||||||
|
alias aes_i586 aes
|
||||||
|
alias aes_generic aes
|
||||||
|
|
||||||
config FEATURE_2_6_MODULES
|
Say Y if unsure.
|
||||||
# Simulate indentation
|
|
||||||
bool "Support version 2.6.x Linux kernels"
|
config FEATURE_MODUTILS_SYMBOLS
|
||||||
|
bool "Support for module.symbols file"
|
||||||
default y
|
default y
|
||||||
depends on INSMOD || RMMOD || MODPROBE
|
depends on DEPMOD || MODPROBE
|
||||||
help
|
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
|
Say Y if unsure.
|
||||||
# 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
|
|
||||||
|
|
||||||
endmenu
|
endmenu
|
||||||
|
@ -5,9 +5,10 @@
|
|||||||
# Licensed under the GPL v2, see the file LICENSE in this tarball.
|
# Licensed under the GPL v2, see the file LICENSE in this tarball.
|
||||||
|
|
||||||
lib-y:=
|
lib-y:=
|
||||||
lib-$(CONFIG_DEPMOD) += depmod.o
|
lib-$(CONFIG_MODPROBE_SMALL) += modprobe-small.o
|
||||||
lib-$(CONFIG_INSMOD) += insmod.o
|
lib-$(CONFIG_DEPMOD) += depmod.o modutils.o
|
||||||
lib-$(CONFIG_LSMOD) += lsmod.o
|
lib-$(CONFIG_INSMOD) += insmod.o modutils.o
|
||||||
lib-$(CONFIG_MODPROBE) += modprobe.o
|
lib-$(CONFIG_LSMOD) += lsmod.o modutils.o
|
||||||
lib-$(CONFIG_MODPROBE_SMALL) += modprobe-small.o
|
lib-$(CONFIG_MODPROBE) += modprobe.o modutils.o
|
||||||
lib-$(CONFIG_RMMOD) += rmmod.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
|
* depmod - generate modules.dep
|
||||||
* Copyright (c) 2008 Bernhard Fischer
|
* 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.
|
* Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
|
||||||
*/
|
*/
|
||||||
@ -10,6 +12,8 @@
|
|||||||
#define _GNU_SOURCE
|
#define _GNU_SOURCE
|
||||||
#include <libbb.h>
|
#include <libbb.h>
|
||||||
#include <sys/utsname.h> /* uname() */
|
#include <sys/utsname.h> /* uname() */
|
||||||
|
#include "modutils.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Theory of operation:
|
* Theory of operation:
|
||||||
* - iterate over all modules and record their full path
|
* - iterate over all modules and record their full path
|
||||||
@ -17,272 +21,194 @@
|
|||||||
* for each depends, look through our list of full paths and emit if found
|
* for each depends, look through our list of full paths and emit if found
|
||||||
*/
|
*/
|
||||||
|
|
||||||
typedef struct dep_lst_t {
|
typedef struct module_info {
|
||||||
char *name;
|
struct module_info *next;
|
||||||
|
char *name, *modname;
|
||||||
llist_t *dependencies;
|
llist_t *dependencies;
|
||||||
llist_t *aliases;
|
llist_t *aliases;
|
||||||
struct dep_lst_t *next;
|
llist_t *symbols;
|
||||||
} dep_lst_t;
|
struct module_info *dnext, *dprev;
|
||||||
|
} module_info;
|
||||||
|
|
||||||
struct globals {
|
enum {
|
||||||
dep_lst_t *lst; /* modules without their corresponding extension */
|
ARG_a = (1<<0), /* All modules, ignore mods in argv */
|
||||||
|
ARG_A = (1<<1), /* Only emit .ko that are newer than modules.dep file */
|
||||||
|
ARG_b = (1<<2), /* not /lib/modules/$(uname -r)/ but this base-dir */
|
||||||
|
ARG_e = (1<<3), /* with -F, print unresolved symbols */
|
||||||
|
ARG_F = (1<<4), /* System.map that contains the symbols */
|
||||||
|
ARG_n = (1<<5) /* dry-run, print to stdout only */
|
||||||
};
|
};
|
||||||
#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)
|
static int FAST_FUNC parse_module(const char *fname, struct stat *sb,
|
||||||
{
|
void *data, int UNUSED_PARAM depth)
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
|
module_info **first = (module_info **) data;
|
||||||
|
char *image, *ptr;
|
||||||
|
module_info *info;
|
||||||
size_t len = sb->st_size;
|
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 */
|
if (strrstr(fname, ".ko") == NULL)
|
||||||
goto skip;
|
return TRUE;
|
||||||
|
|
||||||
/*XXX: FIXME: does not handle compressed modules!
|
image = (char *) xmalloc_open_zipped_read_close(fname, &len);
|
||||||
* There should be a function that looks at the extension and sets up
|
info = xzalloc(sizeof(module_info));
|
||||||
* 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));
|
info->next = *first;
|
||||||
this->name = xstrdup(fname);
|
*first = info;
|
||||||
this->next = G.lst;
|
|
||||||
G.lst = this;
|
info->dnext = info->dprev = info;
|
||||||
//bb_info_msg("fname='%s'", fname);
|
info->name = xstrdup(fname);
|
||||||
ptr = find_keyword(the_module, len, "depends=");
|
info->modname = filename2modname(fname, NULL);
|
||||||
if (!*ptr)
|
for (ptr = image; ptr < image + len - 10; ptr++) {
|
||||||
goto d_none;
|
if (strncmp(ptr, "depends=", 8) == 0) {
|
||||||
deps = depends = xstrdup(ptr);
|
char *u;
|
||||||
//bb_info_msg(" depends='%s'", depends);
|
|
||||||
while (deps) {
|
ptr += 8;
|
||||||
ptr = strsep(&deps, ",");
|
for (u = ptr; *u; u++)
|
||||||
//bb_info_msg("[%s] -> '%s'", fname, (char*)ptr);
|
if (*u == '-')
|
||||||
llist_add_to_end(&this->dependencies, xstrdup(ptr));
|
*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(depends);
|
free(image);
|
||||||
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;
|
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, char **argv) MAIN_EXTERNALLY_VISIBLE;
|
||||||
int depmod_main(int argc UNUSED_PARAM, char **argv)
|
int depmod_main(int argc UNUSED_PARAM, char **argv)
|
||||||
{
|
{
|
||||||
int ret;
|
module_info *modules = NULL, *m, *dep;
|
||||||
size_t moddir_base_len = 0; /* length of the "-b basedir" */
|
char *moddir_base = (char *)CONFIG_DEFAULT_MODULES_DIR;
|
||||||
char *moddir_base = NULL, *moddir, *system_map, *chp;
|
int tmp;
|
||||||
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 */
|
|
||||||
ARG_b = (1<<2), /* not /lib/modules/$(uname -r)/ but this base-dir */
|
|
||||||
ARG_e = (1<<3), /* with -F, print unresolved symbols */
|
|
||||||
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);
|
getopt32(argv, "aAb:eF:n", &moddir_base, NULL);
|
||||||
argv += optind;
|
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
|
* is used, rather than the current kernel version (as returned by
|
||||||
* "uname -r"). */
|
* "uname -r"). */
|
||||||
if (*argv && (sscanf(*argv, "%d.%d.%d", &ret, &ret, &ret) == 3)) {
|
xchdir(moddir_base);
|
||||||
moddir = concat_path_file(CONFIG_DEFAULT_MODULES_DIR, *argv++);
|
if (*argv && (sscanf(*argv, "%d.%d.%d", &tmp, &tmp, &tmp) == 3)) {
|
||||||
|
xchdir(*argv++);
|
||||||
} else {
|
} else {
|
||||||
struct utsname uts;
|
struct utsname uts;
|
||||||
if (uname(&uts) < 0)
|
uname(&uts);
|
||||||
bb_simple_perror_msg_and_die("uname");
|
xchdir(uts.release);
|
||||||
moddir = concat_path_file(CONFIG_DEFAULT_MODULES_DIR, uts.release);
|
|
||||||
}
|
}
|
||||||
/* If no modules are given on the command-line, -a is on per default. */
|
/* If no modules are given on the command-line, -a is on per default. */
|
||||||
option_mask32 |= *argv == NULL;
|
option_mask32 |= *argv == NULL;
|
||||||
|
|
||||||
if (option_mask32 & ARG_b) {
|
/* Scan modules */
|
||||||
moddir_base_len = strlen(moddir_base) + 1;
|
moddir_base = xrealloc_getcwd_or_warn(NULL);
|
||||||
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;
|
|
||||||
do {
|
do {
|
||||||
chp = option_mask32 & ARG_a ? moddir : (*argv + moddir_base_len);
|
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(moddir_base);
|
||||||
|
|
||||||
if (!recursive_action(chp,
|
/* Generate dependency and alias files */
|
||||||
ACTION_RECURSE, /* flags */
|
if (!(option_mask32 & ARG_n))
|
||||||
fileAction, /* file action */
|
freopen(CONFIG_DEFAULT_DEPMOD_FILE, "w", stdout);
|
||||||
NULL, /* dir action */
|
for (m = modules; m != NULL; m = m->next) {
|
||||||
NULL, /* user data */
|
printf("%s:", m->name);
|
||||||
0)) { /* depth */
|
|
||||||
ret = EXIT_FAILURE;
|
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;
|
||||||
}
|
}
|
||||||
} while (!(option_mask32 & ARG_a) && *++argv);
|
puts("");
|
||||||
|
|
||||||
{
|
|
||||||
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)) {
|
|
||||||
if (ENABLE_FEATURE_CLEAN_UP)
|
|
||||||
free(nam);
|
|
||||||
longname = all->name;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
free(nam);
|
|
||||||
all = all->next;
|
|
||||||
}
|
|
||||||
llist_add_to_end(&deps, longname);
|
|
||||||
}
|
|
||||||
mods->dependencies = deps;
|
|
||||||
mods = mods->next;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ENABLE_FEATURE_DEPMOD_PRUNE_FANCY
|
#if ENABLE_FEATURE_MODUTILS_ALIAS
|
||||||
/* modprobe allegedly wants dependencies without duplicates, i.e.
|
if (!(option_mask32 & ARG_n))
|
||||||
* mod1: mod2 mod3
|
freopen("modules.alias", "w", stdout);
|
||||||
* mod2: mod3
|
for (m = modules; m != NULL; m = m->next) {
|
||||||
* mod3:
|
while (m->aliases) {
|
||||||
* implies that mod1 directly depends on mod2 and _not_ mod3 as mod3 is
|
printf("alias %s %s\n",
|
||||||
* already implicitely pulled in via mod2. This leaves us with:
|
(char*)llist_pop(&m->aliases),
|
||||||
* mod1: mod2
|
m->modname);
|
||||||
* mod2: mod3
|
}
|
||||||
* mod3:
|
}
|
||||||
*/
|
#endif
|
||||||
mods = G.lst;
|
#if ENABLE_FEATURE_MODUTILS_SYMBOLS
|
||||||
while (mods) {
|
if (!(option_mask32 & ARG_n))
|
||||||
llist_t *deps = mods->dependencies;
|
freopen("modules.symbols", "w", stdout);
|
||||||
while (deps) {
|
for (m = modules; m != NULL; m = m->next) {
|
||||||
dep_lst_t *all = G.lst;
|
while (m->symbols) {
|
||||||
while (all) {
|
printf("alias symbol:%s %s\n",
|
||||||
if (!strcmp(all->name, deps->data)) {
|
(char*)llist_pop(&m->symbols),
|
||||||
llist_t *implied = all->dependencies;
|
m->modname);
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
all = all->next;
|
|
||||||
}
|
|
||||||
deps = deps->link;
|
|
||||||
}
|
}
|
||||||
mods = mods->next;
|
|
||||||
}
|
}
|
||||||
#endif
|
#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) {
|
if (ENABLE_FEATURE_CLEAN_UP) {
|
||||||
fclose_if_not_stdin(filedes);
|
while (modules) {
|
||||||
free(moddir);
|
module_info *old = modules;
|
||||||
while (G.lst) {
|
modules = modules->next;
|
||||||
dep_lst_t *old = G.lst;
|
|
||||||
G.lst = G.lst->next;
|
|
||||||
free(old->name);
|
free(old->name);
|
||||||
|
free(old->modname);
|
||||||
free(old);
|
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
|
* Mini lsmod implementation for busybox
|
||||||
*
|
*
|
||||||
* Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org>
|
* Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org>
|
||||||
*
|
* Copyright (C) 2008 by Vladimir Dronnikov <dronnikov@gmail.com>
|
||||||
* 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).
|
|
||||||
*
|
*
|
||||||
* Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
|
* Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "libbb.h"
|
#include "libbb.h"
|
||||||
|
|
||||||
|
#if ENABLE_FEATURE_CHECK_TAINTED_MODULE
|
||||||
#if !ENABLE_FEATURE_CHECK_TAINTED_MODULE
|
enum {
|
||||||
static void check_tainted(void) { bb_putchar('\n'); }
|
TAINT_PROPRIETORY_MODULE = (1 << 0),
|
||||||
#else
|
TAINT_FORCED_MODULE = (1 << 1),
|
||||||
#define TAINT_FILENAME "/proc/sys/kernel/tainted"
|
TAINT_UNSAFE_SMP = (1 << 2),
|
||||||
#define TAINT_PROPRIETORY_MODULE (1<<0)
|
};
|
||||||
#define TAINT_FORCED_MODULE (1<<1)
|
|
||||||
#define TAINT_UNSAFE_SMP (1<<2)
|
|
||||||
|
|
||||||
static void check_tainted(void)
|
static void check_tainted(void)
|
||||||
{
|
{
|
||||||
int tainted;
|
int tainted = 0;
|
||||||
FILE *f;
|
char *buf = xmalloc_open_read_close("/proc/sys/kernel/tainted", NULL);
|
||||||
|
if (buf) {
|
||||||
tainted = 0;
|
tainted = atoi(buf);
|
||||||
f = fopen_for_read(TAINT_FILENAME);
|
if (ENABLE_FEATURE_CLEAN_UP)
|
||||||
if (f) {
|
free(buf);
|
||||||
fscanf(f, "%d", &tainted);
|
|
||||||
fclose(f);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tainted) {
|
if (tainted) {
|
||||||
printf(" Tainted: %c%c%c\n",
|
printf(" Tainted: %c%c%c\n",
|
||||||
tainted & TAINT_PROPRIETORY_MODULE ? 'P' : 'G',
|
tainted & TAINT_PROPRIETORY_MODULE ? 'P' : 'G',
|
||||||
tainted & TAINT_FORCED_MODULE ? 'F' : ' ',
|
tainted & TAINT_FORCED_MODULE ? 'F' : ' ',
|
||||||
tainted & TAINT_UNSAFE_SMP ? 'S' : ' ');
|
tainted & TAINT_UNSAFE_SMP ? 'S' : ' ');
|
||||||
} else {
|
} 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
|
#else
|
||||||
xprint_and_close_file(file);
|
static void check_tainted(void) { putchar('\n'); }
|
||||||
#endif /* CONFIG_FEATURE_2_6_MODULES */
|
#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;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* CONFIG_FEATURE_QUERY_MODULE_INTERFACE */
|
|
||||||
|
1135
modutils/modprobe.c
1135
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
|
* Mini rmmod implementation for busybox
|
||||||
*
|
*
|
||||||
* Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org>
|
* 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.
|
* Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "libbb.h"
|
#include "libbb.h"
|
||||||
|
#include "modutils.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);
|
|
||||||
|
|
||||||
int rmmod_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
|
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;
|
unsigned int flags = O_NONBLOCK|O_EXCL;
|
||||||
|
|
||||||
#define misc_buf bb_common_bufsiz1
|
|
||||||
|
|
||||||
/* Parse command line. */
|
/* Parse command line. */
|
||||||
n = getopt32(argv, "wfa");
|
n = getopt32(argv, "wfas"); // -s ignored
|
||||||
|
argv += optind;
|
||||||
|
|
||||||
if (n & 1) // --wait
|
if (n & 1) // --wait
|
||||||
flags &= ~O_NONBLOCK;
|
flags &= ~O_NONBLOCK;
|
||||||
if (n & 2) // --force
|
if (n & 2) // --force
|
||||||
flags |= O_TRUNC;
|
flags |= O_TRUNC;
|
||||||
if (n & 4) {
|
if (n & 4) {
|
||||||
/* Unload _all_ unused modules via NULL delete_module() call */
|
/* Unload _all_ unused modules via NULL delete_module() call */
|
||||||
/* until the number of modules does not change */
|
if (bb_delete_module(NULL, flags) != 0 && errno != EFAULT)
|
||||||
size_t nmod = 0; /* number of modules */
|
bb_perror_msg_and_die("rmmod");
|
||||||
size_t pnmod = -1; /* previous number of modules */
|
|
||||||
|
|
||||||
while (nmod != pnmod) {
|
|
||||||
if (delete_module(NULL, flags) != 0) {
|
|
||||||
if (errno == EFAULT)
|
|
||||||
return ret;
|
|
||||||
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;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (optind == argc)
|
if (!*argv)
|
||||||
bb_show_usage();
|
bb_show_usage();
|
||||||
|
|
||||||
for (n = optind; n < argc; n++) {
|
while (*argv) {
|
||||||
if (ENABLE_FEATURE_2_6_MODULES) {
|
char modname[MODULE_NAME_LEN];
|
||||||
filename2modname(misc_buf, bb_basename(argv[n]));
|
filename2modname(bb_basename(*argv++), modname);
|
||||||
}
|
if (bb_delete_module(modname, flags))
|
||||||
|
bb_error_msg_and_die("cannot unload '%s': %s",
|
||||||
if (delete_module(ENABLE_FEATURE_2_6_MODULES ? misc_buf : argv[n], flags)) {
|
modname, moderror(errno));
|
||||||
bb_simple_perror_msg(argv[n]);
|
|
||||||
ret = EXIT_FAILURE;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user