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