Magellan Linux

Annotation of /trunk/mkinitrd-magellan/busybox/modutils/modutils.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 984 - (hide annotations) (download)
Sun May 30 11:32:42 2010 UTC (14 years ago) by niro
File MIME type: text/plain
File size: 4260 byte(s)
-updated to busybox-1.16.1 and enabled blkid/uuid support in default config
1 niro 816 /*
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     #include "modutils.h"
9    
10     #ifdef __UCLIBC__
11     extern int init_module(void *module, unsigned long len, const char *options);
12     extern int delete_module(const char *module, unsigned int flags);
13     #else
14     # include <sys/syscall.h>
15     # define init_module(mod, len, opts) syscall(__NR_init_module, mod, len, opts)
16     # define delete_module(mod, flags) syscall(__NR_delete_module, mod, flags)
17     #endif
18    
19     void FAST_FUNC replace(char *s, char what, char with)
20     {
21     while (*s) {
22     if (what == *s)
23     *s = with;
24     ++s;
25     }
26     }
27    
28 niro 984 char* FAST_FUNC replace_underscores(char *s)
29 niro 816 {
30     replace(s, '-', '_');
31     return s;
32     }
33    
34     int FAST_FUNC string_to_llist(char *string, llist_t **llist, const char *delim)
35     {
36     char *tok;
37     int len = 0;
38    
39     while ((tok = strsep(&string, delim)) != NULL) {
40     if (tok[0] == '\0')
41     continue;
42     llist_add_to_end(llist, xstrdup(tok));
43     len += strlen(tok);
44     }
45     return len;
46     }
47    
48 niro 984 char* FAST_FUNC filename2modname(const char *filename, char *modname)
49 niro 816 {
50     int i;
51     char *from;
52    
53     if (filename == NULL)
54     return NULL;
55     if (modname == NULL)
56     modname = xmalloc(MODULE_NAME_LEN);
57     from = bb_get_last_path_component_nostrip(filename);
58     for (i = 0; i < (MODULE_NAME_LEN-1) && from[i] != '\0' && from[i] != '.'; i++)
59     modname[i] = (from[i] == '-') ? '_' : from[i];
60 niro 984 modname[i] = '\0';
61 niro 816
62     return modname;
63     }
64    
65 niro 984 char* FAST_FUNC parse_cmdline_module_options(char **argv)
66 niro 816 {
67     char *options;
68     int optlen;
69    
70     options = xzalloc(1);
71     optlen = 0;
72     while (*++argv) {
73     options = xrealloc(options, optlen + 2 + strlen(*argv) + 2);
74     /* Spaces handled by "" pairs, but no way of escaping quotes */
75     optlen += sprintf(options + optlen, (strchr(*argv, ' ') ? "\"%s\" " : "%s "), *argv);
76     }
77     return options;
78     }
79    
80 niro 984 #if ENABLE_FEATURE_INSMOD_TRY_MMAP
81     void* FAST_FUNC try_to_mmap_module(const char *filename, size_t *image_size_p)
82     {
83     /* We have user reports of failure to load 3MB module
84     * on a 16MB RAM machine. Apparently even a transient
85     * memory spike to 6MB during module load
86     * is too big for that system. */
87     void *image;
88     struct stat st;
89     int fd;
90    
91     fd = xopen(filename, O_RDONLY);
92     fstat(fd, &st);
93     image = NULL;
94     /* st.st_size is off_t, we can't just pass it to mmap */
95     if (st.st_size <= *image_size_p) {
96     size_t image_size = st.st_size;
97     image = mmap(NULL, image_size, PROT_READ, MAP_PRIVATE, fd, 0);
98     if (image == MAP_FAILED) {
99     image = NULL;
100     } else if (*(uint32_t*)image != SWAP_BE32(0x7f454C46)) {
101     /* No ELF signature. Compressed module? */
102     munmap(image, image_size);
103     image = NULL;
104     } else {
105     /* Success. Report the size */
106     *image_size_p = image_size;
107     }
108     }
109     close(fd);
110     return image;
111     }
112     #endif
113    
114     /* Return:
115     * 0 on success,
116     * -errno on open/read error,
117     * errno on init_module() error
118     */
119 niro 816 int FAST_FUNC bb_init_module(const char *filename, const char *options)
120     {
121 niro 984 size_t image_size;
122 niro 816 char *image;
123 niro 984 int rc;
124     bool mmaped;
125 niro 816
126 niro 984 if (!options)
127     options = "";
128    
129     //TODO: audit bb_init_module_24 to match error code convention
130 niro 816 #if ENABLE_FEATURE_2_4_MODULES
131     if (get_linux_version_code() < KERNEL_VERSION(2,6,0))
132     return bb_init_module_24(filename, options);
133     #endif
134    
135 niro 984 image_size = INT_MAX - 4095;
136     mmaped = 0;
137     image = try_to_mmap_module(filename, &image_size);
138 niro 816 if (image) {
139 niro 984 mmaped = 1;
140     } else {
141     errno = ENOMEM; /* may be changed by e.g. open errors below */
142     image = xmalloc_open_zipped_read_close(filename, &image_size);
143     if (!image)
144     return -errno;
145 niro 816 }
146    
147 niro 984 errno = 0;
148     init_module(image, image_size, options);
149     rc = errno;
150     if (mmaped)
151     munmap(image, image_size);
152     else
153     free(image);
154 niro 816 return rc;
155     }
156    
157     int FAST_FUNC bb_delete_module(const char *module, unsigned int flags)
158     {
159 niro 984 errno = 0;
160     delete_module(module, flags);
161     return errno;
162 niro 816 }
163 niro 984
164     const char* FAST_FUNC moderror(int err)
165     {
166     switch (err) {
167     case -1: /* btw: it's -EPERM */
168     return "no such module";
169     case ENOEXEC:
170     return "invalid module format";
171     case ENOENT:
172     return "unknown symbol in module, or unknown parameter";
173     case ESRCH:
174     return "module has wrong symbol version";
175     case ENOSYS:
176     return "kernel does not support requested operation";
177     }
178     if (err < 0) /* should always be */
179     err = -err;
180     return strerror(err);
181     }