kldload.c revision 209971
11590Srgrimes/*- 21590Srgrimes * Copyright (c) 1997 Doug Rabson 31590Srgrimes * All rights reserved. 41590Srgrimes * 51590Srgrimes * Redistribution and use in source and binary forms, with or without 61590Srgrimes * modification, are permitted provided that the following conditions 71590Srgrimes * are met: 81590Srgrimes * 1. Redistributions of source code must retain the above copyright 91590Srgrimes * notice, this list of conditions and the following disclaimer. 101590Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 111590Srgrimes * notice, this list of conditions and the following disclaimer in the 121590Srgrimes * documentation and/or other materials provided with the distribution. 131590Srgrimes * 141590Srgrimes * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 151590Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 161590Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 171590Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 181590Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 191590Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 201590Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 211590Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 221590Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 231590Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 241590Srgrimes * SUCH DAMAGE. 251590Srgrimes */ 261590Srgrimes 271590Srgrimes#include <sys/cdefs.h> 281590Srgrimes__FBSDID("$FreeBSD: head/sbin/kldload/kldload.c 209971 2010-07-13 04:13:31Z maxim $"); 291590Srgrimes 301590Srgrimes#include <sys/types.h> 311590Srgrimes#include <sys/param.h> 321590Srgrimes#include <sys/linker.h> 331590Srgrimes#include <sys/sysctl.h> 341590Srgrimes#include <sys/stat.h> 3519234Swollman#include <err.h> 361590Srgrimes#include <stdio.h> 3719234Swollman#include <stdlib.h> 3819234Swollman#include <string.h> 3950477Speter#include <unistd.h> 401590Srgrimes 411590Srgrimes#define PATHCTL "kern.module_path" 421590Srgrimes 431590Srgrimesstatic int path_check(const char *, int); 441590Srgrimesstatic void usage(void); 451590Srgrimes 4614543Sdg/* 471590Srgrimes * Check to see if the requested module is specified as a filename with no 481590Srgrimes * path. If so and if a file by the same name exists in the module path, 491590Srgrimes * warn the user that the module in the path will be used in preference. 501590Srgrimes */ 511590Srgrimesstatic int 521590Srgrimespath_check(const char *kldname, int quiet) 531590Srgrimes{ 541590Srgrimes int mib[5], found; 551590Srgrimes size_t miblen, pathlen; 5636916Speter char kldpath[MAXPATHLEN]; 571590Srgrimes char *path, *tmppath, *element; 581590Srgrimes struct stat sb; 591590Srgrimes dev_t dev; 601590Srgrimes ino_t ino; 611590Srgrimes 621590Srgrimes if (strchr(kldname, '/') != NULL) { 631590Srgrimes return (0); 641590Srgrimes } 651590Srgrimes if (strstr(kldname, ".ko") == NULL) { 661590Srgrimes return (0); 671590Srgrimes } 681590Srgrimes if (stat(kldname, &sb) != 0) { 691590Srgrimes return (0); 701590Srgrimes } 711590Srgrimes 721590Srgrimes found = 0; 731590Srgrimes dev = sb.st_dev; 741590Srgrimes ino = sb.st_ino; 751590Srgrimes 761590Srgrimes miblen = sizeof(mib) / sizeof(mib[0]); 771590Srgrimes if (sysctlnametomib(PATHCTL, mib, &miblen) != 0) { 781590Srgrimes err(1, "sysctlnametomib(%s)", PATHCTL); 791590Srgrimes } 801590Srgrimes if (sysctl(mib, miblen, NULL, &pathlen, NULL, 0) == -1) { 811590Srgrimes err(1, "getting path: sysctl(%s) - size only", PATHCTL); 821590Srgrimes } 831590Srgrimes path = malloc(pathlen + 1); 841590Srgrimes if (path == NULL) { 851590Srgrimes err(1, "allocating %lu bytes for the path", 861590Srgrimes (unsigned long)pathlen + 1); 8731522Ssteve } 8831522Ssteve if (sysctl(mib, miblen, path, &pathlen, NULL, 0) == -1) { 8931522Ssteve err(1, "getting path: sysctl(%s)", PATHCTL); 9031522Ssteve } 9131522Ssteve tmppath = path; 9231522Ssteve 9331522Ssteve while ((element = strsep(&tmppath, ";")) != NULL) { 9431522Ssteve strlcpy(kldpath, element, MAXPATHLEN); 951590Srgrimes if (kldpath[strlen(kldpath) - 1] != '/') { 961590Srgrimes strlcat(kldpath, "/", MAXPATHLEN); 971590Srgrimes } 981590Srgrimes strlcat(kldpath, kldname, MAXPATHLEN); 991590Srgrimes 1001590Srgrimes if (stat(kldpath, &sb) == -1) { 1011590Srgrimes continue; 1021590Srgrimes } 1031590Srgrimes 1041590Srgrimes found = 1; 1051590Srgrimes 1061590Srgrimes if (sb.st_dev != dev || sb.st_ino != ino) { 1071590Srgrimes if (!quiet) { 1081590Srgrimes warnx("%s will be loaded from %s, not the " 1091590Srgrimes "current directory", kldname, element); 1101590Srgrimes } 1111590Srgrimes break; 1121590Srgrimes } else if (sb.st_dev == dev && sb.st_ino == ino) { 1131590Srgrimes break; 1141590Srgrimes } 1151590Srgrimes } 1161590Srgrimes 1171590Srgrimes free(path); 1181590Srgrimes 1191590Srgrimes if (!found) { 1201590Srgrimes if (!quiet) { 1211590Srgrimes warnx("%s is not in the module path", kldname); 1221590Srgrimes } 1231590Srgrimes return (-1); 1241590Srgrimes } 1251590Srgrimes 1261590Srgrimes return (0); 1271590Srgrimes} 1281590Srgrimes 1291590Srgrimesstatic void 1301590Srgrimesusage(void) 1311590Srgrimes{ 1321590Srgrimes fprintf(stderr, "usage: kldload [-v] [-q] file ...\n"); 1331590Srgrimes exit(1); 1341590Srgrimes} 1351590Srgrimes 1361590Srgrimesint 1371590Srgrimesmain(int argc, char** argv) 1381590Srgrimes{ 1391590Srgrimes int c; 1401590Srgrimes int errors; 1411590Srgrimes int fileid; 1421590Srgrimes int verbose; 1431590Srgrimes int quiet; 1441590Srgrimes 1451590Srgrimes errors = 0; 1461590Srgrimes verbose = 0; 1471590Srgrimes quiet = 0; 1481590Srgrimes 1491590Srgrimes while ((c = getopt(argc, argv, "qv")) != -1) { 1501590Srgrimes switch (c) { 1511590Srgrimes case 'q': 1521590Srgrimes quiet = 1; 1531590Srgrimes verbose = 0; 1541590Srgrimes break; 1551590Srgrimes case 'v': 1561590Srgrimes verbose = 1; 1571590Srgrimes quiet = 0; 1581590Srgrimes break; 1591590Srgrimes default: 1601590Srgrimes usage(); 1611590Srgrimes } 1621590Srgrimes } 1631590Srgrimes argc -= optind; 1641590Srgrimes argv += optind; 1651590Srgrimes 1661590Srgrimes if (argc == 0) 1671590Srgrimes usage(); 1681590Srgrimes 1691590Srgrimes while (argc-- != 0) { 1701590Srgrimes if (path_check(argv[0], quiet) == 0) { 1711590Srgrimes fileid = kldload(argv[0]); 1721590Srgrimes if (fileid < 0) { 1731590Srgrimes warn("can't load %s", argv[0]); 1741590Srgrimes errors++; 1751590Srgrimes } else { 1761590Srgrimes if (verbose) 1771590Srgrimes printf("Loaded %s, id=%d\n", argv[0], 17831522Ssteve fileid); 1791590Srgrimes } 18031522Ssteve } else { 1811590Srgrimes errors++; 18231522Ssteve } 18331522Ssteve argv++; 18431522Ssteve } 18531522Ssteve 18631522Ssteve return (errors ? 1 : 0); 1871590Srgrimes} 1881590Srgrimes