]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - sbin/kldload/kldload.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.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 #include <errno.h>
41
42 #define PATHCTL "kern.module_path"
43
44 static int      path_check(const char *, int);
45 static void     usage(void);
46
47 /*
48  * Check to see if the requested module is specified as a filename with no
49  * path.  If so and if a file by the same name exists in the module path,
50  * warn the user that the module in the path will be used in preference.
51  */
52 static int
53 path_check(const char *kldname, int quiet)
54 {
55         int     mib[5], found;
56         size_t  miblen, pathlen;
57         char    kldpath[MAXPATHLEN];
58         char    *path, *tmppath, *element;
59         struct  stat sb;
60         dev_t   dev;
61         ino_t   ino;
62
63         if (strchr(kldname, '/') != NULL) {
64                 return (0);
65         }
66         if (strstr(kldname, ".ko") == NULL) {
67                 return (0);
68         }
69         if (stat(kldname, &sb) != 0) {
70                 return (0);
71         }
72
73         found = 0;
74         dev = sb.st_dev;
75         ino = sb.st_ino;
76
77         miblen = sizeof(mib) / sizeof(mib[0]);
78         if (sysctlnametomib(PATHCTL, mib, &miblen) != 0) {
79                 err(1, "sysctlnametomib(%s)", PATHCTL);
80         }
81         if (sysctl(mib, miblen, NULL, &pathlen, NULL, 0) == -1) {
82                 err(1, "getting path: sysctl(%s) - size only", PATHCTL);
83         }
84         path = malloc(pathlen + 1);
85         if (path == NULL) {
86                 err(1, "allocating %lu bytes for the path",
87                     (unsigned long)pathlen + 1);
88         }
89         if (sysctl(mib, miblen, path, &pathlen, NULL, 0) == -1) {
90                 err(1, "getting path: sysctl(%s)", PATHCTL);
91         }
92         tmppath = path;
93
94         while ((element = strsep(&tmppath, ";")) != NULL) {
95                 strlcpy(kldpath, element, MAXPATHLEN);
96                 if (kldpath[strlen(kldpath) - 1] != '/') {
97                         strlcat(kldpath, "/", MAXPATHLEN);
98                 }
99                 strlcat(kldpath, kldname, MAXPATHLEN);
100                                 
101                 if (stat(kldpath, &sb) == -1) {
102                         continue;
103                 }       
104
105                 found = 1;
106
107                 if (sb.st_dev != dev || sb.st_ino != ino) {
108                         if (!quiet) {
109                                 warnx("%s will be loaded from %s, not the "
110                                     "current directory", kldname, element);
111                         }
112                         break;
113                 } else if (sb.st_dev == dev && sb.st_ino == ino) {
114                         break;
115                 }
116         }
117
118         free(path);
119         
120         if (!found) {
121                 if (!quiet) {
122                         warnx("%s is not in the module path", kldname);
123                 }
124                 return (-1);
125         }
126         
127         return (0);
128 }
129
130 static void
131 usage(void)
132 {
133         fprintf(stderr, "usage: kldload [-nqv] file ...\n");
134         exit(1);
135 }
136
137 int
138 main(int argc, char** argv)
139 {
140         int c;
141         int errors;
142         int fileid;
143         int verbose;
144         int quiet;
145         int check_loaded;
146
147         errors = 0;
148         verbose = 0;
149         quiet = 0;
150         check_loaded = 0;
151     
152         while ((c = getopt(argc, argv, "nqv")) != -1) {
153                 switch (c) {
154                 case 'q':
155                         quiet = 1;
156                         verbose = 0;
157                         break;
158                 case 'v':
159                         verbose = 1;
160                         quiet = 0;
161                         break;
162                 case 'n':
163                         check_loaded = 1;
164                         break;
165                 default:
166                         usage();
167                 }
168         }
169         argc -= optind;
170         argv += optind;
171
172         if (argc == 0)
173                 usage();
174
175         while (argc-- != 0) {
176                 if (path_check(argv[0], quiet) == 0) {
177                         fileid = kldload(argv[0]);
178                         if (fileid < 0) {
179                                 if (check_loaded != 0 && errno == EEXIST) {
180                                         if (verbose)
181                                                 printf("%s is already "
182                                                     "loaded\n", argv[0]);
183                                 } else {
184                                         warn("can't load %s", argv[0]);
185                                         errors++;
186                                 }
187                         } else {
188                                 if (verbose)
189                                         printf("Loaded %s, id=%d\n", argv[0],
190                                             fileid);
191                         }
192                 } else {
193                         errors++;
194                 }
195                 argv++;
196         }
197
198         return (errors ? 1 : 0);
199 }