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