diff options
Diffstat (limited to 'toys/modinfo.c')
-rw-r--r-- | toys/modinfo.c | 105 |
1 files changed, 105 insertions, 0 deletions
diff --git a/toys/modinfo.c b/toys/modinfo.c new file mode 100644 index 00000000..0e32fc66 --- /dev/null +++ b/toys/modinfo.c @@ -0,0 +1,105 @@ +/* vi: set sw=4 ts=4: + * + * modinfo.c - Display module info + * + * Copyright 2012 Andre Renaud <andre@bluewatersys.com> + * + +USE_MODINFO(NEWTOY(modinfo, "<1F:0", TOYFLAG_BIN)) + +config MODINFO + bool "modinfo" + default y + help + usage: modinfo [-0] [-F field] [modulename...] +*/ + +#include "toys.h" + +#define FLAG_0 (1 << 0) + +DEFINE_GLOBALS( + char *field; +) +#define TT this.modinfo + +static const char *modinfo_tags[] = { + "alias", "license", "description", "author", "vermagic", + "srcversion", "intree", "parm", "depends", +}; + +static void output_field(const char *field, const char *value) +{ + int len; + + if (TT.field && strcmp(TT.field, field) != 0) + return; + + len = strlen(field); + + if (TT.field) + xprintf("%s", value); + else + xprintf("%s:%*s%s", + field, 15 - len, "", value); + if (toys.optflags & FLAG_0) + xwrite(fileno(stdout), "\0", 1); + else + xputs(""); +} + + +static void modinfo_file(struct dirtree *dir) +{ + int fd, len, i; + char *buf, *pos; + char *full_name; + + full_name = dirtree_path(dir, NULL); + + output_field("filename", full_name); + fd = xopen(full_name, O_RDONLY); + len = fdlength(fd); + buf = xmalloc(len); + xreadall(fd, buf, len); + + for (pos = buf; pos < buf + len + 10; pos++) { + if (*pos) + continue; + + for (i = 0; i < sizeof(modinfo_tags) / sizeof(modinfo_tags[0]); i++) { + const char *str = modinfo_tags[i]; + int len = strlen(str); + if (strncmp(pos + 1, str, len) == 0 && pos[len + 1] == '=') + output_field(str, &pos[len + 2]); + } + } + + free(full_name); + free(buf); + close(fd); +} + +static int check_module(struct dirtree *new) +{ + if (S_ISREG(new->st.st_mode)) { + char **s; + for (s = toys.optargs; *s; s++) { + int len = strlen(*s); + if (strncmp(*s, new->name, len) == 0 && + strcmp(&new->name[len], ".ko") == 0) + modinfo_file(new); + } + } + + return dirtree_notdotdot(new); +} + +void modinfo_main(void) +{ + struct utsname uts; + if (uname(&uts) < 0) + perror_exit("unable to determine uname"); + sprintf(toybuf, "/lib/modules/%s", uts.release); + dirtree_read(toybuf, check_module); +} |