xref: /aosp_15_r20/external/kmod/tools/depmod.c (revision cc4ad7da8cefe208cb129ac2aa9a357c7c72deb2)
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