1/* vi: set sw=4 ts=4: */ 2/* 3 * Mini insmod implementation for busybox 4 * 5 * Copyright (C) 2008 Timo Teras <timo.teras@iki.fi> 6 * 7 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. 8 */ 9 10#include "libbb.h" 11#include "modutils.h" 12#include <fnmatch.h> 13 14/* 2.6 style insmod has no options and required filename 15 * (not module name - .ko can't be omitted) */ 16 17//usage:#define insmod_trivial_usage 18//usage: IF_FEATURE_2_4_MODULES("[OPTIONS] MODULE ") 19//usage: IF_NOT_FEATURE_2_4_MODULES("FILE ") 20//usage: "[symbol=value]..." 21//usage:#define insmod_full_usage "\n\n" 22//usage: "Load the specified kernel modules into the kernel" 23//usage: IF_FEATURE_2_4_MODULES( "\n" 24//usage: "\nOptions:" 25//usage: "\n -f Force module to load into the wrong kernel version" 26//usage: "\n -k Make module autoclean-able" 27//usage: "\n -v Verbose" 28//usage: "\n -q Quiet" 29//usage: "\n -L Lock: prevent simultaneous loads" 30//usage: IF_FEATURE_INSMOD_LOAD_MAP( 31//usage: "\n -m Output load map to stdout" 32//usage: ) 33//usage: "\n -x Don't export externs" 34//usage: ) 35 36static char *m_filename; 37 38static int FAST_FUNC check_module_name_match(const char *filename, 39 struct stat *statbuf UNUSED_PARAM, 40 void *userdata, int depth UNUSED_PARAM) 41{ 42 char *fullname = (char *) userdata; 43 char *tmp; 44 45 if (fullname[0] == '\0') 46 return FALSE; 47 48 tmp = bb_get_last_path_component_nostrip(filename); 49 if (strcmp(tmp, fullname) == 0) { 50 /* Stop searching if we find a match */ 51 m_filename = xstrdup(filename); 52 return FALSE; 53 } 54 return TRUE; 55} 56 57int insmod_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 58int insmod_main(int argc UNUSED_PARAM, char **argv) 59{ 60 struct stat st; 61 char *filename; 62 FILE *fp = NULL; 63 int pos; 64 int rc; 65 66 /* Compat note: 67 * 2.6 style insmod has no options and required filename 68 * (not module name - .ko can't be omitted). 69 * 2.4 style insmod can take module name without .o 70 * and performs module search in default directories 71 * or in $MODPATH. 72 */ 73 74 IF_FEATURE_2_4_MODULES( 75 getopt32(argv, INSMOD_OPTS INSMOD_ARGS); 76 argv += optind - 1; 77 ); 78 79 filename = *++argv; 80 if (!filename) 81 bb_show_usage(); 82 83 m_filename = NULL; 84 85 pos = strlen(filename) - 2; 86 if (get_linux_version_code() < KERNEL_VERSION(2,6,0)) { 87 if (pos < 0) pos = 0; 88 if (strncmp(&filename[pos], ".o", 2) !=0) 89 filename = xasprintf("%s.o", filename); 90 } else { 91 if (--pos < 0) pos = 0; 92 if (strncmp(&filename[pos], ".ko", 3) !=0) 93 filename = xasprintf("%s.ko", filename); 94 } 95 96 /* Get a filedesc for the module. Check if we have a complete path */ 97 if (stat(filename, &st) < 0 || !S_ISREG(st.st_mode) || 98 (fp = fopen_for_read(filename)) == NULL) { 99 /* Hmm. Could not open it. Search /lib/modules/ */ 100 int r; 101 char *module_dir; 102 103 module_dir = xmalloc_readlink(CONFIG_DEFAULT_MODULES_DIR); 104 if (!module_dir) 105 module_dir = xstrdup(CONFIG_DEFAULT_MODULES_DIR); 106 r = recursive_action(module_dir, ACTION_RECURSE, 107 check_module_name_match, NULL, filename, 0); 108 free(module_dir); 109 if (r) 110 bb_error_msg_and_die("'%s': module not found", filename); 111 if (m_filename == NULL || ((fp = fopen_for_read(m_filename)) == NULL)) 112 bb_error_msg_and_die("'%s': module not found", filename); 113 filename = m_filename; 114 } 115 if (fp != NULL) 116 fclose(fp); 117 118 rc = bb_init_module(filename, parse_cmdline_module_options(argv)); 119 if (rc) 120 bb_error_msg("can't insert '%s': %s", filename, moderror(rc)); 121 122 free(m_filename); 123 return rc; 124} 125