2 * kmod-depmod - calculate modules.dep using libkmod.
4 * Copyright (C) 2011-2013 ProFUSION embedded systems
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.
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.
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/>.
33 #include <sys/utsname.h>
35 #include <shared/array.h>
36 #include <shared/hash.h>
37 #include <shared/macro.h>
38 #include <shared/util.h>
39 #include <shared/scratchbuf.h>
41 #include <libkmod/libkmod-internal.h>
48 #define DEFAULT_VERBOSE LOG_WARNING
49 static int verbose
= DEFAULT_VERBOSE
;
51 static const char CFG_BUILTIN_KEY
[] = "built-in";
52 static const char CFG_EXTERNAL_KEY
[] = "external";
53 static const char *default_cfg_paths
[] = {
54 SYSCONFDIR
"/depmod.d",
56 "/usr/local/lib/depmod.d",
61 static const char cmdopts_s
[] = "aAb:C:E:F:euqrvnP:wmVh";
62 static const struct option cmdopts
[] = {
63 { "all", no_argument
, 0, 'a' },
64 { "quick", no_argument
, 0, 'A' },
65 { "basedir", required_argument
, 0, 'b' },
66 { "config", required_argument
, 0, 'C' },
67 { "symvers", required_argument
, 0, 'E' },
68 { "filesyms", required_argument
, 0, 'F' },
69 { "errsyms", no_argument
, 0, 'e' },
70 { "unresolved-error", no_argument
, 0, 'u' }, /* deprecated */
71 { "quiet", no_argument
, 0, 'q' }, /* deprecated */
72 { "root", no_argument
, 0, 'r' }, /* deprecated */
73 { "verbose", no_argument
, 0, 'v' },
74 { "show", no_argument
, 0, 'n' },
75 { "dry-run", no_argument
, 0, 'n' },
76 { "symbol-prefix", required_argument
, 0, 'P' },
77 { "warn", no_argument
, 0, 'w' },
78 { "map", no_argument
, 0, 'm' }, /* deprecated */
79 { "version", no_argument
, 0, 'V' },
80 { "help", no_argument
, 0, 'h' },
84 static void help(void)
87 "\t%s -[aA] [options] [forced_version]\n"
89 "If no arguments (except options) are given, \"depmod -a\" is assumed\n"
91 "depmod will output a dependency list suitable for the modprobe utility.\n"
94 "\t-a, --all Probe all modules\n"
95 "\t-A, --quick Only does the work if there's a new module\n"
96 "\t-e, --errsyms Report not supplied symbols\n"
97 "\t-n, --show Write the dependency file on stdout only\n"
98 "\t-P, --symbol-prefix Architecture symbol prefix\n"
99 "\t-C, --config=PATH Read configuration from PATH\n"
100 "\t-v, --verbose Enable verbose mode\n"
101 "\t-w, --warn Warn on duplicates\n"
102 "\t-V, --version show version\n"
103 "\t-h, --help show this help\n"
105 "The following options are useful for people managing distributions:\n"
106 "\t-b, --basedir=DIR Use an image of a module tree.\n"
107 "\t-F, --filesyms=FILE Use the file instead of the\n"
108 "\t current kernel symbols.\n"
109 "\t-E, --symvers=FILE Use Module.symvers file to check\n"
110 "\t symbol versions.\n",
111 program_invocation_short_name
);
114 _printf_format_(1, 2)
115 static inline void _show(const char *fmt
, ...)
119 if (verbose
<= DEFAULT_VERBOSE
)
123 vfprintf(stdout
, fmt
, args
);
127 #define SHOW(...) _show(__VA_ARGS__)
130 /* binary index write *************************************************/
131 #include <arpa/inet.h>
132 /* BEGIN: code from module-init-tools/index.c just modified to compile here.
134 * Original copyright:
135 * index.c: module index file shared functions for modprobe and depmod
136 * Copyright (C) 2008 Alan Jenkins <alan-jenkins@tuffmail.co.uk>.
138 * These programs are free software; you can redistribute it and/or modify
139 * it under the terms of the GNU General Public License as published by
140 * the Free Software Foundation; either version 2 of the License, or
141 * (at your option) any later version.
143 * This program is distributed in the hope that it will be useful,
144 * but WITHOUT ANY WARRANTY; without even the implied warranty of
145 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
146 * GNU General Public License for more details.
148 * You should have received a copy of the GNU General Public License
149 * along with these programs. If not, see <http://www.gnu.org/licenses/>.
152 /* see documentation in libkmod/libkmod-index.c */
154 #define INDEX_MAGIC 0xB007F457
155 #define INDEX_VERSION_MAJOR 0x0002
156 #define INDEX_VERSION_MINOR 0x0001
157 #define INDEX_VERSION ((INDEX_VERSION_MAJOR<<16)|INDEX_VERSION_MINOR)
158 #define INDEX_CHILDMAX 128
161 struct index_value
*next
;
162 unsigned int priority
;
166 /* In-memory index (depmod only) */
168 char *prefix
; /* path compression */
169 struct index_value
*values
;
170 unsigned char first
; /* range of child nodes */
172 struct index_node
*children
[INDEX_CHILDMAX
]; /* indexed by character */
176 /* Format of node offsets within index file */
178 INDEX_NODE_FLAGS
= 0xF0000000, /* Flags in high nibble */
179 INDEX_NODE_PREFIX
= 0x80000000,
180 INDEX_NODE_VALUES
= 0x40000000,
181 INDEX_NODE_CHILDS
= 0x20000000,
183 INDEX_NODE_MASK
= 0x0FFFFFFF, /* Offset value */
186 static struct index_node
*index_create(void)
188 struct index_node
*node
;
190 node
= NOFAIL(calloc(sizeof(struct index_node
), 1));
191 node
->prefix
= NOFAIL(strdup(""));
192 node
->first
= INDEX_CHILDMAX
;
197 static void index_values_free(struct index_value
*values
)
200 struct index_value
*value
= values
;
202 values
= value
->next
;
207 static void index_destroy(struct index_node
*node
)
211 for (c
= node
->first
; c
<= node
->last
; c
++) {
212 struct index_node
*child
= node
->children
[c
];
215 index_destroy(child
);
217 index_values_free(node
->values
);
222 static void index__checkstring(const char *str
)
226 for (i
= 0; str
[i
]; i
++) {
229 if (ch
>= INDEX_CHILDMAX
)
230 CRIT("Module index: bad character '%c'=0x%x - only 7-bit ASCII is supported:"
231 "\n%s\n", (char) ch
, (int) ch
, str
);
235 static int index_add_value(struct index_value
**values
,
236 const char *value
, unsigned int priority
)
238 struct index_value
*v
;
242 /* report the presence of duplicate values */
243 for (v
= *values
; v
; v
= v
->next
) {
244 if (streq(v
->value
, value
))
248 /* find position to insert value */
249 while (*values
&& (*values
)->priority
< priority
)
250 values
= &(*values
)->next
;
253 v
= NOFAIL(calloc(sizeof(struct index_value
) + len
+ 1, 1));
255 v
->priority
= priority
;
256 memcpy(v
->value
, value
, len
+ 1);
262 static int index_insert(struct index_node
*node
, const char *key
,
263 const char *value
, unsigned int priority
)
265 int i
= 0; /* index within str */
268 index__checkstring(key
);
269 index__checkstring(value
);
272 int j
; /* index within node->prefix */
274 /* Ensure node->prefix is a prefix of &str[i].
275 If it is not already, then we must split node. */
276 for (j
= 0; node
->prefix
[j
]; j
++) {
277 ch
= node
->prefix
[j
];
279 if (ch
!= key
[i
+j
]) {
280 char *prefix
= node
->prefix
;
281 struct index_node
*n
;
283 /* New child is copy of node with prefix[j+1..N] */
284 n
= NOFAIL(calloc(sizeof(struct index_node
), 1));
285 memcpy(n
, node
, sizeof(struct index_node
));
286 n
->prefix
= NOFAIL(strdup(&prefix
[j
+1]));
288 /* Parent has prefix[0..j], child at prefix[j] */
289 memset(node
, 0, sizeof(struct index_node
));
291 node
->prefix
= prefix
;
294 node
->children
[ch
] = n
;
299 /* j is now length of node->prefix */
304 return index_add_value(&node
->values
, value
, priority
);
306 if (!node
->children
[ch
]) {
307 struct index_node
*child
;
309 if (ch
< node
->first
)
313 node
->children
[ch
] = NOFAIL(calloc(sizeof(struct index_node
), 1));
315 child
= node
->children
[ch
];
316 child
->prefix
= NOFAIL(strdup(&key
[i
+1]));
317 child
->first
= INDEX_CHILDMAX
;
318 index_add_value(&child
->values
, value
, priority
);
323 /* Descend into child node and continue */
324 node
= node
->children
[ch
];
329 static int index__haschildren(const struct index_node
*node
)
331 return node
->first
< INDEX_CHILDMAX
;
334 /* Recursive post-order traversal
336 Pre-order would make for better read-side buffering / readahead / caching.
337 (post-order means you go backwards in the file as you descend the tree).
338 However, index reading is already fast enough.
339 Pre-order is simpler for writing, and depmod is already slow.
341 static uint32_t index_write__node(const struct index_node
*node
, FILE *out
)
343 uint32_t *child_offs
= NULL
;
350 /* Write children and save their offsets */
351 if (index__haschildren(node
)) {
352 const struct index_node
*child
;
355 child_count
= node
->last
- node
->first
+ 1;
356 child_offs
= NOFAIL(malloc(child_count
* sizeof(uint32_t)));
358 for (i
= 0; i
< child_count
; i
++) {
359 child
= node
->children
[node
->first
+ i
];
360 child_offs
[i
] = htonl(index_write__node(child
, out
));
364 /* Now write this node */
367 if (node
->prefix
[0]) {
368 fputs(node
->prefix
, out
);
370 offset
|= INDEX_NODE_PREFIX
;
374 fputc(node
->first
, out
);
375 fputc(node
->last
, out
);
376 fwrite(child_offs
, sizeof(uint32_t), child_count
, out
);
377 offset
|= INDEX_NODE_CHILDS
;
383 const struct index_value
*v
;
384 unsigned int value_count
;
388 for (v
= node
->values
; v
!= NULL
; v
= v
->next
)
390 u
= htonl(value_count
);
391 fwrite(&u
, sizeof(u
), 1, out
);
393 for (v
= node
->values
; v
!= NULL
; v
= v
->next
) {
394 u
= htonl(v
->priority
);
395 fwrite(&u
, sizeof(u
), 1, out
);
396 fputs(v
->value
, out
);
399 offset
|= INDEX_NODE_VALUES
;
405 static void index_write(const struct index_node
*node
, FILE *out
)
407 long initial_offset
, final_offset
;
410 u
= htonl(INDEX_MAGIC
);
411 fwrite(&u
, sizeof(u
), 1, out
);
412 u
= htonl(INDEX_VERSION
);
413 fwrite(&u
, sizeof(u
), 1, out
);
415 /* Second word is reserved for the offset of the root node */
416 initial_offset
= ftell(out
);
417 assert(initial_offset
>= 0);
419 fwrite(&u
, sizeof(uint32_t), 1, out
);
422 u
= htonl(index_write__node(node
, out
));
424 /* Update first word */
425 final_offset
= ftell(out
);
426 assert(final_offset
>= 0);
427 (void)fseek(out
, initial_offset
, SEEK_SET
);
428 fwrite(&u
, sizeof(uint32_t), 1, out
);
429 (void)fseek(out
, final_offset
, SEEK_SET
);
432 /* END: code from module-init-tools/index.c just modified to compile here.
435 /* configuration parsing **********************************************/
436 struct cfg_override
{
437 struct cfg_override
*next
;
449 struct cfg_search
*next
;
450 enum search_type type
;
455 struct cfg_external
{
456 struct cfg_external
*next
;
462 struct cfg_exclude
*next
;
467 const char *kversion
;
468 char dirname
[PATH_MAX
];
471 uint8_t check_symvers
;
472 uint8_t print_unknown
;
474 struct cfg_override
*overrides
;
475 struct cfg_search
*searches
;
476 struct cfg_external
*externals
;
477 struct cfg_exclude
*excludes
;
480 static enum search_type
cfg_define_search_type(const char *path
)
482 if (streq(path
, CFG_BUILTIN_KEY
))
483 return SEARCH_BUILTIN
;
484 if (streq(path
, CFG_EXTERNAL_KEY
))
485 return SEARCH_EXTERNAL
;
489 static int cfg_search_add(struct cfg
*cfg
, const char *path
)
491 struct cfg_search
*s
;
493 enum search_type type
;
495 type
= cfg_define_search_type(path
);
497 if (type
!= SEARCH_PATH
)
500 len
= strlen(path
) + 1;
502 s
= malloc(sizeof(struct cfg_search
) + len
);
504 ERR("search add: out of memory\n");
508 if (type
!= SEARCH_PATH
)
512 memcpy(s
->path
, path
, len
);
515 DBG("search add: %s, search type=%hhu\n", path
, type
);
517 s
->next
= cfg
->searches
;
522 static void cfg_search_free(struct cfg_search
*s
)
527 static int cfg_override_add(struct cfg
*cfg
, const char *modname
, const char *subdir
)
529 struct cfg_override
*o
;
530 size_t modnamelen
= strlen(modname
);
531 size_t subdirlen
= strlen(subdir
);
534 o
= malloc(sizeof(struct cfg_override
) + subdirlen
+ 1
537 ERR("override add: out of memory\n");
540 memcpy(o
->path
, subdir
, subdirlen
);
545 memcpy(o
->path
+ i
, modname
, modnamelen
);
547 o
->path
[i
] = '\0'; /* no extension, so we can match .ko/.ko.gz */
551 DBG("override add: %s\n", o
->path
);
553 o
->next
= cfg
->overrides
;
558 static void cfg_override_free(struct cfg_override
*o
)
563 static int cfg_external_add(struct cfg
*cfg
, const char *path
)
565 struct cfg_external
*ext
;
566 size_t len
= strlen(path
);
568 ext
= malloc(sizeof(struct cfg_external
) + len
+ 1);
570 ERR("external add: out of memory\n");
574 strcpy(ext
->path
, path
);
577 DBG("external add: %s\n", ext
->path
);
579 ext
->next
= cfg
->externals
;
580 cfg
->externals
= ext
;
584 static void cfg_external_free(struct cfg_external
*ext
)
589 static int cfg_exclude_add(struct cfg
*cfg
, const char *path
)
591 struct cfg_exclude
*exc
;
592 size_t len
= strlen(path
);
594 exc
= malloc(sizeof(struct cfg_exclude
) + len
+ 1);
596 ERR("exclude add: out of memory\n");
599 memcpy(exc
->exclude_dir
, path
, len
+ 1);
601 DBG("exclude add: %s\n", path
);
603 exc
->next
= cfg
->excludes
;
608 static void cfg_exclude_free(struct cfg_exclude
*exc
)
613 static int cfg_kernel_matches(const struct cfg
*cfg
, const char *pattern
)
619 if (streq(pattern
, "*"))
622 if (regcomp(&re
, pattern
, REG_EXTENDED
|REG_NOSUB
) != 0)
625 status
= regexec(&re
, cfg
->kversion
, 0, NULL
, 0);
631 static int cfg_file_parse(struct cfg
*cfg
, const char *filename
)
635 unsigned int linenum
= 0;
638 fp
= fopen(filename
, "r");
641 ERR("file parse %s: %m\n", filename
);
645 while ((line
= freadline_wrapped(fp
, &linenum
)) != NULL
) {
648 if (line
[0] == '\0' || line
[0] == '#')
651 cmd
= strtok_r(line
, "\t ", &saveptr
);
655 if (streq(cmd
, "search")) {
657 while ((sp
= strtok_r(NULL
, "\t ", &saveptr
)) != NULL
) {
658 cfg_search_add(cfg
, sp
);
660 } else if (streq(cmd
, "override")) {
661 const char *modname
= strtok_r(NULL
, "\t ", &saveptr
);
662 const char *version
= strtok_r(NULL
, "\t ", &saveptr
);
663 const char *subdir
= strtok_r(NULL
, "\t ", &saveptr
);
665 if (modname
== NULL
|| version
== NULL
||
669 if (!cfg_kernel_matches(cfg
, version
)) {
670 INF("%s:%u: override kernel did not match %s\n",
671 filename
, linenum
, version
);
675 cfg_override_add(cfg
, modname
, subdir
);
676 } else if (streq(cmd
, "external")) {
677 const char *version
= strtok_r(NULL
, "\t ", &saveptr
);
678 const char *dir
= strtok_r(NULL
, "\t ", &saveptr
);
680 if (version
== NULL
|| dir
== NULL
)
683 if (!cfg_kernel_matches(cfg
, version
)) {
684 INF("%s:%u: external directory did not match %s\n",
685 filename
, linenum
, version
);
689 cfg_external_add(cfg
, dir
);
690 } else if (streq(cmd
, "exclude")) {
692 while ((sp
= strtok_r(NULL
, "\t ", &saveptr
)) != NULL
) {
693 cfg_exclude_add(cfg
, sp
);
695 } else if (streq(cmd
, "include")
696 || streq(cmd
, "make_map_files")) {
697 INF("%s:%u: command %s not implemented yet\n",
698 filename
, linenum
, cmd
);
701 ERR("%s:%u: ignoring bad line starting with '%s'\n",
702 filename
, linenum
, cmd
);
714 static int cfg_files_filter_out(DIR *d
, const char *dir
, const char *name
)
716 size_t len
= strlen(name
);
722 if (len
< 6 || !streq(name
+ len
- 5, ".conf")) {
723 INF("All cfg files need .conf: %s/%s\n", dir
, name
);
727 fstatat(dirfd(d
), name
, &st
, 0);
728 if (S_ISDIR(st
.st_mode
)) {
729 ERR("Directories inside directories are not supported: %s/%s\n",
744 static void cfg_file_free(struct cfg_file
*f
)
749 static int cfg_files_insert_sorted(struct cfg_file
***p_files
, size_t *p_n_files
,
750 const char *dir
, const char *name
)
752 struct cfg_file
**files
, *f
;
753 size_t i
, n_files
, namelen
, dirlen
;
756 dirlen
= strlen(dir
);
758 namelen
= strlen(name
);
760 name
= basename(dir
);
761 namelen
= strlen(name
);
762 dirlen
-= namelen
+ 1;
765 n_files
= *p_n_files
;
767 for (i
= 0; i
< n_files
; i
++) {
768 int cmp
= strcmp(name
, files
[i
]->name
);
770 DBG("Ignoring duplicate config file: %.*s/%s\n",
771 (int)dirlen
, dir
, name
);
777 f
= malloc(sizeof(struct cfg_file
) + dirlen
+ namelen
+ 2);
779 ERR("files insert sorted: out of memory\n");
783 tmp
= realloc(files
, sizeof(struct cfg_file
*) * (n_files
+ 1));
785 ERR("files insert sorted: out of memory\n");
789 *p_files
= files
= tmp
;
792 memmove(files
+ i
+ 1, files
+ i
,
793 sizeof(struct cfg_file
*) * (n_files
- i
));
798 f
->namelen
= namelen
;
799 f
->name
= f
->path
+ dirlen
+ 1;
800 memcpy(f
->path
, dir
, dirlen
);
801 f
->path
[dirlen
] = '/';
802 memcpy(f
->path
+ dirlen
+ 1, name
, namelen
);
803 f
->path
[dirlen
+ 1 + namelen
] = '\0';
805 *p_n_files
= n_files
+ 1;
810 * Insert configuration files ignoring duplicates
812 static int cfg_files_list(struct cfg_file
***p_files
, size_t *p_n_files
,
820 if (stat(path
, &st
) != 0) {
822 DBG("could not stat '%s': %m\n", path
);
826 if (!S_ISDIR(st
.st_mode
)) {
827 cfg_files_insert_sorted(p_files
, p_n_files
, path
, NULL
);
833 ERR("files list %s: %m\n", path
);
837 for (dent
= readdir(d
); dent
!= NULL
; dent
= readdir(d
)) {
838 if (cfg_files_filter_out(d
, path
, dent
->d_name
))
841 cfg_files_insert_sorted(p_files
, p_n_files
, path
, dent
->d_name
);
845 DBG("parsed configuration files from %s\n", path
);
849 static int cfg_load(struct cfg
*cfg
, const char * const *cfg_paths
)
851 size_t i
, n_files
= 0;
852 struct cfg_file
**files
= NULL
;
854 if (cfg_paths
== NULL
)
855 cfg_paths
= default_cfg_paths
;
857 for (i
= 0; cfg_paths
[i
] != NULL
; i
++)
858 cfg_files_list(&files
, &n_files
, cfg_paths
[i
]);
860 for (i
= 0; i
< n_files
; i
++) {
861 struct cfg_file
*f
= files
[i
];
862 cfg_file_parse(cfg
, f
->path
);
867 /* For backward compatibility add "updates" to the head of the search
868 * list here. But only if there was no "search" option specified.
870 if (cfg
->searches
== NULL
)
871 cfg_search_add(cfg
, "updates");
876 static void cfg_free(struct cfg
*cfg
)
878 while (cfg
->overrides
) {
879 struct cfg_override
*tmp
= cfg
->overrides
;
880 cfg
->overrides
= cfg
->overrides
->next
;
881 cfg_override_free(tmp
);
884 while (cfg
->searches
) {
885 struct cfg_search
*tmp
= cfg
->searches
;
886 cfg
->searches
= cfg
->searches
->next
;
887 cfg_search_free(tmp
);
890 while (cfg
->externals
) {
891 struct cfg_external
*tmp
= cfg
->externals
;
892 cfg
->externals
= cfg
->externals
->next
;
893 cfg_external_free(tmp
);
896 while (cfg
->excludes
) {
897 struct cfg_exclude
*tmp
= cfg
->excludes
;
898 cfg
->excludes
= cfg
->excludes
->next
;
899 cfg_exclude_free(tmp
);
904 /* depmod calculations ***********************************************/
907 struct kmod_module
*kmod
;
909 const char *relpath
; /* path relative to '$ROOT/lib/modules/$VER/' */
910 char *uncrelpath
; /* same as relpath but ending in .ko */
911 struct kmod_list
*info_list
;
912 struct kmod_list
*dep_sym_list
;
913 struct array deps
; /* struct symbol */
914 size_t baselen
; /* points to start of basename/filename */
916 int sort_idx
; /* sort index using modules.order */
917 int dep_sort_idx
; /* topological sort index */
918 uint16_t idx
; /* index in depmod->modules.array */
919 uint16_t users
; /* how many modules depend on this one */
920 bool visited
; /* helper field to report cycles */
921 struct vertex
*vertex
; /* helper field to report cycles */
932 const struct cfg
*cfg
;
933 struct kmod_ctx
*ctx
;
934 struct array modules
;
935 struct hash
*modules_by_uncrelpath
;
936 struct hash
*modules_by_name
;
937 struct hash
*symbols
;
940 static void mod_free(struct mod
*mod
)
942 DBG("free %p kmod=%p, path=%s\n", mod
, mod
->kmod
, mod
->path
);
943 array_free_array(&mod
->deps
);
944 kmod_module_unref(mod
->kmod
);
945 kmod_module_info_free_list(mod
->info_list
);
946 kmod_module_dependency_symbols_free_list(mod
->dep_sym_list
);
947 free(mod
->uncrelpath
);
952 static int mod_add_dependency(struct mod
*mod
, struct symbol
*sym
)
956 DBG("%s depends on %s %s\n", mod
->path
, sym
->name
,
957 sym
->owner
!= NULL
? sym
->owner
->path
: "(unknown)");
959 if (sym
->owner
== NULL
)
962 err
= array_append_unique(&mod
->deps
, sym
->owner
);
969 SHOW("%s needs \"%s\": %s\n", mod
->path
, sym
->name
, sym
->owner
->path
);
973 static void symbol_free(struct symbol
*sym
)
975 DBG("free %p sym=%s, owner=%p %s\n", sym
, sym
->name
, sym
->owner
,
976 sym
->owner
!= NULL
? sym
->owner
->path
: "");
980 static int depmod_init(struct depmod
*depmod
, struct cfg
*cfg
,
981 struct kmod_ctx
*ctx
)
988 array_init(&depmod
->modules
, 128);
990 depmod
->modules_by_uncrelpath
= hash_new(512, NULL
);
991 if (depmod
->modules_by_uncrelpath
== NULL
) {
993 goto modules_by_uncrelpath_failed
;
996 depmod
->modules_by_name
= hash_new(512, NULL
);
997 if (depmod
->modules_by_name
== NULL
) {
999 goto modules_by_name_failed
;
1002 depmod
->symbols
= hash_new(2048, (void (*)(void *))symbol_free
);
1003 if (depmod
->symbols
== NULL
) {
1005 goto symbols_failed
;
1011 hash_free(depmod
->modules_by_name
);
1012 modules_by_name_failed
:
1013 hash_free(depmod
->modules_by_uncrelpath
);
1014 modules_by_uncrelpath_failed
:
1018 static void depmod_shutdown(struct depmod
*depmod
)
1022 hash_free(depmod
->symbols
);
1024 hash_free(depmod
->modules_by_uncrelpath
);
1026 hash_free(depmod
->modules_by_name
);
1028 for (i
= 0; i
< depmod
->modules
.count
; i
++)
1029 mod_free(depmod
->modules
.array
[i
]);
1030 array_free_array(&depmod
->modules
);
1032 kmod_unref(depmod
->ctx
);
1035 static int depmod_module_add(struct depmod
*depmod
, struct kmod_module
*kmod
)
1037 const struct cfg
*cfg
= depmod
->cfg
;
1038 const char *modname
, *lastslash
;
1043 modname
= kmod_module_get_name(kmod
);
1044 modnamesz
= strlen(modname
) + 1;
1046 mod
= calloc(1, sizeof(struct mod
) + modnamesz
);
1050 mod
->sort_idx
= depmod
->modules
.count
+ 1;
1051 mod
->dep_sort_idx
= INT32_MAX
;
1052 memcpy(mod
->modname
, modname
, modnamesz
);
1053 mod
->modnamesz
= modnamesz
;
1055 array_init(&mod
->deps
, 4);
1057 mod
->path
= strdup(kmod_module_get_path(kmod
));
1058 lastslash
= strrchr(mod
->path
, '/');
1059 mod
->baselen
= lastslash
- mod
->path
;
1060 if (strncmp(mod
->path
, cfg
->dirname
, cfg
->dirnamelen
) == 0 &&
1061 mod
->path
[cfg
->dirnamelen
] == '/')
1062 mod
->relpath
= mod
->path
+ cfg
->dirnamelen
+ 1;
1064 mod
->relpath
= NULL
;
1066 err
= hash_add_unique(depmod
->modules_by_name
, mod
->modname
, mod
);
1068 ERR("hash_add_unique %s: %s\n", mod
->modname
, strerror(-err
));
1072 if (mod
->relpath
!= NULL
) {
1073 size_t uncrelpathlen
= lastslash
- mod
->relpath
+ modnamesz
1074 + strlen(KMOD_EXTENSION_UNCOMPRESSED
);
1075 mod
->uncrelpath
= memdup(mod
->relpath
, uncrelpathlen
+ 1);
1076 mod
->uncrelpath
[uncrelpathlen
] = '\0';
1077 err
= hash_add_unique(depmod
->modules_by_uncrelpath
,
1078 mod
->uncrelpath
, mod
);
1080 ERR("hash_add_unique %s: %s\n",
1081 mod
->uncrelpath
, strerror(-err
));
1082 hash_del(depmod
->modules_by_name
, mod
->modname
);
1087 DBG("add %p kmod=%p, path=%s\n", mod
, kmod
, mod
->path
);
1092 free(mod
->uncrelpath
);
1097 static int depmod_module_del(struct depmod
*depmod
, struct mod
*mod
)
1099 DBG("del %p kmod=%p, path=%s\n", mod
, mod
->kmod
, mod
->path
);
1101 if (mod
->uncrelpath
!= NULL
)
1102 hash_del(depmod
->modules_by_uncrelpath
, mod
->uncrelpath
);
1104 hash_del(depmod
->modules_by_name
, mod
->modname
);
1110 static const char *search_to_string(const struct cfg_search
*s
)
1113 case SEARCH_EXTERNAL
:
1115 case SEARCH_BUILTIN
:
1122 static bool depmod_is_path_starts_with(const char *path
,
1127 if (pathlen
<= prefix_len
)
1129 if (path
[prefix_len
] != '/')
1131 if (memcmp(path
, prefix
, prefix_len
) != 0)
1137 /* returns if existing module @mod is higher priority than newpath.
1138 * note this is the inverse of module-init-tools is_higher_priority()
1140 static 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
)
1142 const struct cfg
*cfg
= depmod
->cfg
;
1143 const struct cfg_override
*ov
;
1144 const struct cfg_search
*se
;
1145 const struct cfg_external
*ext
;
1147 /* baselen includes the last '/' and mod->baselen doesn't. So it's
1148 * actually correct to use modnamelen in the first and modnamesz in
1150 size_t newlen
= baselen
+ modnamelen
;
1151 size_t oldlen
= mod
->baselen
+ mod
->modnamesz
;
1152 const char *oldpath
= mod
->path
;
1153 int i
, bprio
= -1, oldprio
= -1, newprio
= -1;
1154 size_t relnewlen
= 0;
1155 size_t reloldlen
= 0;
1156 const char *relnewpath
= NULL
;
1157 const char *reloldpath
= NULL
;
1159 DBG("comparing priorities of %s and %s\n",
1162 if (strncmp(newpath
, cfg
->dirname
, cfg
->dirnamelen
) == 0) {
1163 relnewpath
= newpath
+ cfg
->dirnamelen
+ 1;
1164 relnewlen
= newlen
- (cfg
->dirnamelen
+ 1);
1166 if (strncmp(oldpath
, cfg
->dirname
, cfg
->dirnamelen
) == 0) {
1167 reloldpath
= oldpath
+ cfg
->dirnamelen
+ 1;
1168 reloldlen
= oldlen
- (cfg
->dirnamelen
+ 1);
1171 for (ov
= cfg
->overrides
; ov
!= NULL
; ov
= ov
->next
) {
1172 DBG("override %s\n", ov
->path
);
1173 if (relnewlen
== ov
->len
&&
1174 memcmp(ov
->path
, relnewpath
, relnewlen
) == 0)
1176 if (reloldlen
== ov
->len
&&
1177 memcmp(ov
->path
, reloldpath
, reloldlen
) == 0)
1181 for (i
= 0, se
= cfg
->searches
; se
!= NULL
; se
= se
->next
, i
++) {
1182 DBG("search %s\n", search_to_string(se
));
1183 if (se
->type
== SEARCH_BUILTIN
)
1185 else if (se
->type
== SEARCH_EXTERNAL
) {
1186 for (ext
= cfg
->externals
; ext
!= NULL
; ext
= ext
->next
, i
++) {
1187 if (depmod_is_path_starts_with(newpath
,
1192 if (depmod_is_path_starts_with(oldpath
,
1198 } else if (relnewlen
> se
->len
&& relnewpath
[se
->len
] == '/' &&
1199 memcmp(se
->path
, relnewpath
, se
->len
) == 0)
1201 else if (reloldlen
> se
->len
&& reloldpath
[se
->len
] == '/' &&
1202 memcmp(se
->path
, reloldpath
, se
->len
) == 0)
1211 DBG("priorities: built-in: %d, old: %d, new: %d\n",
1212 bprio
, oldprio
, newprio
);
1214 return newprio
<= oldprio
;
1217 static int depmod_modules_search_file(struct depmod
*depmod
, size_t baselen
, size_t namelen
, const char *path
)
1219 struct kmod_module
*kmod
;
1221 const char *relpath
;
1222 char modname
[PATH_MAX
];
1226 if (!path_ends_with_kmod_ext(path
+ baselen
, namelen
))
1229 if (path_to_modname(path
, modname
, &modnamelen
) == NULL
) {
1230 ERR("could not get modname from path %s\n", path
);
1234 relpath
= path
+ depmod
->cfg
->dirnamelen
+ 1;
1235 DBG("try %s (%s)\n", relpath
, modname
);
1237 mod
= hash_find(depmod
->modules_by_name
, modname
);
1241 if (depmod_module_is_higher_priority(depmod
, mod
, baselen
,
1242 namelen
, modnamelen
, path
)) {
1243 DBG("Ignored lower priority: %s, higher: %s\n",
1248 DBG("Replace lower priority %s with new module %s\n",
1249 mod
->relpath
, relpath
);
1250 err
= depmod_module_del(depmod
, mod
);
1252 ERR("could not del module %s: %s\n", mod
->path
, strerror(-err
));
1257 err
= kmod_module_new_from_path(depmod
->ctx
, path
, &kmod
);
1259 ERR("could not create module %s: %s\n", path
, strerror(-err
));
1263 err
= depmod_module_add(depmod
, kmod
);
1265 ERR("could not add module %s: %s\n",
1266 path
, strerror(-err
));
1267 kmod_module_unref(kmod
);
1273 static bool should_exclude_dir(const struct cfg
*cfg
, const char *name
)
1275 struct cfg_exclude
*exc
;
1277 if (name
[0] == '.' && (name
[1] == '\0' ||
1278 (name
[1] == '.' && name
[2] == '\0')))
1281 if (streq(name
, "build") || streq(name
, "source"))
1284 for (exc
= cfg
->excludes
; exc
!= NULL
; exc
= exc
->next
) {
1285 if (streq(name
, exc
->exclude_dir
))
1292 static int depmod_modules_search_dir(struct depmod
*depmod
, DIR *d
, size_t baselen
, struct scratchbuf
*s_path
)
1295 int err
= 0, dfd
= dirfd(d
);
1298 while ((de
= readdir(d
)) != NULL
) {
1299 const char *name
= de
->d_name
;
1303 if (should_exclude_dir(depmod
->cfg
, name
))
1306 namelen
= strlen(name
);
1307 if (scratchbuf_alloc(s_path
, baselen
+ namelen
+ 2) < 0) {
1313 path
= scratchbuf_str(s_path
);
1314 memcpy(path
+ baselen
, name
, namelen
+ 1);
1316 if (de
->d_type
== DT_REG
)
1318 else if (de
->d_type
== DT_DIR
)
1322 if (fstatat(dfd
, name
, &st
, 0) < 0) {
1323 ERR("fstatat(%d, %s): %m\n", dfd
, name
);
1325 } else if (S_ISREG(st
.st_mode
))
1327 else if (S_ISDIR(st
.st_mode
))
1330 ERR("unsupported file type %s: %o\n",
1331 path
, st
.st_mode
& S_IFMT
);
1339 fd
= openat(dfd
, name
, O_RDONLY
);
1341 ERR("openat(%d, %s, O_RDONLY): %m\n",
1345 subdir
= fdopendir(fd
);
1346 if (subdir
== NULL
) {
1347 ERR("fdopendir(%d): %m\n", fd
);
1351 path
[baselen
+ namelen
] = '/';
1352 path
[baselen
+ namelen
+ 1] = '\0';
1353 err
= depmod_modules_search_dir(depmod
, subdir
,
1354 baselen
+ namelen
+ 1,
1358 err
= depmod_modules_search_file(depmod
, baselen
,
1363 path
[baselen
+ namelen
] = '\0';
1364 ERR("failed %s: %s\n", path
, strerror(-err
));
1365 err
= 0; /* ignore errors */
1371 static int depmod_modules_search_path(struct depmod
*depmod
,
1375 _cleanup_(scratchbuf_release
) struct scratchbuf s_path_buf
=
1376 SCRATCHBUF_INITIALIZER(buf
);
1385 ERR("could not open directory %s: %m\n", path
);
1389 baselen
= strlen(path
);
1391 if (scratchbuf_alloc(&s_path_buf
, baselen
+ 2) < 0) {
1395 path_buf
= scratchbuf_str(&s_path_buf
);
1397 memcpy(path_buf
, path
, baselen
);
1398 path_buf
[baselen
] = '/';
1400 path_buf
[baselen
] = '\0';
1402 err
= depmod_modules_search_dir(depmod
, d
, baselen
, &s_path_buf
);
1408 static int depmod_modules_search(struct depmod
*depmod
)
1411 struct cfg_external
*ext
;
1413 err
= depmod_modules_search_path(depmod
, depmod
->cfg
->dirname
);
1417 for (ext
= depmod
->cfg
->externals
; ext
!= NULL
; ext
= ext
->next
) {
1418 err
= depmod_modules_search_path(depmod
, ext
->path
);
1419 if (err
< 0 && err
== -ENOENT
)
1420 /* ignore external dir absense */
1427 static int mod_cmp(const void *pa
, const void *pb
) {
1428 const struct mod
*a
= *(const struct mod
**)pa
;
1429 const struct mod
*b
= *(const struct mod
**)pb
;
1430 return a
->sort_idx
- b
->sort_idx
;
1433 static int depmod_modules_build_array(struct depmod
*depmod
)
1435 struct hash_iter module_iter
;
1439 hash_iter_init(depmod
->modules_by_name
, &module_iter
);
1440 while (hash_iter_next(&module_iter
, NULL
, &v
)) {
1441 struct mod
*mod
= (struct mod
*) v
;
1442 mod
->idx
= depmod
->modules
.count
;
1443 err
= array_append(&depmod
->modules
, mod
);
1451 static FILE *dfdopen(const char *dname
, const char *filename
, int flags
,
1457 dfd
= open(dname
, O_RDONLY
);
1459 WRN("could not open directory %s: %m\n", dname
);
1463 fd
= openat(dfd
, filename
, flags
);
1465 WRN("could not open %s at %s: %m\n", filename
, dname
);
1468 ret
= fdopen(fd
, mode
);
1470 WRN("could not associate stream with %s: %m\n", filename
);
1480 static void depmod_modules_sort(struct depmod
*depmod
)
1482 char line
[PATH_MAX
];
1483 const char *order_file
= "modules.order";
1485 unsigned idx
= 0, total
= 0;
1487 fp
= dfdopen(depmod
->cfg
->dirname
, order_file
, O_RDONLY
, "r");
1491 while (fgets(line
, sizeof(line
), fp
) != NULL
) {
1492 size_t len
= strlen(line
);
1496 if (line
[len
- 1] != '\n') {
1497 ERR("%s/%s:%u corrupted line misses '\\n'\n",
1498 depmod
->cfg
->dirname
, order_file
, idx
);
1504 fseek(fp
, 0, SEEK_SET
);
1505 while (fgets(line
, sizeof(line
), fp
) != NULL
) {
1506 size_t len
= strlen(line
);
1512 line
[len
- 1] = '\0';
1514 mod
= hash_find(depmod
->modules_by_uncrelpath
, line
);
1517 mod
->sort_idx
= idx
- total
;
1520 array_sort(&depmod
->modules
, mod_cmp
);
1521 for (idx
= 0; idx
< depmod
->modules
.count
; idx
++) {
1522 struct mod
*m
= depmod
->modules
.array
[idx
];
1530 static int depmod_symbol_add(struct depmod
*depmod
, const char *name
,
1531 bool prefix_skipped
, uint64_t crc
,
1532 const struct mod
*owner
)
1538 if (!prefix_skipped
&& (name
[0] == depmod
->cfg
->sym_prefix
))
1541 namelen
= strlen(name
) + 1;
1542 sym
= malloc(sizeof(struct symbol
) + namelen
);
1546 sym
->owner
= (struct mod
*)owner
;
1548 memcpy(sym
->name
, name
, namelen
);
1550 err
= hash_add(depmod
->symbols
, sym
->name
, sym
);
1556 DBG("add %p sym=%s, owner=%p %s\n", sym
, sym
->name
, owner
,
1557 owner
!= NULL
? owner
->path
: "");
1562 static struct symbol
*depmod_symbol_find(const struct depmod
*depmod
,
1565 if (name
[0] == '.') /* PPC64 needs this: .foo == foo */
1567 if (name
[0] == depmod
->cfg
->sym_prefix
)
1569 return hash_find(depmod
->symbols
, name
);
1572 static int depmod_load_modules(struct depmod
*depmod
)
1574 struct mod
**itr
, **itr_end
;
1576 DBG("load symbols (%zd modules)\n", depmod
->modules
.count
);
1578 itr
= (struct mod
**)depmod
->modules
.array
;
1579 itr_end
= itr
+ depmod
->modules
.count
;
1580 for (; itr
< itr_end
; itr
++) {
1581 struct mod
*mod
= *itr
;
1582 struct kmod_list
*l
, *list
= NULL
;
1583 int err
= kmod_module_get_symbols(mod
->kmod
, &list
);
1586 DBG("ignoring %s: no symbols\n", mod
->path
);
1588 ERR("failed to load symbols from %s: %s\n",
1589 mod
->path
, strerror(-err
));
1592 kmod_list_foreach(l
, list
) {
1593 const char *name
= kmod_module_symbol_get_symbol(l
);
1594 uint64_t crc
= kmod_module_symbol_get_crc(l
);
1595 depmod_symbol_add(depmod
, name
, false, crc
, mod
);
1597 kmod_module_symbols_free_list(list
);
1600 kmod_module_get_info(mod
->kmod
, &mod
->info_list
);
1601 kmod_module_get_dependency_symbols(mod
->kmod
,
1602 &mod
->dep_sym_list
);
1603 kmod_module_unref(mod
->kmod
);
1607 DBG("loaded symbols (%zd modules, %u symbols)\n",
1608 depmod
->modules
.count
, hash_get_count(depmod
->symbols
));
1613 static int depmod_load_module_dependencies(struct depmod
*depmod
, struct mod
*mod
)
1615 const struct cfg
*cfg
= depmod
->cfg
;
1616 struct kmod_list
*l
;
1618 DBG("do dependencies of %s\n", mod
->path
);
1619 kmod_list_foreach(l
, mod
->dep_sym_list
) {
1620 const char *name
= kmod_module_dependency_symbol_get_symbol(l
);
1621 uint64_t crc
= kmod_module_dependency_symbol_get_crc(l
);
1622 int bindtype
= kmod_module_dependency_symbol_get_bind(l
);
1623 struct symbol
*sym
= depmod_symbol_find(depmod
, name
);
1624 uint8_t is_weak
= bindtype
== KMOD_SYMBOL_WEAK
;
1627 DBG("%s needs (%c) unknown symbol %s\n",
1628 mod
->path
, bindtype
, name
);
1629 if (cfg
->print_unknown
&& !is_weak
)
1630 WRN("%s needs unknown symbol %s\n",
1635 if (cfg
->check_symvers
&& sym
->crc
!= crc
&& !is_weak
) {
1636 DBG("symbol %s (%#"PRIx64
") module %s (%#"PRIx64
")\n",
1637 sym
->name
, sym
->crc
, mod
->path
, crc
);
1638 if (cfg
->print_unknown
)
1639 WRN("%s disagrees about version of symbol %s\n",
1643 mod_add_dependency(mod
, sym
);
1649 static int depmod_load_dependencies(struct depmod
*depmod
)
1651 struct mod
**itr
, **itr_end
;
1653 DBG("load dependencies (%zd modules, %u symbols)\n",
1654 depmod
->modules
.count
, hash_get_count(depmod
->symbols
));
1656 itr
= (struct mod
**)depmod
->modules
.array
;
1657 itr_end
= itr
+ depmod
->modules
.count
;
1658 for (; itr
< itr_end
; itr
++) {
1659 struct mod
*mod
= *itr
;
1661 if (mod
->dep_sym_list
== NULL
) {
1662 DBG("ignoring %s: no dependency symbols\n", mod
->path
);
1666 depmod_load_module_dependencies(depmod
, mod
);
1669 DBG("loaded dependencies (%zd modules, %u symbols)\n",
1670 depmod
->modules
.count
, hash_get_count(depmod
->symbols
));
1675 static int dep_cmp(const void *pa
, const void *pb
)
1677 const struct mod
*a
= *(const struct mod
**)pa
;
1678 const struct mod
*b
= *(const struct mod
**)pb
;
1679 return a
->dep_sort_idx
- b
->dep_sort_idx
;
1682 static void depmod_sort_dependencies(struct depmod
*depmod
)
1684 struct mod
**itr
, **itr_end
;
1685 itr
= (struct mod
**)depmod
->modules
.array
;
1686 itr_end
= itr
+ depmod
->modules
.count
;
1687 for (; itr
< itr_end
; itr
++) {
1688 struct mod
*m
= *itr
;
1689 if (m
->deps
.count
> 1)
1690 array_sort(&m
->deps
, dep_cmp
);
1695 struct vertex
*parent
;
1699 static struct vertex
*vertex_new(struct mod
*mod
, struct vertex
*parent
)
1703 v
= malloc(sizeof(*v
));
1712 static void depmod_list_remove_data(struct kmod_list
**list
, void *data
)
1714 struct kmod_list
*l
;
1716 l
= kmod_list_remove_data(*list
, data
);
1720 static int depmod_report_one_cycle(struct depmod
*depmod
,
1721 struct vertex
*vertex
,
1722 struct kmod_list
**roots
,
1723 struct hash
*loop_set
)
1725 const char sep
[] = " -> ";
1728 struct array reverse
;
1734 array_init(&reverse
, 3);
1737 for (v
= vertex
->parent
, n
= 0;
1739 v
= v
->parent
, n
++) {
1741 sz
+= v
->mod
->modnamesz
- 1;
1742 array_append(&reverse
, v
);
1743 rc
= hash_add(loop_set
, v
->mod
->modname
, NULL
);
1746 /* the hash will be freed where created */
1748 sz
+= vertex
->mod
->modnamesz
- 1;
1750 buf
= malloc(sz
+ n
* strlen(sep
) + 1);
1753 for (i
= reverse
.count
- 1; i
>= 0; i
--) {
1756 v
= reverse
.array
[i
];
1758 len
= v
->mod
->modnamesz
- 1;
1759 memcpy(buf
+ sz
, v
->mod
->modname
, len
);
1761 strcpy(buf
+ sz
, sep
);
1764 depmod_list_remove_data(roots
, v
->mod
);
1766 strcpy(buf
+ sz
, vertex
->mod
->modname
);
1767 ERR("Cycle detected: %s\n", buf
);
1770 array_free_array(&reverse
);
1775 static int depmod_report_cycles_from_root(struct depmod
*depmod
,
1776 struct mod
*root_mod
,
1777 struct kmod_list
**roots
,
1780 struct hash
*loop_set
)
1782 struct kmod_list
*free_list
= NULL
; /* struct vertex */
1783 struct kmod_list
*l
;
1784 struct vertex
*root
;
1785 struct vertex
*vertex
;
1788 struct mod
**itr
, **itr_end
;
1792 root
= vertex_new(root_mod
, NULL
);
1794 ERR("No memory to report cycles\n");
1798 l
= kmod_list_append(free_list
, root
);
1800 ERR("No memory to report cycles\n");
1806 stack
[is
++] = (void *)root
;
1809 vertex
= stack
[--is
];
1812 * because of the topological sort we can start only
1813 * from part of a loop or from a branch after a loop
1815 if (m
->visited
&& m
== root
->mod
) {
1817 rc
= depmod_report_one_cycle(depmod
, vertex
,
1827 if (m
->deps
.count
== 0) {
1829 * boundary condition: if there is more than one
1830 * single node branch (not a loop), it is
1831 * recognized as a loop by the code above:
1832 * m->visited because more then one,
1833 * m == root->mod since it is a single node.
1834 * So, prevent deeping into the branch second
1837 depmod_list_remove_data(roots
, m
);
1842 itr
= (struct mod
**) m
->deps
.array
;
1843 itr_end
= itr
+ m
->deps
.count
;
1844 for (; itr
< itr_end
; itr
++) {
1845 struct mod
*dep
= *itr
;
1846 v
= vertex_new(dep
, vertex
);
1848 ERR("No memory to report cycles\n");
1851 assert(is
< stack_size
);
1854 l
= kmod_list_append(free_list
, v
);
1856 ERR("No memory to report cycles\n");
1867 v
= free_list
->data
;
1868 l
= kmod_list_remove(free_list
);
1876 static void depmod_report_cycles(struct depmod
*depmod
, uint16_t n_mods
,
1880 struct kmod_list
*roots
= NULL
; /* struct mod */
1881 struct kmod_list
*l
;
1882 size_t n_r
; /* local n_roots */
1885 _cleanup_free_
void **stack
= NULL
;
1888 struct hash
*loop_set
;
1890 for (i
= 0, n_r
= 0; i
< n_mods
; i
++) {
1893 m
= depmod
->modules
.array
[i
];
1894 l
= kmod_list_append(roots
, m
);
1896 ERR("No memory to report cycles\n");
1903 stack
= malloc(n_r
* sizeof(void *));
1904 if (stack
== NULL
) {
1905 ERR("No memory to report cycles\n");
1909 loop_set
= hash_new(16, NULL
);
1910 if (loop_set
== NULL
) {
1911 ERR("No memory to report cycles\n");
1915 while (roots
!= NULL
) {
1917 l
= kmod_list_remove(roots
);
1919 err
= depmod_report_cycles_from_root(depmod
,
1922 stack
, n_r
, loop_set
);
1927 num_cyclic
= hash_get_count(loop_set
);
1928 ERR("Found %d modules in dependency cycles!\n", num_cyclic
);
1931 hash_free(loop_set
);
1933 while (roots
!= NULL
) {
1934 /* no need to free data, come from outside */
1935 roots
= kmod_list_remove(roots
);
1939 static int depmod_calculate_dependencies(struct depmod
*depmod
)
1941 const struct mod
**itrm
;
1942 uint16_t *users
, *roots
, *sorted
;
1943 uint16_t i
, n_roots
= 0, n_sorted
= 0, n_mods
= depmod
->modules
.count
;
1946 users
= malloc(sizeof(uint16_t) * n_mods
* 3);
1949 roots
= users
+ n_mods
;
1950 sorted
= roots
+ n_mods
;
1952 DBG("calculate dependencies and ordering (%hu modules)\n", n_mods
);
1954 assert(depmod
->modules
.count
< UINT16_MAX
);
1956 /* populate modules users (how many modules uses it) */
1957 itrm
= (const struct mod
**)depmod
->modules
.array
;
1958 for (i
= 0; i
< n_mods
; i
++, itrm
++) {
1959 const struct mod
*m
= *itrm
;
1960 users
[i
] = m
->users
;
1961 if (users
[i
] == 0) {
1967 /* topological sort (outputs modules without users first) */
1968 while (n_roots
> 0) {
1969 const struct mod
**itr_dst
, **itr_dst_end
;
1971 uint16_t src_idx
= roots
[--n_roots
];
1973 src
= depmod
->modules
.array
[src_idx
];
1974 src
->dep_sort_idx
= n_sorted
;
1975 sorted
[n_sorted
] = src_idx
;
1978 itr_dst
= (const struct mod
**)src
->deps
.array
;
1979 itr_dst_end
= itr_dst
+ src
->deps
.count
;
1980 for (; itr_dst
< itr_dst_end
; itr_dst
++) {
1981 const struct mod
*dst
= *itr_dst
;
1982 uint16_t dst_idx
= dst
->idx
;
1983 assert(users
[dst_idx
] > 0);
1985 if (users
[dst_idx
] == 0) {
1986 roots
[n_roots
] = dst_idx
;
1992 if (n_sorted
< n_mods
) {
1993 depmod_report_cycles(depmod
, n_mods
, users
);
1998 depmod_sort_dependencies(depmod
);
2000 DBG("calculated dependencies and ordering (%hu modules)\n", n_mods
);
2007 static int depmod_load(struct depmod
*depmod
)
2011 err
= depmod_load_modules(depmod
);
2015 err
= depmod_load_dependencies(depmod
);
2019 err
= depmod_calculate_dependencies(depmod
);
2026 static size_t mod_count_all_dependencies(const struct mod
*mod
)
2028 size_t i
, count
= 0;
2029 for (i
= 0; i
< mod
->deps
.count
; i
++) {
2030 const struct mod
*d
= mod
->deps
.array
[i
];
2031 count
+= 1 + mod_count_all_dependencies(d
);
2036 static int mod_fill_all_unique_dependencies(const struct mod
*mod
, const struct mod
**deps
, size_t n_deps
, size_t *last
)
2040 for (i
= 0; i
< mod
->deps
.count
; i
++) {
2041 const struct mod
*d
= mod
->deps
.array
[i
];
2045 for (j
= 0; j
< *last
; j
++) {
2055 if (*last
>= n_deps
)
2059 err
= mod_fill_all_unique_dependencies(d
, deps
, n_deps
, last
);
2066 static const struct mod
**mod_get_all_sorted_dependencies(const struct mod
*mod
, size_t *n_deps
)
2068 const struct mod
**deps
;
2071 *n_deps
= mod_count_all_dependencies(mod
);
2075 deps
= malloc(sizeof(struct mod
*) * (*n_deps
));
2079 if (mod_fill_all_unique_dependencies(mod
, deps
, *n_deps
, &last
) < 0) {
2084 qsort(deps
, last
, sizeof(struct mod
*), dep_cmp
);
2089 static inline const char *mod_get_compressed_path(const struct mod
*mod
)
2091 if (mod
->relpath
!= NULL
)
2092 return mod
->relpath
;
2096 static int output_deps(struct depmod
*depmod
, FILE *out
)
2100 for (i
= 0; i
< depmod
->modules
.count
; i
++) {
2101 const struct mod
**deps
, *mod
= depmod
->modules
.array
[i
];
2102 const char *p
= mod_get_compressed_path(mod
);
2105 fprintf(out
, "%s:", p
);
2107 if (mod
->deps
.count
== 0)
2110 deps
= mod_get_all_sorted_dependencies(mod
, &n_deps
);
2112 ERR("could not get all sorted dependencies of %s\n", p
);
2116 for (j
= 0; j
< n_deps
; j
++) {
2117 const struct mod
*d
= deps
[j
];
2118 fprintf(out
, " %s", mod_get_compressed_path(d
));
2128 static int output_deps_bin(struct depmod
*depmod
, FILE *out
)
2130 struct index_node
*idx
;
2136 idx
= index_create();
2140 for (i
= 0; i
< depmod
->modules
.count
; i
++) {
2141 const struct mod
**deps
, *mod
= depmod
->modules
.array
[i
];
2142 const char *p
= mod_get_compressed_path(mod
);
2144 size_t j
, n_deps
, linepos
, linelen
, slen
;
2147 deps
= mod_get_all_sorted_dependencies(mod
, &n_deps
);
2148 if (deps
== NULL
&& n_deps
> 0) {
2149 ERR("could not get all sorted dependencies of %s\n", p
);
2153 linelen
= strlen(p
) + 1;
2154 for (j
= 0; j
< n_deps
; j
++) {
2155 const struct mod
*d
= deps
[j
];
2156 linelen
+= 1 + strlen(mod_get_compressed_path(d
));
2159 line
= malloc(linelen
+ 1);
2162 ERR("modules.deps.bin: out of memory\n");
2168 memcpy(line
+ linepos
, p
, slen
);
2170 line
[linepos
] = ':';
2173 for (j
= 0; j
< n_deps
; j
++) {
2174 const struct mod
*d
= deps
[j
];
2177 line
[linepos
] = ' ';
2180 dp
= mod_get_compressed_path(d
);
2182 memcpy(line
+ linepos
, dp
, slen
);
2185 line
[linepos
] = '\0';
2187 duplicate
= index_insert(idx
, mod
->modname
, line
, mod
->idx
);
2188 if (duplicate
&& depmod
->cfg
->warn_dups
)
2189 WRN("duplicate module deps:\n%s\n", line
);
2194 index_write(idx
, out
);
2200 static int output_aliases(struct depmod
*depmod
, FILE *out
)
2204 fputs("# Aliases extracted from modules themselves.\n", out
);
2206 for (i
= 0; i
< depmod
->modules
.count
; i
++) {
2207 const struct mod
*mod
= depmod
->modules
.array
[i
];
2208 struct kmod_list
*l
;
2210 kmod_list_foreach(l
, mod
->info_list
) {
2211 const char *key
= kmod_module_info_get_key(l
);
2212 const char *value
= kmod_module_info_get_value(l
);
2214 if (!streq(key
, "alias"))
2217 fprintf(out
, "alias %s %s\n", value
, mod
->modname
);
2224 static int output_aliases_bin(struct depmod
*depmod
, FILE *out
)
2226 struct index_node
*idx
;
2232 idx
= index_create();
2236 for (i
= 0; i
< depmod
->modules
.count
; i
++) {
2237 const struct mod
*mod
= depmod
->modules
.array
[i
];
2238 struct kmod_list
*l
;
2240 kmod_list_foreach(l
, mod
->info_list
) {
2241 const char *key
= kmod_module_info_get_key(l
);
2242 const char *value
= kmod_module_info_get_value(l
);
2247 if (!streq(key
, "alias"))
2250 if (alias_normalize(value
, buf
, NULL
) < 0) {
2251 WRN("Unmatched bracket in %s\n", value
);
2256 duplicate
= index_insert(idx
, alias
, mod
->modname
,
2258 if (duplicate
&& depmod
->cfg
->warn_dups
)
2259 WRN("duplicate module alias:\n%s %s\n",
2260 alias
, mod
->modname
);
2264 index_write(idx
, out
);
2270 static int output_softdeps(struct depmod
*depmod
, FILE *out
)
2274 fputs("# Soft dependencies extracted from modules themselves.\n", out
);
2276 for (i
= 0; i
< depmod
->modules
.count
; i
++) {
2277 const struct mod
*mod
= depmod
->modules
.array
[i
];
2278 struct kmod_list
*l
;
2280 kmod_list_foreach(l
, mod
->info_list
) {
2281 const char *key
= kmod_module_info_get_key(l
);
2282 const char *value
= kmod_module_info_get_value(l
);
2284 if (!streq(key
, "softdep"))
2287 fprintf(out
, "softdep %s %s\n", mod
->modname
, value
);
2294 static int output_symbols(struct depmod
*depmod
, FILE *out
)
2296 struct hash_iter iter
;
2299 fputs("# Aliases for symbols, used by symbol_request().\n", out
);
2301 hash_iter_init(depmod
->symbols
, &iter
);
2303 while (hash_iter_next(&iter
, NULL
, &v
)) {
2304 const struct symbol
*sym
= v
;
2305 if (sym
->owner
== NULL
)
2308 fprintf(out
, "alias symbol:%s %s\n",
2309 sym
->name
, sym
->owner
->modname
);
2315 static int output_symbols_bin(struct depmod
*depmod
, FILE *out
)
2317 struct index_node
*idx
;
2319 _cleanup_(scratchbuf_release
) struct scratchbuf salias
=
2320 SCRATCHBUF_INITIALIZER(alias
);
2321 size_t baselen
= sizeof("symbol:") - 1;
2322 struct hash_iter iter
;
2329 idx
= index_create();
2333 memcpy(alias
, "symbol:", baselen
);
2335 hash_iter_init(depmod
->symbols
, &iter
);
2337 while (hash_iter_next(&iter
, NULL
, &v
)) {
2339 const struct symbol
*sym
= v
;
2342 if (sym
->owner
== NULL
)
2345 len
= strlen(sym
->name
);
2347 if (scratchbuf_alloc(&salias
, baselen
+ len
+ 1) < 0) {
2349 goto err_scratchbuf
;
2351 memcpy(scratchbuf_str(&salias
) + baselen
, sym
->name
, len
+ 1);
2352 duplicate
= index_insert(idx
, alias
, sym
->owner
->modname
,
2355 if (duplicate
&& depmod
->cfg
->warn_dups
)
2356 WRN("duplicate module syms:\n%s %s\n",
2357 alias
, sym
->owner
->modname
);
2360 index_write(idx
, out
);
2366 ERR("output symbols: %s\n", strerror(-ret
));
2371 static int output_builtin_bin(struct depmod
*depmod
, FILE *out
)
2374 struct index_node
*idx
;
2375 char line
[PATH_MAX
], modname
[PATH_MAX
];
2380 in
= dfdopen(depmod
->cfg
->dirname
, "modules.builtin", O_RDONLY
, "r");
2384 idx
= index_create();
2390 while (fgets(line
, sizeof(line
), in
) != NULL
) {
2391 if (!isalpha(line
[0])) {
2392 ERR("Invalid modules.builtin line: %s\n", line
);
2396 path_to_modname(line
, modname
, NULL
);
2397 index_insert(idx
, modname
, "", 0);
2400 index_write(idx
, out
);
2407 static int flush_stream(FILE *in
, int endchar
)
2413 c
!= EOF
&& c
!= endchar
&& c
!= '\0';
2417 return c
== endchar
? i
: 0;
2420 static int flush_stream_to(FILE *in
, int endchar
, char *dst
, size_t dst_sz
)
2426 c
!= EOF
&& c
!= endchar
&& c
!= '\0' && i
< dst_sz
;
2431 WRN("Could not flush stream: %d. Partial content: %.*s\n",
2432 ENOSPC
, (int) dst_sz
, dst
);
2436 return c
== endchar
? i
: 0;
2439 static int output_builtin_alias_bin(struct depmod
*depmod
, FILE *out
)
2442 struct index_node
*idx
;
2448 in
= dfdopen(depmod
->cfg
->dirname
, "modules.builtin.modinfo", O_RDONLY
, "r");
2452 idx
= index_create();
2458 /* format: modname.key=value\0 */
2459 while (!feof(in
) && !ferror(in
)) {
2460 char alias
[PATH_MAX
];
2461 char modname
[PATH_MAX
];
2462 char value
[PATH_MAX
];
2465 len
= flush_stream_to(in
, '.', modname
, sizeof(modname
));
2466 modname
[len
] = '\0';
2470 len
= flush_stream_to(in
, '=', value
, sizeof(value
));
2472 if (!streq(value
, "alias")) {
2473 flush_stream(in
, '\0');
2477 len
= flush_stream_to(in
, '\0', value
, sizeof(value
));
2483 if (alias_normalize(value
, alias
, NULL
) < 0) {
2484 WRN("Unmatched bracket in %s\n", value
);
2488 index_insert(idx
, alias
, modname
, 0);
2494 index_write(idx
, out
);
2504 static int output_devname(struct depmod
*depmod
, FILE *out
)
2509 for (i
= 0; i
< depmod
->modules
.count
; i
++) {
2510 const struct mod
*mod
= depmod
->modules
.array
[i
];
2511 struct kmod_list
*l
;
2512 const char *devname
= NULL
;
2514 unsigned int major
= 0, minor
= 0;
2516 kmod_list_foreach(l
, mod
->info_list
) {
2517 const char *key
= kmod_module_info_get_key(l
);
2518 const char *value
= kmod_module_info_get_value(l
);
2519 unsigned int maj
, min
;
2521 if (!streq(key
, "alias"))
2524 if (strstartswith(value
, "devname:"))
2525 devname
= value
+ sizeof("devname:") - 1;
2526 else if (sscanf(value
, "char-major-%u-%u",
2531 } else if (sscanf(value
, "block-major-%u-%u",
2538 if (type
!= '\0' && devname
!= NULL
)
2542 if (devname
!= NULL
) {
2545 fputs("# Device nodes to trigger on-demand module loading.\n",
2549 fprintf(out
, "%s %s %c%u:%u\n", mod
->modname
,
2550 devname
, type
, major
, minor
);
2552 ERR("Module '%s' has devname (%s) but "
2553 "lacks major and minor information. "
2554 "Ignoring.\n", mod
->modname
, devname
);
2561 static int depmod_output(struct depmod
*depmod
, FILE *out
)
2563 static const struct depfile
{
2565 int (*cb
)(struct depmod
*depmod
, FILE *out
);
2566 } *itr
, depfiles
[] = {
2567 { "modules.dep", output_deps
},
2568 { "modules.dep.bin", output_deps_bin
},
2569 { "modules.alias", output_aliases
},
2570 { "modules.alias.bin", output_aliases_bin
},
2571 { "modules.softdep", output_softdeps
},
2572 { "modules.symbols", output_symbols
},
2573 { "modules.symbols.bin", output_symbols_bin
},
2574 { "modules.builtin.bin", output_builtin_bin
},
2575 { "modules.builtin.alias.bin", output_builtin_alias_bin
},
2576 { "modules.devname", output_devname
},
2579 const char *dname
= depmod
->cfg
->dirname
;
2583 gettimeofday(&tv
, NULL
);
2588 dfd
= open(dname
, O_RDONLY
);
2591 CRIT("could not open directory %s: %m\n", dname
);
2596 for (itr
= depfiles
; itr
->name
!= NULL
; itr
++) {
2598 char tmp
[NAME_MAX
] = "";
2602 int flags
= O_CREAT
| O_EXCL
| O_WRONLY
;
2606 snprintf(tmp
, sizeof(tmp
), "%s.%i.%li.%li", itr
->name
, getpid(),
2607 tv
.tv_usec
, tv
.tv_sec
);
2608 fd
= openat(dfd
, tmp
, flags
, mode
);
2610 ERR("openat(%s, %s, %o, %o): %m\n",
2611 dname
, tmp
, flags
, mode
);
2614 fp
= fdopen(fd
, "wb");
2616 ERR("fdopen(%d=%s/%s): %m\n", fd
, dname
, tmp
);
2622 r
= itr
->cb(depmod
, fp
);
2626 ferr
= ferror(fp
) | fclose(fp
);
2629 if (unlinkat(dfd
, tmp
, 0) != 0)
2630 ERR("unlinkat(%s, %s): %m\n", dname
, tmp
);
2632 ERR("Could not write index '%s': %s\n", itr
->name
,
2638 if (renameat(dfd
, tmp
, dfd
, itr
->name
) != 0) {
2640 CRIT("renameat(%s, %s, %s, %s): %m\n",
2641 dname
, tmp
, dname
, itr
->name
);
2647 ERR("Could not create index '%s'. Output is truncated: %s\n",
2648 itr
->name
, strerror(-err
));
2659 static void depmod_add_fake_syms(struct depmod
*depmod
)
2661 /* __this_module is magic inserted by kernel loader. */
2662 depmod_symbol_add(depmod
, "__this_module", true, 0, NULL
);
2663 /* On S390, this is faked up too */
2664 depmod_symbol_add(depmod
, "_GLOBAL_OFFSET_TABLE_", true, 0, NULL
);
2665 /* On PowerPC64 ABIv2, .TOC. is more or less _GLOBAL_OFFSET_TABLE_ */
2666 if (!depmod_symbol_find(depmod
, "TOC."))
2667 depmod_symbol_add(depmod
, "TOC.", true, 0, NULL
);
2670 static int depmod_load_symvers(struct depmod
*depmod
, const char *filename
)
2674 unsigned int linenum
= 0;
2676 fp
= fopen(filename
, "r");
2679 DBG("load symvers: %s: %m\n", filename
);
2682 DBG("load symvers: %s\n", filename
);
2684 /* eg. "0xb352177e\tfind_first_bit\tvmlinux\tEXPORT_SYMBOL" */
2685 while (fgets(line
, sizeof(line
), fp
) != NULL
) {
2686 const char *ver
, *sym
, *where
;
2692 ver
= strtok(line
, " \t");
2693 sym
= strtok(NULL
, " \t");
2694 where
= strtok(NULL
, " \t");
2695 if (!ver
|| !sym
|| !where
)
2698 if (!streq(where
, "vmlinux"))
2701 crc
= strtoull(ver
, &verend
, 16);
2702 if (verend
[0] != '\0') {
2703 ERR("%s:%u Invalid symbol version %s: %m\n",
2704 filename
, linenum
, ver
);
2708 depmod_symbol_add(depmod
, sym
, false, crc
, NULL
);
2710 depmod_add_fake_syms(depmod
);
2712 DBG("loaded symvers: %s\n", filename
);
2718 static int depmod_load_system_map(struct depmod
*depmod
, const char *filename
)
2720 const char ksymstr
[] = "__ksymtab_";
2721 const size_t ksymstr_len
= sizeof(ksymstr
) - 1;
2724 unsigned int linenum
= 0;
2726 fp
= fopen(filename
, "r");
2729 DBG("load System.map: %s: %m\n", filename
);
2732 DBG("load System.map: %s\n", filename
);
2734 /* eg. c0294200 R __ksymtab_devfs_alloc_devnum */
2735 while (fgets(line
, sizeof(line
), fp
) != NULL
) {
2740 p
= strchr(line
, ' ');
2742 goto invalid_syntax
;
2746 goto invalid_syntax
;
2750 if (p
[0] == depmod
->cfg
->sym_prefix
)
2753 /* Covers gpl-only and normal symbols. */
2754 if (strncmp(p
, ksymstr
, ksymstr_len
) != 0)
2757 end
= strchr(p
, '\n');
2761 depmod_symbol_add(depmod
, p
+ ksymstr_len
, true, 0, NULL
);
2765 ERR("%s:%u: invalid line: %s\n", filename
, linenum
, line
);
2767 depmod_add_fake_syms(depmod
);
2769 DBG("loaded System.map: %s\n", filename
);
2776 static int depfile_up_to_date_dir(DIR *d
, time_t mtime
, size_t baselen
, char *path
)
2779 int err
= 1, dfd
= dirfd(d
);
2781 while ((de
= readdir(d
)) != NULL
) {
2782 const char *name
= de
->d_name
;
2786 if (name
[0] == '.' && (name
[1] == '\0' ||
2787 (name
[1] == '.' && name
[2] == '\0')))
2789 if (streq(name
, "build") || streq(name
, "source"))
2791 namelen
= strlen(name
);
2792 if (baselen
+ namelen
+ 2 >= PATH_MAX
) {
2793 path
[baselen
] = '\0';
2794 ERR("path is too long %s%s\n", path
, name
);
2798 if (fstatat(dfd
, name
, &st
, 0) < 0) {
2799 ERR("fstatat(%d, %s): %m\n", dfd
, name
);
2803 if (S_ISDIR(st
.st_mode
)) {
2806 memcpy(path
+ baselen
, name
, namelen
+ 1);
2807 if (baselen
+ namelen
+ 2 + NAME_MAX
>= PATH_MAX
) {
2808 ERR("directory path is too long %s\n", path
);
2811 fd
= openat(dfd
, name
, O_RDONLY
);
2813 ERR("openat(%d, %s, O_RDONLY): %m\n",
2817 subdir
= fdopendir(fd
);
2818 if (subdir
== NULL
) {
2819 ERR("fdopendir(%d): %m\n", fd
);
2823 path
[baselen
+ namelen
] = '/';
2824 path
[baselen
+ namelen
+ 1] = '\0';
2825 err
= depfile_up_to_date_dir(subdir
, mtime
,
2826 baselen
+ namelen
+ 1,
2829 } else if (S_ISREG(st
.st_mode
)) {
2830 if (!path_ends_with_kmod_ext(name
, namelen
))
2833 memcpy(path
+ baselen
, name
, namelen
+ 1);
2834 err
= st
.st_mtime
<= mtime
;
2836 DBG("%s %"PRIu64
" is newer than %"PRIu64
"\n",
2837 path
, (uint64_t)st
.st_mtime
,
2841 ERR("unsupported file type %s: %o\n",
2842 path
, st
.st_mode
& S_IFMT
);
2847 break; /* outdated! */
2849 path
[baselen
+ namelen
] = '\0';
2850 ERR("failed %s: %s\n", path
, strerror(-err
));
2851 err
= 1; /* ignore errors */
2858 /* uptodate: 1, outdated: 0, errors < 0 */
2859 static int depfile_up_to_date(const char *dirname
)
2861 char path
[PATH_MAX
];
2862 DIR *d
= opendir(dirname
);
2868 ERR("could not open directory %s: %m\n", dirname
);
2872 if (fstatat(dirfd(d
), "modules.dep", &st
, 0) != 0) {
2874 ERR("could not fstatat(%s, modules.dep): %m\n", dirname
);
2879 baselen
= strlen(dirname
);
2880 memcpy(path
, dirname
, baselen
);
2881 path
[baselen
] = '/';
2883 path
[baselen
] = '\0';
2885 err
= depfile_up_to_date_dir(d
, st
.st_mtime
, baselen
, path
);
2890 static int is_version_number(const char *version
)
2892 unsigned int d1
, d2
;
2893 return (sscanf(version
, "%u.%u", &d1
, &d2
) == 2);
2896 static int do_depmod(int argc
, char *argv
[])
2899 int err
= 0, all
= 0, maybe_all
= 0, n_config_paths
= 0;
2900 _cleanup_free_
char *root
= NULL
;
2901 _cleanup_free_
const char **config_paths
= NULL
;
2902 const char *system_map
= NULL
;
2903 const char *module_symvers
= NULL
;
2904 const char *null_kmod_config
= NULL
;
2906 struct kmod_ctx
*ctx
= NULL
;
2908 struct depmod depmod
;
2910 memset(&cfg
, 0, sizeof(cfg
));
2911 memset(&depmod
, 0, sizeof(depmod
));
2915 c
= getopt_long(argc
, argv
, cmdopts_s
, cmdopts
, &idx
);
2928 root
= path_make_absolute_cwd(optarg
);
2931 size_t bytes
= sizeof(char *) * (n_config_paths
+ 2);
2932 void *tmp
= realloc(config_paths
, bytes
);
2934 fputs("Error: out-of-memory\n", stderr
);
2935 goto cmdline_failed
;
2938 config_paths
[n_config_paths
] = optarg
;
2940 config_paths
[n_config_paths
] = NULL
;
2944 module_symvers
= optarg
;
2945 cfg
.check_symvers
= 1;
2948 system_map
= optarg
;
2951 cfg
.print_unknown
= 1;
2960 if (optarg
[1] != '\0') {
2961 CRIT("-P only takes a single char\n");
2962 goto cmdline_failed
;
2964 cfg
.sym_prefix
= optarg
[0];
2974 WRN("Ignored deprecated option --%s\n",
2977 WRN("Ignored deprecated option -%c\n", c
);
2982 return EXIT_SUCCESS
;
2984 puts(PACKAGE
" version " VERSION
);
2985 puts(KMOD_FEATURES
);
2986 return EXIT_SUCCESS
;
2988 goto cmdline_failed
;
2990 ERR("unexpected getopt_long() value '%c'.\n", c
);
2991 goto cmdline_failed
;
2995 if (optind
< argc
) {
2996 if (!is_version_number(argv
[optind
])) {
2997 ERR("Bad version passed %s\n", argv
[optind
]);
2998 goto cmdline_failed
;
3000 cfg
.kversion
= argv
[optind
];
3003 if (uname(&un
) < 0) {
3004 CRIT("uname() failed: %s\n", strerror(errno
));
3005 goto cmdline_failed
;
3007 cfg
.kversion
= un
.release
;
3010 cfg
.dirnamelen
= snprintf(cfg
.dirname
, PATH_MAX
,
3011 "%s/lib/modules/%s",
3012 root
== NULL
? "" : root
, cfg
.kversion
);
3020 /* ignore up-to-date errors (< 0) */
3021 if (depfile_up_to_date(cfg
.dirname
) == 1)
3026 ctx
= kmod_new(cfg
.dirname
, &null_kmod_config
);
3028 CRIT("kmod_new(\"%s\", {NULL}) failed: %m\n", cfg
.dirname
);
3029 goto cmdline_failed
;
3032 log_setup_kmod_log(ctx
, verbose
);
3034 err
= depmod_init(&depmod
, &cfg
, ctx
);
3036 CRIT("depmod_init: %s\n", strerror(-err
));
3037 goto depmod_init_failed
;
3039 ctx
= NULL
; /* owned by depmod */
3041 if (module_symvers
!= NULL
) {
3042 err
= depmod_load_symvers(&depmod
, module_symvers
);
3044 CRIT("could not load %s: %s\n", module_symvers
,
3046 goto cmdline_failed
;
3048 } else if (system_map
!= NULL
) {
3049 err
= depmod_load_system_map(&depmod
, system_map
);
3051 CRIT("could not load %s: %s\n", system_map
,
3053 goto cmdline_failed
;
3055 } else if (cfg
.print_unknown
) {
3056 WRN("-e needs -E or -F\n");
3057 cfg
.print_unknown
= 0;
3061 err
= cfg_load(&cfg
, config_paths
);
3063 CRIT("could not load configuration files\n");
3064 goto cmdline_modules_failed
;
3066 err
= depmod_modules_search(&depmod
);
3068 CRIT("could not search modules: %s\n", strerror(-err
));
3069 goto cmdline_modules_failed
;
3074 for (i
= optind
; i
< argc
; i
++) {
3075 const char *path
= argv
[i
];
3076 struct kmod_module
*mod
;
3078 if (path
[0] != '/') {
3079 CRIT("%s: not absolute path.\n", path
);
3080 goto cmdline_modules_failed
;
3083 err
= kmod_module_new_from_path(depmod
.ctx
, path
, &mod
);
3085 CRIT("could not create module %s: %s\n",
3086 path
, strerror(-err
));
3087 goto cmdline_modules_failed
;
3090 err
= depmod_module_add(&depmod
, mod
);
3092 CRIT("could not add module %s: %s\n",
3093 path
, strerror(-err
));
3094 kmod_module_unref(mod
);
3095 goto cmdline_modules_failed
;
3100 err
= depmod_modules_build_array(&depmod
);
3102 CRIT("could not build module array: %s\n",
3104 goto cmdline_modules_failed
;
3107 depmod_modules_sort(&depmod
);
3108 err
= depmod_load(&depmod
);
3110 goto cmdline_modules_failed
;
3112 err
= depmod_output(&depmod
, out
);
3115 depmod_shutdown(&depmod
);
3117 return err
>= 0 ? EXIT_SUCCESS
: EXIT_FAILURE
;
3119 cmdline_modules_failed
:
3120 depmod_shutdown(&depmod
);
3126 return EXIT_FAILURE
;
3129 const struct kmod_cmd kmod_cmd_compat_depmod
= {
3132 .help
= "compat depmod command",