insmod/modprobe: do not pass NULL to kernel as module parameter
[platform/upstream/busybox.git] / modutils / modutils.c
1 /*
2  * Common modutils related functions for busybox
3  *
4  * Copyright (C) 2008 by Timo Teras <timo.teras@iki.fi>
5  *
6  * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
7  */
8
9 #include "modutils.h"
10
11 #ifdef __UCLIBC__
12 extern int init_module(void *module, unsigned long len, const char *options);
13 extern int delete_module(const char *module, unsigned int flags);
14 #else
15 # include <sys/syscall.h>
16 # define init_module(mod, len, opts) syscall(__NR_init_module, mod, len, opts)
17 # define delete_module(mod, flags) syscall(__NR_delete_module, mod, flags)
18 #endif
19
20 /*
21  a libbb candidate from ice age!
22 */
23 llist_t FAST_FUNC *llist_find(llist_t *first, const char *str)
24 {
25         while (first != NULL) {
26                 if (strcmp(first->data, str) == 0)
27                         return first;
28                 first = first->link;
29         }
30         return NULL;
31 }
32
33 void FAST_FUNC replace(char *s, char what, char with)
34 {
35         while (*s) {
36                 if (what == *s)
37                         *s = with;
38                 ++s;
39         }
40 }
41
42 char * FAST_FUNC replace_underscores(char *s)
43 {
44         replace(s, '-', '_');
45         return s;
46 }
47
48 int FAST_FUNC string_to_llist(char *string, llist_t **llist, const char *delim)
49 {
50         char *tok;
51         int len = 0;
52
53         while ((tok = strsep(&string, delim)) != NULL) {
54                 if (tok[0] == '\0')
55                         continue;
56                 llist_add_to_end(llist, xstrdup(tok));
57                 len += strlen(tok);
58         }
59         return len;
60 }
61
62 char * FAST_FUNC filename2modname(const char *filename, char *modname)
63 {
64         int i;
65         char *from;
66
67         if (filename == NULL)
68                 return NULL;
69         if (modname == NULL)
70                 modname = xmalloc(MODULE_NAME_LEN);
71         from = bb_get_last_path_component_nostrip(filename);
72         for (i = 0; i < (MODULE_NAME_LEN-1) && from[i] != '\0' && from[i] != '.'; i++)
73                 modname[i] = (from[i] == '-') ? '_' : from[i];
74         modname[i] = 0;
75
76         return modname;
77 }
78
79 const char * FAST_FUNC moderror(int err)
80 {
81         switch (err) {
82         case -1:
83                 return "no such module";
84         case ENOEXEC:
85                 return "invalid module format";
86         case ENOENT:
87                 return "unknown symbol in module, or unknown parameter";
88         case ESRCH:
89                 return "module has wrong symbol version";
90         case ENOSYS:
91                 return "kernel does not support requested operation";
92         default:
93                 return strerror(err);
94         }
95 }
96
97 char * FAST_FUNC parse_cmdline_module_options(char **argv)
98 {
99         char *options;
100         int optlen;
101
102         options = xzalloc(1);
103         optlen = 0;
104         while (*++argv) {
105                 options = xrealloc(options, optlen + 2 + strlen(*argv) + 2);
106                 /* Spaces handled by "" pairs, but no way of escaping quotes */
107                 optlen += sprintf(options + optlen, (strchr(*argv, ' ') ? "\"%s\" " : "%s "), *argv);
108         }
109         return options;
110 }
111
112 int FAST_FUNC bb_init_module(const char *filename, const char *options)
113 {
114         size_t len = MAXINT(ssize_t);
115         char *image;
116         int rc = ENOENT;
117
118         if (!options)
119                 options = "";
120
121 #if ENABLE_FEATURE_2_4_MODULES
122         if (get_linux_version_code() < KERNEL_VERSION(2,6,0))
123                 return bb_init_module_24(filename, options);
124 #endif
125
126         /* Use the 2.6 way */
127         image = xmalloc_open_zipped_read_close(filename, &len);
128         if (image) {
129                 rc = 0;
130                 if (init_module(image, len, options) != 0)
131                         rc = errno;
132                 free(image);
133         }
134
135         return rc;
136 }
137
138 int FAST_FUNC bb_delete_module(const char *module, unsigned int flags)
139 {
140         return delete_module(module, flags);
141 }