* simplified modprobe
*
* Copyright (c) 2008 Vladimir Dronnikov
- * Copyright (c) 2008 Bernhard Fischer (initial depmod code)
+ * Copyright (c) 2008 Bernhard Reutner-Fischer (initial depmod code)
*
* Licensed under GPLv2, see file LICENSE in this tarball for details.
*/
#include "libbb.h"
-
+/* After libbb.h, since it needs sys/types.h on some systems */
#include <sys/utsname.h> /* uname() */
#include <fnmatch.h>
char *module_load_options;
smallint dep_bb_seen;
smallint wrote_dep_bb_ok;
- int module_count;
+ unsigned module_count;
int module_found_idx;
- int stringbuf_idx;
- char stringbuf[32 * 1024]; /* some modules have lots of stuff */
+ unsigned stringbuf_idx;
+ unsigned stringbuf_size;
+ char *stringbuf; /* some modules have lots of stuff */
/* for example, drivers/media/video/saa7134/saa7134.ko */
+ /* therefore having a fixed biggish buffer is not wise */
};
#define G (*ptr_to_globals)
#define modinfo (G.modinfo )
#define module_found_idx (G.module_found_idx )
#define module_load_options (G.module_load_options)
#define stringbuf_idx (G.stringbuf_idx )
+#define stringbuf_size (G.stringbuf_size )
#define stringbuf (G.stringbuf )
#define INIT_G() do { \
SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \
} while (0)
+static void append(const char *s)
+{
+ unsigned len = strlen(s);
+ if (stringbuf_idx + len + 15 > stringbuf_size) {
+ stringbuf_size = stringbuf_idx + len + 127;
+ dbg2_error_msg("grow stringbuf to %u", stringbuf_size);
+ stringbuf = xrealloc(stringbuf, stringbuf_size);
+ }
+ memcpy(stringbuf + stringbuf_idx, s, len);
+ stringbuf_idx += len;
+}
static void appendc(char c)
{
- if (stringbuf_idx < sizeof(stringbuf))
- stringbuf[stringbuf_idx++] = c;
+ /* We appendc() only after append(), + 15 trick in append()
+ * makes it unnecessary to check for overflow here */
+ stringbuf[stringbuf_idx++] = c;
}
static void bksp(void)
stringbuf_idx--;
}
-static void append(const char *s)
-{
- size_t len = strlen(s);
- if (stringbuf_idx + len < sizeof(stringbuf)) {
- memcpy(stringbuf + stringbuf_idx, s, len);
- stringbuf_idx += len;
- }
-}
-
static void reset_stringbuf(void)
{
stringbuf_idx = 0;
static char* copy_stringbuf(void)
{
- char *copy = xmalloc(stringbuf_idx);
+ char *copy = xzalloc(stringbuf_idx + 1); /* terminating NUL */
return memcpy(copy, stringbuf, stringbuf_idx);
}
{
int wlen;
- if (!ptr) /* happens if read_module cannot read it */
+ if (!ptr) /* happens if xmalloc_open_zipped_read_close cannot read it */
return NULL;
wlen = strlen(word);
return dst;
}
-#if ENABLE_FEATURE_MODPROBE_SMALL_ZIPPED
-# define read_module xmalloc_open_zipped_read_close
-#else
-# define read_module xmalloc_open_read_close
-#endif
-
/* We use error numbers in a loose translation... */
static const char *moderror(int err)
{
char *module_image;
dbg1_error_msg("load_module('%s','%s')", fname, options);
- module_image = read_module(fname, &len);
+ module_image = xmalloc_open_zipped_read_close(fname, &len);
r = (!module_image || init_module(module_image, len, options ? options : "") != 0);
free(module_image);
dbg1_error_msg("load_module:%d", r);
/* Read (possibly compressed) module */
len = 64 * 1024 * 1024; /* 64 Mb at most */
- module_image = read_module(pathname, &len);
+ module_image = xmalloc_open_zipped_read_close(pathname, &len);
//TODO: optimize redundant module body reads
/* "alias1 symbol:sym1 alias2 symbol:sym2" */
pos = (ptr - module_image);
}
bksp(); /* remove last ' ' */
- appendc('\0');
info->aliases = copy_stringbuf();
+ replace(info->aliases, '-', '_');
/* "dependency1 depandency2" */
reset_stringbuf();
dbg2_error_msg("dep:'%s'", ptr);
append(ptr);
}
- appendc('\0');
info->deps = copy_stringbuf();
free(module_image);
while ((line = xmalloc_fgetline(fp)) != NULL) {
char* space;
+ char* linebuf;
int cur;
if (!line[0]) {
if (*space)
*space++ = '\0';
modinfo[cur].aliases = space;
- modinfo[cur].deps = xmalloc_fgetline(fp) ? : xzalloc(1);
+ linebuf = xmalloc_fgetline(fp);
+ modinfo[cur].deps = linebuf ? linebuf : xzalloc(1);
if (modinfo[cur].deps[0]) {
/* deps are not "", so next line must be empty */
line = xmalloc_fgetline(fp);
if (!modinfo[i].aliases) {
parse_module(&modinfo[i], modinfo[i].pathname);
}
- if (result)
+ if (result) {
+ i++;
continue;
+ }
/* "alias1 symbol:sym1 alias2 symbol:sym2" */
desc = str_2_list(modinfo[i].aliases);
/* Does matching substring exist? */
}
free(deps);
- /* insmod -> load it */
+ /* modprobe -> load it */
if (!is_rmmod) {
- errno = 0;
- if (load_module(info->pathname, options) != 0) {
- if (EEXIST != errno) {
- bb_error_msg("'%s': %s",
+ if (!options || strstr(options, "blacklist") == NULL) {
+ errno = 0;
+ if (load_module(info->pathname, options) != 0) {
+ if (EEXIST != errno) {
+ bb_error_msg("'%s': %s",
info->pathname,
moderror(errno));
- } else {
- dbg1_error_msg("'%s': %s",
+ } else {
+ dbg1_error_msg("'%s': %s",
info->pathname,
moderror(errno));
+ }
}
+ } else {
+ dbg1_error_msg("'%s': blacklisted", info->pathname);
}
}
ret:
[-b basedirectory] [forced_version]
depmod [-n -e -v -q -r -u] [-F kernelsyms] module1.ko module2.ko ...
If no arguments (except options) are given, "depmod -a" is assumed.
-depmod will output a dependancy list suitable for the modprobe utility.
+depmod will output a dependency list suitable for the modprobe utility.
Options:
-a, --all Probe all modules
-A, --quick Only does the work if there's a new module
{
struct utsname uts;
char applet0 = applet_name[0];
- USE_FEATURE_MODPROBE_SMALL_OPTIONS_ON_CMDLINE(char *options;)
+ IF_FEATURE_MODPROBE_SMALL_OPTIONS_ON_CMDLINE(char *options;)
/* are we lsmod? -> just dump /proc/modules */
if ('l' == applet0) {
/* Prevent ugly corner cases with no modules at all */
modinfo = xzalloc(sizeof(modinfo[0]));
- /* Goto modules directory */
- xchdir(CONFIG_DEFAULT_MODULES_DIR);
+ if ('i' != applet0) { /* not insmod */
+ /* Goto modules directory */
+ xchdir(CONFIG_DEFAULT_MODULES_DIR);
+ }
uname(&uts); /* never fails */
/* depmod? */
option_mask32 |= OPT_r;
}
- /* Goto $VERSION directory */
- xchdir(uts.release);
+ if ('i' != applet0) { /* not insmod */
+ /* Goto $VERSION directory */
+ xchdir(uts.release);
+ }
#if ENABLE_FEATURE_MODPROBE_SMALL_OPTIONS_ON_CMDLINE
/* If not rmmod, parse possible module options given on command line.
argv[1] = NULL;
#endif
+ if ('i' == applet0) { /* insmod */
+ size_t len;
+ void *map;
+
+ len = MAXINT(ssize_t);
+ map = xmalloc_xopen_read_close(*argv, &len);
+ if (init_module(map, len,
+ IF_FEATURE_MODPROBE_SMALL_OPTIONS_ON_CMDLINE(options ? options : "")
+ IF_NOT_FEATURE_MODPROBE_SMALL_OPTIONS_ON_CMDLINE("")
+ ) != 0)
+ bb_error_msg_and_die("can't insert '%s': %s",
+ *argv, moderror(errno));
+ return 0;
+ }
+
/* Try to load modprobe.dep.bb */
load_dep_bb();
/* Load/remove modules.
- * Only rmmod loops here, insmod/modprobe has only argv[0] */
+ * Only rmmod loops here, modprobe has only argv[0] */
do {
process_module(*argv++, options);
} while (*argv);
if (ENABLE_FEATURE_CLEAN_UP) {
- USE_FEATURE_MODPROBE_SMALL_OPTIONS_ON_CMDLINE(free(options);)
+ IF_FEATURE_MODPROBE_SMALL_OPTIONS_ON_CMDLINE(free(options);)
}
return EXIT_SUCCESS;
}