freebsd-nq/sbin/kldload/kldload.c

204 lines
4.8 KiB
C
Raw Normal View History

1997-05-07 18:19:54 +00:00
/*-
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
1997-05-07 18:19:54 +00:00
* 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 <sys/cdefs.h>
__FBSDID("$FreeBSD$");
1998-01-05 07:07:44 +00:00
#include <sys/types.h>
#include <sys/param.h>
#include <sys/linker.h>
#include <sys/sysctl.h>
#include <sys/stat.h>
#include <err.h>
1997-05-07 18:19:54 +00:00
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
1997-05-07 18:19:54 +00:00
#include <unistd.h>
#include <errno.h>
#define PATHCTL "kern.module_path"
/*
* 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)
{
char *path, *tmppath, *element;
struct stat sb;
int mib[5];
char kldpath[MAXPATHLEN];
size_t miblen, pathlen;
dev_t dev;
ino_t ino;
int found;
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 = nitems(mib);
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)
1997-05-07 18:19:54 +00:00
{
fprintf(stderr, "usage: kldload [-nqv] file ...\n");
exit(1);
1997-05-07 18:19:54 +00:00
}
int
main(int argc, char** argv)
1997-05-07 18:19:54 +00:00
{
int c;
int check_loaded;
int errors;
int fileid;
int quiet;
int verbose;
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();
}
1997-05-07 18:19:54 +00:00
}
argc -= optind;
argv += optind;
1997-05-07 18:19:54 +00:00
if (argc == 0)
usage();
1997-05-07 18:19:54 +00:00
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:
2014-01-13 16:47:25 +00:00
warnx("an error occurred while "
"loading module %s. "
"Please check dmesg(8) for "
"more details.", argv[0]);
break;
default:
warn("can't load %s", argv[0]);
break;
}
2014-01-09 15:35:35 +00:00
errors++;
}
} else {
if (verbose)
printf("Loaded %s, id=%d\n", argv[0],
fileid);
}
} else
errors++;
argv++;
}
1997-05-07 18:19:54 +00:00
return (errors ? 1 : 0);
1997-05-07 18:19:54 +00:00
}