busybox: Fix insmod for linux 3.0
[openwrt.git] / package / busybox / patches / 470-insmod_search.patch
1 --- a/modutils/insmod.c
2 +++ b/modutils/insmod.c
3 @@ -11,6 +11,106 @@
4  
5  #include "libbb.h"
6  #include "modutils.h"
7 +#include <sys/utsname.h>
8 +#ifndef CONFIG_FEATURE_2_4_MODULES
9 +#include <sys/mman.h>
10 +#include <asm/unistd.h>
11 +#include <sys/syscall.h>
12 +#endif
13 +
14 +static char *g_filename = NULL;
15 +
16 +static int FAST_FUNC check_module_name_match(const char *filename, struct stat *statbuf,
17 +                                  void *userdata, int depth)
18 +{
19 +       char *fullname = (char *) userdata;
20 +       char *tmp;
21 +
22 +       if (fullname[0] == '\0')
23 +               return FALSE;
24 +
25 +       tmp = bb_get_last_path_component_nostrip(filename);
26 +       if (strcmp(tmp, fullname) == 0) {
27 +               /* Stop searching if we find a match */
28 +               g_filename = xstrdup(filename);
29 +               return FALSE;
30 +       }
31 +
32 +       return TRUE;
33 +}
34 +
35 +static int find_module(char *filename)
36 +{
37 +       char *module_dir, real_module_dir[FILENAME_MAX];
38 +       int len, slen, ret = ENOENT, k_version;
39 +       struct utsname myuname;
40 +       const char *suffix = ".ko";
41 +       struct stat st;
42 +
43 +       /* check the kernel version */
44 +       if (uname(&myuname) != 0)
45 +               return EINVAL;
46 +
47 +       k_version = myuname.release[0] - '0';
48 +
49 +       if (k_version < 2 || k_version > 9)
50 +               return EINVAL;
51 +
52 +       if (k_version == 2) {
53 +               int k_patchlevel = myuname.release[2] - '0';
54 +               if (k_patchlevel <= 4)
55 +#if ENABLE_FEATURE_2_4_MODULES
56 +                       suffix = ".o";
57 +#else
58 +                       return EINVAL;
59 +#endif
60 +       }
61 +
62 +       len = strlen(filename);
63 +       slen = strlen(suffix);
64 +
65 +       /* check for suffix and absolute path first */
66 +       if ((len < slen + 2) || (strcmp(filename + len - slen, suffix) != 0)) {
67 +               filename = xasprintf("%s%s", filename, suffix);
68 +       } else {
69 +               filename = strdup(filename);
70 +               if ((stat(filename, &st) == 0) && S_ISREG(st.st_mode)) {
71 +                       g_filename = filename;
72 +                       return 0;
73 +               }
74 +               free(filename);
75 +               return ENOENT;
76 +       }
77 +
78 +       /* next: scan /lib/modules/<release> */
79 +       /* Jump through hoops in case /lib/modules/`uname -r`
80 +       * is a symlink.  We do not want recursive_action to
81 +       * follow symlinks, but we do want to follow the
82 +       * /lib/modules/`uname -r` dir, So resolve it ourselves
83 +       * if it is a link... */
84 +       module_dir = concat_path_file(CONFIG_DEFAULT_MODULES_DIR, myuname.release);
85 +       if (realpath(module_dir, real_module_dir) != NULL) {
86 +               free(module_dir);
87 +               module_dir = real_module_dir;
88 +       }
89 +
90 +       recursive_action(module_dir, ACTION_RECURSE,
91 +               check_module_name_match, 0, filename, 0);
92 +
93 +       /* Check if we have a complete path */
94 +       if (g_filename == NULL)
95 +               goto done;
96 +
97 +       if ((stat(g_filename, &st) == 0) && S_ISREG(st.st_mode))
98 +               ret = 0;
99 +       else
100 +               free(g_filename);
101 +
102 +done:
103 +       free(filename);
104 +
105 +       return ret;
106 +}
107  
108  /* 2.6 style insmod has no options and required filename
109   * (not module name - .ko can't be omitted) */
110 @@ -59,9 +159,15 @@ int insmod_main(int argc UNUSED_PARAM, c
111         if (!filename)
112                 bb_show_usage();
113  
114 -       rc = bb_init_module(filename, parse_cmdline_module_options(argv));
115 +       rc = find_module(filename);
116 +       if (rc || (g_filename == NULL))
117 +                       goto done;
118 +
119 +       rc = bb_init_module(g_filename, parse_cmdline_module_options(argv));
120         if (rc)
121                 bb_error_msg("can't insert '%s': %s", filename, moderror(rc));
122 +       free (g_filename);
123  
124 +done:
125         return rc;
126  }
127 --- a/modutils/Config.src
128 +++ b/modutils/Config.src
129 @@ -229,7 +229,7 @@ config FEATURE_MODUTILS_SYMBOLS
130  config DEFAULT_MODULES_DIR
131         string "Default directory containing modules"
132         default "/lib/modules"
133 -       depends on DEPMOD || MODPROBE || MODPROBE_SMALL || MODINFO
134 +       depends on DEPMOD || INSMOD || MODPROBE || MODPROBE_SMALL || MODINFO
135         help
136           Directory that contains kernel modules.
137           Defaults to "/lib/modules"