kldload.c revision 193475
125540Sdfr/*- 225540Sdfr * Copyright (c) 1997 Doug Rabson 325540Sdfr * All rights reserved. 425540Sdfr * 525540Sdfr * Redistribution and use in source and binary forms, with or without 625540Sdfr * modification, are permitted provided that the following conditions 725540Sdfr * are met: 825540Sdfr * 1. Redistributions of source code must retain the above copyright 925540Sdfr * notice, this list of conditions and the following disclaimer. 1025540Sdfr * 2. Redistributions in binary form must reproduce the above copyright 1125540Sdfr * notice, this list of conditions and the following disclaimer in the 1225540Sdfr * documentation and/or other materials provided with the distribution. 1325540Sdfr * 1425540Sdfr * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1525540Sdfr * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1625540Sdfr * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1725540Sdfr * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1825540Sdfr * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1925540Sdfr * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2025540Sdfr * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2125540Sdfr * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2225540Sdfr * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2325540Sdfr * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2425540Sdfr * SUCH DAMAGE. 2525540Sdfr */ 2625540Sdfr 27114589Sobrien#include <sys/cdefs.h> 28114589Sobrien__FBSDID("$FreeBSD: head/sbin/kldload/kldload.c 193475 2009-06-04 23:43:08Z benno $"); 2932269Scharnier 30193475Sbenno#include <sys/types.h> 31193473Sbenno#include <sys/param.h> 32193473Sbenno#include <sys/linker.h> 33193475Sbenno#include <sys/sysctl.h> 34193475Sbenno#include <sys/stat.h> 3530573Sjmg#include <err.h> 3625540Sdfr#include <stdio.h> 3778732Sdd#include <stdlib.h> 38193475Sbenno#include <string.h> 3925540Sdfr#include <unistd.h> 4025540Sdfr 41193475Sbenno#define PATHCTL "kern.module_path" 42193475Sbenno 43193475Sbennostatic int path_check(const char *, int); 44193473Sbennostatic void usage(void); 45193473Sbenno 46193475Sbenno/* 47193475Sbenno * Check to see if the requested module is specified as a filename with no 48193475Sbenno * path. If so and if a file by the same name exists in the module path, 49193475Sbenno * warn the user that the module in the path will be used in preference. 50193475Sbenno */ 51193475Sbennostatic int 52193475Sbennopath_check(const char *kldname, int quiet) 53193475Sbenno{ 54193475Sbenno int mib[5], found; 55193475Sbenno size_t miblen, pathlen; 56193475Sbenno char kldpath[MAXPATHLEN]; 57193475Sbenno char *path, *tmppath, *element; 58193475Sbenno struct stat sb; 59193475Sbenno dev_t dev; 60193475Sbenno ino_t ino; 61193475Sbenno 62193475Sbenno if (strchr(kldname, '/') != NULL) { 63193475Sbenno return (0); 64193475Sbenno } 65193475Sbenno if (strstr(kldname, ".ko") == NULL) { 66193475Sbenno return (0); 67193475Sbenno } 68193475Sbenno if (stat(kldname, &sb) != 0) { 69193475Sbenno return (0); 70193475Sbenno } 71193475Sbenno 72193475Sbenno found = 0; 73193475Sbenno dev = sb.st_dev; 74193475Sbenno ino = sb.st_ino; 75193475Sbenno 76193475Sbenno miblen = sizeof(mib) / sizeof(mib[0]); 77193475Sbenno if (sysctlnametomib(PATHCTL, mib, &miblen) != 0) { 78193475Sbenno err(1, "sysctlnametomib(%s)", PATHCTL); 79193475Sbenno } 80193475Sbenno if (sysctl(mib, miblen, NULL, &pathlen, NULL, 0) == -1) { 81193475Sbenno err(1, "getting path: sysctl(%s) - size only", PATHCTL); 82193475Sbenno } 83193475Sbenno path = malloc(pathlen + 1); 84193475Sbenno if (path == NULL) { 85193475Sbenno err(1, "allocating %lu bytes for the path", 86193475Sbenno (unsigned long)pathlen + 1); 87193475Sbenno } 88193475Sbenno if (sysctl(mib, miblen, path, &pathlen, NULL, 0) == -1) { 89193475Sbenno err(1, "getting path: sysctl(%s)", PATHCTL); 90193475Sbenno } 91193475Sbenno tmppath = path; 92193475Sbenno 93193475Sbenno while ((element = strsep(&tmppath, ";")) != NULL) { 94193475Sbenno strlcpy(kldpath, element, MAXPATHLEN); 95193475Sbenno if (kldpath[strlen(kldpath) - 1] != '/') { 96193475Sbenno strlcat(kldpath, "/", MAXPATHLEN); 97193475Sbenno } 98193475Sbenno strlcat(kldpath, kldname, MAXPATHLEN); 99193475Sbenno 100193475Sbenno if (stat(kldpath, &sb) == -1) { 101193475Sbenno continue; 102193475Sbenno } 103193475Sbenno 104193475Sbenno found = 1; 105193475Sbenno 106193475Sbenno if (sb.st_dev != dev || sb.st_ino != ino) { 107193475Sbenno if (!quiet) { 108193475Sbenno warnx("%s will be loaded from %s, not the " 109193475Sbenno "current directory", kldname, element); 110193475Sbenno } 111193475Sbenno break; 112193475Sbenno } else if (sb.st_dev == dev && sb.st_ino == ino) { 113193475Sbenno break; 114193475Sbenno } 115193475Sbenno } 116193475Sbenno 117193475Sbenno free(path); 118193475Sbenno 119193475Sbenno if (!found) { 120193475Sbenno if (!quiet) { 121193475Sbenno warnx("%s is not in the module path", kldname); 122193475Sbenno } 123193475Sbenno return (-1); 124193475Sbenno } 125193475Sbenno 126193475Sbenno return (0); 127193475Sbenno} 128193475Sbenno 12930627Sjmgstatic void 13030627Sjmgusage(void) 13125540Sdfr{ 132193473Sbenno fprintf(stderr, "usage: kldload [-v] file ...\n"); 133193473Sbenno exit(1); 13425540Sdfr} 13525540Sdfr 13630627Sjmgint 13730627Sjmgmain(int argc, char** argv) 13825540Sdfr{ 139193473Sbenno int c; 140193473Sbenno int errors; 141193473Sbenno int fileid; 142193473Sbenno int verbose; 143193475Sbenno int quiet; 14425540Sdfr 145193473Sbenno errors = 0; 146193473Sbenno verbose = 0; 147193475Sbenno quiet = 0; 148193475Sbenno 149193475Sbenno while ((c = getopt(argc, argv, "qv")) != -1) { 150193473Sbenno switch (c) { 151193475Sbenno case 'q': 152193475Sbenno quiet = 1; 153193475Sbenno verbose = 0; 154193475Sbenno break; 155193473Sbenno case 'v': 156193473Sbenno verbose = 1; 157193475Sbenno quiet = 0; 158193473Sbenno break; 159193473Sbenno default: 160193473Sbenno usage(); 161193473Sbenno } 16225540Sdfr } 163193473Sbenno argc -= optind; 164193473Sbenno argv += optind; 16525540Sdfr 166193473Sbenno if (argc == 0) 167193473Sbenno usage(); 16825540Sdfr 169193473Sbenno while (argc-- != 0) { 170193475Sbenno if (path_check(argv[0], quiet) == 0) { 171193475Sbenno fileid = kldload(argv[0]); 172193475Sbenno if (fileid < 0) { 173193475Sbenno warn("can't load %s", argv[0]); 174193475Sbenno errors++; 175193475Sbenno } else { 176193475Sbenno if (verbose) 177193475Sbenno printf("Loaded %s, id=%d\n", argv[0], 178193475Sbenno fileid); 179193475Sbenno } 180193475Sbenno } else { 181193473Sbenno errors++; 182193473Sbenno } 183193473Sbenno argv++; 184193473Sbenno } 18525540Sdfr 186193473Sbenno return (errors ? 1 : 0); 18725540Sdfr} 188