+ snprintf(path, 256, DEF_MOD_PATH "%s.ko", ver.release, name);
+
+ if (!stat(path, &s))
+ return path;
+
+ t = name;
+ while (t && *t) {
+ if (*t == '_')
+ *t = '-';
+ t++;
+ }
+
+ snprintf(path, 256, DEF_MOD_PATH "%s.ko", ver.release, name);
+
+ if (!stat(path, &s))
+ return path;
+
+ return NULL;
+}
+
+static char* get_module_name(char *path)
+{
+ static char name[32];
+ char *t;
+
+ strncpy(name, basename(path), sizeof(name));
+
+ t = strstr(name, ".ko");
+ if (t)
+ *t = '\0';
+ t = name;
+ while (t && *t) {
+ if (*t == '-')
+ *t = '_';
+ t++;
+ }
+
+ return name;
+}
+
+#if __WORDSIZE == 64
+static int elf_find_section(char *map, const char *section, unsigned int *offset, unsigned int *size)
+{
+ const char *secnames;
+ Elf64_Ehdr *e;
+ Elf64_Shdr *sh;
+ int i;
+
+ e = (Elf64_Ehdr *) map;
+ sh = (Elf64_Shdr *) (map + e->e_shoff);
+
+ secnames = map + sh[e->e_shstrndx].sh_offset;
+ for (i = 0; i < e->e_shnum; i++) {
+ if (!strcmp(section, secnames + sh[i].sh_name)) {
+ *size = sh[i].sh_size;
+ *offset = sh[i].sh_offset;
+ return 0;
+ }
+ }
+
+ return -1;
+}
+#else
+static int elf_find_section(char *map, const char *section, unsigned int *offset, unsigned int *size)
+{
+ const char *secnames;
+ Elf32_Ehdr *e;
+ Elf32_Shdr *sh;
+ int i;
+
+ e = (Elf32_Ehdr *) map;
+ sh = (Elf32_Shdr *) (map + e->e_shoff);
+
+ secnames = map + sh[e->e_shstrndx].sh_offset;
+ for (i = 0; i < e->e_shnum; i++) {
+ if (!strcmp(section, secnames + sh[i].sh_name)) {
+ *size = sh[i].sh_size;
+ *offset = sh[i].sh_offset;
+ return 0;
+ }
+ }
+
+ return -1;
+}
+#endif
+
+static int scan_loaded_modules(void)
+{
+ FILE *fp = fopen("/proc/modules", "r");
+ char buf[256];
+
+ if (!fp) {
+ fprintf(stderr, "failed to open /proc/modules\n");
+ return -1;
+ }
+
+ while (fgets(buf, sizeof(buf), fp)) {
+ struct module m;
+ struct module *n;
+
+ m.name = strtok(buf, " ");
+ m.size = atoi(strtok(NULL, " "));
+ m.usage = atoi(strtok(NULL, " "));
+ m.depends = strtok(NULL, " ");
+
+ if (!m.name || !m.depends)
+ continue;
+
+ n = malloc(sizeof(struct module));
+ if (!n)
+ continue;
+
+ n->name = strdup(m.name);
+ n->depends = strdup(m.depends);
+ n->size = m.size;
+ n->usage = m.usage;
+ n->state = LOADED;
+
+ list_add_tail(&n->list, &modules);
+ }
+
+ return 0;
+}
+
+static struct module* get_module_info(char *module)
+{
+ int fd = open(module, O_RDONLY);
+ unsigned int offset, size;
+ char *map, *strings;
+ struct module *m;
+ struct stat s;
+
+ if (!fd) {
+ fprintf(stderr, "failed to open %s\n", module);
+ return NULL;
+ }
+
+ if (fstat(fd, &s) == -1) {
+ fprintf(stderr, "failed to stat %s\n", module);
+ return NULL;
+ }
+
+ map = mmap(NULL, s.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
+ if (map == MAP_FAILED) {
+ fprintf(stderr, "failed to mmap %s\n", module);
+ return NULL;
+ }
+
+ if (elf_find_section(map, ".modinfo", &offset, &size)) {
+ fprintf(stderr, "failed to load the .modinfo section from %s\n", module);
+ return NULL;
+ }
+
+ strings = map + offset;
+ m = malloc(sizeof(struct module));
+ if (!m)
+ return NULL;
+
+ memset(m, 0, sizeof(struct module));
+ m->size = s.st_size;
+ while (strings && (strings < map + offset + size)) {
+ char *sep;
+ int len;
+
+ while (!strings[0])
+ strings++;
+ sep = strstr(strings, "=");
+ if (!sep)
+ break;
+ len = sep - strings;
+ sep++;
+ if (!strncmp(strings, "depends=", len + 1))
+ m->depends = strdup(sep);
+ strings = &sep[strlen(sep)];
+ }
+
+ m->state = SCANNED;
+
+ return m;
+}
+
+static int scan_module_folder(char *dir)
+{
+ int gl_flags = GLOB_NOESCAPE | GLOB_MARK;
+ int j;
+ glob_t gl;
+
+ if (glob(dir, gl_flags, NULL, &gl) < 0)
+ return -1;
+
+ for (j = 0; j < gl.gl_pathc; j++) {
+ char *name = get_module_name(gl.gl_pathv[j]);
+ struct module *m;
+
+ if (!name)
+ continue;
+
+ m = find_module(name);
+ if (!m) {
+ m = get_module_info(gl.gl_pathv[j]);
+ m->name = strdup(name);
+ list_add_tail(&m->list, &modules);
+ }
+ }
+
+ globfree(&gl);
+
+ return 0;
+}
+
+static int print_modinfo(char *module)
+{
+ int fd = open(module, O_RDONLY);
+ unsigned int offset, size;
+ struct stat s;
+ char *map, *strings;
+
+ if (!fd) {
+ fprintf(stderr, "failed to open %s\n", module);
+ return -1;
+ }
+
+ if (fstat(fd, &s) == -1) {
+ fprintf(stderr, "failed to stat %s\n", module);
+ return -1;
+ }
+
+ map = mmap(NULL, s.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
+ if (map == MAP_FAILED) {
+ fprintf(stderr, "failed to mmap %s\n", module);
+ return -1;
+ }
+
+ if (elf_find_section(map, ".modinfo", &offset, &size)) {
+ fprintf(stderr, "failed to load the .modinfo section from %s\n", module);
+ return -1;
+ }
+
+ strings = map + offset;
+ printf("module:\t\t%s\n", module);
+ while (strings && (strings < map + offset + size)) {
+ char *dup = NULL;
+ char *sep;
+
+ while (!strings[0])
+ strings++;
+ sep = strstr(strings, "=");
+ if (!sep)
+ break;
+ dup = strndup(strings, sep - strings);
+ sep++;
+ if (strncmp(strings, "parm", 4)) {
+ if (strlen(dup) < 7)
+ printf("%s:\t\t%s\n", dup, sep);
+ else
+ printf("%s:\t%s\n", dup, sep);
+ }
+ strings = &sep[strlen(sep)];
+ if (dup)
+ free(dup);
+ }
+
+ return 0;
+}
+
+static int insert_module(char *path, const char *options)
+{
+ void *data = 0;
+ struct stat s;
+ int fd, ret = -1;