|
|
|
diff --git a/modutils/Config.src b/modutils/Config.src
|
|
|
|
index 9b76c83..c7579c5 100644
|
|
|
|
--- a/modutils/Config.src
|
|
|
|
+++ b/modutils/Config.src
|
|
|
|
@@ -166,7 +166,7 @@ config FEATURE_MODUTILS_SYMBOLS
|
|
|
|
config DEFAULT_MODULES_DIR
|
|
|
|
string "Default directory containing modules"
|
|
|
|
default "/lib/modules"
|
|
|
|
- depends on DEPMOD || MODPROBE || MODINFO
|
|
|
|
+ depends on DEPMOD || MODPROBE || MODINFO || INSMOD
|
|
|
|
help
|
|
|
|
Directory that contains kernel modules.
|
|
|
|
Defaults to "/lib/modules"
|
|
|
|
diff --git a/modutils/insmod.c b/modutils/insmod.c
|
|
|
|
index 8526979..d36acc4 100644
|
|
|
|
--- a/modutils/insmod.c
|
|
|
|
+++ b/modutils/insmod.c
|
|
|
|
@@ -45,11 +45,42 @@
|
|
|
|
//usage: )
|
|
|
|
//usage:#endif
|
|
|
|
|
|
|
|
+#include <sys/utsname.h>
|
|
|
|
+static char *m_filename;
|
|
|
|
+static char *m_fullName;
|
|
|
|
+
|
|
|
|
+static int FAST_FUNC check_module_name_match(const char *filename,
|
|
|
|
+ struct stat *statbuf UNUSED_PARAM,
|
|
|
|
+ void *userdata, int depth UNUSED_PARAM)
|
|
|
|
+{
|
|
|
|
+ char *fullname = (char *) userdata;
|
|
|
|
+ char *tmp;
|
|
|
|
+
|
|
|
|
+ if (fullname[0] == '\0')
|
|
|
|
+ return FALSE;
|
|
|
|
+
|
|
|
|
+ tmp = bb_get_last_path_component_nostrip(filename);
|
|
|
|
+ if (strcmp(tmp, fullname) == 0) {
|
|
|
|
+ /* Stop searching if we find a match */
|
|
|
|
+ m_filename = xstrdup(filename);
|
|
|
|
+ return FALSE;
|
|
|
|
+ }
|
|
|
|
+ return TRUE;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
int insmod_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
|
|
|
|
int insmod_main(int argc UNUSED_PARAM, char **argv)
|
|
|
|
{
|
|
|
|
char *filename;
|
|
|
|
int rc;
|
|
|
|
+int len;
|
|
|
|
+char *tmp;
|
|
|
|
+char *tmp2;
|
|
|
|
+int k_version = 0;
|
|
|
|
+struct stat st;
|
|
|
|
+struct utsname uts;
|
|
|
|
+char *m_name;
|
|
|
|
+FILE *fp;
|
|
|
|
|
|
|
|
/* Compat note:
|
|
|
|
* 2.6 style insmod has no options and required filename
|
|
|
|
@@ -68,9 +99,99 @@ int insmod_main(int argc UNUSED_PARAM, char **argv)
|
|
|
|
if (!filename)
|
|
|
|
bb_show_usage();
|
|
|
|
|
|
|
|
- rc = bb_init_module(filename, parse_cmdline_module_options(argv, /*quote_spaces:*/ 0));
|
|
|
|
+ /* Grab the module name */
|
|
|
|
+ tmp = xstrdup(filename);
|
|
|
|
+ len = strlen(filename);
|
|
|
|
+
|
|
|
|
+ if (uname(&uts) == 0) {
|
|
|
|
+ if (uts.release[0] == '2') {
|
|
|
|
+ k_version = uts.release[2] - '0';
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (k_version > 4 && len > 3 && tmp[len - 3] == '.'
|
|
|
|
+ && tmp[len - 2] == 'k' && tmp[len - 1] == 'o'
|
|
|
|
+ ) {
|
|
|
|
+ len -= 3;
|
|
|
|
+ tmp[len] = '\0';
|
|
|
|
+ } else
|
|
|
|
+ if (len > 2 && tmp[len - 2] == '.' && tmp[len - 1] == 'o') {
|
|
|
|
+ len -= 2;
|
|
|
|
+ tmp[len] = '\0';
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (k_version > 4)
|
|
|
|
+ m_fullName = xasprintf("%s.ko", tmp);
|
|
|
|
+ else
|
|
|
|
+ m_fullName = xasprintf("%s.o", tmp);
|
|
|
|
+
|
|
|
|
+ if (!m_name) {
|
|
|
|
+ m_name = tmp;
|
|
|
|
+ }
|
|
|
|
+ free(tmp);
|
|
|
|
+
|
|
|
|
+ /* first look in /var/lib/modules */
|
|
|
|
+ tmp2 = alloca(strlen(m_fullName) + sizeof("/var/lib/modules/"));
|
|
|
|
+ strcpy(tmp2, "/var/lib/modules/");
|
|
|
|
+ strcat(tmp2, m_fullName);
|
|
|
|
+ if (stat(tmp2, &st) >= 0 && S_ISREG(st.st_mode) && (fp = fopen(tmp2, "r")) != NULL) {
|
|
|
|
+ m_filename = xstrdup(tmp2);
|
|
|
|
+ printf("insmod: preferring module %s\n", m_filename);
|
|
|
|
+ } else
|
|
|
|
+ /* Get a filedesc for the module. Check that we have a complete path */
|
|
|
|
+ if (stat(filename, &st) < 0 || !S_ISREG(st.st_mode)
|
|
|
|
+ || (fp = fopen_for_read(filename)) == NULL
|
|
|
|
+ ) {
|
|
|
|
+ /* Hmm. Could not open it. First search under /lib/modules/`uname -r`,
|
|
|
|
+ * but do not error out yet if we fail to find it... */
|
|
|
|
+ if (k_version) { /* uname succeedd */
|
|
|
|
+ char *module_dir;
|
|
|
|
+ char *tmdn;
|
|
|
|
+
|
|
|
|
+ tmdn = concat_path_file(CONFIG_DEFAULT_MODULES_DIR, uts.release);
|
|
|
|
+ /* Jump through hoops in case /lib/modules/`uname -r`
|
|
|
|
+ * is a symlink. We do not want recursive_action to
|
|
|
|
+ * follow symlinks, but we do want to follow the
|
|
|
|
+ * /lib/modules/`uname -r` dir, So resolve it ourselves
|
|
|
|
+ * if it is a link... */
|
|
|
|
+ module_dir = xmalloc_readlink(tmdn);
|
|
|
|
+ if (!module_dir)
|
|
|
|
+ module_dir = xstrdup(tmdn);
|
|
|
|
+ recursive_action(module_dir, ACTION_RECURSE,
|
|
|
|
+ check_module_name_match, NULL, m_fullName, 0);
|
|
|
|
+ free(module_dir);
|
|
|
|
+ free(tmdn);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /* Check if we have found anything yet */
|
|
|
|
+ if (!m_filename || ((fp = fopen_for_read(m_filename)) == NULL)) {
|
|
|
|
+ int r;
|
|
|
|
+ char *module_dir;
|
|
|
|
+
|
|
|
|
+ free(m_filename);
|
|
|
|
+ m_filename = NULL;
|
|
|
|
+ module_dir = xmalloc_readlink(CONFIG_DEFAULT_MODULES_DIR);
|
|
|
|
+ if (!module_dir)
|
|
|
|
+ module_dir = xstrdup(CONFIG_DEFAULT_MODULES_DIR);
|
|
|
|
+ /* No module found under /lib/modules/`uname -r`, this
|
|
|
|
+ * time cast the net a bit wider. Search /lib/modules/ */
|
|
|
|
+ r = recursive_action(module_dir, ACTION_RECURSE,
|
|
|
|
+ check_module_name_match, NULL, m_fullName, 0);
|
|
|
|
+ if (r)
|
|
|
|
+ bb_error_msg_and_die("%s: module not found", m_fullName);
|
|
|
|
+ free(module_dir);
|
|
|
|
+ if (m_filename == NULL
|
|
|
|
+ || ((fp = fopen_for_read(m_filename)) == NULL)
|
|
|
|
+ ) {
|
|
|
|
+ bb_error_msg_and_die("%s: module not found", m_fullName);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ } else
|
|
|
|
+ m_filename = xstrdup(filename);
|
|
|
|
+
|
|
|
|
+ rc = bb_init_module(m_filename, parse_cmdline_module_options(argv, /*quote_spaces:*/ 0));
|
|
|
|
if (rc)
|
|
|
|
- bb_error_msg("can't insert '%s': %s", filename, moderror(rc));
|
|
|
|
+ bb_error_msg("can't insert '%s': %s", m_filename, moderror(rc));
|
|
|
|
|
|
|
|
return rc;
|
|
|
|
}
|