blob: e061501f6d722f76bf6b45ec930f737e85ac91af [file] [log] [blame]
Bernhard Reutner-Fischer55e547e2008-05-26 12:01:49 +00001/* vi: set sw=4 ts=4: */
2/*
3 * depmod - generate modules.dep
4 * Copyright (c) 2008 Bernhard Fischer
5 *
6 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
7 */
8
9#undef _GNU_SOURCE
10#define _GNU_SOURCE
11#include <libbb.h>
12#include <sys/utsname.h> /* uname() */
13
Bernhard Reutner-Fischercf180102008-05-26 15:12:01 +000014/*
15 * Theory of operation:
16 * - iterate over all modules and record their full path
17 * - iterate over all modules looking for "depends=" entries
18 * for each depends, look through our list of full paths and emit if found
19 */
Bernhard Reutner-Fischer55e547e2008-05-26 12:01:49 +000020struct globals {
Bernhard Reutner-Fischer634b0222008-05-28 14:20:20 +000021 llist_t *lst; /* modules without their corresponding extension */
22 size_t moddir_base_len; /* length of the "-b basedir" */
Bernhard Reutner-Fischer55e547e2008-05-26 12:01:49 +000023};
24#define G (*(struct globals*)&bb_common_bufsiz1)
25/* We have to zero it out because of NOEXEC */
26#define INIT_G() memset(&G, 0, sizeof(G))
27
28static int fill_lst(const char *modulename, struct stat ATTRIBUTE_UNUSED *sb,
29 void ATTRIBUTE_UNUSED *data, int ATTRIBUTE_UNUSED depth)
30{
Bernhard Reutner-Fischer634b0222008-05-28 14:20:20 +000031 /* We get a file here. If the file does not have ".ko" but an
32 * intermittent dentry has, it's just their fault.
33 */
34 if (strrstr(modulename, ".ko") != NULL)
Bernhard Reutner-Fischerc21d9c72008-05-28 10:35:51 +000035 llist_add_to(&G.lst, xstrdup(modulename + G.moddir_base_len));
Bernhard Reutner-Fischer55e547e2008-05-26 12:01:49 +000036 return TRUE;
37}
38
Bernhard Reutner-Fischercf180102008-05-26 15:12:01 +000039static int fileAction(const char *fname, struct stat *sb,
Bernhard Reutner-Fischer55e547e2008-05-26 12:01:49 +000040 void *data, int ATTRIBUTE_UNUSED depth)
41{
Bernhard Reutner-Fischercf180102008-05-26 15:12:01 +000042 size_t len = sb->st_size;
Bernhard Reutner-Fischer634b0222008-05-28 14:20:20 +000043 void *the_module;
44 char *ptr;
Bernhard Reutner-Fischercf180102008-05-26 15:12:01 +000045 int fd;
46 char *depends, *deps;
Bernhard Reutner-Fischer55e547e2008-05-26 12:01:49 +000047
Bernhard Reutner-Fischer634b0222008-05-28 14:20:20 +000048 if (strrstr(fname, ".ko") == NULL) /* not a module */
49 goto skip;
50
Bernhard Reutner-Fischercf180102008-05-26 15:12:01 +000051/*XXX: FIXME: does not handle compressed modules!
52 * There should be a function that looks at the extension and sets up
53 * open_transformer for us.
54 */
Bernhard Reutner-Fischercf180102008-05-26 15:12:01 +000055 fd = xopen(fname, O_RDONLY);
56 the_module = mmap(NULL, len, PROT_READ, MAP_SHARED
57#if defined MAP_POPULATE
58 |MAP_POPULATE
59#endif
60 , fd, 0);
61 close(fd);
62 if (the_module == MAP_FAILED)
63 bb_perror_msg_and_die("mmap");
64
65 ptr = the_module;
66
Bernhard Reutner-Fischerc21d9c72008-05-28 10:35:51 +000067 fprintf((FILE*)data, "%s:", fname + G.moddir_base_len);
68//bb_info_msg("fname='%s'", fname + G.moddir_base_len);
Bernhard Reutner-Fischer55e547e2008-05-26 12:01:49 +000069 do {
70 /* search for a 'd' */
Bernhard Reutner-Fischer634b0222008-05-28 14:20:20 +000071 ptr = memchr(ptr, 'd', len - (ptr - (char*)the_module));
Bernhard Reutner-Fischer55e547e2008-05-26 12:01:49 +000072 if (ptr == NULL) /* no d left, done */
Bernhard Reutner-Fischer634b0222008-05-28 14:20:20 +000073 goto none;
74 if (strncmp(ptr, "depends=", sizeof("depends=")-1) == 0)
Bernhard Reutner-Fischer55e547e2008-05-26 12:01:49 +000075 break;
Bernhard Reutner-Fischerc21d9c72008-05-28 10:35:51 +000076 ++ptr;
Bernhard Reutner-Fischer55e547e2008-05-26 12:01:49 +000077 } while (1);
Bernhard Reutner-Fischer6bb55cf2008-05-26 17:04:01 +000078 deps = depends = xstrdup (ptr + sizeof("depends=")-1);
Bernhard Reutner-Fischer55e547e2008-05-26 12:01:49 +000079//bb_info_msg(" depends='%s'", depends);
Bernhard Reutner-Fischer634b0222008-05-28 14:20:20 +000080 while (deps) {
Bernhard Reutner-Fischer55e547e2008-05-26 12:01:49 +000081 llist_t * _lst = G.lst;
Bernhard Reutner-Fischercf180102008-05-26 15:12:01 +000082
Bernhard Reutner-Fischer634b0222008-05-28 14:20:20 +000083 ptr = strsep(&deps, ",");
Bernhard Reutner-Fischer55e547e2008-05-26 12:01:49 +000084 while (_lst) {
Bernhard Reutner-Fischer634b0222008-05-28 14:20:20 +000085 /* Compare the recorded filenames ignoring ".ko*" at the end. */
86 char *tmp = bb_get_last_path_component_nostrip(_lst->data);
87 if (strncmp(ptr, tmp, strrstr(tmp, ".ko") - tmp) == 0)
Bernhard Reutner-Fischer55e547e2008-05-26 12:01:49 +000088 break; /* found it */
89 _lst = _lst->link;
90 }
Bernhard Reutner-Fischer634b0222008-05-28 14:20:20 +000091 if (_lst) {
92//bb_info_msg("[%s] -> '%s'", (char*)ptr, _lst->data);
Bernhard Reutner-Fischer423465c2008-05-26 12:19:35 +000093 fprintf((FILE*)data, " %s", _lst->data);
Bernhard Reutner-Fischer55e547e2008-05-26 12:01:49 +000094 }
95 }
Bernhard Reutner-Fischercf180102008-05-26 15:12:01 +000096 free(depends);
Bernhard Reutner-Fischerc21d9c72008-05-28 10:35:51 +000097 fprintf((FILE*)data, "\n");
Bernhard Reutner-Fischer634b0222008-05-28 14:20:20 +000098 none:
Bernhard Reutner-Fischercf180102008-05-26 15:12:01 +000099 munmap(the_module, sb->st_size);
Bernhard Reutner-Fischer634b0222008-05-28 14:20:20 +0000100 skip:
Bernhard Reutner-Fischer55e547e2008-05-26 12:01:49 +0000101 return TRUE;
102}
103
104int depmod_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
105int depmod_main(int ATTRIBUTE_UNUSED argc, char **argv)
106{
Bernhard Reutner-Fischerc21d9c72008-05-28 10:35:51 +0000107 int ret;
Bernhard Reutner-Fischer1ea25682008-05-26 21:33:05 +0000108 char *moddir_base = NULL, *moddir, *system_map, *chp;
Bernhard Reutner-Fischer6bb55cf2008-05-26 17:04:01 +0000109 FILE *filedes = stdout;
110 enum {
111 ARG_a = (1<<0), /* All modules, ignore mods in argv */
112 ARG_A = (1<<1), /* Only emit .ko that are newer than modules.dep file */
113 ARG_b = (1<<2), /* not /lib/modules/$(uname -r)/ but this base-dir */
114 ARG_e = (1<<3), /* with -F, print unresolved symbols */
115 ARG_F = (1<<4), /* System.map that contains the symbols */
116 ARG_n = (1<<5) /* dry-run, print to stdout only */
117 };
Bernhard Reutner-Fischer55e547e2008-05-26 12:01:49 +0000118
Bernhard Reutner-Fischer6bb55cf2008-05-26 17:04:01 +0000119 getopt32(argv, "aAb:eF:n", &moddir_base, &system_map);
120 argv += optind;
Bernhard Reutner-Fischerc21d9c72008-05-28 10:35:51 +0000121
122 /* got a version to use? */
Bernhard Reutner-Fischer634b0222008-05-28 14:20:20 +0000123 if (*argv && (sscanf(*argv, "%d.%d.%d", &ret, &ret, &ret) == 3)) {
Bernhard Reutner-Fischerc21d9c72008-05-28 10:35:51 +0000124 moddir = concat_path_file(CONFIG_DEFAULT_MODULES_DIR, *argv++);
Bernhard Reutner-Fischer1ea25682008-05-26 21:33:05 +0000125 } else {
Bernhard Reutner-Fischer6bb55cf2008-05-26 17:04:01 +0000126 struct utsname uts;
127 if (uname(&uts) < 0)
128 bb_simple_perror_msg_and_die("uname");
Bernhard Reutner-Fischerc21d9c72008-05-28 10:35:51 +0000129 moddir = concat_path_file(CONFIG_DEFAULT_MODULES_DIR, uts.release);
Bernhard Reutner-Fischer6bb55cf2008-05-26 17:04:01 +0000130 }
Bernhard Reutner-Fischer634b0222008-05-28 14:20:20 +0000131 /* If no modules are given on the command-line, -a is on per default. */
Bernhard Reutner-Fischer1ea25682008-05-26 21:33:05 +0000132 option_mask32 |= *argv == NULL;
133
Bernhard Reutner-Fischer1ea25682008-05-26 21:33:05 +0000134 if (option_mask32 & ARG_b) {
Bernhard Reutner-Fischerc21d9c72008-05-28 10:35:51 +0000135 G.moddir_base_len = strlen(moddir_base);
136 if (ENABLE_FEATURE_CLEAN_UP) {
137 chp = moddir;
138 moddir = concat_path_file(moddir_base, moddir);
139 free (chp);
140 } else
141 moddir = concat_path_file(moddir_base, moddir);
Bernhard Reutner-Fischer6bb55cf2008-05-26 17:04:01 +0000142 }
Bernhard Reutner-Fischer1ea25682008-05-26 21:33:05 +0000143
144 if (!(option_mask32 & ARG_n)) { /* --dry-run */
Bernhard Reutner-Fischerb85fb692008-05-27 10:55:34 +0000145 chp = concat_path_file(moddir, CONFIG_DEFAULT_DEPMOD_FILE);
Bernhard Reutner-Fischer1ea25682008-05-26 21:33:05 +0000146 filedes = xfopen(chp, "w");
147 if (ENABLE_FEATURE_CLEAN_UP)
148 free(chp);
149 }
Bernhard Reutner-Fischerc21d9c72008-05-28 10:35:51 +0000150 ret = EXIT_SUCCESS;
Bernhard Reutner-Fischer634b0222008-05-28 14:20:20 +0000151 /* We have to do a full walk to collect all needed data. */
Bernhard Reutner-Fischer1ea25682008-05-26 21:33:05 +0000152 if (!recursive_action(moddir,
153 ACTION_RECURSE, /* flags */
154 fill_lst, /* file action */
155 NULL, /* dir action */
156 NULL, /* user data */
Bernhard Reutner-Fischer634b0222008-05-28 14:20:20 +0000157 0)) { /* depth */
158 if (ENABLE_FEATURE_CLEAN_UP)
159 ret = EXIT_FAILURE;
160 else
161 return EXIT_FAILURE;
162 }
Bernhard Reutner-Fischer55e547e2008-05-26 12:01:49 +0000163 do {
Bernhard Reutner-Fischerc21d9c72008-05-28 10:35:51 +0000164 chp = option_mask32 & ARG_a ? moddir : *argv++;
Bernhard Reutner-Fischer6bb55cf2008-05-26 17:04:01 +0000165
166 if (!recursive_action(chp,
Bernhard Reutner-Fischer55e547e2008-05-26 12:01:49 +0000167 ACTION_RECURSE, /* flags */
Bernhard Reutner-Fischer55e547e2008-05-26 12:01:49 +0000168 fileAction, /* file action */
169 NULL, /* dir action */
Bernhard Reutner-Fischer423465c2008-05-26 12:19:35 +0000170 (void*)filedes, /* user data */
Bernhard Reutner-Fischer55e547e2008-05-26 12:01:49 +0000171 0)) { /* depth */
Bernhard Reutner-Fischerc21d9c72008-05-28 10:35:51 +0000172 ret = EXIT_FAILURE;
Bernhard Reutner-Fischer55e547e2008-05-26 12:01:49 +0000173 }
Bernhard Reutner-Fischer1ea25682008-05-26 21:33:05 +0000174 } while (!(option_mask32 & ARG_a) && *argv);
Bernhard Reutner-Fischer55e547e2008-05-26 12:01:49 +0000175
Bernhard Reutner-Fischerdc5d7fe2008-05-26 13:30:41 +0000176 if (ENABLE_FEATURE_CLEAN_UP) {
Bernhard Reutner-Fischerc21d9c72008-05-28 10:35:51 +0000177 fclose_if_not_stdin(filedes);
Bernhard Reutner-Fischerdc5d7fe2008-05-26 13:30:41 +0000178 llist_free(G.lst, free);
Bernhard Reutner-Fischer1ea25682008-05-26 21:33:05 +0000179 free(moddir);
Bernhard Reutner-Fischerdc5d7fe2008-05-26 13:30:41 +0000180 }
Bernhard Reutner-Fischerc21d9c72008-05-28 10:35:51 +0000181 return ret;
Bernhard Reutner-Fischer55e547e2008-05-26 12:01:49 +0000182}