]> CyberLeo.Net >> Repos - FreeBSD/releng/8.1.git/blob - sbin/kldload/kldload.c
Copy stable/8 to releng/8.1 in preparation for 8.1-RC1.
[FreeBSD/releng/8.1.git] / sbin / kldload / kldload.c
1 /*-
2  * Copyright (c) 1997 Doug Rabson
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  */
26
27 #include <sys/cdefs.h>
28 __FBSDID("$FreeBSD$");
29
30 #include <sys/types.h>
31 #include <sys/param.h>
32 #include <sys/linker.h>
33 #include <sys/sysctl.h>
34 #include <sys/stat.h>
35 #include <err.h>
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <string.h>
39 #include <unistd.h>
40
41 #define PATHCTL "kern.module_path"
42
43 static int      path_check(const char *, int);
44 static void     usage(void);
45
46 /*
47  * Check to see if the requested module is specified as a filename with no
48  * path.  If so and if a file by the same name exists in the module path,
49  * warn the user that the module in the path will be used in preference.
50  */
51 static int
52 path_check(const char *kldname, int quiet)
53 {
54         int     mib[5], found;
55         size_t  miblen, pathlen;
56         char    kldpath[MAXPATHLEN];
57         char    *path, *tmppath, *element;
58         struct  stat sb;
59         dev_t   dev;
60         ino_t   ino;
61
62         if (strchr(kldname, '/') != NULL) {
63                 return (0);
64         }
65         if (strstr(kldname, ".ko") == NULL) {
66                 return (0);
67         }
68         if (stat(kldname, &sb) != 0) {
69                 return (0);
70         }
71
72         found = 0;
73         dev = sb.st_dev;
74         ino = sb.st_ino;
75
76         miblen = sizeof(mib) / sizeof(mib[0]);
77         if (sysctlnametomib(PATHCTL, mib, &miblen) != 0) {
78                 err(1, "sysctlnametomib(%s)", PATHCTL);
79         }
80         if (sysctl(mib, miblen, NULL, &pathlen, NULL, 0) == -1) {
81                 err(1, "getting path: sysctl(%s) - size only", PATHCTL);
82         }
83         path = malloc(pathlen + 1);
84         if (path == NULL) {
85                 err(1, "allocating %lu bytes for the path",
86                     (unsigned long)pathlen + 1);
87         }
88         if (sysctl(mib, miblen, path, &pathlen, NULL, 0) == -1) {
89                 err(1, "getting path: sysctl(%s)", PATHCTL);
90         }
91         tmppath = path;
92
93         while ((element = strsep(&tmppath, ";")) != NULL) {
94                 strlcpy(kldpath, element, MAXPATHLEN);
95                 if (kldpath[strlen(kldpath) - 1] != '/') {
96                         strlcat(kldpath, "/", MAXPATHLEN);
97                 }
98                 strlcat(kldpath, kldname, MAXPATHLEN);
99                                 
100                 if (stat(kldpath, &sb) == -1) {
101                         continue;
102                 }       
103
104                 found = 1;
105
106                 if (sb.st_dev != dev || sb.st_ino != ino) {
107                         if (!quiet) {
108                                 warnx("%s will be loaded from %s, not the "
109                                     "current directory", kldname, element);
110                         }
111                         break;
112                 } else if (sb.st_dev == dev && sb.st_ino == ino) {
113                         break;
114                 }
115         }
116
117         free(path);
118         
119         if (!found) {
120                 if (!quiet) {
121                         warnx("%s is not in the module path", kldname);
122                 }
123                 return (-1);
124         }
125         
126         return (0);
127 }
128
129 static void
130 usage(void)
131 {
132         fprintf(stderr, "usage: kldload [-v] file ...\n");
133         exit(1);
134 }
135
136 int
137 main(int argc, char** argv)
138 {
139         int c;
140         int errors;
141         int fileid;
142         int verbose;
143         int quiet;
144
145         errors = 0;
146         verbose = 0;
147         quiet = 0;
148     
149         while ((c = getopt(argc, argv, "qv")) != -1) {
150                 switch (c) {
151                 case 'q':
152                         quiet = 1;
153                         verbose = 0;
154                         break;
155                 case 'v':
156                         verbose = 1;
157                         quiet = 0;
158                         break;
159                 default:
160                         usage();
161                 }
162         }
163         argc -= optind;
164         argv += optind;
165
166         if (argc == 0)
167                 usage();
168
169         while (argc-- != 0) {
170                 if (path_check(argv[0], quiet) == 0) {
171                         fileid = kldload(argv[0]);
172                         if (fileid < 0) {
173                                 warn("can't load %s", argv[0]);
174                                 errors++;
175                         } else {
176                                 if (verbose)
177                                         printf("Loaded %s, id=%d\n", argv[0],
178                                             fileid);
179                         }
180                 } else {
181                         errors++;
182                 }
183                 argv++;
184         }
185
186         return (errors ? 1 : 0);
187 }