1 /* Extract module info: useful for both the curious and for scripts. */
2 #define _GNU_SOURCE /* asprintf rocks */
13 #include <sys/utsname.h>
17 #include "zlibsupport.h"
21 #define MODULE_DIR "/lib/modules"
27 const char *name
; /* Terminated by a colon */
32 static struct param
*add_param(const char *name
, struct param
**list
)
35 unsigned int namelen
= strcspn(name
, ":") + 1;
37 for (i
= *list
; i
; i
= i
->next
)
38 if (strncmp(i
->name
, name
, namelen
) == 0)
40 i
= malloc(sizeof(*i
) + namelen
+1);
41 strncpy((char *)(i
+ 1), name
, namelen
);
42 ((char *)(i
+ 1))[namelen
] = '\0';
43 i
->name
= (char *)(i
+ 1);
51 static void print_tag(const char *tag
, const char *info
, unsigned long size
,
52 const char *filename
, char sep
)
54 unsigned int taglen
= strlen(tag
);
56 if (streq(tag
, "filename")) {
57 printf("%s%c", filename
, sep
);
61 for (; info
; info
= next_string(info
, &size
))
62 if (strncmp(info
, tag
, taglen
) == 0 && info
[taglen
] == '=')
63 printf("%s%c", info
+ taglen
+ 1, sep
);
66 static void print_all(const char *info
, unsigned long size
,
67 const char *filename
, char sep
)
69 struct param
*i
, *params
= NULL
;
71 printf("%-16s%s%c", "filename:", filename
, sep
);
72 for (; info
; info
= next_string(info
, &size
)) {
75 /* We expect this in parm and parmtype. */
76 colon
= strchr(info
, ':');
78 /* We store these for handling at the end */
79 if (strstarts(info
, "parm=") && colon
) {
80 i
= add_param(info
+ strlen("parm="), ¶ms
);
84 if (strstarts(info
, "parmtype=") && colon
) {
85 i
= add_param(info
+ strlen("parmtype="), ¶ms
);
91 printf("%s%c", info
, sep
);
95 eq
= strchr(info
, '=');
96 /* Warn if no '=' maybe? */
98 char tag
[eq
- info
+ 2];
99 strncpy(tag
, info
, eq
- info
);
101 tag
[eq
-info
+1] = '\0';
102 printf("%-16s%s%c", tag
, eq
+1, sep
);
106 /* Now show parameters. */
107 for (i
= params
; i
; i
= i
->next
) {
109 printf("%-16s%s%s%c", "parm:", i
->name
, i
->type
, sep
);
111 printf("%-16s%s%s (%s)%c",
112 "parm:", i
->name
, i
->param
, i
->type
, sep
);
114 printf("%-16s%s%s%c", "parm:", i
->name
, i
->param
, sep
);
118 static struct option options
[] =
120 {"author", 0, 0, 'a'},
121 {"description", 0, 0, 'd'},
122 {"license", 0, 0, 'l'},
123 {"parameters", 0, 0, 'p'},
124 {"filename", 0, 0, 'n'},
125 {"version", 0, 0, 'V'},
128 {"field", 1, 0, 'F'},
132 /* - and _ are equivalent, and expect suffix. */
133 static int name_matches(const char *line
, const char *end
, const char *modname
)
138 /* Ignore comment lines */
139 if (line
[strspn(line
, "\t ")] == '#')
142 /* Find last / before colon. */
143 p
= memchr(line
, ':', end
- line
);
154 for (i
= 0; modname
[i
]; i
++) {
155 /* Module names can't have colons. */
156 if (modname
[i
] == ':')
158 if (modname
[i
] == p
[i
])
160 if (modname
[i
] == '_' && p
[i
] == '-')
162 if (modname
[i
] == '-' && p
[i
] == '_')
166 /* Must match all the way to the extension */
167 return (p
[i
] == '.');
170 static char *next_line(char *p
, const char *end
)
174 eol
= memchr(p
, '\n', end
- p
);
177 return (char *)end
+ 1;
180 static void *grab_module(const char *name
, unsigned long *size
, char**filename
,
181 const char *kernel
, const char *basedir
)
185 char *depname
, *p
, *moddir
;
187 if (strchr(name
, '.') || strchr(name
, '/')) {
188 data
= grab_file(name
, size
);
190 *filename
= strdup(name
);
193 fprintf(stderr
, "modinfo: could not open %s: %s\n",
194 name
, strerror(errno
));
201 asprintf(&moddir
, "%s/%s/%s",
202 basedir
, MODULE_DIR
, kernel
);
204 asprintf(&moddir
, "%s/%s",
209 asprintf(&moddir
, "%s/%s/%s",
210 basedir
, MODULE_DIR
, buf
.release
);
212 asprintf(&moddir
, "%s/%s",
213 MODULE_DIR
, buf
.release
);
215 asprintf(&depname
, "%s/%s", moddir
, "modules.dep");
217 /* Search for it in modules.dep. */
218 data
= grab_file(depname
, size
);
220 fprintf(stderr
, "modinfo: could not open %s\n", depname
);
226 for (p
= data
; p
< data
+ *size
; p
= next_line(p
, data
+ *size
)) {
227 if (name_matches(p
, data
+ *size
, name
)) {
228 int namelen
= strcspn(p
, ":");
230 if ('/' == p
[0]) { /* old style deps - absolute path */
231 *filename
= malloc(namelen
+ strlen(basedir
)+2);
232 if (strlen(basedir
)) {
233 sprintf(*filename
, "%s/", basedir
);
234 memcpy(*filename
+strlen(basedir
)+1,p
,
237 +strlen(basedir
)+1] = '\0';
239 memcpy(*filename
,p
,namelen
);
240 (*filename
)[namelen
] = '\0';
243 *filename
= malloc(namelen
+ strlen(moddir
)+2);
244 sprintf(*filename
, "%s/", moddir
);
245 memcpy(*filename
+strlen(moddir
)+1, p
,namelen
);
246 (*filename
)[namelen
+strlen(moddir
)+1] ='\0';
248 release_file(data
, *size
);
249 data
= grab_file(*filename
, size
);
252 "modinfo: could not open %s: %s\n",
253 *filename
, strerror(errno
));
257 release_file(data
, *size
);
258 fprintf(stderr
, "modinfo: could not find module %s\n", name
);
262 static void usage(const char *name
)
264 fprintf(stderr
, "Usage: %s [-0][-F field][-k kernelversion][-b basedir] module...\n"
265 " Prints out the information about one or more module(s).\n"
266 " If a fieldname is given, just print out that field (or nothing if not found).\n"
267 " Otherwise, print all information out in a readable form\n"
268 " If -0 is given, separate with nul, not newline.\n"
269 " If -b is given, use an image of the module tree.\n",
273 int main(int argc
, char *argv
[])
275 const char *field
= NULL
;
276 const char *kernel
= NULL
;
278 unsigned long infosize
= 0;
282 if (native_endianness() == 0)
285 while ((opt
= getopt_long(argc
,argv
,"adlpVhn0F:k:b:",options
,NULL
)) >= 0){
287 case 'a': field
= "author"; break;
288 case 'd': field
= "description"; break;
289 case 'l': field
= "license"; break;
290 case 'p': field
= "parm"; break;
291 case 'n': field
= "filename"; break;
292 case 'V': printf(PACKAGE
" version " VERSION
"\n"); exit(0);
293 case 'F': field
= optarg
; break;
294 case '0': sep
= '\0'; break;
295 case 'k': kernel
= optarg
; break;
296 case 'b': basedir
= optarg
; break;
297 case 'h': usage(argv
[0]); exit(0); break;
299 usage(argv
[0]); exit(1);
302 if (argc
< optind
+ 1) {
307 for (opt
= optind
; opt
< argc
; opt
++) {
309 unsigned long modulesize
;
312 mod
= grab_module(argv
[opt
], &modulesize
, &filename
,
319 info
= get_section(mod
, modulesize
, ".modinfo", &infosize
);
321 release_file(mod
, modulesize
);
326 print_tag(field
, info
, infosize
, filename
, sep
);
328 print_all(info
, infosize
, filename
, sep
);
329 release_file(mod
, modulesize
);