More little stuff.
[oweals/busybox.git] / insmod.c
1 /* vi: set sw=4 ts=4: */
2 /*
3  * Mini insmod implementation for busybox
4  *
5  * Copyright (C) 1999,2000 by Lineo, inc.
6  * Written by Erik Andersen <andersen@lineo.com>, <andersee@debian.org>
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  * General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21  *
22  */
23
24 #include "internal.h"
25 #include <stdlib.h>
26 #include <stdio.h>
27 #include <errno.h>
28 #include <unistd.h>
29 #include <dirent.h>
30 #include <sys/syscall.h>
31 #include <linux/module.h>
32
33 #define _PATH_MODULES   "/lib/modules"
34
35 #warning "Danger Will Robinson, Danger!!!"
36 #warning " "
37 #warning "insmod is still under construction.  Don't use it."
38 #warning " "
39 #warning "      You have been warned!"
40 #warning " "
41
42
43 /* Some firendly syscalls to cheer everyone's day...  */
44 _syscall2(int, init_module, const char *, name,
45                   const struct module *, info)
46 #ifndef BB_RMMOD
47 _syscall1(int, delete_module, const char *, name)
48 #else
49 extern int delete_module(const char *);
50 #endif
51
52 #if defined(__i386__) || defined(__m68k__) || defined(__arm__)
53 /* Jump through hoops to fixup error return codes */
54 #define __NR__create_module  __NR_create_module
55 static inline _syscall2(long, _create_module, const char *, name, size_t,
56                                                 size)
57 unsigned long create_module(const char *name, size_t size)
58 {
59         long ret = _create_module(name, size);
60
61         if (ret == -1 && errno > 125) {
62                 ret = -errno;
63                 errno = 0;
64         }
65         return ret;
66 }
67 #else
68 _syscall2(unsigned long, create_module, const char *, name, size_t, size)
69 #endif
70 static char m_filename[PATH_MAX + 1] = "\0";
71 static char m_fullName[PATH_MAX + 1] = "\0";
72 static const char insmod_usage[] =
73         "insmod [OPTION]... MODULE [symbol=value]...\n\n"
74         "Loads the specified kernel modules into the kernel.\n\n"
75         "Options:\n"
76
77         "\t-f\tForce module to load into the wrong kernel version.\n"
78         "\t-k\tMake module autoclean-able.\n";
79
80
81 static int findNamedModule(const char *fileName, struct stat *statbuf)
82 {
83         if (m_fullName[0] == '\0')
84                 return (FALSE);
85         else {
86                 char *tmp = strrchr(fileName, '/');
87
88                 if (tmp == NULL)
89                         tmp = (char *) fileName;
90                 else
91                         tmp++;
92                 if (check_wildcard_match(tmp, m_fullName) == TRUE) {
93                         /* Stop searching if we find a match */
94                         memcpy(m_filename, fileName, strlen(fileName));
95                         return (FALSE);
96                 }
97         }
98         return (TRUE);
99 }
100
101
102 extern int insmod_main(int argc, char **argv)
103 {
104         int len;
105         char *tmp;
106         char m_name[PATH_MAX + 1] = "\0";
107         FILE *fp;
108
109         if (argc <= 1) {
110                 usage(insmod_usage);
111         }
112
113         /* Parse any options */
114         while (--argc > 0 && **(++argv) == '-') {
115                 while (*(++(*argv))) {
116                         switch (**argv) {
117                         case 'f':
118                                 break;
119                         case 'k':
120                                 break;
121                         default:
122                                 usage(insmod_usage);
123                         }
124                 }
125         }
126
127         if (argc <= 0)
128                 usage(insmod_usage);
129
130         /* Grab the module name */
131         if ((tmp = strrchr(*argv, '/')) != NULL)
132                 tmp++;
133         else
134                 tmp = *argv;
135         len = strlen(tmp);
136
137         if (len > 2 && tmp[len - 2] == '.' && tmp[len - 1] == 'o')
138                 len -= 2;
139         memcpy(m_name, tmp, len);
140         strcpy(m_fullName, m_name);
141         strcat(m_fullName, ".o");
142
143         /* Get a filedesc for the module */
144         if ((fp = fopen(*argv, "r")) == NULL) {
145                 /* Hmpf.  Could not open it. Search through _PATH_MODULES to find a module named m_name */
146                 if (recursiveAction(_PATH_MODULES, TRUE, FALSE, FALSE,
147                                                         findNamedModule, findNamedModule) == FALSE) {
148                         if (m_filename[0] == '\0'
149                                 || ((fp = fopen(m_filename, "r")) == NULL)) {
150                                 perror("No module by that name found in " _PATH_MODULES
151                                            "\n");
152                                 exit(FALSE);
153                         }
154                 }
155         } else
156                 memcpy(m_filename, *argv, strlen(*argv));
157
158
159         fprintf(stderr, "m_filename='%s'\n", m_filename);
160         fprintf(stderr, "m_name='%s'\n", m_name);
161
162
163         /* TODO: do something roughtly like this... */
164 #if 0
165
166         if ((f = obj_load(fp)) == NULL) {
167                 perror("Could not load the module\n");
168                 exit(FALSE);
169         }
170
171         /* Let the module know about the kernel symbols.  */
172         add_kernel_symbols(f);
173
174         if (!create_this_module(f, m_name)) {
175                 perror("Could not create the module\n");
176                 exit(FALSE);
177         }
178
179         if (!obj_check_undefineds(f, quiet)) {
180                 perror("Undefined symbols in the module\n");
181                 exit(FALSE);
182         }
183         obj_allocate_commons(f);
184
185         /* Perse the module's arguments */
186         while (argc-- > 0 && *(argv++) != '\0') {
187                 if (!process_module_arguments(f, argc - optind, argv + optind)) {
188                         perror("Undefined symbols in the module\n");
189                         exit(FALSE);
190                 }
191         }
192
193         /* Find current size of the module */
194         m_size = obj_load_size(f);
195
196
197         errno = 0;
198         m_addr = create_module(m_name, m_size);
199         switch (errno) {
200                 /* yada yada */
201         default:
202                 perror("create_module: %m");
203
204         }
205
206 #endif
207
208         fclose(fp);
209         exit(TRUE);
210 }