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