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