2e920ef40ca6c6e966ece78784ecd35c4420e68d
[project/ubox.git] / kmodloader.c
1 /*
2 * Copyright (C) 2013 Felix Fietkau <nbd@openwrt.org>
3 * Copyright (C) 2013 John Crispin <blogic@openwrt.org>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU Lesser General Public License version 2.1
7 * as published by the Free Software Foundation
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 */
14
15 #define _GNU_SOURCE
16 #include <sys/syscall.h>
17 #include <sys/mman.h>
18 #include <sys/utsname.h>
19
20 #include <stdlib.h>
21 #include <unistd.h>
22 #include <sys/syscall.h>
23 #include <sys/types.h>
24 #include <values.h>
25 #include <errno.h>
26 #include <stdio.h>
27 #include <string.h>
28 #include <sys/stat.h>
29 #include <fcntl.h>
30 #include <libgen.h>
31 #include <glob.h>
32 #include <elf.h>
33
34 #include <libubox/avl.h>
35 #include <libubox/avl-cmp.h>
36 #include <libubox/utils.h>
37 #include <libubox/ulog.h>
38
39 #define DEF_MOD_PATH "/modules/%s/"
40 /* duplicated from in-kernel include/linux/module.h */
41 #define MODULE_NAME_LEN (64 - sizeof(unsigned long))
42
43 enum {
44 SCANNED,
45 PROBE,
46 LOADED,
47 };
48
49 struct module {
50 char *name;
51 char *depends;
52 char *opts;
53
54 int size;
55 int usage;
56 int state;
57 int error;
58 int refcnt; /* number of references from module_node.m */
59 };
60
61 struct module_node {
62 struct avl_node avl;
63 struct module *m;
64 bool is_alias;
65 };
66
67 static struct avl_tree modules;
68
69 static char **module_folders = NULL;
70
71 static void free_module(struct module *m);
72
73 static int init_module_folders(void)
74 {
75 int n = 0;
76 struct stat st;
77 struct utsname ver;
78 char *s, *e, *p, path[256], ldpath[256];
79
80 e = ldpath;
81 s = getenv("LD_LIBRARY_PATH");
82
83 if (s)
84 e += snprintf(ldpath, sizeof(ldpath), "%s:", s);
85
86 e += snprintf(e, sizeof(ldpath) - (e - ldpath), "/lib");
87
88 uname(&ver);
89
90 for (s = p = ldpath; p <= e; p++) {
91 if (*p != ':' && *p != '\0')
92 continue;
93
94 *p = 0;
95 snprintf(path, sizeof(path), "%s" DEF_MOD_PATH, s, ver.release);
96
97 if (!stat(path, &st) && S_ISDIR(st.st_mode)) {
98 module_folders = realloc(module_folders, sizeof(p) * (n + 2));
99
100 if (!module_folders) {
101 ULOG_ERR("out of memory\n");
102 return -1;
103 }
104
105 module_folders[n++] = strdup(path);
106 }
107
108 s = p + 1;
109 }
110
111 if (!module_folders)
112 return -1;
113
114 module_folders[n] = NULL;
115 return 0;
116 }
117
118 static struct module *find_module(const char *name)
119 {
120 struct module_node *mn;
121 mn = avl_find_element(&modules, name, mn, avl);
122 if (mn)
123 return mn->m;
124 else
125 return NULL;
126 }
127
128 static void free_modules(void)
129 {
130 struct module_node *mn, *tmp;
131
132 avl_remove_all_elements(&modules, mn, avl, tmp) {
133 struct module *m = mn->m;
134
135 m->refcnt -= 1;
136 if (m->refcnt == 0)
137 free_module(m);
138 free(mn);
139 }
140 }
141
142 static char* get_module_path(char *name)
143 {
144 char **p;
145 static char path[256];
146 struct stat s;
147
148 if (!stat(name, &s) && S_ISREG(s.st_mode))
149 return name;
150
151 for (p = module_folders; *p; p++) {
152 snprintf(path, sizeof(path), "%s%s.ko", *p, name);
153 if (!stat(path, &s) && S_ISREG(s.st_mode))
154 return path;
155 }
156
157 return NULL;
158 }
159
160 static char* get_module_name(char *path)
161 {
162 static char name[MODULE_NAME_LEN];
163 char *t;
164
165 strncpy(name, basename(path), sizeof(name) - 1);
166
167 t = strstr(name, ".ko");
168 if (t)
169 *t = '\0';
170
171 return name;
172 }
173
174 static int elf64_find_section(char *map, const char *section, unsigned int *offset, unsigned int *size)
175 {
176 const char *secnames;
177 Elf64_Ehdr *e;
178 Elf64_Shdr *sh;
179 int i;
180
181 e = (Elf64_Ehdr *) map;
182 sh = (Elf64_Shdr *) (map + e->e_shoff);
183
184 secnames = map + sh[e->e_shstrndx].sh_offset;
185 for (i = 0; i < e->e_shnum; i++) {
186 if (!strcmp(section, secnames + sh[i].sh_name)) {
187 *size = sh[i].sh_size;
188 *offset = sh[i].sh_offset;
189 return 0;
190 }
191 }
192
193 return -1;
194 }
195
196 static int elf32_find_section(char *map, const char *section, unsigned int *offset, unsigned int *size)
197 {
198 const char *secnames;
199 Elf32_Ehdr *e;
200 Elf32_Shdr *sh;
201 int i;
202
203 e = (Elf32_Ehdr *) map;
204 sh = (Elf32_Shdr *) (map + e->e_shoff);
205
206 secnames = map + sh[e->e_shstrndx].sh_offset;
207 for (i = 0; i < e->e_shnum; i++) {
208 if (!strcmp(section, secnames + sh[i].sh_name)) {
209 *size = sh[i].sh_size;
210 *offset = sh[i].sh_offset;
211 return 0;
212 }
213 }
214
215 return -1;
216 }
217
218 static int elf_find_section(char *map, const char *section, unsigned int *offset, unsigned int *size)
219 {
220 int clazz = map[EI_CLASS];
221 int endian = map[EI_DATA];
222
223 #if __BYTE_ORDER == __LITTLE_ENDIAN
224 if (endian != ELFDATA2LSB)
225 #elif __BYTE_ORDER == __BIG_ENDIAN
226 if (endian != ELFDATA2MSB)
227 #else
228 #error "unsupported endian"
229 #endif
230 {
231 ULOG_ERR("invalid endianess: %d\n", endian);
232 return -1;
233 }
234
235 if (clazz == ELFCLASS32)
236 return elf32_find_section(map, section, offset, size);
237 else if (clazz == ELFCLASS64)
238 return elf64_find_section(map, section, offset, size);
239
240 ULOG_ERR("unknown elf format %d\n", clazz);
241
242 return -1;
243 }
244
245 static struct module_node *
246 alloc_module_node(const char *name, struct module *m, bool is_alias)
247 {
248 struct module_node *mn;
249 char *_name;
250
251 mn = calloc_a(sizeof(*mn),
252 &_name, strlen(name) + 1);
253 if (mn) {
254 mn->avl.key = strcpy(_name, name);
255 mn->m = m;
256 mn->is_alias = is_alias;
257 avl_insert(&modules, &mn->avl);
258 m->refcnt += 1;
259 }
260 return mn;
261 }
262
263 static struct module *
264 alloc_module(const char *name, const char * const *aliases, int naliases, const char *depends, int size)
265 {
266 struct module *m;
267 char *_name, *_dep;
268 int i;
269
270 m = calloc_a(sizeof(*m),
271 &_name, strlen(name) + 1,
272 &_dep, depends ? strlen(depends) + 2 : 0);
273 if (!m)
274 return NULL;
275
276 m->name = strcpy(_name, name);
277 m->opts = 0;
278
279 if (depends) {
280 m->depends = strcpy(_dep, depends);
281 while (*_dep) {
282 if (*_dep == ',')
283 *_dep = '\0';
284 _dep++;
285 }
286 }
287 m->size = size;
288
289 m->refcnt = 0;
290 alloc_module_node(m->name, m, false);
291 for (i = 0; i < naliases; i++)
292 alloc_module_node(aliases[i], m, true);
293
294 return m;
295 }
296
297 static void free_module(struct module *m)
298 {
299 if (m->opts)
300 free(m->opts);
301 free(m);
302 }
303
304 static int scan_loaded_modules(void)
305 {
306 size_t buf_len = 0;
307 char *buf = NULL;
308 FILE *fp;
309
310 fp = fopen("/proc/modules", "r");
311 if (!fp) {
312 ULOG_ERR("failed to open /proc/modules\n");
313 return -1;
314 }
315
316 while (getline(&buf, &buf_len, fp) > 0) {
317 struct module m;
318 struct module *n;
319
320 m.name = strtok(buf, " ");
321 m.size = atoi(strtok(NULL, " "));
322 m.usage = atoi(strtok(NULL, " "));
323 m.depends = strtok(NULL, " ");
324
325 if (!m.name || !m.depends)
326 continue;
327
328 n = find_module(m.name);
329 if (!n) {
330 /* possibly a module outside /lib/modules/<ver>/ */
331 n = alloc_module(m.name, NULL, 0, m.depends, m.size);
332 }
333 n->usage = m.usage;
334 n->state = LOADED;
335 }
336 free(buf);
337 fclose(fp);
338
339 return 0;
340 }
341
342 static struct module* get_module_info(const char *module, const char *name)
343 {
344 int fd = open(module, O_RDONLY);
345 unsigned int offset, size;
346 char *map = MAP_FAILED, *strings, *dep = NULL;
347 const char **aliases = NULL;
348 int naliases = 0;
349 struct module *m = NULL;
350 struct stat s;
351
352 if (fd < 0) {
353 ULOG_ERR("failed to open %s\n", module);
354 goto out;
355 }
356
357 if (fstat(fd, &s) == -1) {
358 ULOG_ERR("failed to stat %s\n", module);
359 goto out;
360 }
361
362 map = mmap(NULL, s.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
363 if (map == MAP_FAILED) {
364 ULOG_ERR("failed to mmap %s\n", module);
365 goto out;
366 }
367
368 if (elf_find_section(map, ".modinfo", &offset, &size)) {
369 ULOG_ERR("failed to load the .modinfo section from %s\n", module);
370 goto out;
371 }
372
373 strings = map + offset;
374 while (true) {
375 char *sep;
376 int len;
377
378 while (!strings[0])
379 strings++;
380 if (strings >= map + offset + size)
381 break;
382 sep = strstr(strings, "=");
383 if (!sep)
384 break;
385 len = sep - strings;
386 sep++;
387 if (!strncmp(strings, "depends=", len + 1))
388 dep = sep;
389 else if (!strncmp(strings, "alias=", len + 1)) {
390 aliases = realloc(aliases, sizeof(sep) * (naliases + 1));
391 if (!aliases) {
392 ULOG_ERR("out of memory\n");
393 goto out;
394 }
395
396 aliases[naliases++] = sep;
397 }
398 strings = &sep[strlen(sep)];
399 }
400
401 m = alloc_module(name, aliases, naliases, dep, s.st_size);
402
403 if (m)
404 m->state = SCANNED;
405
406 out:
407 if (map != MAP_FAILED)
408 munmap(map, s.st_size);
409
410 if (fd >= 0)
411 close(fd);
412
413 free(aliases);
414
415 return m;
416 }
417
418 static int scan_module_folder(const char *dir)
419 {
420 int gl_flags = GLOB_NOESCAPE | GLOB_MARK;
421 struct utsname ver;
422 char *path;
423 glob_t gl;
424 int j, rv = 0;
425
426 uname(&ver);
427 path = alloca(strlen(dir) + sizeof("*.ko") + 1);
428 sprintf(path, "%s*.ko", dir);
429
430 if (glob(path, gl_flags, NULL, &gl) < 0)
431 return -1;
432
433 for (j = 0; j < gl.gl_pathc; j++) {
434 char *name = get_module_name(gl.gl_pathv[j]);
435 struct module *m;
436
437 if (!name)
438 continue;
439
440 m = find_module(name);
441 if (!m) {
442 if (!get_module_info(gl.gl_pathv[j], name))
443 rv |= -1;
444 }
445 }
446
447 globfree(&gl);
448
449 return rv;
450 }
451
452 static int scan_module_folders(void)
453 {
454 int rv = 0;
455 char **p;
456
457 if (init_module_folders())
458 return -1;
459
460 for (p = module_folders; *p; p++)
461 rv |= scan_module_folder(*p);
462
463 return rv;
464 }
465
466 static int print_modinfo(char *module)
467 {
468 int fd = open(module, O_RDONLY);
469 unsigned int offset, size;
470 struct stat s;
471 char *map = MAP_FAILED, *strings;
472 int rv = -1;
473
474 if (fd < 0) {
475 ULOG_ERR("failed to open %s\n", module);
476 goto out;
477 }
478
479 if (fstat(fd, &s) == -1) {
480 ULOG_ERR("failed to stat %s\n", module);
481 goto out;
482 }
483
484 map = mmap(NULL, s.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
485 if (map == MAP_FAILED) {
486 ULOG_ERR("failed to mmap %s\n", module);
487 goto out;
488 }
489
490 if (elf_find_section(map, ".modinfo", &offset, &size)) {
491 ULOG_ERR("failed to load the .modinfo section from %s\n", module);
492 goto out;
493 }
494
495 strings = map + offset;
496 printf("module:\t\t%s\n", module);
497 while (true) {
498 char *dup = NULL;
499 char *sep;
500
501 while (!strings[0])
502 strings++;
503 if (strings >= map + offset + size)
504 break;
505 sep = strstr(strings, "=");
506 if (!sep)
507 break;
508 dup = strndup(strings, sep - strings);
509 sep++;
510 if (strncmp(strings, "parm", 4)) {
511 if (strlen(dup) < 7)
512 printf("%s:\t\t%s\n", dup, sep);
513 else
514 printf("%s:\t%s\n", dup, sep);
515 }
516 strings = &sep[strlen(sep)];
517 if (dup)
518 free(dup);
519 }
520
521 rv = 0;
522
523 out:
524 if (map != MAP_FAILED)
525 munmap(map, s.st_size);
526
527 if (fd >= 0)
528 close(fd);
529
530 return rv;
531 }
532
533 static int deps_available(struct module *m, int verbose)
534 {
535 char *dep;
536 int err = 0;
537
538 if (!m->depends || !strcmp(m->depends, "-") || !strcmp(m->depends, ""))
539 return 0;
540
541 dep = m->depends;
542
543 while (*dep) {
544 m = find_module(dep);
545
546 if (verbose && !m)
547 ULOG_ERR("missing dependency %s\n", dep);
548 if (verbose && m && (m->state != LOADED))
549 ULOG_ERR("dependency not loaded %s\n", dep);
550 if (!m || (m->state != LOADED))
551 err++;
552 dep += strlen(dep) + 1;
553 }
554
555 return err;
556 }
557
558 static int insert_module(char *path, const char *options)
559 {
560 void *data = 0;
561 struct stat s;
562 int fd, ret = -1;
563
564 if (stat(path, &s)) {
565 ULOG_ERR("missing module %s\n", path);
566 return ret;
567 }
568
569 fd = open(path, O_RDONLY);
570 if (fd < 0) {
571 ULOG_ERR("cannot open %s\n", path);
572 return ret;
573 }
574
575 data = malloc(s.st_size);
576 if (!data) {
577 ULOG_ERR("out of memory\n");
578 goto out;
579 }
580
581 if (read(fd, data, s.st_size) == s.st_size) {
582 ret = syscall(__NR_init_module, data, (unsigned long) s.st_size, options);
583 if (errno == EEXIST)
584 ret = 0;
585 }
586 else
587 ULOG_ERR("failed to read full module %s\n", path);
588
589 out:
590 close(fd);
591 free(data);
592
593 return ret;
594 }
595
596 static void load_moddeps(struct module *_m)
597 {
598 char *dep;
599 struct module *m;
600
601 if (!strcmp(_m->depends, "-") || !strcmp(_m->depends, ""))
602 return;
603
604 dep = _m->depends;
605
606 while (*dep) {
607 m = find_module(dep);
608
609 if (!m)
610 ULOG_ERR("failed to find dependency %s\n", dep);
611 if (m && (m->state != LOADED)) {
612 m->state = PROBE;
613 load_moddeps(m);
614 }
615
616 dep = dep + strlen(dep) + 1;
617 }
618 }
619
620 static int iterations = 0;
621 static int load_modprobe(void)
622 {
623 int loaded, todo;
624 struct module_node *mn;
625 struct module *m;
626
627 avl_for_each_element(&modules, mn, avl) {
628 if (mn->is_alias)
629 continue;
630 m = mn->m;
631 if (m->state == PROBE)
632 load_moddeps(m);
633 }
634
635 do {
636 loaded = 0;
637 todo = 0;
638 avl_for_each_element(&modules, mn, avl) {
639 if (mn->is_alias)
640 continue;
641 m = mn->m;
642 if ((m->state == PROBE) && (!deps_available(m, 0)) && m->error < 2) {
643 if (!insert_module(get_module_path(m->name), (m->opts) ? (m->opts) : (""))) {
644 m->state = LOADED;
645 m->error = 0;
646 loaded++;
647 continue;
648 }
649
650 if (++m->error > 1)
651 ULOG_ERR("failed to load %s\n", m->name);
652 }
653
654 if ((m->state == PROBE) || m->error)
655 todo++;
656 }
657 iterations++;
658 } while (loaded);
659
660 return todo;
661 }
662
663 static int print_insmod_usage(void)
664 {
665 ULOG_INFO("Usage:\n\tinsmod filename [args]\n");
666
667 return -1;
668 }
669
670 static int print_modprobe_usage(void)
671 {
672 ULOG_INFO("Usage:\n\tmodprobe [-q] filename\n");
673
674 return -1;
675 }
676
677 static int print_usage(char *arg)
678 {
679 ULOG_INFO("Usage:\n\t%s module\n", arg);
680
681 return -1;
682 }
683
684 static int main_insmod(int argc, char **argv)
685 {
686 char *name, *cur, *options;
687 int i, ret, len;
688
689 if (argc < 2)
690 return print_insmod_usage();
691
692 name = get_module_name(argv[1]);
693 if (!name) {
694 ULOG_ERR("cannot find module - %s\n", argv[1]);
695 return -1;
696 }
697
698 if (scan_loaded_modules())
699 return -1;
700
701 if (find_module(name)) {
702 ULOG_ERR("module is already loaded - %s\n", name);
703 return -1;
704
705 }
706
707 free_modules();
708
709 for (len = 0, i = 2; i < argc; i++)
710 len += strlen(argv[i]) + 1;
711
712 options = malloc(len);
713 if (!options) {
714 ULOG_ERR("out of memory\n");
715 ret = -1;
716 goto err;
717 }
718
719 options[0] = 0;
720 cur = options;
721 for (i = 2; i < argc; i++) {
722 if (options[0]) {
723 *cur = ' ';
724 cur++;
725 }
726 cur += sprintf(cur, "%s", argv[i]);
727 }
728
729 if (init_module_folders()) {
730 fprintf(stderr, "Failed to find the folder holding the modules\n");
731 ret = -1;
732 goto err;
733 }
734
735 if (get_module_path(argv[1])) {
736 name = argv[1];
737 } else if (!get_module_path(name)) {
738 fprintf(stderr, "Failed to find %s. Maybe it is a built in module ?\n", name);
739 ret = -1;
740 goto err;
741 }
742
743 ret = insert_module(get_module_path(name), options);
744 if (ret)
745 ULOG_ERR("failed to insert %s\n", get_module_path(name));
746
747 err:
748 free(options);
749 return ret;
750 }
751
752 static int main_rmmod(int argc, char **argv)
753 {
754 struct module *m;
755 char *name;
756 int ret;
757
758 if (argc != 2)
759 return print_usage("rmmod");
760
761 if (scan_loaded_modules())
762 return -1;
763
764 name = get_module_name(argv[1]);
765 m = find_module(name);
766 if (!m) {
767 ULOG_ERR("module is not loaded\n");
768 return -1;
769 }
770 ret = syscall(__NR_delete_module, m->name, 0);
771
772 if (ret)
773 ULOG_ERR("unloading the module failed\n");
774
775 free_modules();
776
777 return ret;
778 }
779
780 static int main_lsmod(int argc, char **argv)
781 {
782 struct module_node *mn;
783 struct module *m;
784 char *dep;
785
786 if (scan_loaded_modules())
787 return -1;
788
789 avl_for_each_element(&modules, mn, avl) {
790 if (mn->is_alias)
791 continue;
792 m = mn->m;
793 if (m->state == LOADED) {
794 printf("%-20s%8d%3d ",
795 m->name, m->size, m->usage);
796 if (m->depends && strcmp(m->depends, "-") && strcmp(m->depends, "")) {
797 dep = m->depends;
798 while (*dep) {
799 printf("%s", dep);
800 dep = dep + strlen(dep) + 1;
801 if (*dep)
802 printf(",");
803 }
804 }
805 printf("\n");
806 }
807 }
808
809 free_modules();
810
811 return 0;
812 }
813
814 static int main_modinfo(int argc, char **argv)
815 {
816 struct module *m;
817 char *name;
818
819 if (argc != 2)
820 return print_usage("modinfo");
821
822 if (scan_module_folders())
823 return -1;
824
825 name = get_module_name(argv[1]);
826 m = find_module(name);
827 if (!m) {
828 ULOG_ERR("cannot find module - %s\n", argv[1]);
829 return -1;
830 }
831
832 name = get_module_path(m->name);
833 if (!name) {
834 ULOG_ERR("cannot find path of module - %s\n", m->name);
835 return -1;
836 }
837
838 print_modinfo(name);
839
840 return 0;
841 }
842
843 static int main_modprobe(int argc, char **argv)
844 {
845 struct module_node *mn;
846 struct module *m;
847 char *name;
848 char *mod = NULL;
849 int opt;
850 bool quiet = false;
851
852 while ((opt = getopt(argc, argv, "q")) != -1 ) {
853 switch (opt) {
854 case 'q': /* shhhh! */
855 quiet = true;
856 break;
857 default: /* '?' */
858 return print_modprobe_usage();
859 break;
860 }
861 }
862
863 if (optind >= argc)
864 return print_modprobe_usage(); /* expected module after options */
865
866 mod = argv[optind];
867
868 if (scan_module_folders())
869 return -1;
870
871 if (scan_loaded_modules())
872 return -1;
873
874 name = get_module_name(mod);
875 m = find_module(name);
876 if (m && m->state == LOADED) {
877 if (!quiet)
878 ULOG_ERR("%s is already loaded\n", name);
879 return 0;
880 } else if (!m) {
881 if (!quiet)
882 ULOG_ERR("failed to find a module named %s\n", name);
883 return -1;
884 } else {
885 int fail;
886
887 m->state = PROBE;
888
889 fail = load_modprobe();
890
891 if (fail) {
892 ULOG_ERR("%d module%s could not be probed\n",
893 fail, (fail == 1) ? ("") : ("s"));
894
895 avl_for_each_element(&modules, mn, avl) {
896 if (mn->is_alias)
897 continue;
898 m = mn->m;
899 if ((m->state == PROBE) || m->error)
900 ULOG_ERR("- %s\n", m->name);
901 }
902 }
903 }
904
905 free_modules();
906
907 return 0;
908 }
909
910 static int main_loader(int argc, char **argv)
911 {
912 int gl_flags = GLOB_NOESCAPE | GLOB_MARK;
913 char *dir = "/etc/modules.d/";
914 struct module_node *mn;
915 struct module *m;
916 glob_t gl;
917 char *path;
918 int fail, j;
919
920 if (argc > 1)
921 dir = argv[1];
922
923 path = malloc(strlen(dir) + 2);
924 if (!path) {
925 ULOG_ERR("out of memory\n");
926 return -1;
927 }
928
929 strcpy(path, dir);
930 strcat(path, "*");
931
932 if (scan_module_folders()) {
933 free (path);
934 return -1;
935 }
936
937 if (scan_loaded_modules()) {
938 free (path);
939 return -1;
940 }
941
942 ULOG_INFO("loading kernel modules from %s\n", path);
943
944 if (glob(path, gl_flags, NULL, &gl) < 0)
945 goto out;
946
947 for (j = 0; j < gl.gl_pathc; j++) {
948 FILE *fp = fopen(gl.gl_pathv[j], "r");
949 size_t mod_len = 0;
950 char *mod = NULL;
951
952 if (!fp) {
953 ULOG_ERR("failed to open %s\n", gl.gl_pathv[j]);
954 continue;
955 }
956
957 while (getline(&mod, &mod_len, fp) > 0) {
958 char *nl = strchr(mod, '\n');
959 struct module *m;
960 char *opts;
961
962 if (nl)
963 *nl = '\0';
964
965 opts = strchr(mod, ' ');
966 if (opts)
967 *opts++ = '\0';
968
969 m = find_module(get_module_name(mod));
970 if (!m || (m->state == LOADED))
971 continue;
972
973 if (opts)
974 m->opts = strdup(opts);
975 m->state = PROBE;
976 if (basename(gl.gl_pathv[j])[0] - '0' <= 9)
977 load_modprobe();
978
979 }
980 free(mod);
981 fclose(fp);
982 }
983
984 fail = load_modprobe();
985
986 if (fail) {
987 ULOG_ERR("%d module%s could not be probed\n",
988 fail, (fail == 1) ? ("") : ("s"));
989
990 avl_for_each_element(&modules, mn, avl) {
991 if (mn->is_alias)
992 continue;
993 m = mn->m;
994 if ((m->state == PROBE) || (m->error))
995 ULOG_ERR("- %s - %d\n", m->name, deps_available(m, 1));
996 }
997 } else {
998 ULOG_INFO("done loading kernel modules from %s\n", path);
999 }
1000
1001 out:
1002 globfree(&gl);
1003 free(path);
1004
1005 return 0;
1006 }
1007
1008 static inline char weight(char c)
1009 {
1010 return c == '_' ? '-' : c;
1011 }
1012
1013 static int avl_modcmp(const void *k1, const void *k2, void *ptr)
1014 {
1015 const char *s1 = k1;
1016 const char *s2 = k2;
1017
1018 while (*s1 && (weight(*s1) == weight(*s2)))
1019 {
1020 s1++;
1021 s2++;
1022 }
1023
1024 return (unsigned char)weight(*s1) - (unsigned char)weight(*s2);
1025 }
1026
1027 int main(int argc, char **argv)
1028 {
1029 char *exec = basename(*argv);
1030
1031 avl_init(&modules, avl_modcmp, false, NULL);
1032 if (!strcmp(exec, "insmod"))
1033 return main_insmod(argc, argv);
1034
1035 if (!strcmp(exec, "rmmod"))
1036 return main_rmmod(argc, argv);
1037
1038 if (!strcmp(exec, "lsmod"))
1039 return main_lsmod(argc, argv);
1040
1041 if (!strcmp(exec, "modinfo"))
1042 return main_modinfo(argc, argv);
1043
1044 if (!strcmp(exec, "modprobe"))
1045 return main_modprobe(argc, argv);
1046
1047 ulog_open(ULOG_KMSG, LOG_USER, "kmodloader");
1048 return main_loader(argc, argv);
1049 }