blob: 405785ff5f1753b7fe8f44991de074108db4199a [file] [log] [blame]
Denis Vlasenkoba1315d2008-09-13 14:59:38 +00001/*
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__
12extern int init_module(void *module, unsigned long len, const char *options);
13extern 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
Denis Vlasenkoba1315d2008-09-13 14:59:38 +000020/*
21 a libbb candidate from ice age!
22*/
23llist_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
33void 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
42char * FAST_FUNC replace_underscores(char *s)
43{
44 replace(s, '-', '_');
45 return s;
46}
47
48int 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
62char * 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);
Denis Vlasenko48637e02009-02-26 12:00:52 +000072 for (i = 0; i < (MODULE_NAME_LEN-1) && from[i] != '\0' && from[i] != '.'; i++)
Denis Vlasenkoba1315d2008-09-13 14:59:38 +000073 modname[i] = (from[i] == '-') ? '_' : from[i];
74 modname[i] = 0;
75
76 return modname;
77}
78
79const 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
97char * 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 */
Denis Vlasenkobb26db42008-10-31 02:04:28 +0000107 optlen += sprintf(options + optlen, (strchr(*argv, ' ') ? "\"%s\" " : "%s "), *argv);
Denis Vlasenkoba1315d2008-09-13 14:59:38 +0000108 }
109 return options;
110}
111
112int 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
Denis Vlasenko3b5c9b82009-03-13 23:43:26 +0000118 if (!options)
119 options = "";
120
Denis Vlasenkoba1315d2008-09-13 14:59:38 +0000121#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 */
Denis Vlasenkofc668922008-11-06 02:32:31 +0000127 image = xmalloc_open_zipped_read_close(filename, &len);
Denis Vlasenkoba1315d2008-09-13 14:59:38 +0000128 if (image) {
Denis Vlasenko3b5c9b82009-03-13 23:43:26 +0000129 rc = 0;
Denis Vlasenkoba1315d2008-09-13 14:59:38 +0000130 if (init_module(image, len, options) != 0)
131 rc = errno;
Denis Vlasenkoba1315d2008-09-13 14:59:38 +0000132 free(image);
133 }
134
135 return rc;
136}
137
138int FAST_FUNC bb_delete_module(const char *module, unsigned int flags)
139{
140 return delete_module(module, flags);
141}