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