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