kldload.c revision 260483
18876Srgrimes/*- 24Srgrimes * Copyright (c) 1997 Doug Rabson 34Srgrimes * All rights reserved. 44Srgrimes * 58876Srgrimes * Redistribution and use in source and binary forms, with or without 64Srgrimes * modification, are permitted provided that the following conditions 74Srgrimes * are met: 84Srgrimes * 1. Redistributions of source code must retain the above copyright 94Srgrimes * notice, this list of conditions and the following disclaimer. 104Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 118876Srgrimes * notice, this list of conditions and the following disclaimer in the 128876Srgrimes * documentation and/or other materials provided with the distribution. 134Srgrimes * 144Srgrimes * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 158876Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 164Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 178876Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 184Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 194Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 204Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 214Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 228876Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 234Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 244Srgrimes * SUCH DAMAGE. 254Srgrimes */ 264Srgrimes 274Srgrimes#include <sys/cdefs.h> 284Srgrimes__FBSDID("$FreeBSD: head/sbin/kldload/kldload.c 260483 2014-01-09 15:34:23Z bapt $"); 294Srgrimes 304Srgrimes#include <sys/types.h> 31116176Sobrien#include <sys/param.h> 32116176Sobrien#include <sys/linker.h> 33116176Sobrien#include <sys/sysctl.h> 342056Swollman#include <sys/stat.h> 3547098Sbde#include <err.h> 3612734Sbde#include <stdio.h> 372056Swollman#include <stdlib.h> 384Srgrimes#include <string.h> 394Srgrimes#include <unistd.h> 404Srgrimes#include <errno.h> 4192756Salfred 424Srgrimes#define PATHCTL "kern.module_path" 4312515Sphk 444Srgrimesstatic int path_check(const char *, int); 4537504Sbdestatic void usage(void); 464Srgrimes 474Srgrimes/* 484Srgrimes * Check to see if the requested module is specified as a filename with no 49131952Smarcel * path. If so and if a file by the same name exists in the module path, 50131952Smarcel * warn the user that the module in the path will be used in preference. 514Srgrimes */ 5212515Sphkstatic int 53131952Smarcelpath_check(const char *kldname, int quiet) 544Srgrimes{ 554Srgrimes int mib[5], found; 56131952Smarcel size_t miblen, pathlen; 574Srgrimes char kldpath[MAXPATHLEN]; 584Srgrimes char *path, *tmppath, *element; 594Srgrimes struct stat sb; 60131952Smarcel dev_t dev; 61131952Smarcel ino_t ino; 62131952Smarcel 63131952Smarcel if (strchr(kldname, '/') != NULL) { 64131952Smarcel return (0); 654Srgrimes } 66131952Smarcel if (strstr(kldname, ".ko") == NULL) { 67131952Smarcel return (0); 68131952Smarcel } 69131952Smarcel if (stat(kldname, &sb) != 0) { 70131952Smarcel return (0); 714Srgrimes } 724Srgrimes 734Srgrimes found = 0; 744Srgrimes dev = sb.st_dev; 754Srgrimes ino = sb.st_ino; 764Srgrimes 774Srgrimes miblen = sizeof(mib) / sizeof(mib[0]); 78131952Smarcel if (sysctlnametomib(PATHCTL, mib, &miblen) != 0) { 794Srgrimes err(1, "sysctlnametomib(%s)", PATHCTL); 804Srgrimes } 814Srgrimes if (sysctl(mib, miblen, NULL, &pathlen, NULL, 0) == -1) { 824Srgrimes err(1, "getting path: sysctl(%s) - size only", PATHCTL); 83131952Smarcel } 844Srgrimes path = malloc(pathlen + 1); 85131952Smarcel if (path == NULL) { 864Srgrimes err(1, "allocating %lu bytes for the path", 874Srgrimes (unsigned long)pathlen + 1); 88131952Smarcel } 89131952Smarcel if (sysctl(mib, miblen, path, &pathlen, NULL, 0) == -1) { 904Srgrimes err(1, "getting path: sysctl(%s)", PATHCTL); 914Srgrimes } 924Srgrimes tmppath = path; 934Srgrimes 94131952Smarcel while ((element = strsep(&tmppath, ";")) != NULL) { 954Srgrimes strlcpy(kldpath, element, MAXPATHLEN); 96131952Smarcel if (kldpath[strlen(kldpath) - 1] != '/') { 974Srgrimes strlcat(kldpath, "/", MAXPATHLEN); 984Srgrimes } 99131952Smarcel strlcat(kldpath, kldname, MAXPATHLEN); 100131952Smarcel 1014Srgrimes if (stat(kldpath, &sb) == -1) { 102131952Smarcel continue; 1034Srgrimes } 104131952Smarcel 105131952Smarcel found = 1; 106131952Smarcel 107131952Smarcel if (sb.st_dev != dev || sb.st_ino != ino) { 108131952Smarcel if (!quiet) { 1094Srgrimes warnx("%s will be loaded from %s, not the " 1104Srgrimes "current directory", kldname, element); 111131952Smarcel } 112131952Smarcel break; 1134Srgrimes } else if (sb.st_dev == dev && sb.st_ino == ino) { 114131952Smarcel break; 1154Srgrimes } 116131952Smarcel } 117131952Smarcel 118131952Smarcel free(path); 119131952Smarcel 120131952Smarcel if (!found) { 1214Srgrimes if (!quiet) { 1224Srgrimes warnx("%s is not in the module path", kldname); 1234Srgrimes } 124131952Smarcel return (-1); 1254Srgrimes } 1264Srgrimes 127131952Smarcel return (0); 128131952Smarcel} 1294Srgrimes 1304Srgrimesstatic void 1314Srgrimesusage(void) 132131952Smarcel{ 133131952Smarcel fprintf(stderr, "usage: kldload [-nqv] file ...\n"); 1344Srgrimes exit(1); 1354Srgrimes} 136131952Smarcel 137131952Smarcelint 1384Srgrimesmain(int argc, char** argv) 1394Srgrimes{ 1404Srgrimes int c; 1414Srgrimes int errors; 142131952Smarcel int fileid; 1434Srgrimes int verbose; 1444Srgrimes int quiet; 145131952Smarcel int check_loaded; 146131952Smarcel 1474Srgrimes errors = 0; 148131952Smarcel verbose = 0; 149131952Smarcel quiet = 0; 1504Srgrimes check_loaded = 0; 151131952Smarcel 1524Srgrimes 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 if (errno == EEXIST) { 185 warnx("can't load %s: module " 186 "already loaded or " 187 "in kernel", argv[0]); 188 } else { 189 warn("can't load %s", argv[0]); 190 errors++; 191 } 192 } 193 } else { 194 if (verbose) 195 printf("Loaded %s, id=%d\n", argv[0], 196 fileid); 197 } 198 } else { 199 errors++; 200 } 201 argv++; 202 } 203 204 return (errors ? 1 : 0); 205} 206