]> git.ipfire.org Git - thirdparty/kmod.git/blame - tools/depmod.c
depmod: Stop opening modules.modinfo once per module
[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
0246e063
LDM
2349static int flush_stream(FILE *in, int endchar)
2350{
2351 size_t i = 0;
2352 int c;
2353
2354 for (c = fgetc(in);
2355 c != EOF && c != endchar && c != '\0';
2356 c = fgetc(in))
2357 ;
2358
2359 return c == endchar ? i : 0;
2360}
2361
2362static int flush_stream_to(FILE *in, int endchar, char *dst, size_t dst_sz)
2363{
2364 size_t i = 0;
2365 int c;
2366
2367 for (c = fgetc(in);
2368 c != EOF && c != endchar && c != '\0' && i < dst_sz;
2369 c = fgetc(in))
2370 dst[i++] = c;
2371
2372 if (i == dst_sz) {
2373 WRN("Could not flush stream: %d. Partial content: %.*s\n",
2374 ENOSPC, (int) dst_sz, dst);
2375 }
2376
2377 return c == endchar ? i : 0;
2378}
2379
2380static int output_builtin_alias_bin(struct depmod *depmod, FILE *out)
2381{
2382 FILE *in;
2383 struct index_node *idx;
2384 int ret;
2385
2386 if (out == stdout)
2387 return 0;
2388
2389 in = dfdopen(depmod->cfg->dirname, "modules.builtin.modinfo", O_RDONLY, "r");
2390 if (in == NULL)
2391 return 0;
2392
2393 idx = index_create();
2394 if (idx == NULL) {
2395 fclose(in);
2396 return -ENOMEM;
2397 }
2398
2399 /* format: modname.key=value\0 */
2400 while (!feof(in) && !ferror(in)) {
2401 char alias[PATH_MAX];
2402 char modname[PATH_MAX];
2403 char value[PATH_MAX];
2404 size_t len;
2405
2406 len = flush_stream_to(in, '.', modname, sizeof(modname));
2407 modname[len] = '\0';
2408 if (!len)
2409 continue;
2410
2411 len = flush_stream_to(in, '=', value, sizeof(value));
2412 value[len] = '\0';
2413 if (!streq(value, "alias")) {
2414 flush_stream(in, '\0');
2415 continue;
2416 }
2417
2418 len = flush_stream_to(in, '\0', value, sizeof(value));
2419 value[len] = '\0';
2420 if (!len)
2421 continue;
2422
2423 alias[0] = '\0';
2424 if (alias_normalize(value, alias, NULL) < 0) {
2425 WRN("Unmatched bracket in %s\n", value);
2426 continue;
2427 }
2428
2429 index_insert(idx, alias, modname, 0);
2430 }
2431
2432 if (ferror(in)) {
2433 ret = -EINVAL;
2434 } else {
2435 index_write(idx, out);
2436 ret = 0;
2437 }
2438
2439 index_destroy(idx);
2440 fclose(in);
2441
2442 return ret;
2443}
2444
25c41512
GSB
2445static int output_devname(struct depmod *depmod, FILE *out)
2446{
2447 size_t i;
4c30a11d 2448 bool empty = true;
25c41512
GSB
2449
2450 for (i = 0; i < depmod->modules.count; i++) {
2451 const struct mod *mod = depmod->modules.array[i];
7062eca3 2452 struct kmod_list *l;
25c41512
GSB
2453 const char *devname = NULL;
2454 char type = '\0';
2455 unsigned int major = 0, minor = 0;
25c41512 2456
7062eca3 2457 kmod_list_foreach(l, mod->info_list) {
25c41512
GSB
2458 const char *key = kmod_module_info_get_key(l);
2459 const char *value = kmod_module_info_get_value(l);
2460 unsigned int maj, min;
2461
2462 if (!streq(key, "alias"))
2463 continue;
2464
2465 if (strstartswith(value, "devname:"))
2466 devname = value + sizeof("devname:") - 1;
2467 else if (sscanf(value, "char-major-%u-%u",
2468 &maj, &min) == 2) {
2469 type = 'c';
2470 major = maj;
2471 minor = min;
2472 } else if (sscanf(value, "block-major-%u-%u",
2473 &maj, &min) == 2) {
2474 type = 'b';
2475 major = maj;
2476 minor = min;
2477 }
2478
6506ddf5
TG
2479 if (type != '\0' && devname != NULL)
2480 break;
2481 }
2482
2483 if (devname != NULL) {
4c30a11d
JT
2484 if (type != '\0') {
2485 if (empty) {
2486 fputs("# Device nodes to trigger on-demand module loading.\n",
2487 out);
2488 empty = false;
2489 }
447eed8c 2490 fprintf(out, "%s %s %c%u:%u\n", mod->modname,
25c41512 2491 devname, type, major, minor);
4c30a11d 2492 } else
6506ddf5
TG
2493 ERR("Module '%s' has devname (%s) but "
2494 "lacks major and minor information. "
2495 "Ignoring.\n", mod->modname, devname);
25c41512 2496 }
25c41512
GSB
2497 }
2498
2499 return 0;
2500}
2501
2502static int depmod_output(struct depmod *depmod, FILE *out)
2503{
2504 static const struct depfile {
2505 const char *name;
2506 int (*cb)(struct depmod *depmod, FILE *out);
2507 } *itr, depfiles[] = {
015946da
LDM
2508 { "modules.dep", output_deps },
2509 { "modules.dep.bin", output_deps_bin },
2510 { "modules.alias", output_aliases },
2511 { "modules.alias.bin", output_aliases_bin },
2512 { "modules.softdep", output_softdeps },
2513 { "modules.symbols", output_symbols },
2514 { "modules.symbols.bin", output_symbols_bin },
2515 { "modules.builtin.bin", output_builtin_bin },
b866b216 2516 { "modules.builtin.alias.bin", output_builtin_alias_bin },
015946da
LDM
2517 { "modules.devname", output_devname },
2518 { }
25c41512
GSB
2519 };
2520 const char *dname = depmod->cfg->dirname;
2521 int dfd, err = 0;
a06bacf5
MS
2522 struct timeval tv;
2523
2524 gettimeofday(&tv, NULL);
25c41512
GSB
2525
2526 if (out != NULL)
2527 dfd = -1;
2528 else {
2529 dfd = open(dname, O_RDONLY);
2530 if (dfd < 0) {
2531 err = -errno;
63698377 2532 CRIT("could not open directory %s: %m\n", dname);
25c41512
GSB
2533 return err;
2534 }
2535 }
2536
2537 for (itr = depfiles; itr->name != NULL; itr++) {
2538 FILE *fp = out;
2539 char tmp[NAME_MAX] = "";
3f376cd8 2540 int r, ferr;
25c41512
GSB
2541
2542 if (fp == NULL) {
a06bacf5 2543 int flags = O_CREAT | O_EXCL | O_WRONLY;
25c41512
GSB
2544 int mode = 0644;
2545 int fd;
2546
a06bacf5
MS
2547 snprintf(tmp, sizeof(tmp), "%s.%i.%li.%li", itr->name, getpid(),
2548 tv.tv_usec, tv.tv_sec);
25c41512
GSB
2549 fd = openat(dfd, tmp, flags, mode);
2550 if (fd < 0) {
2551 ERR("openat(%s, %s, %o, %o): %m\n",
2552 dname, tmp, flags, mode);
2553 continue;
2554 }
2555 fp = fdopen(fd, "wb");
2556 if (fp == NULL) {
2557 ERR("fdopen(%d=%s/%s): %m\n", fd, dname, tmp);
2558 close(fd);
2559 continue;
2560 }
2561 }
2562
2563 r = itr->cb(depmod, fp);
2564 if (fp == out)
2565 continue;
2566
3f376cd8
LDM
2567 ferr = ferror(fp) | fclose(fp);
2568
25c41512
GSB
2569 if (r < 0) {
2570 if (unlinkat(dfd, tmp, 0) != 0)
2571 ERR("unlinkat(%s, %s): %m\n", dname, tmp);
80e49ad9
LDM
2572
2573 ERR("Could not write index '%s': %s\n", itr->name,
2574 strerror(-r));
2575 err = -errno;
2576 break;
2577 }
2578
80e49ad9
LDM
2579 if (renameat(dfd, tmp, dfd, itr->name) != 0) {
2580 err = -errno;
2581 CRIT("renameat(%s, %s, %s, %s): %m\n",
2582 dname, tmp, dname, itr->name);
2583 break;
25c41512 2584 }
a4fb97a7 2585
3f376cd8 2586 if (ferr) {
a4fb97a7 2587 err = -ENOSPC;
3f376cd8
LDM
2588 ERR("Could not create index '%s'. Output is truncated: %s\n",
2589 itr->name, strerror(-err));
a4fb97a7
LDM
2590 break;
2591 }
25c41512
GSB
2592 }
2593
2594 if (dfd >= 0)
2595 close(dfd);
80e49ad9 2596
25c41512
GSB
2597 return err;
2598}
2599
4a0e46da
GSB
2600static void depmod_add_fake_syms(struct depmod *depmod)
2601{
2602 /* __this_module is magic inserted by kernel loader. */
572a2711 2603 depmod_symbol_add(depmod, "__this_module", true, 0, NULL);
4a0e46da 2604 /* On S390, this is faked up too */
572a2711 2605 depmod_symbol_add(depmod, "_GLOBAL_OFFSET_TABLE_", true, 0, NULL);
d46136bb 2606 /* On PowerPC64 ABIv2, .TOC. is more or less _GLOBAL_OFFSET_TABLE_ */
e22e1c1f
MS
2607 if (!depmod_symbol_find(depmod, "TOC."))
2608 depmod_symbol_add(depmod, "TOC.", true, 0, NULL);
4a0e46da
GSB
2609}
2610
2611static int depmod_load_symvers(struct depmod *depmod, const char *filename)
2612{
2613 char line[10240];
2614 FILE *fp;
2615 unsigned int linenum = 0;
4a0e46da
GSB
2616
2617 fp = fopen(filename, "r");
035cbdc7
KR
2618 if (fp == NULL) {
2619 int err = -errno;
2620 DBG("load symvers: %s: %m\n", filename);
4a0e46da 2621 return err;
035cbdc7
KR
2622 }
2623 DBG("load symvers: %s\n", filename);
4a0e46da
GSB
2624
2625 /* eg. "0xb352177e\tfind_first_bit\tvmlinux\tEXPORT_SYMBOL" */
2626 while (fgets(line, sizeof(line), fp) != NULL) {
2627 const char *ver, *sym, *where;
2628 char *verend;
2629 uint64_t crc;
2630
2631 linenum++;
2632
2633 ver = strtok(line, " \t");
2634 sym = strtok(NULL, " \t");
2635 where = strtok(NULL, " \t");
2636 if (!ver || !sym || !where)
2637 continue;
2638
2639 if (!streq(where, "vmlinux"))
2640 continue;
2641
2642 crc = strtoull(ver, &verend, 16);
2643 if (verend[0] != '\0') {
2644 ERR("%s:%u Invalid symbol version %s: %m\n",
2645 filename, linenum, ver);
2646 continue;
2647 }
2648
572a2711 2649 depmod_symbol_add(depmod, sym, false, crc, NULL);
4a0e46da
GSB
2650 }
2651 depmod_add_fake_syms(depmod);
2652
035cbdc7 2653 DBG("loaded symvers: %s\n", filename);
4a0e46da
GSB
2654
2655 fclose(fp);
035cbdc7 2656 return 0;
4a0e46da
GSB
2657}
2658
2659static int depmod_load_system_map(struct depmod *depmod, const char *filename)
2660{
2661 const char ksymstr[] = "__ksymtab_";
2662 const size_t ksymstr_len = sizeof(ksymstr) - 1;
2663 char line[10240];
2664 FILE *fp;
2665 unsigned int linenum = 0;
4a0e46da
GSB
2666
2667 fp = fopen(filename, "r");
035cbdc7
KR
2668 if (fp == NULL) {
2669 int err = -errno;
2670 DBG("load System.map: %s: %m\n", filename);
4a0e46da 2671 return err;
035cbdc7
KR
2672 }
2673 DBG("load System.map: %s\n", filename);
4a0e46da
GSB
2674
2675 /* eg. c0294200 R __ksymtab_devfs_alloc_devnum */
2676 while (fgets(line, sizeof(line), fp) != NULL) {
2677 char *p, *end;
2678
2679 linenum++;
2680
2681 p = strchr(line, ' ');
2682 if (p == NULL)
2683 goto invalid_syntax;
2684 p++;
2685 p = strchr(p, ' ');
2686 if (p == NULL)
2687 goto invalid_syntax;
2688 p++;
2689
572a2711
AM
2690 /* skip prefix */
2691 if (p[0] == depmod->cfg->sym_prefix)
2692 p++;
2693
4a0e46da
GSB
2694 /* Covers gpl-only and normal symbols. */
2695 if (strncmp(p, ksymstr, ksymstr_len) != 0)
2696 continue;
2697
2698 end = strchr(p, '\n');
2699 if (end != NULL)
2700 *end = '\0';
2701
572a2711 2702 depmod_symbol_add(depmod, p + ksymstr_len, true, 0, NULL);
4a0e46da
GSB
2703 continue;
2704
2705 invalid_syntax:
2706 ERR("%s:%u: invalid line: %s\n", filename, linenum, line);
2707 }
2708 depmod_add_fake_syms(depmod);
2709
035cbdc7 2710 DBG("loaded System.map: %s\n", filename);
4a0e46da
GSB
2711
2712 fclose(fp);
035cbdc7 2713 return 0;
4a0e46da 2714}
25c41512 2715
18cd9da3
GSB
2716
2717static int depfile_up_to_date_dir(DIR *d, time_t mtime, size_t baselen, char *path)
2718{
2719 struct dirent *de;
2720 int err = 1, dfd = dirfd(d);
2721
2722 while ((de = readdir(d)) != NULL) {
2723 const char *name = de->d_name;
2724 size_t namelen;
2725 struct stat st;
2726
2727 if (name[0] == '.' && (name[1] == '\0' ||
2728 (name[1] == '.' && name[2] == '\0')))
2729 continue;
2730 if (streq(name, "build") || streq(name, "source"))
2731 continue;
2732 namelen = strlen(name);
2733 if (baselen + namelen + 2 >= PATH_MAX) {
2734 path[baselen] = '\0';
1958af88 2735 ERR("path is too long %s%s\n", path, name);
18cd9da3
GSB
2736 continue;
2737 }
2738
2739 if (fstatat(dfd, name, &st, 0) < 0) {
2740 ERR("fstatat(%d, %s): %m\n", dfd, name);
2741 continue;
2742 }
2743
2744 if (S_ISDIR(st.st_mode)) {
2745 int fd;
2746 DIR *subdir;
2747 memcpy(path + baselen, name, namelen + 1);
2748 if (baselen + namelen + 2 + NAME_MAX >= PATH_MAX) {
2749 ERR("directory path is too long %s\n", path);
2750 continue;
2751 }
2752 fd = openat(dfd, name, O_RDONLY);
2753 if (fd < 0) {
2754 ERR("openat(%d, %s, O_RDONLY): %m\n",
2755 dfd, name);
2756 continue;
2757 }
2758 subdir = fdopendir(fd);
2759 if (subdir == NULL) {
2760 ERR("fdopendir(%d): %m\n", fd);
2761 close(fd);
2762 continue;
2763 }
2764 path[baselen + namelen] = '/';
2765 path[baselen + namelen + 1] = '\0';
2766 err = depfile_up_to_date_dir(subdir, mtime,
2767 baselen + namelen + 1,
2768 path);
2769 closedir(subdir);
2770 } else if (S_ISREG(st.st_mode)) {
650f89cd 2771 if (!path_ends_with_kmod_ext(name, namelen))
18cd9da3 2772 continue;
650f89cd 2773
18cd9da3
GSB
2774 memcpy(path + baselen, name, namelen + 1);
2775 err = st.st_mtime <= mtime;
2776 if (err == 0) {
2777 DBG("%s %"PRIu64" is newer than %"PRIu64"\n",
2778 path, (uint64_t)st.st_mtime,
2779 (uint64_t)mtime);
2780 }
2781 } else {
2782 ERR("unsupported file type %s: %o\n",
2783 path, st.st_mode & S_IFMT);
2784 continue;
2785 }
2786
2787 if (err == 0)
2788 break; /* outdated! */
2789 else if (err < 0) {
2790 path[baselen + namelen] = '\0';
2791 ERR("failed %s: %s\n", path, strerror(-err));
2792 err = 1; /* ignore errors */
2793 }
2794 }
2795
2796 return err;
2797}
2798
2799/* uptodate: 1, outdated: 0, errors < 0 */
64b8b586
GSB
2800static int depfile_up_to_date(const char *dirname)
2801{
18cd9da3
GSB
2802 char path[PATH_MAX];
2803 DIR *d = opendir(dirname);
2804 struct stat st;
2805 size_t baselen;
2806 int err;
2807 if (d == NULL) {
2808 err = -errno;
63698377 2809 ERR("could not open directory %s: %m\n", dirname);
18cd9da3
GSB
2810 return err;
2811 }
2812
2813 if (fstatat(dirfd(d), "modules.dep", &st, 0) != 0) {
2814 err = -errno;
63698377 2815 ERR("could not fstatat(%s, modules.dep): %m\n", dirname);
18cd9da3
GSB
2816 closedir(d);
2817 return err;
2818 }
2819
2820 baselen = strlen(dirname);
2821 memcpy(path, dirname, baselen);
2822 path[baselen] = '/';
2823 baselen++;
2824 path[baselen] = '\0';
2825
2826 err = depfile_up_to_date_dir(d, st.st_mtime, baselen, path);
2827 closedir(d);
2828 return err;
64b8b586
GSB
2829}
2830
2831static int is_version_number(const char *version)
2832{
2833 unsigned int d1, d2;
2834 return (sscanf(version, "%u.%u", &d1, &d2) == 2);
2835}
2836
f6cf14ce 2837static int do_depmod(int argc, char *argv[])
64b8b586
GSB
2838{
2839 FILE *out = NULL;
31f1d0d3 2840 int err = 0, all = 0, maybe_all = 0, n_config_paths = 0;
a07ea032
LDM
2841 _cleanup_free_ char *root = NULL;
2842 _cleanup_free_ const char **config_paths = NULL;
64b8b586
GSB
2843 const char *system_map = NULL;
2844 const char *module_symvers = NULL;
2845 const char *null_kmod_config = NULL;
2846 struct utsname un;
2847 struct kmod_ctx *ctx = NULL;
2848 struct cfg cfg;
2849 struct depmod depmod;
2850
2851 memset(&cfg, 0, sizeof(cfg));
2852 memset(&depmod, 0, sizeof(depmod));
2853
2854 for (;;) {
2855 int c, idx = 0;
2856 c = getopt_long(argc, argv, cmdopts_s, cmdopts, &idx);
2857 if (c == -1)
2858 break;
2859 switch (c) {
2860 case 'a':
2861 all = 1;
2862 break;
2863 case 'A':
2864 maybe_all = 1;
2865 break;
2866 case 'b':
a07ea032
LDM
2867 if (root)
2868 free(root);
2869 root = path_make_absolute_cwd(optarg);
64b8b586
GSB
2870 break;
2871 case 'C': {
2872 size_t bytes = sizeof(char *) * (n_config_paths + 2);
2873 void *tmp = realloc(config_paths, bytes);
2874 if (!tmp) {
2875 fputs("Error: out-of-memory\n", stderr);
2876 goto cmdline_failed;
2877 }
2878 config_paths = tmp;
2879 config_paths[n_config_paths] = optarg;
2880 n_config_paths++;
2881 config_paths[n_config_paths] = NULL;
2882 break;
2883 }
2884 case 'E':
2885 module_symvers = optarg;
2886 cfg.check_symvers = 1;
2887 break;
2888 case 'F':
2889 system_map = optarg;
2890 break;
2891 case 'e':
2892 cfg.print_unknown = 1;
2893 break;
2894 case 'v':
2895 verbose++;
2896 break;
2897 case 'n':
2898 out = stdout;
2899 break;
2900 case 'P':
2901 if (optarg[1] != '\0') {
2902 CRIT("-P only takes a single char\n");
2903 goto cmdline_failed;
2904 }
2905 cfg.sym_prefix = optarg[0];
2906 break;
2907 case 'w':
2908 cfg.warn_dups = 1;
2909 break;
2910 case 'u':
2911 case 'q':
2912 case 'r':
2913 case 'm':
61c48db3
LDM
2914 if (idx > 0)
2915 WRN("Ignored deprecated option --%s\n",
2916 cmdopts[idx].name);
2917 else
2918 WRN("Ignored deprecated option -%c\n", c);
2919
64b8b586
GSB
2920 break;
2921 case 'h':
4a2e20df 2922 help();
64b8b586
GSB
2923 return EXIT_SUCCESS;
2924 case 'V':
2925 puts(PACKAGE " version " VERSION);
655de275 2926 puts(KMOD_FEATURES);
64b8b586
GSB
2927 return EXIT_SUCCESS;
2928 case '?':
2929 goto cmdline_failed;
2930 default:
61c48db3 2931 ERR("unexpected getopt_long() value '%c'.\n", c);
64b8b586
GSB
2932 goto cmdline_failed;
2933 }
2934 }
2935
f3f62f5e
LA
2936 if (optind < argc) {
2937 if (!is_version_number(argv[optind])) {
2938 ERR("Bad version passed %s\n", argv[optind]);
2939 goto cmdline_failed;
2940 }
64b8b586
GSB
2941 cfg.kversion = argv[optind];
2942 optind++;
2943 } else {
2944 if (uname(&un) < 0) {
2945 CRIT("uname() failed: %s\n", strerror(errno));
2946 goto cmdline_failed;
2947 }
2948 cfg.kversion = un.release;
2949 }
2950
2951 cfg.dirnamelen = snprintf(cfg.dirname, PATH_MAX,
c5b37dba 2952 "%s/lib/modules/%s",
e15a56af 2953 root == NULL ? "" : root, cfg.kversion);
64b8b586
GSB
2954
2955 if (optind == argc)
2956 all = 1;
2957
2958 if (maybe_all) {
2959 if (out == stdout)
2960 goto done;
18cd9da3 2961 /* ignore up-to-date errors (< 0) */
50f43ce2 2962 if (depfile_up_to_date(cfg.dirname) == 1)
64b8b586
GSB
2963 goto done;
2964 all = 1;
2965 }
2966
2967 ctx = kmod_new(cfg.dirname, &null_kmod_config);
2968 if (ctx == NULL) {
2969 CRIT("kmod_new(\"%s\", {NULL}) failed: %m\n", cfg.dirname);
2970 goto cmdline_failed;
2971 }
52a50fe2
LDM
2972
2973 log_setup_kmod_log(ctx, verbose);
64b8b586
GSB
2974
2975 err = depmod_init(&depmod, &cfg, ctx);
2976 if (err < 0) {
2977 CRIT("depmod_init: %s\n", strerror(-err));
2978 goto depmod_init_failed;
2979 }
2980 ctx = NULL; /* owned by depmod */
2981
4a0e46da
GSB
2982 if (module_symvers != NULL) {
2983 err = depmod_load_symvers(&depmod, module_symvers);
2984 if (err < 0) {
63698377 2985 CRIT("could not load %s: %s\n", module_symvers,
4a0e46da
GSB
2986 strerror(-err));
2987 goto cmdline_failed;
2988 }
2989 } else if (system_map != NULL) {
2990 err = depmod_load_system_map(&depmod, system_map);
2991 if (err < 0) {
035cbdc7 2992 CRIT("could not load %s: %s\n", system_map,
4a0e46da
GSB
2993 strerror(-err));
2994 goto cmdline_failed;
2995 }
2996 } else if (cfg.print_unknown) {
2997 WRN("-e needs -E or -F\n");
2998 cfg.print_unknown = 0;
2999 }
3000
64b8b586
GSB
3001 if (all) {
3002 err = cfg_load(&cfg, config_paths);
3003 if (err < 0) {
63698377 3004 CRIT("could not load configuration files\n");
64b8b586
GSB
3005 goto cmdline_modules_failed;
3006 }
3007 err = depmod_modules_search(&depmod);
3008 if (err < 0) {
63698377 3009 CRIT("could not search modules: %s\n", strerror(-err));
64b8b586
GSB
3010 goto cmdline_modules_failed;
3011 }
3012 } else {
31f1d0d3
LDM
3013 int i;
3014
64b8b586
GSB
3015 for (i = optind; i < argc; i++) {
3016 const char *path = argv[i];
3017 struct kmod_module *mod;
3018
3019 if (path[0] != '/') {
b0bcadd0 3020 CRIT("%s: not absolute path.\n", path);
64b8b586
GSB
3021 goto cmdline_modules_failed;
3022 }
3023
3024 err = kmod_module_new_from_path(depmod.ctx, path, &mod);
3025 if (err < 0) {
63698377 3026 CRIT("could not create module %s: %s\n",
64b8b586
GSB
3027 path, strerror(-err));
3028 goto cmdline_modules_failed;
3029 }
3030
3031 err = depmod_module_add(&depmod, mod);
3032 if (err < 0) {
63698377 3033 CRIT("could not add module %s: %s\n",
64b8b586
GSB
3034 path, strerror(-err));
3035 kmod_module_unref(mod);
3036 goto cmdline_modules_failed;
3037 }
3038 }
3039 }
3040
00bd3191
JAS
3041 err = depmod_modules_build_array(&depmod);
3042 if (err < 0) {
3043 CRIT("could not build module array: %s\n",
3044 strerror(-err));
3045 goto cmdline_modules_failed;
3046 }
3047
64b8b586
GSB
3048 depmod_modules_sort(&depmod);
3049 err = depmod_load(&depmod);
3050 if (err < 0)
3051 goto cmdline_modules_failed;
3052
25c41512 3053 err = depmod_output(&depmod, out);
64b8b586
GSB
3054
3055done:
3056 depmod_shutdown(&depmod);
3057 cfg_free(&cfg);
64b8b586
GSB
3058 return err >= 0 ? EXIT_SUCCESS : EXIT_FAILURE;
3059
3060cmdline_modules_failed:
3061 depmod_shutdown(&depmod);
3062depmod_init_failed:
3063 if (ctx != NULL)
3064 kmod_unref(ctx);
3065cmdline_failed:
3066 cfg_free(&cfg);
64b8b586
GSB
3067 return EXIT_FAILURE;
3068}
f6cf14ce 3069
f6cf14ce
LDM
3070const struct kmod_cmd kmod_cmd_compat_depmod = {
3071 .name = "depmod",
3072 .cmd = do_depmod,
3073 .help = "compat depmod command",
3074};