1*cc4ad7daSAndroid Build Coastguard Worker /*
2*cc4ad7daSAndroid Build Coastguard Worker * kmod-depmod - calculate modules.dep using libkmod.
3*cc4ad7daSAndroid Build Coastguard Worker *
4*cc4ad7daSAndroid Build Coastguard Worker * Copyright (C) 2011-2013 ProFUSION embedded systems
5*cc4ad7daSAndroid Build Coastguard Worker *
6*cc4ad7daSAndroid Build Coastguard Worker * This program is free software: you can redistribute it and/or modify
7*cc4ad7daSAndroid Build Coastguard Worker * it under the terms of the GNU General Public License as published by
8*cc4ad7daSAndroid Build Coastguard Worker * the Free Software Foundation, either version 2 of the License, or
9*cc4ad7daSAndroid Build Coastguard Worker * (at your option) any later version.
10*cc4ad7daSAndroid Build Coastguard Worker *
11*cc4ad7daSAndroid Build Coastguard Worker * This program is distributed in the hope that it will be useful,
12*cc4ad7daSAndroid Build Coastguard Worker * but WITHOUT ANY WARRANTY; without even the implied warranty of
13*cc4ad7daSAndroid Build Coastguard Worker * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14*cc4ad7daSAndroid Build Coastguard Worker * GNU General Public License for more details.
15*cc4ad7daSAndroid Build Coastguard Worker *
16*cc4ad7daSAndroid Build Coastguard Worker * You should have received a copy of the GNU General Public License
17*cc4ad7daSAndroid Build Coastguard Worker * along with this program. If not, see <http://www.gnu.org/licenses/>.
18*cc4ad7daSAndroid Build Coastguard Worker */
19*cc4ad7daSAndroid Build Coastguard Worker
20*cc4ad7daSAndroid Build Coastguard Worker #include <assert.h>
21*cc4ad7daSAndroid Build Coastguard Worker #include <ctype.h>
22*cc4ad7daSAndroid Build Coastguard Worker #include <dirent.h>
23*cc4ad7daSAndroid Build Coastguard Worker #include <errno.h>
24*cc4ad7daSAndroid Build Coastguard Worker #include <getopt.h>
25*cc4ad7daSAndroid Build Coastguard Worker #include <limits.h>
26*cc4ad7daSAndroid Build Coastguard Worker #include <regex.h>
27*cc4ad7daSAndroid Build Coastguard Worker #include <stdio.h>
28*cc4ad7daSAndroid Build Coastguard Worker #include <stdlib.h>
29*cc4ad7daSAndroid Build Coastguard Worker #include <string.h>
30*cc4ad7daSAndroid Build Coastguard Worker #include <unistd.h>
31*cc4ad7daSAndroid Build Coastguard Worker #include <sys/stat.h>
32*cc4ad7daSAndroid Build Coastguard Worker #include <sys/time.h>
33*cc4ad7daSAndroid Build Coastguard Worker #include <sys/utsname.h>
34*cc4ad7daSAndroid Build Coastguard Worker
35*cc4ad7daSAndroid Build Coastguard Worker #include <shared/array.h>
36*cc4ad7daSAndroid Build Coastguard Worker #include <shared/hash.h>
37*cc4ad7daSAndroid Build Coastguard Worker #include <shared/macro.h>
38*cc4ad7daSAndroid Build Coastguard Worker #include <shared/util.h>
39*cc4ad7daSAndroid Build Coastguard Worker #include <shared/scratchbuf.h>
40*cc4ad7daSAndroid Build Coastguard Worker
41*cc4ad7daSAndroid Build Coastguard Worker #include <libkmod/libkmod-internal.h>
42*cc4ad7daSAndroid Build Coastguard Worker
43*cc4ad7daSAndroid Build Coastguard Worker #undef ERR
44*cc4ad7daSAndroid Build Coastguard Worker #undef DBG
45*cc4ad7daSAndroid Build Coastguard Worker
46*cc4ad7daSAndroid Build Coastguard Worker #include "kmod.h"
47*cc4ad7daSAndroid Build Coastguard Worker
48*cc4ad7daSAndroid Build Coastguard Worker #define DEFAULT_VERBOSE LOG_WARNING
49*cc4ad7daSAndroid Build Coastguard Worker static int verbose = DEFAULT_VERBOSE;
50*cc4ad7daSAndroid Build Coastguard Worker
51*cc4ad7daSAndroid Build Coastguard Worker static const char CFG_BUILTIN_KEY[] = "built-in";
52*cc4ad7daSAndroid Build Coastguard Worker static const char CFG_EXTERNAL_KEY[] = "external";
53*cc4ad7daSAndroid Build Coastguard Worker static const char *const default_cfg_paths[] = {
54*cc4ad7daSAndroid Build Coastguard Worker SYSCONFDIR "/depmod.d",
55*cc4ad7daSAndroid Build Coastguard Worker "/run/depmod.d",
56*cc4ad7daSAndroid Build Coastguard Worker "/usr/local/lib/depmod.d",
57*cc4ad7daSAndroid Build Coastguard Worker DISTCONFDIR "/depmod.d",
58*cc4ad7daSAndroid Build Coastguard Worker "/lib/depmod.d",
59*cc4ad7daSAndroid Build Coastguard Worker NULL
60*cc4ad7daSAndroid Build Coastguard Worker };
61*cc4ad7daSAndroid Build Coastguard Worker
62*cc4ad7daSAndroid Build Coastguard Worker static const char cmdopts_s[] = "aAb:o:C:E:F:euqrvnP:wmVh";
63*cc4ad7daSAndroid Build Coastguard Worker static const struct option cmdopts[] = {
64*cc4ad7daSAndroid Build Coastguard Worker { "all", no_argument, 0, 'a' },
65*cc4ad7daSAndroid Build Coastguard Worker { "quick", no_argument, 0, 'A' },
66*cc4ad7daSAndroid Build Coastguard Worker { "basedir", required_argument, 0, 'b' },
67*cc4ad7daSAndroid Build Coastguard Worker { "outdir", required_argument, 0, 'o' },
68*cc4ad7daSAndroid Build Coastguard Worker { "config", required_argument, 0, 'C' },
69*cc4ad7daSAndroid Build Coastguard Worker { "symvers", required_argument, 0, 'E' },
70*cc4ad7daSAndroid Build Coastguard Worker { "filesyms", required_argument, 0, 'F' },
71*cc4ad7daSAndroid Build Coastguard Worker { "errsyms", no_argument, 0, 'e' },
72*cc4ad7daSAndroid Build Coastguard Worker { "unresolved-error", no_argument, 0, 'u' }, /* deprecated */
73*cc4ad7daSAndroid Build Coastguard Worker { "quiet", no_argument, 0, 'q' }, /* deprecated */
74*cc4ad7daSAndroid Build Coastguard Worker { "root", no_argument, 0, 'r' }, /* deprecated */
75*cc4ad7daSAndroid Build Coastguard Worker { "verbose", no_argument, 0, 'v' },
76*cc4ad7daSAndroid Build Coastguard Worker { "show", no_argument, 0, 'n' },
77*cc4ad7daSAndroid Build Coastguard Worker { "dry-run", no_argument, 0, 'n' },
78*cc4ad7daSAndroid Build Coastguard Worker { "symbol-prefix", required_argument, 0, 'P' },
79*cc4ad7daSAndroid Build Coastguard Worker { "warn", no_argument, 0, 'w' },
80*cc4ad7daSAndroid Build Coastguard Worker { "map", no_argument, 0, 'm' }, /* deprecated */
81*cc4ad7daSAndroid Build Coastguard Worker { "version", no_argument, 0, 'V' },
82*cc4ad7daSAndroid Build Coastguard Worker { "help", no_argument, 0, 'h' },
83*cc4ad7daSAndroid Build Coastguard Worker { }
84*cc4ad7daSAndroid Build Coastguard Worker };
85*cc4ad7daSAndroid Build Coastguard Worker
help(void)86*cc4ad7daSAndroid Build Coastguard Worker static void help(void)
87*cc4ad7daSAndroid Build Coastguard Worker {
88*cc4ad7daSAndroid Build Coastguard Worker printf("Usage:\n"
89*cc4ad7daSAndroid Build Coastguard Worker "\t%s -[aA] [options] [forced_version]\n"
90*cc4ad7daSAndroid Build Coastguard Worker "\n"
91*cc4ad7daSAndroid Build Coastguard Worker "If no arguments (except options) are given, \"depmod -a\" is assumed\n"
92*cc4ad7daSAndroid Build Coastguard Worker "\n"
93*cc4ad7daSAndroid Build Coastguard Worker "depmod will output a dependency list suitable for the modprobe utility.\n"
94*cc4ad7daSAndroid Build Coastguard Worker "\n"
95*cc4ad7daSAndroid Build Coastguard Worker "Options:\n"
96*cc4ad7daSAndroid Build Coastguard Worker "\t-a, --all Probe all modules\n"
97*cc4ad7daSAndroid Build Coastguard Worker "\t-A, --quick Only does the work if there's a new module\n"
98*cc4ad7daSAndroid Build Coastguard Worker "\t-e, --errsyms Report not supplied symbols\n"
99*cc4ad7daSAndroid Build Coastguard Worker "\t-n, --show Write the dependency file on stdout only\n"
100*cc4ad7daSAndroid Build Coastguard Worker "\t-P, --symbol-prefix Architecture symbol prefix\n"
101*cc4ad7daSAndroid Build Coastguard Worker "\t-C, --config=PATH Read configuration from PATH\n"
102*cc4ad7daSAndroid Build Coastguard Worker "\t-v, --verbose Enable verbose mode\n"
103*cc4ad7daSAndroid Build Coastguard Worker "\t-w, --warn Warn on duplicates\n"
104*cc4ad7daSAndroid Build Coastguard Worker "\t-V, --version show version\n"
105*cc4ad7daSAndroid Build Coastguard Worker "\t-h, --help show this help\n"
106*cc4ad7daSAndroid Build Coastguard Worker "\n"
107*cc4ad7daSAndroid Build Coastguard Worker "The following options are useful for people managing distributions:\n"
108*cc4ad7daSAndroid Build Coastguard Worker "\t-b, --basedir=DIR Use an image of a module tree.\n"
109*cc4ad7daSAndroid Build Coastguard Worker "\t-o, --outdir=DIR Output directory for generated files.\n"
110*cc4ad7daSAndroid Build Coastguard Worker "\t-F, --filesyms=FILE Use the file instead of the\n"
111*cc4ad7daSAndroid Build Coastguard Worker "\t current kernel symbols.\n"
112*cc4ad7daSAndroid Build Coastguard Worker "\t-E, --symvers=FILE Use Module.symvers file to check\n"
113*cc4ad7daSAndroid Build Coastguard Worker "\t symbol versions.\n",
114*cc4ad7daSAndroid Build Coastguard Worker program_invocation_short_name);
115*cc4ad7daSAndroid Build Coastguard Worker }
116*cc4ad7daSAndroid Build Coastguard Worker
117*cc4ad7daSAndroid Build Coastguard Worker _printf_format_(1, 2)
_show(const char * fmt,...)118*cc4ad7daSAndroid Build Coastguard Worker static inline void _show(const char *fmt, ...)
119*cc4ad7daSAndroid Build Coastguard Worker {
120*cc4ad7daSAndroid Build Coastguard Worker va_list args;
121*cc4ad7daSAndroid Build Coastguard Worker
122*cc4ad7daSAndroid Build Coastguard Worker if (verbose <= DEFAULT_VERBOSE)
123*cc4ad7daSAndroid Build Coastguard Worker return;
124*cc4ad7daSAndroid Build Coastguard Worker
125*cc4ad7daSAndroid Build Coastguard Worker va_start(args, fmt);
126*cc4ad7daSAndroid Build Coastguard Worker vfprintf(stdout, fmt, args);
127*cc4ad7daSAndroid Build Coastguard Worker fflush(stdout);
128*cc4ad7daSAndroid Build Coastguard Worker va_end(args);
129*cc4ad7daSAndroid Build Coastguard Worker }
130*cc4ad7daSAndroid Build Coastguard Worker #define SHOW(...) _show(__VA_ARGS__)
131*cc4ad7daSAndroid Build Coastguard Worker
132*cc4ad7daSAndroid Build Coastguard Worker
133*cc4ad7daSAndroid Build Coastguard Worker /* binary index write *************************************************/
134*cc4ad7daSAndroid Build Coastguard Worker #include <arpa/inet.h>
135*cc4ad7daSAndroid Build Coastguard Worker /* BEGIN: code from module-init-tools/index.c just modified to compile here.
136*cc4ad7daSAndroid Build Coastguard Worker *
137*cc4ad7daSAndroid Build Coastguard Worker * Original copyright:
138*cc4ad7daSAndroid Build Coastguard Worker * index.c: module index file shared functions for modprobe and depmod
139*cc4ad7daSAndroid Build Coastguard Worker * Copyright (C) 2008 Alan Jenkins <[email protected]>.
140*cc4ad7daSAndroid Build Coastguard Worker *
141*cc4ad7daSAndroid Build Coastguard Worker * These programs are free software; you can redistribute it and/or modify
142*cc4ad7daSAndroid Build Coastguard Worker * it under the terms of the GNU General Public License as published by
143*cc4ad7daSAndroid Build Coastguard Worker * the Free Software Foundation; either version 2 of the License, or
144*cc4ad7daSAndroid Build Coastguard Worker * (at your option) any later version.
145*cc4ad7daSAndroid Build Coastguard Worker *
146*cc4ad7daSAndroid Build Coastguard Worker * This program is distributed in the hope that it will be useful,
147*cc4ad7daSAndroid Build Coastguard Worker * but WITHOUT ANY WARRANTY; without even the implied warranty of
148*cc4ad7daSAndroid Build Coastguard Worker * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
149*cc4ad7daSAndroid Build Coastguard Worker * GNU General Public License for more details.
150*cc4ad7daSAndroid Build Coastguard Worker *
151*cc4ad7daSAndroid Build Coastguard Worker * You should have received a copy of the GNU General Public License
152*cc4ad7daSAndroid Build Coastguard Worker * along with these programs. If not, see <http://www.gnu.org/licenses/>.
153*cc4ad7daSAndroid Build Coastguard Worker */
154*cc4ad7daSAndroid Build Coastguard Worker
155*cc4ad7daSAndroid Build Coastguard Worker /* see documentation in libkmod/libkmod-index.c */
156*cc4ad7daSAndroid Build Coastguard Worker
157*cc4ad7daSAndroid Build Coastguard Worker #define INDEX_MAGIC 0xB007F457
158*cc4ad7daSAndroid Build Coastguard Worker #define INDEX_VERSION_MAJOR 0x0002
159*cc4ad7daSAndroid Build Coastguard Worker #define INDEX_VERSION_MINOR 0x0001
160*cc4ad7daSAndroid Build Coastguard Worker #define INDEX_VERSION ((INDEX_VERSION_MAJOR<<16)|INDEX_VERSION_MINOR)
161*cc4ad7daSAndroid Build Coastguard Worker #define INDEX_CHILDMAX 128
162*cc4ad7daSAndroid Build Coastguard Worker
163*cc4ad7daSAndroid Build Coastguard Worker struct index_value {
164*cc4ad7daSAndroid Build Coastguard Worker struct index_value *next;
165*cc4ad7daSAndroid Build Coastguard Worker unsigned int priority;
166*cc4ad7daSAndroid Build Coastguard Worker char value[0];
167*cc4ad7daSAndroid Build Coastguard Worker };
168*cc4ad7daSAndroid Build Coastguard Worker
169*cc4ad7daSAndroid Build Coastguard Worker /* In-memory index (depmod only) */
170*cc4ad7daSAndroid Build Coastguard Worker struct index_node {
171*cc4ad7daSAndroid Build Coastguard Worker char *prefix; /* path compression */
172*cc4ad7daSAndroid Build Coastguard Worker struct index_value *values;
173*cc4ad7daSAndroid Build Coastguard Worker unsigned char first; /* range of child nodes */
174*cc4ad7daSAndroid Build Coastguard Worker unsigned char last;
175*cc4ad7daSAndroid Build Coastguard Worker struct index_node *children[INDEX_CHILDMAX]; /* indexed by character */
176*cc4ad7daSAndroid Build Coastguard Worker };
177*cc4ad7daSAndroid Build Coastguard Worker
178*cc4ad7daSAndroid Build Coastguard Worker
179*cc4ad7daSAndroid Build Coastguard Worker /* Format of node offsets within index file */
180*cc4ad7daSAndroid Build Coastguard Worker enum node_offset {
181*cc4ad7daSAndroid Build Coastguard Worker INDEX_NODE_FLAGS = 0xF0000000, /* Flags in high nibble */
182*cc4ad7daSAndroid Build Coastguard Worker INDEX_NODE_PREFIX = 0x80000000,
183*cc4ad7daSAndroid Build Coastguard Worker INDEX_NODE_VALUES = 0x40000000,
184*cc4ad7daSAndroid Build Coastguard Worker INDEX_NODE_CHILDS = 0x20000000,
185*cc4ad7daSAndroid Build Coastguard Worker
186*cc4ad7daSAndroid Build Coastguard Worker INDEX_NODE_MASK = 0x0FFFFFFF, /* Offset value */
187*cc4ad7daSAndroid Build Coastguard Worker };
188*cc4ad7daSAndroid Build Coastguard Worker
index_create(void)189*cc4ad7daSAndroid Build Coastguard Worker static struct index_node *index_create(void)
190*cc4ad7daSAndroid Build Coastguard Worker {
191*cc4ad7daSAndroid Build Coastguard Worker struct index_node *node;
192*cc4ad7daSAndroid Build Coastguard Worker
193*cc4ad7daSAndroid Build Coastguard Worker node = NOFAIL(calloc(1, sizeof(struct index_node)));
194*cc4ad7daSAndroid Build Coastguard Worker node->prefix = NOFAIL(strdup(""));
195*cc4ad7daSAndroid Build Coastguard Worker node->first = INDEX_CHILDMAX;
196*cc4ad7daSAndroid Build Coastguard Worker
197*cc4ad7daSAndroid Build Coastguard Worker return node;
198*cc4ad7daSAndroid Build Coastguard Worker }
199*cc4ad7daSAndroid Build Coastguard Worker
index_values_free(struct index_value * values)200*cc4ad7daSAndroid Build Coastguard Worker static void index_values_free(struct index_value *values)
201*cc4ad7daSAndroid Build Coastguard Worker {
202*cc4ad7daSAndroid Build Coastguard Worker while (values) {
203*cc4ad7daSAndroid Build Coastguard Worker struct index_value *value = values;
204*cc4ad7daSAndroid Build Coastguard Worker
205*cc4ad7daSAndroid Build Coastguard Worker values = value->next;
206*cc4ad7daSAndroid Build Coastguard Worker free(value);
207*cc4ad7daSAndroid Build Coastguard Worker }
208*cc4ad7daSAndroid Build Coastguard Worker }
209*cc4ad7daSAndroid Build Coastguard Worker
index_destroy(struct index_node * node)210*cc4ad7daSAndroid Build Coastguard Worker static void index_destroy(struct index_node *node)
211*cc4ad7daSAndroid Build Coastguard Worker {
212*cc4ad7daSAndroid Build Coastguard Worker int c;
213*cc4ad7daSAndroid Build Coastguard Worker
214*cc4ad7daSAndroid Build Coastguard Worker for (c = node->first; c <= node->last; c++) {
215*cc4ad7daSAndroid Build Coastguard Worker struct index_node *child = node->children[c];
216*cc4ad7daSAndroid Build Coastguard Worker
217*cc4ad7daSAndroid Build Coastguard Worker if (child)
218*cc4ad7daSAndroid Build Coastguard Worker index_destroy(child);
219*cc4ad7daSAndroid Build Coastguard Worker }
220*cc4ad7daSAndroid Build Coastguard Worker index_values_free(node->values);
221*cc4ad7daSAndroid Build Coastguard Worker free(node->prefix);
222*cc4ad7daSAndroid Build Coastguard Worker free(node);
223*cc4ad7daSAndroid Build Coastguard Worker }
224*cc4ad7daSAndroid Build Coastguard Worker
index__checkstring(const char * str)225*cc4ad7daSAndroid Build Coastguard Worker static void index__checkstring(const char *str)
226*cc4ad7daSAndroid Build Coastguard Worker {
227*cc4ad7daSAndroid Build Coastguard Worker int i;
228*cc4ad7daSAndroid Build Coastguard Worker
229*cc4ad7daSAndroid Build Coastguard Worker for (i = 0; str[i]; i++) {
230*cc4ad7daSAndroid Build Coastguard Worker int ch = str[i];
231*cc4ad7daSAndroid Build Coastguard Worker
232*cc4ad7daSAndroid Build Coastguard Worker if (ch >= INDEX_CHILDMAX)
233*cc4ad7daSAndroid Build Coastguard Worker CRIT("Module index: bad character '%c'=0x%x - only 7-bit ASCII is supported:"
234*cc4ad7daSAndroid Build Coastguard Worker "\n%s\n", (char) ch, (int) ch, str);
235*cc4ad7daSAndroid Build Coastguard Worker }
236*cc4ad7daSAndroid Build Coastguard Worker }
237*cc4ad7daSAndroid Build Coastguard Worker
index_add_value(struct index_value ** values,const char * value,unsigned int priority)238*cc4ad7daSAndroid Build Coastguard Worker static int index_add_value(struct index_value **values,
239*cc4ad7daSAndroid Build Coastguard Worker const char *value, unsigned int priority)
240*cc4ad7daSAndroid Build Coastguard Worker {
241*cc4ad7daSAndroid Build Coastguard Worker struct index_value *v;
242*cc4ad7daSAndroid Build Coastguard Worker int duplicate = 0;
243*cc4ad7daSAndroid Build Coastguard Worker int len;
244*cc4ad7daSAndroid Build Coastguard Worker
245*cc4ad7daSAndroid Build Coastguard Worker /* report the presence of duplicate values */
246*cc4ad7daSAndroid Build Coastguard Worker for (v = *values; v; v = v->next) {
247*cc4ad7daSAndroid Build Coastguard Worker if (streq(v->value, value))
248*cc4ad7daSAndroid Build Coastguard Worker duplicate = 1;
249*cc4ad7daSAndroid Build Coastguard Worker }
250*cc4ad7daSAndroid Build Coastguard Worker
251*cc4ad7daSAndroid Build Coastguard Worker /* find position to insert value */
252*cc4ad7daSAndroid Build Coastguard Worker while (*values && (*values)->priority < priority)
253*cc4ad7daSAndroid Build Coastguard Worker values = &(*values)->next;
254*cc4ad7daSAndroid Build Coastguard Worker
255*cc4ad7daSAndroid Build Coastguard Worker len = strlen(value);
256*cc4ad7daSAndroid Build Coastguard Worker v = NOFAIL(calloc(1, sizeof(struct index_value) + len + 1));
257*cc4ad7daSAndroid Build Coastguard Worker v->next = *values;
258*cc4ad7daSAndroid Build Coastguard Worker v->priority = priority;
259*cc4ad7daSAndroid Build Coastguard Worker memcpy(v->value, value, len + 1);
260*cc4ad7daSAndroid Build Coastguard Worker *values = v;
261*cc4ad7daSAndroid Build Coastguard Worker
262*cc4ad7daSAndroid Build Coastguard Worker return duplicate;
263*cc4ad7daSAndroid Build Coastguard Worker }
264*cc4ad7daSAndroid Build Coastguard Worker
index_insert(struct index_node * node,const char * key,const char * value,unsigned int priority)265*cc4ad7daSAndroid Build Coastguard Worker static int index_insert(struct index_node *node, const char *key,
266*cc4ad7daSAndroid Build Coastguard Worker const char *value, unsigned int priority)
267*cc4ad7daSAndroid Build Coastguard Worker {
268*cc4ad7daSAndroid Build Coastguard Worker int i = 0; /* index within str */
269*cc4ad7daSAndroid Build Coastguard Worker int ch;
270*cc4ad7daSAndroid Build Coastguard Worker
271*cc4ad7daSAndroid Build Coastguard Worker index__checkstring(key);
272*cc4ad7daSAndroid Build Coastguard Worker index__checkstring(value);
273*cc4ad7daSAndroid Build Coastguard Worker
274*cc4ad7daSAndroid Build Coastguard Worker while(1) {
275*cc4ad7daSAndroid Build Coastguard Worker int j; /* index within node->prefix */
276*cc4ad7daSAndroid Build Coastguard Worker
277*cc4ad7daSAndroid Build Coastguard Worker /* Ensure node->prefix is a prefix of &str[i].
278*cc4ad7daSAndroid Build Coastguard Worker If it is not already, then we must split node. */
279*cc4ad7daSAndroid Build Coastguard Worker for (j = 0; node->prefix[j]; j++) {
280*cc4ad7daSAndroid Build Coastguard Worker ch = node->prefix[j];
281*cc4ad7daSAndroid Build Coastguard Worker
282*cc4ad7daSAndroid Build Coastguard Worker if (ch != key[i+j]) {
283*cc4ad7daSAndroid Build Coastguard Worker char *prefix = node->prefix;
284*cc4ad7daSAndroid Build Coastguard Worker struct index_node *n;
285*cc4ad7daSAndroid Build Coastguard Worker
286*cc4ad7daSAndroid Build Coastguard Worker /* New child is copy of node with prefix[j+1..N] */
287*cc4ad7daSAndroid Build Coastguard Worker n = NOFAIL(calloc(1, sizeof(struct index_node)));
288*cc4ad7daSAndroid Build Coastguard Worker memcpy(n, node, sizeof(struct index_node));
289*cc4ad7daSAndroid Build Coastguard Worker n->prefix = NOFAIL(strdup(&prefix[j+1]));
290*cc4ad7daSAndroid Build Coastguard Worker
291*cc4ad7daSAndroid Build Coastguard Worker /* Parent has prefix[0..j], child at prefix[j] */
292*cc4ad7daSAndroid Build Coastguard Worker memset(node, 0, sizeof(struct index_node));
293*cc4ad7daSAndroid Build Coastguard Worker prefix[j] = '\0';
294*cc4ad7daSAndroid Build Coastguard Worker node->prefix = prefix;
295*cc4ad7daSAndroid Build Coastguard Worker node->first = ch;
296*cc4ad7daSAndroid Build Coastguard Worker node->last = ch;
297*cc4ad7daSAndroid Build Coastguard Worker node->children[ch] = n;
298*cc4ad7daSAndroid Build Coastguard Worker
299*cc4ad7daSAndroid Build Coastguard Worker break;
300*cc4ad7daSAndroid Build Coastguard Worker }
301*cc4ad7daSAndroid Build Coastguard Worker }
302*cc4ad7daSAndroid Build Coastguard Worker /* j is now length of node->prefix */
303*cc4ad7daSAndroid Build Coastguard Worker i += j;
304*cc4ad7daSAndroid Build Coastguard Worker
305*cc4ad7daSAndroid Build Coastguard Worker ch = key[i];
306*cc4ad7daSAndroid Build Coastguard Worker if(ch == '\0')
307*cc4ad7daSAndroid Build Coastguard Worker return index_add_value(&node->values, value, priority);
308*cc4ad7daSAndroid Build Coastguard Worker
309*cc4ad7daSAndroid Build Coastguard Worker if (!node->children[ch]) {
310*cc4ad7daSAndroid Build Coastguard Worker struct index_node *child;
311*cc4ad7daSAndroid Build Coastguard Worker
312*cc4ad7daSAndroid Build Coastguard Worker if (ch < node->first)
313*cc4ad7daSAndroid Build Coastguard Worker node->first = ch;
314*cc4ad7daSAndroid Build Coastguard Worker if (ch > node->last)
315*cc4ad7daSAndroid Build Coastguard Worker node->last = ch;
316*cc4ad7daSAndroid Build Coastguard Worker node->children[ch] = NOFAIL(calloc(1, sizeof(struct index_node)));
317*cc4ad7daSAndroid Build Coastguard Worker
318*cc4ad7daSAndroid Build Coastguard Worker child = node->children[ch];
319*cc4ad7daSAndroid Build Coastguard Worker child->prefix = NOFAIL(strdup(&key[i+1]));
320*cc4ad7daSAndroid Build Coastguard Worker child->first = INDEX_CHILDMAX;
321*cc4ad7daSAndroid Build Coastguard Worker index_add_value(&child->values, value, priority);
322*cc4ad7daSAndroid Build Coastguard Worker
323*cc4ad7daSAndroid Build Coastguard Worker return 0;
324*cc4ad7daSAndroid Build Coastguard Worker }
325*cc4ad7daSAndroid Build Coastguard Worker
326*cc4ad7daSAndroid Build Coastguard Worker /* Descend into child node and continue */
327*cc4ad7daSAndroid Build Coastguard Worker node = node->children[ch];
328*cc4ad7daSAndroid Build Coastguard Worker i++;
329*cc4ad7daSAndroid Build Coastguard Worker }
330*cc4ad7daSAndroid Build Coastguard Worker }
331*cc4ad7daSAndroid Build Coastguard Worker
index__haschildren(const struct index_node * node)332*cc4ad7daSAndroid Build Coastguard Worker static int index__haschildren(const struct index_node *node)
333*cc4ad7daSAndroid Build Coastguard Worker {
334*cc4ad7daSAndroid Build Coastguard Worker return node->first < INDEX_CHILDMAX;
335*cc4ad7daSAndroid Build Coastguard Worker }
336*cc4ad7daSAndroid Build Coastguard Worker
337*cc4ad7daSAndroid Build Coastguard Worker /* Recursive post-order traversal
338*cc4ad7daSAndroid Build Coastguard Worker
339*cc4ad7daSAndroid Build Coastguard Worker Pre-order would make for better read-side buffering / readahead / caching.
340*cc4ad7daSAndroid Build Coastguard Worker (post-order means you go backwards in the file as you descend the tree).
341*cc4ad7daSAndroid Build Coastguard Worker However, index reading is already fast enough.
342*cc4ad7daSAndroid Build Coastguard Worker Pre-order is simpler for writing, and depmod is already slow.
343*cc4ad7daSAndroid Build Coastguard Worker */
index_write__node(const struct index_node * node,FILE * out)344*cc4ad7daSAndroid Build Coastguard Worker static uint32_t index_write__node(const struct index_node *node, FILE *out)
345*cc4ad7daSAndroid Build Coastguard Worker {
346*cc4ad7daSAndroid Build Coastguard Worker uint32_t *child_offs = NULL;
347*cc4ad7daSAndroid Build Coastguard Worker int child_count = 0;
348*cc4ad7daSAndroid Build Coastguard Worker long offset;
349*cc4ad7daSAndroid Build Coastguard Worker
350*cc4ad7daSAndroid Build Coastguard Worker if (!node)
351*cc4ad7daSAndroid Build Coastguard Worker return 0;
352*cc4ad7daSAndroid Build Coastguard Worker
353*cc4ad7daSAndroid Build Coastguard Worker /* Write children and save their offsets */
354*cc4ad7daSAndroid Build Coastguard Worker if (index__haschildren(node)) {
355*cc4ad7daSAndroid Build Coastguard Worker const struct index_node *child;
356*cc4ad7daSAndroid Build Coastguard Worker int i;
357*cc4ad7daSAndroid Build Coastguard Worker
358*cc4ad7daSAndroid Build Coastguard Worker child_count = node->last - node->first + 1;
359*cc4ad7daSAndroid Build Coastguard Worker child_offs = NOFAIL(malloc(child_count * sizeof(uint32_t)));
360*cc4ad7daSAndroid Build Coastguard Worker
361*cc4ad7daSAndroid Build Coastguard Worker for (i = 0; i < child_count; i++) {
362*cc4ad7daSAndroid Build Coastguard Worker child = node->children[node->first + i];
363*cc4ad7daSAndroid Build Coastguard Worker child_offs[i] = htonl(index_write__node(child, out));
364*cc4ad7daSAndroid Build Coastguard Worker }
365*cc4ad7daSAndroid Build Coastguard Worker }
366*cc4ad7daSAndroid Build Coastguard Worker
367*cc4ad7daSAndroid Build Coastguard Worker /* Now write this node */
368*cc4ad7daSAndroid Build Coastguard Worker offset = ftell(out);
369*cc4ad7daSAndroid Build Coastguard Worker
370*cc4ad7daSAndroid Build Coastguard Worker if (node->prefix[0]) {
371*cc4ad7daSAndroid Build Coastguard Worker fputs(node->prefix, out);
372*cc4ad7daSAndroid Build Coastguard Worker fputc('\0', out);
373*cc4ad7daSAndroid Build Coastguard Worker offset |= INDEX_NODE_PREFIX;
374*cc4ad7daSAndroid Build Coastguard Worker }
375*cc4ad7daSAndroid Build Coastguard Worker
376*cc4ad7daSAndroid Build Coastguard Worker if (child_count) {
377*cc4ad7daSAndroid Build Coastguard Worker fputc(node->first, out);
378*cc4ad7daSAndroid Build Coastguard Worker fputc(node->last, out);
379*cc4ad7daSAndroid Build Coastguard Worker fwrite(child_offs, sizeof(uint32_t), child_count, out);
380*cc4ad7daSAndroid Build Coastguard Worker offset |= INDEX_NODE_CHILDS;
381*cc4ad7daSAndroid Build Coastguard Worker }
382*cc4ad7daSAndroid Build Coastguard Worker
383*cc4ad7daSAndroid Build Coastguard Worker free(child_offs);
384*cc4ad7daSAndroid Build Coastguard Worker
385*cc4ad7daSAndroid Build Coastguard Worker if (node->values) {
386*cc4ad7daSAndroid Build Coastguard Worker const struct index_value *v;
387*cc4ad7daSAndroid Build Coastguard Worker unsigned int value_count;
388*cc4ad7daSAndroid Build Coastguard Worker uint32_t u;
389*cc4ad7daSAndroid Build Coastguard Worker
390*cc4ad7daSAndroid Build Coastguard Worker value_count = 0;
391*cc4ad7daSAndroid Build Coastguard Worker for (v = node->values; v != NULL; v = v->next)
392*cc4ad7daSAndroid Build Coastguard Worker value_count++;
393*cc4ad7daSAndroid Build Coastguard Worker u = htonl(value_count);
394*cc4ad7daSAndroid Build Coastguard Worker fwrite(&u, sizeof(u), 1, out);
395*cc4ad7daSAndroid Build Coastguard Worker
396*cc4ad7daSAndroid Build Coastguard Worker for (v = node->values; v != NULL; v = v->next) {
397*cc4ad7daSAndroid Build Coastguard Worker u = htonl(v->priority);
398*cc4ad7daSAndroid Build Coastguard Worker fwrite(&u, sizeof(u), 1, out);
399*cc4ad7daSAndroid Build Coastguard Worker fputs(v->value, out);
400*cc4ad7daSAndroid Build Coastguard Worker fputc('\0', out);
401*cc4ad7daSAndroid Build Coastguard Worker }
402*cc4ad7daSAndroid Build Coastguard Worker offset |= INDEX_NODE_VALUES;
403*cc4ad7daSAndroid Build Coastguard Worker }
404*cc4ad7daSAndroid Build Coastguard Worker
405*cc4ad7daSAndroid Build Coastguard Worker return offset;
406*cc4ad7daSAndroid Build Coastguard Worker }
407*cc4ad7daSAndroid Build Coastguard Worker
index_write(const struct index_node * node,FILE * out)408*cc4ad7daSAndroid Build Coastguard Worker static void index_write(const struct index_node *node, FILE *out)
409*cc4ad7daSAndroid Build Coastguard Worker {
410*cc4ad7daSAndroid Build Coastguard Worker long initial_offset, final_offset;
411*cc4ad7daSAndroid Build Coastguard Worker uint32_t u;
412*cc4ad7daSAndroid Build Coastguard Worker
413*cc4ad7daSAndroid Build Coastguard Worker u = htonl(INDEX_MAGIC);
414*cc4ad7daSAndroid Build Coastguard Worker fwrite(&u, sizeof(u), 1, out);
415*cc4ad7daSAndroid Build Coastguard Worker u = htonl(INDEX_VERSION);
416*cc4ad7daSAndroid Build Coastguard Worker fwrite(&u, sizeof(u), 1, out);
417*cc4ad7daSAndroid Build Coastguard Worker
418*cc4ad7daSAndroid Build Coastguard Worker /* Second word is reserved for the offset of the root node */
419*cc4ad7daSAndroid Build Coastguard Worker initial_offset = ftell(out);
420*cc4ad7daSAndroid Build Coastguard Worker assert(initial_offset >= 0);
421*cc4ad7daSAndroid Build Coastguard Worker u = 0;
422*cc4ad7daSAndroid Build Coastguard Worker fwrite(&u, sizeof(uint32_t), 1, out);
423*cc4ad7daSAndroid Build Coastguard Worker
424*cc4ad7daSAndroid Build Coastguard Worker /* Dump trie */
425*cc4ad7daSAndroid Build Coastguard Worker u = htonl(index_write__node(node, out));
426*cc4ad7daSAndroid Build Coastguard Worker
427*cc4ad7daSAndroid Build Coastguard Worker /* Update first word */
428*cc4ad7daSAndroid Build Coastguard Worker final_offset = ftell(out);
429*cc4ad7daSAndroid Build Coastguard Worker assert(final_offset >= 0);
430*cc4ad7daSAndroid Build Coastguard Worker (void)fseek(out, initial_offset, SEEK_SET);
431*cc4ad7daSAndroid Build Coastguard Worker fwrite(&u, sizeof(uint32_t), 1, out);
432*cc4ad7daSAndroid Build Coastguard Worker (void)fseek(out, final_offset, SEEK_SET);
433*cc4ad7daSAndroid Build Coastguard Worker }
434*cc4ad7daSAndroid Build Coastguard Worker
435*cc4ad7daSAndroid Build Coastguard Worker /* END: code from module-init-tools/index.c just modified to compile here.
436*cc4ad7daSAndroid Build Coastguard Worker */
437*cc4ad7daSAndroid Build Coastguard Worker
438*cc4ad7daSAndroid Build Coastguard Worker /* configuration parsing **********************************************/
439*cc4ad7daSAndroid Build Coastguard Worker struct cfg_override {
440*cc4ad7daSAndroid Build Coastguard Worker struct cfg_override *next;
441*cc4ad7daSAndroid Build Coastguard Worker size_t len;
442*cc4ad7daSAndroid Build Coastguard Worker char path[];
443*cc4ad7daSAndroid Build Coastguard Worker };
444*cc4ad7daSAndroid Build Coastguard Worker
445*cc4ad7daSAndroid Build Coastguard Worker enum search_type {
446*cc4ad7daSAndroid Build Coastguard Worker SEARCH_PATH,
447*cc4ad7daSAndroid Build Coastguard Worker SEARCH_BUILTIN,
448*cc4ad7daSAndroid Build Coastguard Worker SEARCH_EXTERNAL
449*cc4ad7daSAndroid Build Coastguard Worker };
450*cc4ad7daSAndroid Build Coastguard Worker
451*cc4ad7daSAndroid Build Coastguard Worker struct cfg_search {
452*cc4ad7daSAndroid Build Coastguard Worker struct cfg_search *next;
453*cc4ad7daSAndroid Build Coastguard Worker enum search_type type;
454*cc4ad7daSAndroid Build Coastguard Worker size_t len;
455*cc4ad7daSAndroid Build Coastguard Worker char path[];
456*cc4ad7daSAndroid Build Coastguard Worker };
457*cc4ad7daSAndroid Build Coastguard Worker
458*cc4ad7daSAndroid Build Coastguard Worker struct cfg_external {
459*cc4ad7daSAndroid Build Coastguard Worker struct cfg_external *next;
460*cc4ad7daSAndroid Build Coastguard Worker size_t len;
461*cc4ad7daSAndroid Build Coastguard Worker char path[];
462*cc4ad7daSAndroid Build Coastguard Worker };
463*cc4ad7daSAndroid Build Coastguard Worker
464*cc4ad7daSAndroid Build Coastguard Worker struct cfg_exclude {
465*cc4ad7daSAndroid Build Coastguard Worker struct cfg_exclude *next;
466*cc4ad7daSAndroid Build Coastguard Worker char exclude_dir[];
467*cc4ad7daSAndroid Build Coastguard Worker };
468*cc4ad7daSAndroid Build Coastguard Worker
469*cc4ad7daSAndroid Build Coastguard Worker struct cfg {
470*cc4ad7daSAndroid Build Coastguard Worker const char *kversion;
471*cc4ad7daSAndroid Build Coastguard Worker char dirname[PATH_MAX];
472*cc4ad7daSAndroid Build Coastguard Worker size_t dirnamelen;
473*cc4ad7daSAndroid Build Coastguard Worker char outdirname[PATH_MAX];
474*cc4ad7daSAndroid Build Coastguard Worker size_t outdirnamelen;
475*cc4ad7daSAndroid Build Coastguard Worker char sym_prefix;
476*cc4ad7daSAndroid Build Coastguard Worker uint8_t check_symvers;
477*cc4ad7daSAndroid Build Coastguard Worker uint8_t print_unknown;
478*cc4ad7daSAndroid Build Coastguard Worker uint8_t warn_dups;
479*cc4ad7daSAndroid Build Coastguard Worker struct cfg_override *overrides;
480*cc4ad7daSAndroid Build Coastguard Worker struct cfg_search *searches;
481*cc4ad7daSAndroid Build Coastguard Worker struct cfg_external *externals;
482*cc4ad7daSAndroid Build Coastguard Worker struct cfg_exclude *excludes;
483*cc4ad7daSAndroid Build Coastguard Worker };
484*cc4ad7daSAndroid Build Coastguard Worker
cfg_define_search_type(const char * path)485*cc4ad7daSAndroid Build Coastguard Worker static enum search_type cfg_define_search_type(const char *path)
486*cc4ad7daSAndroid Build Coastguard Worker {
487*cc4ad7daSAndroid Build Coastguard Worker if (streq(path, CFG_BUILTIN_KEY))
488*cc4ad7daSAndroid Build Coastguard Worker return SEARCH_BUILTIN;
489*cc4ad7daSAndroid Build Coastguard Worker if (streq(path, CFG_EXTERNAL_KEY))
490*cc4ad7daSAndroid Build Coastguard Worker return SEARCH_EXTERNAL;
491*cc4ad7daSAndroid Build Coastguard Worker return SEARCH_PATH;
492*cc4ad7daSAndroid Build Coastguard Worker }
493*cc4ad7daSAndroid Build Coastguard Worker
cfg_search_add(struct cfg * cfg,const char * path)494*cc4ad7daSAndroid Build Coastguard Worker static int cfg_search_add(struct cfg *cfg, const char *path)
495*cc4ad7daSAndroid Build Coastguard Worker {
496*cc4ad7daSAndroid Build Coastguard Worker struct cfg_search *s;
497*cc4ad7daSAndroid Build Coastguard Worker size_t len;
498*cc4ad7daSAndroid Build Coastguard Worker enum search_type type;
499*cc4ad7daSAndroid Build Coastguard Worker
500*cc4ad7daSAndroid Build Coastguard Worker type = cfg_define_search_type(path);
501*cc4ad7daSAndroid Build Coastguard Worker
502*cc4ad7daSAndroid Build Coastguard Worker if (type != SEARCH_PATH)
503*cc4ad7daSAndroid Build Coastguard Worker len = 0;
504*cc4ad7daSAndroid Build Coastguard Worker else
505*cc4ad7daSAndroid Build Coastguard Worker len = strlen(path) + 1;
506*cc4ad7daSAndroid Build Coastguard Worker
507*cc4ad7daSAndroid Build Coastguard Worker s = malloc(sizeof(struct cfg_search) + len);
508*cc4ad7daSAndroid Build Coastguard Worker if (s == NULL) {
509*cc4ad7daSAndroid Build Coastguard Worker ERR("search add: out of memory\n");
510*cc4ad7daSAndroid Build Coastguard Worker return -ENOMEM;
511*cc4ad7daSAndroid Build Coastguard Worker }
512*cc4ad7daSAndroid Build Coastguard Worker s->type = type;
513*cc4ad7daSAndroid Build Coastguard Worker if (type != SEARCH_PATH)
514*cc4ad7daSAndroid Build Coastguard Worker s->len = 0;
515*cc4ad7daSAndroid Build Coastguard Worker else {
516*cc4ad7daSAndroid Build Coastguard Worker s->len = len - 1;
517*cc4ad7daSAndroid Build Coastguard Worker memcpy(s->path, path, len);
518*cc4ad7daSAndroid Build Coastguard Worker }
519*cc4ad7daSAndroid Build Coastguard Worker
520*cc4ad7daSAndroid Build Coastguard Worker DBG("search add: %s, search type=%hhu\n", path, type);
521*cc4ad7daSAndroid Build Coastguard Worker
522*cc4ad7daSAndroid Build Coastguard Worker s->next = cfg->searches;
523*cc4ad7daSAndroid Build Coastguard Worker cfg->searches = s;
524*cc4ad7daSAndroid Build Coastguard Worker return 0;
525*cc4ad7daSAndroid Build Coastguard Worker }
526*cc4ad7daSAndroid Build Coastguard Worker
cfg_search_free(struct cfg_search * s)527*cc4ad7daSAndroid Build Coastguard Worker static void cfg_search_free(struct cfg_search *s)
528*cc4ad7daSAndroid Build Coastguard Worker {
529*cc4ad7daSAndroid Build Coastguard Worker free(s);
530*cc4ad7daSAndroid Build Coastguard Worker }
531*cc4ad7daSAndroid Build Coastguard Worker
cfg_override_add(struct cfg * cfg,const char * modname,const char * subdir)532*cc4ad7daSAndroid Build Coastguard Worker static int cfg_override_add(struct cfg *cfg, const char *modname, const char *subdir)
533*cc4ad7daSAndroid Build Coastguard Worker {
534*cc4ad7daSAndroid Build Coastguard Worker struct cfg_override *o;
535*cc4ad7daSAndroid Build Coastguard Worker size_t modnamelen = strlen(modname);
536*cc4ad7daSAndroid Build Coastguard Worker size_t subdirlen = strlen(subdir);
537*cc4ad7daSAndroid Build Coastguard Worker size_t i;
538*cc4ad7daSAndroid Build Coastguard Worker
539*cc4ad7daSAndroid Build Coastguard Worker o = malloc(sizeof(struct cfg_override) + subdirlen + 1
540*cc4ad7daSAndroid Build Coastguard Worker + modnamelen + 1);
541*cc4ad7daSAndroid Build Coastguard Worker if (o == NULL) {
542*cc4ad7daSAndroid Build Coastguard Worker ERR("override add: out of memory\n");
543*cc4ad7daSAndroid Build Coastguard Worker return -ENOMEM;
544*cc4ad7daSAndroid Build Coastguard Worker }
545*cc4ad7daSAndroid Build Coastguard Worker memcpy(o->path, subdir, subdirlen);
546*cc4ad7daSAndroid Build Coastguard Worker i = subdirlen;
547*cc4ad7daSAndroid Build Coastguard Worker o->path[i] = '/';
548*cc4ad7daSAndroid Build Coastguard Worker i++;
549*cc4ad7daSAndroid Build Coastguard Worker
550*cc4ad7daSAndroid Build Coastguard Worker memcpy(o->path + i, modname, modnamelen);
551*cc4ad7daSAndroid Build Coastguard Worker i += modnamelen;
552*cc4ad7daSAndroid Build Coastguard Worker o->path[i] = '\0'; /* no extension, so we can match .ko/.ko.gz */
553*cc4ad7daSAndroid Build Coastguard Worker
554*cc4ad7daSAndroid Build Coastguard Worker o->len = i;
555*cc4ad7daSAndroid Build Coastguard Worker
556*cc4ad7daSAndroid Build Coastguard Worker DBG("override add: %s\n", o->path);
557*cc4ad7daSAndroid Build Coastguard Worker
558*cc4ad7daSAndroid Build Coastguard Worker o->next = cfg->overrides;
559*cc4ad7daSAndroid Build Coastguard Worker cfg->overrides = o;
560*cc4ad7daSAndroid Build Coastguard Worker return 0;
561*cc4ad7daSAndroid Build Coastguard Worker }
562*cc4ad7daSAndroid Build Coastguard Worker
cfg_override_free(struct cfg_override * o)563*cc4ad7daSAndroid Build Coastguard Worker static void cfg_override_free(struct cfg_override *o)
564*cc4ad7daSAndroid Build Coastguard Worker {
565*cc4ad7daSAndroid Build Coastguard Worker free(o);
566*cc4ad7daSAndroid Build Coastguard Worker }
567*cc4ad7daSAndroid Build Coastguard Worker
cfg_external_add(struct cfg * cfg,const char * path)568*cc4ad7daSAndroid Build Coastguard Worker static int cfg_external_add(struct cfg *cfg, const char *path)
569*cc4ad7daSAndroid Build Coastguard Worker {
570*cc4ad7daSAndroid Build Coastguard Worker struct cfg_external *ext;
571*cc4ad7daSAndroid Build Coastguard Worker size_t len = strlen(path);
572*cc4ad7daSAndroid Build Coastguard Worker
573*cc4ad7daSAndroid Build Coastguard Worker ext = malloc(sizeof(struct cfg_external) + len + 1);
574*cc4ad7daSAndroid Build Coastguard Worker if (ext == NULL) {
575*cc4ad7daSAndroid Build Coastguard Worker ERR("external add: out of memory\n");
576*cc4ad7daSAndroid Build Coastguard Worker return -ENOMEM;
577*cc4ad7daSAndroid Build Coastguard Worker }
578*cc4ad7daSAndroid Build Coastguard Worker
579*cc4ad7daSAndroid Build Coastguard Worker strcpy(ext->path, path);
580*cc4ad7daSAndroid Build Coastguard Worker ext->len = len;
581*cc4ad7daSAndroid Build Coastguard Worker
582*cc4ad7daSAndroid Build Coastguard Worker DBG("external add: %s\n", ext->path);
583*cc4ad7daSAndroid Build Coastguard Worker
584*cc4ad7daSAndroid Build Coastguard Worker ext->next = cfg->externals;
585*cc4ad7daSAndroid Build Coastguard Worker cfg->externals = ext;
586*cc4ad7daSAndroid Build Coastguard Worker return 0;
587*cc4ad7daSAndroid Build Coastguard Worker }
588*cc4ad7daSAndroid Build Coastguard Worker
cfg_external_free(struct cfg_external * ext)589*cc4ad7daSAndroid Build Coastguard Worker static void cfg_external_free(struct cfg_external *ext)
590*cc4ad7daSAndroid Build Coastguard Worker {
591*cc4ad7daSAndroid Build Coastguard Worker free(ext);
592*cc4ad7daSAndroid Build Coastguard Worker }
593*cc4ad7daSAndroid Build Coastguard Worker
cfg_exclude_add(struct cfg * cfg,const char * path)594*cc4ad7daSAndroid Build Coastguard Worker static int cfg_exclude_add(struct cfg *cfg, const char *path)
595*cc4ad7daSAndroid Build Coastguard Worker {
596*cc4ad7daSAndroid Build Coastguard Worker struct cfg_exclude *exc;
597*cc4ad7daSAndroid Build Coastguard Worker size_t len = strlen(path);
598*cc4ad7daSAndroid Build Coastguard Worker
599*cc4ad7daSAndroid Build Coastguard Worker exc = malloc(sizeof(struct cfg_exclude) + len + 1);
600*cc4ad7daSAndroid Build Coastguard Worker if (exc == NULL) {
601*cc4ad7daSAndroid Build Coastguard Worker ERR("exclude add: out of memory\n");
602*cc4ad7daSAndroid Build Coastguard Worker return -ENOMEM;
603*cc4ad7daSAndroid Build Coastguard Worker }
604*cc4ad7daSAndroid Build Coastguard Worker memcpy(exc->exclude_dir, path, len + 1);
605*cc4ad7daSAndroid Build Coastguard Worker
606*cc4ad7daSAndroid Build Coastguard Worker DBG("exclude add: %s\n", path);
607*cc4ad7daSAndroid Build Coastguard Worker
608*cc4ad7daSAndroid Build Coastguard Worker exc->next = cfg->excludes;
609*cc4ad7daSAndroid Build Coastguard Worker cfg->excludes = exc;
610*cc4ad7daSAndroid Build Coastguard Worker return 0;
611*cc4ad7daSAndroid Build Coastguard Worker }
612*cc4ad7daSAndroid Build Coastguard Worker
cfg_exclude_free(struct cfg_exclude * exc)613*cc4ad7daSAndroid Build Coastguard Worker static void cfg_exclude_free(struct cfg_exclude *exc)
614*cc4ad7daSAndroid Build Coastguard Worker {
615*cc4ad7daSAndroid Build Coastguard Worker free(exc);
616*cc4ad7daSAndroid Build Coastguard Worker }
617*cc4ad7daSAndroid Build Coastguard Worker
cfg_kernel_matches(const struct cfg * cfg,const char * pattern)618*cc4ad7daSAndroid Build Coastguard Worker static int cfg_kernel_matches(const struct cfg *cfg, const char *pattern)
619*cc4ad7daSAndroid Build Coastguard Worker {
620*cc4ad7daSAndroid Build Coastguard Worker regex_t re;
621*cc4ad7daSAndroid Build Coastguard Worker int status;
622*cc4ad7daSAndroid Build Coastguard Worker
623*cc4ad7daSAndroid Build Coastguard Worker /* old style */
624*cc4ad7daSAndroid Build Coastguard Worker if (streq(pattern, "*"))
625*cc4ad7daSAndroid Build Coastguard Worker return 1;
626*cc4ad7daSAndroid Build Coastguard Worker
627*cc4ad7daSAndroid Build Coastguard Worker if (regcomp(&re, pattern, REG_EXTENDED|REG_NOSUB) != 0)
628*cc4ad7daSAndroid Build Coastguard Worker return 0;
629*cc4ad7daSAndroid Build Coastguard Worker
630*cc4ad7daSAndroid Build Coastguard Worker status = regexec(&re, cfg->kversion, 0, NULL, 0);
631*cc4ad7daSAndroid Build Coastguard Worker regfree(&re);
632*cc4ad7daSAndroid Build Coastguard Worker
633*cc4ad7daSAndroid Build Coastguard Worker return status == 0;
634*cc4ad7daSAndroid Build Coastguard Worker }
635*cc4ad7daSAndroid Build Coastguard Worker
cfg_file_parse(struct cfg * cfg,const char * filename)636*cc4ad7daSAndroid Build Coastguard Worker static int cfg_file_parse(struct cfg *cfg, const char *filename)
637*cc4ad7daSAndroid Build Coastguard Worker {
638*cc4ad7daSAndroid Build Coastguard Worker char *line;
639*cc4ad7daSAndroid Build Coastguard Worker FILE *fp;
640*cc4ad7daSAndroid Build Coastguard Worker unsigned int linenum = 0;
641*cc4ad7daSAndroid Build Coastguard Worker int err;
642*cc4ad7daSAndroid Build Coastguard Worker
643*cc4ad7daSAndroid Build Coastguard Worker fp = fopen(filename, "r");
644*cc4ad7daSAndroid Build Coastguard Worker if (fp == NULL) {
645*cc4ad7daSAndroid Build Coastguard Worker err = -errno;
646*cc4ad7daSAndroid Build Coastguard Worker ERR("file parse %s: %m\n", filename);
647*cc4ad7daSAndroid Build Coastguard Worker return err;
648*cc4ad7daSAndroid Build Coastguard Worker }
649*cc4ad7daSAndroid Build Coastguard Worker
650*cc4ad7daSAndroid Build Coastguard Worker while ((line = freadline_wrapped(fp, &linenum)) != NULL) {
651*cc4ad7daSAndroid Build Coastguard Worker char *cmd, *saveptr;
652*cc4ad7daSAndroid Build Coastguard Worker
653*cc4ad7daSAndroid Build Coastguard Worker if (line[0] == '\0' || line[0] == '#')
654*cc4ad7daSAndroid Build Coastguard Worker goto done_next;
655*cc4ad7daSAndroid Build Coastguard Worker
656*cc4ad7daSAndroid Build Coastguard Worker cmd = strtok_r(line, "\t ", &saveptr);
657*cc4ad7daSAndroid Build Coastguard Worker if (cmd == NULL)
658*cc4ad7daSAndroid Build Coastguard Worker goto done_next;
659*cc4ad7daSAndroid Build Coastguard Worker
660*cc4ad7daSAndroid Build Coastguard Worker if (streq(cmd, "search")) {
661*cc4ad7daSAndroid Build Coastguard Worker const char *sp;
662*cc4ad7daSAndroid Build Coastguard Worker while ((sp = strtok_r(NULL, "\t ", &saveptr)) != NULL) {
663*cc4ad7daSAndroid Build Coastguard Worker cfg_search_add(cfg, sp);
664*cc4ad7daSAndroid Build Coastguard Worker }
665*cc4ad7daSAndroid Build Coastguard Worker } else if (streq(cmd, "override")) {
666*cc4ad7daSAndroid Build Coastguard Worker const char *modname = strtok_r(NULL, "\t ", &saveptr);
667*cc4ad7daSAndroid Build Coastguard Worker const char *version = strtok_r(NULL, "\t ", &saveptr);
668*cc4ad7daSAndroid Build Coastguard Worker const char *subdir = strtok_r(NULL, "\t ", &saveptr);
669*cc4ad7daSAndroid Build Coastguard Worker
670*cc4ad7daSAndroid Build Coastguard Worker if (modname == NULL || version == NULL ||
671*cc4ad7daSAndroid Build Coastguard Worker subdir == NULL)
672*cc4ad7daSAndroid Build Coastguard Worker goto syntax_error;
673*cc4ad7daSAndroid Build Coastguard Worker
674*cc4ad7daSAndroid Build Coastguard Worker if (!cfg_kernel_matches(cfg, version)) {
675*cc4ad7daSAndroid Build Coastguard Worker INF("%s:%u: override kernel did not match %s\n",
676*cc4ad7daSAndroid Build Coastguard Worker filename, linenum, version);
677*cc4ad7daSAndroid Build Coastguard Worker goto done_next;
678*cc4ad7daSAndroid Build Coastguard Worker }
679*cc4ad7daSAndroid Build Coastguard Worker
680*cc4ad7daSAndroid Build Coastguard Worker cfg_override_add(cfg, modname, subdir);
681*cc4ad7daSAndroid Build Coastguard Worker } else if (streq(cmd, "external")) {
682*cc4ad7daSAndroid Build Coastguard Worker const char *version = strtok_r(NULL, "\t ", &saveptr);
683*cc4ad7daSAndroid Build Coastguard Worker const char *dir = strtok_r(NULL, "\t ", &saveptr);
684*cc4ad7daSAndroid Build Coastguard Worker
685*cc4ad7daSAndroid Build Coastguard Worker if (version == NULL || dir == NULL)
686*cc4ad7daSAndroid Build Coastguard Worker goto syntax_error;
687*cc4ad7daSAndroid Build Coastguard Worker
688*cc4ad7daSAndroid Build Coastguard Worker if (!cfg_kernel_matches(cfg, version)) {
689*cc4ad7daSAndroid Build Coastguard Worker INF("%s:%u: external directory did not match %s\n",
690*cc4ad7daSAndroid Build Coastguard Worker filename, linenum, version);
691*cc4ad7daSAndroid Build Coastguard Worker goto done_next;
692*cc4ad7daSAndroid Build Coastguard Worker }
693*cc4ad7daSAndroid Build Coastguard Worker
694*cc4ad7daSAndroid Build Coastguard Worker cfg_external_add(cfg, dir);
695*cc4ad7daSAndroid Build Coastguard Worker } else if (streq(cmd, "exclude")) {
696*cc4ad7daSAndroid Build Coastguard Worker const char *sp;
697*cc4ad7daSAndroid Build Coastguard Worker while ((sp = strtok_r(NULL, "\t ", &saveptr)) != NULL) {
698*cc4ad7daSAndroid Build Coastguard Worker cfg_exclude_add(cfg, sp);
699*cc4ad7daSAndroid Build Coastguard Worker }
700*cc4ad7daSAndroid Build Coastguard Worker } else if (streq(cmd, "include")
701*cc4ad7daSAndroid Build Coastguard Worker || streq(cmd, "make_map_files")) {
702*cc4ad7daSAndroid Build Coastguard Worker INF("%s:%u: command %s not implemented yet\n",
703*cc4ad7daSAndroid Build Coastguard Worker filename, linenum, cmd);
704*cc4ad7daSAndroid Build Coastguard Worker } else {
705*cc4ad7daSAndroid Build Coastguard Worker syntax_error:
706*cc4ad7daSAndroid Build Coastguard Worker ERR("%s:%u: ignoring bad line starting with '%s'\n",
707*cc4ad7daSAndroid Build Coastguard Worker filename, linenum, cmd);
708*cc4ad7daSAndroid Build Coastguard Worker }
709*cc4ad7daSAndroid Build Coastguard Worker
710*cc4ad7daSAndroid Build Coastguard Worker done_next:
711*cc4ad7daSAndroid Build Coastguard Worker free(line);
712*cc4ad7daSAndroid Build Coastguard Worker }
713*cc4ad7daSAndroid Build Coastguard Worker
714*cc4ad7daSAndroid Build Coastguard Worker fclose(fp);
715*cc4ad7daSAndroid Build Coastguard Worker
716*cc4ad7daSAndroid Build Coastguard Worker return 0;
717*cc4ad7daSAndroid Build Coastguard Worker }
718*cc4ad7daSAndroid Build Coastguard Worker
cfg_files_filter_out(DIR * d,const char * dir,const char * name)719*cc4ad7daSAndroid Build Coastguard Worker static int cfg_files_filter_out(DIR *d, const char *dir, const char *name)
720*cc4ad7daSAndroid Build Coastguard Worker {
721*cc4ad7daSAndroid Build Coastguard Worker size_t len = strlen(name);
722*cc4ad7daSAndroid Build Coastguard Worker struct stat st;
723*cc4ad7daSAndroid Build Coastguard Worker
724*cc4ad7daSAndroid Build Coastguard Worker if (name[0] == '.')
725*cc4ad7daSAndroid Build Coastguard Worker return 1;
726*cc4ad7daSAndroid Build Coastguard Worker
727*cc4ad7daSAndroid Build Coastguard Worker if (len < 6 || !streq(name + len - 5, ".conf")) {
728*cc4ad7daSAndroid Build Coastguard Worker INF("All cfg files need .conf: %s/%s\n", dir, name);
729*cc4ad7daSAndroid Build Coastguard Worker return 1;
730*cc4ad7daSAndroid Build Coastguard Worker }
731*cc4ad7daSAndroid Build Coastguard Worker
732*cc4ad7daSAndroid Build Coastguard Worker fstatat(dirfd(d), name, &st, 0);
733*cc4ad7daSAndroid Build Coastguard Worker if (S_ISDIR(st.st_mode)) {
734*cc4ad7daSAndroid Build Coastguard Worker ERR("Directories inside directories are not supported: %s/%s\n",
735*cc4ad7daSAndroid Build Coastguard Worker dir, name);
736*cc4ad7daSAndroid Build Coastguard Worker return 1;
737*cc4ad7daSAndroid Build Coastguard Worker }
738*cc4ad7daSAndroid Build Coastguard Worker
739*cc4ad7daSAndroid Build Coastguard Worker return 0;
740*cc4ad7daSAndroid Build Coastguard Worker }
741*cc4ad7daSAndroid Build Coastguard Worker
742*cc4ad7daSAndroid Build Coastguard Worker struct cfg_file {
743*cc4ad7daSAndroid Build Coastguard Worker size_t dirlen;
744*cc4ad7daSAndroid Build Coastguard Worker size_t namelen;
745*cc4ad7daSAndroid Build Coastguard Worker const char *name;
746*cc4ad7daSAndroid Build Coastguard Worker char path[];
747*cc4ad7daSAndroid Build Coastguard Worker };
748*cc4ad7daSAndroid Build Coastguard Worker
cfg_file_free(struct cfg_file * f)749*cc4ad7daSAndroid Build Coastguard Worker static void cfg_file_free(struct cfg_file *f)
750*cc4ad7daSAndroid Build Coastguard Worker {
751*cc4ad7daSAndroid Build Coastguard Worker free(f);
752*cc4ad7daSAndroid Build Coastguard Worker }
753*cc4ad7daSAndroid Build Coastguard Worker
cfg_files_insert_sorted(struct cfg_file *** p_files,size_t * p_n_files,const char * dir,const char * name)754*cc4ad7daSAndroid Build Coastguard Worker static int cfg_files_insert_sorted(struct cfg_file ***p_files, size_t *p_n_files,
755*cc4ad7daSAndroid Build Coastguard Worker const char *dir, const char *name)
756*cc4ad7daSAndroid Build Coastguard Worker {
757*cc4ad7daSAndroid Build Coastguard Worker struct cfg_file **files, *f;
758*cc4ad7daSAndroid Build Coastguard Worker size_t i, n_files, namelen, dirlen;
759*cc4ad7daSAndroid Build Coastguard Worker void *tmp;
760*cc4ad7daSAndroid Build Coastguard Worker
761*cc4ad7daSAndroid Build Coastguard Worker dirlen = strlen(dir);
762*cc4ad7daSAndroid Build Coastguard Worker if (name != NULL)
763*cc4ad7daSAndroid Build Coastguard Worker namelen = strlen(name);
764*cc4ad7daSAndroid Build Coastguard Worker else {
765*cc4ad7daSAndroid Build Coastguard Worker name = basename(dir);
766*cc4ad7daSAndroid Build Coastguard Worker namelen = strlen(name);
767*cc4ad7daSAndroid Build Coastguard Worker dirlen -= namelen + 1;
768*cc4ad7daSAndroid Build Coastguard Worker }
769*cc4ad7daSAndroid Build Coastguard Worker
770*cc4ad7daSAndroid Build Coastguard Worker n_files = *p_n_files;
771*cc4ad7daSAndroid Build Coastguard Worker files = *p_files;
772*cc4ad7daSAndroid Build Coastguard Worker for (i = 0; i < n_files; i++) {
773*cc4ad7daSAndroid Build Coastguard Worker int cmp = strcmp(name, files[i]->name);
774*cc4ad7daSAndroid Build Coastguard Worker if (cmp == 0) {
775*cc4ad7daSAndroid Build Coastguard Worker DBG("Ignoring duplicate config file: %.*s/%s\n",
776*cc4ad7daSAndroid Build Coastguard Worker (int)dirlen, dir, name);
777*cc4ad7daSAndroid Build Coastguard Worker return -EEXIST;
778*cc4ad7daSAndroid Build Coastguard Worker } else if (cmp < 0)
779*cc4ad7daSAndroid Build Coastguard Worker break;
780*cc4ad7daSAndroid Build Coastguard Worker }
781*cc4ad7daSAndroid Build Coastguard Worker
782*cc4ad7daSAndroid Build Coastguard Worker f = malloc(sizeof(struct cfg_file) + dirlen + namelen + 2);
783*cc4ad7daSAndroid Build Coastguard Worker if (f == NULL) {
784*cc4ad7daSAndroid Build Coastguard Worker ERR("files insert sorted: out of memory\n");
785*cc4ad7daSAndroid Build Coastguard Worker return -ENOMEM;
786*cc4ad7daSAndroid Build Coastguard Worker }
787*cc4ad7daSAndroid Build Coastguard Worker
788*cc4ad7daSAndroid Build Coastguard Worker tmp = realloc(files, sizeof(struct cfg_file *) * (n_files + 1));
789*cc4ad7daSAndroid Build Coastguard Worker if (tmp == NULL) {
790*cc4ad7daSAndroid Build Coastguard Worker ERR("files insert sorted: out of memory\n");
791*cc4ad7daSAndroid Build Coastguard Worker free(f);
792*cc4ad7daSAndroid Build Coastguard Worker return -ENOMEM;
793*cc4ad7daSAndroid Build Coastguard Worker }
794*cc4ad7daSAndroid Build Coastguard Worker *p_files = files = tmp;
795*cc4ad7daSAndroid Build Coastguard Worker
796*cc4ad7daSAndroid Build Coastguard Worker if (i < n_files) {
797*cc4ad7daSAndroid Build Coastguard Worker memmove(files + i + 1, files + i,
798*cc4ad7daSAndroid Build Coastguard Worker sizeof(struct cfg_file *) * (n_files - i));
799*cc4ad7daSAndroid Build Coastguard Worker }
800*cc4ad7daSAndroid Build Coastguard Worker files[i] = f;
801*cc4ad7daSAndroid Build Coastguard Worker
802*cc4ad7daSAndroid Build Coastguard Worker f->dirlen = dirlen;
803*cc4ad7daSAndroid Build Coastguard Worker f->namelen = namelen;
804*cc4ad7daSAndroid Build Coastguard Worker f->name = f->path + dirlen + 1;
805*cc4ad7daSAndroid Build Coastguard Worker memcpy(f->path, dir, dirlen);
806*cc4ad7daSAndroid Build Coastguard Worker f->path[dirlen] = '/';
807*cc4ad7daSAndroid Build Coastguard Worker memcpy(f->path + dirlen + 1, name, namelen);
808*cc4ad7daSAndroid Build Coastguard Worker f->path[dirlen + 1 + namelen] = '\0';
809*cc4ad7daSAndroid Build Coastguard Worker
810*cc4ad7daSAndroid Build Coastguard Worker *p_n_files = n_files + 1;
811*cc4ad7daSAndroid Build Coastguard Worker return 0;
812*cc4ad7daSAndroid Build Coastguard Worker }
813*cc4ad7daSAndroid Build Coastguard Worker
814*cc4ad7daSAndroid Build Coastguard Worker /*
815*cc4ad7daSAndroid Build Coastguard Worker * Insert configuration files ignoring duplicates
816*cc4ad7daSAndroid Build Coastguard Worker */
cfg_files_list(struct cfg_file *** p_files,size_t * p_n_files,const char * path)817*cc4ad7daSAndroid Build Coastguard Worker static int cfg_files_list(struct cfg_file ***p_files, size_t *p_n_files,
818*cc4ad7daSAndroid Build Coastguard Worker const char *path)
819*cc4ad7daSAndroid Build Coastguard Worker {
820*cc4ad7daSAndroid Build Coastguard Worker struct dirent *dent;
821*cc4ad7daSAndroid Build Coastguard Worker DIR *d;
822*cc4ad7daSAndroid Build Coastguard Worker int err = 0;
823*cc4ad7daSAndroid Build Coastguard Worker struct stat st;
824*cc4ad7daSAndroid Build Coastguard Worker
825*cc4ad7daSAndroid Build Coastguard Worker if (stat(path, &st) != 0) {
826*cc4ad7daSAndroid Build Coastguard Worker err = -errno;
827*cc4ad7daSAndroid Build Coastguard Worker DBG("could not stat '%s': %m\n", path);
828*cc4ad7daSAndroid Build Coastguard Worker return err;
829*cc4ad7daSAndroid Build Coastguard Worker }
830*cc4ad7daSAndroid Build Coastguard Worker
831*cc4ad7daSAndroid Build Coastguard Worker if (!S_ISDIR(st.st_mode)) {
832*cc4ad7daSAndroid Build Coastguard Worker cfg_files_insert_sorted(p_files, p_n_files, path, NULL);
833*cc4ad7daSAndroid Build Coastguard Worker return 0;
834*cc4ad7daSAndroid Build Coastguard Worker }
835*cc4ad7daSAndroid Build Coastguard Worker
836*cc4ad7daSAndroid Build Coastguard Worker d = opendir(path);
837*cc4ad7daSAndroid Build Coastguard Worker if (d == NULL) {
838*cc4ad7daSAndroid Build Coastguard Worker ERR("files list %s: %m\n", path);
839*cc4ad7daSAndroid Build Coastguard Worker return -EINVAL;
840*cc4ad7daSAndroid Build Coastguard Worker }
841*cc4ad7daSAndroid Build Coastguard Worker
842*cc4ad7daSAndroid Build Coastguard Worker for (dent = readdir(d); dent != NULL; dent = readdir(d)) {
843*cc4ad7daSAndroid Build Coastguard Worker if (cfg_files_filter_out(d, path, dent->d_name))
844*cc4ad7daSAndroid Build Coastguard Worker continue;
845*cc4ad7daSAndroid Build Coastguard Worker
846*cc4ad7daSAndroid Build Coastguard Worker cfg_files_insert_sorted(p_files, p_n_files, path, dent->d_name);
847*cc4ad7daSAndroid Build Coastguard Worker }
848*cc4ad7daSAndroid Build Coastguard Worker
849*cc4ad7daSAndroid Build Coastguard Worker closedir(d);
850*cc4ad7daSAndroid Build Coastguard Worker DBG("parsed configuration files from %s\n", path);
851*cc4ad7daSAndroid Build Coastguard Worker return err;
852*cc4ad7daSAndroid Build Coastguard Worker }
853*cc4ad7daSAndroid Build Coastguard Worker
cfg_load(struct cfg * cfg,const char * const * cfg_paths)854*cc4ad7daSAndroid Build Coastguard Worker static int cfg_load(struct cfg *cfg, const char * const *cfg_paths)
855*cc4ad7daSAndroid Build Coastguard Worker {
856*cc4ad7daSAndroid Build Coastguard Worker size_t i, n_files = 0;
857*cc4ad7daSAndroid Build Coastguard Worker struct cfg_file **files = NULL;
858*cc4ad7daSAndroid Build Coastguard Worker
859*cc4ad7daSAndroid Build Coastguard Worker if (cfg_paths == NULL)
860*cc4ad7daSAndroid Build Coastguard Worker cfg_paths = default_cfg_paths;
861*cc4ad7daSAndroid Build Coastguard Worker
862*cc4ad7daSAndroid Build Coastguard Worker for (i = 0; cfg_paths[i] != NULL; i++)
863*cc4ad7daSAndroid Build Coastguard Worker cfg_files_list(&files, &n_files, cfg_paths[i]);
864*cc4ad7daSAndroid Build Coastguard Worker
865*cc4ad7daSAndroid Build Coastguard Worker for (i = 0; i < n_files; i++) {
866*cc4ad7daSAndroid Build Coastguard Worker struct cfg_file *f = files[i];
867*cc4ad7daSAndroid Build Coastguard Worker cfg_file_parse(cfg, f->path);
868*cc4ad7daSAndroid Build Coastguard Worker cfg_file_free(f);
869*cc4ad7daSAndroid Build Coastguard Worker }
870*cc4ad7daSAndroid Build Coastguard Worker free(files);
871*cc4ad7daSAndroid Build Coastguard Worker
872*cc4ad7daSAndroid Build Coastguard Worker /* For backward compatibility add "updates" to the head of the search
873*cc4ad7daSAndroid Build Coastguard Worker * list here. But only if there was no "search" option specified.
874*cc4ad7daSAndroid Build Coastguard Worker */
875*cc4ad7daSAndroid Build Coastguard Worker if (cfg->searches == NULL)
876*cc4ad7daSAndroid Build Coastguard Worker cfg_search_add(cfg, "updates");
877*cc4ad7daSAndroid Build Coastguard Worker
878*cc4ad7daSAndroid Build Coastguard Worker return 0;
879*cc4ad7daSAndroid Build Coastguard Worker }
880*cc4ad7daSAndroid Build Coastguard Worker
cfg_free(struct cfg * cfg)881*cc4ad7daSAndroid Build Coastguard Worker static void cfg_free(struct cfg *cfg)
882*cc4ad7daSAndroid Build Coastguard Worker {
883*cc4ad7daSAndroid Build Coastguard Worker while (cfg->overrides) {
884*cc4ad7daSAndroid Build Coastguard Worker struct cfg_override *tmp = cfg->overrides;
885*cc4ad7daSAndroid Build Coastguard Worker cfg->overrides = cfg->overrides->next;
886*cc4ad7daSAndroid Build Coastguard Worker cfg_override_free(tmp);
887*cc4ad7daSAndroid Build Coastguard Worker }
888*cc4ad7daSAndroid Build Coastguard Worker
889*cc4ad7daSAndroid Build Coastguard Worker while (cfg->searches) {
890*cc4ad7daSAndroid Build Coastguard Worker struct cfg_search *tmp = cfg->searches;
891*cc4ad7daSAndroid Build Coastguard Worker cfg->searches = cfg->searches->next;
892*cc4ad7daSAndroid Build Coastguard Worker cfg_search_free(tmp);
893*cc4ad7daSAndroid Build Coastguard Worker }
894*cc4ad7daSAndroid Build Coastguard Worker
895*cc4ad7daSAndroid Build Coastguard Worker while (cfg->externals) {
896*cc4ad7daSAndroid Build Coastguard Worker struct cfg_external *tmp = cfg->externals;
897*cc4ad7daSAndroid Build Coastguard Worker cfg->externals = cfg->externals->next;
898*cc4ad7daSAndroid Build Coastguard Worker cfg_external_free(tmp);
899*cc4ad7daSAndroid Build Coastguard Worker }
900*cc4ad7daSAndroid Build Coastguard Worker
901*cc4ad7daSAndroid Build Coastguard Worker while (cfg->excludes) {
902*cc4ad7daSAndroid Build Coastguard Worker struct cfg_exclude *tmp = cfg->excludes;
903*cc4ad7daSAndroid Build Coastguard Worker cfg->excludes = cfg->excludes->next;
904*cc4ad7daSAndroid Build Coastguard Worker cfg_exclude_free(tmp);
905*cc4ad7daSAndroid Build Coastguard Worker }
906*cc4ad7daSAndroid Build Coastguard Worker }
907*cc4ad7daSAndroid Build Coastguard Worker
908*cc4ad7daSAndroid Build Coastguard Worker
909*cc4ad7daSAndroid Build Coastguard Worker /* depmod calculations ***********************************************/
910*cc4ad7daSAndroid Build Coastguard Worker struct vertex;
911*cc4ad7daSAndroid Build Coastguard Worker struct mod {
912*cc4ad7daSAndroid Build Coastguard Worker struct kmod_module *kmod;
913*cc4ad7daSAndroid Build Coastguard Worker char *path;
914*cc4ad7daSAndroid Build Coastguard Worker const char *relpath; /* path relative to '$ROOT$MODULE_DIRECTORY/$VER/' */
915*cc4ad7daSAndroid Build Coastguard Worker char *uncrelpath; /* same as relpath but ending in .ko */
916*cc4ad7daSAndroid Build Coastguard Worker struct kmod_list *info_list;
917*cc4ad7daSAndroid Build Coastguard Worker struct kmod_list *dep_sym_list;
918*cc4ad7daSAndroid Build Coastguard Worker struct array deps; /* struct symbol */
919*cc4ad7daSAndroid Build Coastguard Worker size_t baselen; /* points to start of basename/filename */
920*cc4ad7daSAndroid Build Coastguard Worker size_t modnamesz;
921*cc4ad7daSAndroid Build Coastguard Worker int sort_idx; /* sort index using modules.order */
922*cc4ad7daSAndroid Build Coastguard Worker int dep_sort_idx; /* topological sort index */
923*cc4ad7daSAndroid Build Coastguard Worker uint16_t idx; /* index in depmod->modules.array */
924*cc4ad7daSAndroid Build Coastguard Worker uint16_t users; /* how many modules depend on this one */
925*cc4ad7daSAndroid Build Coastguard Worker bool visited; /* helper field to report cycles */
926*cc4ad7daSAndroid Build Coastguard Worker struct vertex *vertex; /* helper field to report cycles */
927*cc4ad7daSAndroid Build Coastguard Worker char modname[];
928*cc4ad7daSAndroid Build Coastguard Worker };
929*cc4ad7daSAndroid Build Coastguard Worker
930*cc4ad7daSAndroid Build Coastguard Worker struct symbol {
931*cc4ad7daSAndroid Build Coastguard Worker struct mod *owner;
932*cc4ad7daSAndroid Build Coastguard Worker uint64_t crc;
933*cc4ad7daSAndroid Build Coastguard Worker char name[];
934*cc4ad7daSAndroid Build Coastguard Worker };
935*cc4ad7daSAndroid Build Coastguard Worker
936*cc4ad7daSAndroid Build Coastguard Worker struct depmod {
937*cc4ad7daSAndroid Build Coastguard Worker const struct cfg *cfg;
938*cc4ad7daSAndroid Build Coastguard Worker struct kmod_ctx *ctx;
939*cc4ad7daSAndroid Build Coastguard Worker struct array modules;
940*cc4ad7daSAndroid Build Coastguard Worker struct hash *modules_by_uncrelpath;
941*cc4ad7daSAndroid Build Coastguard Worker struct hash *modules_by_name;
942*cc4ad7daSAndroid Build Coastguard Worker struct hash *symbols;
943*cc4ad7daSAndroid Build Coastguard Worker };
944*cc4ad7daSAndroid Build Coastguard Worker
mod_free(struct mod * mod)945*cc4ad7daSAndroid Build Coastguard Worker static void mod_free(struct mod *mod)
946*cc4ad7daSAndroid Build Coastguard Worker {
947*cc4ad7daSAndroid Build Coastguard Worker DBG("free %p kmod=%p, path=%s\n", mod, mod->kmod, mod->path);
948*cc4ad7daSAndroid Build Coastguard Worker array_free_array(&mod->deps);
949*cc4ad7daSAndroid Build Coastguard Worker kmod_module_unref(mod->kmod);
950*cc4ad7daSAndroid Build Coastguard Worker kmod_module_info_free_list(mod->info_list);
951*cc4ad7daSAndroid Build Coastguard Worker kmod_module_dependency_symbols_free_list(mod->dep_sym_list);
952*cc4ad7daSAndroid Build Coastguard Worker free(mod->uncrelpath);
953*cc4ad7daSAndroid Build Coastguard Worker free(mod->path);
954*cc4ad7daSAndroid Build Coastguard Worker free(mod);
955*cc4ad7daSAndroid Build Coastguard Worker }
956*cc4ad7daSAndroid Build Coastguard Worker
mod_add_dependency(struct mod * mod,struct symbol * sym)957*cc4ad7daSAndroid Build Coastguard Worker static int mod_add_dependency(struct mod *mod, struct symbol *sym)
958*cc4ad7daSAndroid Build Coastguard Worker {
959*cc4ad7daSAndroid Build Coastguard Worker int err;
960*cc4ad7daSAndroid Build Coastguard Worker
961*cc4ad7daSAndroid Build Coastguard Worker DBG("%s depends on %s %s\n", mod->path, sym->name,
962*cc4ad7daSAndroid Build Coastguard Worker sym->owner != NULL ? sym->owner->path : "(unknown)");
963*cc4ad7daSAndroid Build Coastguard Worker
964*cc4ad7daSAndroid Build Coastguard Worker if (sym->owner == NULL)
965*cc4ad7daSAndroid Build Coastguard Worker return 0;
966*cc4ad7daSAndroid Build Coastguard Worker
967*cc4ad7daSAndroid Build Coastguard Worker err = array_append_unique(&mod->deps, sym->owner);
968*cc4ad7daSAndroid Build Coastguard Worker if (err == -EEXIST)
969*cc4ad7daSAndroid Build Coastguard Worker return 0;
970*cc4ad7daSAndroid Build Coastguard Worker if (err < 0)
971*cc4ad7daSAndroid Build Coastguard Worker return err;
972*cc4ad7daSAndroid Build Coastguard Worker
973*cc4ad7daSAndroid Build Coastguard Worker sym->owner->users++;
974*cc4ad7daSAndroid Build Coastguard Worker SHOW("%s needs \"%s\": %s\n", mod->path, sym->name, sym->owner->path);
975*cc4ad7daSAndroid Build Coastguard Worker return 0;
976*cc4ad7daSAndroid Build Coastguard Worker }
977*cc4ad7daSAndroid Build Coastguard Worker
symbol_free(struct symbol * sym)978*cc4ad7daSAndroid Build Coastguard Worker static void symbol_free(struct symbol *sym)
979*cc4ad7daSAndroid Build Coastguard Worker {
980*cc4ad7daSAndroid Build Coastguard Worker DBG("free %p sym=%s, owner=%p %s\n", sym, sym->name, sym->owner,
981*cc4ad7daSAndroid Build Coastguard Worker sym->owner != NULL ? sym->owner->path : "");
982*cc4ad7daSAndroid Build Coastguard Worker free(sym);
983*cc4ad7daSAndroid Build Coastguard Worker }
984*cc4ad7daSAndroid Build Coastguard Worker
depmod_init(struct depmod * depmod,struct cfg * cfg,struct kmod_ctx * ctx)985*cc4ad7daSAndroid Build Coastguard Worker static int depmod_init(struct depmod *depmod, struct cfg *cfg,
986*cc4ad7daSAndroid Build Coastguard Worker struct kmod_ctx *ctx)
987*cc4ad7daSAndroid Build Coastguard Worker {
988*cc4ad7daSAndroid Build Coastguard Worker int err = 0;
989*cc4ad7daSAndroid Build Coastguard Worker
990*cc4ad7daSAndroid Build Coastguard Worker depmod->cfg = cfg;
991*cc4ad7daSAndroid Build Coastguard Worker depmod->ctx = ctx;
992*cc4ad7daSAndroid Build Coastguard Worker
993*cc4ad7daSAndroid Build Coastguard Worker array_init(&depmod->modules, 128);
994*cc4ad7daSAndroid Build Coastguard Worker
995*cc4ad7daSAndroid Build Coastguard Worker depmod->modules_by_uncrelpath = hash_new(512, NULL);
996*cc4ad7daSAndroid Build Coastguard Worker if (depmod->modules_by_uncrelpath == NULL) {
997*cc4ad7daSAndroid Build Coastguard Worker err = -errno;
998*cc4ad7daSAndroid Build Coastguard Worker goto modules_by_uncrelpath_failed;
999*cc4ad7daSAndroid Build Coastguard Worker }
1000*cc4ad7daSAndroid Build Coastguard Worker
1001*cc4ad7daSAndroid Build Coastguard Worker depmod->modules_by_name = hash_new(512, NULL);
1002*cc4ad7daSAndroid Build Coastguard Worker if (depmod->modules_by_name == NULL) {
1003*cc4ad7daSAndroid Build Coastguard Worker err = -errno;
1004*cc4ad7daSAndroid Build Coastguard Worker goto modules_by_name_failed;
1005*cc4ad7daSAndroid Build Coastguard Worker }
1006*cc4ad7daSAndroid Build Coastguard Worker
1007*cc4ad7daSAndroid Build Coastguard Worker depmod->symbols = hash_new(2048, (void (*)(void *))symbol_free);
1008*cc4ad7daSAndroid Build Coastguard Worker if (depmod->symbols == NULL) {
1009*cc4ad7daSAndroid Build Coastguard Worker err = -errno;
1010*cc4ad7daSAndroid Build Coastguard Worker goto symbols_failed;
1011*cc4ad7daSAndroid Build Coastguard Worker }
1012*cc4ad7daSAndroid Build Coastguard Worker
1013*cc4ad7daSAndroid Build Coastguard Worker return 0;
1014*cc4ad7daSAndroid Build Coastguard Worker
1015*cc4ad7daSAndroid Build Coastguard Worker symbols_failed:
1016*cc4ad7daSAndroid Build Coastguard Worker hash_free(depmod->modules_by_name);
1017*cc4ad7daSAndroid Build Coastguard Worker modules_by_name_failed:
1018*cc4ad7daSAndroid Build Coastguard Worker hash_free(depmod->modules_by_uncrelpath);
1019*cc4ad7daSAndroid Build Coastguard Worker modules_by_uncrelpath_failed:
1020*cc4ad7daSAndroid Build Coastguard Worker return err;
1021*cc4ad7daSAndroid Build Coastguard Worker }
1022*cc4ad7daSAndroid Build Coastguard Worker
depmod_shutdown(struct depmod * depmod)1023*cc4ad7daSAndroid Build Coastguard Worker static void depmod_shutdown(struct depmod *depmod)
1024*cc4ad7daSAndroid Build Coastguard Worker {
1025*cc4ad7daSAndroid Build Coastguard Worker size_t i;
1026*cc4ad7daSAndroid Build Coastguard Worker
1027*cc4ad7daSAndroid Build Coastguard Worker hash_free(depmod->symbols);
1028*cc4ad7daSAndroid Build Coastguard Worker
1029*cc4ad7daSAndroid Build Coastguard Worker hash_free(depmod->modules_by_uncrelpath);
1030*cc4ad7daSAndroid Build Coastguard Worker
1031*cc4ad7daSAndroid Build Coastguard Worker hash_free(depmod->modules_by_name);
1032*cc4ad7daSAndroid Build Coastguard Worker
1033*cc4ad7daSAndroid Build Coastguard Worker for (i = 0; i < depmod->modules.count; i++)
1034*cc4ad7daSAndroid Build Coastguard Worker mod_free(depmod->modules.array[i]);
1035*cc4ad7daSAndroid Build Coastguard Worker array_free_array(&depmod->modules);
1036*cc4ad7daSAndroid Build Coastguard Worker
1037*cc4ad7daSAndroid Build Coastguard Worker kmod_unref(depmod->ctx);
1038*cc4ad7daSAndroid Build Coastguard Worker }
1039*cc4ad7daSAndroid Build Coastguard Worker
depmod_module_add(struct depmod * depmod,struct kmod_module * kmod)1040*cc4ad7daSAndroid Build Coastguard Worker static int depmod_module_add(struct depmod *depmod, struct kmod_module *kmod)
1041*cc4ad7daSAndroid Build Coastguard Worker {
1042*cc4ad7daSAndroid Build Coastguard Worker const struct cfg *cfg = depmod->cfg;
1043*cc4ad7daSAndroid Build Coastguard Worker const char *modname, *lastslash;
1044*cc4ad7daSAndroid Build Coastguard Worker size_t modnamesz;
1045*cc4ad7daSAndroid Build Coastguard Worker struct mod *mod;
1046*cc4ad7daSAndroid Build Coastguard Worker int err;
1047*cc4ad7daSAndroid Build Coastguard Worker
1048*cc4ad7daSAndroid Build Coastguard Worker modname = kmod_module_get_name(kmod);
1049*cc4ad7daSAndroid Build Coastguard Worker modnamesz = strlen(modname) + 1;
1050*cc4ad7daSAndroid Build Coastguard Worker
1051*cc4ad7daSAndroid Build Coastguard Worker mod = calloc(1, sizeof(struct mod) + modnamesz);
1052*cc4ad7daSAndroid Build Coastguard Worker if (mod == NULL)
1053*cc4ad7daSAndroid Build Coastguard Worker return -ENOMEM;
1054*cc4ad7daSAndroid Build Coastguard Worker mod->kmod = kmod;
1055*cc4ad7daSAndroid Build Coastguard Worker mod->sort_idx = depmod->modules.count + 1;
1056*cc4ad7daSAndroid Build Coastguard Worker mod->dep_sort_idx = INT32_MAX;
1057*cc4ad7daSAndroid Build Coastguard Worker memcpy(mod->modname, modname, modnamesz);
1058*cc4ad7daSAndroid Build Coastguard Worker mod->modnamesz = modnamesz;
1059*cc4ad7daSAndroid Build Coastguard Worker
1060*cc4ad7daSAndroid Build Coastguard Worker array_init(&mod->deps, 4);
1061*cc4ad7daSAndroid Build Coastguard Worker
1062*cc4ad7daSAndroid Build Coastguard Worker mod->path = strdup(kmod_module_get_path(kmod));
1063*cc4ad7daSAndroid Build Coastguard Worker lastslash = strrchr(mod->path, '/');
1064*cc4ad7daSAndroid Build Coastguard Worker mod->baselen = lastslash - mod->path;
1065*cc4ad7daSAndroid Build Coastguard Worker if (strncmp(mod->path, cfg->dirname, cfg->dirnamelen) == 0 &&
1066*cc4ad7daSAndroid Build Coastguard Worker mod->path[cfg->dirnamelen] == '/')
1067*cc4ad7daSAndroid Build Coastguard Worker mod->relpath = mod->path + cfg->dirnamelen + 1;
1068*cc4ad7daSAndroid Build Coastguard Worker else
1069*cc4ad7daSAndroid Build Coastguard Worker mod->relpath = NULL;
1070*cc4ad7daSAndroid Build Coastguard Worker
1071*cc4ad7daSAndroid Build Coastguard Worker err = hash_add_unique(depmod->modules_by_name, mod->modname, mod);
1072*cc4ad7daSAndroid Build Coastguard Worker if (err < 0) {
1073*cc4ad7daSAndroid Build Coastguard Worker ERR("hash_add_unique %s: %s\n", mod->modname, strerror(-err));
1074*cc4ad7daSAndroid Build Coastguard Worker goto fail;
1075*cc4ad7daSAndroid Build Coastguard Worker }
1076*cc4ad7daSAndroid Build Coastguard Worker
1077*cc4ad7daSAndroid Build Coastguard Worker if (mod->relpath != NULL) {
1078*cc4ad7daSAndroid Build Coastguard Worker size_t uncrelpathlen = lastslash - mod->relpath + modnamesz
1079*cc4ad7daSAndroid Build Coastguard Worker + strlen(KMOD_EXTENSION_UNCOMPRESSED);
1080*cc4ad7daSAndroid Build Coastguard Worker mod->uncrelpath = memdup(mod->relpath, uncrelpathlen + 1);
1081*cc4ad7daSAndroid Build Coastguard Worker mod->uncrelpath[uncrelpathlen] = '\0';
1082*cc4ad7daSAndroid Build Coastguard Worker err = hash_add_unique(depmod->modules_by_uncrelpath,
1083*cc4ad7daSAndroid Build Coastguard Worker mod->uncrelpath, mod);
1084*cc4ad7daSAndroid Build Coastguard Worker if (err < 0) {
1085*cc4ad7daSAndroid Build Coastguard Worker ERR("hash_add_unique %s: %s\n",
1086*cc4ad7daSAndroid Build Coastguard Worker mod->uncrelpath, strerror(-err));
1087*cc4ad7daSAndroid Build Coastguard Worker hash_del(depmod->modules_by_name, mod->modname);
1088*cc4ad7daSAndroid Build Coastguard Worker goto fail;
1089*cc4ad7daSAndroid Build Coastguard Worker }
1090*cc4ad7daSAndroid Build Coastguard Worker }
1091*cc4ad7daSAndroid Build Coastguard Worker
1092*cc4ad7daSAndroid Build Coastguard Worker DBG("add %p kmod=%p, path=%s\n", mod, kmod, mod->path);
1093*cc4ad7daSAndroid Build Coastguard Worker
1094*cc4ad7daSAndroid Build Coastguard Worker return 0;
1095*cc4ad7daSAndroid Build Coastguard Worker
1096*cc4ad7daSAndroid Build Coastguard Worker fail:
1097*cc4ad7daSAndroid Build Coastguard Worker free(mod->uncrelpath);
1098*cc4ad7daSAndroid Build Coastguard Worker free(mod);
1099*cc4ad7daSAndroid Build Coastguard Worker return err;
1100*cc4ad7daSAndroid Build Coastguard Worker }
1101*cc4ad7daSAndroid Build Coastguard Worker
depmod_module_del(struct depmod * depmod,struct mod * mod)1102*cc4ad7daSAndroid Build Coastguard Worker static int depmod_module_del(struct depmod *depmod, struct mod *mod)
1103*cc4ad7daSAndroid Build Coastguard Worker {
1104*cc4ad7daSAndroid Build Coastguard Worker DBG("del %p kmod=%p, path=%s\n", mod, mod->kmod, mod->path);
1105*cc4ad7daSAndroid Build Coastguard Worker
1106*cc4ad7daSAndroid Build Coastguard Worker if (mod->uncrelpath != NULL)
1107*cc4ad7daSAndroid Build Coastguard Worker hash_del(depmod->modules_by_uncrelpath, mod->uncrelpath);
1108*cc4ad7daSAndroid Build Coastguard Worker
1109*cc4ad7daSAndroid Build Coastguard Worker hash_del(depmod->modules_by_name, mod->modname);
1110*cc4ad7daSAndroid Build Coastguard Worker
1111*cc4ad7daSAndroid Build Coastguard Worker mod_free(mod);
1112*cc4ad7daSAndroid Build Coastguard Worker return 0;
1113*cc4ad7daSAndroid Build Coastguard Worker }
1114*cc4ad7daSAndroid Build Coastguard Worker
search_to_string(const struct cfg_search * s)1115*cc4ad7daSAndroid Build Coastguard Worker static const char *search_to_string(const struct cfg_search *s)
1116*cc4ad7daSAndroid Build Coastguard Worker {
1117*cc4ad7daSAndroid Build Coastguard Worker switch(s->type) {
1118*cc4ad7daSAndroid Build Coastguard Worker case SEARCH_EXTERNAL:
1119*cc4ad7daSAndroid Build Coastguard Worker return "external";
1120*cc4ad7daSAndroid Build Coastguard Worker case SEARCH_BUILTIN:
1121*cc4ad7daSAndroid Build Coastguard Worker return "built-in";
1122*cc4ad7daSAndroid Build Coastguard Worker default:
1123*cc4ad7daSAndroid Build Coastguard Worker return s->path;
1124*cc4ad7daSAndroid Build Coastguard Worker }
1125*cc4ad7daSAndroid Build Coastguard Worker }
1126*cc4ad7daSAndroid Build Coastguard Worker
depmod_is_path_starts_with(const char * path,size_t pathlen,const char * prefix,size_t prefix_len)1127*cc4ad7daSAndroid Build Coastguard Worker static bool depmod_is_path_starts_with(const char *path,
1128*cc4ad7daSAndroid Build Coastguard Worker size_t pathlen,
1129*cc4ad7daSAndroid Build Coastguard Worker const char *prefix,
1130*cc4ad7daSAndroid Build Coastguard Worker size_t prefix_len)
1131*cc4ad7daSAndroid Build Coastguard Worker {
1132*cc4ad7daSAndroid Build Coastguard Worker if (pathlen <= prefix_len)
1133*cc4ad7daSAndroid Build Coastguard Worker return false;
1134*cc4ad7daSAndroid Build Coastguard Worker if (path[prefix_len] != '/')
1135*cc4ad7daSAndroid Build Coastguard Worker return false;
1136*cc4ad7daSAndroid Build Coastguard Worker if (memcmp(path, prefix, prefix_len) != 0)
1137*cc4ad7daSAndroid Build Coastguard Worker return false;
1138*cc4ad7daSAndroid Build Coastguard Worker
1139*cc4ad7daSAndroid Build Coastguard Worker return true;
1140*cc4ad7daSAndroid Build Coastguard Worker }
1141*cc4ad7daSAndroid Build Coastguard Worker
1142*cc4ad7daSAndroid Build Coastguard Worker /* returns if existing module @mod is higher priority than newpath.
1143*cc4ad7daSAndroid Build Coastguard Worker * note this is the inverse of module-init-tools is_higher_priority()
1144*cc4ad7daSAndroid Build Coastguard Worker */
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)1145*cc4ad7daSAndroid Build Coastguard Worker 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)
1146*cc4ad7daSAndroid Build Coastguard Worker {
1147*cc4ad7daSAndroid Build Coastguard Worker const struct cfg *cfg = depmod->cfg;
1148*cc4ad7daSAndroid Build Coastguard Worker const struct cfg_override *ov;
1149*cc4ad7daSAndroid Build Coastguard Worker const struct cfg_search *se;
1150*cc4ad7daSAndroid Build Coastguard Worker const struct cfg_external *ext;
1151*cc4ad7daSAndroid Build Coastguard Worker
1152*cc4ad7daSAndroid Build Coastguard Worker /* baselen includes the last '/' and mod->baselen doesn't. So it's
1153*cc4ad7daSAndroid Build Coastguard Worker * actually correct to use modnamelen in the first and modnamesz in
1154*cc4ad7daSAndroid Build Coastguard Worker * the latter */
1155*cc4ad7daSAndroid Build Coastguard Worker size_t newlen = baselen + modnamelen;
1156*cc4ad7daSAndroid Build Coastguard Worker size_t oldlen = mod->baselen + mod->modnamesz;
1157*cc4ad7daSAndroid Build Coastguard Worker const char *oldpath = mod->path;
1158*cc4ad7daSAndroid Build Coastguard Worker int i, bprio = -1, oldprio = -1, newprio = -1;
1159*cc4ad7daSAndroid Build Coastguard Worker size_t relnewlen = 0;
1160*cc4ad7daSAndroid Build Coastguard Worker size_t reloldlen = 0;
1161*cc4ad7daSAndroid Build Coastguard Worker const char *relnewpath = NULL;
1162*cc4ad7daSAndroid Build Coastguard Worker const char *reloldpath = NULL;
1163*cc4ad7daSAndroid Build Coastguard Worker
1164*cc4ad7daSAndroid Build Coastguard Worker DBG("comparing priorities of %s and %s\n",
1165*cc4ad7daSAndroid Build Coastguard Worker oldpath, newpath);
1166*cc4ad7daSAndroid Build Coastguard Worker
1167*cc4ad7daSAndroid Build Coastguard Worker if (strncmp(newpath, cfg->dirname, cfg->dirnamelen) == 0) {
1168*cc4ad7daSAndroid Build Coastguard Worker relnewpath = newpath + cfg->dirnamelen + 1;
1169*cc4ad7daSAndroid Build Coastguard Worker relnewlen = newlen - (cfg->dirnamelen + 1);
1170*cc4ad7daSAndroid Build Coastguard Worker }
1171*cc4ad7daSAndroid Build Coastguard Worker if (strncmp(oldpath, cfg->dirname, cfg->dirnamelen) == 0) {
1172*cc4ad7daSAndroid Build Coastguard Worker reloldpath = oldpath + cfg->dirnamelen + 1;
1173*cc4ad7daSAndroid Build Coastguard Worker reloldlen = oldlen - (cfg->dirnamelen + 1);
1174*cc4ad7daSAndroid Build Coastguard Worker }
1175*cc4ad7daSAndroid Build Coastguard Worker
1176*cc4ad7daSAndroid Build Coastguard Worker for (ov = cfg->overrides; ov != NULL; ov = ov->next) {
1177*cc4ad7daSAndroid Build Coastguard Worker DBG("override %s\n", ov->path);
1178*cc4ad7daSAndroid Build Coastguard Worker if (relnewlen == ov->len &&
1179*cc4ad7daSAndroid Build Coastguard Worker memcmp(ov->path, relnewpath, relnewlen) == 0)
1180*cc4ad7daSAndroid Build Coastguard Worker return 0;
1181*cc4ad7daSAndroid Build Coastguard Worker if (reloldlen == ov->len &&
1182*cc4ad7daSAndroid Build Coastguard Worker memcmp(ov->path, reloldpath, reloldlen) == 0)
1183*cc4ad7daSAndroid Build Coastguard Worker return 1;
1184*cc4ad7daSAndroid Build Coastguard Worker }
1185*cc4ad7daSAndroid Build Coastguard Worker
1186*cc4ad7daSAndroid Build Coastguard Worker for (i = 0, se = cfg->searches; se != NULL; se = se->next, i++) {
1187*cc4ad7daSAndroid Build Coastguard Worker DBG("search %s\n", search_to_string(se));
1188*cc4ad7daSAndroid Build Coastguard Worker if (se->type == SEARCH_BUILTIN)
1189*cc4ad7daSAndroid Build Coastguard Worker bprio = i;
1190*cc4ad7daSAndroid Build Coastguard Worker else if (se->type == SEARCH_EXTERNAL) {
1191*cc4ad7daSAndroid Build Coastguard Worker for (ext = cfg->externals; ext != NULL; ext = ext->next, i++) {
1192*cc4ad7daSAndroid Build Coastguard Worker if (depmod_is_path_starts_with(newpath,
1193*cc4ad7daSAndroid Build Coastguard Worker newlen,
1194*cc4ad7daSAndroid Build Coastguard Worker ext->path,
1195*cc4ad7daSAndroid Build Coastguard Worker ext->len))
1196*cc4ad7daSAndroid Build Coastguard Worker newprio = i;
1197*cc4ad7daSAndroid Build Coastguard Worker if (depmod_is_path_starts_with(oldpath,
1198*cc4ad7daSAndroid Build Coastguard Worker oldlen,
1199*cc4ad7daSAndroid Build Coastguard Worker ext->path,
1200*cc4ad7daSAndroid Build Coastguard Worker ext->len))
1201*cc4ad7daSAndroid Build Coastguard Worker oldprio = i;
1202*cc4ad7daSAndroid Build Coastguard Worker }
1203*cc4ad7daSAndroid Build Coastguard Worker } else if (relnewlen > se->len && relnewpath[se->len] == '/' &&
1204*cc4ad7daSAndroid Build Coastguard Worker memcmp(se->path, relnewpath, se->len) == 0)
1205*cc4ad7daSAndroid Build Coastguard Worker newprio = i;
1206*cc4ad7daSAndroid Build Coastguard Worker else if (reloldlen > se->len && reloldpath[se->len] == '/' &&
1207*cc4ad7daSAndroid Build Coastguard Worker memcmp(se->path, reloldpath, se->len) == 0)
1208*cc4ad7daSAndroid Build Coastguard Worker oldprio = i;
1209*cc4ad7daSAndroid Build Coastguard Worker }
1210*cc4ad7daSAndroid Build Coastguard Worker
1211*cc4ad7daSAndroid Build Coastguard Worker if (newprio < 0)
1212*cc4ad7daSAndroid Build Coastguard Worker newprio = bprio;
1213*cc4ad7daSAndroid Build Coastguard Worker if (oldprio < 0)
1214*cc4ad7daSAndroid Build Coastguard Worker oldprio = bprio;
1215*cc4ad7daSAndroid Build Coastguard Worker
1216*cc4ad7daSAndroid Build Coastguard Worker DBG("priorities: built-in: %d, old: %d, new: %d\n",
1217*cc4ad7daSAndroid Build Coastguard Worker bprio, oldprio, newprio);
1218*cc4ad7daSAndroid Build Coastguard Worker
1219*cc4ad7daSAndroid Build Coastguard Worker return newprio <= oldprio;
1220*cc4ad7daSAndroid Build Coastguard Worker }
1221*cc4ad7daSAndroid Build Coastguard Worker
depmod_modules_search_file(struct depmod * depmod,size_t baselen,size_t namelen,const char * path)1222*cc4ad7daSAndroid Build Coastguard Worker static int depmod_modules_search_file(struct depmod *depmod, size_t baselen, size_t namelen, const char *path)
1223*cc4ad7daSAndroid Build Coastguard Worker {
1224*cc4ad7daSAndroid Build Coastguard Worker struct kmod_module *kmod;
1225*cc4ad7daSAndroid Build Coastguard Worker struct mod *mod;
1226*cc4ad7daSAndroid Build Coastguard Worker const char *relpath;
1227*cc4ad7daSAndroid Build Coastguard Worker char modname[PATH_MAX];
1228*cc4ad7daSAndroid Build Coastguard Worker size_t modnamelen;
1229*cc4ad7daSAndroid Build Coastguard Worker int err;
1230*cc4ad7daSAndroid Build Coastguard Worker
1231*cc4ad7daSAndroid Build Coastguard Worker if (!path_ends_with_kmod_ext(path + baselen, namelen))
1232*cc4ad7daSAndroid Build Coastguard Worker return 0;
1233*cc4ad7daSAndroid Build Coastguard Worker
1234*cc4ad7daSAndroid Build Coastguard Worker if (path_to_modname(path, modname, &modnamelen) == NULL) {
1235*cc4ad7daSAndroid Build Coastguard Worker ERR("could not get modname from path %s\n", path);
1236*cc4ad7daSAndroid Build Coastguard Worker return -EINVAL;
1237*cc4ad7daSAndroid Build Coastguard Worker }
1238*cc4ad7daSAndroid Build Coastguard Worker
1239*cc4ad7daSAndroid Build Coastguard Worker relpath = path + depmod->cfg->dirnamelen + 1;
1240*cc4ad7daSAndroid Build Coastguard Worker DBG("try %s (%s)\n", relpath, modname);
1241*cc4ad7daSAndroid Build Coastguard Worker
1242*cc4ad7daSAndroid Build Coastguard Worker mod = hash_find(depmod->modules_by_name, modname);
1243*cc4ad7daSAndroid Build Coastguard Worker if (mod == NULL)
1244*cc4ad7daSAndroid Build Coastguard Worker goto add;
1245*cc4ad7daSAndroid Build Coastguard Worker
1246*cc4ad7daSAndroid Build Coastguard Worker if (depmod_module_is_higher_priority(depmod, mod, baselen,
1247*cc4ad7daSAndroid Build Coastguard Worker namelen, modnamelen, path)) {
1248*cc4ad7daSAndroid Build Coastguard Worker DBG("Ignored lower priority: %s, higher: %s\n",
1249*cc4ad7daSAndroid Build Coastguard Worker path, mod->path);
1250*cc4ad7daSAndroid Build Coastguard Worker return 0;
1251*cc4ad7daSAndroid Build Coastguard Worker }
1252*cc4ad7daSAndroid Build Coastguard Worker
1253*cc4ad7daSAndroid Build Coastguard Worker DBG("Replace lower priority %s with new module %s\n",
1254*cc4ad7daSAndroid Build Coastguard Worker mod->relpath, relpath);
1255*cc4ad7daSAndroid Build Coastguard Worker err = depmod_module_del(depmod, mod);
1256*cc4ad7daSAndroid Build Coastguard Worker if (err < 0) {
1257*cc4ad7daSAndroid Build Coastguard Worker ERR("could not del module %s: %s\n", mod->path, strerror(-err));
1258*cc4ad7daSAndroid Build Coastguard Worker return err;
1259*cc4ad7daSAndroid Build Coastguard Worker }
1260*cc4ad7daSAndroid Build Coastguard Worker
1261*cc4ad7daSAndroid Build Coastguard Worker add:
1262*cc4ad7daSAndroid Build Coastguard Worker err = kmod_module_new_from_path(depmod->ctx, path, &kmod);
1263*cc4ad7daSAndroid Build Coastguard Worker if (err < 0) {
1264*cc4ad7daSAndroid Build Coastguard Worker ERR("could not create module %s: %s\n", path, strerror(-err));
1265*cc4ad7daSAndroid Build Coastguard Worker return err;
1266*cc4ad7daSAndroid Build Coastguard Worker }
1267*cc4ad7daSAndroid Build Coastguard Worker
1268*cc4ad7daSAndroid Build Coastguard Worker err = depmod_module_add(depmod, kmod);
1269*cc4ad7daSAndroid Build Coastguard Worker if (err < 0) {
1270*cc4ad7daSAndroid Build Coastguard Worker ERR("could not add module %s: %s\n",
1271*cc4ad7daSAndroid Build Coastguard Worker path, strerror(-err));
1272*cc4ad7daSAndroid Build Coastguard Worker kmod_module_unref(kmod);
1273*cc4ad7daSAndroid Build Coastguard Worker return err;
1274*cc4ad7daSAndroid Build Coastguard Worker }
1275*cc4ad7daSAndroid Build Coastguard Worker return 0;
1276*cc4ad7daSAndroid Build Coastguard Worker }
1277*cc4ad7daSAndroid Build Coastguard Worker
should_exclude_dir(const struct cfg * cfg,const char * name)1278*cc4ad7daSAndroid Build Coastguard Worker static bool should_exclude_dir(const struct cfg *cfg, const char *name)
1279*cc4ad7daSAndroid Build Coastguard Worker {
1280*cc4ad7daSAndroid Build Coastguard Worker struct cfg_exclude *exc;
1281*cc4ad7daSAndroid Build Coastguard Worker
1282*cc4ad7daSAndroid Build Coastguard Worker if (name[0] == '.' && (name[1] == '\0' ||
1283*cc4ad7daSAndroid Build Coastguard Worker (name[1] == '.' && name[2] == '\0')))
1284*cc4ad7daSAndroid Build Coastguard Worker return true;
1285*cc4ad7daSAndroid Build Coastguard Worker
1286*cc4ad7daSAndroid Build Coastguard Worker if (streq(name, "build") || streq(name, "source"))
1287*cc4ad7daSAndroid Build Coastguard Worker return true;
1288*cc4ad7daSAndroid Build Coastguard Worker
1289*cc4ad7daSAndroid Build Coastguard Worker for (exc = cfg->excludes; exc != NULL; exc = exc->next) {
1290*cc4ad7daSAndroid Build Coastguard Worker if (streq(name, exc->exclude_dir))
1291*cc4ad7daSAndroid Build Coastguard Worker return true;
1292*cc4ad7daSAndroid Build Coastguard Worker }
1293*cc4ad7daSAndroid Build Coastguard Worker
1294*cc4ad7daSAndroid Build Coastguard Worker return false;
1295*cc4ad7daSAndroid Build Coastguard Worker }
1296*cc4ad7daSAndroid Build Coastguard Worker
depmod_modules_search_dir(struct depmod * depmod,DIR * d,size_t baselen,struct scratchbuf * s_path)1297*cc4ad7daSAndroid Build Coastguard Worker static int depmod_modules_search_dir(struct depmod *depmod, DIR *d, size_t baselen, struct scratchbuf *s_path)
1298*cc4ad7daSAndroid Build Coastguard Worker {
1299*cc4ad7daSAndroid Build Coastguard Worker struct dirent *de;
1300*cc4ad7daSAndroid Build Coastguard Worker int err = 0, dfd = dirfd(d);
1301*cc4ad7daSAndroid Build Coastguard Worker char *path;
1302*cc4ad7daSAndroid Build Coastguard Worker
1303*cc4ad7daSAndroid Build Coastguard Worker while ((de = readdir(d)) != NULL) {
1304*cc4ad7daSAndroid Build Coastguard Worker const char *name = de->d_name;
1305*cc4ad7daSAndroid Build Coastguard Worker size_t namelen;
1306*cc4ad7daSAndroid Build Coastguard Worker uint8_t is_dir;
1307*cc4ad7daSAndroid Build Coastguard Worker
1308*cc4ad7daSAndroid Build Coastguard Worker if (should_exclude_dir(depmod->cfg, name))
1309*cc4ad7daSAndroid Build Coastguard Worker continue;
1310*cc4ad7daSAndroid Build Coastguard Worker
1311*cc4ad7daSAndroid Build Coastguard Worker namelen = strlen(name);
1312*cc4ad7daSAndroid Build Coastguard Worker if (scratchbuf_alloc(s_path, baselen + namelen + 2) < 0) {
1313*cc4ad7daSAndroid Build Coastguard Worker err = -ENOMEM;
1314*cc4ad7daSAndroid Build Coastguard Worker ERR("No memory\n");
1315*cc4ad7daSAndroid Build Coastguard Worker continue;
1316*cc4ad7daSAndroid Build Coastguard Worker }
1317*cc4ad7daSAndroid Build Coastguard Worker
1318*cc4ad7daSAndroid Build Coastguard Worker path = scratchbuf_str(s_path);
1319*cc4ad7daSAndroid Build Coastguard Worker memcpy(path + baselen, name, namelen + 1);
1320*cc4ad7daSAndroid Build Coastguard Worker
1321*cc4ad7daSAndroid Build Coastguard Worker if (de->d_type == DT_REG)
1322*cc4ad7daSAndroid Build Coastguard Worker is_dir = 0;
1323*cc4ad7daSAndroid Build Coastguard Worker else if (de->d_type == DT_DIR)
1324*cc4ad7daSAndroid Build Coastguard Worker is_dir = 1;
1325*cc4ad7daSAndroid Build Coastguard Worker else {
1326*cc4ad7daSAndroid Build Coastguard Worker struct stat st;
1327*cc4ad7daSAndroid Build Coastguard Worker if (fstatat(dfd, name, &st, 0) < 0) {
1328*cc4ad7daSAndroid Build Coastguard Worker ERR("fstatat(%d, %s): %m\n", dfd, name);
1329*cc4ad7daSAndroid Build Coastguard Worker continue;
1330*cc4ad7daSAndroid Build Coastguard Worker } else if (S_ISREG(st.st_mode))
1331*cc4ad7daSAndroid Build Coastguard Worker is_dir = 0;
1332*cc4ad7daSAndroid Build Coastguard Worker else if (S_ISDIR(st.st_mode))
1333*cc4ad7daSAndroid Build Coastguard Worker is_dir = 1;
1334*cc4ad7daSAndroid Build Coastguard Worker else {
1335*cc4ad7daSAndroid Build Coastguard Worker ERR("unsupported file type %s: %o\n",
1336*cc4ad7daSAndroid Build Coastguard Worker path, st.st_mode & S_IFMT);
1337*cc4ad7daSAndroid Build Coastguard Worker continue;
1338*cc4ad7daSAndroid Build Coastguard Worker }
1339*cc4ad7daSAndroid Build Coastguard Worker }
1340*cc4ad7daSAndroid Build Coastguard Worker
1341*cc4ad7daSAndroid Build Coastguard Worker if (is_dir) {
1342*cc4ad7daSAndroid Build Coastguard Worker int fd;
1343*cc4ad7daSAndroid Build Coastguard Worker DIR *subdir;
1344*cc4ad7daSAndroid Build Coastguard Worker fd = openat(dfd, name, O_RDONLY);
1345*cc4ad7daSAndroid Build Coastguard Worker if (fd < 0) {
1346*cc4ad7daSAndroid Build Coastguard Worker ERR("openat(%d, %s, O_RDONLY): %m\n",
1347*cc4ad7daSAndroid Build Coastguard Worker dfd, name);
1348*cc4ad7daSAndroid Build Coastguard Worker continue;
1349*cc4ad7daSAndroid Build Coastguard Worker }
1350*cc4ad7daSAndroid Build Coastguard Worker subdir = fdopendir(fd);
1351*cc4ad7daSAndroid Build Coastguard Worker if (subdir == NULL) {
1352*cc4ad7daSAndroid Build Coastguard Worker ERR("fdopendir(%d): %m\n", fd);
1353*cc4ad7daSAndroid Build Coastguard Worker close(fd);
1354*cc4ad7daSAndroid Build Coastguard Worker continue;
1355*cc4ad7daSAndroid Build Coastguard Worker }
1356*cc4ad7daSAndroid Build Coastguard Worker path[baselen + namelen] = '/';
1357*cc4ad7daSAndroid Build Coastguard Worker path[baselen + namelen + 1] = '\0';
1358*cc4ad7daSAndroid Build Coastguard Worker err = depmod_modules_search_dir(depmod, subdir,
1359*cc4ad7daSAndroid Build Coastguard Worker baselen + namelen + 1,
1360*cc4ad7daSAndroid Build Coastguard Worker s_path);
1361*cc4ad7daSAndroid Build Coastguard Worker closedir(subdir);
1362*cc4ad7daSAndroid Build Coastguard Worker } else {
1363*cc4ad7daSAndroid Build Coastguard Worker err = depmod_modules_search_file(depmod, baselen,
1364*cc4ad7daSAndroid Build Coastguard Worker namelen, path);
1365*cc4ad7daSAndroid Build Coastguard Worker }
1366*cc4ad7daSAndroid Build Coastguard Worker
1367*cc4ad7daSAndroid Build Coastguard Worker if (err < 0) {
1368*cc4ad7daSAndroid Build Coastguard Worker path[baselen + namelen] = '\0';
1369*cc4ad7daSAndroid Build Coastguard Worker ERR("failed %s: %s\n", path, strerror(-err));
1370*cc4ad7daSAndroid Build Coastguard Worker err = 0; /* ignore errors */
1371*cc4ad7daSAndroid Build Coastguard Worker }
1372*cc4ad7daSAndroid Build Coastguard Worker }
1373*cc4ad7daSAndroid Build Coastguard Worker return err;
1374*cc4ad7daSAndroid Build Coastguard Worker }
1375*cc4ad7daSAndroid Build Coastguard Worker
depmod_modules_search_path(struct depmod * depmod,const char * path)1376*cc4ad7daSAndroid Build Coastguard Worker static int depmod_modules_search_path(struct depmod *depmod,
1377*cc4ad7daSAndroid Build Coastguard Worker const char *path)
1378*cc4ad7daSAndroid Build Coastguard Worker {
1379*cc4ad7daSAndroid Build Coastguard Worker char buf[256];
1380*cc4ad7daSAndroid Build Coastguard Worker _cleanup_(scratchbuf_release) struct scratchbuf s_path_buf =
1381*cc4ad7daSAndroid Build Coastguard Worker SCRATCHBUF_INITIALIZER(buf);
1382*cc4ad7daSAndroid Build Coastguard Worker char *path_buf;
1383*cc4ad7daSAndroid Build Coastguard Worker DIR *d;
1384*cc4ad7daSAndroid Build Coastguard Worker size_t baselen;
1385*cc4ad7daSAndroid Build Coastguard Worker int err;
1386*cc4ad7daSAndroid Build Coastguard Worker
1387*cc4ad7daSAndroid Build Coastguard Worker d = opendir(path);
1388*cc4ad7daSAndroid Build Coastguard Worker if (d == NULL) {
1389*cc4ad7daSAndroid Build Coastguard Worker err = -errno;
1390*cc4ad7daSAndroid Build Coastguard Worker ERR("could not open directory %s: %m\n", path);
1391*cc4ad7daSAndroid Build Coastguard Worker return err;
1392*cc4ad7daSAndroid Build Coastguard Worker }
1393*cc4ad7daSAndroid Build Coastguard Worker
1394*cc4ad7daSAndroid Build Coastguard Worker baselen = strlen(path);
1395*cc4ad7daSAndroid Build Coastguard Worker
1396*cc4ad7daSAndroid Build Coastguard Worker if (scratchbuf_alloc(&s_path_buf, baselen + 2) < 0) {
1397*cc4ad7daSAndroid Build Coastguard Worker err = -ENOMEM;
1398*cc4ad7daSAndroid Build Coastguard Worker goto out;
1399*cc4ad7daSAndroid Build Coastguard Worker }
1400*cc4ad7daSAndroid Build Coastguard Worker path_buf = scratchbuf_str(&s_path_buf);
1401*cc4ad7daSAndroid Build Coastguard Worker
1402*cc4ad7daSAndroid Build Coastguard Worker memcpy(path_buf, path, baselen);
1403*cc4ad7daSAndroid Build Coastguard Worker path_buf[baselen] = '/';
1404*cc4ad7daSAndroid Build Coastguard Worker baselen++;
1405*cc4ad7daSAndroid Build Coastguard Worker path_buf[baselen] = '\0';
1406*cc4ad7daSAndroid Build Coastguard Worker
1407*cc4ad7daSAndroid Build Coastguard Worker err = depmod_modules_search_dir(depmod, d, baselen, &s_path_buf);
1408*cc4ad7daSAndroid Build Coastguard Worker out:
1409*cc4ad7daSAndroid Build Coastguard Worker closedir(d);
1410*cc4ad7daSAndroid Build Coastguard Worker return err;
1411*cc4ad7daSAndroid Build Coastguard Worker }
1412*cc4ad7daSAndroid Build Coastguard Worker
depmod_modules_search(struct depmod * depmod)1413*cc4ad7daSAndroid Build Coastguard Worker static int depmod_modules_search(struct depmod *depmod)
1414*cc4ad7daSAndroid Build Coastguard Worker {
1415*cc4ad7daSAndroid Build Coastguard Worker int err;
1416*cc4ad7daSAndroid Build Coastguard Worker struct cfg_external *ext;
1417*cc4ad7daSAndroid Build Coastguard Worker
1418*cc4ad7daSAndroid Build Coastguard Worker err = depmod_modules_search_path(depmod, depmod->cfg->dirname);
1419*cc4ad7daSAndroid Build Coastguard Worker if (err < 0)
1420*cc4ad7daSAndroid Build Coastguard Worker return err;
1421*cc4ad7daSAndroid Build Coastguard Worker
1422*cc4ad7daSAndroid Build Coastguard Worker for (ext = depmod->cfg->externals; ext != NULL; ext = ext->next) {
1423*cc4ad7daSAndroid Build Coastguard Worker err = depmod_modules_search_path(depmod, ext->path);
1424*cc4ad7daSAndroid Build Coastguard Worker if (err < 0 && err == -ENOENT)
1425*cc4ad7daSAndroid Build Coastguard Worker /* ignore external dir absense */
1426*cc4ad7daSAndroid Build Coastguard Worker continue;
1427*cc4ad7daSAndroid Build Coastguard Worker }
1428*cc4ad7daSAndroid Build Coastguard Worker
1429*cc4ad7daSAndroid Build Coastguard Worker return 0;
1430*cc4ad7daSAndroid Build Coastguard Worker }
1431*cc4ad7daSAndroid Build Coastguard Worker
mod_cmp(const void * pa,const void * pb)1432*cc4ad7daSAndroid Build Coastguard Worker static int mod_cmp(const void *pa, const void *pb) {
1433*cc4ad7daSAndroid Build Coastguard Worker const struct mod *a = *(const struct mod **)pa;
1434*cc4ad7daSAndroid Build Coastguard Worker const struct mod *b = *(const struct mod **)pb;
1435*cc4ad7daSAndroid Build Coastguard Worker return a->sort_idx - b->sort_idx;
1436*cc4ad7daSAndroid Build Coastguard Worker }
1437*cc4ad7daSAndroid Build Coastguard Worker
depmod_modules_build_array(struct depmod * depmod)1438*cc4ad7daSAndroid Build Coastguard Worker static int depmod_modules_build_array(struct depmod *depmod)
1439*cc4ad7daSAndroid Build Coastguard Worker {
1440*cc4ad7daSAndroid Build Coastguard Worker struct hash_iter module_iter;
1441*cc4ad7daSAndroid Build Coastguard Worker const void *v;
1442*cc4ad7daSAndroid Build Coastguard Worker int err;
1443*cc4ad7daSAndroid Build Coastguard Worker
1444*cc4ad7daSAndroid Build Coastguard Worker hash_iter_init(depmod->modules_by_name, &module_iter);
1445*cc4ad7daSAndroid Build Coastguard Worker while (hash_iter_next(&module_iter, NULL, &v)) {
1446*cc4ad7daSAndroid Build Coastguard Worker struct mod *mod = (struct mod *) v;
1447*cc4ad7daSAndroid Build Coastguard Worker mod->idx = depmod->modules.count;
1448*cc4ad7daSAndroid Build Coastguard Worker err = array_append(&depmod->modules, mod);
1449*cc4ad7daSAndroid Build Coastguard Worker if (err < 0)
1450*cc4ad7daSAndroid Build Coastguard Worker return err;
1451*cc4ad7daSAndroid Build Coastguard Worker }
1452*cc4ad7daSAndroid Build Coastguard Worker
1453*cc4ad7daSAndroid Build Coastguard Worker return 0;
1454*cc4ad7daSAndroid Build Coastguard Worker }
1455*cc4ad7daSAndroid Build Coastguard Worker
dfdopen(const char * dname,const char * filename,int flags,const char * mode)1456*cc4ad7daSAndroid Build Coastguard Worker static FILE *dfdopen(const char *dname, const char *filename, int flags,
1457*cc4ad7daSAndroid Build Coastguard Worker const char *mode)
1458*cc4ad7daSAndroid Build Coastguard Worker {
1459*cc4ad7daSAndroid Build Coastguard Worker int fd, dfd;
1460*cc4ad7daSAndroid Build Coastguard Worker FILE *ret;
1461*cc4ad7daSAndroid Build Coastguard Worker
1462*cc4ad7daSAndroid Build Coastguard Worker dfd = open(dname, O_RDONLY);
1463*cc4ad7daSAndroid Build Coastguard Worker if (dfd < 0) {
1464*cc4ad7daSAndroid Build Coastguard Worker WRN("could not open directory %s: %m\n", dname);
1465*cc4ad7daSAndroid Build Coastguard Worker return NULL;
1466*cc4ad7daSAndroid Build Coastguard Worker }
1467*cc4ad7daSAndroid Build Coastguard Worker
1468*cc4ad7daSAndroid Build Coastguard Worker fd = openat(dfd, filename, flags);
1469*cc4ad7daSAndroid Build Coastguard Worker if (fd < 0) {
1470*cc4ad7daSAndroid Build Coastguard Worker WRN("could not open %s at %s: %m\n", filename, dname);
1471*cc4ad7daSAndroid Build Coastguard Worker ret = NULL;
1472*cc4ad7daSAndroid Build Coastguard Worker } else {
1473*cc4ad7daSAndroid Build Coastguard Worker ret = fdopen(fd, mode);
1474*cc4ad7daSAndroid Build Coastguard Worker if (!ret) {
1475*cc4ad7daSAndroid Build Coastguard Worker WRN("could not associate stream with %s: %m\n", filename);
1476*cc4ad7daSAndroid Build Coastguard Worker close(fd);
1477*cc4ad7daSAndroid Build Coastguard Worker }
1478*cc4ad7daSAndroid Build Coastguard Worker }
1479*cc4ad7daSAndroid Build Coastguard Worker close(dfd);
1480*cc4ad7daSAndroid Build Coastguard Worker return ret;
1481*cc4ad7daSAndroid Build Coastguard Worker }
1482*cc4ad7daSAndroid Build Coastguard Worker
1483*cc4ad7daSAndroid Build Coastguard Worker
1484*cc4ad7daSAndroid Build Coastguard Worker
depmod_modules_sort(struct depmod * depmod)1485*cc4ad7daSAndroid Build Coastguard Worker static void depmod_modules_sort(struct depmod *depmod)
1486*cc4ad7daSAndroid Build Coastguard Worker {
1487*cc4ad7daSAndroid Build Coastguard Worker char line[PATH_MAX];
1488*cc4ad7daSAndroid Build Coastguard Worker const char *order_file = "modules.order";
1489*cc4ad7daSAndroid Build Coastguard Worker FILE *fp;
1490*cc4ad7daSAndroid Build Coastguard Worker unsigned idx = 0, total = 0;
1491*cc4ad7daSAndroid Build Coastguard Worker
1492*cc4ad7daSAndroid Build Coastguard Worker fp = dfdopen(depmod->cfg->dirname, order_file, O_RDONLY, "r");
1493*cc4ad7daSAndroid Build Coastguard Worker if (fp == NULL)
1494*cc4ad7daSAndroid Build Coastguard Worker return;
1495*cc4ad7daSAndroid Build Coastguard Worker
1496*cc4ad7daSAndroid Build Coastguard Worker while (fgets(line, sizeof(line), fp) != NULL) {
1497*cc4ad7daSAndroid Build Coastguard Worker size_t len = strlen(line);
1498*cc4ad7daSAndroid Build Coastguard Worker idx++;
1499*cc4ad7daSAndroid Build Coastguard Worker if (len == 0)
1500*cc4ad7daSAndroid Build Coastguard Worker continue;
1501*cc4ad7daSAndroid Build Coastguard Worker if (line[len - 1] != '\n') {
1502*cc4ad7daSAndroid Build Coastguard Worker ERR("%s/%s:%u corrupted line misses '\\n'\n",
1503*cc4ad7daSAndroid Build Coastguard Worker depmod->cfg->dirname, order_file, idx);
1504*cc4ad7daSAndroid Build Coastguard Worker goto corrupted;
1505*cc4ad7daSAndroid Build Coastguard Worker }
1506*cc4ad7daSAndroid Build Coastguard Worker }
1507*cc4ad7daSAndroid Build Coastguard Worker total = idx + 1;
1508*cc4ad7daSAndroid Build Coastguard Worker idx = 0;
1509*cc4ad7daSAndroid Build Coastguard Worker fseek(fp, 0, SEEK_SET);
1510*cc4ad7daSAndroid Build Coastguard Worker while (fgets(line, sizeof(line), fp) != NULL) {
1511*cc4ad7daSAndroid Build Coastguard Worker size_t len = strlen(line);
1512*cc4ad7daSAndroid Build Coastguard Worker struct mod *mod;
1513*cc4ad7daSAndroid Build Coastguard Worker
1514*cc4ad7daSAndroid Build Coastguard Worker idx++;
1515*cc4ad7daSAndroid Build Coastguard Worker if (len == 0)
1516*cc4ad7daSAndroid Build Coastguard Worker continue;
1517*cc4ad7daSAndroid Build Coastguard Worker line[len - 1] = '\0';
1518*cc4ad7daSAndroid Build Coastguard Worker
1519*cc4ad7daSAndroid Build Coastguard Worker mod = hash_find(depmod->modules_by_uncrelpath, line);
1520*cc4ad7daSAndroid Build Coastguard Worker if (mod == NULL)
1521*cc4ad7daSAndroid Build Coastguard Worker continue;
1522*cc4ad7daSAndroid Build Coastguard Worker mod->sort_idx = idx - total;
1523*cc4ad7daSAndroid Build Coastguard Worker }
1524*cc4ad7daSAndroid Build Coastguard Worker
1525*cc4ad7daSAndroid Build Coastguard Worker array_sort(&depmod->modules, mod_cmp);
1526*cc4ad7daSAndroid Build Coastguard Worker for (idx = 0; idx < depmod->modules.count; idx++) {
1527*cc4ad7daSAndroid Build Coastguard Worker struct mod *m = depmod->modules.array[idx];
1528*cc4ad7daSAndroid Build Coastguard Worker m->idx = idx;
1529*cc4ad7daSAndroid Build Coastguard Worker }
1530*cc4ad7daSAndroid Build Coastguard Worker
1531*cc4ad7daSAndroid Build Coastguard Worker corrupted:
1532*cc4ad7daSAndroid Build Coastguard Worker fclose(fp);
1533*cc4ad7daSAndroid Build Coastguard Worker }
1534*cc4ad7daSAndroid Build Coastguard Worker
depmod_symbol_add(struct depmod * depmod,const char * name,bool prefix_skipped,uint64_t crc,const struct mod * owner)1535*cc4ad7daSAndroid Build Coastguard Worker static int depmod_symbol_add(struct depmod *depmod, const char *name,
1536*cc4ad7daSAndroid Build Coastguard Worker bool prefix_skipped, uint64_t crc,
1537*cc4ad7daSAndroid Build Coastguard Worker const struct mod *owner)
1538*cc4ad7daSAndroid Build Coastguard Worker {
1539*cc4ad7daSAndroid Build Coastguard Worker size_t namelen;
1540*cc4ad7daSAndroid Build Coastguard Worker int err;
1541*cc4ad7daSAndroid Build Coastguard Worker struct symbol *sym;
1542*cc4ad7daSAndroid Build Coastguard Worker
1543*cc4ad7daSAndroid Build Coastguard Worker if (!prefix_skipped && (name[0] == depmod->cfg->sym_prefix))
1544*cc4ad7daSAndroid Build Coastguard Worker name++;
1545*cc4ad7daSAndroid Build Coastguard Worker
1546*cc4ad7daSAndroid Build Coastguard Worker namelen = strlen(name) + 1;
1547*cc4ad7daSAndroid Build Coastguard Worker sym = malloc(sizeof(struct symbol) + namelen);
1548*cc4ad7daSAndroid Build Coastguard Worker if (sym == NULL)
1549*cc4ad7daSAndroid Build Coastguard Worker return -ENOMEM;
1550*cc4ad7daSAndroid Build Coastguard Worker
1551*cc4ad7daSAndroid Build Coastguard Worker sym->owner = (struct mod *)owner;
1552*cc4ad7daSAndroid Build Coastguard Worker sym->crc = crc;
1553*cc4ad7daSAndroid Build Coastguard Worker memcpy(sym->name, name, namelen);
1554*cc4ad7daSAndroid Build Coastguard Worker
1555*cc4ad7daSAndroid Build Coastguard Worker err = hash_add(depmod->symbols, sym->name, sym);
1556*cc4ad7daSAndroid Build Coastguard Worker if (err < 0) {
1557*cc4ad7daSAndroid Build Coastguard Worker free(sym);
1558*cc4ad7daSAndroid Build Coastguard Worker return err;
1559*cc4ad7daSAndroid Build Coastguard Worker }
1560*cc4ad7daSAndroid Build Coastguard Worker
1561*cc4ad7daSAndroid Build Coastguard Worker DBG("add %p sym=%s, owner=%p %s\n", sym, sym->name, owner,
1562*cc4ad7daSAndroid Build Coastguard Worker owner != NULL ? owner->path : "");
1563*cc4ad7daSAndroid Build Coastguard Worker
1564*cc4ad7daSAndroid Build Coastguard Worker return 0;
1565*cc4ad7daSAndroid Build Coastguard Worker }
1566*cc4ad7daSAndroid Build Coastguard Worker
depmod_symbol_find(const struct depmod * depmod,const char * name)1567*cc4ad7daSAndroid Build Coastguard Worker static struct symbol *depmod_symbol_find(const struct depmod *depmod,
1568*cc4ad7daSAndroid Build Coastguard Worker const char *name)
1569*cc4ad7daSAndroid Build Coastguard Worker {
1570*cc4ad7daSAndroid Build Coastguard Worker if (name[0] == '.') /* PPC64 needs this: .foo == foo */
1571*cc4ad7daSAndroid Build Coastguard Worker name++;
1572*cc4ad7daSAndroid Build Coastguard Worker if (name[0] == depmod->cfg->sym_prefix)
1573*cc4ad7daSAndroid Build Coastguard Worker name++;
1574*cc4ad7daSAndroid Build Coastguard Worker return hash_find(depmod->symbols, name);
1575*cc4ad7daSAndroid Build Coastguard Worker }
1576*cc4ad7daSAndroid Build Coastguard Worker
depmod_load_modules(struct depmod * depmod)1577*cc4ad7daSAndroid Build Coastguard Worker static int depmod_load_modules(struct depmod *depmod)
1578*cc4ad7daSAndroid Build Coastguard Worker {
1579*cc4ad7daSAndroid Build Coastguard Worker struct mod **itr, **itr_end;
1580*cc4ad7daSAndroid Build Coastguard Worker
1581*cc4ad7daSAndroid Build Coastguard Worker DBG("load symbols (%zd modules)\n", depmod->modules.count);
1582*cc4ad7daSAndroid Build Coastguard Worker
1583*cc4ad7daSAndroid Build Coastguard Worker itr = (struct mod **)depmod->modules.array;
1584*cc4ad7daSAndroid Build Coastguard Worker itr_end = itr + depmod->modules.count;
1585*cc4ad7daSAndroid Build Coastguard Worker for (; itr < itr_end; itr++) {
1586*cc4ad7daSAndroid Build Coastguard Worker struct mod *mod = *itr;
1587*cc4ad7daSAndroid Build Coastguard Worker struct kmod_list *l, *list = NULL;
1588*cc4ad7daSAndroid Build Coastguard Worker int err = kmod_module_get_symbols(mod->kmod, &list);
1589*cc4ad7daSAndroid Build Coastguard Worker if (err < 0) {
1590*cc4ad7daSAndroid Build Coastguard Worker if (err == -ENODATA)
1591*cc4ad7daSAndroid Build Coastguard Worker DBG("ignoring %s: no symbols\n", mod->path);
1592*cc4ad7daSAndroid Build Coastguard Worker else
1593*cc4ad7daSAndroid Build Coastguard Worker ERR("failed to load symbols from %s: %s\n",
1594*cc4ad7daSAndroid Build Coastguard Worker mod->path, strerror(-err));
1595*cc4ad7daSAndroid Build Coastguard Worker goto load_info;
1596*cc4ad7daSAndroid Build Coastguard Worker }
1597*cc4ad7daSAndroid Build Coastguard Worker kmod_list_foreach(l, list) {
1598*cc4ad7daSAndroid Build Coastguard Worker const char *name = kmod_module_symbol_get_symbol(l);
1599*cc4ad7daSAndroid Build Coastguard Worker uint64_t crc = kmod_module_symbol_get_crc(l);
1600*cc4ad7daSAndroid Build Coastguard Worker depmod_symbol_add(depmod, name, false, crc, mod);
1601*cc4ad7daSAndroid Build Coastguard Worker }
1602*cc4ad7daSAndroid Build Coastguard Worker kmod_module_symbols_free_list(list);
1603*cc4ad7daSAndroid Build Coastguard Worker
1604*cc4ad7daSAndroid Build Coastguard Worker load_info:
1605*cc4ad7daSAndroid Build Coastguard Worker kmod_module_get_info(mod->kmod, &mod->info_list);
1606*cc4ad7daSAndroid Build Coastguard Worker kmod_module_get_dependency_symbols(mod->kmod,
1607*cc4ad7daSAndroid Build Coastguard Worker &mod->dep_sym_list);
1608*cc4ad7daSAndroid Build Coastguard Worker kmod_module_unref(mod->kmod);
1609*cc4ad7daSAndroid Build Coastguard Worker mod->kmod = NULL;
1610*cc4ad7daSAndroid Build Coastguard Worker }
1611*cc4ad7daSAndroid Build Coastguard Worker
1612*cc4ad7daSAndroid Build Coastguard Worker DBG("loaded symbols (%zd modules, %u symbols)\n",
1613*cc4ad7daSAndroid Build Coastguard Worker depmod->modules.count, hash_get_count(depmod->symbols));
1614*cc4ad7daSAndroid Build Coastguard Worker
1615*cc4ad7daSAndroid Build Coastguard Worker return 0;
1616*cc4ad7daSAndroid Build Coastguard Worker }
1617*cc4ad7daSAndroid Build Coastguard Worker
depmod_load_module_dependencies(struct depmod * depmod,struct mod * mod)1618*cc4ad7daSAndroid Build Coastguard Worker static int depmod_load_module_dependencies(struct depmod *depmod, struct mod *mod)
1619*cc4ad7daSAndroid Build Coastguard Worker {
1620*cc4ad7daSAndroid Build Coastguard Worker const struct cfg *cfg = depmod->cfg;
1621*cc4ad7daSAndroid Build Coastguard Worker struct kmod_list *l;
1622*cc4ad7daSAndroid Build Coastguard Worker
1623*cc4ad7daSAndroid Build Coastguard Worker DBG("do dependencies of %s\n", mod->path);
1624*cc4ad7daSAndroid Build Coastguard Worker kmod_list_foreach(l, mod->dep_sym_list) {
1625*cc4ad7daSAndroid Build Coastguard Worker const char *name = kmod_module_dependency_symbol_get_symbol(l);
1626*cc4ad7daSAndroid Build Coastguard Worker uint64_t crc = kmod_module_dependency_symbol_get_crc(l);
1627*cc4ad7daSAndroid Build Coastguard Worker int bindtype = kmod_module_dependency_symbol_get_bind(l);
1628*cc4ad7daSAndroid Build Coastguard Worker struct symbol *sym = depmod_symbol_find(depmod, name);
1629*cc4ad7daSAndroid Build Coastguard Worker uint8_t is_weak = bindtype == KMOD_SYMBOL_WEAK;
1630*cc4ad7daSAndroid Build Coastguard Worker
1631*cc4ad7daSAndroid Build Coastguard Worker if (sym == NULL) {
1632*cc4ad7daSAndroid Build Coastguard Worker DBG("%s needs (%c) unknown symbol %s\n",
1633*cc4ad7daSAndroid Build Coastguard Worker mod->path, bindtype, name);
1634*cc4ad7daSAndroid Build Coastguard Worker if (cfg->print_unknown && !is_weak)
1635*cc4ad7daSAndroid Build Coastguard Worker WRN("%s needs unknown symbol %s\n",
1636*cc4ad7daSAndroid Build Coastguard Worker mod->path, name);
1637*cc4ad7daSAndroid Build Coastguard Worker continue;
1638*cc4ad7daSAndroid Build Coastguard Worker }
1639*cc4ad7daSAndroid Build Coastguard Worker
1640*cc4ad7daSAndroid Build Coastguard Worker if (cfg->check_symvers && sym->crc != crc && !is_weak) {
1641*cc4ad7daSAndroid Build Coastguard Worker DBG("symbol %s (%#"PRIx64") module %s (%#"PRIx64")\n",
1642*cc4ad7daSAndroid Build Coastguard Worker sym->name, sym->crc, mod->path, crc);
1643*cc4ad7daSAndroid Build Coastguard Worker if (cfg->print_unknown)
1644*cc4ad7daSAndroid Build Coastguard Worker WRN("%s disagrees about version of symbol %s\n",
1645*cc4ad7daSAndroid Build Coastguard Worker mod->path, name);
1646*cc4ad7daSAndroid Build Coastguard Worker }
1647*cc4ad7daSAndroid Build Coastguard Worker
1648*cc4ad7daSAndroid Build Coastguard Worker mod_add_dependency(mod, sym);
1649*cc4ad7daSAndroid Build Coastguard Worker }
1650*cc4ad7daSAndroid Build Coastguard Worker
1651*cc4ad7daSAndroid Build Coastguard Worker return 0;
1652*cc4ad7daSAndroid Build Coastguard Worker }
1653*cc4ad7daSAndroid Build Coastguard Worker
depmod_load_dependencies(struct depmod * depmod)1654*cc4ad7daSAndroid Build Coastguard Worker static int depmod_load_dependencies(struct depmod *depmod)
1655*cc4ad7daSAndroid Build Coastguard Worker {
1656*cc4ad7daSAndroid Build Coastguard Worker struct mod **itr, **itr_end;
1657*cc4ad7daSAndroid Build Coastguard Worker
1658*cc4ad7daSAndroid Build Coastguard Worker DBG("load dependencies (%zd modules, %u symbols)\n",
1659*cc4ad7daSAndroid Build Coastguard Worker depmod->modules.count, hash_get_count(depmod->symbols));
1660*cc4ad7daSAndroid Build Coastguard Worker
1661*cc4ad7daSAndroid Build Coastguard Worker itr = (struct mod **)depmod->modules.array;
1662*cc4ad7daSAndroid Build Coastguard Worker itr_end = itr + depmod->modules.count;
1663*cc4ad7daSAndroid Build Coastguard Worker for (; itr < itr_end; itr++) {
1664*cc4ad7daSAndroid Build Coastguard Worker struct mod *mod = *itr;
1665*cc4ad7daSAndroid Build Coastguard Worker
1666*cc4ad7daSAndroid Build Coastguard Worker if (mod->dep_sym_list == NULL) {
1667*cc4ad7daSAndroid Build Coastguard Worker DBG("ignoring %s: no dependency symbols\n", mod->path);
1668*cc4ad7daSAndroid Build Coastguard Worker continue;
1669*cc4ad7daSAndroid Build Coastguard Worker }
1670*cc4ad7daSAndroid Build Coastguard Worker
1671*cc4ad7daSAndroid Build Coastguard Worker depmod_load_module_dependencies(depmod, mod);
1672*cc4ad7daSAndroid Build Coastguard Worker }
1673*cc4ad7daSAndroid Build Coastguard Worker
1674*cc4ad7daSAndroid Build Coastguard Worker DBG("loaded dependencies (%zd modules, %u symbols)\n",
1675*cc4ad7daSAndroid Build Coastguard Worker depmod->modules.count, hash_get_count(depmod->symbols));
1676*cc4ad7daSAndroid Build Coastguard Worker
1677*cc4ad7daSAndroid Build Coastguard Worker return 0;
1678*cc4ad7daSAndroid Build Coastguard Worker }
1679*cc4ad7daSAndroid Build Coastguard Worker
dep_cmp(const void * pa,const void * pb)1680*cc4ad7daSAndroid Build Coastguard Worker static int dep_cmp(const void *pa, const void *pb)
1681*cc4ad7daSAndroid Build Coastguard Worker {
1682*cc4ad7daSAndroid Build Coastguard Worker const struct mod *a = *(const struct mod **)pa;
1683*cc4ad7daSAndroid Build Coastguard Worker const struct mod *b = *(const struct mod **)pb;
1684*cc4ad7daSAndroid Build Coastguard Worker return a->dep_sort_idx - b->dep_sort_idx;
1685*cc4ad7daSAndroid Build Coastguard Worker }
1686*cc4ad7daSAndroid Build Coastguard Worker
depmod_sort_dependencies(struct depmod * depmod)1687*cc4ad7daSAndroid Build Coastguard Worker static void depmod_sort_dependencies(struct depmod *depmod)
1688*cc4ad7daSAndroid Build Coastguard Worker {
1689*cc4ad7daSAndroid Build Coastguard Worker struct mod **itr, **itr_end;
1690*cc4ad7daSAndroid Build Coastguard Worker itr = (struct mod **)depmod->modules.array;
1691*cc4ad7daSAndroid Build Coastguard Worker itr_end = itr + depmod->modules.count;
1692*cc4ad7daSAndroid Build Coastguard Worker for (; itr < itr_end; itr++) {
1693*cc4ad7daSAndroid Build Coastguard Worker struct mod *m = *itr;
1694*cc4ad7daSAndroid Build Coastguard Worker if (m->deps.count > 1)
1695*cc4ad7daSAndroid Build Coastguard Worker array_sort(&m->deps, dep_cmp);
1696*cc4ad7daSAndroid Build Coastguard Worker }
1697*cc4ad7daSAndroid Build Coastguard Worker }
1698*cc4ad7daSAndroid Build Coastguard Worker
1699*cc4ad7daSAndroid Build Coastguard Worker struct vertex {
1700*cc4ad7daSAndroid Build Coastguard Worker struct vertex *parent;
1701*cc4ad7daSAndroid Build Coastguard Worker struct mod *mod;
1702*cc4ad7daSAndroid Build Coastguard Worker };
1703*cc4ad7daSAndroid Build Coastguard Worker
vertex_new(struct mod * mod,struct vertex * parent)1704*cc4ad7daSAndroid Build Coastguard Worker static struct vertex *vertex_new(struct mod *mod, struct vertex *parent)
1705*cc4ad7daSAndroid Build Coastguard Worker {
1706*cc4ad7daSAndroid Build Coastguard Worker struct vertex *v;
1707*cc4ad7daSAndroid Build Coastguard Worker
1708*cc4ad7daSAndroid Build Coastguard Worker v = malloc(sizeof(*v));
1709*cc4ad7daSAndroid Build Coastguard Worker if (v == NULL)
1710*cc4ad7daSAndroid Build Coastguard Worker return NULL;
1711*cc4ad7daSAndroid Build Coastguard Worker
1712*cc4ad7daSAndroid Build Coastguard Worker v->parent = parent;
1713*cc4ad7daSAndroid Build Coastguard Worker v->mod = mod;
1714*cc4ad7daSAndroid Build Coastguard Worker return v;
1715*cc4ad7daSAndroid Build Coastguard Worker }
1716*cc4ad7daSAndroid Build Coastguard Worker
depmod_list_remove_data(struct kmod_list ** list,void * data)1717*cc4ad7daSAndroid Build Coastguard Worker static void depmod_list_remove_data(struct kmod_list **list, void *data)
1718*cc4ad7daSAndroid Build Coastguard Worker {
1719*cc4ad7daSAndroid Build Coastguard Worker struct kmod_list *l;
1720*cc4ad7daSAndroid Build Coastguard Worker
1721*cc4ad7daSAndroid Build Coastguard Worker l = kmod_list_remove_data(*list, data);
1722*cc4ad7daSAndroid Build Coastguard Worker *list = l;
1723*cc4ad7daSAndroid Build Coastguard Worker }
1724*cc4ad7daSAndroid Build Coastguard Worker
depmod_report_one_cycle(struct depmod * depmod,struct vertex * vertex,struct kmod_list ** roots,struct hash * loop_set)1725*cc4ad7daSAndroid Build Coastguard Worker static int depmod_report_one_cycle(struct depmod *depmod,
1726*cc4ad7daSAndroid Build Coastguard Worker struct vertex *vertex,
1727*cc4ad7daSAndroid Build Coastguard Worker struct kmod_list **roots,
1728*cc4ad7daSAndroid Build Coastguard Worker struct hash *loop_set)
1729*cc4ad7daSAndroid Build Coastguard Worker {
1730*cc4ad7daSAndroid Build Coastguard Worker const char sep[] = " -> ";
1731*cc4ad7daSAndroid Build Coastguard Worker size_t sz;
1732*cc4ad7daSAndroid Build Coastguard Worker char *buf;
1733*cc4ad7daSAndroid Build Coastguard Worker struct array reverse;
1734*cc4ad7daSAndroid Build Coastguard Worker int i;
1735*cc4ad7daSAndroid Build Coastguard Worker int n;
1736*cc4ad7daSAndroid Build Coastguard Worker struct vertex *v;
1737*cc4ad7daSAndroid Build Coastguard Worker int rc;
1738*cc4ad7daSAndroid Build Coastguard Worker
1739*cc4ad7daSAndroid Build Coastguard Worker array_init(&reverse, 3);
1740*cc4ad7daSAndroid Build Coastguard Worker
1741*cc4ad7daSAndroid Build Coastguard Worker sz = 0;
1742*cc4ad7daSAndroid Build Coastguard Worker for (v = vertex->parent, n = 0;
1743*cc4ad7daSAndroid Build Coastguard Worker v != NULL;
1744*cc4ad7daSAndroid Build Coastguard Worker v = v->parent, n++) {
1745*cc4ad7daSAndroid Build Coastguard Worker
1746*cc4ad7daSAndroid Build Coastguard Worker sz += v->mod->modnamesz - 1;
1747*cc4ad7daSAndroid Build Coastguard Worker array_append(&reverse, v);
1748*cc4ad7daSAndroid Build Coastguard Worker rc = hash_add(loop_set, v->mod->modname, NULL);
1749*cc4ad7daSAndroid Build Coastguard Worker if (rc != 0)
1750*cc4ad7daSAndroid Build Coastguard Worker return rc;
1751*cc4ad7daSAndroid Build Coastguard Worker /* the hash will be freed where created */
1752*cc4ad7daSAndroid Build Coastguard Worker }
1753*cc4ad7daSAndroid Build Coastguard Worker sz += vertex->mod->modnamesz - 1;
1754*cc4ad7daSAndroid Build Coastguard Worker
1755*cc4ad7daSAndroid Build Coastguard Worker buf = malloc(sz + n * strlen(sep) + 1);
1756*cc4ad7daSAndroid Build Coastguard Worker
1757*cc4ad7daSAndroid Build Coastguard Worker sz = 0;
1758*cc4ad7daSAndroid Build Coastguard Worker for (i = reverse.count - 1; i >= 0; i--) {
1759*cc4ad7daSAndroid Build Coastguard Worker size_t len;
1760*cc4ad7daSAndroid Build Coastguard Worker
1761*cc4ad7daSAndroid Build Coastguard Worker v = reverse.array[i];
1762*cc4ad7daSAndroid Build Coastguard Worker
1763*cc4ad7daSAndroid Build Coastguard Worker len = v->mod->modnamesz - 1;
1764*cc4ad7daSAndroid Build Coastguard Worker memcpy(buf + sz, v->mod->modname, len);
1765*cc4ad7daSAndroid Build Coastguard Worker sz += len;
1766*cc4ad7daSAndroid Build Coastguard Worker strcpy(buf + sz, sep);
1767*cc4ad7daSAndroid Build Coastguard Worker sz += strlen(sep);
1768*cc4ad7daSAndroid Build Coastguard Worker
1769*cc4ad7daSAndroid Build Coastguard Worker depmod_list_remove_data(roots, v->mod);
1770*cc4ad7daSAndroid Build Coastguard Worker }
1771*cc4ad7daSAndroid Build Coastguard Worker strcpy(buf + sz, vertex->mod->modname);
1772*cc4ad7daSAndroid Build Coastguard Worker ERR("Cycle detected: %s\n", buf);
1773*cc4ad7daSAndroid Build Coastguard Worker
1774*cc4ad7daSAndroid Build Coastguard Worker free(buf);
1775*cc4ad7daSAndroid Build Coastguard Worker array_free_array(&reverse);
1776*cc4ad7daSAndroid Build Coastguard Worker
1777*cc4ad7daSAndroid Build Coastguard Worker return 0;
1778*cc4ad7daSAndroid Build Coastguard Worker }
1779*cc4ad7daSAndroid Build Coastguard Worker
depmod_report_cycles_from_root(struct depmod * depmod,struct mod * root_mod,struct kmod_list ** roots,void ** stack,size_t stack_size,struct hash * loop_set)1780*cc4ad7daSAndroid Build Coastguard Worker static int depmod_report_cycles_from_root(struct depmod *depmod,
1781*cc4ad7daSAndroid Build Coastguard Worker struct mod *root_mod,
1782*cc4ad7daSAndroid Build Coastguard Worker struct kmod_list **roots,
1783*cc4ad7daSAndroid Build Coastguard Worker void **stack,
1784*cc4ad7daSAndroid Build Coastguard Worker size_t stack_size,
1785*cc4ad7daSAndroid Build Coastguard Worker struct hash *loop_set)
1786*cc4ad7daSAndroid Build Coastguard Worker {
1787*cc4ad7daSAndroid Build Coastguard Worker struct kmod_list *free_list = NULL; /* struct vertex */
1788*cc4ad7daSAndroid Build Coastguard Worker struct kmod_list *l;
1789*cc4ad7daSAndroid Build Coastguard Worker struct vertex *root;
1790*cc4ad7daSAndroid Build Coastguard Worker struct vertex *vertex;
1791*cc4ad7daSAndroid Build Coastguard Worker struct vertex *v;
1792*cc4ad7daSAndroid Build Coastguard Worker struct mod *m;
1793*cc4ad7daSAndroid Build Coastguard Worker struct mod **itr, **itr_end;
1794*cc4ad7daSAndroid Build Coastguard Worker size_t is;
1795*cc4ad7daSAndroid Build Coastguard Worker int ret = -ENOMEM;
1796*cc4ad7daSAndroid Build Coastguard Worker
1797*cc4ad7daSAndroid Build Coastguard Worker root = vertex_new(root_mod, NULL);
1798*cc4ad7daSAndroid Build Coastguard Worker if (root == NULL) {
1799*cc4ad7daSAndroid Build Coastguard Worker ERR("No memory to report cycles\n");
1800*cc4ad7daSAndroid Build Coastguard Worker goto out;
1801*cc4ad7daSAndroid Build Coastguard Worker }
1802*cc4ad7daSAndroid Build Coastguard Worker
1803*cc4ad7daSAndroid Build Coastguard Worker l = kmod_list_append(free_list, root);
1804*cc4ad7daSAndroid Build Coastguard Worker if (l == NULL) {
1805*cc4ad7daSAndroid Build Coastguard Worker ERR("No memory to report cycles\n");
1806*cc4ad7daSAndroid Build Coastguard Worker goto out;
1807*cc4ad7daSAndroid Build Coastguard Worker }
1808*cc4ad7daSAndroid Build Coastguard Worker free_list = l;
1809*cc4ad7daSAndroid Build Coastguard Worker
1810*cc4ad7daSAndroid Build Coastguard Worker is = 0;
1811*cc4ad7daSAndroid Build Coastguard Worker stack[is++] = (void *)root;
1812*cc4ad7daSAndroid Build Coastguard Worker
1813*cc4ad7daSAndroid Build Coastguard Worker while (is > 0) {
1814*cc4ad7daSAndroid Build Coastguard Worker vertex = stack[--is];
1815*cc4ad7daSAndroid Build Coastguard Worker m = vertex->mod;
1816*cc4ad7daSAndroid Build Coastguard Worker /*
1817*cc4ad7daSAndroid Build Coastguard Worker * because of the topological sort we can start only
1818*cc4ad7daSAndroid Build Coastguard Worker * from part of a loop or from a branch after a loop
1819*cc4ad7daSAndroid Build Coastguard Worker */
1820*cc4ad7daSAndroid Build Coastguard Worker if (m->visited && m == root->mod) {
1821*cc4ad7daSAndroid Build Coastguard Worker int rc;
1822*cc4ad7daSAndroid Build Coastguard Worker rc = depmod_report_one_cycle(depmod, vertex,
1823*cc4ad7daSAndroid Build Coastguard Worker roots, loop_set);
1824*cc4ad7daSAndroid Build Coastguard Worker if (rc != 0) {
1825*cc4ad7daSAndroid Build Coastguard Worker ret = rc;
1826*cc4ad7daSAndroid Build Coastguard Worker goto out;
1827*cc4ad7daSAndroid Build Coastguard Worker }
1828*cc4ad7daSAndroid Build Coastguard Worker continue;
1829*cc4ad7daSAndroid Build Coastguard Worker }
1830*cc4ad7daSAndroid Build Coastguard Worker
1831*cc4ad7daSAndroid Build Coastguard Worker m->visited = true;
1832*cc4ad7daSAndroid Build Coastguard Worker if (m->deps.count == 0) {
1833*cc4ad7daSAndroid Build Coastguard Worker /*
1834*cc4ad7daSAndroid Build Coastguard Worker * boundary condition: if there is more than one
1835*cc4ad7daSAndroid Build Coastguard Worker * single node branch (not a loop), it is
1836*cc4ad7daSAndroid Build Coastguard Worker * recognized as a loop by the code above:
1837*cc4ad7daSAndroid Build Coastguard Worker * m->visited because more then one,
1838*cc4ad7daSAndroid Build Coastguard Worker * m == root->mod since it is a single node.
1839*cc4ad7daSAndroid Build Coastguard Worker * So, prevent deeping into the branch second
1840*cc4ad7daSAndroid Build Coastguard Worker * time.
1841*cc4ad7daSAndroid Build Coastguard Worker */
1842*cc4ad7daSAndroid Build Coastguard Worker depmod_list_remove_data(roots, m);
1843*cc4ad7daSAndroid Build Coastguard Worker
1844*cc4ad7daSAndroid Build Coastguard Worker continue;
1845*cc4ad7daSAndroid Build Coastguard Worker }
1846*cc4ad7daSAndroid Build Coastguard Worker
1847*cc4ad7daSAndroid Build Coastguard Worker itr = (struct mod **) m->deps.array;
1848*cc4ad7daSAndroid Build Coastguard Worker itr_end = itr + m->deps.count;
1849*cc4ad7daSAndroid Build Coastguard Worker for (; itr < itr_end; itr++) {
1850*cc4ad7daSAndroid Build Coastguard Worker struct mod *dep = *itr;
1851*cc4ad7daSAndroid Build Coastguard Worker v = vertex_new(dep, vertex);
1852*cc4ad7daSAndroid Build Coastguard Worker if (v == NULL) {
1853*cc4ad7daSAndroid Build Coastguard Worker ERR("No memory to report cycles\n");
1854*cc4ad7daSAndroid Build Coastguard Worker goto out;
1855*cc4ad7daSAndroid Build Coastguard Worker }
1856*cc4ad7daSAndroid Build Coastguard Worker assert(is < stack_size);
1857*cc4ad7daSAndroid Build Coastguard Worker stack[is++] = v;
1858*cc4ad7daSAndroid Build Coastguard Worker
1859*cc4ad7daSAndroid Build Coastguard Worker l = kmod_list_append(free_list, v);
1860*cc4ad7daSAndroid Build Coastguard Worker if (l == NULL) {
1861*cc4ad7daSAndroid Build Coastguard Worker ERR("No memory to report cycles\n");
1862*cc4ad7daSAndroid Build Coastguard Worker goto out;
1863*cc4ad7daSAndroid Build Coastguard Worker }
1864*cc4ad7daSAndroid Build Coastguard Worker free_list = l;
1865*cc4ad7daSAndroid Build Coastguard Worker
1866*cc4ad7daSAndroid Build Coastguard Worker }
1867*cc4ad7daSAndroid Build Coastguard Worker }
1868*cc4ad7daSAndroid Build Coastguard Worker ret = 0;
1869*cc4ad7daSAndroid Build Coastguard Worker
1870*cc4ad7daSAndroid Build Coastguard Worker out:
1871*cc4ad7daSAndroid Build Coastguard Worker while (free_list) {
1872*cc4ad7daSAndroid Build Coastguard Worker v = free_list->data;
1873*cc4ad7daSAndroid Build Coastguard Worker l = kmod_list_remove(free_list);
1874*cc4ad7daSAndroid Build Coastguard Worker free_list = l;
1875*cc4ad7daSAndroid Build Coastguard Worker free(v);
1876*cc4ad7daSAndroid Build Coastguard Worker }
1877*cc4ad7daSAndroid Build Coastguard Worker
1878*cc4ad7daSAndroid Build Coastguard Worker return ret;
1879*cc4ad7daSAndroid Build Coastguard Worker }
1880*cc4ad7daSAndroid Build Coastguard Worker
depmod_report_cycles(struct depmod * depmod,uint16_t n_mods,uint16_t * users)1881*cc4ad7daSAndroid Build Coastguard Worker static void depmod_report_cycles(struct depmod *depmod, uint16_t n_mods,
1882*cc4ad7daSAndroid Build Coastguard Worker uint16_t *users)
1883*cc4ad7daSAndroid Build Coastguard Worker {
1884*cc4ad7daSAndroid Build Coastguard Worker int num_cyclic = 0;
1885*cc4ad7daSAndroid Build Coastguard Worker struct kmod_list *roots = NULL; /* struct mod */
1886*cc4ad7daSAndroid Build Coastguard Worker struct kmod_list *l;
1887*cc4ad7daSAndroid Build Coastguard Worker size_t n_r; /* local n_roots */
1888*cc4ad7daSAndroid Build Coastguard Worker int i;
1889*cc4ad7daSAndroid Build Coastguard Worker int err;
1890*cc4ad7daSAndroid Build Coastguard Worker _cleanup_free_ void **stack = NULL;
1891*cc4ad7daSAndroid Build Coastguard Worker struct mod *m;
1892*cc4ad7daSAndroid Build Coastguard Worker struct mod *root;
1893*cc4ad7daSAndroid Build Coastguard Worker struct hash *loop_set;
1894*cc4ad7daSAndroid Build Coastguard Worker
1895*cc4ad7daSAndroid Build Coastguard Worker for (i = 0, n_r = 0; i < n_mods; i++) {
1896*cc4ad7daSAndroid Build Coastguard Worker if (users[i] <= 0)
1897*cc4ad7daSAndroid Build Coastguard Worker continue;
1898*cc4ad7daSAndroid Build Coastguard Worker m = depmod->modules.array[i];
1899*cc4ad7daSAndroid Build Coastguard Worker l = kmod_list_append(roots, m);
1900*cc4ad7daSAndroid Build Coastguard Worker if (l == NULL) {
1901*cc4ad7daSAndroid Build Coastguard Worker ERR("No memory to report cycles\n");
1902*cc4ad7daSAndroid Build Coastguard Worker goto out_list;
1903*cc4ad7daSAndroid Build Coastguard Worker }
1904*cc4ad7daSAndroid Build Coastguard Worker roots = l;
1905*cc4ad7daSAndroid Build Coastguard Worker n_r++;
1906*cc4ad7daSAndroid Build Coastguard Worker }
1907*cc4ad7daSAndroid Build Coastguard Worker
1908*cc4ad7daSAndroid Build Coastguard Worker stack = malloc(n_r * sizeof(void *));
1909*cc4ad7daSAndroid Build Coastguard Worker if (stack == NULL) {
1910*cc4ad7daSAndroid Build Coastguard Worker ERR("No memory to report cycles\n");
1911*cc4ad7daSAndroid Build Coastguard Worker goto out_list;
1912*cc4ad7daSAndroid Build Coastguard Worker }
1913*cc4ad7daSAndroid Build Coastguard Worker
1914*cc4ad7daSAndroid Build Coastguard Worker loop_set = hash_new(16, NULL);
1915*cc4ad7daSAndroid Build Coastguard Worker if (loop_set == NULL) {
1916*cc4ad7daSAndroid Build Coastguard Worker ERR("No memory to report cycles\n");
1917*cc4ad7daSAndroid Build Coastguard Worker goto out_list;
1918*cc4ad7daSAndroid Build Coastguard Worker }
1919*cc4ad7daSAndroid Build Coastguard Worker
1920*cc4ad7daSAndroid Build Coastguard Worker while (roots != NULL) {
1921*cc4ad7daSAndroid Build Coastguard Worker root = roots->data;
1922*cc4ad7daSAndroid Build Coastguard Worker l = kmod_list_remove(roots);
1923*cc4ad7daSAndroid Build Coastguard Worker roots = l;
1924*cc4ad7daSAndroid Build Coastguard Worker err = depmod_report_cycles_from_root(depmod,
1925*cc4ad7daSAndroid Build Coastguard Worker root,
1926*cc4ad7daSAndroid Build Coastguard Worker &roots,
1927*cc4ad7daSAndroid Build Coastguard Worker stack, n_r, loop_set);
1928*cc4ad7daSAndroid Build Coastguard Worker if (err < 0)
1929*cc4ad7daSAndroid Build Coastguard Worker goto out_hash;
1930*cc4ad7daSAndroid Build Coastguard Worker }
1931*cc4ad7daSAndroid Build Coastguard Worker
1932*cc4ad7daSAndroid Build Coastguard Worker num_cyclic = hash_get_count(loop_set);
1933*cc4ad7daSAndroid Build Coastguard Worker ERR("Found %d modules in dependency cycles!\n", num_cyclic);
1934*cc4ad7daSAndroid Build Coastguard Worker
1935*cc4ad7daSAndroid Build Coastguard Worker out_hash:
1936*cc4ad7daSAndroid Build Coastguard Worker hash_free(loop_set);
1937*cc4ad7daSAndroid Build Coastguard Worker out_list:
1938*cc4ad7daSAndroid Build Coastguard Worker while (roots != NULL) {
1939*cc4ad7daSAndroid Build Coastguard Worker /* no need to free data, come from outside */
1940*cc4ad7daSAndroid Build Coastguard Worker roots = kmod_list_remove(roots);
1941*cc4ad7daSAndroid Build Coastguard Worker }
1942*cc4ad7daSAndroid Build Coastguard Worker }
1943*cc4ad7daSAndroid Build Coastguard Worker
depmod_calculate_dependencies(struct depmod * depmod)1944*cc4ad7daSAndroid Build Coastguard Worker static int depmod_calculate_dependencies(struct depmod *depmod)
1945*cc4ad7daSAndroid Build Coastguard Worker {
1946*cc4ad7daSAndroid Build Coastguard Worker const struct mod **itrm;
1947*cc4ad7daSAndroid Build Coastguard Worker uint16_t *users, *roots, *sorted;
1948*cc4ad7daSAndroid Build Coastguard Worker uint16_t i, n_roots = 0, n_sorted = 0, n_mods = depmod->modules.count;
1949*cc4ad7daSAndroid Build Coastguard Worker int ret = 0;
1950*cc4ad7daSAndroid Build Coastguard Worker
1951*cc4ad7daSAndroid Build Coastguard Worker users = malloc(sizeof(uint16_t) * n_mods * 3);
1952*cc4ad7daSAndroid Build Coastguard Worker if (users == NULL)
1953*cc4ad7daSAndroid Build Coastguard Worker return -ENOMEM;
1954*cc4ad7daSAndroid Build Coastguard Worker roots = users + n_mods;
1955*cc4ad7daSAndroid Build Coastguard Worker sorted = roots + n_mods;
1956*cc4ad7daSAndroid Build Coastguard Worker
1957*cc4ad7daSAndroid Build Coastguard Worker DBG("calculate dependencies and ordering (%hu modules)\n", n_mods);
1958*cc4ad7daSAndroid Build Coastguard Worker
1959*cc4ad7daSAndroid Build Coastguard Worker assert(depmod->modules.count < UINT16_MAX);
1960*cc4ad7daSAndroid Build Coastguard Worker
1961*cc4ad7daSAndroid Build Coastguard Worker /* populate modules users (how many modules uses it) */
1962*cc4ad7daSAndroid Build Coastguard Worker itrm = (const struct mod **)depmod->modules.array;
1963*cc4ad7daSAndroid Build Coastguard Worker for (i = 0; i < n_mods; i++, itrm++) {
1964*cc4ad7daSAndroid Build Coastguard Worker const struct mod *m = *itrm;
1965*cc4ad7daSAndroid Build Coastguard Worker users[i] = m->users;
1966*cc4ad7daSAndroid Build Coastguard Worker if (users[i] == 0) {
1967*cc4ad7daSAndroid Build Coastguard Worker roots[n_roots] = i;
1968*cc4ad7daSAndroid Build Coastguard Worker n_roots++;
1969*cc4ad7daSAndroid Build Coastguard Worker }
1970*cc4ad7daSAndroid Build Coastguard Worker }
1971*cc4ad7daSAndroid Build Coastguard Worker
1972*cc4ad7daSAndroid Build Coastguard Worker /* topological sort (outputs modules without users first) */
1973*cc4ad7daSAndroid Build Coastguard Worker while (n_roots > 0) {
1974*cc4ad7daSAndroid Build Coastguard Worker const struct mod **itr_dst, **itr_dst_end;
1975*cc4ad7daSAndroid Build Coastguard Worker struct mod *src;
1976*cc4ad7daSAndroid Build Coastguard Worker uint16_t src_idx = roots[--n_roots];
1977*cc4ad7daSAndroid Build Coastguard Worker
1978*cc4ad7daSAndroid Build Coastguard Worker src = depmod->modules.array[src_idx];
1979*cc4ad7daSAndroid Build Coastguard Worker src->dep_sort_idx = n_sorted;
1980*cc4ad7daSAndroid Build Coastguard Worker sorted[n_sorted] = src_idx;
1981*cc4ad7daSAndroid Build Coastguard Worker n_sorted++;
1982*cc4ad7daSAndroid Build Coastguard Worker
1983*cc4ad7daSAndroid Build Coastguard Worker itr_dst = (const struct mod **)src->deps.array;
1984*cc4ad7daSAndroid Build Coastguard Worker itr_dst_end = itr_dst + src->deps.count;
1985*cc4ad7daSAndroid Build Coastguard Worker for (; itr_dst < itr_dst_end; itr_dst++) {
1986*cc4ad7daSAndroid Build Coastguard Worker const struct mod *dst = *itr_dst;
1987*cc4ad7daSAndroid Build Coastguard Worker uint16_t dst_idx = dst->idx;
1988*cc4ad7daSAndroid Build Coastguard Worker assert(users[dst_idx] > 0);
1989*cc4ad7daSAndroid Build Coastguard Worker users[dst_idx]--;
1990*cc4ad7daSAndroid Build Coastguard Worker if (users[dst_idx] == 0) {
1991*cc4ad7daSAndroid Build Coastguard Worker roots[n_roots] = dst_idx;
1992*cc4ad7daSAndroid Build Coastguard Worker n_roots++;
1993*cc4ad7daSAndroid Build Coastguard Worker }
1994*cc4ad7daSAndroid Build Coastguard Worker }
1995*cc4ad7daSAndroid Build Coastguard Worker }
1996*cc4ad7daSAndroid Build Coastguard Worker
1997*cc4ad7daSAndroid Build Coastguard Worker if (n_sorted < n_mods) {
1998*cc4ad7daSAndroid Build Coastguard Worker depmod_report_cycles(depmod, n_mods, users);
1999*cc4ad7daSAndroid Build Coastguard Worker ret = -EINVAL;
2000*cc4ad7daSAndroid Build Coastguard Worker goto exit;
2001*cc4ad7daSAndroid Build Coastguard Worker }
2002*cc4ad7daSAndroid Build Coastguard Worker
2003*cc4ad7daSAndroid Build Coastguard Worker depmod_sort_dependencies(depmod);
2004*cc4ad7daSAndroid Build Coastguard Worker
2005*cc4ad7daSAndroid Build Coastguard Worker DBG("calculated dependencies and ordering (%hu modules)\n", n_mods);
2006*cc4ad7daSAndroid Build Coastguard Worker
2007*cc4ad7daSAndroid Build Coastguard Worker exit:
2008*cc4ad7daSAndroid Build Coastguard Worker free(users);
2009*cc4ad7daSAndroid Build Coastguard Worker return ret;
2010*cc4ad7daSAndroid Build Coastguard Worker }
2011*cc4ad7daSAndroid Build Coastguard Worker
depmod_load(struct depmod * depmod)2012*cc4ad7daSAndroid Build Coastguard Worker static int depmod_load(struct depmod *depmod)
2013*cc4ad7daSAndroid Build Coastguard Worker {
2014*cc4ad7daSAndroid Build Coastguard Worker int err;
2015*cc4ad7daSAndroid Build Coastguard Worker
2016*cc4ad7daSAndroid Build Coastguard Worker err = depmod_load_modules(depmod);
2017*cc4ad7daSAndroid Build Coastguard Worker if (err < 0)
2018*cc4ad7daSAndroid Build Coastguard Worker return err;
2019*cc4ad7daSAndroid Build Coastguard Worker
2020*cc4ad7daSAndroid Build Coastguard Worker err = depmod_load_dependencies(depmod);
2021*cc4ad7daSAndroid Build Coastguard Worker if (err < 0)
2022*cc4ad7daSAndroid Build Coastguard Worker return err;
2023*cc4ad7daSAndroid Build Coastguard Worker
2024*cc4ad7daSAndroid Build Coastguard Worker err = depmod_calculate_dependencies(depmod);
2025*cc4ad7daSAndroid Build Coastguard Worker if (err < 0)
2026*cc4ad7daSAndroid Build Coastguard Worker return err;
2027*cc4ad7daSAndroid Build Coastguard Worker
2028*cc4ad7daSAndroid Build Coastguard Worker return 0;
2029*cc4ad7daSAndroid Build Coastguard Worker }
2030*cc4ad7daSAndroid Build Coastguard Worker
mod_count_all_dependencies(const struct mod * mod)2031*cc4ad7daSAndroid Build Coastguard Worker static size_t mod_count_all_dependencies(const struct mod *mod)
2032*cc4ad7daSAndroid Build Coastguard Worker {
2033*cc4ad7daSAndroid Build Coastguard Worker size_t i, count = 0;
2034*cc4ad7daSAndroid Build Coastguard Worker for (i = 0; i < mod->deps.count; i++) {
2035*cc4ad7daSAndroid Build Coastguard Worker const struct mod *d = mod->deps.array[i];
2036*cc4ad7daSAndroid Build Coastguard Worker count += 1 + mod_count_all_dependencies(d);
2037*cc4ad7daSAndroid Build Coastguard Worker }
2038*cc4ad7daSAndroid Build Coastguard Worker return count;
2039*cc4ad7daSAndroid Build Coastguard Worker }
2040*cc4ad7daSAndroid Build Coastguard Worker
mod_fill_all_unique_dependencies(const struct mod * mod,const struct mod ** deps,size_t n_deps,size_t * last)2041*cc4ad7daSAndroid Build Coastguard Worker static int mod_fill_all_unique_dependencies(const struct mod *mod, const struct mod **deps, size_t n_deps, size_t *last)
2042*cc4ad7daSAndroid Build Coastguard Worker {
2043*cc4ad7daSAndroid Build Coastguard Worker size_t i;
2044*cc4ad7daSAndroid Build Coastguard Worker int err = 0;
2045*cc4ad7daSAndroid Build Coastguard Worker for (i = 0; i < mod->deps.count; i++) {
2046*cc4ad7daSAndroid Build Coastguard Worker const struct mod *d = mod->deps.array[i];
2047*cc4ad7daSAndroid Build Coastguard Worker size_t j;
2048*cc4ad7daSAndroid Build Coastguard Worker uint8_t exists = 0;
2049*cc4ad7daSAndroid Build Coastguard Worker
2050*cc4ad7daSAndroid Build Coastguard Worker for (j = 0; j < *last; j++) {
2051*cc4ad7daSAndroid Build Coastguard Worker if (deps[j] == d) {
2052*cc4ad7daSAndroid Build Coastguard Worker exists = 1;
2053*cc4ad7daSAndroid Build Coastguard Worker break;
2054*cc4ad7daSAndroid Build Coastguard Worker }
2055*cc4ad7daSAndroid Build Coastguard Worker }
2056*cc4ad7daSAndroid Build Coastguard Worker
2057*cc4ad7daSAndroid Build Coastguard Worker if (exists)
2058*cc4ad7daSAndroid Build Coastguard Worker continue;
2059*cc4ad7daSAndroid Build Coastguard Worker
2060*cc4ad7daSAndroid Build Coastguard Worker if (*last >= n_deps)
2061*cc4ad7daSAndroid Build Coastguard Worker return -ENOSPC;
2062*cc4ad7daSAndroid Build Coastguard Worker deps[*last] = d;
2063*cc4ad7daSAndroid Build Coastguard Worker (*last)++;
2064*cc4ad7daSAndroid Build Coastguard Worker err = mod_fill_all_unique_dependencies(d, deps, n_deps, last);
2065*cc4ad7daSAndroid Build Coastguard Worker if (err < 0)
2066*cc4ad7daSAndroid Build Coastguard Worker break;
2067*cc4ad7daSAndroid Build Coastguard Worker }
2068*cc4ad7daSAndroid Build Coastguard Worker return err;
2069*cc4ad7daSAndroid Build Coastguard Worker }
2070*cc4ad7daSAndroid Build Coastguard Worker
mod_get_all_sorted_dependencies(const struct mod * mod,size_t * n_deps)2071*cc4ad7daSAndroid Build Coastguard Worker static const struct mod **mod_get_all_sorted_dependencies(const struct mod *mod, size_t *n_deps)
2072*cc4ad7daSAndroid Build Coastguard Worker {
2073*cc4ad7daSAndroid Build Coastguard Worker const struct mod **deps;
2074*cc4ad7daSAndroid Build Coastguard Worker size_t last = 0;
2075*cc4ad7daSAndroid Build Coastguard Worker
2076*cc4ad7daSAndroid Build Coastguard Worker *n_deps = mod_count_all_dependencies(mod);
2077*cc4ad7daSAndroid Build Coastguard Worker if (*n_deps == 0)
2078*cc4ad7daSAndroid Build Coastguard Worker return NULL;
2079*cc4ad7daSAndroid Build Coastguard Worker
2080*cc4ad7daSAndroid Build Coastguard Worker deps = malloc(sizeof(struct mod *) * (*n_deps));
2081*cc4ad7daSAndroid Build Coastguard Worker if (deps == NULL)
2082*cc4ad7daSAndroid Build Coastguard Worker return NULL;
2083*cc4ad7daSAndroid Build Coastguard Worker
2084*cc4ad7daSAndroid Build Coastguard Worker if (mod_fill_all_unique_dependencies(mod, deps, *n_deps, &last) < 0) {
2085*cc4ad7daSAndroid Build Coastguard Worker free(deps);
2086*cc4ad7daSAndroid Build Coastguard Worker return NULL;
2087*cc4ad7daSAndroid Build Coastguard Worker }
2088*cc4ad7daSAndroid Build Coastguard Worker
2089*cc4ad7daSAndroid Build Coastguard Worker qsort(deps, last, sizeof(struct mod *), dep_cmp);
2090*cc4ad7daSAndroid Build Coastguard Worker *n_deps = last;
2091*cc4ad7daSAndroid Build Coastguard Worker return deps;
2092*cc4ad7daSAndroid Build Coastguard Worker }
2093*cc4ad7daSAndroid Build Coastguard Worker
mod_get_compressed_path(const struct mod * mod)2094*cc4ad7daSAndroid Build Coastguard Worker static inline const char *mod_get_compressed_path(const struct mod *mod)
2095*cc4ad7daSAndroid Build Coastguard Worker {
2096*cc4ad7daSAndroid Build Coastguard Worker if (mod->relpath != NULL)
2097*cc4ad7daSAndroid Build Coastguard Worker return mod->relpath;
2098*cc4ad7daSAndroid Build Coastguard Worker return mod->path;
2099*cc4ad7daSAndroid Build Coastguard Worker }
2100*cc4ad7daSAndroid Build Coastguard Worker
output_deps(struct depmod * depmod,FILE * out)2101*cc4ad7daSAndroid Build Coastguard Worker static int output_deps(struct depmod *depmod, FILE *out)
2102*cc4ad7daSAndroid Build Coastguard Worker {
2103*cc4ad7daSAndroid Build Coastguard Worker size_t i;
2104*cc4ad7daSAndroid Build Coastguard Worker
2105*cc4ad7daSAndroid Build Coastguard Worker for (i = 0; i < depmod->modules.count; i++) {
2106*cc4ad7daSAndroid Build Coastguard Worker const struct mod **deps, *mod = depmod->modules.array[i];
2107*cc4ad7daSAndroid Build Coastguard Worker const char *p = mod_get_compressed_path(mod);
2108*cc4ad7daSAndroid Build Coastguard Worker size_t j, n_deps;
2109*cc4ad7daSAndroid Build Coastguard Worker
2110*cc4ad7daSAndroid Build Coastguard Worker fprintf(out, "%s:", p);
2111*cc4ad7daSAndroid Build Coastguard Worker
2112*cc4ad7daSAndroid Build Coastguard Worker if (mod->deps.count == 0)
2113*cc4ad7daSAndroid Build Coastguard Worker goto end;
2114*cc4ad7daSAndroid Build Coastguard Worker
2115*cc4ad7daSAndroid Build Coastguard Worker deps = mod_get_all_sorted_dependencies(mod, &n_deps);
2116*cc4ad7daSAndroid Build Coastguard Worker if (deps == NULL) {
2117*cc4ad7daSAndroid Build Coastguard Worker ERR("could not get all sorted dependencies of %s\n", p);
2118*cc4ad7daSAndroid Build Coastguard Worker goto end;
2119*cc4ad7daSAndroid Build Coastguard Worker }
2120*cc4ad7daSAndroid Build Coastguard Worker
2121*cc4ad7daSAndroid Build Coastguard Worker for (j = 0; j < n_deps; j++) {
2122*cc4ad7daSAndroid Build Coastguard Worker const struct mod *d = deps[j];
2123*cc4ad7daSAndroid Build Coastguard Worker fprintf(out, " %s", mod_get_compressed_path(d));
2124*cc4ad7daSAndroid Build Coastguard Worker }
2125*cc4ad7daSAndroid Build Coastguard Worker free(deps);
2126*cc4ad7daSAndroid Build Coastguard Worker end:
2127*cc4ad7daSAndroid Build Coastguard Worker putc('\n', out);
2128*cc4ad7daSAndroid Build Coastguard Worker }
2129*cc4ad7daSAndroid Build Coastguard Worker
2130*cc4ad7daSAndroid Build Coastguard Worker return 0;
2131*cc4ad7daSAndroid Build Coastguard Worker }
2132*cc4ad7daSAndroid Build Coastguard Worker
output_deps_bin(struct depmod * depmod,FILE * out)2133*cc4ad7daSAndroid Build Coastguard Worker static int output_deps_bin(struct depmod *depmod, FILE *out)
2134*cc4ad7daSAndroid Build Coastguard Worker {
2135*cc4ad7daSAndroid Build Coastguard Worker struct index_node *idx;
2136*cc4ad7daSAndroid Build Coastguard Worker size_t i;
2137*cc4ad7daSAndroid Build Coastguard Worker
2138*cc4ad7daSAndroid Build Coastguard Worker if (out == stdout)
2139*cc4ad7daSAndroid Build Coastguard Worker return 0;
2140*cc4ad7daSAndroid Build Coastguard Worker
2141*cc4ad7daSAndroid Build Coastguard Worker idx = index_create();
2142*cc4ad7daSAndroid Build Coastguard Worker if (idx == NULL)
2143*cc4ad7daSAndroid Build Coastguard Worker return -ENOMEM;
2144*cc4ad7daSAndroid Build Coastguard Worker
2145*cc4ad7daSAndroid Build Coastguard Worker for (i = 0; i < depmod->modules.count; i++) {
2146*cc4ad7daSAndroid Build Coastguard Worker const struct mod **deps, *mod = depmod->modules.array[i];
2147*cc4ad7daSAndroid Build Coastguard Worker const char *p = mod_get_compressed_path(mod);
2148*cc4ad7daSAndroid Build Coastguard Worker char *line;
2149*cc4ad7daSAndroid Build Coastguard Worker size_t j, n_deps, linepos, linelen, slen;
2150*cc4ad7daSAndroid Build Coastguard Worker int duplicate;
2151*cc4ad7daSAndroid Build Coastguard Worker
2152*cc4ad7daSAndroid Build Coastguard Worker deps = mod_get_all_sorted_dependencies(mod, &n_deps);
2153*cc4ad7daSAndroid Build Coastguard Worker if (deps == NULL && n_deps > 0) {
2154*cc4ad7daSAndroid Build Coastguard Worker ERR("could not get all sorted dependencies of %s\n", p);
2155*cc4ad7daSAndroid Build Coastguard Worker continue;
2156*cc4ad7daSAndroid Build Coastguard Worker }
2157*cc4ad7daSAndroid Build Coastguard Worker
2158*cc4ad7daSAndroid Build Coastguard Worker linelen = strlen(p) + 1;
2159*cc4ad7daSAndroid Build Coastguard Worker for (j = 0; j < n_deps; j++) {
2160*cc4ad7daSAndroid Build Coastguard Worker const struct mod *d = deps[j];
2161*cc4ad7daSAndroid Build Coastguard Worker linelen += 1 + strlen(mod_get_compressed_path(d));
2162*cc4ad7daSAndroid Build Coastguard Worker }
2163*cc4ad7daSAndroid Build Coastguard Worker
2164*cc4ad7daSAndroid Build Coastguard Worker line = malloc(linelen + 1);
2165*cc4ad7daSAndroid Build Coastguard Worker if (line == NULL) {
2166*cc4ad7daSAndroid Build Coastguard Worker free(deps);
2167*cc4ad7daSAndroid Build Coastguard Worker ERR("modules.deps.bin: out of memory\n");
2168*cc4ad7daSAndroid Build Coastguard Worker continue;
2169*cc4ad7daSAndroid Build Coastguard Worker }
2170*cc4ad7daSAndroid Build Coastguard Worker
2171*cc4ad7daSAndroid Build Coastguard Worker linepos = 0;
2172*cc4ad7daSAndroid Build Coastguard Worker slen = strlen(p);
2173*cc4ad7daSAndroid Build Coastguard Worker memcpy(line + linepos, p, slen);
2174*cc4ad7daSAndroid Build Coastguard Worker linepos += slen;
2175*cc4ad7daSAndroid Build Coastguard Worker line[linepos] = ':';
2176*cc4ad7daSAndroid Build Coastguard Worker linepos++;
2177*cc4ad7daSAndroid Build Coastguard Worker
2178*cc4ad7daSAndroid Build Coastguard Worker for (j = 0; j < n_deps; j++) {
2179*cc4ad7daSAndroid Build Coastguard Worker const struct mod *d = deps[j];
2180*cc4ad7daSAndroid Build Coastguard Worker const char *dp;
2181*cc4ad7daSAndroid Build Coastguard Worker
2182*cc4ad7daSAndroid Build Coastguard Worker line[linepos] = ' ';
2183*cc4ad7daSAndroid Build Coastguard Worker linepos++;
2184*cc4ad7daSAndroid Build Coastguard Worker
2185*cc4ad7daSAndroid Build Coastguard Worker dp = mod_get_compressed_path(d);
2186*cc4ad7daSAndroid Build Coastguard Worker slen = strlen(dp);
2187*cc4ad7daSAndroid Build Coastguard Worker memcpy(line + linepos, dp, slen);
2188*cc4ad7daSAndroid Build Coastguard Worker linepos += slen;
2189*cc4ad7daSAndroid Build Coastguard Worker }
2190*cc4ad7daSAndroid Build Coastguard Worker line[linepos] = '\0';
2191*cc4ad7daSAndroid Build Coastguard Worker
2192*cc4ad7daSAndroid Build Coastguard Worker duplicate = index_insert(idx, mod->modname, line, mod->idx);
2193*cc4ad7daSAndroid Build Coastguard Worker if (duplicate && depmod->cfg->warn_dups)
2194*cc4ad7daSAndroid Build Coastguard Worker WRN("duplicate module deps:\n%s\n", line);
2195*cc4ad7daSAndroid Build Coastguard Worker free(line);
2196*cc4ad7daSAndroid Build Coastguard Worker free(deps);
2197*cc4ad7daSAndroid Build Coastguard Worker }
2198*cc4ad7daSAndroid Build Coastguard Worker
2199*cc4ad7daSAndroid Build Coastguard Worker index_write(idx, out);
2200*cc4ad7daSAndroid Build Coastguard Worker index_destroy(idx);
2201*cc4ad7daSAndroid Build Coastguard Worker
2202*cc4ad7daSAndroid Build Coastguard Worker return 0;
2203*cc4ad7daSAndroid Build Coastguard Worker }
2204*cc4ad7daSAndroid Build Coastguard Worker
output_aliases(struct depmod * depmod,FILE * out)2205*cc4ad7daSAndroid Build Coastguard Worker static int output_aliases(struct depmod *depmod, FILE *out)
2206*cc4ad7daSAndroid Build Coastguard Worker {
2207*cc4ad7daSAndroid Build Coastguard Worker size_t i;
2208*cc4ad7daSAndroid Build Coastguard Worker
2209*cc4ad7daSAndroid Build Coastguard Worker fputs("# Aliases extracted from modules themselves.\n", out);
2210*cc4ad7daSAndroid Build Coastguard Worker
2211*cc4ad7daSAndroid Build Coastguard Worker for (i = 0; i < depmod->modules.count; i++) {
2212*cc4ad7daSAndroid Build Coastguard Worker const struct mod *mod = depmod->modules.array[i];
2213*cc4ad7daSAndroid Build Coastguard Worker struct kmod_list *l;
2214*cc4ad7daSAndroid Build Coastguard Worker
2215*cc4ad7daSAndroid Build Coastguard Worker kmod_list_foreach(l, mod->info_list) {
2216*cc4ad7daSAndroid Build Coastguard Worker const char *key = kmod_module_info_get_key(l);
2217*cc4ad7daSAndroid Build Coastguard Worker const char *value = kmod_module_info_get_value(l);
2218*cc4ad7daSAndroid Build Coastguard Worker
2219*cc4ad7daSAndroid Build Coastguard Worker if (!streq(key, "alias"))
2220*cc4ad7daSAndroid Build Coastguard Worker continue;
2221*cc4ad7daSAndroid Build Coastguard Worker
2222*cc4ad7daSAndroid Build Coastguard Worker fprintf(out, "alias %s %s\n", value, mod->modname);
2223*cc4ad7daSAndroid Build Coastguard Worker }
2224*cc4ad7daSAndroid Build Coastguard Worker }
2225*cc4ad7daSAndroid Build Coastguard Worker
2226*cc4ad7daSAndroid Build Coastguard Worker return 0;
2227*cc4ad7daSAndroid Build Coastguard Worker }
2228*cc4ad7daSAndroid Build Coastguard Worker
output_aliases_bin(struct depmod * depmod,FILE * out)2229*cc4ad7daSAndroid Build Coastguard Worker static int output_aliases_bin(struct depmod *depmod, FILE *out)
2230*cc4ad7daSAndroid Build Coastguard Worker {
2231*cc4ad7daSAndroid Build Coastguard Worker struct index_node *idx;
2232*cc4ad7daSAndroid Build Coastguard Worker size_t i;
2233*cc4ad7daSAndroid Build Coastguard Worker
2234*cc4ad7daSAndroid Build Coastguard Worker if (out == stdout)
2235*cc4ad7daSAndroid Build Coastguard Worker return 0;
2236*cc4ad7daSAndroid Build Coastguard Worker
2237*cc4ad7daSAndroid Build Coastguard Worker idx = index_create();
2238*cc4ad7daSAndroid Build Coastguard Worker if (idx == NULL)
2239*cc4ad7daSAndroid Build Coastguard Worker return -ENOMEM;
2240*cc4ad7daSAndroid Build Coastguard Worker
2241*cc4ad7daSAndroid Build Coastguard Worker for (i = 0; i < depmod->modules.count; i++) {
2242*cc4ad7daSAndroid Build Coastguard Worker const struct mod *mod = depmod->modules.array[i];
2243*cc4ad7daSAndroid Build Coastguard Worker struct kmod_list *l;
2244*cc4ad7daSAndroid Build Coastguard Worker
2245*cc4ad7daSAndroid Build Coastguard Worker kmod_list_foreach(l, mod->info_list) {
2246*cc4ad7daSAndroid Build Coastguard Worker const char *key = kmod_module_info_get_key(l);
2247*cc4ad7daSAndroid Build Coastguard Worker const char *value = kmod_module_info_get_value(l);
2248*cc4ad7daSAndroid Build Coastguard Worker char buf[PATH_MAX];
2249*cc4ad7daSAndroid Build Coastguard Worker const char *alias;
2250*cc4ad7daSAndroid Build Coastguard Worker int duplicate;
2251*cc4ad7daSAndroid Build Coastguard Worker
2252*cc4ad7daSAndroid Build Coastguard Worker if (!streq(key, "alias"))
2253*cc4ad7daSAndroid Build Coastguard Worker continue;
2254*cc4ad7daSAndroid Build Coastguard Worker
2255*cc4ad7daSAndroid Build Coastguard Worker if (alias_normalize(value, buf, NULL) < 0) {
2256*cc4ad7daSAndroid Build Coastguard Worker WRN("Unmatched bracket in %s\n", value);
2257*cc4ad7daSAndroid Build Coastguard Worker continue;
2258*cc4ad7daSAndroid Build Coastguard Worker }
2259*cc4ad7daSAndroid Build Coastguard Worker alias = buf;
2260*cc4ad7daSAndroid Build Coastguard Worker
2261*cc4ad7daSAndroid Build Coastguard Worker duplicate = index_insert(idx, alias, mod->modname,
2262*cc4ad7daSAndroid Build Coastguard Worker mod->idx);
2263*cc4ad7daSAndroid Build Coastguard Worker if (duplicate && depmod->cfg->warn_dups)
2264*cc4ad7daSAndroid Build Coastguard Worker WRN("duplicate module alias:\n%s %s\n",
2265*cc4ad7daSAndroid Build Coastguard Worker alias, mod->modname);
2266*cc4ad7daSAndroid Build Coastguard Worker }
2267*cc4ad7daSAndroid Build Coastguard Worker }
2268*cc4ad7daSAndroid Build Coastguard Worker
2269*cc4ad7daSAndroid Build Coastguard Worker index_write(idx, out);
2270*cc4ad7daSAndroid Build Coastguard Worker index_destroy(idx);
2271*cc4ad7daSAndroid Build Coastguard Worker
2272*cc4ad7daSAndroid Build Coastguard Worker return 0;
2273*cc4ad7daSAndroid Build Coastguard Worker }
2274*cc4ad7daSAndroid Build Coastguard Worker
output_softdeps(struct depmod * depmod,FILE * out)2275*cc4ad7daSAndroid Build Coastguard Worker static int output_softdeps(struct depmod *depmod, FILE *out)
2276*cc4ad7daSAndroid Build Coastguard Worker {
2277*cc4ad7daSAndroid Build Coastguard Worker size_t i;
2278*cc4ad7daSAndroid Build Coastguard Worker
2279*cc4ad7daSAndroid Build Coastguard Worker fputs("# Soft dependencies extracted from modules themselves.\n", out);
2280*cc4ad7daSAndroid Build Coastguard Worker
2281*cc4ad7daSAndroid Build Coastguard Worker for (i = 0; i < depmod->modules.count; i++) {
2282*cc4ad7daSAndroid Build Coastguard Worker const struct mod *mod = depmod->modules.array[i];
2283*cc4ad7daSAndroid Build Coastguard Worker struct kmod_list *l;
2284*cc4ad7daSAndroid Build Coastguard Worker
2285*cc4ad7daSAndroid Build Coastguard Worker kmod_list_foreach(l, mod->info_list) {
2286*cc4ad7daSAndroid Build Coastguard Worker const char *key = kmod_module_info_get_key(l);
2287*cc4ad7daSAndroid Build Coastguard Worker const char *value = kmod_module_info_get_value(l);
2288*cc4ad7daSAndroid Build Coastguard Worker
2289*cc4ad7daSAndroid Build Coastguard Worker if (!streq(key, "softdep"))
2290*cc4ad7daSAndroid Build Coastguard Worker continue;
2291*cc4ad7daSAndroid Build Coastguard Worker
2292*cc4ad7daSAndroid Build Coastguard Worker fprintf(out, "softdep %s %s\n", mod->modname, value);
2293*cc4ad7daSAndroid Build Coastguard Worker }
2294*cc4ad7daSAndroid Build Coastguard Worker }
2295*cc4ad7daSAndroid Build Coastguard Worker
2296*cc4ad7daSAndroid Build Coastguard Worker return 0;
2297*cc4ad7daSAndroid Build Coastguard Worker }
2298*cc4ad7daSAndroid Build Coastguard Worker
output_symbols(struct depmod * depmod,FILE * out)2299*cc4ad7daSAndroid Build Coastguard Worker static int output_symbols(struct depmod *depmod, FILE *out)
2300*cc4ad7daSAndroid Build Coastguard Worker {
2301*cc4ad7daSAndroid Build Coastguard Worker struct hash_iter iter;
2302*cc4ad7daSAndroid Build Coastguard Worker const void *v;
2303*cc4ad7daSAndroid Build Coastguard Worker
2304*cc4ad7daSAndroid Build Coastguard Worker fputs("# Aliases for symbols, used by symbol_request().\n", out);
2305*cc4ad7daSAndroid Build Coastguard Worker
2306*cc4ad7daSAndroid Build Coastguard Worker hash_iter_init(depmod->symbols, &iter);
2307*cc4ad7daSAndroid Build Coastguard Worker
2308*cc4ad7daSAndroid Build Coastguard Worker while (hash_iter_next(&iter, NULL, &v)) {
2309*cc4ad7daSAndroid Build Coastguard Worker const struct symbol *sym = v;
2310*cc4ad7daSAndroid Build Coastguard Worker if (sym->owner == NULL)
2311*cc4ad7daSAndroid Build Coastguard Worker continue;
2312*cc4ad7daSAndroid Build Coastguard Worker
2313*cc4ad7daSAndroid Build Coastguard Worker fprintf(out, "alias symbol:%s %s\n",
2314*cc4ad7daSAndroid Build Coastguard Worker sym->name, sym->owner->modname);
2315*cc4ad7daSAndroid Build Coastguard Worker }
2316*cc4ad7daSAndroid Build Coastguard Worker
2317*cc4ad7daSAndroid Build Coastguard Worker return 0;
2318*cc4ad7daSAndroid Build Coastguard Worker }
2319*cc4ad7daSAndroid Build Coastguard Worker
output_symbols_bin(struct depmod * depmod,FILE * out)2320*cc4ad7daSAndroid Build Coastguard Worker static int output_symbols_bin(struct depmod *depmod, FILE *out)
2321*cc4ad7daSAndroid Build Coastguard Worker {
2322*cc4ad7daSAndroid Build Coastguard Worker struct index_node *idx;
2323*cc4ad7daSAndroid Build Coastguard Worker char alias[1024];
2324*cc4ad7daSAndroid Build Coastguard Worker _cleanup_(scratchbuf_release) struct scratchbuf salias =
2325*cc4ad7daSAndroid Build Coastguard Worker SCRATCHBUF_INITIALIZER(alias);
2326*cc4ad7daSAndroid Build Coastguard Worker size_t baselen = sizeof("symbol:") - 1;
2327*cc4ad7daSAndroid Build Coastguard Worker struct hash_iter iter;
2328*cc4ad7daSAndroid Build Coastguard Worker const void *v;
2329*cc4ad7daSAndroid Build Coastguard Worker int ret = 0;
2330*cc4ad7daSAndroid Build Coastguard Worker
2331*cc4ad7daSAndroid Build Coastguard Worker if (out == stdout)
2332*cc4ad7daSAndroid Build Coastguard Worker return 0;
2333*cc4ad7daSAndroid Build Coastguard Worker
2334*cc4ad7daSAndroid Build Coastguard Worker idx = index_create();
2335*cc4ad7daSAndroid Build Coastguard Worker if (idx == NULL)
2336*cc4ad7daSAndroid Build Coastguard Worker return -ENOMEM;
2337*cc4ad7daSAndroid Build Coastguard Worker
2338*cc4ad7daSAndroid Build Coastguard Worker memcpy(alias, "symbol:", baselen);
2339*cc4ad7daSAndroid Build Coastguard Worker
2340*cc4ad7daSAndroid Build Coastguard Worker hash_iter_init(depmod->symbols, &iter);
2341*cc4ad7daSAndroid Build Coastguard Worker
2342*cc4ad7daSAndroid Build Coastguard Worker while (hash_iter_next(&iter, NULL, &v)) {
2343*cc4ad7daSAndroid Build Coastguard Worker int duplicate;
2344*cc4ad7daSAndroid Build Coastguard Worker const struct symbol *sym = v;
2345*cc4ad7daSAndroid Build Coastguard Worker size_t len;
2346*cc4ad7daSAndroid Build Coastguard Worker
2347*cc4ad7daSAndroid Build Coastguard Worker if (sym->owner == NULL)
2348*cc4ad7daSAndroid Build Coastguard Worker continue;
2349*cc4ad7daSAndroid Build Coastguard Worker
2350*cc4ad7daSAndroid Build Coastguard Worker len = strlen(sym->name);
2351*cc4ad7daSAndroid Build Coastguard Worker
2352*cc4ad7daSAndroid Build Coastguard Worker if (scratchbuf_alloc(&salias, baselen + len + 1) < 0) {
2353*cc4ad7daSAndroid Build Coastguard Worker ret = -ENOMEM;
2354*cc4ad7daSAndroid Build Coastguard Worker goto err_scratchbuf;
2355*cc4ad7daSAndroid Build Coastguard Worker }
2356*cc4ad7daSAndroid Build Coastguard Worker memcpy(scratchbuf_str(&salias) + baselen, sym->name, len + 1);
2357*cc4ad7daSAndroid Build Coastguard Worker duplicate = index_insert(idx, alias, sym->owner->modname,
2358*cc4ad7daSAndroid Build Coastguard Worker sym->owner->idx);
2359*cc4ad7daSAndroid Build Coastguard Worker
2360*cc4ad7daSAndroid Build Coastguard Worker if (duplicate && depmod->cfg->warn_dups)
2361*cc4ad7daSAndroid Build Coastguard Worker WRN("duplicate module syms:\n%s %s\n",
2362*cc4ad7daSAndroid Build Coastguard Worker alias, sym->owner->modname);
2363*cc4ad7daSAndroid Build Coastguard Worker }
2364*cc4ad7daSAndroid Build Coastguard Worker
2365*cc4ad7daSAndroid Build Coastguard Worker index_write(idx, out);
2366*cc4ad7daSAndroid Build Coastguard Worker
2367*cc4ad7daSAndroid Build Coastguard Worker err_scratchbuf:
2368*cc4ad7daSAndroid Build Coastguard Worker index_destroy(idx);
2369*cc4ad7daSAndroid Build Coastguard Worker
2370*cc4ad7daSAndroid Build Coastguard Worker if (ret < 0)
2371*cc4ad7daSAndroid Build Coastguard Worker ERR("output symbols: %s\n", strerror(-ret));
2372*cc4ad7daSAndroid Build Coastguard Worker
2373*cc4ad7daSAndroid Build Coastguard Worker return ret;
2374*cc4ad7daSAndroid Build Coastguard Worker }
2375*cc4ad7daSAndroid Build Coastguard Worker
output_builtin_bin(struct depmod * depmod,FILE * out)2376*cc4ad7daSAndroid Build Coastguard Worker static int output_builtin_bin(struct depmod *depmod, FILE *out)
2377*cc4ad7daSAndroid Build Coastguard Worker {
2378*cc4ad7daSAndroid Build Coastguard Worker FILE *in;
2379*cc4ad7daSAndroid Build Coastguard Worker struct index_node *idx;
2380*cc4ad7daSAndroid Build Coastguard Worker char line[PATH_MAX], modname[PATH_MAX];
2381*cc4ad7daSAndroid Build Coastguard Worker
2382*cc4ad7daSAndroid Build Coastguard Worker if (out == stdout)
2383*cc4ad7daSAndroid Build Coastguard Worker return 0;
2384*cc4ad7daSAndroid Build Coastguard Worker
2385*cc4ad7daSAndroid Build Coastguard Worker in = dfdopen(depmod->cfg->dirname, "modules.builtin", O_RDONLY, "r");
2386*cc4ad7daSAndroid Build Coastguard Worker if (in == NULL)
2387*cc4ad7daSAndroid Build Coastguard Worker return 0;
2388*cc4ad7daSAndroid Build Coastguard Worker
2389*cc4ad7daSAndroid Build Coastguard Worker idx = index_create();
2390*cc4ad7daSAndroid Build Coastguard Worker if (idx == NULL) {
2391*cc4ad7daSAndroid Build Coastguard Worker fclose(in);
2392*cc4ad7daSAndroid Build Coastguard Worker return -ENOMEM;
2393*cc4ad7daSAndroid Build Coastguard Worker }
2394*cc4ad7daSAndroid Build Coastguard Worker
2395*cc4ad7daSAndroid Build Coastguard Worker while (fgets(line, sizeof(line), in) != NULL) {
2396*cc4ad7daSAndroid Build Coastguard Worker if (!isalpha(line[0])) {
2397*cc4ad7daSAndroid Build Coastguard Worker ERR("Invalid modules.builtin line: %s\n", line);
2398*cc4ad7daSAndroid Build Coastguard Worker continue;
2399*cc4ad7daSAndroid Build Coastguard Worker }
2400*cc4ad7daSAndroid Build Coastguard Worker
2401*cc4ad7daSAndroid Build Coastguard Worker path_to_modname(line, modname, NULL);
2402*cc4ad7daSAndroid Build Coastguard Worker index_insert(idx, modname, "", 0);
2403*cc4ad7daSAndroid Build Coastguard Worker }
2404*cc4ad7daSAndroid Build Coastguard Worker
2405*cc4ad7daSAndroid Build Coastguard Worker index_write(idx, out);
2406*cc4ad7daSAndroid Build Coastguard Worker index_destroy(idx);
2407*cc4ad7daSAndroid Build Coastguard Worker fclose(in);
2408*cc4ad7daSAndroid Build Coastguard Worker
2409*cc4ad7daSAndroid Build Coastguard Worker return 0;
2410*cc4ad7daSAndroid Build Coastguard Worker }
2411*cc4ad7daSAndroid Build Coastguard Worker
flush_stream(FILE * in,int endchar)2412*cc4ad7daSAndroid Build Coastguard Worker static int flush_stream(FILE *in, int endchar)
2413*cc4ad7daSAndroid Build Coastguard Worker {
2414*cc4ad7daSAndroid Build Coastguard Worker size_t i = 0;
2415*cc4ad7daSAndroid Build Coastguard Worker int c;
2416*cc4ad7daSAndroid Build Coastguard Worker
2417*cc4ad7daSAndroid Build Coastguard Worker for (c = fgetc(in);
2418*cc4ad7daSAndroid Build Coastguard Worker c != EOF && c != endchar && c != '\0';
2419*cc4ad7daSAndroid Build Coastguard Worker c = fgetc(in))
2420*cc4ad7daSAndroid Build Coastguard Worker ;
2421*cc4ad7daSAndroid Build Coastguard Worker
2422*cc4ad7daSAndroid Build Coastguard Worker return c == endchar ? i : 0;
2423*cc4ad7daSAndroid Build Coastguard Worker }
2424*cc4ad7daSAndroid Build Coastguard Worker
flush_stream_to(FILE * in,int endchar,char * dst,size_t dst_sz)2425*cc4ad7daSAndroid Build Coastguard Worker static int flush_stream_to(FILE *in, int endchar, char *dst, size_t dst_sz)
2426*cc4ad7daSAndroid Build Coastguard Worker {
2427*cc4ad7daSAndroid Build Coastguard Worker size_t i = 0;
2428*cc4ad7daSAndroid Build Coastguard Worker int c;
2429*cc4ad7daSAndroid Build Coastguard Worker
2430*cc4ad7daSAndroid Build Coastguard Worker for (c = fgetc(in);
2431*cc4ad7daSAndroid Build Coastguard Worker c != EOF && c != endchar && c != '\0' && i < dst_sz;
2432*cc4ad7daSAndroid Build Coastguard Worker c = fgetc(in))
2433*cc4ad7daSAndroid Build Coastguard Worker dst[i++] = c;
2434*cc4ad7daSAndroid Build Coastguard Worker
2435*cc4ad7daSAndroid Build Coastguard Worker if (i == dst_sz) {
2436*cc4ad7daSAndroid Build Coastguard Worker WRN("Could not flush stream: %d. Partial content: %.*s\n",
2437*cc4ad7daSAndroid Build Coastguard Worker ENOSPC, (int) dst_sz, dst);
2438*cc4ad7daSAndroid Build Coastguard Worker i--;
2439*cc4ad7daSAndroid Build Coastguard Worker }
2440*cc4ad7daSAndroid Build Coastguard Worker
2441*cc4ad7daSAndroid Build Coastguard Worker return c == endchar ? i : 0;
2442*cc4ad7daSAndroid Build Coastguard Worker }
2443*cc4ad7daSAndroid Build Coastguard Worker
output_builtin_alias_bin(struct depmod * depmod,FILE * out)2444*cc4ad7daSAndroid Build Coastguard Worker static int output_builtin_alias_bin(struct depmod *depmod, FILE *out)
2445*cc4ad7daSAndroid Build Coastguard Worker {
2446*cc4ad7daSAndroid Build Coastguard Worker FILE *in;
2447*cc4ad7daSAndroid Build Coastguard Worker struct index_node *idx;
2448*cc4ad7daSAndroid Build Coastguard Worker int ret;
2449*cc4ad7daSAndroid Build Coastguard Worker
2450*cc4ad7daSAndroid Build Coastguard Worker if (out == stdout)
2451*cc4ad7daSAndroid Build Coastguard Worker return 0;
2452*cc4ad7daSAndroid Build Coastguard Worker
2453*cc4ad7daSAndroid Build Coastguard Worker in = dfdopen(depmod->cfg->dirname, "modules.builtin.modinfo", O_RDONLY, "r");
2454*cc4ad7daSAndroid Build Coastguard Worker if (in == NULL)
2455*cc4ad7daSAndroid Build Coastguard Worker return 0;
2456*cc4ad7daSAndroid Build Coastguard Worker
2457*cc4ad7daSAndroid Build Coastguard Worker idx = index_create();
2458*cc4ad7daSAndroid Build Coastguard Worker if (idx == NULL) {
2459*cc4ad7daSAndroid Build Coastguard Worker fclose(in);
2460*cc4ad7daSAndroid Build Coastguard Worker return -ENOMEM;
2461*cc4ad7daSAndroid Build Coastguard Worker }
2462*cc4ad7daSAndroid Build Coastguard Worker
2463*cc4ad7daSAndroid Build Coastguard Worker /* format: modname.key=value\0 */
2464*cc4ad7daSAndroid Build Coastguard Worker while (!feof(in) && !ferror(in)) {
2465*cc4ad7daSAndroid Build Coastguard Worker char alias[PATH_MAX];
2466*cc4ad7daSAndroid Build Coastguard Worker char modname[PATH_MAX];
2467*cc4ad7daSAndroid Build Coastguard Worker char value[PATH_MAX];
2468*cc4ad7daSAndroid Build Coastguard Worker size_t len;
2469*cc4ad7daSAndroid Build Coastguard Worker
2470*cc4ad7daSAndroid Build Coastguard Worker len = flush_stream_to(in, '.', modname, sizeof(modname));
2471*cc4ad7daSAndroid Build Coastguard Worker modname[len] = '\0';
2472*cc4ad7daSAndroid Build Coastguard Worker if (!len)
2473*cc4ad7daSAndroid Build Coastguard Worker continue;
2474*cc4ad7daSAndroid Build Coastguard Worker
2475*cc4ad7daSAndroid Build Coastguard Worker len = flush_stream_to(in, '=', value, sizeof(value));
2476*cc4ad7daSAndroid Build Coastguard Worker value[len] = '\0';
2477*cc4ad7daSAndroid Build Coastguard Worker if (!streq(value, "alias")) {
2478*cc4ad7daSAndroid Build Coastguard Worker flush_stream(in, '\0');
2479*cc4ad7daSAndroid Build Coastguard Worker continue;
2480*cc4ad7daSAndroid Build Coastguard Worker }
2481*cc4ad7daSAndroid Build Coastguard Worker
2482*cc4ad7daSAndroid Build Coastguard Worker len = flush_stream_to(in, '\0', value, sizeof(value));
2483*cc4ad7daSAndroid Build Coastguard Worker value[len] = '\0';
2484*cc4ad7daSAndroid Build Coastguard Worker if (!len)
2485*cc4ad7daSAndroid Build Coastguard Worker continue;
2486*cc4ad7daSAndroid Build Coastguard Worker
2487*cc4ad7daSAndroid Build Coastguard Worker alias[0] = '\0';
2488*cc4ad7daSAndroid Build Coastguard Worker if (alias_normalize(value, alias, NULL) < 0) {
2489*cc4ad7daSAndroid Build Coastguard Worker WRN("Unmatched bracket in %s\n", value);
2490*cc4ad7daSAndroid Build Coastguard Worker continue;
2491*cc4ad7daSAndroid Build Coastguard Worker }
2492*cc4ad7daSAndroid Build Coastguard Worker
2493*cc4ad7daSAndroid Build Coastguard Worker index_insert(idx, alias, modname, 0);
2494*cc4ad7daSAndroid Build Coastguard Worker }
2495*cc4ad7daSAndroid Build Coastguard Worker
2496*cc4ad7daSAndroid Build Coastguard Worker if (ferror(in)) {
2497*cc4ad7daSAndroid Build Coastguard Worker ret = -EINVAL;
2498*cc4ad7daSAndroid Build Coastguard Worker } else {
2499*cc4ad7daSAndroid Build Coastguard Worker index_write(idx, out);
2500*cc4ad7daSAndroid Build Coastguard Worker ret = 0;
2501*cc4ad7daSAndroid Build Coastguard Worker }
2502*cc4ad7daSAndroid Build Coastguard Worker
2503*cc4ad7daSAndroid Build Coastguard Worker index_destroy(idx);
2504*cc4ad7daSAndroid Build Coastguard Worker fclose(in);
2505*cc4ad7daSAndroid Build Coastguard Worker
2506*cc4ad7daSAndroid Build Coastguard Worker return ret;
2507*cc4ad7daSAndroid Build Coastguard Worker }
2508*cc4ad7daSAndroid Build Coastguard Worker
output_devname(struct depmod * depmod,FILE * out)2509*cc4ad7daSAndroid Build Coastguard Worker static int output_devname(struct depmod *depmod, FILE *out)
2510*cc4ad7daSAndroid Build Coastguard Worker {
2511*cc4ad7daSAndroid Build Coastguard Worker size_t i;
2512*cc4ad7daSAndroid Build Coastguard Worker bool empty = true;
2513*cc4ad7daSAndroid Build Coastguard Worker
2514*cc4ad7daSAndroid Build Coastguard Worker for (i = 0; i < depmod->modules.count; i++) {
2515*cc4ad7daSAndroid Build Coastguard Worker const struct mod *mod = depmod->modules.array[i];
2516*cc4ad7daSAndroid Build Coastguard Worker struct kmod_list *l;
2517*cc4ad7daSAndroid Build Coastguard Worker const char *devname = NULL;
2518*cc4ad7daSAndroid Build Coastguard Worker char type = '\0';
2519*cc4ad7daSAndroid Build Coastguard Worker unsigned int major = 0, minor = 0;
2520*cc4ad7daSAndroid Build Coastguard Worker
2521*cc4ad7daSAndroid Build Coastguard Worker kmod_list_foreach(l, mod->info_list) {
2522*cc4ad7daSAndroid Build Coastguard Worker const char *key = kmod_module_info_get_key(l);
2523*cc4ad7daSAndroid Build Coastguard Worker const char *value = kmod_module_info_get_value(l);
2524*cc4ad7daSAndroid Build Coastguard Worker unsigned int maj, min;
2525*cc4ad7daSAndroid Build Coastguard Worker
2526*cc4ad7daSAndroid Build Coastguard Worker if (!streq(key, "alias"))
2527*cc4ad7daSAndroid Build Coastguard Worker continue;
2528*cc4ad7daSAndroid Build Coastguard Worker
2529*cc4ad7daSAndroid Build Coastguard Worker if (strstartswith(value, "devname:"))
2530*cc4ad7daSAndroid Build Coastguard Worker devname = value + sizeof("devname:") - 1;
2531*cc4ad7daSAndroid Build Coastguard Worker else if (sscanf(value, "char-major-%u-%u",
2532*cc4ad7daSAndroid Build Coastguard Worker &maj, &min) == 2) {
2533*cc4ad7daSAndroid Build Coastguard Worker type = 'c';
2534*cc4ad7daSAndroid Build Coastguard Worker major = maj;
2535*cc4ad7daSAndroid Build Coastguard Worker minor = min;
2536*cc4ad7daSAndroid Build Coastguard Worker } else if (sscanf(value, "block-major-%u-%u",
2537*cc4ad7daSAndroid Build Coastguard Worker &maj, &min) == 2) {
2538*cc4ad7daSAndroid Build Coastguard Worker type = 'b';
2539*cc4ad7daSAndroid Build Coastguard Worker major = maj;
2540*cc4ad7daSAndroid Build Coastguard Worker minor = min;
2541*cc4ad7daSAndroid Build Coastguard Worker }
2542*cc4ad7daSAndroid Build Coastguard Worker
2543*cc4ad7daSAndroid Build Coastguard Worker if (type != '\0' && devname != NULL)
2544*cc4ad7daSAndroid Build Coastguard Worker break;
2545*cc4ad7daSAndroid Build Coastguard Worker }
2546*cc4ad7daSAndroid Build Coastguard Worker
2547*cc4ad7daSAndroid Build Coastguard Worker if (devname != NULL) {
2548*cc4ad7daSAndroid Build Coastguard Worker if (type != '\0') {
2549*cc4ad7daSAndroid Build Coastguard Worker if (empty) {
2550*cc4ad7daSAndroid Build Coastguard Worker fputs("# Device nodes to trigger on-demand module loading.\n",
2551*cc4ad7daSAndroid Build Coastguard Worker out);
2552*cc4ad7daSAndroid Build Coastguard Worker empty = false;
2553*cc4ad7daSAndroid Build Coastguard Worker }
2554*cc4ad7daSAndroid Build Coastguard Worker fprintf(out, "%s %s %c%u:%u\n", mod->modname,
2555*cc4ad7daSAndroid Build Coastguard Worker devname, type, major, minor);
2556*cc4ad7daSAndroid Build Coastguard Worker } else
2557*cc4ad7daSAndroid Build Coastguard Worker ERR("Module '%s' has devname (%s) but "
2558*cc4ad7daSAndroid Build Coastguard Worker "lacks major and minor information. "
2559*cc4ad7daSAndroid Build Coastguard Worker "Ignoring.\n", mod->modname, devname);
2560*cc4ad7daSAndroid Build Coastguard Worker }
2561*cc4ad7daSAndroid Build Coastguard Worker }
2562*cc4ad7daSAndroid Build Coastguard Worker
2563*cc4ad7daSAndroid Build Coastguard Worker return 0;
2564*cc4ad7daSAndroid Build Coastguard Worker }
2565*cc4ad7daSAndroid Build Coastguard Worker
depmod_output(struct depmod * depmod,FILE * out)2566*cc4ad7daSAndroid Build Coastguard Worker static int depmod_output(struct depmod *depmod, FILE *out)
2567*cc4ad7daSAndroid Build Coastguard Worker {
2568*cc4ad7daSAndroid Build Coastguard Worker static const struct depfile {
2569*cc4ad7daSAndroid Build Coastguard Worker const char *name;
2570*cc4ad7daSAndroid Build Coastguard Worker int (*cb)(struct depmod *depmod, FILE *out);
2571*cc4ad7daSAndroid Build Coastguard Worker } *itr, depfiles[] = {
2572*cc4ad7daSAndroid Build Coastguard Worker { "modules.dep", output_deps },
2573*cc4ad7daSAndroid Build Coastguard Worker { "modules.dep.bin", output_deps_bin },
2574*cc4ad7daSAndroid Build Coastguard Worker { "modules.alias", output_aliases },
2575*cc4ad7daSAndroid Build Coastguard Worker { "modules.alias.bin", output_aliases_bin },
2576*cc4ad7daSAndroid Build Coastguard Worker { "modules.softdep", output_softdeps },
2577*cc4ad7daSAndroid Build Coastguard Worker { "modules.symbols", output_symbols },
2578*cc4ad7daSAndroid Build Coastguard Worker { "modules.symbols.bin", output_symbols_bin },
2579*cc4ad7daSAndroid Build Coastguard Worker { "modules.builtin.bin", output_builtin_bin },
2580*cc4ad7daSAndroid Build Coastguard Worker { "modules.builtin.alias.bin", output_builtin_alias_bin },
2581*cc4ad7daSAndroid Build Coastguard Worker { "modules.devname", output_devname },
2582*cc4ad7daSAndroid Build Coastguard Worker { }
2583*cc4ad7daSAndroid Build Coastguard Worker };
2584*cc4ad7daSAndroid Build Coastguard Worker const char *dname = depmod->cfg->outdirname;
2585*cc4ad7daSAndroid Build Coastguard Worker int dfd, err = 0;
2586*cc4ad7daSAndroid Build Coastguard Worker struct timeval tv;
2587*cc4ad7daSAndroid Build Coastguard Worker
2588*cc4ad7daSAndroid Build Coastguard Worker gettimeofday(&tv, NULL);
2589*cc4ad7daSAndroid Build Coastguard Worker
2590*cc4ad7daSAndroid Build Coastguard Worker if (out != NULL)
2591*cc4ad7daSAndroid Build Coastguard Worker dfd = -1;
2592*cc4ad7daSAndroid Build Coastguard Worker else {
2593*cc4ad7daSAndroid Build Coastguard Worker err = mkdir_p(dname, strlen(dname), 0755);
2594*cc4ad7daSAndroid Build Coastguard Worker if (err < 0) {
2595*cc4ad7daSAndroid Build Coastguard Worker CRIT("could not create directory %s: %m\n", dname);
2596*cc4ad7daSAndroid Build Coastguard Worker return err;
2597*cc4ad7daSAndroid Build Coastguard Worker }
2598*cc4ad7daSAndroid Build Coastguard Worker dfd = open(dname, O_RDONLY);
2599*cc4ad7daSAndroid Build Coastguard Worker if (dfd < 0) {
2600*cc4ad7daSAndroid Build Coastguard Worker err = -errno;
2601*cc4ad7daSAndroid Build Coastguard Worker CRIT("could not open directory %s: %m\n", dname);
2602*cc4ad7daSAndroid Build Coastguard Worker return err;
2603*cc4ad7daSAndroid Build Coastguard Worker }
2604*cc4ad7daSAndroid Build Coastguard Worker }
2605*cc4ad7daSAndroid Build Coastguard Worker
2606*cc4ad7daSAndroid Build Coastguard Worker for (itr = depfiles; itr->name != NULL; itr++) {
2607*cc4ad7daSAndroid Build Coastguard Worker FILE *fp = out;
2608*cc4ad7daSAndroid Build Coastguard Worker char tmp[NAME_MAX] = "";
2609*cc4ad7daSAndroid Build Coastguard Worker int r, ferr;
2610*cc4ad7daSAndroid Build Coastguard Worker
2611*cc4ad7daSAndroid Build Coastguard Worker if (fp == NULL) {
2612*cc4ad7daSAndroid Build Coastguard Worker int flags = O_CREAT | O_EXCL | O_WRONLY;
2613*cc4ad7daSAndroid Build Coastguard Worker int mode = 0644;
2614*cc4ad7daSAndroid Build Coastguard Worker int fd;
2615*cc4ad7daSAndroid Build Coastguard Worker
2616*cc4ad7daSAndroid Build Coastguard Worker snprintf(tmp, sizeof(tmp), "%s.%i.%li.%li", itr->name, getpid(),
2617*cc4ad7daSAndroid Build Coastguard Worker tv.tv_usec, tv.tv_sec);
2618*cc4ad7daSAndroid Build Coastguard Worker fd = openat(dfd, tmp, flags, mode);
2619*cc4ad7daSAndroid Build Coastguard Worker if (fd < 0) {
2620*cc4ad7daSAndroid Build Coastguard Worker ERR("openat(%s, %s, %o, %o): %m\n",
2621*cc4ad7daSAndroid Build Coastguard Worker dname, tmp, flags, mode);
2622*cc4ad7daSAndroid Build Coastguard Worker continue;
2623*cc4ad7daSAndroid Build Coastguard Worker }
2624*cc4ad7daSAndroid Build Coastguard Worker fp = fdopen(fd, "wb");
2625*cc4ad7daSAndroid Build Coastguard Worker if (fp == NULL) {
2626*cc4ad7daSAndroid Build Coastguard Worker ERR("fdopen(%d=%s/%s): %m\n", fd, dname, tmp);
2627*cc4ad7daSAndroid Build Coastguard Worker close(fd);
2628*cc4ad7daSAndroid Build Coastguard Worker continue;
2629*cc4ad7daSAndroid Build Coastguard Worker }
2630*cc4ad7daSAndroid Build Coastguard Worker }
2631*cc4ad7daSAndroid Build Coastguard Worker
2632*cc4ad7daSAndroid Build Coastguard Worker r = itr->cb(depmod, fp);
2633*cc4ad7daSAndroid Build Coastguard Worker if (fp == out)
2634*cc4ad7daSAndroid Build Coastguard Worker continue;
2635*cc4ad7daSAndroid Build Coastguard Worker
2636*cc4ad7daSAndroid Build Coastguard Worker ferr = ferror(fp) | fclose(fp);
2637*cc4ad7daSAndroid Build Coastguard Worker
2638*cc4ad7daSAndroid Build Coastguard Worker if (r < 0) {
2639*cc4ad7daSAndroid Build Coastguard Worker if (unlinkat(dfd, tmp, 0) != 0)
2640*cc4ad7daSAndroid Build Coastguard Worker ERR("unlinkat(%s, %s): %m\n", dname, tmp);
2641*cc4ad7daSAndroid Build Coastguard Worker
2642*cc4ad7daSAndroid Build Coastguard Worker ERR("Could not write index '%s': %s\n", itr->name,
2643*cc4ad7daSAndroid Build Coastguard Worker strerror(-r));
2644*cc4ad7daSAndroid Build Coastguard Worker err = -errno;
2645*cc4ad7daSAndroid Build Coastguard Worker break;
2646*cc4ad7daSAndroid Build Coastguard Worker }
2647*cc4ad7daSAndroid Build Coastguard Worker
2648*cc4ad7daSAndroid Build Coastguard Worker if (renameat(dfd, tmp, dfd, itr->name) != 0) {
2649*cc4ad7daSAndroid Build Coastguard Worker err = -errno;
2650*cc4ad7daSAndroid Build Coastguard Worker CRIT("renameat(%s, %s, %s, %s): %m\n",
2651*cc4ad7daSAndroid Build Coastguard Worker dname, tmp, dname, itr->name);
2652*cc4ad7daSAndroid Build Coastguard Worker break;
2653*cc4ad7daSAndroid Build Coastguard Worker }
2654*cc4ad7daSAndroid Build Coastguard Worker
2655*cc4ad7daSAndroid Build Coastguard Worker if (ferr) {
2656*cc4ad7daSAndroid Build Coastguard Worker err = -ENOSPC;
2657*cc4ad7daSAndroid Build Coastguard Worker ERR("Could not create index '%s'. Output is truncated: %s\n",
2658*cc4ad7daSAndroid Build Coastguard Worker itr->name, strerror(-err));
2659*cc4ad7daSAndroid Build Coastguard Worker break;
2660*cc4ad7daSAndroid Build Coastguard Worker }
2661*cc4ad7daSAndroid Build Coastguard Worker }
2662*cc4ad7daSAndroid Build Coastguard Worker
2663*cc4ad7daSAndroid Build Coastguard Worker if (dfd >= 0)
2664*cc4ad7daSAndroid Build Coastguard Worker close(dfd);
2665*cc4ad7daSAndroid Build Coastguard Worker
2666*cc4ad7daSAndroid Build Coastguard Worker return err;
2667*cc4ad7daSAndroid Build Coastguard Worker }
2668*cc4ad7daSAndroid Build Coastguard Worker
depmod_add_fake_syms(struct depmod * depmod)2669*cc4ad7daSAndroid Build Coastguard Worker static void depmod_add_fake_syms(struct depmod *depmod)
2670*cc4ad7daSAndroid Build Coastguard Worker {
2671*cc4ad7daSAndroid Build Coastguard Worker /* __this_module is magic inserted by kernel loader. */
2672*cc4ad7daSAndroid Build Coastguard Worker depmod_symbol_add(depmod, "__this_module", true, 0, NULL);
2673*cc4ad7daSAndroid Build Coastguard Worker /* On S390, this is faked up too */
2674*cc4ad7daSAndroid Build Coastguard Worker depmod_symbol_add(depmod, "_GLOBAL_OFFSET_TABLE_", true, 0, NULL);
2675*cc4ad7daSAndroid Build Coastguard Worker /* On PowerPC64 ABIv2, .TOC. is more or less _GLOBAL_OFFSET_TABLE_ */
2676*cc4ad7daSAndroid Build Coastguard Worker if (!depmod_symbol_find(depmod, "TOC."))
2677*cc4ad7daSAndroid Build Coastguard Worker depmod_symbol_add(depmod, "TOC.", true, 0, NULL);
2678*cc4ad7daSAndroid Build Coastguard Worker }
2679*cc4ad7daSAndroid Build Coastguard Worker
depmod_load_symvers(struct depmod * depmod,const char * filename)2680*cc4ad7daSAndroid Build Coastguard Worker static int depmod_load_symvers(struct depmod *depmod, const char *filename)
2681*cc4ad7daSAndroid Build Coastguard Worker {
2682*cc4ad7daSAndroid Build Coastguard Worker char line[10240];
2683*cc4ad7daSAndroid Build Coastguard Worker FILE *fp;
2684*cc4ad7daSAndroid Build Coastguard Worker unsigned int linenum = 0;
2685*cc4ad7daSAndroid Build Coastguard Worker
2686*cc4ad7daSAndroid Build Coastguard Worker fp = fopen(filename, "r");
2687*cc4ad7daSAndroid Build Coastguard Worker if (fp == NULL) {
2688*cc4ad7daSAndroid Build Coastguard Worker int err = -errno;
2689*cc4ad7daSAndroid Build Coastguard Worker DBG("load symvers: %s: %m\n", filename);
2690*cc4ad7daSAndroid Build Coastguard Worker return err;
2691*cc4ad7daSAndroid Build Coastguard Worker }
2692*cc4ad7daSAndroid Build Coastguard Worker DBG("load symvers: %s\n", filename);
2693*cc4ad7daSAndroid Build Coastguard Worker
2694*cc4ad7daSAndroid Build Coastguard Worker /* eg. "0xb352177e\tfind_first_bit\tvmlinux\tEXPORT_SYMBOL" */
2695*cc4ad7daSAndroid Build Coastguard Worker while (fgets(line, sizeof(line), fp) != NULL) {
2696*cc4ad7daSAndroid Build Coastguard Worker const char *ver, *sym, *where;
2697*cc4ad7daSAndroid Build Coastguard Worker char *verend;
2698*cc4ad7daSAndroid Build Coastguard Worker uint64_t crc;
2699*cc4ad7daSAndroid Build Coastguard Worker
2700*cc4ad7daSAndroid Build Coastguard Worker linenum++;
2701*cc4ad7daSAndroid Build Coastguard Worker
2702*cc4ad7daSAndroid Build Coastguard Worker ver = strtok(line, " \t");
2703*cc4ad7daSAndroid Build Coastguard Worker sym = strtok(NULL, " \t");
2704*cc4ad7daSAndroid Build Coastguard Worker where = strtok(NULL, " \t");
2705*cc4ad7daSAndroid Build Coastguard Worker if (!ver || !sym || !where)
2706*cc4ad7daSAndroid Build Coastguard Worker continue;
2707*cc4ad7daSAndroid Build Coastguard Worker
2708*cc4ad7daSAndroid Build Coastguard Worker if (!streq(where, "vmlinux"))
2709*cc4ad7daSAndroid Build Coastguard Worker continue;
2710*cc4ad7daSAndroid Build Coastguard Worker
2711*cc4ad7daSAndroid Build Coastguard Worker crc = strtoull(ver, &verend, 16);
2712*cc4ad7daSAndroid Build Coastguard Worker if (verend[0] != '\0') {
2713*cc4ad7daSAndroid Build Coastguard Worker ERR("%s:%u Invalid symbol version %s: %m\n",
2714*cc4ad7daSAndroid Build Coastguard Worker filename, linenum, ver);
2715*cc4ad7daSAndroid Build Coastguard Worker continue;
2716*cc4ad7daSAndroid Build Coastguard Worker }
2717*cc4ad7daSAndroid Build Coastguard Worker
2718*cc4ad7daSAndroid Build Coastguard Worker depmod_symbol_add(depmod, sym, false, crc, NULL);
2719*cc4ad7daSAndroid Build Coastguard Worker }
2720*cc4ad7daSAndroid Build Coastguard Worker depmod_add_fake_syms(depmod);
2721*cc4ad7daSAndroid Build Coastguard Worker
2722*cc4ad7daSAndroid Build Coastguard Worker DBG("loaded symvers: %s\n", filename);
2723*cc4ad7daSAndroid Build Coastguard Worker
2724*cc4ad7daSAndroid Build Coastguard Worker fclose(fp);
2725*cc4ad7daSAndroid Build Coastguard Worker return 0;
2726*cc4ad7daSAndroid Build Coastguard Worker }
2727*cc4ad7daSAndroid Build Coastguard Worker
depmod_load_system_map(struct depmod * depmod,const char * filename)2728*cc4ad7daSAndroid Build Coastguard Worker static int depmod_load_system_map(struct depmod *depmod, const char *filename)
2729*cc4ad7daSAndroid Build Coastguard Worker {
2730*cc4ad7daSAndroid Build Coastguard Worker const char ksymstr[] = "__ksymtab_";
2731*cc4ad7daSAndroid Build Coastguard Worker const size_t ksymstr_len = sizeof(ksymstr) - 1;
2732*cc4ad7daSAndroid Build Coastguard Worker char line[10240];
2733*cc4ad7daSAndroid Build Coastguard Worker FILE *fp;
2734*cc4ad7daSAndroid Build Coastguard Worker unsigned int linenum = 0;
2735*cc4ad7daSAndroid Build Coastguard Worker
2736*cc4ad7daSAndroid Build Coastguard Worker fp = fopen(filename, "r");
2737*cc4ad7daSAndroid Build Coastguard Worker if (fp == NULL) {
2738*cc4ad7daSAndroid Build Coastguard Worker int err = -errno;
2739*cc4ad7daSAndroid Build Coastguard Worker DBG("load System.map: %s: %m\n", filename);
2740*cc4ad7daSAndroid Build Coastguard Worker return err;
2741*cc4ad7daSAndroid Build Coastguard Worker }
2742*cc4ad7daSAndroid Build Coastguard Worker DBG("load System.map: %s\n", filename);
2743*cc4ad7daSAndroid Build Coastguard Worker
2744*cc4ad7daSAndroid Build Coastguard Worker /* eg. c0294200 R __ksymtab_devfs_alloc_devnum */
2745*cc4ad7daSAndroid Build Coastguard Worker while (fgets(line, sizeof(line), fp) != NULL) {
2746*cc4ad7daSAndroid Build Coastguard Worker char *p, *end;
2747*cc4ad7daSAndroid Build Coastguard Worker
2748*cc4ad7daSAndroid Build Coastguard Worker linenum++;
2749*cc4ad7daSAndroid Build Coastguard Worker
2750*cc4ad7daSAndroid Build Coastguard Worker p = strchr(line, ' ');
2751*cc4ad7daSAndroid Build Coastguard Worker if (p == NULL)
2752*cc4ad7daSAndroid Build Coastguard Worker goto invalid_syntax;
2753*cc4ad7daSAndroid Build Coastguard Worker p++;
2754*cc4ad7daSAndroid Build Coastguard Worker p = strchr(p, ' ');
2755*cc4ad7daSAndroid Build Coastguard Worker if (p == NULL)
2756*cc4ad7daSAndroid Build Coastguard Worker goto invalid_syntax;
2757*cc4ad7daSAndroid Build Coastguard Worker p++;
2758*cc4ad7daSAndroid Build Coastguard Worker
2759*cc4ad7daSAndroid Build Coastguard Worker /* skip prefix */
2760*cc4ad7daSAndroid Build Coastguard Worker if (p[0] == depmod->cfg->sym_prefix)
2761*cc4ad7daSAndroid Build Coastguard Worker p++;
2762*cc4ad7daSAndroid Build Coastguard Worker
2763*cc4ad7daSAndroid Build Coastguard Worker /* Covers gpl-only and normal symbols. */
2764*cc4ad7daSAndroid Build Coastguard Worker if (strncmp(p, ksymstr, ksymstr_len) != 0)
2765*cc4ad7daSAndroid Build Coastguard Worker continue;
2766*cc4ad7daSAndroid Build Coastguard Worker
2767*cc4ad7daSAndroid Build Coastguard Worker end = strchr(p, '\n');
2768*cc4ad7daSAndroid Build Coastguard Worker if (end != NULL)
2769*cc4ad7daSAndroid Build Coastguard Worker *end = '\0';
2770*cc4ad7daSAndroid Build Coastguard Worker
2771*cc4ad7daSAndroid Build Coastguard Worker depmod_symbol_add(depmod, p + ksymstr_len, true, 0, NULL);
2772*cc4ad7daSAndroid Build Coastguard Worker continue;
2773*cc4ad7daSAndroid Build Coastguard Worker
2774*cc4ad7daSAndroid Build Coastguard Worker invalid_syntax:
2775*cc4ad7daSAndroid Build Coastguard Worker ERR("%s:%u: invalid line: %s\n", filename, linenum, line);
2776*cc4ad7daSAndroid Build Coastguard Worker }
2777*cc4ad7daSAndroid Build Coastguard Worker depmod_add_fake_syms(depmod);
2778*cc4ad7daSAndroid Build Coastguard Worker
2779*cc4ad7daSAndroid Build Coastguard Worker DBG("loaded System.map: %s\n", filename);
2780*cc4ad7daSAndroid Build Coastguard Worker
2781*cc4ad7daSAndroid Build Coastguard Worker fclose(fp);
2782*cc4ad7daSAndroid Build Coastguard Worker return 0;
2783*cc4ad7daSAndroid Build Coastguard Worker }
2784*cc4ad7daSAndroid Build Coastguard Worker
2785*cc4ad7daSAndroid Build Coastguard Worker
depfile_up_to_date_dir(DIR * d,time_t mtime,size_t baselen,char * path)2786*cc4ad7daSAndroid Build Coastguard Worker static int depfile_up_to_date_dir(DIR *d, time_t mtime, size_t baselen, char *path)
2787*cc4ad7daSAndroid Build Coastguard Worker {
2788*cc4ad7daSAndroid Build Coastguard Worker struct dirent *de;
2789*cc4ad7daSAndroid Build Coastguard Worker int err = 1, dfd = dirfd(d);
2790*cc4ad7daSAndroid Build Coastguard Worker
2791*cc4ad7daSAndroid Build Coastguard Worker while ((de = readdir(d)) != NULL) {
2792*cc4ad7daSAndroid Build Coastguard Worker const char *name = de->d_name;
2793*cc4ad7daSAndroid Build Coastguard Worker size_t namelen;
2794*cc4ad7daSAndroid Build Coastguard Worker struct stat st;
2795*cc4ad7daSAndroid Build Coastguard Worker
2796*cc4ad7daSAndroid Build Coastguard Worker if (name[0] == '.' && (name[1] == '\0' ||
2797*cc4ad7daSAndroid Build Coastguard Worker (name[1] == '.' && name[2] == '\0')))
2798*cc4ad7daSAndroid Build Coastguard Worker continue;
2799*cc4ad7daSAndroid Build Coastguard Worker if (streq(name, "build") || streq(name, "source"))
2800*cc4ad7daSAndroid Build Coastguard Worker continue;
2801*cc4ad7daSAndroid Build Coastguard Worker namelen = strlen(name);
2802*cc4ad7daSAndroid Build Coastguard Worker if (baselen + namelen + 2 >= PATH_MAX) {
2803*cc4ad7daSAndroid Build Coastguard Worker path[baselen] = '\0';
2804*cc4ad7daSAndroid Build Coastguard Worker ERR("path is too long %s%s\n", path, name);
2805*cc4ad7daSAndroid Build Coastguard Worker continue;
2806*cc4ad7daSAndroid Build Coastguard Worker }
2807*cc4ad7daSAndroid Build Coastguard Worker
2808*cc4ad7daSAndroid Build Coastguard Worker if (fstatat(dfd, name, &st, 0) < 0) {
2809*cc4ad7daSAndroid Build Coastguard Worker ERR("fstatat(%d, %s): %m\n", dfd, name);
2810*cc4ad7daSAndroid Build Coastguard Worker continue;
2811*cc4ad7daSAndroid Build Coastguard Worker }
2812*cc4ad7daSAndroid Build Coastguard Worker
2813*cc4ad7daSAndroid Build Coastguard Worker if (S_ISDIR(st.st_mode)) {
2814*cc4ad7daSAndroid Build Coastguard Worker int fd;
2815*cc4ad7daSAndroid Build Coastguard Worker DIR *subdir;
2816*cc4ad7daSAndroid Build Coastguard Worker memcpy(path + baselen, name, namelen + 1);
2817*cc4ad7daSAndroid Build Coastguard Worker if (baselen + namelen + 2 + NAME_MAX >= PATH_MAX) {
2818*cc4ad7daSAndroid Build Coastguard Worker ERR("directory path is too long %s\n", path);
2819*cc4ad7daSAndroid Build Coastguard Worker continue;
2820*cc4ad7daSAndroid Build Coastguard Worker }
2821*cc4ad7daSAndroid Build Coastguard Worker fd = openat(dfd, name, O_RDONLY);
2822*cc4ad7daSAndroid Build Coastguard Worker if (fd < 0) {
2823*cc4ad7daSAndroid Build Coastguard Worker ERR("openat(%d, %s, O_RDONLY): %m\n",
2824*cc4ad7daSAndroid Build Coastguard Worker dfd, name);
2825*cc4ad7daSAndroid Build Coastguard Worker continue;
2826*cc4ad7daSAndroid Build Coastguard Worker }
2827*cc4ad7daSAndroid Build Coastguard Worker subdir = fdopendir(fd);
2828*cc4ad7daSAndroid Build Coastguard Worker if (subdir == NULL) {
2829*cc4ad7daSAndroid Build Coastguard Worker ERR("fdopendir(%d): %m\n", fd);
2830*cc4ad7daSAndroid Build Coastguard Worker close(fd);
2831*cc4ad7daSAndroid Build Coastguard Worker continue;
2832*cc4ad7daSAndroid Build Coastguard Worker }
2833*cc4ad7daSAndroid Build Coastguard Worker path[baselen + namelen] = '/';
2834*cc4ad7daSAndroid Build Coastguard Worker path[baselen + namelen + 1] = '\0';
2835*cc4ad7daSAndroid Build Coastguard Worker err = depfile_up_to_date_dir(subdir, mtime,
2836*cc4ad7daSAndroid Build Coastguard Worker baselen + namelen + 1,
2837*cc4ad7daSAndroid Build Coastguard Worker path);
2838*cc4ad7daSAndroid Build Coastguard Worker closedir(subdir);
2839*cc4ad7daSAndroid Build Coastguard Worker } else if (S_ISREG(st.st_mode)) {
2840*cc4ad7daSAndroid Build Coastguard Worker if (!path_ends_with_kmod_ext(name, namelen))
2841*cc4ad7daSAndroid Build Coastguard Worker continue;
2842*cc4ad7daSAndroid Build Coastguard Worker
2843*cc4ad7daSAndroid Build Coastguard Worker memcpy(path + baselen, name, namelen + 1);
2844*cc4ad7daSAndroid Build Coastguard Worker err = st.st_mtime <= mtime;
2845*cc4ad7daSAndroid Build Coastguard Worker if (err == 0) {
2846*cc4ad7daSAndroid Build Coastguard Worker DBG("%s %"PRIu64" is newer than %"PRIu64"\n",
2847*cc4ad7daSAndroid Build Coastguard Worker path, (uint64_t)st.st_mtime,
2848*cc4ad7daSAndroid Build Coastguard Worker (uint64_t)mtime);
2849*cc4ad7daSAndroid Build Coastguard Worker }
2850*cc4ad7daSAndroid Build Coastguard Worker } else {
2851*cc4ad7daSAndroid Build Coastguard Worker ERR("unsupported file type %s: %o\n",
2852*cc4ad7daSAndroid Build Coastguard Worker path, st.st_mode & S_IFMT);
2853*cc4ad7daSAndroid Build Coastguard Worker continue;
2854*cc4ad7daSAndroid Build Coastguard Worker }
2855*cc4ad7daSAndroid Build Coastguard Worker
2856*cc4ad7daSAndroid Build Coastguard Worker if (err == 0)
2857*cc4ad7daSAndroid Build Coastguard Worker break; /* outdated! */
2858*cc4ad7daSAndroid Build Coastguard Worker else if (err < 0) {
2859*cc4ad7daSAndroid Build Coastguard Worker path[baselen + namelen] = '\0';
2860*cc4ad7daSAndroid Build Coastguard Worker ERR("failed %s: %s\n", path, strerror(-err));
2861*cc4ad7daSAndroid Build Coastguard Worker err = 1; /* ignore errors */
2862*cc4ad7daSAndroid Build Coastguard Worker }
2863*cc4ad7daSAndroid Build Coastguard Worker }
2864*cc4ad7daSAndroid Build Coastguard Worker
2865*cc4ad7daSAndroid Build Coastguard Worker return err;
2866*cc4ad7daSAndroid Build Coastguard Worker }
2867*cc4ad7daSAndroid Build Coastguard Worker
2868*cc4ad7daSAndroid Build Coastguard Worker /* uptodate: 1, outdated: 0, errors < 0 */
depfile_up_to_date(const char * dirname)2869*cc4ad7daSAndroid Build Coastguard Worker static int depfile_up_to_date(const char *dirname)
2870*cc4ad7daSAndroid Build Coastguard Worker {
2871*cc4ad7daSAndroid Build Coastguard Worker char path[PATH_MAX];
2872*cc4ad7daSAndroid Build Coastguard Worker DIR *d = opendir(dirname);
2873*cc4ad7daSAndroid Build Coastguard Worker struct stat st;
2874*cc4ad7daSAndroid Build Coastguard Worker size_t baselen;
2875*cc4ad7daSAndroid Build Coastguard Worker int err;
2876*cc4ad7daSAndroid Build Coastguard Worker if (d == NULL) {
2877*cc4ad7daSAndroid Build Coastguard Worker err = -errno;
2878*cc4ad7daSAndroid Build Coastguard Worker ERR("could not open directory %s: %m\n", dirname);
2879*cc4ad7daSAndroid Build Coastguard Worker return err;
2880*cc4ad7daSAndroid Build Coastguard Worker }
2881*cc4ad7daSAndroid Build Coastguard Worker
2882*cc4ad7daSAndroid Build Coastguard Worker if (fstatat(dirfd(d), "modules.dep", &st, 0) != 0) {
2883*cc4ad7daSAndroid Build Coastguard Worker err = -errno;
2884*cc4ad7daSAndroid Build Coastguard Worker ERR("could not fstatat(%s, modules.dep): %m\n", dirname);
2885*cc4ad7daSAndroid Build Coastguard Worker closedir(d);
2886*cc4ad7daSAndroid Build Coastguard Worker return err;
2887*cc4ad7daSAndroid Build Coastguard Worker }
2888*cc4ad7daSAndroid Build Coastguard Worker
2889*cc4ad7daSAndroid Build Coastguard Worker baselen = strlen(dirname);
2890*cc4ad7daSAndroid Build Coastguard Worker memcpy(path, dirname, baselen);
2891*cc4ad7daSAndroid Build Coastguard Worker path[baselen] = '/';
2892*cc4ad7daSAndroid Build Coastguard Worker baselen++;
2893*cc4ad7daSAndroid Build Coastguard Worker path[baselen] = '\0';
2894*cc4ad7daSAndroid Build Coastguard Worker
2895*cc4ad7daSAndroid Build Coastguard Worker err = depfile_up_to_date_dir(d, st.st_mtime, baselen, path);
2896*cc4ad7daSAndroid Build Coastguard Worker closedir(d);
2897*cc4ad7daSAndroid Build Coastguard Worker return err;
2898*cc4ad7daSAndroid Build Coastguard Worker }
2899*cc4ad7daSAndroid Build Coastguard Worker
is_version_number(const char * version)2900*cc4ad7daSAndroid Build Coastguard Worker static int is_version_number(const char *version)
2901*cc4ad7daSAndroid Build Coastguard Worker {
2902*cc4ad7daSAndroid Build Coastguard Worker unsigned int d1, d2;
2903*cc4ad7daSAndroid Build Coastguard Worker return (sscanf(version, "%u.%u", &d1, &d2) == 2);
2904*cc4ad7daSAndroid Build Coastguard Worker }
2905*cc4ad7daSAndroid Build Coastguard Worker
do_depmod(int argc,char * argv[])2906*cc4ad7daSAndroid Build Coastguard Worker static int do_depmod(int argc, char *argv[])
2907*cc4ad7daSAndroid Build Coastguard Worker {
2908*cc4ad7daSAndroid Build Coastguard Worker FILE *out = NULL;
2909*cc4ad7daSAndroid Build Coastguard Worker int err = 0, all = 0, maybe_all = 0, n_config_paths = 0;
2910*cc4ad7daSAndroid Build Coastguard Worker _cleanup_free_ char *root = NULL;
2911*cc4ad7daSAndroid Build Coastguard Worker _cleanup_free_ char *out_root = NULL;
2912*cc4ad7daSAndroid Build Coastguard Worker _cleanup_free_ const char **config_paths = NULL;
2913*cc4ad7daSAndroid Build Coastguard Worker const char *system_map = NULL;
2914*cc4ad7daSAndroid Build Coastguard Worker const char *module_symvers = NULL;
2915*cc4ad7daSAndroid Build Coastguard Worker const char *null_kmod_config = NULL;
2916*cc4ad7daSAndroid Build Coastguard Worker struct utsname un;
2917*cc4ad7daSAndroid Build Coastguard Worker struct kmod_ctx *ctx = NULL;
2918*cc4ad7daSAndroid Build Coastguard Worker struct cfg cfg;
2919*cc4ad7daSAndroid Build Coastguard Worker struct depmod depmod;
2920*cc4ad7daSAndroid Build Coastguard Worker
2921*cc4ad7daSAndroid Build Coastguard Worker memset(&cfg, 0, sizeof(cfg));
2922*cc4ad7daSAndroid Build Coastguard Worker memset(&depmod, 0, sizeof(depmod));
2923*cc4ad7daSAndroid Build Coastguard Worker
2924*cc4ad7daSAndroid Build Coastguard Worker for (;;) {
2925*cc4ad7daSAndroid Build Coastguard Worker int c, idx = 0;
2926*cc4ad7daSAndroid Build Coastguard Worker c = getopt_long(argc, argv, cmdopts_s, cmdopts, &idx);
2927*cc4ad7daSAndroid Build Coastguard Worker if (c == -1)
2928*cc4ad7daSAndroid Build Coastguard Worker break;
2929*cc4ad7daSAndroid Build Coastguard Worker switch (c) {
2930*cc4ad7daSAndroid Build Coastguard Worker case 'a':
2931*cc4ad7daSAndroid Build Coastguard Worker all = 1;
2932*cc4ad7daSAndroid Build Coastguard Worker break;
2933*cc4ad7daSAndroid Build Coastguard Worker case 'A':
2934*cc4ad7daSAndroid Build Coastguard Worker maybe_all = 1;
2935*cc4ad7daSAndroid Build Coastguard Worker break;
2936*cc4ad7daSAndroid Build Coastguard Worker case 'b':
2937*cc4ad7daSAndroid Build Coastguard Worker if (root)
2938*cc4ad7daSAndroid Build Coastguard Worker free(root);
2939*cc4ad7daSAndroid Build Coastguard Worker root = path_make_absolute_cwd(optarg);
2940*cc4ad7daSAndroid Build Coastguard Worker break;
2941*cc4ad7daSAndroid Build Coastguard Worker case 'o':
2942*cc4ad7daSAndroid Build Coastguard Worker if (out_root)
2943*cc4ad7daSAndroid Build Coastguard Worker free(out_root);
2944*cc4ad7daSAndroid Build Coastguard Worker out_root = path_make_absolute_cwd(optarg);
2945*cc4ad7daSAndroid Build Coastguard Worker break;
2946*cc4ad7daSAndroid Build Coastguard Worker case 'C': {
2947*cc4ad7daSAndroid Build Coastguard Worker size_t bytes = sizeof(char *) * (n_config_paths + 2);
2948*cc4ad7daSAndroid Build Coastguard Worker void *tmp = realloc(config_paths, bytes);
2949*cc4ad7daSAndroid Build Coastguard Worker if (!tmp) {
2950*cc4ad7daSAndroid Build Coastguard Worker fputs("Error: out-of-memory\n", stderr);
2951*cc4ad7daSAndroid Build Coastguard Worker goto cmdline_failed;
2952*cc4ad7daSAndroid Build Coastguard Worker }
2953*cc4ad7daSAndroid Build Coastguard Worker config_paths = tmp;
2954*cc4ad7daSAndroid Build Coastguard Worker config_paths[n_config_paths] = optarg;
2955*cc4ad7daSAndroid Build Coastguard Worker n_config_paths++;
2956*cc4ad7daSAndroid Build Coastguard Worker config_paths[n_config_paths] = NULL;
2957*cc4ad7daSAndroid Build Coastguard Worker break;
2958*cc4ad7daSAndroid Build Coastguard Worker }
2959*cc4ad7daSAndroid Build Coastguard Worker case 'E':
2960*cc4ad7daSAndroid Build Coastguard Worker module_symvers = optarg;
2961*cc4ad7daSAndroid Build Coastguard Worker cfg.check_symvers = 1;
2962*cc4ad7daSAndroid Build Coastguard Worker break;
2963*cc4ad7daSAndroid Build Coastguard Worker case 'F':
2964*cc4ad7daSAndroid Build Coastguard Worker system_map = optarg;
2965*cc4ad7daSAndroid Build Coastguard Worker break;
2966*cc4ad7daSAndroid Build Coastguard Worker case 'e':
2967*cc4ad7daSAndroid Build Coastguard Worker cfg.print_unknown = 1;
2968*cc4ad7daSAndroid Build Coastguard Worker break;
2969*cc4ad7daSAndroid Build Coastguard Worker case 'v':
2970*cc4ad7daSAndroid Build Coastguard Worker verbose++;
2971*cc4ad7daSAndroid Build Coastguard Worker break;
2972*cc4ad7daSAndroid Build Coastguard Worker case 'n':
2973*cc4ad7daSAndroid Build Coastguard Worker out = stdout;
2974*cc4ad7daSAndroid Build Coastguard Worker break;
2975*cc4ad7daSAndroid Build Coastguard Worker case 'P':
2976*cc4ad7daSAndroid Build Coastguard Worker if (optarg[1] != '\0') {
2977*cc4ad7daSAndroid Build Coastguard Worker CRIT("-P only takes a single char\n");
2978*cc4ad7daSAndroid Build Coastguard Worker goto cmdline_failed;
2979*cc4ad7daSAndroid Build Coastguard Worker }
2980*cc4ad7daSAndroid Build Coastguard Worker cfg.sym_prefix = optarg[0];
2981*cc4ad7daSAndroid Build Coastguard Worker break;
2982*cc4ad7daSAndroid Build Coastguard Worker case 'w':
2983*cc4ad7daSAndroid Build Coastguard Worker cfg.warn_dups = 1;
2984*cc4ad7daSAndroid Build Coastguard Worker break;
2985*cc4ad7daSAndroid Build Coastguard Worker case 'u':
2986*cc4ad7daSAndroid Build Coastguard Worker case 'q':
2987*cc4ad7daSAndroid Build Coastguard Worker case 'r':
2988*cc4ad7daSAndroid Build Coastguard Worker case 'm':
2989*cc4ad7daSAndroid Build Coastguard Worker if (idx > 0)
2990*cc4ad7daSAndroid Build Coastguard Worker WRN("Ignored deprecated option --%s\n",
2991*cc4ad7daSAndroid Build Coastguard Worker cmdopts[idx].name);
2992*cc4ad7daSAndroid Build Coastguard Worker else
2993*cc4ad7daSAndroid Build Coastguard Worker WRN("Ignored deprecated option -%c\n", c);
2994*cc4ad7daSAndroid Build Coastguard Worker
2995*cc4ad7daSAndroid Build Coastguard Worker break;
2996*cc4ad7daSAndroid Build Coastguard Worker case 'h':
2997*cc4ad7daSAndroid Build Coastguard Worker help();
2998*cc4ad7daSAndroid Build Coastguard Worker return EXIT_SUCCESS;
2999*cc4ad7daSAndroid Build Coastguard Worker case 'V':
3000*cc4ad7daSAndroid Build Coastguard Worker puts(PACKAGE " version " VERSION);
3001*cc4ad7daSAndroid Build Coastguard Worker puts(KMOD_FEATURES);
3002*cc4ad7daSAndroid Build Coastguard Worker return EXIT_SUCCESS;
3003*cc4ad7daSAndroid Build Coastguard Worker case '?':
3004*cc4ad7daSAndroid Build Coastguard Worker goto cmdline_failed;
3005*cc4ad7daSAndroid Build Coastguard Worker default:
3006*cc4ad7daSAndroid Build Coastguard Worker ERR("unexpected getopt_long() value '%c'.\n", c);
3007*cc4ad7daSAndroid Build Coastguard Worker goto cmdline_failed;
3008*cc4ad7daSAndroid Build Coastguard Worker }
3009*cc4ad7daSAndroid Build Coastguard Worker }
3010*cc4ad7daSAndroid Build Coastguard Worker
3011*cc4ad7daSAndroid Build Coastguard Worker if (optind < argc) {
3012*cc4ad7daSAndroid Build Coastguard Worker if (!is_version_number(argv[optind])) {
3013*cc4ad7daSAndroid Build Coastguard Worker ERR("Bad version passed %s\n", argv[optind]);
3014*cc4ad7daSAndroid Build Coastguard Worker goto cmdline_failed;
3015*cc4ad7daSAndroid Build Coastguard Worker }
3016*cc4ad7daSAndroid Build Coastguard Worker cfg.kversion = argv[optind];
3017*cc4ad7daSAndroid Build Coastguard Worker optind++;
3018*cc4ad7daSAndroid Build Coastguard Worker } else {
3019*cc4ad7daSAndroid Build Coastguard Worker if (uname(&un) < 0) {
3020*cc4ad7daSAndroid Build Coastguard Worker CRIT("uname() failed: %s\n", strerror(errno));
3021*cc4ad7daSAndroid Build Coastguard Worker goto cmdline_failed;
3022*cc4ad7daSAndroid Build Coastguard Worker }
3023*cc4ad7daSAndroid Build Coastguard Worker cfg.kversion = un.release;
3024*cc4ad7daSAndroid Build Coastguard Worker }
3025*cc4ad7daSAndroid Build Coastguard Worker
3026*cc4ad7daSAndroid Build Coastguard Worker cfg.dirnamelen = snprintf(cfg.dirname, PATH_MAX,
3027*cc4ad7daSAndroid Build Coastguard Worker "%s" MODULE_DIRECTORY "/%s",
3028*cc4ad7daSAndroid Build Coastguard Worker root ?: "", cfg.kversion);
3029*cc4ad7daSAndroid Build Coastguard Worker
3030*cc4ad7daSAndroid Build Coastguard Worker cfg.outdirnamelen = snprintf(cfg.outdirname, PATH_MAX,
3031*cc4ad7daSAndroid Build Coastguard Worker "%s" MODULE_DIRECTORY "/%s",
3032*cc4ad7daSAndroid Build Coastguard Worker out_root ?: (root ?: ""), cfg.kversion);
3033*cc4ad7daSAndroid Build Coastguard Worker
3034*cc4ad7daSAndroid Build Coastguard Worker if (optind == argc)
3035*cc4ad7daSAndroid Build Coastguard Worker all = 1;
3036*cc4ad7daSAndroid Build Coastguard Worker
3037*cc4ad7daSAndroid Build Coastguard Worker if (maybe_all) {
3038*cc4ad7daSAndroid Build Coastguard Worker if (out == stdout)
3039*cc4ad7daSAndroid Build Coastguard Worker goto done;
3040*cc4ad7daSAndroid Build Coastguard Worker /* ignore up-to-date errors (< 0) */
3041*cc4ad7daSAndroid Build Coastguard Worker if (depfile_up_to_date(cfg.dirname) == 1)
3042*cc4ad7daSAndroid Build Coastguard Worker goto done;
3043*cc4ad7daSAndroid Build Coastguard Worker all = 1;
3044*cc4ad7daSAndroid Build Coastguard Worker }
3045*cc4ad7daSAndroid Build Coastguard Worker
3046*cc4ad7daSAndroid Build Coastguard Worker ctx = kmod_new(cfg.dirname, &null_kmod_config);
3047*cc4ad7daSAndroid Build Coastguard Worker if (ctx == NULL) {
3048*cc4ad7daSAndroid Build Coastguard Worker CRIT("kmod_new(\"%s\", {NULL}) failed: %m\n", cfg.dirname);
3049*cc4ad7daSAndroid Build Coastguard Worker goto cmdline_failed;
3050*cc4ad7daSAndroid Build Coastguard Worker }
3051*cc4ad7daSAndroid Build Coastguard Worker
3052*cc4ad7daSAndroid Build Coastguard Worker log_setup_kmod_log(ctx, verbose);
3053*cc4ad7daSAndroid Build Coastguard Worker
3054*cc4ad7daSAndroid Build Coastguard Worker err = depmod_init(&depmod, &cfg, ctx);
3055*cc4ad7daSAndroid Build Coastguard Worker if (err < 0) {
3056*cc4ad7daSAndroid Build Coastguard Worker CRIT("depmod_init: %s\n", strerror(-err));
3057*cc4ad7daSAndroid Build Coastguard Worker goto depmod_init_failed;
3058*cc4ad7daSAndroid Build Coastguard Worker }
3059*cc4ad7daSAndroid Build Coastguard Worker ctx = NULL; /* owned by depmod */
3060*cc4ad7daSAndroid Build Coastguard Worker
3061*cc4ad7daSAndroid Build Coastguard Worker if (module_symvers != NULL) {
3062*cc4ad7daSAndroid Build Coastguard Worker err = depmod_load_symvers(&depmod, module_symvers);
3063*cc4ad7daSAndroid Build Coastguard Worker if (err < 0) {
3064*cc4ad7daSAndroid Build Coastguard Worker CRIT("could not load %s: %s\n", module_symvers,
3065*cc4ad7daSAndroid Build Coastguard Worker strerror(-err));
3066*cc4ad7daSAndroid Build Coastguard Worker goto cmdline_failed;
3067*cc4ad7daSAndroid Build Coastguard Worker }
3068*cc4ad7daSAndroid Build Coastguard Worker } else if (system_map != NULL) {
3069*cc4ad7daSAndroid Build Coastguard Worker err = depmod_load_system_map(&depmod, system_map);
3070*cc4ad7daSAndroid Build Coastguard Worker if (err < 0) {
3071*cc4ad7daSAndroid Build Coastguard Worker CRIT("could not load %s: %s\n", system_map,
3072*cc4ad7daSAndroid Build Coastguard Worker strerror(-err));
3073*cc4ad7daSAndroid Build Coastguard Worker goto cmdline_failed;
3074*cc4ad7daSAndroid Build Coastguard Worker }
3075*cc4ad7daSAndroid Build Coastguard Worker } else if (cfg.print_unknown) {
3076*cc4ad7daSAndroid Build Coastguard Worker WRN("-e needs -E or -F\n");
3077*cc4ad7daSAndroid Build Coastguard Worker cfg.print_unknown = 0;
3078*cc4ad7daSAndroid Build Coastguard Worker }
3079*cc4ad7daSAndroid Build Coastguard Worker
3080*cc4ad7daSAndroid Build Coastguard Worker if (all) {
3081*cc4ad7daSAndroid Build Coastguard Worker err = cfg_load(&cfg, config_paths);
3082*cc4ad7daSAndroid Build Coastguard Worker if (err < 0) {
3083*cc4ad7daSAndroid Build Coastguard Worker CRIT("could not load configuration files\n");
3084*cc4ad7daSAndroid Build Coastguard Worker goto cmdline_modules_failed;
3085*cc4ad7daSAndroid Build Coastguard Worker }
3086*cc4ad7daSAndroid Build Coastguard Worker err = depmod_modules_search(&depmod);
3087*cc4ad7daSAndroid Build Coastguard Worker if (err < 0) {
3088*cc4ad7daSAndroid Build Coastguard Worker CRIT("could not search modules: %s\n", strerror(-err));
3089*cc4ad7daSAndroid Build Coastguard Worker goto cmdline_modules_failed;
3090*cc4ad7daSAndroid Build Coastguard Worker }
3091*cc4ad7daSAndroid Build Coastguard Worker } else {
3092*cc4ad7daSAndroid Build Coastguard Worker int i;
3093*cc4ad7daSAndroid Build Coastguard Worker
3094*cc4ad7daSAndroid Build Coastguard Worker for (i = optind; i < argc; i++) {
3095*cc4ad7daSAndroid Build Coastguard Worker const char *path = argv[i];
3096*cc4ad7daSAndroid Build Coastguard Worker struct kmod_module *mod;
3097*cc4ad7daSAndroid Build Coastguard Worker
3098*cc4ad7daSAndroid Build Coastguard Worker if (path[0] != '/') {
3099*cc4ad7daSAndroid Build Coastguard Worker CRIT("%s: not absolute path.\n", path);
3100*cc4ad7daSAndroid Build Coastguard Worker goto cmdline_modules_failed;
3101*cc4ad7daSAndroid Build Coastguard Worker }
3102*cc4ad7daSAndroid Build Coastguard Worker
3103*cc4ad7daSAndroid Build Coastguard Worker err = kmod_module_new_from_path(depmod.ctx, path, &mod);
3104*cc4ad7daSAndroid Build Coastguard Worker if (err < 0) {
3105*cc4ad7daSAndroid Build Coastguard Worker CRIT("could not create module %s: %s\n",
3106*cc4ad7daSAndroid Build Coastguard Worker path, strerror(-err));
3107*cc4ad7daSAndroid Build Coastguard Worker goto cmdline_modules_failed;
3108*cc4ad7daSAndroid Build Coastguard Worker }
3109*cc4ad7daSAndroid Build Coastguard Worker
3110*cc4ad7daSAndroid Build Coastguard Worker err = depmod_module_add(&depmod, mod);
3111*cc4ad7daSAndroid Build Coastguard Worker if (err < 0) {
3112*cc4ad7daSAndroid Build Coastguard Worker CRIT("could not add module %s: %s\n",
3113*cc4ad7daSAndroid Build Coastguard Worker path, strerror(-err));
3114*cc4ad7daSAndroid Build Coastguard Worker kmod_module_unref(mod);
3115*cc4ad7daSAndroid Build Coastguard Worker goto cmdline_modules_failed;
3116*cc4ad7daSAndroid Build Coastguard Worker }
3117*cc4ad7daSAndroid Build Coastguard Worker }
3118*cc4ad7daSAndroid Build Coastguard Worker }
3119*cc4ad7daSAndroid Build Coastguard Worker
3120*cc4ad7daSAndroid Build Coastguard Worker err = depmod_modules_build_array(&depmod);
3121*cc4ad7daSAndroid Build Coastguard Worker if (err < 0) {
3122*cc4ad7daSAndroid Build Coastguard Worker CRIT("could not build module array: %s\n",
3123*cc4ad7daSAndroid Build Coastguard Worker strerror(-err));
3124*cc4ad7daSAndroid Build Coastguard Worker goto cmdline_modules_failed;
3125*cc4ad7daSAndroid Build Coastguard Worker }
3126*cc4ad7daSAndroid Build Coastguard Worker
3127*cc4ad7daSAndroid Build Coastguard Worker depmod_modules_sort(&depmod);
3128*cc4ad7daSAndroid Build Coastguard Worker err = depmod_load(&depmod);
3129*cc4ad7daSAndroid Build Coastguard Worker if (err < 0)
3130*cc4ad7daSAndroid Build Coastguard Worker goto cmdline_modules_failed;
3131*cc4ad7daSAndroid Build Coastguard Worker
3132*cc4ad7daSAndroid Build Coastguard Worker err = depmod_output(&depmod, out);
3133*cc4ad7daSAndroid Build Coastguard Worker
3134*cc4ad7daSAndroid Build Coastguard Worker done:
3135*cc4ad7daSAndroid Build Coastguard Worker depmod_shutdown(&depmod);
3136*cc4ad7daSAndroid Build Coastguard Worker cfg_free(&cfg);
3137*cc4ad7daSAndroid Build Coastguard Worker return err >= 0 ? EXIT_SUCCESS : EXIT_FAILURE;
3138*cc4ad7daSAndroid Build Coastguard Worker
3139*cc4ad7daSAndroid Build Coastguard Worker cmdline_modules_failed:
3140*cc4ad7daSAndroid Build Coastguard Worker depmod_shutdown(&depmod);
3141*cc4ad7daSAndroid Build Coastguard Worker depmod_init_failed:
3142*cc4ad7daSAndroid Build Coastguard Worker if (ctx != NULL)
3143*cc4ad7daSAndroid Build Coastguard Worker kmod_unref(ctx);
3144*cc4ad7daSAndroid Build Coastguard Worker cmdline_failed:
3145*cc4ad7daSAndroid Build Coastguard Worker cfg_free(&cfg);
3146*cc4ad7daSAndroid Build Coastguard Worker return EXIT_FAILURE;
3147*cc4ad7daSAndroid Build Coastguard Worker }
3148*cc4ad7daSAndroid Build Coastguard Worker
3149*cc4ad7daSAndroid Build Coastguard Worker const struct kmod_cmd kmod_cmd_compat_depmod = {
3150*cc4ad7daSAndroid Build Coastguard Worker .name = "depmod",
3151*cc4ad7daSAndroid Build Coastguard Worker .cmd = do_depmod,
3152*cc4ad7daSAndroid Build Coastguard Worker .help = "compat depmod command",
3153*cc4ad7daSAndroid Build Coastguard Worker };
3154