xref: /netbsd-src/external/bsd/iscsi/dist/src/initiator/libkmod.c (revision 5e01dafb5c1f3a68ee2f80136c3b6043ad89a0f3)
1 /*	$NetBSD: libkmod.c,v 1.2 2009/06/30 02:44:52 agc Exp $	*/
2 
3 /*-
4  * Copyright (c) 2008 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
17  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26  * POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 #include <sys/cdefs.h>
30 #ifndef lint
31 __RCSID("$NetBSD: libkmod.c,v 1.2 2009/06/30 02:44:52 agc Exp $");
32 #endif /* !lint */
33 
34 #include <sys/module.h>
35 
36 #include <prop/proplib.h>
37 
38 #include <assert.h>
39 #include <err.h>
40 #include <stdbool.h>
41 #include <stdio.h>
42 #include <stdlib.h>
43 #include <string.h>
44 #include <unistd.h>
45 
46 #include "libkmod.h"
47 
48 #ifdef USE_LIBKMOD
49 
50 static const char *classes[] = {
51 	"any",
52 	"misc",
53 	"vfs",
54 	"driver",
55 	"exec",
56 };
57 
58 static const char *sources[] = {
59 	"builtin",
60 	"boot",
61 	"filesys",
62 };
63 
64 /* comparison routine for qsort */
65 static int
modcmp(const void * a,const void * b)66 modcmp(const void *a, const void *b)
67 {
68 	const modstat_t *msa, *msb;
69 
70 	msa = a;
71 	msb = b;
72 	return strcmp(msa->ms_name, msb->ms_name);
73 }
74 
75 /* function which "opens" a module */
76 int
openkmod(kernel_t * kernel)77 openkmod(kernel_t *kernel)
78 {
79 	kernel->size = 4096;
80 	for (;;) {
81 		kernel->iov.iov_base = malloc(kernel->size);
82 		kernel->iov.iov_len = kernel->size;
83 		if (modctl(MODCTL_STAT, &kernel->iov)) {
84 			warn("modctl(MODCTL_STAT)");
85 			return 0;
86 		}
87 		if (kernel->size >= kernel->iov.iov_len) {
88 			break;
89 		}
90 		free(kernel->iov.iov_base);
91 		kernel->size = kernel->iov.iov_len;
92 	}
93 	kernel->size = kernel->iov.iov_len / sizeof(modstat_t);
94 	qsort(kernel->iov.iov_base, kernel->size, sizeof(modstat_t), modcmp);
95 	return 1;
96 }
97 
98 /* return details on the module */
99 int
readkmod(kernel_t * kernel,kmod_t * module)100 readkmod(kernel_t *kernel, kmod_t *module)
101 {
102 	modstat_t *ms;
103 
104 	if (kernel->c * sizeof(*ms) >= kernel->iov.iov_len) {
105 		return 0;
106 	}
107 	ms = kernel->iov.iov_base;
108 	ms += kernel->c++;
109 	(void) memset(module, 0x0, sizeof(*module));
110 	module->name = strdup(ms->ms_name);
111 	module->class = strdup(classes[ms->ms_class]);
112 	module->source = strdup(sources[ms->ms_source]);
113 	module->refcnt = ms->ms_refcnt;
114 	module->size = ms->ms_size;
115 	if (ms->ms_required[0]) {
116 		module->required = strdup(ms->ms_required);
117 	}
118 	return 1;
119 }
120 
121 /* free up all resources allocated in a module read */
122 void
freekmod(kmod_t * module)123 freekmod(kmod_t *module)
124 {
125 	(void) free(module->name);
126 	(void) free(module->class);
127 	(void) free(module->source);
128 	if (module->required) {
129 		(void) free(module->required);
130 	}
131 }
132 
133 /* "close" the module */
134 int
closekmod(kernel_t * kernel)135 closekmod(kernel_t *kernel)
136 {
137 	(void) free(kernel->iov.iov_base);
138 	return 1;
139 }
140 
141 /* do the modstat operation */
142 int
kmodstat(const char * modname,FILE * fp)143 kmodstat(const char *modname, FILE *fp)
144 {
145 	kernel_t	kernel;
146 	kmod_t		module;
147 	int		modc;
148 
149 	(void) memset(&kernel, 0x0, sizeof(kernel));
150 	(void) memset(&module, 0x0, sizeof(module));
151 	if (!openkmod(&kernel)) {
152 		(void) fprintf(stderr, "can't read kernel modules\n");
153 		return 0;
154 	}
155 	for (modc = 0 ; readkmod(&kernel, &module) ; ) {
156 		if (modname == NULL || strcmp(modname, module.name) == 0) {
157 			if (modc++ == 0) {
158 				if (fp) {
159 					(void) fprintf(fp,
160 						"NAME\t\tCLASS\tSOURCE\tREFS"
161 						"\tSIZE\tREQUIRES\n");
162 				}
163 			}
164 			if (fp) {
165 				(void) fprintf(fp, "%-16s%s\t%s\t%d\t%u\t%s\n",
166 				module.name,
167 				module.class,
168 				module.source,
169 				module.refcnt,
170 				module.size,
171 				(module.required) ? module.required : "-");
172 			}
173 			freekmod(&module);
174 		}
175 	}
176 	(void) closekmod(&kernel);
177 	return modc;
178 }
179 
180 /* load the named module into the kernel */
181 int
kmodload(const char * module)182 kmodload(const char *module)
183 {
184 	prop_dictionary_t	 props;
185 	modctl_load_t		 cmdargs;
186 	char			*propsstr;
187 
188 	props = prop_dictionary_create();
189 
190 	propsstr = prop_dictionary_externalize(props);
191 	if (propsstr == NULL) {
192 		(void) fprintf(stderr, "Failed to process properties");
193 		return 0;
194 	}
195 
196 	cmdargs.ml_filename = module;
197 	cmdargs.ml_flags = 0;
198 	cmdargs.ml_props = propsstr;
199 	cmdargs.ml_propslen = strlen(propsstr);
200 
201 	if (modctl(MODCTL_LOAD, &cmdargs)) {
202 		(void) fprintf(stderr, "modctl failure\n");
203 		return 0;
204 	}
205 
206 	(void) free(propsstr);
207 	prop_object_release(props);
208 
209 	return 1;
210 }
211 
212 /* and unload the module from the kernel */
213 int
kmodunload(const char * name)214 kmodunload(const char *name)
215 {
216 	return modctl(MODCTL_UNLOAD, __UNCONST(name)) == 0;
217 }
218 
219 #endif /* USE_LIBKMOD */
220