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