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 [-qv] 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 } 188