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