1 /* Extract module info: useful for both the curious and for scripts. */
2 #define _GNU_SOURCE /* asprintf rocks */
13 #include <sys/utsname.h>
19 #include "zlibsupport.h"
23 #define MODULE_DIR "/lib/modules"
29 const char *name
; /* Terminated by a colon */
34 static struct param
*add_param(const char *name
, struct param
**list
)
37 unsigned int namelen
= strcspn(name
, ":") + 1;
39 for (i
= *list
; i
; i
= i
->next
)
40 if (strncmp(i
->name
, name
, namelen
) == 0)
42 i
= NOFAIL(malloc(sizeof(*i
) + namelen
+1));
43 strncpy((char *)(i
+ 1), name
, namelen
);
44 ((char *)(i
+ 1))[namelen
] = '\0';
45 i
->name
= (char *)(i
+ 1);
53 static void print_tag(const char *tag
, struct string_table
*tags
,
54 const char *filename
, char sep
)
57 unsigned int taglen
= strlen(tag
);
59 if (streq(tag
, "filename")) {
60 printf("%s%c", filename
, sep
);
64 for (j
= 0; j
< tags
->cnt
; j
++) {
65 const char *info
= tags
->str
[j
];
66 if (strncmp(info
, tag
, taglen
) == 0 && info
[taglen
] == '=')
67 printf("%s%c", info
+ taglen
+ 1, sep
);
71 static void print_all(struct string_table
*tags
,
72 const char *filename
, char sep
)
75 struct param
*i
, *params
= NULL
;
77 printf("%-16s%s%c", "filename:", filename
, sep
);
78 for (j
= 0; j
< tags
->cnt
; j
++) {
79 const char *info
= tags
->str
[j
];
82 /* We expect this in parm and parmtype. */
83 colon
= strchr(info
, ':');
85 /* We store these for handling at the end */
86 if (strstarts(info
, "parm=") && colon
) {
87 i
= add_param(info
+ strlen("parm="), ¶ms
);
91 if (strstarts(info
, "parmtype=") && colon
) {
92 i
= add_param(info
+ strlen("parmtype="), ¶ms
);
98 printf("%s%c", info
, sep
);
102 eq
= strchr(info
, '=');
103 /* Warn if no '=' maybe? */
105 char tag
[eq
- info
+ 2];
106 strncpy(tag
, info
, eq
- info
);
108 tag
[eq
-info
+1] = '\0';
109 printf("%-16s%s%c", tag
, eq
+1, sep
);
113 /* Now show parameters. */
114 for (i
= params
; i
; i
= i
->next
) {
116 printf("%-16s%s%s%c", "parm:", i
->name
, i
->type
, sep
);
118 printf("%-16s%s%s (%s)%c",
119 "parm:", i
->name
, i
->param
, i
->type
, sep
);
121 printf("%-16s%s%s%c", "parm:", i
->name
, i
->param
, sep
);
125 static struct option options
[] =
127 {"author", 0, 0, 'a'},
128 {"description", 0, 0, 'd'},
129 {"license", 0, 0, 'l'},
130 {"parameters", 0, 0, 'p'},
131 {"filename", 0, 0, 'n'},
132 {"version", 0, 0, 'V'},
135 {"field", 1, 0, 'F'},
139 /* - and _ are equivalent, and expect suffix. */
140 static int name_matches(const char *line
, const char *end
, const char *modname
)
145 /* Ignore comment lines */
146 if (line
[strspn(line
, "\t ")] == '#')
149 /* Find last / before colon. */
150 p
= memchr(line
, ':', end
- line
);
161 for (i
= 0; modname
[i
]; i
++) {
162 /* Module names can't have colons. */
163 if (modname
[i
] == ':')
165 if (modname
[i
] == p
[i
])
167 if (modname
[i
] == '_' && p
[i
] == '-')
169 if (modname
[i
] == '-' && p
[i
] == '_')
173 /* Must match all the way to the extension */
174 return (p
[i
] == '.');
177 static char *next_line(char *p
, const char *end
)
181 eol
= memchr(p
, '\n', end
- p
);
184 return (char *)end
+ 1;
187 static struct elf_file
*grab_module(const char *name
,
194 char *depname
, *p
, *moddir
;
195 struct elf_file
*module
;
197 if (strchr(name
, '.') || strchr(name
, '/')) {
198 module
= grab_elf_file(name
);
200 error("modinfo: could not open %s: %s\n",
201 name
, strerror(errno
));
207 kernel
= buf
.release
;
210 nofail_asprintf(&moddir
, "%s/%s/%s", basedir
, MODULE_DIR
, kernel
);
212 nofail_asprintf(&moddir
, "%s/%s", MODULE_DIR
, kernel
);
214 /* Search for it in modules.dep. */
215 nofail_asprintf(&depname
, "%s/%s", moddir
, "modules.dep");
216 data
= grab_file(depname
, &size
);
218 error("modinfo: could not open %s\n", depname
);
224 for (p
= data
; p
< data
+ size
; p
= next_line(p
, data
+ size
)) {
225 if (name_matches(p
, data
+ size
, name
)) {
226 int namelen
= strcspn(p
, ":");
231 dir
= basedir
; /* old style deps - abs. path */
233 dir
= moddir
; /* new style - relative path */
236 nofail_asprintf(&filename
, "%s/%s", dir
, p
);
237 filename
[namelen
+ strlen(dir
) + 1] = '\0';
239 filename
= strndup(p
, namelen
);
241 release_file(data
, size
);
242 module
= grab_elf_file(filename
);
244 error("modinfo: could not open %s: %s\n",
245 *filename
, strerror(errno
));
250 release_file(data
, size
);
251 error("modinfo: could not find module %s\n", name
);
255 static void usage(const char *name
)
257 fprintf(stderr
, "Usage: %s [-0][-F field][-k kernelversion][-b basedir] module...\n"
258 " Prints out the information about one or more module(s).\n"
259 " If a fieldname is given, just print out that field (or nothing if not found).\n"
260 " Otherwise, print all information out in a readable form\n"
261 " If -0 is given, separate with nul, not newline.\n"
262 " If -b is given, use an image of the module tree.\n",
266 int main(int argc
, char *argv
[])
268 const char *field
= NULL
;
269 const char *kernel
= NULL
;
274 logging
= 0; /* send messages to stderr */
276 if (native_endianness() == 0)
279 while ((opt
= getopt_long(argc
,argv
,"adlpVhn0F:k:b:",options
,NULL
)) >= 0){
281 case 'a': field
= "author"; break;
282 case 'd': field
= "description"; break;
283 case 'l': field
= "license"; break;
284 case 'p': field
= "parm"; break;
285 case 'n': field
= "filename"; break;
286 case 'V': printf(PACKAGE
" version " VERSION
"\n"); exit(0);
287 case 'F': field
= optarg
; break;
288 case '0': sep
= '\0'; break;
289 case 'k': kernel
= optarg
; break;
290 case 'b': basedir
= optarg
; break;
291 case 'h': usage(argv
[0]); exit(0); break;
293 usage(argv
[0]); exit(1);
296 if (argc
< optind
+ 1) {
301 for (opt
= optind
; opt
< argc
; opt
++) {
302 struct string_table
*tags
;
303 struct elf_file
*mod
;
305 mod
= grab_module(argv
[opt
], kernel
, basedir
);
310 tags
= mod
->ops
->load_strings(mod
, ".modinfo", NULL
, error
);
312 release_elf_file(mod
);
316 print_tag(field
, tags
, mod
->pathname
, sep
);
318 print_all(tags
, mod
->pathname
, sep
);
320 release_elf_file(mod
);