Changes for kernel and Busybox
[tomato.git] / release / src / router / busybox / modutils / insmod.c
blobf6d4b982ff4838e326010eb61849fe125edbf543
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: "\n -f Force module to load into the wrong kernel version"
28 //usage: "\n -k Make module autoclean-able"
29 //usage: "\n -v Verbose"
30 //usage: "\n -q Quiet"
31 //usage: "\n -L Lock: prevent simultaneous loads"
32 //usage: IF_FEATURE_INSMOD_LOAD_MAP(
33 //usage: "\n -m Output load map to stdout"
34 //usage: )
35 //usage: "\n -x Don't export externs"
36 //usage: )
37 //usage:#endif
39 static char *m_filename;
41 static int FAST_FUNC check_module_name_match(const char *filename,
42 struct stat *statbuf UNUSED_PARAM,
43 void *userdata, int depth UNUSED_PARAM)
45 char *fullname = (char *) userdata;
46 char *tmp;
48 if (fullname[0] == '\0')
49 return FALSE;
51 tmp = bb_get_last_path_component_nostrip(filename);
52 if (strcmp(tmp, fullname) == 0) {
53 /* Stop searching if we find a match */
54 m_filename = xstrdup(filename);
55 return FALSE;
57 return TRUE;
60 int insmod_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
61 int insmod_main(int argc UNUSED_PARAM, char **argv)
63 struct stat st;
64 char *filename;
65 FILE *fp = NULL;
66 int pos;
67 int rc;
69 /* Compat note:
70 * 2.6 style insmod has no options and required filename
71 * (not module name - .ko can't be omitted).
72 * 2.4 style insmod can take module name without .o
73 * and performs module search in default directories
74 * or in $MODPATH.
77 IF_FEATURE_2_4_MODULES(
78 getopt32(argv, INSMOD_OPTS INSMOD_ARGS);
79 argv += optind - 1;
82 filename = *++argv;
83 if (!filename)
84 bb_show_usage();
86 m_filename = NULL;
88 pos = strlen(filename) - 2;
89 if (get_linux_version_code() < KERNEL_VERSION(2,6,0)) {
90 if (pos < 0) pos = 0;
91 if (strncmp(&filename[pos], ".o", 2) !=0)
92 filename = xasprintf("%s.o", filename);
93 } else {
94 if (--pos < 0) pos = 0;
95 if (strncmp(&filename[pos], ".ko", 3) !=0)
96 filename = xasprintf("%s.ko", filename);
99 /* Get a filedesc for the module. Check if we have a complete path */
100 if (stat(filename, &st) < 0 || !S_ISREG(st.st_mode) ||
101 (fp = fopen_for_read(filename)) == NULL) {
102 /* Hmm. Could not open it. Search /lib/modules/ */
103 int r;
104 char *module_dir;
106 module_dir = xmalloc_readlink(CONFIG_DEFAULT_MODULES_DIR);
107 if (!module_dir)
108 module_dir = xstrdup(CONFIG_DEFAULT_MODULES_DIR);
109 r = recursive_action(module_dir, ACTION_RECURSE,
110 check_module_name_match, NULL, filename, 0);
111 free(module_dir);
112 if (r)
113 bb_error_msg_and_die("'%s': module not found", filename);
114 if (m_filename == NULL || ((fp = fopen_for_read(m_filename)) == NULL))
115 bb_error_msg_and_die("'%s': module not found", filename);
116 filename = m_filename;
118 if (fp != NULL)
119 fclose(fp);
121 rc = bb_init_module(filename, parse_cmdline_module_options(argv, /*quote_spaces:*/ 0));
122 if (rc)
123 bb_error_msg("can't insert '%s': %s", filename, moderror(rc));
125 free(m_filename);
126 return rc;