kmodloader: Increase path array size to make it always fit
[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[330], 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 load_modprobe(bool allow_load_retry)
621 {
622 int loaded, skipped, failed;
623 struct module_node *mn;
624 struct module *m;
625 bool load_retry = false;
626 static bool first_iteration = true;
627
628 avl_for_each_element(&modules, mn, avl) {
629 if (mn->is_alias)
630 continue;
631 m = mn->m;
632 if (m->state == PROBE)
633 load_moddeps(m);
634 }
635
636 do {
637 loaded = 0;
638 skipped = 0;
639 failed = 0;
640 avl_for_each_element(&modules, mn, avl) {
641 if (mn->is_alias)
642 continue;
643 m = mn->m;
644 if ((m->state == PROBE) && (!deps_available(m, 0)) && (!m->error || load_retry)) {
645 if (!insert_module(get_module_path(m->name), (m->opts) ? (m->opts) : (""))) {
646 m->state = LOADED;
647 m->error = 0;
648 loaded++;
649 continue;
650 }
651
652 m->error = 1;
653 }
654
655 if (m->error)
656 failed++;
657 else if (m->state == PROBE)
658 skipped++;
659 }
660
661 if (allow_load_retry) {
662 /* if we can't load anything else let's try to load failed modules */
663 load_retry = loaded ? (failed && !skipped) : (failed && !load_retry && !first_iteration);
664 }
665
666 first_iteration = false;
667 } while (loaded || load_retry);
668
669 return skipped + failed;
670 }
671
672 static int print_insmod_usage(void)
673 {
674 ULOG_INFO("Usage:\n\tinsmod filename [args]\n");
675
676 return -1;
677 }
678
679 static int print_modprobe_usage(void)
680 {
681 ULOG_INFO("Usage:\n\tmodprobe [-q] filename\n");
682
683 return -1;
684 }
685
686 static int print_usage(char *arg)
687 {
688 ULOG_INFO("Usage:\n\t%s module\n", arg);
689
690 return -1;
691 }
692
693 static int main_insmod(int argc, char **argv)
694 {
695 char *name, *cur, *options;
696 int i, ret, len;
697
698 if (argc < 2)
699 return print_insmod_usage();
700
701 name = get_module_name(argv[1]);
702 if (!name) {
703 ULOG_ERR("cannot find module - %s\n", argv[1]);
704 return -1;
705 }
706
707 if (scan_loaded_modules())
708 return -1;
709
710 if (find_module(name)) {
711 ULOG_ERR("module is already loaded - %s\n", name);
712 return -1;
713
714 }
715
716 free_modules();
717
718 for (len = 0, i = 2; i < argc; i++)
719 len += strlen(argv[i]) + 1;
720
721 options = malloc(len);
722 if (!options) {
723 ULOG_ERR("out of memory\n");
724 ret = -1;
725 goto err;
726 }
727
728 options[0] = 0;
729 cur = options;
730 for (i = 2; i < argc; i++) {
731 if (options[0]) {
732 *cur = ' ';
733 cur++;
734 }
735 cur += sprintf(cur, "%s", argv[i]);
736 }
737
738 if (init_module_folders()) {
739 fprintf(stderr, "Failed to find the folder holding the modules\n");
740 ret = -1;
741 goto err;
742 }
743
744 if (get_module_path(argv[1])) {
745 name = argv[1];
746 } else if (!get_module_path(name)) {
747 fprintf(stderr, "Failed to find %s. Maybe it is a built in module ?\n", name);
748 ret = -1;
749 goto err;
750 }
751
752 ret = insert_module(get_module_path(name), options);
753 if (ret)
754 ULOG_ERR("failed to insert %s\n", get_module_path(name));
755
756 err:
757 free(options);
758 return ret;
759 }
760
761 static int main_rmmod(int argc, char **argv)
762 {
763 struct module *m;
764 char *name;
765 int ret;
766
767 if (argc != 2)
768 return print_usage("rmmod");
769
770 if (scan_loaded_modules())
771 return -1;
772
773 name = get_module_name(argv[1]);
774 m = find_module(name);
775 if (!m) {
776 ULOG_ERR("module is not loaded\n");
777 return -1;
778 }
779 ret = syscall(__NR_delete_module, m->name, 0);
780
781 if (ret)
782 ULOG_ERR("unloading the module failed\n");
783
784 free_modules();
785
786 return ret;
787 }
788
789 static int main_lsmod(int argc, char **argv)
790 {
791 struct module_node *mn;
792 struct module *m;
793 char *dep;
794
795 if (scan_loaded_modules())
796 return -1;
797
798 avl_for_each_element(&modules, mn, avl) {
799 if (mn->is_alias)
800 continue;
801 m = mn->m;
802 if (m->state == LOADED) {
803 printf("%-20s%8d%3d ",
804 m->name, m->size, m->usage);
805 if (m->depends && strcmp(m->depends, "-") && strcmp(m->depends, "")) {
806 dep = m->depends;
807 while (*dep) {
808 printf("%s", dep);
809 dep = dep + strlen(dep) + 1;
810 if (*dep)
811 printf(",");
812 }
813 }
814 printf("\n");
815 }
816 }
817
818 free_modules();
819
820 return 0;
821 }
822
823 static int main_modinfo(int argc, char **argv)
824 {
825 struct module *m;
826 char *name;
827
828 if (argc != 2)
829 return print_usage("modinfo");
830
831 if (scan_module_folders())
832 return -1;
833
834 name = get_module_name(argv[1]);
835 m = find_module(name);
836 if (!m) {
837 ULOG_ERR("cannot find module - %s\n", argv[1]);
838 return -1;
839 }
840
841 name = get_module_path(m->name);
842 if (!name) {
843 ULOG_ERR("cannot find path of module - %s\n", m->name);
844 return -1;
845 }
846
847 print_modinfo(name);
848
849 return 0;
850 }
851
852 static int main_modprobe(int argc, char **argv)
853 {
854 struct module_node *mn;
855 struct module *m;
856 char *name;
857 char *mod = NULL;
858 int opt;
859 bool quiet = false;
860
861 while ((opt = getopt(argc, argv, "q")) != -1 ) {
862 switch (opt) {
863 case 'q': /* shhhh! */
864 quiet = true;
865 break;
866 default: /* '?' */
867 return print_modprobe_usage();
868 break;
869 }
870 }
871
872 if (optind >= argc)
873 return print_modprobe_usage(); /* expected module after options */
874
875 mod = argv[optind];
876
877 if (scan_module_folders())
878 return -1;
879
880 if (scan_loaded_modules())
881 return -1;
882
883 name = get_module_name(mod);
884 m = find_module(name);
885 if (m && m->state == LOADED) {
886 if (!quiet)
887 ULOG_ERR("%s is already loaded\n", name);
888 return 0;
889 } else if (!m) {
890 if (!quiet)
891 ULOG_ERR("failed to find a module named %s\n", name);
892 return -1;
893 } else {
894 int fail;
895
896 m->state = PROBE;
897
898 fail = load_modprobe(true);
899
900 if (fail) {
901 ULOG_ERR("%d module%s could not be probed\n",
902 fail, (fail == 1) ? ("") : ("s"));
903
904 avl_for_each_element(&modules, mn, avl) {
905 if (mn->is_alias)
906 continue;
907 m = mn->m;
908 if ((m->state == PROBE) || m->error)
909 ULOG_ERR("- %s\n", m->name);
910 }
911 }
912 }
913
914 free_modules();
915
916 return 0;
917 }
918
919 static int main_loader(int argc, char **argv)
920 {
921 int gl_flags = GLOB_NOESCAPE | GLOB_MARK;
922 char *dir = "/etc/modules.d/";
923 struct module_node *mn;
924 struct module *m;
925 glob_t gl;
926 char *path;
927 int fail, j;
928
929 if (argc > 1)
930 dir = argv[1];
931
932 path = malloc(strlen(dir) + 2);
933 if (!path) {
934 ULOG_ERR("out of memory\n");
935 return -1;
936 }
937
938 strcpy(path, dir);
939 strcat(path, "*");
940
941 if (scan_module_folders()) {
942 free (path);
943 return -1;
944 }
945
946 if (scan_loaded_modules()) {
947 free (path);
948 return -1;
949 }
950
951 ULOG_INFO("loading kernel modules from %s\n", path);
952
953 if (glob(path, gl_flags, NULL, &gl) < 0)
954 goto out;
955
956 for (j = 0; j < gl.gl_pathc; j++) {
957 FILE *fp = fopen(gl.gl_pathv[j], "r");
958 size_t mod_len = 0;
959 char *mod = NULL;
960
961 if (!fp) {
962 ULOG_ERR("failed to open %s\n", gl.gl_pathv[j]);
963 continue;
964 }
965
966 while (getline(&mod, &mod_len, fp) > 0) {
967 char *nl = strchr(mod, '\n');
968 struct module *m;
969 char *opts;
970
971 if (nl)
972 *nl = '\0';
973
974 opts = strchr(mod, ' ');
975 if (opts)
976 *opts++ = '\0';
977
978 m = find_module(get_module_name(mod));
979 if (!m || (m->state == LOADED))
980 continue;
981
982 if (opts)
983 m->opts = strdup(opts);
984 m->state = PROBE;
985 if (basename(gl.gl_pathv[j])[0] - '0' <= 9)
986 load_modprobe(false);
987
988 }
989 free(mod);
990 fclose(fp);
991 }
992
993 fail = load_modprobe(true);
994
995 if (fail) {
996 ULOG_ERR("%d module%s could not be probed\n",
997 fail, (fail == 1) ? ("") : ("s"));
998
999 avl_for_each_element(&modules, mn, avl) {
1000 if (mn->is_alias)
1001 continue;
1002 m = mn->m;
1003 if ((m->state == PROBE) || (m->error))
1004 ULOG_ERR("- %s - %d\n", m->name, deps_available(m, 1));
1005 }
1006 } else {
1007 ULOG_INFO("done loading kernel modules from %s\n", path);
1008 }
1009
1010 out:
1011 globfree(&gl);
1012 free(path);
1013
1014 return 0;
1015 }
1016
1017 static inline char weight(char c)
1018 {
1019 return c == '_' ? '-' : c;
1020 }
1021
1022 static int avl_modcmp(const void *k1, const void *k2, void *ptr)
1023 {
1024 const char *s1 = k1;
1025 const char *s2 = k2;
1026
1027 while (*s1 && (weight(*s1) == weight(*s2)))
1028 {
1029 s1++;
1030 s2++;
1031 }
1032
1033 return (unsigned char)weight(*s1) - (unsigned char)weight(*s2);
1034 }
1035
1036 int main(int argc, char **argv)
1037 {
1038 char *exec = basename(*argv);
1039
1040 avl_init(&modules, avl_modcmp, false, NULL);
1041 if (!strcmp(exec, "insmod"))
1042 return main_insmod(argc, argv);
1043
1044 if (!strcmp(exec, "rmmod"))
1045 return main_rmmod(argc, argv);
1046
1047 if (!strcmp(exec, "lsmod"))
1048 return main_lsmod(argc, argv);
1049
1050 if (!strcmp(exec, "modinfo"))
1051 return main_modinfo(argc, argv);
1052
1053 if (!strcmp(exec, "modprobe"))
1054 return main_modprobe(argc, argv);
1055
1056 ulog_open(ULOG_KMSG, LOG_USER, "kmodloader");
1057 return main_loader(argc, argv);
1058 }