/*- * Copyright (c) 1997 Doug Rabson * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #define PATHCTL "kern.module_path" static int path_check(const char *, int); static void usage(void); /* * Check to see if the requested module is specified as a filename with no * path. If so and if a file by the same name exists in the module path, * warn the user that the module in the path will be used in preference. */ static int path_check(const char *kldname, int quiet) { int mib[5], found; size_t miblen, pathlen; char kldpath[MAXPATHLEN]; char *path, *tmppath, *element; struct stat sb; dev_t dev; ino_t ino; if (strchr(kldname, '/') != NULL) { return (0); } if (strstr(kldname, ".ko") == NULL) { return (0); } if (stat(kldname, &sb) != 0) { return (0); } found = 0; dev = sb.st_dev; ino = sb.st_ino; miblen = sizeof(mib) / sizeof(mib[0]); if (sysctlnametomib(PATHCTL, mib, &miblen) != 0) { err(1, "sysctlnametomib(%s)", PATHCTL); } if (sysctl(mib, miblen, NULL, &pathlen, NULL, 0) == -1) { err(1, "getting path: sysctl(%s) - size only", PATHCTL); } path = malloc(pathlen + 1); if (path == NULL) { err(1, "allocating %lu bytes for the path", (unsigned long)pathlen + 1); } if (sysctl(mib, miblen, path, &pathlen, NULL, 0) == -1) { err(1, "getting path: sysctl(%s)", PATHCTL); } tmppath = path; while ((element = strsep(&tmppath, ";")) != NULL) { strlcpy(kldpath, element, MAXPATHLEN); if (kldpath[strlen(kldpath) - 1] != '/') { strlcat(kldpath, "/", MAXPATHLEN); } strlcat(kldpath, kldname, MAXPATHLEN); if (stat(kldpath, &sb) == -1) { continue; } found = 1; if (sb.st_dev != dev || sb.st_ino != ino) { if (!quiet) { warnx("%s will be loaded from %s, not the " "current directory", kldname, element); } break; } else if (sb.st_dev == dev && sb.st_ino == ino) { break; } } free(path); if (!found) { if (!quiet) { warnx("%s is not in the module path", kldname); } return (-1); } return (0); } static void usage(void) { fprintf(stderr, "usage: kldload [-nqv] file ...\n"); exit(1); } int main(int argc, char** argv) { int c; int errors; int fileid; int verbose; int quiet; int check_loaded; errors = 0; verbose = 0; quiet = 0; check_loaded = 0; while ((c = getopt(argc, argv, "nqv")) != -1) { switch (c) { case 'q': quiet = 1; verbose = 0; break; case 'v': verbose = 1; quiet = 0; break; case 'n': check_loaded = 1; break; default: usage(); } } argc -= optind; argv += optind; if (argc == 0) usage(); while (argc-- != 0) { if (path_check(argv[0], quiet) == 0) { fileid = kldload(argv[0]); if (fileid < 0) { if (check_loaded != 0 && errno == EEXIST) { if (verbose) printf("%s is already " "loaded\n", argv[0]); } else { switch (errno) { case EEXIST: warnx("can't load %s: module " "already loaded or " "in kernel", argv[0]); break; case ENOEXEC: warnx("an error occurred while " "loading the module. " "Please check dmesg(8) for " "more details."); break; default: warn("can't load %s", argv[0]); break; } errors++; } } else { if (verbose) printf("Loaded %s, id=%d\n", argv[0], fileid); } } else { errors++; } argv++; } return (errors ? 1 : 0); }