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