]> git.ipfire.org Git - thirdparty/kmod.git/blob - tools/depmod.c
07a35baebd0f78122e732af98a742a8e0ed5a414
[thirdparty/kmod.git] / tools / depmod.c
1 /*
2 * kmod-depmod - calculate modules.dep using libkmod.
3 *
4 * Copyright (C) 2011-2013 ProFUSION embedded systems
5 *
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include <assert.h>
21 #include <ctype.h>
22 #include <dirent.h>
23 #include <errno.h>
24 #include <getopt.h>
25 #include <limits.h>
26 #include <regex.h>
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <unistd.h>
31 #include <sys/stat.h>
32 #include <sys/time.h>
33 #include <sys/utsname.h>
34
35 #include <shared/array.h>
36 #include <shared/hash.h>
37 #include <shared/macro.h>
38 #include <shared/util.h>
39 #include <shared/scratchbuf.h>
40
41 #include <libkmod/libkmod-internal.h>
42
43 #undef ERR
44 #undef DBG
45
46 #include "kmod.h"
47
48 #define DEFAULT_VERBOSE LOG_WARNING
49 static int verbose = DEFAULT_VERBOSE;
50
51 static const char CFG_BUILTIN_KEY[] = "built-in";
52 static const char CFG_EXTERNAL_KEY[] = "external";
53 static const char *default_cfg_paths[] = {
54 SYSCONFDIR "/depmod.d",
55 "/run/depmod.d",
56 "/usr/local/lib/depmod.d",
57 "/lib/depmod.d",
58 NULL
59 };
60
61 static const char cmdopts_s[] = "aAb:C:E:F:euqrvnP:wmVh";
62 static const struct option cmdopts[] = {
63 { "all", no_argument, 0, 'a' },
64 { "quick", no_argument, 0, 'A' },
65 { "basedir", required_argument, 0, 'b' },
66 { "config", required_argument, 0, 'C' },
67 { "symvers", required_argument, 0, 'E' },
68 { "filesyms", required_argument, 0, 'F' },
69 { "errsyms", no_argument, 0, 'e' },
70 { "unresolved-error", no_argument, 0, 'u' }, /* deprecated */
71 { "quiet", no_argument, 0, 'q' }, /* deprecated */
72 { "root", no_argument, 0, 'r' }, /* deprecated */
73 { "verbose", no_argument, 0, 'v' },
74 { "show", no_argument, 0, 'n' },
75 { "dry-run", no_argument, 0, 'n' },
76 { "symbol-prefix", required_argument, 0, 'P' },
77 { "warn", no_argument, 0, 'w' },
78 { "map", no_argument, 0, 'm' }, /* deprecated */
79 { "version", no_argument, 0, 'V' },
80 { "help", no_argument, 0, 'h' },
81 { }
82 };
83
84 static void help(void)
85 {
86 printf("Usage:\n"
87 "\t%s -[aA] [options] [forced_version]\n"
88 "\n"
89 "If no arguments (except options) are given, \"depmod -a\" is assumed\n"
90 "\n"
91 "depmod will output a dependency list suitable for the modprobe utility.\n"
92 "\n"
93 "Options:\n"
94 "\t-a, --all Probe all modules\n"
95 "\t-A, --quick Only does the work if there's a new module\n"
96 "\t-e, --errsyms Report not supplied symbols\n"
97 "\t-n, --show Write the dependency file on stdout only\n"
98 "\t-P, --symbol-prefix Architecture symbol prefix\n"
99 "\t-C, --config=PATH Read configuration from PATH\n"
100 "\t-v, --verbose Enable verbose mode\n"
101 "\t-w, --warn Warn on duplicates\n"
102 "\t-V, --version show version\n"
103 "\t-h, --help show this help\n"
104 "\n"
105 "The following options are useful for people managing distributions:\n"
106 "\t-b, --basedir=DIR Use an image of a module tree.\n"
107 "\t-F, --filesyms=FILE Use the file instead of the\n"
108 "\t current kernel symbols.\n"
109 "\t-E, --symvers=FILE Use Module.symvers file to check\n"
110 "\t symbol versions.\n",
111 program_invocation_short_name);
112 }
113
114 _printf_format_(1, 2)
115 static inline void _show(const char *fmt, ...)
116 {
117 va_list args;
118
119 if (verbose <= DEFAULT_VERBOSE)
120 return;
121
122 va_start(args, fmt);
123 vfprintf(stdout, fmt, args);
124 fflush(stdout);
125 va_end(args);
126 }
127 #define SHOW(...) _show(__VA_ARGS__)
128
129
130 /* binary index write *************************************************/
131 #include <arpa/inet.h>
132 /* BEGIN: code from module-init-tools/index.c just modified to compile here.
133 *
134 * Original copyright:
135 * index.c: module index file shared functions for modprobe and depmod
136 * Copyright (C) 2008 Alan Jenkins <alan-jenkins@tuffmail.co.uk>.
137 *
138 * These programs are free software; you can redistribute it and/or modify
139 * it under the terms of the GNU General Public License as published by
140 * the Free Software Foundation; either version 2 of the License, or
141 * (at your option) any later version.
142 *
143 * This program is distributed in the hope that it will be useful,
144 * but WITHOUT ANY WARRANTY; without even the implied warranty of
145 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
146 * GNU General Public License for more details.
147 *
148 * You should have received a copy of the GNU General Public License
149 * along with these programs. If not, see <http://www.gnu.org/licenses/>.
150 */
151
152 /* see documentation in libkmod/libkmod-index.c */
153
154 #define INDEX_MAGIC 0xB007F457
155 #define INDEX_VERSION_MAJOR 0x0002
156 #define INDEX_VERSION_MINOR 0x0001
157 #define INDEX_VERSION ((INDEX_VERSION_MAJOR<<16)|INDEX_VERSION_MINOR)
158 #define INDEX_CHILDMAX 128
159
160 struct index_value {
161 struct index_value *next;
162 unsigned int priority;
163 char value[0];
164 };
165
166 /* In-memory index (depmod only) */
167 struct index_node {
168 char *prefix; /* path compression */
169 struct index_value *values;
170 unsigned char first; /* range of child nodes */
171 unsigned char last;
172 struct index_node *children[INDEX_CHILDMAX]; /* indexed by character */
173 };
174
175
176 /* Format of node offsets within index file */
177 enum node_offset {
178 INDEX_NODE_FLAGS = 0xF0000000, /* Flags in high nibble */
179 INDEX_NODE_PREFIX = 0x80000000,
180 INDEX_NODE_VALUES = 0x40000000,
181 INDEX_NODE_CHILDS = 0x20000000,
182
183 INDEX_NODE_MASK = 0x0FFFFFFF, /* Offset value */
184 };
185
186 static struct index_node *index_create(void)
187 {
188 struct index_node *node;
189
190 node = NOFAIL(calloc(sizeof(struct index_node), 1));
191 node->prefix = NOFAIL(strdup(""));
192 node->first = INDEX_CHILDMAX;
193
194 return node;
195 }
196
197 static void index_values_free(struct index_value *values)
198 {
199 while (values) {
200 struct index_value *value = values;
201
202 values = value->next;
203 free(value);
204 }
205 }
206
207 static void index_destroy(struct index_node *node)
208 {
209 int c;
210
211 for (c = node->first; c <= node->last; c++) {
212 struct index_node *child = node->children[c];
213
214 if (child)
215 index_destroy(child);
216 }
217 index_values_free(node->values);
218 free(node->prefix);
219 free(node);
220 }
221
222 static void index__checkstring(const char *str)
223 {
224 int i;
225
226 for (i = 0; str[i]; i++) {
227 int ch = str[i];
228
229 if (ch >= INDEX_CHILDMAX)
230 CRIT("Module index: bad character '%c'=0x%x - only 7-bit ASCII is supported:"
231 "\n%s\n", (char) ch, (int) ch, str);
232 }
233 }
234
235 static int index_add_value(struct index_value **values,
236 const char *value, unsigned int priority)
237 {
238 struct index_value *v;
239 int duplicate = 0;
240 int len;
241
242 /* report the presence of duplicate values */
243 for (v = *values; v; v = v->next) {
244 if (streq(v->value, value))
245 duplicate = 1;
246 }
247
248 /* find position to insert value */
249 while (*values && (*values)->priority < priority)
250 values = &(*values)->next;
251
252 len = strlen(value);
253 v = NOFAIL(calloc(sizeof(struct index_value) + len + 1, 1));
254 v->next = *values;
255 v->priority = priority;
256 memcpy(v->value, value, len + 1);
257 *values = v;
258
259 return duplicate;
260 }
261
262 static int index_insert(struct index_node *node, const char *key,
263 const char *value, unsigned int priority)
264 {
265 int i = 0; /* index within str */
266 int ch;
267
268 index__checkstring(key);
269 index__checkstring(value);
270
271 while(1) {
272 int j; /* index within node->prefix */
273
274 /* Ensure node->prefix is a prefix of &str[i].
275 If it is not already, then we must split node. */
276 for (j = 0; node->prefix[j]; j++) {
277 ch = node->prefix[j];
278
279 if (ch != key[i+j]) {
280 char *prefix = node->prefix;
281 struct index_node *n;
282
283 /* New child is copy of node with prefix[j+1..N] */
284 n = NOFAIL(calloc(sizeof(struct index_node), 1));
285 memcpy(n, node, sizeof(struct index_node));
286 n->prefix = NOFAIL(strdup(&prefix[j+1]));
287
288 /* Parent has prefix[0..j], child at prefix[j] */
289 memset(node, 0, sizeof(struct index_node));
290 prefix[j] = '\0';
291 node->prefix = prefix;
292 node->first = ch;
293 node->last = ch;
294 node->children[ch] = n;
295
296 break;
297 }
298 }
299 /* j is now length of node->prefix */
300 i += j;
301
302 ch = key[i];
303 if(ch == '\0')
304 return index_add_value(&node->values, value, priority);
305
306 if (!node->children[ch]) {
307 struct index_node *child;
308
309 if (ch < node->first)
310 node->first = ch;
311 if (ch > node->last)
312 node->last = ch;
313 node->children[ch] = NOFAIL(calloc(sizeof(struct index_node), 1));
314
315 child = node->children[ch];
316 child->prefix = NOFAIL(strdup(&key[i+1]));
317 child->first = INDEX_CHILDMAX;
318 index_add_value(&child->values, value, priority);
319
320 return 0;
321 }
322
323 /* Descend into child node and continue */
324 node = node->children[ch];
325 i++;
326 }
327 }
328
329 static int index__haschildren(const struct index_node *node)
330 {
331 return node->first < INDEX_CHILDMAX;
332 }
333
334 /* Recursive post-order traversal
335
336 Pre-order would make for better read-side buffering / readahead / caching.
337 (post-order means you go backwards in the file as you descend the tree).
338 However, index reading is already fast enough.
339 Pre-order is simpler for writing, and depmod is already slow.
340 */
341 static uint32_t index_write__node(const struct index_node *node, FILE *out)
342 {
343 uint32_t *child_offs = NULL;
344 int child_count = 0;
345 long offset;
346
347 if (!node)
348 return 0;
349
350 /* Write children and save their offsets */
351 if (index__haschildren(node)) {
352 const struct index_node *child;
353 int i;
354
355 child_count = node->last - node->first + 1;
356 child_offs = NOFAIL(malloc(child_count * sizeof(uint32_t)));
357
358 for (i = 0; i < child_count; i++) {
359 child = node->children[node->first + i];
360 child_offs[i] = htonl(index_write__node(child, out));
361 }
362 }
363
364 /* Now write this node */
365 offset = ftell(out);
366
367 if (node->prefix[0]) {
368 fputs(node->prefix, out);
369 fputc('\0', out);
370 offset |= INDEX_NODE_PREFIX;
371 }
372
373 if (child_count) {
374 fputc(node->first, out);
375 fputc(node->last, out);
376 fwrite(child_offs, sizeof(uint32_t), child_count, out);
377 offset |= INDEX_NODE_CHILDS;
378 }
379
380 free(child_offs);
381
382 if (node->values) {
383 const struct index_value *v;
384 unsigned int value_count;
385 uint32_t u;
386
387 value_count = 0;
388 for (v = node->values; v != NULL; v = v->next)
389 value_count++;
390 u = htonl(value_count);
391 fwrite(&u, sizeof(u), 1, out);
392
393 for (v = node->values; v != NULL; v = v->next) {
394 u = htonl(v->priority);
395 fwrite(&u, sizeof(u), 1, out);
396 fputs(v->value, out);
397 fputc('\0', out);
398 }
399 offset |= INDEX_NODE_VALUES;
400 }
401
402 return offset;
403 }
404
405 static void index_write(const struct index_node *node, FILE *out)
406 {
407 long initial_offset, final_offset;
408 uint32_t u;
409
410 u = htonl(INDEX_MAGIC);
411 fwrite(&u, sizeof(u), 1, out);
412 u = htonl(INDEX_VERSION);
413 fwrite(&u, sizeof(u), 1, out);
414
415 /* Second word is reserved for the offset of the root node */
416 initial_offset = ftell(out);
417 assert(initial_offset >= 0);
418 u = 0;
419 fwrite(&u, sizeof(uint32_t), 1, out);
420
421 /* Dump trie */
422 u = htonl(index_write__node(node, out));
423
424 /* Update first word */
425 final_offset = ftell(out);
426 assert(final_offset >= 0);
427 (void)fseek(out, initial_offset, SEEK_SET);
428 fwrite(&u, sizeof(uint32_t), 1, out);
429 (void)fseek(out, final_offset, SEEK_SET);
430 }
431
432 /* END: code from module-init-tools/index.c just modified to compile here.
433 */
434
435 /* configuration parsing **********************************************/
436 struct cfg_override {
437 struct cfg_override *next;
438 size_t len;
439 char path[];
440 };
441
442 enum search_type {
443 SEARCH_PATH,
444 SEARCH_BUILTIN,
445 SEARCH_EXTERNAL
446 };
447
448 struct cfg_search {
449 struct cfg_search *next;
450 enum search_type type;
451 size_t len;
452 char path[];
453 };
454
455 struct cfg_external {
456 struct cfg_external *next;
457 size_t len;
458 char path[];
459 };
460
461 struct cfg {
462 const char *kversion;
463 char dirname[PATH_MAX];
464 size_t dirnamelen;
465 char sym_prefix;
466 uint8_t check_symvers;
467 uint8_t print_unknown;
468 uint8_t warn_dups;
469 struct cfg_override *overrides;
470 struct cfg_search *searches;
471 struct cfg_external *externals;
472 };
473
474 static enum search_type cfg_define_search_type(const char *path)
475 {
476 if (streq(path, CFG_BUILTIN_KEY))
477 return SEARCH_BUILTIN;
478 if (streq(path, CFG_EXTERNAL_KEY))
479 return SEARCH_EXTERNAL;
480 return SEARCH_PATH;
481 }
482
483 static int cfg_search_add(struct cfg *cfg, const char *path)
484 {
485 struct cfg_search *s;
486 size_t len;
487 enum search_type type;
488
489 type = cfg_define_search_type(path);
490
491 if (type != SEARCH_PATH)
492 len = 0;
493 else
494 len = strlen(path) + 1;
495
496 s = malloc(sizeof(struct cfg_search) + len);
497 if (s == NULL) {
498 ERR("search add: out of memory\n");
499 return -ENOMEM;
500 }
501 s->type = type;
502 if (type != SEARCH_PATH)
503 s->len = 0;
504 else {
505 s->len = len - 1;
506 memcpy(s->path, path, len);
507 }
508
509 DBG("search add: %s, search type=%hhu\n", path, type);
510
511 s->next = cfg->searches;
512 cfg->searches = s;
513 return 0;
514 }
515
516 static void cfg_search_free(struct cfg_search *s)
517 {
518 free(s);
519 }
520
521 static int cfg_override_add(struct cfg *cfg, const char *modname, const char *subdir)
522 {
523 struct cfg_override *o;
524 size_t modnamelen = strlen(modname);
525 size_t subdirlen = strlen(subdir);
526 size_t i;
527
528 o = malloc(sizeof(struct cfg_override) + subdirlen + 1
529 + modnamelen + 1);
530 if (o == NULL) {
531 ERR("override add: out of memory\n");
532 return -ENOMEM;
533 }
534 memcpy(o->path, subdir, subdirlen);
535 i = subdirlen;
536 o->path[i] = '/';
537 i++;
538
539 memcpy(o->path + i, modname, modnamelen);
540 i += modnamelen;
541 o->path[i] = '\0'; /* no extension, so we can match .ko/.ko.gz */
542
543 o->len = i;
544
545 DBG("override add: %s\n", o->path);
546
547 o->next = cfg->overrides;
548 cfg->overrides = o;
549 return 0;
550 }
551
552 static void cfg_override_free(struct cfg_override *o)
553 {
554 free(o);
555 }
556
557 static int cfg_external_add(struct cfg *cfg, const char *path)
558 {
559 struct cfg_external *ext;
560 size_t len = strlen(path);
561
562 ext = malloc(sizeof(struct cfg_external) + len + 1);
563 if (ext == NULL) {
564 ERR("external add: out of memory\n");
565 return -ENOMEM;
566 }
567
568 strcpy(ext->path, path);
569 ext->len = len;
570
571 DBG("external add: %s\n", ext->path);
572
573 ext->next = cfg->externals;
574 cfg->externals = ext;
575 return 0;
576 }
577
578 static void cfg_external_free(struct cfg_external *ext)
579 {
580 free(ext);
581 }
582
583 static int cfg_kernel_matches(const struct cfg *cfg, const char *pattern)
584 {
585 regex_t re;
586 int status;
587
588 /* old style */
589 if (streq(pattern, "*"))
590 return 1;
591
592 if (regcomp(&re, pattern, REG_EXTENDED|REG_NOSUB) != 0)
593 return 0;
594
595 status = regexec(&re, cfg->kversion, 0, NULL, 0);
596 regfree(&re);
597
598 return status == 0;
599 }
600
601 static int cfg_file_parse(struct cfg *cfg, const char *filename)
602 {
603 char *line;
604 FILE *fp;
605 unsigned int linenum = 0;
606 int err;
607
608 fp = fopen(filename, "r");
609 if (fp == NULL) {
610 err = -errno;
611 ERR("file parse %s: %m\n", filename);
612 return err;
613 }
614
615 while ((line = freadline_wrapped(fp, &linenum)) != NULL) {
616 char *cmd, *saveptr;
617
618 if (line[0] == '\0' || line[0] == '#')
619 goto done_next;
620
621 cmd = strtok_r(line, "\t ", &saveptr);
622 if (cmd == NULL)
623 goto done_next;
624
625 if (streq(cmd, "search")) {
626 const char *sp;
627 while ((sp = strtok_r(NULL, "\t ", &saveptr)) != NULL) {
628 cfg_search_add(cfg, sp);
629 }
630 } else if (streq(cmd, "override")) {
631 const char *modname = strtok_r(NULL, "\t ", &saveptr);
632 const char *version = strtok_r(NULL, "\t ", &saveptr);
633 const char *subdir = strtok_r(NULL, "\t ", &saveptr);
634
635 if (modname == NULL || version == NULL ||
636 subdir == NULL)
637 goto syntax_error;
638
639 if (!cfg_kernel_matches(cfg, version)) {
640 INF("%s:%u: override kernel did not match %s\n",
641 filename, linenum, version);
642 goto done_next;
643 }
644
645 cfg_override_add(cfg, modname, subdir);
646 } else if (streq(cmd, "external")) {
647 const char *version = strtok_r(NULL, "\t ", &saveptr);
648 const char *dir = strtok_r(NULL, "\t ", &saveptr);
649
650 if (version == NULL || dir == NULL)
651 goto syntax_error;
652
653 if (!cfg_kernel_matches(cfg, version)) {
654 INF("%s:%u: external directory did not match %s\n",
655 filename, linenum, version);
656 goto done_next;
657 }
658
659 cfg_external_add(cfg, dir);
660 } else if (streq(cmd, "include")
661 || streq(cmd, "make_map_files")) {
662 INF("%s:%u: command %s not implemented yet\n",
663 filename, linenum, cmd);
664 } else {
665 syntax_error:
666 ERR("%s:%u: ignoring bad line starting with '%s'\n",
667 filename, linenum, cmd);
668 }
669
670 done_next:
671 free(line);
672 }
673
674 fclose(fp);
675
676 return 0;
677 }
678
679 static int cfg_files_filter_out(DIR *d, const char *dir, const char *name)
680 {
681 size_t len = strlen(name);
682 struct stat st;
683
684 if (name[0] == '.')
685 return 1;
686
687 if (len < 6 || !streq(name + len - 5, ".conf")) {
688 INF("All cfg files need .conf: %s/%s\n", dir, name);
689 return 1;
690 }
691
692 fstatat(dirfd(d), name, &st, 0);
693 if (S_ISDIR(st.st_mode)) {
694 ERR("Directories inside directories are not supported: %s/%s\n",
695 dir, name);
696 return 1;
697 }
698
699 return 0;
700 }
701
702 struct cfg_file {
703 size_t dirlen;
704 size_t namelen;
705 const char *name;
706 char path[];
707 };
708
709 static void cfg_file_free(struct cfg_file *f)
710 {
711 free(f);
712 }
713
714 static int cfg_files_insert_sorted(struct cfg_file ***p_files, size_t *p_n_files,
715 const char *dir, const char *name)
716 {
717 struct cfg_file **files, *f;
718 size_t i, n_files, namelen, dirlen;
719 void *tmp;
720
721 dirlen = strlen(dir);
722 if (name != NULL)
723 namelen = strlen(name);
724 else {
725 name = basename(dir);
726 namelen = strlen(name);
727 dirlen -= namelen + 1;
728 }
729
730 n_files = *p_n_files;
731 files = *p_files;
732 for (i = 0; i < n_files; i++) {
733 int cmp = strcmp(name, files[i]->name);
734 if (cmp == 0) {
735 DBG("Ignoring duplicate config file: %.*s/%s\n",
736 (int)dirlen, dir, name);
737 return -EEXIST;
738 } else if (cmp < 0)
739 break;
740 }
741
742 f = malloc(sizeof(struct cfg_file) + dirlen + namelen + 2);
743 if (f == NULL) {
744 ERR("files insert sorted: out of memory\n");
745 return -ENOMEM;
746 }
747
748 tmp = realloc(files, sizeof(struct cfg_file *) * (n_files + 1));
749 if (tmp == NULL) {
750 ERR("files insert sorted: out of memory\n");
751 free(f);
752 return -ENOMEM;
753 }
754 *p_files = files = tmp;
755
756 if (i < n_files) {
757 memmove(files + i + 1, files + i,
758 sizeof(struct cfg_file *) * (n_files - i));
759 }
760 files[i] = f;
761
762 f->dirlen = dirlen;
763 f->namelen = namelen;
764 f->name = f->path + dirlen + 1;
765 memcpy(f->path, dir, dirlen);
766 f->path[dirlen] = '/';
767 memcpy(f->path + dirlen + 1, name, namelen);
768 f->path[dirlen + 1 + namelen] = '\0';
769
770 *p_n_files = n_files + 1;
771 return 0;
772 }
773
774 /*
775 * Insert configuration files ignoring duplicates
776 */
777 static int cfg_files_list(struct cfg_file ***p_files, size_t *p_n_files,
778 const char *path)
779 {
780 struct dirent *dent;
781 DIR *d;
782 int err = 0;
783 struct stat st;
784
785 if (stat(path, &st) != 0) {
786 err = -errno;
787 DBG("could not stat '%s': %m\n", path);
788 return err;
789 }
790
791 if (!S_ISDIR(st.st_mode)) {
792 cfg_files_insert_sorted(p_files, p_n_files, path, NULL);
793 return 0;
794 }
795
796 d = opendir(path);
797 if (d == NULL) {
798 ERR("files list %s: %m\n", path);
799 return -EINVAL;
800 }
801
802 for (dent = readdir(d); dent != NULL; dent = readdir(d)) {
803 if (cfg_files_filter_out(d, path, dent->d_name))
804 continue;
805
806 cfg_files_insert_sorted(p_files, p_n_files, path, dent->d_name);
807 }
808
809 closedir(d);
810 DBG("parsed configuration files from %s\n", path);
811 return err;
812 }
813
814 static int cfg_load(struct cfg *cfg, const char * const *cfg_paths)
815 {
816 size_t i, n_files = 0;
817 struct cfg_file **files = NULL;
818
819 if (cfg_paths == NULL)
820 cfg_paths = default_cfg_paths;
821
822 for (i = 0; cfg_paths[i] != NULL; i++)
823 cfg_files_list(&files, &n_files, cfg_paths[i]);
824
825 for (i = 0; i < n_files; i++) {
826 struct cfg_file *f = files[i];
827 cfg_file_parse(cfg, f->path);
828 cfg_file_free(f);
829 }
830 free(files);
831
832 /* For backward compatibility add "updates" to the head of the search
833 * list here. But only if there was no "search" option specified.
834 */
835 if (cfg->searches == NULL)
836 cfg_search_add(cfg, "updates");
837
838 return 0;
839 }
840
841 static void cfg_free(struct cfg *cfg)
842 {
843 while (cfg->overrides) {
844 struct cfg_override *tmp = cfg->overrides;
845 cfg->overrides = cfg->overrides->next;
846 cfg_override_free(tmp);
847 }
848
849 while (cfg->searches) {
850 struct cfg_search *tmp = cfg->searches;
851 cfg->searches = cfg->searches->next;
852 cfg_search_free(tmp);
853 }
854
855 while (cfg->externals) {
856 struct cfg_external *tmp = cfg->externals;
857 cfg->externals = cfg->externals->next;
858 cfg_external_free(tmp);
859 }
860 }
861
862
863 /* depmod calculations ***********************************************/
864 struct vertex;
865 struct mod {
866 struct kmod_module *kmod;
867 char *path;
868 const char *relpath; /* path relative to '$ROOT/lib/modules/$VER/' */
869 char *uncrelpath; /* same as relpath but ending in .ko */
870 struct kmod_list *info_list;
871 struct kmod_list *dep_sym_list;
872 struct array deps; /* struct symbol */
873 size_t baselen; /* points to start of basename/filename */
874 size_t modnamesz;
875 int sort_idx; /* sort index using modules.order */
876 int dep_sort_idx; /* topological sort index */
877 uint16_t idx; /* index in depmod->modules.array */
878 uint16_t users; /* how many modules depend on this one */
879 bool visited; /* helper field to report cycles */
880 struct vertex *vertex; /* helper field to report cycles */
881 char modname[];
882 };
883
884 struct symbol {
885 struct mod *owner;
886 uint64_t crc;
887 char name[];
888 };
889
890 struct depmod {
891 const struct cfg *cfg;
892 struct kmod_ctx *ctx;
893 struct array modules;
894 struct hash *modules_by_uncrelpath;
895 struct hash *modules_by_name;
896 struct hash *symbols;
897 };
898
899 static void mod_free(struct mod *mod)
900 {
901 DBG("free %p kmod=%p, path=%s\n", mod, mod->kmod, mod->path);
902 array_free_array(&mod->deps);
903 kmod_module_unref(mod->kmod);
904 kmod_module_info_free_list(mod->info_list);
905 kmod_module_dependency_symbols_free_list(mod->dep_sym_list);
906 free(mod->uncrelpath);
907 free(mod->path);
908 free(mod);
909 }
910
911 static int mod_add_dependency(struct mod *mod, struct symbol *sym)
912 {
913 int err;
914
915 DBG("%s depends on %s %s\n", mod->path, sym->name,
916 sym->owner != NULL ? sym->owner->path : "(unknown)");
917
918 if (sym->owner == NULL)
919 return 0;
920
921 err = array_append_unique(&mod->deps, sym->owner);
922 if (err == -EEXIST)
923 return 0;
924 if (err < 0)
925 return err;
926
927 sym->owner->users++;
928 SHOW("%s needs \"%s\": %s\n", mod->path, sym->name, sym->owner->path);
929 return 0;
930 }
931
932 static void symbol_free(struct symbol *sym)
933 {
934 DBG("free %p sym=%s, owner=%p %s\n", sym, sym->name, sym->owner,
935 sym->owner != NULL ? sym->owner->path : "");
936 free(sym);
937 }
938
939 static int depmod_init(struct depmod *depmod, struct cfg *cfg,
940 struct kmod_ctx *ctx)
941 {
942 int err = 0;
943
944 depmod->cfg = cfg;
945 depmod->ctx = ctx;
946
947 array_init(&depmod->modules, 128);
948
949 depmod->modules_by_uncrelpath = hash_new(512, NULL);
950 if (depmod->modules_by_uncrelpath == NULL) {
951 err = -errno;
952 goto modules_by_uncrelpath_failed;
953 }
954
955 depmod->modules_by_name = hash_new(512, NULL);
956 if (depmod->modules_by_name == NULL) {
957 err = -errno;
958 goto modules_by_name_failed;
959 }
960
961 depmod->symbols = hash_new(2048, (void (*)(void *))symbol_free);
962 if (depmod->symbols == NULL) {
963 err = -errno;
964 goto symbols_failed;
965 }
966
967 return 0;
968
969 symbols_failed:
970 hash_free(depmod->modules_by_name);
971 modules_by_name_failed:
972 hash_free(depmod->modules_by_uncrelpath);
973 modules_by_uncrelpath_failed:
974 return err;
975 }
976
977 static void depmod_shutdown(struct depmod *depmod)
978 {
979 size_t i;
980
981 hash_free(depmod->symbols);
982
983 hash_free(depmod->modules_by_uncrelpath);
984
985 hash_free(depmod->modules_by_name);
986
987 for (i = 0; i < depmod->modules.count; i++)
988 mod_free(depmod->modules.array[i]);
989 array_free_array(&depmod->modules);
990
991 kmod_unref(depmod->ctx);
992 }
993
994 static int depmod_module_add(struct depmod *depmod, struct kmod_module *kmod)
995 {
996 const struct cfg *cfg = depmod->cfg;
997 const char *modname, *lastslash;
998 size_t modnamesz;
999 struct mod *mod;
1000 int err;
1001
1002 modname = kmod_module_get_name(kmod);
1003 modnamesz = strlen(modname) + 1;
1004
1005 mod = calloc(1, sizeof(struct mod) + modnamesz);
1006 if (mod == NULL)
1007 return -ENOMEM;
1008 mod->kmod = kmod;
1009 mod->sort_idx = depmod->modules.count + 1;
1010 mod->dep_sort_idx = INT32_MAX;
1011 memcpy(mod->modname, modname, modnamesz);
1012 mod->modnamesz = modnamesz;
1013
1014 array_init(&mod->deps, 4);
1015
1016 mod->path = strdup(kmod_module_get_path(kmod));
1017 lastslash = strrchr(mod->path, '/');
1018 mod->baselen = lastslash - mod->path;
1019 if (strncmp(mod->path, cfg->dirname, cfg->dirnamelen) == 0 &&
1020 mod->path[cfg->dirnamelen] == '/')
1021 mod->relpath = mod->path + cfg->dirnamelen + 1;
1022 else
1023 mod->relpath = NULL;
1024
1025 err = hash_add_unique(depmod->modules_by_name, mod->modname, mod);
1026 if (err < 0) {
1027 ERR("hash_add_unique %s: %s\n", mod->modname, strerror(-err));
1028 goto fail;
1029 }
1030
1031 if (mod->relpath != NULL) {
1032 size_t uncrelpathlen = lastslash - mod->relpath + modnamesz
1033 + strlen(KMOD_EXTENSION_UNCOMPRESSED);
1034 mod->uncrelpath = memdup(mod->relpath, uncrelpathlen + 1);
1035 mod->uncrelpath[uncrelpathlen] = '\0';
1036 err = hash_add_unique(depmod->modules_by_uncrelpath,
1037 mod->uncrelpath, mod);
1038 if (err < 0) {
1039 ERR("hash_add_unique %s: %s\n",
1040 mod->uncrelpath, strerror(-err));
1041 hash_del(depmod->modules_by_name, mod->modname);
1042 goto fail;
1043 }
1044 }
1045
1046 DBG("add %p kmod=%p, path=%s\n", mod, kmod, mod->path);
1047
1048 return 0;
1049
1050 fail:
1051 free(mod->uncrelpath);
1052 free(mod);
1053 return err;
1054 }
1055
1056 static int depmod_module_del(struct depmod *depmod, struct mod *mod)
1057 {
1058 DBG("del %p kmod=%p, path=%s\n", mod, mod->kmod, mod->path);
1059
1060 if (mod->uncrelpath != NULL)
1061 hash_del(depmod->modules_by_uncrelpath, mod->uncrelpath);
1062
1063 hash_del(depmod->modules_by_name, mod->modname);
1064
1065 mod_free(mod);
1066 return 0;
1067 }
1068
1069 static const char *search_to_string(const struct cfg_search *s)
1070 {
1071 switch(s->type) {
1072 case SEARCH_EXTERNAL:
1073 return "external";
1074 case SEARCH_BUILTIN:
1075 return "built-in";
1076 default:
1077 return s->path;
1078 }
1079 }
1080
1081 static bool depmod_is_path_starts_with(const char *path,
1082 size_t pathlen,
1083 const char *prefix,
1084 size_t prefix_len)
1085 {
1086 if (pathlen <= prefix_len)
1087 return false;
1088 if (path[prefix_len] != '/')
1089 return false;
1090 if (memcmp(path, prefix, prefix_len) != 0)
1091 return false;
1092
1093 return true;
1094 }
1095
1096 /* returns if existing module @mod is higher priority than newpath.
1097 * note this is the inverse of module-init-tools is_higher_priority()
1098 */
1099 static int depmod_module_is_higher_priority(const struct depmod *depmod, const struct mod *mod, size_t baselen, size_t namelen, size_t modnamelen, const char *newpath)
1100 {
1101 const struct cfg *cfg = depmod->cfg;
1102 const struct cfg_override *ov;
1103 const struct cfg_search *se;
1104 const struct cfg_external *ext;
1105
1106 /* baselen includes the last '/' and mod->baselen doesn't. So it's
1107 * actually correct to use modnamelen in the first and modnamesz in
1108 * the latter */
1109 size_t newlen = baselen + modnamelen;
1110 size_t oldlen = mod->baselen + mod->modnamesz;
1111 const char *oldpath = mod->path;
1112 int i, bprio = -1, oldprio = -1, newprio = -1;
1113 size_t relnewlen = 0;
1114 size_t reloldlen = 0;
1115 const char *relnewpath = NULL;
1116 const char *reloldpath = NULL;
1117
1118 DBG("comparing priorities of %s and %s\n",
1119 oldpath, newpath);
1120
1121 if (strncmp(newpath, cfg->dirname, cfg->dirnamelen) == 0) {
1122 relnewpath = newpath + cfg->dirnamelen + 1;
1123 relnewlen = newlen - (cfg->dirnamelen + 1);
1124 }
1125 if (strncmp(oldpath, cfg->dirname, cfg->dirnamelen) == 0) {
1126 reloldpath = oldpath + cfg->dirnamelen + 1;
1127 reloldlen = oldlen - (cfg->dirnamelen + 1);
1128 }
1129
1130 for (ov = cfg->overrides; ov != NULL; ov = ov->next) {
1131 DBG("override %s\n", ov->path);
1132 if (relnewlen == ov->len &&
1133 memcmp(ov->path, relnewpath, relnewlen) == 0)
1134 return 0;
1135 if (reloldlen == ov->len &&
1136 memcmp(ov->path, reloldpath, reloldlen) == 0)
1137 return 1;
1138 }
1139
1140 for (i = 0, se = cfg->searches; se != NULL; se = se->next, i++) {
1141 DBG("search %s\n", search_to_string(se));
1142 if (se->type == SEARCH_BUILTIN)
1143 bprio = i;
1144 else if (se->type == SEARCH_EXTERNAL) {
1145 for (ext = cfg->externals; ext != NULL; ext = ext->next, i++) {
1146 if (depmod_is_path_starts_with(newpath,
1147 newlen,
1148 ext->path,
1149 ext->len))
1150 newprio = i;
1151 if (depmod_is_path_starts_with(oldpath,
1152 oldlen,
1153 ext->path,
1154 ext->len))
1155 oldprio = i;
1156 }
1157 } else if (relnewlen > se->len && relnewpath[se->len] == '/' &&
1158 memcmp(se->path, relnewpath, se->len) == 0)
1159 newprio = i;
1160 else if (reloldlen > se->len && reloldpath[se->len] == '/' &&
1161 memcmp(se->path, reloldpath, se->len) == 0)
1162 oldprio = i;
1163 }
1164
1165 if (newprio < 0)
1166 newprio = bprio;
1167 if (oldprio < 0)
1168 oldprio = bprio;
1169
1170 DBG("priorities: built-in: %d, old: %d, new: %d\n",
1171 bprio, oldprio, newprio);
1172
1173 return newprio <= oldprio;
1174 }
1175
1176 static int depmod_modules_search_file(struct depmod *depmod, size_t baselen, size_t namelen, const char *path)
1177 {
1178 struct kmod_module *kmod;
1179 struct mod *mod;
1180 const char *relpath;
1181 char modname[PATH_MAX];
1182 size_t modnamelen;
1183 int err;
1184
1185 if (!path_ends_with_kmod_ext(path + baselen, namelen))
1186 return 0;
1187
1188 if (path_to_modname(path, modname, &modnamelen) == NULL) {
1189 ERR("could not get modname from path %s\n", path);
1190 return -EINVAL;
1191 }
1192
1193 relpath = path + depmod->cfg->dirnamelen + 1;
1194 DBG("try %s (%s)\n", relpath, modname);
1195
1196 mod = hash_find(depmod->modules_by_name, modname);
1197 if (mod == NULL)
1198 goto add;
1199
1200 if (depmod_module_is_higher_priority(depmod, mod, baselen,
1201 namelen, modnamelen, path)) {
1202 DBG("Ignored lower priority: %s, higher: %s\n",
1203 path, mod->path);
1204 return 0;
1205 }
1206
1207 DBG("Replace lower priority %s with new module %s\n",
1208 mod->relpath, relpath);
1209 err = depmod_module_del(depmod, mod);
1210 if (err < 0) {
1211 ERR("could not del module %s: %s\n", mod->path, strerror(-err));
1212 return err;
1213 }
1214
1215 add:
1216 err = kmod_module_new_from_path(depmod->ctx, path, &kmod);
1217 if (err < 0) {
1218 ERR("could not create module %s: %s\n", path, strerror(-err));
1219 return err;
1220 }
1221
1222 err = depmod_module_add(depmod, kmod);
1223 if (err < 0) {
1224 ERR("could not add module %s: %s\n",
1225 path, strerror(-err));
1226 kmod_module_unref(kmod);
1227 return err;
1228 }
1229 return 0;
1230 }
1231
1232 static int depmod_modules_search_dir(struct depmod *depmod, DIR *d, size_t baselen, struct scratchbuf *s_path)
1233 {
1234 struct dirent *de;
1235 int err = 0, dfd = dirfd(d);
1236 char *path;
1237
1238 while ((de = readdir(d)) != NULL) {
1239 const char *name = de->d_name;
1240 size_t namelen;
1241 uint8_t is_dir;
1242
1243 if (name[0] == '.' && (name[1] == '\0' ||
1244 (name[1] == '.' && name[2] == '\0')))
1245 continue;
1246 if (streq(name, "build") || streq(name, "source"))
1247 continue;
1248 namelen = strlen(name);
1249 if (scratchbuf_alloc(s_path, baselen + namelen + 2) < 0) {
1250 err = -ENOMEM;
1251 ERR("No memory\n");
1252 continue;
1253 }
1254
1255 path = scratchbuf_str(s_path);
1256 memcpy(path + baselen, name, namelen + 1);
1257
1258 if (de->d_type == DT_REG)
1259 is_dir = 0;
1260 else if (de->d_type == DT_DIR)
1261 is_dir = 1;
1262 else {
1263 struct stat st;
1264 if (fstatat(dfd, name, &st, 0) < 0) {
1265 ERR("fstatat(%d, %s): %m\n", dfd, name);
1266 continue;
1267 } else if (S_ISREG(st.st_mode))
1268 is_dir = 0;
1269 else if (S_ISDIR(st.st_mode))
1270 is_dir = 1;
1271 else {
1272 ERR("unsupported file type %s: %o\n",
1273 path, st.st_mode & S_IFMT);
1274 continue;
1275 }
1276 }
1277
1278 if (is_dir) {
1279 int fd;
1280 DIR *subdir;
1281 fd = openat(dfd, name, O_RDONLY);
1282 if (fd < 0) {
1283 ERR("openat(%d, %s, O_RDONLY): %m\n",
1284 dfd, name);
1285 continue;
1286 }
1287 subdir = fdopendir(fd);
1288 if (subdir == NULL) {
1289 ERR("fdopendir(%d): %m\n", fd);
1290 close(fd);
1291 continue;
1292 }
1293 path[baselen + namelen] = '/';
1294 path[baselen + namelen + 1] = '\0';
1295 err = depmod_modules_search_dir(depmod, subdir,
1296 baselen + namelen + 1,
1297 s_path);
1298 closedir(subdir);
1299 } else {
1300 err = depmod_modules_search_file(depmod, baselen,
1301 namelen, path);
1302 }
1303
1304 if (err < 0) {
1305 path[baselen + namelen] = '\0';
1306 ERR("failed %s: %s\n", path, strerror(-err));
1307 err = 0; /* ignore errors */
1308 }
1309 }
1310 return err;
1311 }
1312
1313 static int depmod_modules_search_path(struct depmod *depmod,
1314 const char *path)
1315 {
1316 char buf[256];
1317 _cleanup_(scratchbuf_release) struct scratchbuf s_path_buf =
1318 SCRATCHBUF_INITIALIZER(buf);
1319 char *path_buf;
1320 DIR *d;
1321 size_t baselen;
1322 int err;
1323
1324 d = opendir(path);
1325 if (d == NULL) {
1326 err = -errno;
1327 ERR("could not open directory %s: %m\n", path);
1328 return err;
1329 }
1330
1331 baselen = strlen(path);
1332
1333 if (scratchbuf_alloc(&s_path_buf, baselen + 2) < 0) {
1334 err = -ENOMEM;
1335 goto out;
1336 }
1337 path_buf = scratchbuf_str(&s_path_buf);
1338
1339 memcpy(path_buf, path, baselen);
1340 path_buf[baselen] = '/';
1341 baselen++;
1342 path_buf[baselen] = '\0';
1343
1344 err = depmod_modules_search_dir(depmod, d, baselen, &s_path_buf);
1345 out:
1346 closedir(d);
1347 return err;
1348 }
1349
1350 static int depmod_modules_search(struct depmod *depmod)
1351 {
1352 int err;
1353 struct cfg_external *ext;
1354
1355 err = depmod_modules_search_path(depmod, depmod->cfg->dirname);
1356 if (err < 0)
1357 return err;
1358
1359 for (ext = depmod->cfg->externals; ext != NULL; ext = ext->next) {
1360 err = depmod_modules_search_path(depmod, ext->path);
1361 if (err < 0 && err == -ENOENT)
1362 /* ignore external dir absense */
1363 continue;
1364 }
1365
1366 return 0;
1367 }
1368
1369 static int mod_cmp(const void *pa, const void *pb) {
1370 const struct mod *a = *(const struct mod **)pa;
1371 const struct mod *b = *(const struct mod **)pb;
1372 return a->sort_idx - b->sort_idx;
1373 }
1374
1375 static int depmod_modules_build_array(struct depmod *depmod)
1376 {
1377 struct hash_iter module_iter;
1378 const void *v;
1379 int err;
1380
1381 hash_iter_init(depmod->modules_by_name, &module_iter);
1382 while (hash_iter_next(&module_iter, NULL, &v)) {
1383 struct mod *mod = (struct mod *) v;
1384 mod->idx = depmod->modules.count;
1385 err = array_append(&depmod->modules, mod);
1386 if (err < 0)
1387 return err;
1388 }
1389
1390 return 0;
1391 }
1392
1393 static FILE *dfdopen(const char *dname, const char *filename, int flags,
1394 const char *mode)
1395 {
1396 int fd, dfd;
1397 FILE *ret;
1398
1399 dfd = open(dname, O_RDONLY);
1400 if (dfd < 0) {
1401 WRN("could not open directory %s: %m\n", dname);
1402 return NULL;
1403 }
1404
1405 fd = openat(dfd, filename, flags);
1406 if (fd < 0) {
1407 WRN("could not open %s at %s: %m\n", filename, dname);
1408 ret = NULL;
1409 } else {
1410 ret = fdopen(fd, mode);
1411 if (!ret) {
1412 WRN("could not associate stream with %s: %m\n", filename);
1413 close(fd);
1414 }
1415 }
1416 close(dfd);
1417 return ret;
1418 }
1419
1420
1421
1422 static void depmod_modules_sort(struct depmod *depmod)
1423 {
1424 char line[PATH_MAX];
1425 const char *order_file = "modules.order";
1426 FILE *fp;
1427 unsigned idx = 0, total = 0;
1428
1429 fp = dfdopen(depmod->cfg->dirname, order_file, O_RDONLY, "r");
1430 if (fp == NULL)
1431 return;
1432
1433 while (fgets(line, sizeof(line), fp) != NULL) {
1434 size_t len = strlen(line);
1435 idx++;
1436 if (len == 0)
1437 continue;
1438 if (line[len - 1] != '\n') {
1439 ERR("%s/%s:%u corrupted line misses '\\n'\n",
1440 depmod->cfg->dirname, order_file, idx);
1441 goto corrupted;
1442 }
1443 }
1444 total = idx + 1;
1445 idx = 0;
1446 fseek(fp, 0, SEEK_SET);
1447 while (fgets(line, sizeof(line), fp) != NULL) {
1448 size_t len = strlen(line);
1449 struct mod *mod;
1450
1451 idx++;
1452 if (len == 0)
1453 continue;
1454 line[len - 1] = '\0';
1455
1456 mod = hash_find(depmod->modules_by_uncrelpath, line);
1457 if (mod == NULL)
1458 continue;
1459 mod->sort_idx = idx - total;
1460 }
1461
1462 array_sort(&depmod->modules, mod_cmp);
1463 for (idx = 0; idx < depmod->modules.count; idx++) {
1464 struct mod *m = depmod->modules.array[idx];
1465 m->idx = idx;
1466 }
1467
1468 corrupted:
1469 fclose(fp);
1470 }
1471
1472 static int depmod_symbol_add(struct depmod *depmod, const char *name,
1473 bool prefix_skipped, uint64_t crc,
1474 const struct mod *owner)
1475 {
1476 size_t namelen;
1477 int err;
1478 struct symbol *sym;
1479
1480 if (!prefix_skipped && (name[0] == depmod->cfg->sym_prefix))
1481 name++;
1482
1483 namelen = strlen(name) + 1;
1484 sym = malloc(sizeof(struct symbol) + namelen);
1485 if (sym == NULL)
1486 return -ENOMEM;
1487
1488 sym->owner = (struct mod *)owner;
1489 sym->crc = crc;
1490 memcpy(sym->name, name, namelen);
1491
1492 err = hash_add(depmod->symbols, sym->name, sym);
1493 if (err < 0) {
1494 free(sym);
1495 return err;
1496 }
1497
1498 DBG("add %p sym=%s, owner=%p %s\n", sym, sym->name, owner,
1499 owner != NULL ? owner->path : "");
1500
1501 return 0;
1502 }
1503
1504 static struct symbol *depmod_symbol_find(const struct depmod *depmod,
1505 const char *name)
1506 {
1507 if (name[0] == '.') /* PPC64 needs this: .foo == foo */
1508 name++;
1509 if (name[0] == depmod->cfg->sym_prefix)
1510 name++;
1511 return hash_find(depmod->symbols, name);
1512 }
1513
1514 static int depmod_load_modules(struct depmod *depmod)
1515 {
1516 struct mod **itr, **itr_end;
1517
1518 DBG("load symbols (%zd modules)\n", depmod->modules.count);
1519
1520 itr = (struct mod **)depmod->modules.array;
1521 itr_end = itr + depmod->modules.count;
1522 for (; itr < itr_end; itr++) {
1523 struct mod *mod = *itr;
1524 struct kmod_list *l, *list = NULL;
1525 int err = kmod_module_get_symbols(mod->kmod, &list);
1526 if (err < 0) {
1527 if (err == -ENOENT)
1528 DBG("ignoring %s: no symbols\n", mod->path);
1529 else
1530 ERR("failed to load symbols from %s: %s\n",
1531 mod->path, strerror(-err));
1532 goto load_info;
1533 }
1534 kmod_list_foreach(l, list) {
1535 const char *name = kmod_module_symbol_get_symbol(l);
1536 uint64_t crc = kmod_module_symbol_get_crc(l);
1537 depmod_symbol_add(depmod, name, false, crc, mod);
1538 }
1539 kmod_module_symbols_free_list(list);
1540
1541 load_info:
1542 kmod_module_get_info(mod->kmod, &mod->info_list);
1543 kmod_module_get_dependency_symbols(mod->kmod,
1544 &mod->dep_sym_list);
1545 kmod_module_unref(mod->kmod);
1546 mod->kmod = NULL;
1547 }
1548
1549 DBG("loaded symbols (%zd modules, %u symbols)\n",
1550 depmod->modules.count, hash_get_count(depmod->symbols));
1551
1552 return 0;
1553 }
1554
1555 static int depmod_load_module_dependencies(struct depmod *depmod, struct mod *mod)
1556 {
1557 const struct cfg *cfg = depmod->cfg;
1558 struct kmod_list *l;
1559
1560 DBG("do dependencies of %s\n", mod->path);
1561 kmod_list_foreach(l, mod->dep_sym_list) {
1562 const char *name = kmod_module_dependency_symbol_get_symbol(l);
1563 uint64_t crc = kmod_module_dependency_symbol_get_crc(l);
1564 int bindtype = kmod_module_dependency_symbol_get_bind(l);
1565 struct symbol *sym = depmod_symbol_find(depmod, name);
1566 uint8_t is_weak = bindtype == KMOD_SYMBOL_WEAK;
1567
1568 if (sym == NULL) {
1569 DBG("%s needs (%c) unknown symbol %s\n",
1570 mod->path, bindtype, name);
1571 if (cfg->print_unknown && !is_weak)
1572 WRN("%s needs unknown symbol %s\n",
1573 mod->path, name);
1574 continue;
1575 }
1576
1577 if (cfg->check_symvers && sym->crc != crc && !is_weak) {
1578 DBG("symbol %s (%#"PRIx64") module %s (%#"PRIx64")\n",
1579 sym->name, sym->crc, mod->path, crc);
1580 if (cfg->print_unknown)
1581 WRN("%s disagrees about version of symbol %s\n",
1582 mod->path, name);
1583 }
1584
1585 mod_add_dependency(mod, sym);
1586 }
1587
1588 return 0;
1589 }
1590
1591 static int depmod_load_dependencies(struct depmod *depmod)
1592 {
1593 struct mod **itr, **itr_end;
1594
1595 DBG("load dependencies (%zd modules, %u symbols)\n",
1596 depmod->modules.count, hash_get_count(depmod->symbols));
1597
1598 itr = (struct mod **)depmod->modules.array;
1599 itr_end = itr + depmod->modules.count;
1600 for (; itr < itr_end; itr++) {
1601 struct mod *mod = *itr;
1602
1603 if (mod->dep_sym_list == NULL) {
1604 DBG("ignoring %s: no dependency symbols\n", mod->path);
1605 continue;
1606 }
1607
1608 depmod_load_module_dependencies(depmod, mod);
1609 }
1610
1611 DBG("loaded dependencies (%zd modules, %u symbols)\n",
1612 depmod->modules.count, hash_get_count(depmod->symbols));
1613
1614 return 0;
1615 }
1616
1617 static int dep_cmp(const void *pa, const void *pb)
1618 {
1619 const struct mod *a = *(const struct mod **)pa;
1620 const struct mod *b = *(const struct mod **)pb;
1621 return a->dep_sort_idx - b->dep_sort_idx;
1622 }
1623
1624 static void depmod_sort_dependencies(struct depmod *depmod)
1625 {
1626 struct mod **itr, **itr_end;
1627 itr = (struct mod **)depmod->modules.array;
1628 itr_end = itr + depmod->modules.count;
1629 for (; itr < itr_end; itr++) {
1630 struct mod *m = *itr;
1631 if (m->deps.count > 1)
1632 array_sort(&m->deps, dep_cmp);
1633 }
1634 }
1635
1636 struct vertex {
1637 struct vertex *parent;
1638 struct mod *mod;
1639 };
1640
1641 static struct vertex *vertex_new(struct mod *mod, struct vertex *parent)
1642 {
1643 struct vertex *v;
1644
1645 v = malloc(sizeof(*v));
1646 if (v == NULL)
1647 return NULL;
1648
1649 v->parent = parent;
1650 v->mod = mod;
1651 return v;
1652 }
1653
1654 static void depmod_list_remove_data(struct kmod_list **list, void *data)
1655 {
1656 struct kmod_list *l;
1657
1658 l = kmod_list_remove_data(*list, data);
1659 *list = l;
1660 }
1661
1662 static int depmod_report_one_cycle(struct depmod *depmod,
1663 struct vertex *vertex,
1664 struct kmod_list **roots,
1665 struct hash *loop_set)
1666 {
1667 const char sep[] = " -> ";
1668 size_t sz;
1669 char *buf;
1670 struct array reverse;
1671 int i;
1672 int n;
1673 struct vertex *v;
1674 int rc;
1675
1676 array_init(&reverse, 3);
1677
1678 sz = 0;
1679 for (v = vertex->parent, n = 0;
1680 v != NULL;
1681 v = v->parent, n++) {
1682
1683 sz += v->mod->modnamesz - 1;
1684 array_append(&reverse, v);
1685 rc = hash_add(loop_set, v->mod->modname, NULL);
1686 if (rc != 0)
1687 return rc;
1688 /* the hash will be freed where created */
1689 }
1690 sz += vertex->mod->modnamesz - 1;
1691
1692 buf = malloc(sz + n * strlen(sep) + 1);
1693
1694 sz = 0;
1695 for (i = reverse.count - 1; i >= 0; i--) {
1696 size_t len;
1697
1698 v = reverse.array[i];
1699
1700 len = v->mod->modnamesz - 1;
1701 memcpy(buf + sz, v->mod->modname, len);
1702 sz += len;
1703 strcpy(buf + sz, sep);
1704 sz += strlen(sep);
1705
1706 depmod_list_remove_data(roots, v->mod);
1707 }
1708 strcpy(buf + sz, vertex->mod->modname);
1709 ERR("Cycle detected: %s\n", buf);
1710
1711 free(buf);
1712 array_free_array(&reverse);
1713
1714 return 0;
1715 }
1716
1717 static int depmod_report_cycles_from_root(struct depmod *depmod,
1718 struct mod *root_mod,
1719 struct kmod_list **roots,
1720 void **stack,
1721 size_t stack_size,
1722 struct hash *loop_set)
1723 {
1724 struct kmod_list *free_list = NULL; /* struct vertex */
1725 struct kmod_list *l;
1726 struct vertex *root;
1727 struct vertex *vertex;
1728 struct vertex *v;
1729 struct mod *m;
1730 struct mod **itr, **itr_end;
1731 size_t is;
1732 int ret = -ENOMEM;
1733
1734 root = vertex_new(root_mod, NULL);
1735 if (root == NULL) {
1736 ERR("No memory to report cycles\n");
1737 goto out;
1738 }
1739
1740 l = kmod_list_append(free_list, root);
1741 if (l == NULL) {
1742 ERR("No memory to report cycles\n");
1743 goto out;
1744 }
1745 free_list = l;
1746
1747 is = 0;
1748 stack[is++] = (void *)root;
1749
1750 while (is > 0) {
1751 vertex = stack[--is];
1752 m = vertex->mod;
1753 /*
1754 * because of the topological sort we can start only
1755 * from part of a loop or from a branch after a loop
1756 */
1757 if (m->visited && m == root->mod) {
1758 int rc;
1759 rc = depmod_report_one_cycle(depmod, vertex,
1760 roots, loop_set);
1761 if (rc != 0) {
1762 ret = rc;
1763 goto out;
1764 }
1765 continue;
1766 }
1767
1768 m->visited = true;
1769 if (m->deps.count == 0) {
1770 /*
1771 * boundary condition: if there is more than one
1772 * single node branch (not a loop), it is
1773 * recognized as a loop by the code above:
1774 * m->visited because more then one,
1775 * m == root->mod since it is a single node.
1776 * So, prevent deeping into the branch second
1777 * time.
1778 */
1779 depmod_list_remove_data(roots, m);
1780
1781 continue;
1782 }
1783
1784 itr = (struct mod **) m->deps.array;
1785 itr_end = itr + m->deps.count;
1786 for (; itr < itr_end; itr++) {
1787 struct mod *dep = *itr;
1788 v = vertex_new(dep, vertex);
1789 if (v == NULL) {
1790 ERR("No memory to report cycles\n");
1791 goto out;
1792 }
1793 assert(is < stack_size);
1794 stack[is++] = v;
1795
1796 l = kmod_list_append(free_list, v);
1797 if (l == NULL) {
1798 ERR("No memory to report cycles\n");
1799 goto out;
1800 }
1801 free_list = l;
1802
1803 }
1804 }
1805 ret = 0;
1806
1807 out:
1808 while (free_list) {
1809 v = free_list->data;
1810 l = kmod_list_remove(free_list);
1811 free_list = l;
1812 free(v);
1813 }
1814
1815 return ret;
1816 }
1817
1818 static void depmod_report_cycles(struct depmod *depmod, uint16_t n_mods,
1819 uint16_t *users)
1820 {
1821 int num_cyclic = 0;
1822 struct kmod_list *roots = NULL; /* struct mod */
1823 struct kmod_list *l;
1824 size_t n_r; /* local n_roots */
1825 int i;
1826 int err;
1827 _cleanup_free_ void **stack = NULL;
1828 struct mod *m;
1829 struct mod *root;
1830 struct hash *loop_set;
1831
1832 for (i = 0, n_r = 0; i < n_mods; i++) {
1833 if (users[i] <= 0)
1834 continue;
1835 m = depmod->modules.array[i];
1836 l = kmod_list_append(roots, m);
1837 if (l == NULL) {
1838 ERR("No memory to report cycles\n");
1839 goto out_list;
1840 }
1841 roots = l;
1842 n_r++;
1843 }
1844
1845 stack = malloc(n_r * sizeof(void *));
1846 if (stack == NULL) {
1847 ERR("No memory to report cycles\n");
1848 goto out_list;
1849 }
1850
1851 loop_set = hash_new(16, NULL);
1852 if (loop_set == NULL) {
1853 ERR("No memory to report cycles\n");
1854 goto out_list;
1855 }
1856
1857 while (roots != NULL) {
1858 root = roots->data;
1859 l = kmod_list_remove(roots);
1860 roots = l;
1861 err = depmod_report_cycles_from_root(depmod,
1862 root,
1863 &roots,
1864 stack, n_r, loop_set);
1865 if (err < 0)
1866 goto out_hash;
1867 }
1868
1869 num_cyclic = hash_get_count(loop_set);
1870 ERR("Found %d modules in dependency cycles!\n", num_cyclic);
1871
1872 out_hash:
1873 hash_free(loop_set);
1874 out_list:
1875 while (roots != NULL) {
1876 /* no need to free data, come from outside */
1877 roots = kmod_list_remove(roots);
1878 }
1879 }
1880
1881 static int depmod_calculate_dependencies(struct depmod *depmod)
1882 {
1883 const struct mod **itrm;
1884 uint16_t *users, *roots, *sorted;
1885 uint16_t i, n_roots = 0, n_sorted = 0, n_mods = depmod->modules.count;
1886 int ret = 0;
1887
1888 users = malloc(sizeof(uint16_t) * n_mods * 3);
1889 if (users == NULL)
1890 return -ENOMEM;
1891 roots = users + n_mods;
1892 sorted = roots + n_mods;
1893
1894 DBG("calculate dependencies and ordering (%hu modules)\n", n_mods);
1895
1896 assert(depmod->modules.count < UINT16_MAX);
1897
1898 /* populate modules users (how many modules uses it) */
1899 itrm = (const struct mod **)depmod->modules.array;
1900 for (i = 0; i < n_mods; i++, itrm++) {
1901 const struct mod *m = *itrm;
1902 users[i] = m->users;
1903 if (users[i] == 0) {
1904 roots[n_roots] = i;
1905 n_roots++;
1906 }
1907 }
1908
1909 /* topological sort (outputs modules without users first) */
1910 while (n_roots > 0) {
1911 const struct mod **itr_dst, **itr_dst_end;
1912 struct mod *src;
1913 uint16_t src_idx = roots[--n_roots];
1914
1915 src = depmod->modules.array[src_idx];
1916 src->dep_sort_idx = n_sorted;
1917 sorted[n_sorted] = src_idx;
1918 n_sorted++;
1919
1920 itr_dst = (const struct mod **)src->deps.array;
1921 itr_dst_end = itr_dst + src->deps.count;
1922 for (; itr_dst < itr_dst_end; itr_dst++) {
1923 const struct mod *dst = *itr_dst;
1924 uint16_t dst_idx = dst->idx;
1925 assert(users[dst_idx] > 0);
1926 users[dst_idx]--;
1927 if (users[dst_idx] == 0) {
1928 roots[n_roots] = dst_idx;
1929 n_roots++;
1930 }
1931 }
1932 }
1933
1934 if (n_sorted < n_mods) {
1935 depmod_report_cycles(depmod, n_mods, users);
1936 ret = -EINVAL;
1937 goto exit;
1938 }
1939
1940 depmod_sort_dependencies(depmod);
1941
1942 DBG("calculated dependencies and ordering (%hu modules)\n", n_mods);
1943
1944 exit:
1945 free(users);
1946 return ret;
1947 }
1948
1949 static int depmod_load(struct depmod *depmod)
1950 {
1951 int err;
1952
1953 err = depmod_load_modules(depmod);
1954 if (err < 0)
1955 return err;
1956
1957 err = depmod_load_dependencies(depmod);
1958 if (err < 0)
1959 return err;
1960
1961 err = depmod_calculate_dependencies(depmod);
1962 if (err < 0)
1963 return err;
1964
1965 return 0;
1966 }
1967
1968 static size_t mod_count_all_dependencies(const struct mod *mod)
1969 {
1970 size_t i, count = 0;
1971 for (i = 0; i < mod->deps.count; i++) {
1972 const struct mod *d = mod->deps.array[i];
1973 count += 1 + mod_count_all_dependencies(d);
1974 }
1975 return count;
1976 }
1977
1978 static int mod_fill_all_unique_dependencies(const struct mod *mod, const struct mod **deps, size_t n_deps, size_t *last)
1979 {
1980 size_t i;
1981 int err = 0;
1982 for (i = 0; i < mod->deps.count; i++) {
1983 const struct mod *d = mod->deps.array[i];
1984 size_t j;
1985 uint8_t exists = 0;
1986
1987 for (j = 0; j < *last; j++) {
1988 if (deps[j] == d) {
1989 exists = 1;
1990 break;
1991 }
1992 }
1993
1994 if (exists)
1995 continue;
1996
1997 if (*last >= n_deps)
1998 return -ENOSPC;
1999 deps[*last] = d;
2000 (*last)++;
2001 err = mod_fill_all_unique_dependencies(d, deps, n_deps, last);
2002 if (err < 0)
2003 break;
2004 }
2005 return err;
2006 }
2007
2008 static const struct mod **mod_get_all_sorted_dependencies(const struct mod *mod, size_t *n_deps)
2009 {
2010 const struct mod **deps;
2011 size_t last = 0;
2012
2013 *n_deps = mod_count_all_dependencies(mod);
2014 if (*n_deps == 0)
2015 return NULL;
2016
2017 deps = malloc(sizeof(struct mod *) * (*n_deps));
2018 if (deps == NULL)
2019 return NULL;
2020
2021 if (mod_fill_all_unique_dependencies(mod, deps, *n_deps, &last) < 0) {
2022 free(deps);
2023 return NULL;
2024 }
2025
2026 qsort(deps, last, sizeof(struct mod *), dep_cmp);
2027 *n_deps = last;
2028 return deps;
2029 }
2030
2031 static inline const char *mod_get_compressed_path(const struct mod *mod)
2032 {
2033 if (mod->relpath != NULL)
2034 return mod->relpath;
2035 return mod->path;
2036 }
2037
2038 static int output_deps(struct depmod *depmod, FILE *out)
2039 {
2040 size_t i;
2041
2042 for (i = 0; i < depmod->modules.count; i++) {
2043 const struct mod **deps, *mod = depmod->modules.array[i];
2044 const char *p = mod_get_compressed_path(mod);
2045 size_t j, n_deps;
2046
2047 fprintf(out, "%s:", p);
2048
2049 if (mod->deps.count == 0)
2050 goto end;
2051
2052 deps = mod_get_all_sorted_dependencies(mod, &n_deps);
2053 if (deps == NULL) {
2054 ERR("could not get all sorted dependencies of %s\n", p);
2055 goto end;
2056 }
2057
2058 for (j = 0; j < n_deps; j++) {
2059 const struct mod *d = deps[j];
2060 fprintf(out, " %s", mod_get_compressed_path(d));
2061 }
2062 free(deps);
2063 end:
2064 putc('\n', out);
2065 }
2066
2067 return 0;
2068 }
2069
2070 static int output_deps_bin(struct depmod *depmod, FILE *out)
2071 {
2072 struct index_node *idx;
2073 size_t i;
2074
2075 if (out == stdout)
2076 return 0;
2077
2078 idx = index_create();
2079 if (idx == NULL)
2080 return -ENOMEM;
2081
2082 for (i = 0; i < depmod->modules.count; i++) {
2083 const struct mod **deps, *mod = depmod->modules.array[i];
2084 const char *p = mod_get_compressed_path(mod);
2085 char *line;
2086 size_t j, n_deps, linepos, linelen, slen;
2087 int duplicate;
2088
2089 deps = mod_get_all_sorted_dependencies(mod, &n_deps);
2090 if (deps == NULL && n_deps > 0) {
2091 ERR("could not get all sorted dependencies of %s\n", p);
2092 continue;
2093 }
2094
2095 linelen = strlen(p) + 1;
2096 for (j = 0; j < n_deps; j++) {
2097 const struct mod *d = deps[j];
2098 linelen += 1 + strlen(mod_get_compressed_path(d));
2099 }
2100
2101 line = malloc(linelen + 1);
2102 if (line == NULL) {
2103 free(deps);
2104 ERR("modules.deps.bin: out of memory\n");
2105 continue;
2106 }
2107
2108 linepos = 0;
2109 slen = strlen(p);
2110 memcpy(line + linepos, p, slen);
2111 linepos += slen;
2112 line[linepos] = ':';
2113 linepos++;
2114
2115 for (j = 0; j < n_deps; j++) {
2116 const struct mod *d = deps[j];
2117 const char *dp;
2118
2119 line[linepos] = ' ';
2120 linepos++;
2121
2122 dp = mod_get_compressed_path(d);
2123 slen = strlen(dp);
2124 memcpy(line + linepos, dp, slen);
2125 linepos += slen;
2126 }
2127 line[linepos] = '\0';
2128
2129 duplicate = index_insert(idx, mod->modname, line, mod->idx);
2130 if (duplicate && depmod->cfg->warn_dups)
2131 WRN("duplicate module deps:\n%s\n", line);
2132 free(line);
2133 free(deps);
2134 }
2135
2136 index_write(idx, out);
2137 index_destroy(idx);
2138
2139 return 0;
2140 }
2141
2142 static int output_aliases(struct depmod *depmod, FILE *out)
2143 {
2144 size_t i;
2145
2146 fputs("# Aliases extracted from modules themselves.\n", out);
2147
2148 for (i = 0; i < depmod->modules.count; i++) {
2149 const struct mod *mod = depmod->modules.array[i];
2150 struct kmod_list *l;
2151
2152 kmod_list_foreach(l, mod->info_list) {
2153 const char *key = kmod_module_info_get_key(l);
2154 const char *value = kmod_module_info_get_value(l);
2155
2156 if (!streq(key, "alias"))
2157 continue;
2158
2159 fprintf(out, "alias %s %s\n", value, mod->modname);
2160 }
2161 }
2162
2163 return 0;
2164 }
2165
2166 static int output_aliases_bin(struct depmod *depmod, FILE *out)
2167 {
2168 struct index_node *idx;
2169 size_t i;
2170
2171 if (out == stdout)
2172 return 0;
2173
2174 idx = index_create();
2175 if (idx == NULL)
2176 return -ENOMEM;
2177
2178 for (i = 0; i < depmod->modules.count; i++) {
2179 const struct mod *mod = depmod->modules.array[i];
2180 struct kmod_list *l;
2181
2182 kmod_list_foreach(l, mod->info_list) {
2183 const char *key = kmod_module_info_get_key(l);
2184 const char *value = kmod_module_info_get_value(l);
2185 char buf[PATH_MAX];
2186 const char *alias;
2187 int duplicate;
2188
2189 if (!streq(key, "alias"))
2190 continue;
2191
2192 if (alias_normalize(value, buf, NULL) < 0) {
2193 WRN("Unmatched bracket in %s\n", value);
2194 continue;
2195 }
2196 alias = buf;
2197
2198 duplicate = index_insert(idx, alias, mod->modname,
2199 mod->idx);
2200 if (duplicate && depmod->cfg->warn_dups)
2201 WRN("duplicate module alias:\n%s %s\n",
2202 alias, mod->modname);
2203 }
2204 }
2205
2206 index_write(idx, out);
2207 index_destroy(idx);
2208
2209 return 0;
2210 }
2211
2212 static int output_softdeps(struct depmod *depmod, FILE *out)
2213 {
2214 size_t i;
2215
2216 fputs("# Soft dependencies extracted from modules themselves.\n", out);
2217
2218 for (i = 0; i < depmod->modules.count; i++) {
2219 const struct mod *mod = depmod->modules.array[i];
2220 struct kmod_list *l;
2221
2222 kmod_list_foreach(l, mod->info_list) {
2223 const char *key = kmod_module_info_get_key(l);
2224 const char *value = kmod_module_info_get_value(l);
2225
2226 if (!streq(key, "softdep"))
2227 continue;
2228
2229 fprintf(out, "softdep %s %s\n", mod->modname, value);
2230 }
2231 }
2232
2233 return 0;
2234 }
2235
2236 static int output_symbols(struct depmod *depmod, FILE *out)
2237 {
2238 struct hash_iter iter;
2239 const void *v;
2240
2241 fputs("# Aliases for symbols, used by symbol_request().\n", out);
2242
2243 hash_iter_init(depmod->symbols, &iter);
2244
2245 while (hash_iter_next(&iter, NULL, &v)) {
2246 const struct symbol *sym = v;
2247 if (sym->owner == NULL)
2248 continue;
2249
2250 fprintf(out, "alias symbol:%s %s\n",
2251 sym->name, sym->owner->modname);
2252 }
2253
2254 return 0;
2255 }
2256
2257 static int output_symbols_bin(struct depmod *depmod, FILE *out)
2258 {
2259 struct index_node *idx;
2260 char alias[1024];
2261 _cleanup_(scratchbuf_release) struct scratchbuf salias =
2262 SCRATCHBUF_INITIALIZER(alias);
2263 size_t baselen = sizeof("symbol:") - 1;
2264 struct hash_iter iter;
2265 const void *v;
2266 int ret = 0;
2267
2268 if (out == stdout)
2269 return 0;
2270
2271 idx = index_create();
2272 if (idx == NULL)
2273 return -ENOMEM;
2274
2275 memcpy(alias, "symbol:", baselen);
2276
2277 hash_iter_init(depmod->symbols, &iter);
2278
2279 while (hash_iter_next(&iter, NULL, &v)) {
2280 int duplicate;
2281 const struct symbol *sym = v;
2282 size_t len;
2283
2284 if (sym->owner == NULL)
2285 continue;
2286
2287 len = strlen(sym->name);
2288
2289 if (scratchbuf_alloc(&salias, baselen + len + 1) < 0) {
2290 ret = -ENOMEM;
2291 goto err_scratchbuf;
2292 }
2293 memcpy(scratchbuf_str(&salias) + baselen, sym->name, len + 1);
2294 duplicate = index_insert(idx, alias, sym->owner->modname,
2295 sym->owner->idx);
2296
2297 if (duplicate && depmod->cfg->warn_dups)
2298 WRN("duplicate module syms:\n%s %s\n",
2299 alias, sym->owner->modname);
2300 }
2301
2302 index_write(idx, out);
2303
2304 err_scratchbuf:
2305 index_destroy(idx);
2306
2307 if (ret < 0)
2308 ERR("output symbols: %s\n", strerror(-ret));
2309
2310 return ret;
2311 }
2312
2313 static int output_builtin_bin(struct depmod *depmod, FILE *out)
2314 {
2315 FILE *in;
2316 struct index_node *idx;
2317 char line[PATH_MAX], modname[PATH_MAX];
2318
2319 if (out == stdout)
2320 return 0;
2321
2322 in = dfdopen(depmod->cfg->dirname, "modules.builtin", O_RDONLY, "r");
2323 if (in == NULL)
2324 return 0;
2325
2326 idx = index_create();
2327 if (idx == NULL) {
2328 fclose(in);
2329 return -ENOMEM;
2330 }
2331
2332 while (fgets(line, sizeof(line), in) != NULL) {
2333 if (!isalpha(line[0])) {
2334 ERR("Invalid modules.builtin line: %s\n", line);
2335 continue;
2336 }
2337
2338 path_to_modname(line, modname, NULL);
2339 index_insert(idx, modname, "", 0);
2340 }
2341
2342 index_write(idx, out);
2343 index_destroy(idx);
2344 fclose(in);
2345
2346 return 0;
2347 }
2348
2349 static int flush_stream(FILE *in, int endchar)
2350 {
2351 size_t i = 0;
2352 int c;
2353
2354 for (c = fgetc(in);
2355 c != EOF && c != endchar && c != '\0';
2356 c = fgetc(in))
2357 ;
2358
2359 return c == endchar ? i : 0;
2360 }
2361
2362 static int flush_stream_to(FILE *in, int endchar, char *dst, size_t dst_sz)
2363 {
2364 size_t i = 0;
2365 int c;
2366
2367 for (c = fgetc(in);
2368 c != EOF && c != endchar && c != '\0' && i < dst_sz;
2369 c = fgetc(in))
2370 dst[i++] = c;
2371
2372 if (i == dst_sz) {
2373 WRN("Could not flush stream: %d. Partial content: %.*s\n",
2374 ENOSPC, (int) dst_sz, dst);
2375 }
2376
2377 return c == endchar ? i : 0;
2378 }
2379
2380 static int output_builtin_alias_bin(struct depmod *depmod, FILE *out)
2381 {
2382 FILE *in;
2383 struct index_node *idx;
2384 int ret;
2385
2386 if (out == stdout)
2387 return 0;
2388
2389 in = dfdopen(depmod->cfg->dirname, "modules.builtin.modinfo", O_RDONLY, "r");
2390 if (in == NULL)
2391 return 0;
2392
2393 idx = index_create();
2394 if (idx == NULL) {
2395 fclose(in);
2396 return -ENOMEM;
2397 }
2398
2399 /* format: modname.key=value\0 */
2400 while (!feof(in) && !ferror(in)) {
2401 char alias[PATH_MAX];
2402 char modname[PATH_MAX];
2403 char value[PATH_MAX];
2404 size_t len;
2405
2406 len = flush_stream_to(in, '.', modname, sizeof(modname));
2407 modname[len] = '\0';
2408 if (!len)
2409 continue;
2410
2411 len = flush_stream_to(in, '=', value, sizeof(value));
2412 value[len] = '\0';
2413 if (!streq(value, "alias")) {
2414 flush_stream(in, '\0');
2415 continue;
2416 }
2417
2418 len = flush_stream_to(in, '\0', value, sizeof(value));
2419 value[len] = '\0';
2420 if (!len)
2421 continue;
2422
2423 alias[0] = '\0';
2424 if (alias_normalize(value, alias, NULL) < 0) {
2425 WRN("Unmatched bracket in %s\n", value);
2426 continue;
2427 }
2428
2429 index_insert(idx, alias, modname, 0);
2430 }
2431
2432 if (ferror(in)) {
2433 ret = -EINVAL;
2434 } else {
2435 index_write(idx, out);
2436 ret = 0;
2437 }
2438
2439 index_destroy(idx);
2440 fclose(in);
2441
2442 return ret;
2443 }
2444
2445 static int output_devname(struct depmod *depmod, FILE *out)
2446 {
2447 size_t i;
2448 bool empty = true;
2449
2450 for (i = 0; i < depmod->modules.count; i++) {
2451 const struct mod *mod = depmod->modules.array[i];
2452 struct kmod_list *l;
2453 const char *devname = NULL;
2454 char type = '\0';
2455 unsigned int major = 0, minor = 0;
2456
2457 kmod_list_foreach(l, mod->info_list) {
2458 const char *key = kmod_module_info_get_key(l);
2459 const char *value = kmod_module_info_get_value(l);
2460 unsigned int maj, min;
2461
2462 if (!streq(key, "alias"))
2463 continue;
2464
2465 if (strstartswith(value, "devname:"))
2466 devname = value + sizeof("devname:") - 1;
2467 else if (sscanf(value, "char-major-%u-%u",
2468 &maj, &min) == 2) {
2469 type = 'c';
2470 major = maj;
2471 minor = min;
2472 } else if (sscanf(value, "block-major-%u-%u",
2473 &maj, &min) == 2) {
2474 type = 'b';
2475 major = maj;
2476 minor = min;
2477 }
2478
2479 if (type != '\0' && devname != NULL)
2480 break;
2481 }
2482
2483 if (devname != NULL) {
2484 if (type != '\0') {
2485 if (empty) {
2486 fputs("# Device nodes to trigger on-demand module loading.\n",
2487 out);
2488 empty = false;
2489 }
2490 fprintf(out, "%s %s %c%u:%u\n", mod->modname,
2491 devname, type, major, minor);
2492 } else
2493 ERR("Module '%s' has devname (%s) but "
2494 "lacks major and minor information. "
2495 "Ignoring.\n", mod->modname, devname);
2496 }
2497 }
2498
2499 return 0;
2500 }
2501
2502 static int depmod_output(struct depmod *depmod, FILE *out)
2503 {
2504 static const struct depfile {
2505 const char *name;
2506 int (*cb)(struct depmod *depmod, FILE *out);
2507 } *itr, depfiles[] = {
2508 { "modules.dep", output_deps },
2509 { "modules.dep.bin", output_deps_bin },
2510 { "modules.alias", output_aliases },
2511 { "modules.alias.bin", output_aliases_bin },
2512 { "modules.softdep", output_softdeps },
2513 { "modules.symbols", output_symbols },
2514 { "modules.symbols.bin", output_symbols_bin },
2515 { "modules.builtin.bin", output_builtin_bin },
2516 { "modules.builtin.alias.bin", output_builtin_alias_bin },
2517 { "modules.devname", output_devname },
2518 { }
2519 };
2520 const char *dname = depmod->cfg->dirname;
2521 int dfd, err = 0;
2522 struct timeval tv;
2523
2524 gettimeofday(&tv, NULL);
2525
2526 if (out != NULL)
2527 dfd = -1;
2528 else {
2529 dfd = open(dname, O_RDONLY);
2530 if (dfd < 0) {
2531 err = -errno;
2532 CRIT("could not open directory %s: %m\n", dname);
2533 return err;
2534 }
2535 }
2536
2537 for (itr = depfiles; itr->name != NULL; itr++) {
2538 FILE *fp = out;
2539 char tmp[NAME_MAX] = "";
2540 int r, ferr;
2541
2542 if (fp == NULL) {
2543 int flags = O_CREAT | O_EXCL | O_WRONLY;
2544 int mode = 0644;
2545 int fd;
2546
2547 snprintf(tmp, sizeof(tmp), "%s.%i.%li.%li", itr->name, getpid(),
2548 tv.tv_usec, tv.tv_sec);
2549 fd = openat(dfd, tmp, flags, mode);
2550 if (fd < 0) {
2551 ERR("openat(%s, %s, %o, %o): %m\n",
2552 dname, tmp, flags, mode);
2553 continue;
2554 }
2555 fp = fdopen(fd, "wb");
2556 if (fp == NULL) {
2557 ERR("fdopen(%d=%s/%s): %m\n", fd, dname, tmp);
2558 close(fd);
2559 continue;
2560 }
2561 }
2562
2563 r = itr->cb(depmod, fp);
2564 if (fp == out)
2565 continue;
2566
2567 ferr = ferror(fp) | fclose(fp);
2568
2569 if (r < 0) {
2570 if (unlinkat(dfd, tmp, 0) != 0)
2571 ERR("unlinkat(%s, %s): %m\n", dname, tmp);
2572
2573 ERR("Could not write index '%s': %s\n", itr->name,
2574 strerror(-r));
2575 err = -errno;
2576 break;
2577 }
2578
2579 if (renameat(dfd, tmp, dfd, itr->name) != 0) {
2580 err = -errno;
2581 CRIT("renameat(%s, %s, %s, %s): %m\n",
2582 dname, tmp, dname, itr->name);
2583 break;
2584 }
2585
2586 if (ferr) {
2587 err = -ENOSPC;
2588 ERR("Could not create index '%s'. Output is truncated: %s\n",
2589 itr->name, strerror(-err));
2590 break;
2591 }
2592 }
2593
2594 if (dfd >= 0)
2595 close(dfd);
2596
2597 return err;
2598 }
2599
2600 static void depmod_add_fake_syms(struct depmod *depmod)
2601 {
2602 /* __this_module is magic inserted by kernel loader. */
2603 depmod_symbol_add(depmod, "__this_module", true, 0, NULL);
2604 /* On S390, this is faked up too */
2605 depmod_symbol_add(depmod, "_GLOBAL_OFFSET_TABLE_", true, 0, NULL);
2606 /* On PowerPC64 ABIv2, .TOC. is more or less _GLOBAL_OFFSET_TABLE_ */
2607 if (!depmod_symbol_find(depmod, "TOC."))
2608 depmod_symbol_add(depmod, "TOC.", true, 0, NULL);
2609 }
2610
2611 static int depmod_load_symvers(struct depmod *depmod, const char *filename)
2612 {
2613 char line[10240];
2614 FILE *fp;
2615 unsigned int linenum = 0;
2616
2617 fp = fopen(filename, "r");
2618 if (fp == NULL) {
2619 int err = -errno;
2620 DBG("load symvers: %s: %m\n", filename);
2621 return err;
2622 }
2623 DBG("load symvers: %s\n", filename);
2624
2625 /* eg. "0xb352177e\tfind_first_bit\tvmlinux\tEXPORT_SYMBOL" */
2626 while (fgets(line, sizeof(line), fp) != NULL) {
2627 const char *ver, *sym, *where;
2628 char *verend;
2629 uint64_t crc;
2630
2631 linenum++;
2632
2633 ver = strtok(line, " \t");
2634 sym = strtok(NULL, " \t");
2635 where = strtok(NULL, " \t");
2636 if (!ver || !sym || !where)
2637 continue;
2638
2639 if (!streq(where, "vmlinux"))
2640 continue;
2641
2642 crc = strtoull(ver, &verend, 16);
2643 if (verend[0] != '\0') {
2644 ERR("%s:%u Invalid symbol version %s: %m\n",
2645 filename, linenum, ver);
2646 continue;
2647 }
2648
2649 depmod_symbol_add(depmod, sym, false, crc, NULL);
2650 }
2651 depmod_add_fake_syms(depmod);
2652
2653 DBG("loaded symvers: %s\n", filename);
2654
2655 fclose(fp);
2656 return 0;
2657 }
2658
2659 static int depmod_load_system_map(struct depmod *depmod, const char *filename)
2660 {
2661 const char ksymstr[] = "__ksymtab_";
2662 const size_t ksymstr_len = sizeof(ksymstr) - 1;
2663 char line[10240];
2664 FILE *fp;
2665 unsigned int linenum = 0;
2666
2667 fp = fopen(filename, "r");
2668 if (fp == NULL) {
2669 int err = -errno;
2670 DBG("load System.map: %s: %m\n", filename);
2671 return err;
2672 }
2673 DBG("load System.map: %s\n", filename);
2674
2675 /* eg. c0294200 R __ksymtab_devfs_alloc_devnum */
2676 while (fgets(line, sizeof(line), fp) != NULL) {
2677 char *p, *end;
2678
2679 linenum++;
2680
2681 p = strchr(line, ' ');
2682 if (p == NULL)
2683 goto invalid_syntax;
2684 p++;
2685 p = strchr(p, ' ');
2686 if (p == NULL)
2687 goto invalid_syntax;
2688 p++;
2689
2690 /* skip prefix */
2691 if (p[0] == depmod->cfg->sym_prefix)
2692 p++;
2693
2694 /* Covers gpl-only and normal symbols. */
2695 if (strncmp(p, ksymstr, ksymstr_len) != 0)
2696 continue;
2697
2698 end = strchr(p, '\n');
2699 if (end != NULL)
2700 *end = '\0';
2701
2702 depmod_symbol_add(depmod, p + ksymstr_len, true, 0, NULL);
2703 continue;
2704
2705 invalid_syntax:
2706 ERR("%s:%u: invalid line: %s\n", filename, linenum, line);
2707 }
2708 depmod_add_fake_syms(depmod);
2709
2710 DBG("loaded System.map: %s\n", filename);
2711
2712 fclose(fp);
2713 return 0;
2714 }
2715
2716
2717 static int depfile_up_to_date_dir(DIR *d, time_t mtime, size_t baselen, char *path)
2718 {
2719 struct dirent *de;
2720 int err = 1, dfd = dirfd(d);
2721
2722 while ((de = readdir(d)) != NULL) {
2723 const char *name = de->d_name;
2724 size_t namelen;
2725 struct stat st;
2726
2727 if (name[0] == '.' && (name[1] == '\0' ||
2728 (name[1] == '.' && name[2] == '\0')))
2729 continue;
2730 if (streq(name, "build") || streq(name, "source"))
2731 continue;
2732 namelen = strlen(name);
2733 if (baselen + namelen + 2 >= PATH_MAX) {
2734 path[baselen] = '\0';
2735 ERR("path is too long %s%s\n", path, name);
2736 continue;
2737 }
2738
2739 if (fstatat(dfd, name, &st, 0) < 0) {
2740 ERR("fstatat(%d, %s): %m\n", dfd, name);
2741 continue;
2742 }
2743
2744 if (S_ISDIR(st.st_mode)) {
2745 int fd;
2746 DIR *subdir;
2747 memcpy(path + baselen, name, namelen + 1);
2748 if (baselen + namelen + 2 + NAME_MAX >= PATH_MAX) {
2749 ERR("directory path is too long %s\n", path);
2750 continue;
2751 }
2752 fd = openat(dfd, name, O_RDONLY);
2753 if (fd < 0) {
2754 ERR("openat(%d, %s, O_RDONLY): %m\n",
2755 dfd, name);
2756 continue;
2757 }
2758 subdir = fdopendir(fd);
2759 if (subdir == NULL) {
2760 ERR("fdopendir(%d): %m\n", fd);
2761 close(fd);
2762 continue;
2763 }
2764 path[baselen + namelen] = '/';
2765 path[baselen + namelen + 1] = '\0';
2766 err = depfile_up_to_date_dir(subdir, mtime,
2767 baselen + namelen + 1,
2768 path);
2769 closedir(subdir);
2770 } else if (S_ISREG(st.st_mode)) {
2771 if (!path_ends_with_kmod_ext(name, namelen))
2772 continue;
2773
2774 memcpy(path + baselen, name, namelen + 1);
2775 err = st.st_mtime <= mtime;
2776 if (err == 0) {
2777 DBG("%s %"PRIu64" is newer than %"PRIu64"\n",
2778 path, (uint64_t)st.st_mtime,
2779 (uint64_t)mtime);
2780 }
2781 } else {
2782 ERR("unsupported file type %s: %o\n",
2783 path, st.st_mode & S_IFMT);
2784 continue;
2785 }
2786
2787 if (err == 0)
2788 break; /* outdated! */
2789 else if (err < 0) {
2790 path[baselen + namelen] = '\0';
2791 ERR("failed %s: %s\n", path, strerror(-err));
2792 err = 1; /* ignore errors */
2793 }
2794 }
2795
2796 return err;
2797 }
2798
2799 /* uptodate: 1, outdated: 0, errors < 0 */
2800 static int depfile_up_to_date(const char *dirname)
2801 {
2802 char path[PATH_MAX];
2803 DIR *d = opendir(dirname);
2804 struct stat st;
2805 size_t baselen;
2806 int err;
2807 if (d == NULL) {
2808 err = -errno;
2809 ERR("could not open directory %s: %m\n", dirname);
2810 return err;
2811 }
2812
2813 if (fstatat(dirfd(d), "modules.dep", &st, 0) != 0) {
2814 err = -errno;
2815 ERR("could not fstatat(%s, modules.dep): %m\n", dirname);
2816 closedir(d);
2817 return err;
2818 }
2819
2820 baselen = strlen(dirname);
2821 memcpy(path, dirname, baselen);
2822 path[baselen] = '/';
2823 baselen++;
2824 path[baselen] = '\0';
2825
2826 err = depfile_up_to_date_dir(d, st.st_mtime, baselen, path);
2827 closedir(d);
2828 return err;
2829 }
2830
2831 static int is_version_number(const char *version)
2832 {
2833 unsigned int d1, d2;
2834 return (sscanf(version, "%u.%u", &d1, &d2) == 2);
2835 }
2836
2837 static int do_depmod(int argc, char *argv[])
2838 {
2839 FILE *out = NULL;
2840 int err = 0, all = 0, maybe_all = 0, n_config_paths = 0;
2841 _cleanup_free_ char *root = NULL;
2842 _cleanup_free_ const char **config_paths = NULL;
2843 const char *system_map = NULL;
2844 const char *module_symvers = NULL;
2845 const char *null_kmod_config = NULL;
2846 struct utsname un;
2847 struct kmod_ctx *ctx = NULL;
2848 struct cfg cfg;
2849 struct depmod depmod;
2850
2851 memset(&cfg, 0, sizeof(cfg));
2852 memset(&depmod, 0, sizeof(depmod));
2853
2854 for (;;) {
2855 int c, idx = 0;
2856 c = getopt_long(argc, argv, cmdopts_s, cmdopts, &idx);
2857 if (c == -1)
2858 break;
2859 switch (c) {
2860 case 'a':
2861 all = 1;
2862 break;
2863 case 'A':
2864 maybe_all = 1;
2865 break;
2866 case 'b':
2867 if (root)
2868 free(root);
2869 root = path_make_absolute_cwd(optarg);
2870 break;
2871 case 'C': {
2872 size_t bytes = sizeof(char *) * (n_config_paths + 2);
2873 void *tmp = realloc(config_paths, bytes);
2874 if (!tmp) {
2875 fputs("Error: out-of-memory\n", stderr);
2876 goto cmdline_failed;
2877 }
2878 config_paths = tmp;
2879 config_paths[n_config_paths] = optarg;
2880 n_config_paths++;
2881 config_paths[n_config_paths] = NULL;
2882 break;
2883 }
2884 case 'E':
2885 module_symvers = optarg;
2886 cfg.check_symvers = 1;
2887 break;
2888 case 'F':
2889 system_map = optarg;
2890 break;
2891 case 'e':
2892 cfg.print_unknown = 1;
2893 break;
2894 case 'v':
2895 verbose++;
2896 break;
2897 case 'n':
2898 out = stdout;
2899 break;
2900 case 'P':
2901 if (optarg[1] != '\0') {
2902 CRIT("-P only takes a single char\n");
2903 goto cmdline_failed;
2904 }
2905 cfg.sym_prefix = optarg[0];
2906 break;
2907 case 'w':
2908 cfg.warn_dups = 1;
2909 break;
2910 case 'u':
2911 case 'q':
2912 case 'r':
2913 case 'm':
2914 if (idx > 0)
2915 WRN("Ignored deprecated option --%s\n",
2916 cmdopts[idx].name);
2917 else
2918 WRN("Ignored deprecated option -%c\n", c);
2919
2920 break;
2921 case 'h':
2922 help();
2923 return EXIT_SUCCESS;
2924 case 'V':
2925 puts(PACKAGE " version " VERSION);
2926 puts(KMOD_FEATURES);
2927 return EXIT_SUCCESS;
2928 case '?':
2929 goto cmdline_failed;
2930 default:
2931 ERR("unexpected getopt_long() value '%c'.\n", c);
2932 goto cmdline_failed;
2933 }
2934 }
2935
2936 if (optind < argc) {
2937 if (!is_version_number(argv[optind])) {
2938 ERR("Bad version passed %s\n", argv[optind]);
2939 goto cmdline_failed;
2940 }
2941 cfg.kversion = argv[optind];
2942 optind++;
2943 } else {
2944 if (uname(&un) < 0) {
2945 CRIT("uname() failed: %s\n", strerror(errno));
2946 goto cmdline_failed;
2947 }
2948 cfg.kversion = un.release;
2949 }
2950
2951 cfg.dirnamelen = snprintf(cfg.dirname, PATH_MAX,
2952 "%s/lib/modules/%s",
2953 root == NULL ? "" : root, cfg.kversion);
2954
2955 if (optind == argc)
2956 all = 1;
2957
2958 if (maybe_all) {
2959 if (out == stdout)
2960 goto done;
2961 /* ignore up-to-date errors (< 0) */
2962 if (depfile_up_to_date(cfg.dirname) == 1)
2963 goto done;
2964 all = 1;
2965 }
2966
2967 ctx = kmod_new(cfg.dirname, &null_kmod_config);
2968 if (ctx == NULL) {
2969 CRIT("kmod_new(\"%s\", {NULL}) failed: %m\n", cfg.dirname);
2970 goto cmdline_failed;
2971 }
2972
2973 log_setup_kmod_log(ctx, verbose);
2974
2975 err = depmod_init(&depmod, &cfg, ctx);
2976 if (err < 0) {
2977 CRIT("depmod_init: %s\n", strerror(-err));
2978 goto depmod_init_failed;
2979 }
2980 ctx = NULL; /* owned by depmod */
2981
2982 if (module_symvers != NULL) {
2983 err = depmod_load_symvers(&depmod, module_symvers);
2984 if (err < 0) {
2985 CRIT("could not load %s: %s\n", module_symvers,
2986 strerror(-err));
2987 goto cmdline_failed;
2988 }
2989 } else if (system_map != NULL) {
2990 err = depmod_load_system_map(&depmod, system_map);
2991 if (err < 0) {
2992 CRIT("could not load %s: %s\n", system_map,
2993 strerror(-err));
2994 goto cmdline_failed;
2995 }
2996 } else if (cfg.print_unknown) {
2997 WRN("-e needs -E or -F\n");
2998 cfg.print_unknown = 0;
2999 }
3000
3001 if (all) {
3002 err = cfg_load(&cfg, config_paths);
3003 if (err < 0) {
3004 CRIT("could not load configuration files\n");
3005 goto cmdline_modules_failed;
3006 }
3007 err = depmod_modules_search(&depmod);
3008 if (err < 0) {
3009 CRIT("could not search modules: %s\n", strerror(-err));
3010 goto cmdline_modules_failed;
3011 }
3012 } else {
3013 int i;
3014
3015 for (i = optind; i < argc; i++) {
3016 const char *path = argv[i];
3017 struct kmod_module *mod;
3018
3019 if (path[0] != '/') {
3020 CRIT("%s: not absolute path.\n", path);
3021 goto cmdline_modules_failed;
3022 }
3023
3024 err = kmod_module_new_from_path(depmod.ctx, path, &mod);
3025 if (err < 0) {
3026 CRIT("could not create module %s: %s\n",
3027 path, strerror(-err));
3028 goto cmdline_modules_failed;
3029 }
3030
3031 err = depmod_module_add(&depmod, mod);
3032 if (err < 0) {
3033 CRIT("could not add module %s: %s\n",
3034 path, strerror(-err));
3035 kmod_module_unref(mod);
3036 goto cmdline_modules_failed;
3037 }
3038 }
3039 }
3040
3041 err = depmod_modules_build_array(&depmod);
3042 if (err < 0) {
3043 CRIT("could not build module array: %s\n",
3044 strerror(-err));
3045 goto cmdline_modules_failed;
3046 }
3047
3048 depmod_modules_sort(&depmod);
3049 err = depmod_load(&depmod);
3050 if (err < 0)
3051 goto cmdline_modules_failed;
3052
3053 err = depmod_output(&depmod, out);
3054
3055 done:
3056 depmod_shutdown(&depmod);
3057 cfg_free(&cfg);
3058 return err >= 0 ? EXIT_SUCCESS : EXIT_FAILURE;
3059
3060 cmdline_modules_failed:
3061 depmod_shutdown(&depmod);
3062 depmod_init_failed:
3063 if (ctx != NULL)
3064 kmod_unref(ctx);
3065 cmdline_failed:
3066 cfg_free(&cfg);
3067 return EXIT_FAILURE;
3068 }
3069
3070 const struct kmod_cmd kmod_cmd_compat_depmod = {
3071 .name = "depmod",
3072 .cmd = do_depmod,
3073 .help = "compat depmod command",
3074 };