]> git.ipfire.org Git - thirdparty/kmod.git/blame - tools/kmod-depmod.c
kmod-depmod: implement -F and -E options.
[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
7436788c
GSB
2265static int output_deps_bin(struct depmod *depmod, FILE *out)
2266{
2267 struct index_node *idx;
2268 size_t i;
2269
2270 if (out == stdout)
2271 return 0;
2272
2273 idx = index_create();
2274 if (idx == NULL)
2275 return -ENOMEM;
2276
2277 for (i = 0; i < depmod->modules.count; i++) {
2278 const struct mod **deps, *mod = depmod->modules.array[i];
2279 const char *p = mod_get_compressed_path(mod);
2280 char *line;
2281 size_t j, n_deps, linepos, linelen, slen;
2282 int duplicate;
2283
2284 if (mod->dep_loop) {
2285 DBG("Ignored %s due dependency loops\n", p);
2286 continue;
2287 }
2288
2289 deps = mod_get_all_sorted_dependencies(mod, &n_deps);
2290 if (deps == NULL && n_deps > 0) {
2291 ERR("Could not get all sorted dependencies of %s\n", p);
2292 continue;
2293 }
2294
2295 linelen = strlen(p) + 1;
2296 for (j = 0; j < n_deps; j++) {
2297 const struct mod *d = deps[j];
2298 if (d->dep_loop) {
2299 DBG("Ignored %s (dependency of %s) "
2300 "due dependency loops\n",
2301 mod_get_compressed_path(d), p);
2302 continue;
2303 }
2304 linelen += 1 + strlen(mod_get_compressed_path(d));
2305 }
2306
2307 line = malloc(linelen + 1);
2308 if (line == NULL) {
2309 free(deps);
2310 ERR("modules.deps.bin: out of memory\n");
2311 continue;
2312 }
2313
2314 linepos = 0;
2315 slen = strlen(p);
2316 memcpy(line + linepos, p, slen);
2317 linepos += slen;
2318 line[linepos] = ':';
2319 linepos++;
2320
2321 for (j = 0; j < n_deps; j++) {
2322 const struct mod *d = deps[j];
2323 const char *dp;
2324 if (d->dep_loop)
2325 continue;
2326 line[linepos] = ' ';
2327 linepos++;
2328
2329 dp = mod_get_compressed_path(d);
2330 slen = strlen(dp);
2331 memcpy(line + linepos, dp, slen);
2332 linepos += slen;
2333 }
2334 line[linepos] = '\0';
2335
2336 duplicate = index_insert(idx, mod->modname, line, mod->idx);
2337 if (duplicate && depmod->cfg->warn_dups)
2338 WRN("duplicate module deps:\n%s\n", line);
2339 free(line);
2340 }
2341
2342 index_write(idx, out);
2343 index_destroy(idx);
2344
2345 return 0;
2346}
2347
0d131745
GSB
2348static int output_aliases(struct depmod *depmod, FILE *out)
2349{
2350 size_t i;
2351
2352 fputs("# Aliases extracted from modules themselves.\n", out);
2353
2354 for (i = 0; i < depmod->modules.count; i++) {
2355 const struct mod *mod = depmod->modules.array[i];
2356 struct kmod_list *l, *list = NULL;
2357 int r = kmod_module_get_info(mod->kmod, &list);
2358 if (r < 0 || list == NULL)
2359 continue;
2360 kmod_list_foreach(l, list) {
2361 const char *key = kmod_module_info_get_key(l);
2362 const char *value = kmod_module_info_get_value(l);
2363
2364 if (!streq(key, "alias"))
2365 continue;
2366
2367 fprintf(out, "alias %s %s\n",
2368 value, kmod_module_get_name(mod->kmod));
2369 }
2370 kmod_module_info_free_list(list);
2371 }
2372
2373 return 0;
2374}
2375
ec77abb9
GSB
2376static int output_aliases_bin(struct depmod *depmod, FILE *out)
2377{
2378 char buf[1024];
2379 struct index_node *idx;
2380 size_t i;
2381
2382 if (out == stdout)
2383 return 0;
2384
2385 idx = index_create();
2386 if (idx == NULL)
2387 return -ENOMEM;
2388
2389 for (i = 0; i < depmod->modules.count; i++) {
2390 const struct mod *mod = depmod->modules.array[i];
2391 struct kmod_list *l, *list = NULL;
2392 int r = kmod_module_get_info(mod->kmod, &list);
2393 if (r < 0 || list == NULL)
2394 continue;
2395 kmod_list_foreach(l, list) {
2396 const char *key = kmod_module_info_get_key(l);
2397 const char *value = kmod_module_info_get_value(l);
2398 const char *modname, *alias;
2399 int duplicate;
2400
2401 if (!streq(key, "alias"))
2402 continue;
2403
2404 alias = underscores(value, buf, sizeof(buf));
2405 if (alias == NULL)
2406 continue;
2407
2408 modname = kmod_module_get_name(mod->kmod);
2409 duplicate = index_insert(idx, alias, modname,
2410 mod->idx);
2411 if (duplicate && depmod->cfg->warn_dups)
2412 WRN("duplicate module alias:\n%s %s\n",
2413 alias, modname);
2414 }
2415 kmod_module_info_free_list(list);
2416 }
2417
2418 index_write(idx, out);
2419 index_destroy(idx);
2420
2421 return 0;
2422}
2423
8bc830ef
GSB
2424static int output_softdeps(struct depmod *depmod, FILE *out)
2425{
2426 size_t i;
2427
2428 fputs("# Soft dependencies extracted from modules themselves.\n", out);
2429 fputs("# Copy, with a .conf extension, to /etc/modprobe.d to use "
2430 "it with modprobe.\n", out);
2431
2432 for (i = 0; i < depmod->modules.count; i++) {
2433 const struct mod *mod = depmod->modules.array[i];
2434 struct kmod_list *l, *list = NULL;
2435 int r = kmod_module_get_info(mod->kmod, &list);
2436 if (r < 0 || list == NULL)
2437 continue;
2438 kmod_list_foreach(l, list) {
2439 const char *key = kmod_module_info_get_key(l);
2440 const char *value = kmod_module_info_get_value(l);
2441
2442 if (!streq(key, "softdep"))
2443 continue;
2444
2445 fprintf(out, "softdep %s %s\n",
2446 kmod_module_get_name(mod->kmod), value);
2447 }
2448 kmod_module_info_free_list(list);
2449 }
2450
2451 return 0;
2452}
2453
9a14d0e9
GSB
2454static int output_symbols(struct depmod *depmod, FILE *out)
2455{
2456 size_t i;
2457
2458 fputs("# Aliases for symbols, used by symbol_request().\n", out);
2459
2460 for (i = 0; i < depmod->symbols->n_buckets; i++) {
2461 const struct hash_bucket *b = depmod->symbols->buckets + i;
2462 unsigned j;
2463 for (j = 0; j < b->used; j++) {
2464 const struct hash_entry *e = b->entries + j;
2465 const struct symbol *sym = e->value;
2466 if (sym->owner == NULL)
2467 continue;
2468 fprintf(out, "alias symbol:%s %s\n",
2469 sym->name, sym->owner->modname);
2470 }
2471 }
2472
2473 return 0;
2474}
2475
75a9723b
GSB
2476static int output_symbols_bin(struct depmod *depmod, FILE *out)
2477{
2478 struct index_node *idx;
2479 char alias[1024];
2480 size_t i, baselen = sizeof("symbol:") - 1;
2481
2482 if (out == stdout)
2483 return 0;
2484
2485 idx = index_create();
2486 if (idx == NULL)
2487 return -ENOMEM;
2488
2489 memcpy(alias, "symbol:", baselen);
2490
2491 for (i = 0; i < depmod->symbols->n_buckets; i++) {
2492 const struct hash_bucket *b = depmod->symbols->buckets + i;
2493 unsigned j;
2494 for (j = 0; j < b->used; j++) {
2495 const struct hash_entry *e = b->entries + j;
2496 const struct symbol *sym = e->value;
2497 int duplicate;
2498
2499 if (sym->owner == NULL)
2500 continue;
2501
2502 strcpy(alias + baselen, sym->name);
2503 duplicate = index_insert(idx, alias,
2504 sym->owner->modname,
2505 sym->owner->idx);
2506 if (duplicate && depmod->cfg->warn_dups)
2507 WRN("duplicate module syms:\n%s %s\n",
2508 alias, sym->owner->modname);
2509 }
2510 }
2511
2512 index_write(idx, out);
2513 index_destroy(idx);
2514 return 0;
2515}
2516
4b144e5f
GSB
2517static int output_builtin_bin(struct depmod *depmod, FILE *out)
2518{
2519 FILE *in;
2520 struct index_node *idx;
2521 char infile[PATH_MAX], line[PATH_MAX], modname[NAME_MAX];
2522
2523 if (out == stdout)
2524 return 0;
2525
2526 snprintf(infile, sizeof(infile), "%s/modules.builtin",
2527 depmod->cfg->dirname);
2528 in = fopen(infile, "r");
2529 if (in == NULL) {
2530 int err = -errno;
2531 ERR("Could not open %s: %m\n", infile);
2532 return err;
2533 }
2534
2535 idx = index_create();
2536 if (idx == NULL) {
2537 fclose(in);
2538 return -ENOMEM;
2539 }
2540
2541 while (fgets(line, sizeof(line), in) != NULL) {
2542 if (!isalpha(line[0])) {
2543 ERR("Invalid modules.builtin line: %s\n", line);
2544 continue;
2545 }
2546
2547 path_to_modname(line, modname, NULL);
2548 index_insert(idx, modname, "", 0);
2549 }
2550
2551 index_write(idx, out);
2552 index_destroy(idx);
2553 fclose(in);
2554
2555 return 0;
2556}
2557
25c41512
GSB
2558static int output_devname(struct depmod *depmod, FILE *out)
2559{
2560 size_t i;
2561
2562 fputs("# Device nodes to trigger on-demand module loading.\n", out);
2563
2564 for (i = 0; i < depmod->modules.count; i++) {
2565 const struct mod *mod = depmod->modules.array[i];
2566 struct kmod_list *l, *list = NULL;
2567 const char *devname = NULL;
2568 char type = '\0';
2569 unsigned int major = 0, minor = 0;
2570 int r;
2571
2572 r = kmod_module_get_info(mod->kmod, &list);
2573 if (r < 0 || list == NULL)
2574 continue;
2575
2576 kmod_list_foreach(l, list) {
2577 const char *key = kmod_module_info_get_key(l);
2578 const char *value = kmod_module_info_get_value(l);
2579 unsigned int maj, min;
2580
2581 if (!streq(key, "alias"))
2582 continue;
2583
2584 if (strstartswith(value, "devname:"))
2585 devname = value + sizeof("devname:") - 1;
2586 else if (sscanf(value, "char-major-%u-%u",
2587 &maj, &min) == 2) {
2588 type = 'c';
2589 major = maj;
2590 minor = min;
2591 } else if (sscanf(value, "block-major-%u-%u",
2592 &maj, &min) == 2) {
2593 type = 'b';
2594 major = maj;
2595 minor = min;
2596 }
2597
2598 if (type != '\0' && devname != NULL) {
2599 fprintf(out, "%s %s %c%u:%u\n",
2600 kmod_module_get_name(mod->kmod),
2601 devname, type, major, minor);
2602 break;
2603 }
2604 }
2605 kmod_module_info_free_list(list);
2606 }
2607
2608 return 0;
2609}
2610
2611static int depmod_output(struct depmod *depmod, FILE *out)
2612{
2613 static const struct depfile {
2614 const char *name;
2615 int (*cb)(struct depmod *depmod, FILE *out);
2616 } *itr, depfiles[] = {
8e3505c5 2617 {"modules.dep", output_deps},
7436788c 2618 {"modules.dep.bin", output_deps_bin},
0d131745 2619 {"modules.alias", output_aliases},
ec77abb9 2620 {"modules.alias.bin", output_aliases_bin},
8bc830ef 2621 {"modules.softdep", output_softdeps},
9a14d0e9 2622 {"modules.symbols", output_symbols},
75a9723b 2623 {"modules.symbols.bin", output_symbols_bin},
4b144e5f 2624 {"modules.builtin.bin", output_builtin_bin},
25c41512
GSB
2625 {"modules.devname", output_devname},
2626 {NULL, NULL}
2627 };
2628 const char *dname = depmod->cfg->dirname;
2629 int dfd, err = 0;
2630
2631 if (out != NULL)
2632 dfd = -1;
2633 else {
2634 dfd = open(dname, O_RDONLY);
2635 if (dfd < 0) {
2636 err = -errno;
2637 CRIT("Could not open directory %s: %m\n", dname);
2638 return err;
2639 }
2640 }
2641
2642 for (itr = depfiles; itr->name != NULL; itr++) {
2643 FILE *fp = out;
2644 char tmp[NAME_MAX] = "";
2645 int r;
2646
2647 if (fp == NULL) {
2648 int flags = O_CREAT | O_TRUNC | O_WRONLY;
2649 int mode = 0644;
2650 int fd;
2651
2652 snprintf(tmp, sizeof(tmp), "%s.tmp", itr->name);
2653 fd = openat(dfd, tmp, flags, mode);
2654 if (fd < 0) {
2655 ERR("openat(%s, %s, %o, %o): %m\n",
2656 dname, tmp, flags, mode);
2657 continue;
2658 }
2659 fp = fdopen(fd, "wb");
2660 if (fp == NULL) {
2661 ERR("fdopen(%d=%s/%s): %m\n", fd, dname, tmp);
2662 close(fd);
2663 continue;
2664 }
2665 }
2666
2667 r = itr->cb(depmod, fp);
2668 if (fp == out)
2669 continue;
2670
2671 fclose(fp);
2672 if (r < 0) {
2673 if (unlinkat(dfd, tmp, 0) != 0)
2674 ERR("unlinkat(%s, %s): %m\n", dname, tmp);
2675 } else {
2676 unlinkat(dfd, itr->name, 0);
2677 if (renameat(dfd, tmp, dfd, itr->name) != 0) {
2678 err = -errno;
2679 CRIT("renameat(%s, %s, %s, %s): %m\n",
2680 dname, tmp, dname, itr->name);
2681 break;
2682 }
2683 }
2684 }
2685
2686 if (dfd >= 0)
2687 close(dfd);
2688 return err;
2689}
2690
4a0e46da
GSB
2691static void depmod_add_fake_syms(struct depmod *depmod)
2692{
2693 /* __this_module is magic inserted by kernel loader. */
2694 depmod_symbol_add(depmod, "__this_module", 0, NULL);
2695 /* On S390, this is faked up too */
2696 depmod_symbol_add(depmod, "_GLOBAL_OFFSET_TABLE_", 0, NULL);
2697}
2698
2699static int depmod_load_symvers(struct depmod *depmod, const char *filename)
2700{
2701 char line[10240];
2702 FILE *fp;
2703 unsigned int linenum = 0;
2704 int err;
2705
2706 fp = fopen(filename, "r");
2707 err = -errno;
2708 DBG("load symvers: %s: %s\n", filename, strerror(-err));
2709 if (fp == NULL)
2710 return err;
2711
2712 /* eg. "0xb352177e\tfind_first_bit\tvmlinux\tEXPORT_SYMBOL" */
2713 while (fgets(line, sizeof(line), fp) != NULL) {
2714 const char *ver, *sym, *where;
2715 char *verend;
2716 uint64_t crc;
2717
2718 linenum++;
2719
2720 ver = strtok(line, " \t");
2721 sym = strtok(NULL, " \t");
2722 where = strtok(NULL, " \t");
2723 if (!ver || !sym || !where)
2724 continue;
2725
2726 if (!streq(where, "vmlinux"))
2727 continue;
2728
2729 crc = strtoull(ver, &verend, 16);
2730 if (verend[0] != '\0') {
2731 ERR("%s:%u Invalid symbol version %s: %m\n",
2732 filename, linenum, ver);
2733 continue;
2734 }
2735
2736 depmod_symbol_add(depmod, sym, crc, NULL);
2737 }
2738 depmod_add_fake_syms(depmod);
2739
2740 DBG("loaded symvers: %s: %s\n", filename, strerror(-err));
2741
2742 fclose(fp);
2743 return err;
2744}
2745
2746static int depmod_load_system_map(struct depmod *depmod, const char *filename)
2747{
2748 const char ksymstr[] = "__ksymtab_";
2749 const size_t ksymstr_len = sizeof(ksymstr) - 1;
2750 char line[10240];
2751 FILE *fp;
2752 unsigned int linenum = 0;
2753 int err;
2754
2755 fp = fopen(filename, "r");
2756 err = -errno;
2757 DBG("load System.map: %s: %s\n", filename, strerror(-err));
2758 if (fp == NULL)
2759 return err;
2760
2761 /* eg. c0294200 R __ksymtab_devfs_alloc_devnum */
2762 while (fgets(line, sizeof(line), fp) != NULL) {
2763 char *p, *end;
2764
2765 linenum++;
2766
2767 p = strchr(line, ' ');
2768 if (p == NULL)
2769 goto invalid_syntax;
2770 p++;
2771 p = strchr(p, ' ');
2772 if (p == NULL)
2773 goto invalid_syntax;
2774 p++;
2775
2776 /* Covers gpl-only and normal symbols. */
2777 if (strncmp(p, ksymstr, ksymstr_len) != 0)
2778 continue;
2779
2780 end = strchr(p, '\n');
2781 if (end != NULL)
2782 *end = '\0';
2783
2784 depmod_symbol_add(depmod, p + ksymstr_len, 0, NULL);
2785 continue;
2786
2787 invalid_syntax:
2788 ERR("%s:%u: invalid line: %s\n", filename, linenum, line);
2789 }
2790 depmod_add_fake_syms(depmod);
2791
2792 DBG("loaded System.map: %s: %s\n", filename, strerror(-err));
2793
2794 fclose(fp);
2795 return err;
2796}
25c41512 2797
64b8b586
GSB
2798static int depfile_up_to_date(const char *dirname)
2799{
2800 ERR("TODO depfile_up_to_date()\n");
2801 return 0;
2802}
2803
2804static int is_version_number(const char *version)
2805{
2806 unsigned int d1, d2;
2807 return (sscanf(version, "%u.%u", &d1, &d2) == 2);
2808}
2809
2810int main(int argc, char *argv[])
2811{
2812 FILE *out = NULL;
2813 int i, err = 0, all = 0, maybe_all = 0, n_config_paths = 0;
2814 const char **config_paths = NULL;
2815 const char *root = "";
2816 const char *system_map = NULL;
2817 const char *module_symvers = NULL;
2818 const char *null_kmod_config = NULL;
2819 struct utsname un;
2820 struct kmod_ctx *ctx = NULL;
2821 struct cfg cfg;
2822 struct depmod depmod;
2823
2824 memset(&cfg, 0, sizeof(cfg));
2825 memset(&depmod, 0, sizeof(depmod));
2826
2827 for (;;) {
2828 int c, idx = 0;
2829 c = getopt_long(argc, argv, cmdopts_s, cmdopts, &idx);
2830 if (c == -1)
2831 break;
2832 switch (c) {
2833 case 'a':
2834 all = 1;
2835 break;
2836 case 'A':
2837 maybe_all = 1;
2838 break;
2839 case 'b':
2840 root = optarg;
2841 break;
2842 case 'C': {
2843 size_t bytes = sizeof(char *) * (n_config_paths + 2);
2844 void *tmp = realloc(config_paths, bytes);
2845 if (!tmp) {
2846 fputs("Error: out-of-memory\n", stderr);
2847 goto cmdline_failed;
2848 }
2849 config_paths = tmp;
2850 config_paths[n_config_paths] = optarg;
2851 n_config_paths++;
2852 config_paths[n_config_paths] = NULL;
2853 break;
2854 }
2855 case 'E':
2856 module_symvers = optarg;
2857 cfg.check_symvers = 1;
2858 break;
2859 case 'F':
2860 system_map = optarg;
2861 break;
2862 case 'e':
2863 cfg.print_unknown = 1;
2864 break;
2865 case 'v':
2866 verbose++;
2867 break;
2868 case 'n':
2869 out = stdout;
2870 break;
2871 case 'P':
2872 if (optarg[1] != '\0') {
2873 CRIT("-P only takes a single char\n");
2874 goto cmdline_failed;
2875 }
2876 cfg.sym_prefix = optarg[0];
2877 break;
2878 case 'w':
2879 cfg.warn_dups = 1;
2880 break;
2881 case 'u':
2882 case 'q':
2883 case 'r':
2884 case 'm':
2885 if (idx > 0) {
2886 fprintf(stderr,
2887 "ignored deprecated option --%s\n",
2888 cmdopts[idx].name);
2889 } else {
2890 fprintf(stderr,
2891 "ignored deprecated option -%c\n", c);
2892 }
2893 break;
2894 case 'h':
2895 help(argv[0]);
2896 free(config_paths);
2897 return EXIT_SUCCESS;
2898 case 'V':
2899 puts(PACKAGE " version " VERSION);
2900 free(config_paths);
2901 return EXIT_SUCCESS;
2902 case '?':
2903 goto cmdline_failed;
2904 default:
2905 fprintf(stderr,
2906 "Error: unexpected getopt_long() value '%c'.\n",
2907 c);
2908 goto cmdline_failed;
2909 }
2910 }
2911
2912 if (optind < argc && is_version_number(argv[optind])) {
2913 cfg.kversion = argv[optind];
2914 optind++;
2915 } else {
2916 if (uname(&un) < 0) {
2917 CRIT("uname() failed: %s\n", strerror(errno));
2918 goto cmdline_failed;
2919 }
2920 cfg.kversion = un.release;
2921 }
2922
2923 cfg.dirnamelen = snprintf(cfg.dirname, PATH_MAX,
2924 "%s" ROOTPREFIX "/lib/modules/%s",
2925 root, cfg.kversion);
2926
2927 if (optind == argc)
2928 all = 1;
2929
2930 if (maybe_all) {
2931 if (out == stdout)
2932 goto done;
2933 if (depfile_up_to_date(cfg.dirname))
2934 goto done;
2935 all = 1;
2936 }
2937
2938 ctx = kmod_new(cfg.dirname, &null_kmod_config);
2939 if (ctx == NULL) {
2940 CRIT("kmod_new(\"%s\", {NULL}) failed: %m\n", cfg.dirname);
2941 goto cmdline_failed;
2942 }
2943 kmod_set_log_priority(ctx, verbose);
2944
2945 err = depmod_init(&depmod, &cfg, ctx);
2946 if (err < 0) {
2947 CRIT("depmod_init: %s\n", strerror(-err));
2948 goto depmod_init_failed;
2949 }
2950 ctx = NULL; /* owned by depmod */
2951
4a0e46da
GSB
2952 if (module_symvers != NULL) {
2953 err = depmod_load_symvers(&depmod, module_symvers);
2954 if (err < 0) {
2955 CRIT("Could not load %s: %s\n", module_symvers,
2956 strerror(-err));
2957 goto cmdline_failed;
2958 }
2959 } else if (system_map != NULL) {
2960 err = depmod_load_system_map(&depmod, system_map);
2961 if (err < 0) {
2962 CRIT("Could not load %s: %s\n", module_symvers,
2963 strerror(-err));
2964 goto cmdline_failed;
2965 }
2966 } else if (cfg.print_unknown) {
2967 WRN("-e needs -E or -F\n");
2968 cfg.print_unknown = 0;
2969 }
2970
64b8b586
GSB
2971 if (all) {
2972 err = cfg_load(&cfg, config_paths);
2973 if (err < 0) {
2974 CRIT("Could not load configuration files\n");
2975 goto cmdline_modules_failed;
2976 }
2977 err = depmod_modules_search(&depmod);
2978 if (err < 0) {
2979 CRIT("Could search modules: %s\n", strerror(-err));
2980 goto cmdline_modules_failed;
2981 }
2982 } else {
2983 for (i = optind; i < argc; i++) {
2984 const char *path = argv[i];
2985 struct kmod_module *mod;
2986
2987 if (path[0] != '/') {
2988 CRIT("%s: not absolute path.", path);
2989 goto cmdline_modules_failed;
2990 }
2991
2992 err = kmod_module_new_from_path(depmod.ctx, path, &mod);
2993 if (err < 0) {
2994 CRIT("Could not create module %s: %s\n",
2995 path, strerror(-err));
2996 goto cmdline_modules_failed;
2997 }
2998
2999 err = depmod_module_add(&depmod, mod);
3000 if (err < 0) {
3001 CRIT("Could not add module %s: %s\n",
3002 path, strerror(-err));
3003 kmod_module_unref(mod);
3004 goto cmdline_modules_failed;
3005 }
3006 }
3007 }
3008
3009 depmod_modules_sort(&depmod);
3010 err = depmod_load(&depmod);
3011 if (err < 0)
3012 goto cmdline_modules_failed;
3013
25c41512 3014 err = depmod_output(&depmod, out);
64b8b586
GSB
3015
3016done:
3017 depmod_shutdown(&depmod);
3018 cfg_free(&cfg);
3019 free(config_paths);
3020 return err >= 0 ? EXIT_SUCCESS : EXIT_FAILURE;
3021
3022cmdline_modules_failed:
3023 depmod_shutdown(&depmod);
3024depmod_init_failed:
3025 if (ctx != NULL)
3026 kmod_unref(ctx);
3027cmdline_failed:
3028 cfg_free(&cfg);
3029 free(config_paths);
3030 return EXIT_FAILURE;
3031}