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