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