You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

162 lines
4.7 KiB

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;
}