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