]> git.ipfire.org Git - thirdparty/kmod.git/blame - tools/kmod-depmod.c
kmod-depmod: dump deps.
[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
169/* hash like libkmod-hash.c *******************************************/
170struct hash_entry {
171 const char *key;
172 const void *value;
173};
174
175struct hash_bucket {
176 struct hash_entry *entries;
177 unsigned int used;
178 unsigned int total;
179};
180
181struct hash {
182 unsigned int count;
183 unsigned int step;
184 unsigned int n_buckets;
185 void (*free_value)(void *value);
186 struct hash_bucket buckets[];
187};
188
189static struct hash *hash_new(unsigned int n_buckets,
190 void (*free_value)(void *value))
191{
192 struct hash *hash = calloc(1, sizeof(struct hash) +
193 n_buckets * sizeof(struct hash_bucket));
194 if (hash == NULL)
195 return NULL;
196 hash->n_buckets = n_buckets;
197 hash->free_value = free_value;
198 hash->step = n_buckets / 32;
199 if (hash->step == 0)
200 hash->step = 4;
201 else if (hash->step > 64)
202 hash->step = 64;
203 return hash;
204}
205
206static void hash_free(struct hash *hash)
207{
208 struct hash_bucket *bucket, *bucket_end;
209 bucket = hash->buckets;
210 bucket_end = bucket + hash->n_buckets;
211 for (; bucket < bucket_end; bucket++) {
212 if (hash->free_value) {
213 struct hash_entry *entry, *entry_end;
214 entry = bucket->entries;
215 entry_end = entry + bucket->used;
216 for (; entry < entry_end; entry++)
217 hash->free_value((void *)entry->value);
218 }
219 free(bucket->entries);
220 }
221 free(hash);
222}
223
224static inline unsigned int hash_superfast(const char *key, unsigned int len)
225{
226 /* Paul Hsieh (http://www.azillionmonkeys.com/qed/hash.html)
227 * used by WebCore (http://webkit.org/blog/8/hashtables-part-2/)
228 * EFL's eina and possible others.
229 */
230 unsigned int tmp, hash = len, rem = len & 3;
231 const unsigned short *itr = (const unsigned short *)key;
232
233 len /= 4;
234
235 /* Main loop */
236 for (; len > 0; len--) {
237 hash += itr[0];
238 tmp = (itr[1] << 11) ^ hash;
239 hash = (hash << 16) ^ tmp;
240 itr += 2;
241 hash += hash >> 11;
242 }
243
244 /* Handle end cases */
245 switch (rem) {
246 case 3:
247 hash += *itr;
248 hash ^= hash << 16;
249 hash ^= key[2] << 18;
250 hash += hash >> 11;
251 break;
252
253 case 2:
254 hash += *itr;
255 hash ^= hash << 11;
256 hash += hash >> 17;
257 break;
258
259 case 1:
260 hash += *(const char *)itr;
261 hash ^= hash << 10;
262 hash += hash >> 1;
263 }
264
265 /* Force "avalanching" of final 127 bits */
266 hash ^= hash << 3;
267 hash += hash >> 5;
268 hash ^= hash << 4;
269 hash += hash >> 17;
270 hash ^= hash << 25;
271 hash += hash >> 6;
272
273 return hash;
274}
275
276/*
277 * add or replace key in hash map.
278 *
279 * none of key or value are copied, just references are remembered as is,
280 * make sure they are live while pair exists in hash!
281 */
282static int hash_add(struct hash *hash, const char *key, const void *value)
283{
284 unsigned int keylen = strlen(key);
285 unsigned int hashval = hash_superfast(key, keylen);
286 unsigned int pos = hashval % hash->n_buckets;
287 struct hash_bucket *bucket = hash->buckets + pos;
288 struct hash_entry *entry, *entry_end;
289
290 if (bucket->used + 1 >= bucket->total) {
291 unsigned new_total = bucket->total + hash->step;
292 size_t size = new_total * sizeof(struct hash_entry);
293 struct hash_entry *tmp = realloc(bucket->entries, size);
294 if (tmp == NULL)
295 return -errno;
296 bucket->entries = tmp;
297 bucket->total = new_total;
298 }
299
300 entry = bucket->entries;
301 entry_end = entry + bucket->used;
302 for (; entry < entry_end; entry++) {
303 int c = strcmp(key, entry->key);
304 if (c == 0) {
305 hash->free_value((void *)entry->value);
306 entry->value = value;
307 return 0;
308 } else if (c < 0) {
309 memmove(entry + 1, entry,
310 (entry_end - entry) * sizeof(struct hash_entry));
311 break;
312 }
313 }
314
315 entry->key = key;
316 entry->value = value;
317 bucket->used++;
318 hash->count++;
319 return 0;
320}
321
322/* similar to hash_add(), but fails if key already exists */
323static int hash_add_unique(struct hash *hash, const char *key, const void *value)
324{
325 unsigned int keylen = strlen(key);
326 unsigned int hashval = hash_superfast(key, keylen);
327 unsigned int pos = hashval % hash->n_buckets;
328 struct hash_bucket *bucket = hash->buckets + pos;
329 struct hash_entry *entry, *entry_end;
330
331 if (bucket->used + 1 >= bucket->total) {
332 unsigned new_total = bucket->total + hash->step;
333 size_t size = new_total * sizeof(struct hash_entry);
334 struct hash_entry *tmp = realloc(bucket->entries, size);
335 if (tmp == NULL)
336 return -errno;
337 bucket->entries = tmp;
338 bucket->total = new_total;
339 }
340
341 entry = bucket->entries;
342 entry_end = entry + bucket->used;
343 for (; entry < entry_end; entry++) {
344 int c = strcmp(key, entry->key);
345 if (c == 0)
346 return -EEXIST;
347 else if (c < 0) {
348 memmove(entry + 1, entry,
349 (entry_end - entry) * sizeof(struct hash_entry));
350 break;
351 }
352 }
353
354 entry->key = key;
355 entry->value = value;
356 bucket->used++;
357 hash->count++;
358 return 0;
359}
360
361static int hash_entry_cmp(const void *pa, const void *pb)
362{
363 const struct hash_entry *a = pa;
364 const struct hash_entry *b = pb;
365 return strcmp(a->key, b->key);
366}
367
368static void *hash_find(const struct hash *hash, const char *key)
369{
370 unsigned int keylen = strlen(key);
371 unsigned int hashval = hash_superfast(key, keylen);
372 unsigned int pos = hashval % hash->n_buckets;
373 const struct hash_bucket *bucket = hash->buckets + pos;
374 const struct hash_entry se = {
375 .key = key,
376 .value = NULL
377 };
378 const struct hash_entry *entry = bsearch(
379 &se, bucket->entries, bucket->used,
380 sizeof(struct hash_entry), hash_entry_cmp);
381 if (entry == NULL)
382 return NULL;
383 return (void *)entry->value;
384}
385
386static int hash_del(struct hash *hash, const char *key)
387{
388 unsigned int keylen = strlen(key);
389 unsigned int hashval = hash_superfast(key, keylen);
390 unsigned int pos = hashval % hash->n_buckets;
391 unsigned int steps_used, steps_total;
392 struct hash_bucket *bucket = hash->buckets + pos;
393 struct hash_entry *entry, *entry_end;
394 const struct hash_entry se = {
395 .key = key,
396 .value = NULL
397 };
398
399 entry = bsearch(&se, bucket->entries, bucket->used,
400 sizeof(struct hash_entry), hash_entry_cmp);
401 if (entry == NULL)
402 return -ENOENT;
403
404 entry_end = bucket->entries + bucket->used;
405 memmove(entry, entry + 1,
406 (entry_end - entry) * sizeof(struct hash_entry));
407
408 bucket->used--;
409 hash->count--;
410
411 steps_used = bucket->used / hash->step;
412 steps_total = bucket->total / hash->step;
413 if (steps_used + 1 < steps_total) {
414 size_t size = (steps_used + 1) *
415 hash->step * sizeof(struct hash_entry);
416 struct hash_entry *tmp = realloc(bucket->entries, size);
417 if (tmp) {
418 bucket->entries = tmp;
419 bucket->total = (steps_used + 1) * hash->step;
420 }
421 }
422
423 return 0;
424}
425
426static unsigned int hash_get_count(const struct hash *hash)
427{
428 return hash->count;
429}
430
431/* basic pointer array growing in steps ******************************/
432struct array {
433 void **array;
434 size_t count;
435 size_t total;
436 size_t step;
437};
438
439static void array_init(struct array *array, size_t step)
440{
441 assert(step > 0);
442 array->array = NULL;
443 array->count = 0;
444 array->total = 0;
445 array->step = step;
446}
447
448static int array_append(struct array *array, const void *element)
449{
450 size_t idx;
451
452 if (array->count + 1 >= array->total) {
453 size_t new_total = array->total + array->step;
454 void *tmp = realloc(array->array, sizeof(void *) * new_total);
455 assert(array->step > 0);
456 if (tmp == NULL)
457 return -ENOMEM;
458 array->array = tmp;
459 array->total = new_total;
460 }
461 idx = array->count;
462 array->array[idx] = (void *)element;
463 array->count++;
464 return idx;
465}
466
467static int array_append_unique(struct array *array, const void *element)
468{
469 void **itr = array->array;
470 void **itr_end = itr + array->count;
471 for (; itr < itr_end; itr++)
472 if (*itr == element)
473 return -EEXIST;
474 return array_append(array, element);
475}
476
477static void array_pop(struct array *array) {
478 array->count--;
479 if (array->count + array->step < array->total) {
480 size_t new_total = array->total - array->step;
481 void *tmp = realloc(array->array, sizeof(void *) * new_total);
482 assert(array->step > 0);
483 if (tmp == NULL)
484 return;
485 array->array = tmp;
486 array->total = new_total;
487 }
488}
489
490static void array_free_array(struct array *array) {
491 free(array->array);
492 array->count = 0;
493 array->total = 0;
494}
495
496
497static void array_sort(struct array *array, int (*cmp)(const void *a, const void *b))
498{
499 qsort(array->array, array->count, sizeof(void *), cmp);
500}
501
502/* configuration parsing **********************************************/
503struct cfg_override {
504 struct cfg_override *next;
505 size_t len;
506 char path[];
507};
508
509struct cfg_search {
510 struct cfg_search *next;
511 uint8_t builtin;
512 size_t len;
513 char path[];
514};
515
516struct cfg {
517 const char *kversion;
518 char dirname[PATH_MAX];
519 size_t dirnamelen;
520 char sym_prefix;
521 uint8_t check_symvers;
522 uint8_t print_unknown;
523 uint8_t warn_dups;
524 struct cfg_override *overrides;
525 struct cfg_search *searches;
526};
527
528static int cfg_search_add(struct cfg *cfg, const char *path, uint8_t builtin)
529{
530 struct cfg_search *s;
531 size_t len;
532
533 if (builtin)
534 len = 0;
535 else
536 len = strlen(path) + 1;
537
538 s = malloc(sizeof(struct cfg_search) + len);
539 if (s == NULL) {
540 ERR("search add: out of memory\n");
541 return -ENOMEM;
542 }
543 s->builtin = builtin;
544 if (builtin)
545 s->len = 0;
546 else {
547 s->len = len;
548 memcpy(s->path, path, len);
549 }
550
551 DBG("search add: %s, builtin=%hhu\n", path, builtin);
552
553 s->next = cfg->searches;
554 cfg->searches = s;
555 return 0;
556}
557
558static void cfg_search_free(struct cfg_search *s)
559{
560 free(s);
561}
562
563static int cfg_override_add(struct cfg *cfg, const char *modname, const char *subdir)
564{
565 struct cfg_override *o;
566 size_t modnamelen = strlen(modname);
567 size_t subdirlen = strlen(subdir);
568 size_t i;
569
570 o = malloc(sizeof(struct cfg_override) + cfg->dirnamelen + 1 +
571 subdirlen + 1 + modnamelen + 1);
572 if (o == NULL) {
573 ERR("override add: out of memory\n");
574 return -ENOMEM;
575 }
576 memcpy(o->path, cfg->dirname, cfg->dirnamelen);
577 i = cfg->dirnamelen;
578 o->path[i] = '/';
579 i++;
580
581 memcpy(o->path + i, subdir, subdirlen);
582 i += subdirlen;
583 o->path[i] = '/';
584 i++;
585
586 memcpy(o->path + i, modname, modnamelen);
587 i += modnamelen;
588 o->path[i] = '\0'; /* no extension, so we can match .ko/.ko.gz */
589
590 o->len = i;
591
592 DBG("override add: %s\n", o->path);
593
594 o->next = cfg->overrides;
595 cfg->overrides = o;
596 return 0;
597}
598
599static void cfg_override_free(struct cfg_override *o)
600{
601 free(o);
602}
603
604static int cfg_kernel_matches(const struct cfg *cfg, const char *pattern)
605{
606 regex_t re;
607 int status;
608
609 /* old style */
610 if (streq(pattern, "*"))
611 return 1;
612
613 if (regcomp(&re, pattern, REG_EXTENDED|REG_NOSUB) != 0)
614 return 0;
615
616 status = regexec(&re, cfg->kversion, 0, NULL, 0);
617 regfree(&re);
618
619 return status == 0;
620}
621
622/* same as libkmod-util.c */
623static char *getline_wrapped(FILE *fp, unsigned int *linenum)
624{
625 int size = 256;
626 int i = 0;
627 char *buf = malloc(size);
628
629 for(;;) {
630 int ch = getc_unlocked(fp);
631
632 switch(ch) {
633 case EOF:
634 if (i == 0) {
635 free(buf);
636 return NULL;
637 }
638 /* else fall through */
639
640 case '\n':
641 if (linenum)
642 (*linenum)++;
643 if (i == size)
644 buf = realloc(buf, size + 1);
645 buf[i] = '\0';
646 return buf;
647
648 case '\\':
649 ch = getc_unlocked(fp);
650
651 if (ch == '\n') {
652 if (linenum)
653 (*linenum)++;
654 continue;
655 }
656 /* else fall through */
657
658 default:
659 buf[i++] = ch;
660
661 if (i == size) {
662 size *= 2;
663 buf = realloc(buf, size);
664 }
665 }
666 }
667}
668
669static int cfg_file_parse(struct cfg *cfg, const char *filename)
670{
671 char *line;
672 FILE *fp;
673 unsigned int linenum = 0;
674 int err;
675
676 fp = fopen(filename, "r");
677 if (fp == NULL) {
678 err = -errno;
679 ERR("file parse %s: %m", filename);
680 return err;
681 }
682
683 while ((line = getline_wrapped(fp, &linenum)) != NULL) {
684 char *cmd, *saveptr;
685
686 if (line[0] == '\0' || line[0] == '#')
687 goto done_next;
688
689 cmd = strtok_r(line, "\t ", &saveptr);
690 if (cmd == NULL)
691 goto done_next;
692
693 if (streq(cmd, "search")) {
694 const char *sp;
695 while ((sp = strtok_r(NULL, "\t ", &saveptr)) != NULL) {
696 uint8_t builtin = streq(sp, CFG_BUILTIN_KEY);
697 cfg_search_add(cfg, sp, builtin);
698 }
699 } else if (streq(cmd, "override")) {
700 const char *modname = strtok_r(NULL, "\t ", &saveptr);
701 const char *version = strtok_r(NULL, "\t ", &saveptr);
702 const char *subdir = strtok_r(NULL, "\t ", &saveptr);
703
704 if (modname == NULL || version == NULL ||
705 subdir == NULL)
706 goto syntax_error;
707
708 if (!cfg_kernel_matches(cfg, version)) {
709 INF("%s:%u: override kernel did not match %s\n",
710 filename, linenum, version);
711 goto done_next;
712 }
713
714 cfg_override_add(cfg, modname, subdir);
715 } else if (streq(cmd, "include")
716 || streq(cmd, "make_map_files")) {
717 INF("%s:%u: command %s not implemented yet\n",
718 filename, linenum, cmd);
719 } else {
720syntax_error:
721 ERR("%s:%u: ignoring bad line starting with '%s'\n",
722 filename, linenum, cmd);
723 }
724
725done_next:
726 free(line);
727 }
728
729 fclose(fp);
730
731 return 0;
732}
733
734static int cfg_files_filter_out(DIR *d, const char *dir, const char *name)
735{
736 size_t len = strlen(name);
737 struct stat st;
738
739 if (name[0] == '.')
740 return 1;
741
742 if (len < 6 || !streq(name + len - 5, ".conf")) {
743 INF("All cfg files need .conf: %s/%s\n", dir, name);
744 return 1;
745 }
746
747 fstatat(dirfd(d), name, &st, 0);
748 if (S_ISDIR(st.st_mode)) {
749 ERR("Directories inside directories are not supported: %s/%s\n",
750 dir, name);
751 return 1;
752 }
753
754 return 0;
755}
756
757struct cfg_file {
758 size_t dirlen;
759 size_t namelen;
760 const char *name;
761 char path[];
762};
763
764static void cfg_file_free(struct cfg_file *f)
765{
766 free(f);
767}
768
769static int cfg_files_insert_sorted(struct cfg_file ***p_files, size_t *p_n_files,
770 const char *dir, const char *name)
771{
772 struct cfg_file **files, *f;
773 size_t i, n_files, namelen, dirlen;
774 void *tmp;
775
776 dirlen = strlen(dir);
777 if (name != NULL)
778 namelen = strlen(name);
779 else {
780 name = basename(dir);
781 namelen = strlen(name);
782 dirlen -= namelen - 1;
783 }
784
785 n_files = *p_n_files;
786 files = *p_files;
787 for (i = 0; i < n_files; i++) {
788 int cmp = strcmp(name, files[i]->name);
789 if (cmp == 0) {
790 DBG("Ignoring duplicate config file: %.*s/%s\n",
791 (int)dirlen, dir, name);
792 return -EEXIST;
793 } else if (cmp < 0)
794 break;
795 }
796
797 f = malloc(sizeof(struct cfg_file) + dirlen + namelen + 2);
798 if (f == NULL) {
799 ERR("files insert sorted: out of memory\n");
800 return -ENOMEM;
801 }
802
803 tmp = realloc(files, sizeof(struct cfg_file *) * (n_files + 1));
804 if (tmp == NULL) {
805 ERR("files insert sorted: out of memory\n");
806 free(f);
807 return -ENOMEM;
808 }
809 *p_files = files = tmp;
810
811 if (i < n_files) {
812 memmove(files + i + 1, files + i,
813 sizeof(struct cfg_file *) * (n_files - i));
814 }
815 files[i] = f;
816
817 f->dirlen = dirlen;
818 f->namelen = namelen;
819 f->name = f->path + dirlen + 1;
820 memcpy(f->path, dir, dirlen);
821 f->path[dirlen] = '/';
822 memcpy(f->path + dirlen + 1, name, namelen);
823 f->path[dirlen + 1 + namelen] = '\0';
824
825 *p_n_files = n_files + 1;
826 return 0;
827}
828
829/*
830 * Insert configuration files ignoring duplicates
831 */
832static int cfg_files_list(struct cfg_file ***p_files, size_t *p_n_files,
833 const char *path)
834{
835 DIR *d;
836 int err = 0;
837 struct stat st;
838
839 if (stat(path, &st) != 0) {
840 err = -errno;
841 DBG("could not stat '%s': %m\n", path);
842 return err;
843 }
844
845 if (S_ISREG(st.st_mode)) {
846 cfg_files_insert_sorted(p_files, p_n_files, path, NULL);
847 return 0;
848 } if (!S_ISDIR(st.st_mode)) {
849 ERR("unsupported file mode %s: %#x\n", path, st.st_mode);
850 return -EINVAL;
851 }
852
853 d = opendir(path);
854 if (d == NULL) {
855 ERR("files list %s: %m\n", path);
856 return -EINVAL;
857 }
858
859 for (;;) {
860 struct dirent ent, *entp;
861
862 err = readdir_r(d, &ent, &entp);
863 if (err != 0) {
864 ERR("reading entry %s\n", strerror(-err));
865 break;
866 }
867 if (entp == NULL)
868 break;
869 if (cfg_files_filter_out(d, path, entp->d_name))
870 continue;
871
872 cfg_files_insert_sorted(p_files, p_n_files, path, entp->d_name);
873 }
874
875 closedir(d);
876 DBG("parsed configuration files from %s: %s\n", path, strerror(-err));
877 return err;
878}
879
880static int cfg_load(struct cfg *cfg, const char * const *cfg_paths)
881{
882 size_t i, n_files = 0;
883 struct cfg_file **files = NULL;
884
885 if (cfg_paths == NULL)
886 cfg_paths = default_cfg_paths;
887
888 for (i = 0; cfg_paths[i] != NULL; i++)
889 cfg_files_list(&files, &n_files, cfg_paths[i]);
890
891 for (i = 0; i < n_files; i++) {
892 struct cfg_file *f = files[i];
893 cfg_file_parse(cfg, f->path);
894 cfg_file_free(f);
895 }
896 free(files);
897
898 /* For backward compatibility add "updates" to the head of the search
899 * list here. But only if there was no "search" option specified.
900 */
901 if (cfg->searches == NULL)
902 cfg_search_add(cfg, "updates", 0);
903
904 return 0;
905}
906
907static void cfg_free(struct cfg *cfg)
908{
909 while (cfg->overrides) {
910 struct cfg_override *tmp = cfg->overrides;
911 cfg->overrides = cfg->overrides->next;
912 cfg_override_free(tmp);
913 }
914
915 while (cfg->searches) {
916 struct cfg_search *tmp = cfg->searches;
917 cfg->searches = cfg->searches->next;
918 cfg_search_free(tmp);
919 }
920}
921
922
923/* depmod calculations ***********************************************/
924struct mod {
925 struct kmod_module *kmod;
926 const char *path;
927 const char *relpath; /* path relative to '$ROOT/lib/modules/$VER/' */
928 struct array deps; /* struct symbol */
929 size_t baselen; /* points to start of basename/filename */
930 size_t modnamelen;
931 int sort_idx; /* sort index using modules.order */
932 int dep_sort_idx; /* topological sort index */
933 uint16_t idx; /* index in depmod->modules.array */
934 uint16_t users; /* how many modules depend on this one */
935 uint8_t dep_loop : 1;
936 char modname[];
937};
938
939struct symbol {
940 struct mod *owner;
941 uint64_t crc;
942 char name[];
943};
944
945struct depmod {
946 const struct cfg *cfg;
947 struct kmod_ctx *ctx;
948 struct array modules;
949 struct hash *modules_by_relpath;
950 struct hash *modules_by_name;
951 struct hash *symbols;
952 unsigned int dep_loops;
953};
954
955static void mod_free(struct mod *mod)
956{
957 DBG("free %p kmod=%p, path=%s\n", mod, mod->kmod, mod->path);
958 array_free_array(&mod->deps);
959 kmod_module_unref(mod->kmod);
960 free(mod);
961}
962
963static int mod_add_dependency(struct mod *mod, struct symbol *sym)
964{
965 int err;
966
967 DBG("%s depends on %s %s\n", mod->path, sym->name,
968 sym->owner != NULL ? sym->owner->path : "(unknown)");
969
970 if (sym->owner == NULL)
971 return 0;
972
973 err = array_append_unique(&mod->deps, sym->owner);
974 if (err == -EEXIST)
975 return 0;
976 if (err < 0)
977 return err;
978
979 sym->owner->users++;
980 SHOW("%s needs \"%s\": %s\n", mod->path, sym->name, sym->owner->path);
981 return 0;
982}
983
984static void symbol_free(struct symbol *sym)
985{
986 DBG("free %p sym=%s, owner=%p %s\n", sym, sym->name, sym->owner,
987 sym->owner != NULL ? sym->owner->path : "");
988 free(sym);
989}
990
991static int depmod_init(struct depmod *depmod, struct cfg *cfg, struct kmod_ctx *ctx)
992{
993 int err = 0;
994
995 depmod->cfg = cfg;
996 depmod->ctx = ctx;
997
998 array_init(&depmod->modules, 128);
999
1000 depmod->modules_by_relpath = hash_new(512, NULL);
1001 if (depmod->modules_by_relpath == NULL) {
1002 err = -errno;
1003 goto modules_by_relpath_failed;
1004 }
1005
1006 depmod->modules_by_name = hash_new(512, NULL);
1007 if (depmod->modules_by_name == NULL) {
1008 err = -errno;
1009 goto modules_by_name_failed;
1010 }
1011
1012 depmod->symbols = hash_new(2048, (void (*)(void *))symbol_free);
1013 if (depmod->symbols == NULL) {
1014 err = -errno;
1015 goto symbols_failed;
1016 }
1017
1018 return 0;
1019
1020symbols_failed:
1021 hash_free(depmod->modules_by_name);
1022modules_by_name_failed:
1023 hash_free(depmod->modules_by_relpath);
1024modules_by_relpath_failed:
1025 return err;
1026}
1027
1028static void depmod_shutdown(struct depmod *depmod)
1029{
1030 size_t i;
1031
1032 hash_free(depmod->symbols);
1033
1034 hash_free(depmod->modules_by_relpath);
1035
1036 hash_free(depmod->modules_by_name);
1037
1038 for (i = 0; i < depmod->modules.count; i++)
1039 mod_free(depmod->modules.array[i]);
1040 array_free_array(&depmod->modules);
1041
1042 kmod_unref(depmod->ctx);
1043}
1044
1045static int depmod_module_add(struct depmod *depmod, struct kmod_module *kmod)
1046{
1047 const struct cfg *cfg = depmod->cfg;
1048 const char *modname;
1049 size_t modnamelen;
1050 struct mod *mod;
1051 int err;
1052
1053 modname = kmod_module_get_name(kmod);
1054 modnamelen = strlen(modname) + 1;
1055
1056 mod = calloc(1, sizeof(struct mod) + modnamelen);
1057 if (mod == NULL)
1058 return -ENOMEM;
1059 mod->kmod = kmod;
1060 mod->sort_idx = depmod->modules.count + 1;
1061 mod->dep_sort_idx = INT32_MAX;
1062 mod->idx = depmod->modules.count;
1063 memcpy(mod->modname, modname, modnamelen);
1064 mod->modnamelen = modnamelen;
1065
1066 array_init(&mod->deps, 4);
1067
1068 mod->path = kmod_module_get_path(kmod);
1069 mod->baselen = strrchr(mod->path, '/') - mod->path + 1;
1070 if (strncmp(mod->path, cfg->dirname, cfg->dirnamelen) == 0 &&
1071 mod->path[cfg->dirnamelen] == '/')
1072 mod->relpath = mod->path + cfg->dirnamelen + 1;
1073 else
1074 mod->relpath = NULL;
1075
1076 err = array_append(&depmod->modules, mod);
1077 if (err < 0) {
1078 free(mod);
1079 return err;
1080 }
1081
1082 err = hash_add_unique(depmod->modules_by_name, mod->modname, mod);
1083 if (err < 0) {
1084 ERR("hash_add_unique %s: %s\n", mod->modname, strerror(-err));
1085 array_pop(&depmod->modules);
1086 free(mod);
1087 return err;
1088 }
1089
1090 if (mod->relpath != NULL) {
1091 err = hash_add_unique(depmod->modules_by_relpath,
1092 mod->relpath, mod);
1093 if (err < 0) {
1094 ERR("hash_add_unique %s: %s\n",
1095 mod->relpath, strerror(-err));
1096 hash_del(depmod->modules_by_name, mod->modname);
1097 array_pop(&depmod->modules);
1098 free(mod);
1099 return err;
1100 }
1101 }
1102
1103 DBG("add %p kmod=%p, path=%s\n", mod, kmod, mod->path);
1104
1105 return 0;
1106}
1107
1108static int depmod_module_replace(struct depmod *depmod, struct mod *mod, struct kmod_module *kmod)
1109{
1110 const struct cfg *cfg = depmod->cfg;
1111 const char *path, *relpath;
1112 int err;
1113
1114 path = kmod_module_get_path(kmod);
1115 if (strncmp(path, cfg->dirname, cfg->dirnamelen) == 0 &&
1116 path[cfg->dirnamelen] == '/')
1117 relpath = path + cfg->dirnamelen + 1;
1118 else
1119 relpath = NULL;
1120
1121 if (relpath != NULL) {
1122 err = hash_add_unique(depmod->modules_by_relpath, relpath, mod);
1123 if (err < 0) {
1124 ERR("hash_add_unique %s: %s\n",
1125 relpath, strerror(-err));
1126 return err;
1127 }
1128 }
1129
1130 if (mod->relpath != NULL)
1131 hash_del(depmod->modules_by_relpath, mod->relpath);
1132 kmod_module_unref(mod->kmod);
1133 mod->relpath = relpath;
1134 mod->path = path;
1135 mod->kmod = kmod;
1136 return 0;
1137}
1138
1139/* returns if existing module @mod is higher priority than newpath.
1140 * note this is the inverse of module-init-tools is_higher_priority()
1141 */
1142static 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)
1143{
1144 const struct cfg *cfg = depmod->cfg;
1145 const struct cfg_override *ov;
1146 const struct cfg_search *se;
1147 size_t newlen = baselen + modnamelen;
1148 size_t oldlen = mod->baselen + mod->modnamelen;
1149 const char *oldpath = mod->path;
1150 int i, bprio = -1, oldprio = -1, newprio = -1;
1151
1152 DBG("comparing priorities of %s and %s\n",
1153 oldpath, newpath);
1154
1155 for (ov = cfg->overrides; ov != NULL; ov = ov->next) {
1156 DBG("override %s\n", ov->path);
1157 if (newlen == ov->len && memcmp(ov->path, newpath, newlen) == 0)
1158 return 0;
1159 if (oldlen == ov->len && memcmp(ov->path, oldpath, oldlen) == 0)
1160 return 1;
1161 }
1162
1163 for (i = 0, se = cfg->searches; se != NULL; se = se->next, i++) {
1164 DBG("search %s\n", se->builtin ? "built-in" : se->path);
1165 if (se->builtin)
1166 bprio = i;
1167 else if (newlen >= se->len &&
1168 memcmp(se->path, newpath, se->len) == 0)
1169 newprio = i;
1170 else if (oldlen >= se->len &&
1171 memcmp(se->path, oldpath, se->len) == 0)
1172 oldprio = i;
1173 }
1174
1175 if (newprio < 0)
1176 newprio = bprio;
1177 if (oldprio < 0)
1178 oldprio = bprio;
1179
1180 DBG("priorities: built-in: %d, old: %d, new: %d\n",
1181 bprio, newprio, oldprio);
1182
1183 return newprio <= oldprio;
1184}
1185
1186static int depmod_modules_search_file(struct depmod *depmod, size_t baselen, size_t namelen, const char *path)
1187{
1188 struct kmod_module *kmod;
1189 struct mod *mod;
1190 const char *relpath, *modname;
1191 const struct ext {
1192 const char *ext;
1193 size_t len;
1194 } *eitr, exts[] = {
1195 {".ko", sizeof(".ko") - 1},
1196 {".ko.gz", sizeof(".ko.gz") - 1},
1197 {NULL, 0},
1198 };
1199 size_t modnamelen;
1200 uint8_t matches = 0;
1201 int err = 0;
1202
1203 for (eitr = exts; eitr->ext != NULL; eitr++) {
1204 if (namelen <= eitr->len)
1205 continue;
1206 if (streq(path + baselen + namelen - eitr->len, eitr->ext)) {
1207 matches = 1;
1208 break;
1209 }
1210 }
1211 if (!matches)
1212 return 0;
1213
1214 relpath = path + depmod->cfg->dirnamelen + 1;
1215 DBG("try %s\n", relpath);
1216
1217 err = kmod_module_new_from_path(depmod->ctx, path, &kmod);
1218 if (err < 0) {
1219 ERR("Could not create module %s: %s\n",
1220 path, strerror(-err));
1221 return err;
1222 }
1223
1224 modname = kmod_module_get_name(kmod);
1225 mod = hash_find(depmod->modules_by_name, modname);
1226 if (mod == NULL) {
1227 err = depmod_module_add(depmod, kmod);
1228 if (err < 0) {
1229 ERR("Could not add module %s: %s\n",
1230 path, strerror(-err));
1231 kmod_module_unref(kmod);
1232 return err;
1233 }
1234 return 0;
1235 }
1236
1237 modnamelen = strlen(modname);
1238 if (depmod_module_is_higher_priority(depmod, mod, baselen,
1239 namelen, modnamelen, path)) {
1240 DBG("Ignored lower priority: %s, higher: %s\n",
1241 path, mod->path);
1242 kmod_module_unref(kmod);
1243 return 0;
1244 }
1245
1246 err = depmod_module_replace(depmod, mod, kmod);
1247 if (err < 0) {
1248 ERR("Could not replace existing module %s\n", path);
1249 kmod_module_unref(kmod);
1250 return err;
1251 }
1252
1253 return 0;
1254}
1255
1256static int depmod_modules_search_dir(struct depmod *depmod, DIR *d, size_t baselen, char *path)
1257{
1258 struct dirent *de;
1259 int err = 0, dfd = dirfd(d);
1260
1261 while ((de = readdir(d)) != NULL) {
1262 const char *name = de->d_name;
1263 size_t namelen;
1264 uint8_t is_dir;
1265
1266 if (name[0] == '.' && (name[1] == '\0' ||
1267 (name[1] == '.' && name[2] == '\0')))
1268 continue;
1269 if (streq(name, "build") || streq(name, "source"))
1270 continue;
1271 namelen = strlen(name);
1272 if (baselen + namelen + 2 >= PATH_MAX) {
1273 path[baselen] = '\0';
1274 ERR("path is too long %s%s %zd\n", path, name);
1275 continue;
1276 }
1277 memcpy(path + baselen, name, namelen + 1);
1278
1279 if (de->d_type == DT_REG)
1280 is_dir = 0;
1281 else if (de->d_type == DT_DIR)
1282 is_dir = 1;
1283 else {
1284 struct stat st;
1285 if (fstatat(dfd, name, &st, 0) < 0) {
1286 ERR("fstatat(%d, %s): %m\n", dfd, name);
1287 continue;
1288 } else if (S_ISREG(st.st_mode))
1289 is_dir = 0;
1290 else if (S_ISDIR(st.st_mode))
1291 is_dir = 1;
1292 else {
1293 ERR("unsupported file type %s: %o\n",
1294 path, st.st_mode & S_IFMT);
1295 continue;
1296 }
1297 }
1298
1299 if (is_dir) {
1300 int fd;
1301 DIR *subdir;
1302 if (baselen + namelen + 2 + NAME_MAX >= PATH_MAX) {
1303 ERR("directory path is too long %s\n", path);
1304 continue;
1305 }
1306 fd = openat(dfd, name, O_RDONLY);
1307 if (fd < 0) {
1308 ERR("openat(%d, %s, O_RDONLY): %m\n",
1309 dfd, name);
1310 continue;
1311 }
1312 subdir = fdopendir(fd);
1313 if (subdir == NULL) {
1314 ERR("fdopendir(%d): %m\n", fd);
1315 close(fd);
1316 continue;
1317 }
1318 path[baselen + namelen] = '/';
1319 path[baselen + namelen + 1] = '\0';
1320 err = depmod_modules_search_dir(depmod, subdir,
1321 baselen + namelen + 1,
1322 path);
1323 closedir(subdir);
1324 } else {
1325 err = depmod_modules_search_file(depmod, baselen,
1326 namelen, path);
1327 }
1328
1329 if (err < 0) {
1330 path[baselen + namelen] = '\0';
1331 ERR("failed %s: %s\n", path, strerror(-err));
1332 err = 0; /* ignore errors */
1333 }
1334 }
1335
1336 return err;
1337}
1338
1339static int depmod_modules_search(struct depmod *depmod)
1340{
1341 char path[PATH_MAX];
1342 DIR *d = opendir(depmod->cfg->dirname);
1343 size_t baselen;
1344 int err;
1345 if (d == NULL) {
1346 err = -errno;
1347 ERR("Couldn't open directory %s: %m\n", depmod->cfg->dirname);
1348 return err;
1349 }
1350
1351 baselen = depmod->cfg->dirnamelen;
1352 memcpy(path, depmod->cfg->dirname, baselen);
1353 path[baselen] = '/';
1354 baselen++;
1355 path[baselen] = '\0';
1356
1357 err = depmod_modules_search_dir(depmod, d, baselen, path);
1358 closedir(d);
1359 return 0;
1360}
1361
1362static int mod_cmp(const void *pa, const void *pb) {
1363 const struct mod *a = *(const struct mod **)pa;
1364 const struct mod *b = *(const struct mod **)pb;
1365 if (a->dep_loop == b->dep_loop)
1366 return a->sort_idx - b->sort_idx;
1367 else if (a->dep_loop)
1368 return 1;
1369 else if (b->dep_loop)
1370 return -1;
1371 return a->sort_idx - b->sort_idx;
1372}
1373
1374static void depmod_modules_sort(struct depmod *depmod)
1375{
1376 char order_file[PATH_MAX], line[PATH_MAX];
1377 FILE *fp;
1378 unsigned idx = 0, total = 0;
1379
1380 snprintf(order_file, sizeof(order_file), "%s/modules.order",
1381 depmod->cfg->dirname);
1382 fp = fopen(order_file, "r");
1383 if (fp == NULL) {
1384 ERR("could not open %s: %m\n", order_file);
1385 return;
1386 }
1387
1388 while (fgets(line, sizeof(line), fp) != NULL) {
1389 size_t len = strlen(line);
1390 idx++;
1391 if (len == 0)
1392 continue;
1393 if (line[len - 1] != '\n') {
1394 ERR("%s:%u corrupted line misses '\\n'\n",
1395 order_file, idx);
1396 goto corrupted;
1397 }
1398 }
1399 total = idx + 1;
1400 idx = 0;
1401 fseek(fp, 0, SEEK_SET);
1402 while (fgets(line, sizeof(line), fp) != NULL) {
1403 size_t len = strlen(line);
1404 struct mod *mod;
1405
1406 idx++;
1407 if (len == 0)
1408 continue;
1409 line[len - 1] = '\0';
1410
1411 mod = hash_find(depmod->modules_by_relpath, line);
1412 if (mod == NULL)
1413 continue;
1414 mod->sort_idx = idx - total;
1415 }
1416
1417 array_sort(&depmod->modules, mod_cmp);
1418 for (idx = 0; idx < depmod->modules.count; idx++) {
1419 struct mod *m = depmod->modules.array[idx];
1420 m->idx = idx;
1421 }
1422
1423corrupted:
1424 fclose(fp);
1425}
1426
1427static int depmod_symbol_add(struct depmod *depmod, const char *name, uint64_t crc, const struct mod *owner)
1428{
1429 size_t namelen;
1430 int err;
1431 struct symbol *sym;
1432
1433 if (name[0] == depmod->cfg->sym_prefix)
1434 name++;
1435
1436 namelen = strlen(name) + 1;
1437 sym = malloc(sizeof(struct symbol) + namelen);
1438 if (sym == NULL)
1439 return -ENOMEM;
1440
1441 sym->owner = (struct mod *)owner;
1442 sym->crc = crc;
1443 memcpy(sym->name, name, namelen);
1444
1445 err = hash_add(depmod->symbols, sym->name, sym);
1446 if (err < 0) {
1447 free(sym);
1448 return err;
1449 }
1450
1451 DBG("add %p sym=%s, owner=%p %s\n", sym, sym->name, owner,
1452 owner != NULL ? owner->path : "");
1453
1454 return 0;
1455}
1456
1457static struct symbol *depmod_symbol_find(const struct depmod *depmod, const char *name)
1458{
1459 if (name[0] == '.') /* PPC64 needs this: .foo == foo */
1460 name++;
1461 if (name[0] == depmod->cfg->sym_prefix)
1462 name++;
1463 return hash_find(depmod->symbols, name);
1464}
1465
1466static int depmod_load_symbols(struct depmod *depmod)
1467{
1468 const struct mod **itr, **itr_end;
1469
1470 DBG("load symbols (%zd modules)\n", depmod->modules.count);
1471
1472 itr = (const struct mod **)depmod->modules.array;
1473 itr_end = itr + depmod->modules.count;
1474 for (; itr < itr_end; itr++) {
1475 const struct mod *mod = *itr;
1476 struct kmod_list *l, *list = NULL;
1477 int err = kmod_module_get_symbols(mod->kmod, &list);
1478 if (err < 0) {
1479 DBG("ignoring %s: no symbols: %s\n",
1480 mod->path, strerror(-err));
1481 continue;
1482 }
1483 kmod_list_foreach(l, list) {
1484 const char *name = kmod_module_symbol_get_symbol(l);
1485 uint64_t crc = kmod_module_symbol_get_crc(l);
1486 depmod_symbol_add(depmod, name, crc, mod);
1487 }
1488 kmod_module_symbols_free_list(list);
1489 }
1490
1491 DBG("loaded symbols (%zd modules, %zd symbols)\n",
1492 depmod->modules.count, hash_get_count(depmod->symbols));
1493
1494 return 0;
1495}
1496
1497static int depmod_load_module_dependencies(struct depmod *depmod, struct mod *mod)
1498{
1499 const struct cfg *cfg = depmod->cfg;
1500 struct kmod_list *l, *list = NULL;
1501 int err = kmod_module_get_dependency_symbols(mod->kmod, &list);
1502 if (err < 0) {
1503 DBG("ignoring %s: no dependency symbols: %s\n",
1504 mod->path, strerror(-err));
1505 return 0;
1506 }
1507
1508 DBG("do dependencies of %s\n", mod->path);
1509 kmod_list_foreach(l, list) {
1510 const char *name = kmod_module_dependency_symbol_get_symbol(l);
1511 uint64_t crc = kmod_module_dependency_symbol_get_crc(l);
1512 int bind = kmod_module_dependency_symbol_get_bind(l);
1513 struct symbol *sym = depmod_symbol_find(depmod, name);
1514 uint8_t is_weak = bind == KMOD_SYMBOL_WEAK;
1515
1516 if (sym == NULL) {
1517 DBG("%s needs (%c) unknown symbol %s\n",
1518 mod->path, bind, name);
1519 if (cfg->print_unknown && !is_weak)
1520 WRN("%s needs unknown symbol %s\n",
1521 mod->path, name);
1522 continue;
1523 }
1524
1525 if (cfg->check_symvers && sym->crc != crc && !is_weak) {
1526 DBG("symbol %s (%#"PRIx64") module %s (%#"PRIx64")\n",
1527 sym->name, sym->crc, mod->path, crc);
1528 if (cfg->print_unknown)
1529 WRN("%s disagrees about version of symbol %s\n",
1530 mod->path, name);
1531 }
1532
1533 mod_add_dependency(mod, sym);
1534 }
1535 kmod_module_dependency_symbols_free_list(list);
1536 return 0;
1537}
1538
1539static int depmod_load_dependencies(struct depmod *depmod)
1540{
1541 struct mod **itr, **itr_end;
1542
1543 DBG("load dependencies (%zd modules, %zd symbols)\n",
1544 depmod->modules.count, hash_get_count(depmod->symbols));
1545
1546 itr = (struct mod **)depmod->modules.array;
1547 itr_end = itr + depmod->modules.count;
1548 for (; itr < itr_end; itr++) {
1549 struct mod *mod = *itr;
1550 depmod_load_module_dependencies(depmod, mod);
1551 }
1552
1553 DBG("loaded dependencies (%zd modules, %zd symbols)\n",
1554 depmod->modules.count, hash_get_count(depmod->symbols));
1555
1556 return 0;
1557}
1558
1559static int dep_cmp(const void *pa, const void *pb)
1560{
1561 const struct mod *a = *(const struct mod **)pa;
1562 const struct mod *b = *(const struct mod **)pb;
1563 if (a->dep_loop == b->dep_loop)
1564 return a->dep_sort_idx - b->dep_sort_idx;
1565 else if (a->dep_loop)
1566 return 1;
1567 else if (b->dep_loop)
1568 return -1;
1569 return a->dep_sort_idx - b->dep_sort_idx;
1570}
1571
1572static void depmod_sort_dependencies(struct depmod *depmod)
1573{
1574 struct mod **itr, **itr_end;
1575 itr = (struct mod **)depmod->modules.array;
1576 itr_end = itr + depmod->modules.count;
1577 for (; itr < itr_end; itr++) {
1578 struct mod *m = *itr;
1579 if (m->deps.count > 1)
1580 array_sort(&m->deps, dep_cmp);
1581 }
1582}
1583
1584static int depmod_calculate_dependencies(struct depmod *depmod)
1585{
1586 const struct mod **itrm;
1587 uint16_t *users, *roots, *sorted;
1588 uint16_t i, n_roots = 0, n_sorted = 0, n_mods = depmod->modules.count;
1589
1590 users = malloc(sizeof(uint16_t) * n_mods * 3);
1591 if (users == NULL)
1592 return -ENOMEM;
1593 roots = users + n_mods;
1594 sorted = roots + n_mods;
1595
1596 DBG("calculate dependencies and ordering (%zd modules)\n", n_mods);
1597
1598 assert(depmod->modules.count < UINT16_MAX);
1599
1600 /* populate modules users (how many modules uses it) */
1601 itrm = (const struct mod **)depmod->modules.array;
1602 for (i = 0; i < n_mods; i++, itrm++) {
1603 const struct mod *m = *itrm;
1604 users[i] = m->users;
1605 if (users[i] == 0) {
1606 roots[n_roots] = i;
1607 n_roots++;
1608 }
1609 }
1610
1611 /* topological sort (outputs modules without users first) */
1612 while (n_roots > 0) {
1613 const struct mod **itr_dst, **itr_dst_end;
1614 struct mod *src;
1615 uint16_t src_idx = roots[--n_roots];
1616
1617 src = depmod->modules.array[src_idx];
1618 src->dep_sort_idx = n_sorted;
1619 sorted[n_sorted] = src_idx;
1620 n_sorted++;
1621
1622 itr_dst = (const struct mod **)src->deps.array;
1623 itr_dst_end = itr_dst + src->deps.count;
1624 for (; itr_dst < itr_dst_end; itr_dst++) {
1625 const struct mod *dst = *itr_dst;
1626 uint16_t dst_idx = dst->idx;
1627 assert(users[dst_idx] > 0);
1628 users[dst_idx]--;
1629 if (users[dst_idx] == 0) {
1630 roots[n_roots] = dst_idx;
1631 n_roots++;
1632 }
1633 }
1634 }
1635
1636 if (n_sorted < n_mods) {
1637 WRN("found %hu modules in dependency cycles!\n",
1638 n_mods - n_sorted);
1639 for (i = 0; i < n_mods; i++) {
1640 struct mod *m;
1641 if (users[i] == 0)
1642 continue;
1643 m = depmod->modules.array[i];
1644 WRN("%s in dependency cycle!\n", m->path);
1645 m->dep_loop = 1;
1646 m->dep_sort_idx = INT32_MAX;
1647 depmod->dep_loops++;
1648 }
1649 }
1650
1651 depmod_sort_dependencies(depmod);
1652
1653 DBG("calculated dependencies and ordering (%u loops, %zd modules)\n",
1654 depmod->dep_loops, n_mods);
1655
1656 free(users);
1657 return 0;
1658}
1659
1660static int depmod_load(struct depmod *depmod)
1661{
1662 int err;
1663
1664 err = depmod_load_symbols(depmod);
1665 if (err < 0)
1666 return err;
1667
1668 err = depmod_load_dependencies(depmod);
1669 if (err < 0)
1670 return err;
1671
1672 err = depmod_calculate_dependencies(depmod);
1673 if (err < 0)
1674 return err;
1675
1676 return 0;
1677}
1678
8e3505c5
GSB
1679static size_t mod_count_all_dependencies(const struct mod *mod)
1680{
1681 size_t i, count = 0;
1682 for (i = 0; i < mod->deps.count; i++) {
1683 const struct mod *d = mod->deps.array[i];
1684 count += 1 + mod_count_all_dependencies(d);
1685 }
1686 return count;
1687}
1688
1689static int mod_fill_all_unique_dependencies(const struct mod *mod, const struct mod **deps, size_t n_deps, size_t *last)
1690{
1691 size_t i;
1692 int err = 0;
1693 for (i = 0; i < mod->deps.count; i++) {
1694 const struct mod *d = mod->deps.array[i];
1695 size_t j;
1696 uint8_t exists = 0;
1697
1698 for (j = 0; j < *last; j++) {
1699 if (deps[j] == d) {
1700 exists = 1;
1701 break;
1702 }
1703 }
1704
1705 if (exists)
1706 continue;
1707
1708 if (*last >= n_deps)
1709 return -ENOSPC;
1710 deps[*last] = d;
1711 (*last)++;
1712 err = mod_fill_all_unique_dependencies(d, deps, n_deps, last);
1713 if (err < 0)
1714 break;
1715 }
1716 return err;
1717}
1718
1719static const struct mod **mod_get_all_sorted_dependencies(const struct mod *mod, size_t *n_deps)
1720{
1721 const struct mod **deps;
1722 size_t last = 0;
1723
1724 *n_deps = mod_count_all_dependencies(mod);
1725 if (*n_deps == 0)
1726 return NULL;
1727
1728 deps = malloc(sizeof(struct mod *) * (*n_deps));
1729 if (deps == NULL)
1730 return NULL;
1731
1732 if (mod_fill_all_unique_dependencies(mod, deps, *n_deps, &last) < 0) {
1733 free(deps);
1734 return NULL;
1735 }
1736
1737 qsort(deps, last, sizeof(struct mod *), dep_cmp);
1738 *n_deps = last;
1739 return deps;
1740}
1741
1742static inline const char *mod_get_compressed_path(const struct mod *mod)
1743{
1744 if (mod->relpath != NULL)
1745 return mod->relpath;
1746 return mod->path;
1747}
1748
1749static int output_deps(struct depmod *depmod, FILE *out)
1750{
1751 size_t i;
1752
1753 for (i = 0; i < depmod->modules.count; i++) {
1754 const struct mod **deps, *mod = depmod->modules.array[i];
1755 const char *p = mod_get_compressed_path(mod);
1756 size_t j, n_deps;
1757
1758 if (mod->dep_loop) {
1759 DBG("Ignored %s due dependency loops\n", p);
1760 continue;
1761 }
1762
1763 fprintf(out, "%s:", p);
1764
1765 if (mod->deps.count == 0)
1766 goto end;
1767
1768 deps = mod_get_all_sorted_dependencies(mod, &n_deps);
1769 if (deps == NULL) {
1770 ERR("Could not get all sorted dependencies of %s\n", p);
1771 goto end;
1772 }
1773
1774 for (j = 0; j < n_deps; j++) {
1775 const struct mod *d = deps[j];
1776 if (d->dep_loop) {
1777 DBG("Ignored %s (dependency of %s) "
1778 "due dependency loops\n",
1779 mod_get_compressed_path(d), p);
1780 continue;
1781 }
1782 fprintf(out, " %s", mod_get_compressed_path(d));
1783 }
1784 free(deps);
1785 end:
1786 putc('\n', out);
1787 }
1788
1789 return 0;
1790}
1791
0d131745
GSB
1792static int output_aliases(struct depmod *depmod, FILE *out)
1793{
1794 size_t i;
1795
1796 fputs("# Aliases extracted from modules themselves.\n", out);
1797
1798 for (i = 0; i < depmod->modules.count; i++) {
1799 const struct mod *mod = depmod->modules.array[i];
1800 struct kmod_list *l, *list = NULL;
1801 int r = kmod_module_get_info(mod->kmod, &list);
1802 if (r < 0 || list == NULL)
1803 continue;
1804 kmod_list_foreach(l, list) {
1805 const char *key = kmod_module_info_get_key(l);
1806 const char *value = kmod_module_info_get_value(l);
1807
1808 if (!streq(key, "alias"))
1809 continue;
1810
1811 fprintf(out, "alias %s %s\n",
1812 value, kmod_module_get_name(mod->kmod));
1813 }
1814 kmod_module_info_free_list(list);
1815 }
1816
1817 return 0;
1818}
1819
8bc830ef
GSB
1820static int output_softdeps(struct depmod *depmod, FILE *out)
1821{
1822 size_t i;
1823
1824 fputs("# Soft dependencies extracted from modules themselves.\n", out);
1825 fputs("# Copy, with a .conf extension, to /etc/modprobe.d to use "
1826 "it with modprobe.\n", out);
1827
1828 for (i = 0; i < depmod->modules.count; i++) {
1829 const struct mod *mod = depmod->modules.array[i];
1830 struct kmod_list *l, *list = NULL;
1831 int r = kmod_module_get_info(mod->kmod, &list);
1832 if (r < 0 || list == NULL)
1833 continue;
1834 kmod_list_foreach(l, list) {
1835 const char *key = kmod_module_info_get_key(l);
1836 const char *value = kmod_module_info_get_value(l);
1837
1838 if (!streq(key, "softdep"))
1839 continue;
1840
1841 fprintf(out, "softdep %s %s\n",
1842 kmod_module_get_name(mod->kmod), value);
1843 }
1844 kmod_module_info_free_list(list);
1845 }
1846
1847 return 0;
1848}
1849
9a14d0e9
GSB
1850static int output_symbols(struct depmod *depmod, FILE *out)
1851{
1852 size_t i;
1853
1854 fputs("# Aliases for symbols, used by symbol_request().\n", out);
1855
1856 for (i = 0; i < depmod->symbols->n_buckets; i++) {
1857 const struct hash_bucket *b = depmod->symbols->buckets + i;
1858 unsigned j;
1859 for (j = 0; j < b->used; j++) {
1860 const struct hash_entry *e = b->entries + j;
1861 const struct symbol *sym = e->value;
1862 if (sym->owner == NULL)
1863 continue;
1864 fprintf(out, "alias symbol:%s %s\n",
1865 sym->name, sym->owner->modname);
1866 }
1867 }
1868
1869 return 0;
1870}
1871
25c41512
GSB
1872static int output_devname(struct depmod *depmod, FILE *out)
1873{
1874 size_t i;
1875
1876 fputs("# Device nodes to trigger on-demand module loading.\n", out);
1877
1878 for (i = 0; i < depmod->modules.count; i++) {
1879 const struct mod *mod = depmod->modules.array[i];
1880 struct kmod_list *l, *list = NULL;
1881 const char *devname = NULL;
1882 char type = '\0';
1883 unsigned int major = 0, minor = 0;
1884 int r;
1885
1886 r = kmod_module_get_info(mod->kmod, &list);
1887 if (r < 0 || list == NULL)
1888 continue;
1889
1890 kmod_list_foreach(l, list) {
1891 const char *key = kmod_module_info_get_key(l);
1892 const char *value = kmod_module_info_get_value(l);
1893 unsigned int maj, min;
1894
1895 if (!streq(key, "alias"))
1896 continue;
1897
1898 if (strstartswith(value, "devname:"))
1899 devname = value + sizeof("devname:") - 1;
1900 else if (sscanf(value, "char-major-%u-%u",
1901 &maj, &min) == 2) {
1902 type = 'c';
1903 major = maj;
1904 minor = min;
1905 } else if (sscanf(value, "block-major-%u-%u",
1906 &maj, &min) == 2) {
1907 type = 'b';
1908 major = maj;
1909 minor = min;
1910 }
1911
1912 if (type != '\0' && devname != NULL) {
1913 fprintf(out, "%s %s %c%u:%u\n",
1914 kmod_module_get_name(mod->kmod),
1915 devname, type, major, minor);
1916 break;
1917 }
1918 }
1919 kmod_module_info_free_list(list);
1920 }
1921
1922 return 0;
1923}
1924
1925static int depmod_output(struct depmod *depmod, FILE *out)
1926{
1927 static const struct depfile {
1928 const char *name;
1929 int (*cb)(struct depmod *depmod, FILE *out);
1930 } *itr, depfiles[] = {
8e3505c5 1931 {"modules.dep", output_deps},
25c41512 1932 //{"modules.dep.bin", output_deps_bin},
0d131745 1933 {"modules.alias", output_aliases},
25c41512 1934 //{"modules.alias.bin", output_aliases_bin},
8bc830ef 1935 {"modules.softdep", output_softdeps},
9a14d0e9 1936 {"modules.symbols", output_symbols},
25c41512
GSB
1937 //{"modules.symbols.bin", output_symbols_bin},
1938 //{"modules.builtin.bin", output_builtin_bin},
1939 {"modules.devname", output_devname},
1940 {NULL, NULL}
1941 };
1942 const char *dname = depmod->cfg->dirname;
1943 int dfd, err = 0;
1944
1945 if (out != NULL)
1946 dfd = -1;
1947 else {
1948 dfd = open(dname, O_RDONLY);
1949 if (dfd < 0) {
1950 err = -errno;
1951 CRIT("Could not open directory %s: %m\n", dname);
1952 return err;
1953 }
1954 }
1955
1956 for (itr = depfiles; itr->name != NULL; itr++) {
1957 FILE *fp = out;
1958 char tmp[NAME_MAX] = "";
1959 int r;
1960
1961 if (fp == NULL) {
1962 int flags = O_CREAT | O_TRUNC | O_WRONLY;
1963 int mode = 0644;
1964 int fd;
1965
1966 snprintf(tmp, sizeof(tmp), "%s.tmp", itr->name);
1967 fd = openat(dfd, tmp, flags, mode);
1968 if (fd < 0) {
1969 ERR("openat(%s, %s, %o, %o): %m\n",
1970 dname, tmp, flags, mode);
1971 continue;
1972 }
1973 fp = fdopen(fd, "wb");
1974 if (fp == NULL) {
1975 ERR("fdopen(%d=%s/%s): %m\n", fd, dname, tmp);
1976 close(fd);
1977 continue;
1978 }
1979 }
1980
1981 r = itr->cb(depmod, fp);
1982 if (fp == out)
1983 continue;
1984
1985 fclose(fp);
1986 if (r < 0) {
1987 if (unlinkat(dfd, tmp, 0) != 0)
1988 ERR("unlinkat(%s, %s): %m\n", dname, tmp);
1989 } else {
1990 unlinkat(dfd, itr->name, 0);
1991 if (renameat(dfd, tmp, dfd, itr->name) != 0) {
1992 err = -errno;
1993 CRIT("renameat(%s, %s, %s, %s): %m\n",
1994 dname, tmp, dname, itr->name);
1995 break;
1996 }
1997 }
1998 }
1999
2000 if (dfd >= 0)
2001 close(dfd);
2002 return err;
2003}
2004
2005
64b8b586
GSB
2006static int depfile_up_to_date(const char *dirname)
2007{
2008 ERR("TODO depfile_up_to_date()\n");
2009 return 0;
2010}
2011
2012static int is_version_number(const char *version)
2013{
2014 unsigned int d1, d2;
2015 return (sscanf(version, "%u.%u", &d1, &d2) == 2);
2016}
2017
2018int main(int argc, char *argv[])
2019{
2020 FILE *out = NULL;
2021 int i, err = 0, all = 0, maybe_all = 0, n_config_paths = 0;
2022 const char **config_paths = NULL;
2023 const char *root = "";
2024 const char *system_map = NULL;
2025 const char *module_symvers = NULL;
2026 const char *null_kmod_config = NULL;
2027 struct utsname un;
2028 struct kmod_ctx *ctx = NULL;
2029 struct cfg cfg;
2030 struct depmod depmod;
2031
2032 memset(&cfg, 0, sizeof(cfg));
2033 memset(&depmod, 0, sizeof(depmod));
2034
2035 for (;;) {
2036 int c, idx = 0;
2037 c = getopt_long(argc, argv, cmdopts_s, cmdopts, &idx);
2038 if (c == -1)
2039 break;
2040 switch (c) {
2041 case 'a':
2042 all = 1;
2043 break;
2044 case 'A':
2045 maybe_all = 1;
2046 break;
2047 case 'b':
2048 root = optarg;
2049 break;
2050 case 'C': {
2051 size_t bytes = sizeof(char *) * (n_config_paths + 2);
2052 void *tmp = realloc(config_paths, bytes);
2053 if (!tmp) {
2054 fputs("Error: out-of-memory\n", stderr);
2055 goto cmdline_failed;
2056 }
2057 config_paths = tmp;
2058 config_paths[n_config_paths] = optarg;
2059 n_config_paths++;
2060 config_paths[n_config_paths] = NULL;
2061 break;
2062 }
2063 case 'E':
2064 module_symvers = optarg;
2065 cfg.check_symvers = 1;
2066 break;
2067 case 'F':
2068 system_map = optarg;
2069 break;
2070 case 'e':
2071 cfg.print_unknown = 1;
2072 break;
2073 case 'v':
2074 verbose++;
2075 break;
2076 case 'n':
2077 out = stdout;
2078 break;
2079 case 'P':
2080 if (optarg[1] != '\0') {
2081 CRIT("-P only takes a single char\n");
2082 goto cmdline_failed;
2083 }
2084 cfg.sym_prefix = optarg[0];
2085 break;
2086 case 'w':
2087 cfg.warn_dups = 1;
2088 break;
2089 case 'u':
2090 case 'q':
2091 case 'r':
2092 case 'm':
2093 if (idx > 0) {
2094 fprintf(stderr,
2095 "ignored deprecated option --%s\n",
2096 cmdopts[idx].name);
2097 } else {
2098 fprintf(stderr,
2099 "ignored deprecated option -%c\n", c);
2100 }
2101 break;
2102 case 'h':
2103 help(argv[0]);
2104 free(config_paths);
2105 return EXIT_SUCCESS;
2106 case 'V':
2107 puts(PACKAGE " version " VERSION);
2108 free(config_paths);
2109 return EXIT_SUCCESS;
2110 case '?':
2111 goto cmdline_failed;
2112 default:
2113 fprintf(stderr,
2114 "Error: unexpected getopt_long() value '%c'.\n",
2115 c);
2116 goto cmdline_failed;
2117 }
2118 }
2119
2120 if (optind < argc && is_version_number(argv[optind])) {
2121 cfg.kversion = argv[optind];
2122 optind++;
2123 } else {
2124 if (uname(&un) < 0) {
2125 CRIT("uname() failed: %s\n", strerror(errno));
2126 goto cmdline_failed;
2127 }
2128 cfg.kversion = un.release;
2129 }
2130
2131 cfg.dirnamelen = snprintf(cfg.dirname, PATH_MAX,
2132 "%s" ROOTPREFIX "/lib/modules/%s",
2133 root, cfg.kversion);
2134
2135 if (optind == argc)
2136 all = 1;
2137
2138 if (maybe_all) {
2139 if (out == stdout)
2140 goto done;
2141 if (depfile_up_to_date(cfg.dirname))
2142 goto done;
2143 all = 1;
2144 }
2145
2146 ctx = kmod_new(cfg.dirname, &null_kmod_config);
2147 if (ctx == NULL) {
2148 CRIT("kmod_new(\"%s\", {NULL}) failed: %m\n", cfg.dirname);
2149 goto cmdline_failed;
2150 }
2151 kmod_set_log_priority(ctx, verbose);
2152
2153 err = depmod_init(&depmod, &cfg, ctx);
2154 if (err < 0) {
2155 CRIT("depmod_init: %s\n", strerror(-err));
2156 goto depmod_init_failed;
2157 }
2158 ctx = NULL; /* owned by depmod */
2159
2160 if (all) {
2161 err = cfg_load(&cfg, config_paths);
2162 if (err < 0) {
2163 CRIT("Could not load configuration files\n");
2164 goto cmdline_modules_failed;
2165 }
2166 err = depmod_modules_search(&depmod);
2167 if (err < 0) {
2168 CRIT("Could search modules: %s\n", strerror(-err));
2169 goto cmdline_modules_failed;
2170 }
2171 } else {
2172 for (i = optind; i < argc; i++) {
2173 const char *path = argv[i];
2174 struct kmod_module *mod;
2175
2176 if (path[0] != '/') {
2177 CRIT("%s: not absolute path.", path);
2178 goto cmdline_modules_failed;
2179 }
2180
2181 err = kmod_module_new_from_path(depmod.ctx, path, &mod);
2182 if (err < 0) {
2183 CRIT("Could not create module %s: %s\n",
2184 path, strerror(-err));
2185 goto cmdline_modules_failed;
2186 }
2187
2188 err = depmod_module_add(&depmod, mod);
2189 if (err < 0) {
2190 CRIT("Could not add module %s: %s\n",
2191 path, strerror(-err));
2192 kmod_module_unref(mod);
2193 goto cmdline_modules_failed;
2194 }
2195 }
2196 }
2197
2198 depmod_modules_sort(&depmod);
2199 err = depmod_load(&depmod);
2200 if (err < 0)
2201 goto cmdline_modules_failed;
2202
25c41512 2203 err = depmod_output(&depmod, out);
64b8b586
GSB
2204
2205done:
2206 depmod_shutdown(&depmod);
2207 cfg_free(&cfg);
2208 free(config_paths);
2209 return err >= 0 ? EXIT_SUCCESS : EXIT_FAILURE;
2210
2211cmdline_modules_failed:
2212 depmod_shutdown(&depmod);
2213depmod_init_failed:
2214 if (ctx != NULL)
2215 kmod_unref(ctx);
2216cmdline_failed:
2217 cfg_free(&cfg);
2218 free(config_paths);
2219 return EXIT_FAILURE;
2220}