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