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