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