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