xref: /aosp_15_r20/external/kmod/shared/util.c (revision cc4ad7da8cefe208cb129ac2aa9a357c7c72deb2)
1*cc4ad7daSAndroid Build Coastguard Worker /*
2*cc4ad7daSAndroid Build Coastguard Worker  * kmod - interface to kernel module operations
3*cc4ad7daSAndroid Build Coastguard Worker  *
4*cc4ad7daSAndroid Build Coastguard Worker  * Copyright (C) 2011-2013  ProFUSION embedded systems
5*cc4ad7daSAndroid Build Coastguard Worker  * Copyright (C) 2012  Lucas De Marchi <[email protected]>
6*cc4ad7daSAndroid Build Coastguard Worker  * Copyright (C) 2013-2014  Intel Corporation. All rights reserved.
7*cc4ad7daSAndroid Build Coastguard Worker  *
8*cc4ad7daSAndroid Build Coastguard Worker  * This library is free software; you can redistribute it and/or
9*cc4ad7daSAndroid Build Coastguard Worker  * modify it under the terms of the GNU Lesser General Public
10*cc4ad7daSAndroid Build Coastguard Worker  * License as published by the Free Software Foundation; either
11*cc4ad7daSAndroid Build Coastguard Worker  * version 2.1 of the License, or (at your option) any later version.
12*cc4ad7daSAndroid Build Coastguard Worker  *
13*cc4ad7daSAndroid Build Coastguard Worker  * This library is distributed in the hope that it will be useful,
14*cc4ad7daSAndroid Build Coastguard Worker  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15*cc4ad7daSAndroid Build Coastguard Worker  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16*cc4ad7daSAndroid Build Coastguard Worker  * Lesser General Public License for more details.
17*cc4ad7daSAndroid Build Coastguard Worker  *
18*cc4ad7daSAndroid Build Coastguard Worker  * You should have received a copy of the GNU Lesser General Public
19*cc4ad7daSAndroid Build Coastguard Worker  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
20*cc4ad7daSAndroid Build Coastguard Worker  */
21*cc4ad7daSAndroid Build Coastguard Worker 
22*cc4ad7daSAndroid Build Coastguard Worker #include <assert.h>
23*cc4ad7daSAndroid Build Coastguard Worker #include <ctype.h>
24*cc4ad7daSAndroid Build Coastguard Worker #include <errno.h>
25*cc4ad7daSAndroid Build Coastguard Worker #include <stdarg.h>
26*cc4ad7daSAndroid Build Coastguard Worker #include <stddef.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 
32*cc4ad7daSAndroid Build Coastguard Worker #include <shared/missing.h>
33*cc4ad7daSAndroid Build Coastguard Worker #include <shared/util.h>
34*cc4ad7daSAndroid Build Coastguard Worker 
35*cc4ad7daSAndroid Build Coastguard Worker #define USEC_PER_SEC  1000000ULL
36*cc4ad7daSAndroid Build Coastguard Worker #define NSEC_PER_USEC 1000ULL
37*cc4ad7daSAndroid Build Coastguard Worker 
38*cc4ad7daSAndroid Build Coastguard Worker static const struct kmod_ext {
39*cc4ad7daSAndroid Build Coastguard Worker 	const char *ext;
40*cc4ad7daSAndroid Build Coastguard Worker 	size_t len;
41*cc4ad7daSAndroid Build Coastguard Worker } kmod_exts[] = {
42*cc4ad7daSAndroid Build Coastguard Worker 	{KMOD_EXTENSION_UNCOMPRESSED, sizeof(KMOD_EXTENSION_UNCOMPRESSED) - 1},
43*cc4ad7daSAndroid Build Coastguard Worker #ifdef ENABLE_ZLIB
44*cc4ad7daSAndroid Build Coastguard Worker 	{".ko.gz", sizeof(".ko.gz") - 1},
45*cc4ad7daSAndroid Build Coastguard Worker #endif
46*cc4ad7daSAndroid Build Coastguard Worker #ifdef ENABLE_XZ
47*cc4ad7daSAndroid Build Coastguard Worker 	{".ko.xz", sizeof(".ko.xz") - 1},
48*cc4ad7daSAndroid Build Coastguard Worker #endif
49*cc4ad7daSAndroid Build Coastguard Worker #ifdef ENABLE_ZSTD
50*cc4ad7daSAndroid Build Coastguard Worker 	{".ko.zst", sizeof(".ko.zst") - 1},
51*cc4ad7daSAndroid Build Coastguard Worker #endif
52*cc4ad7daSAndroid Build Coastguard Worker 	{ }
53*cc4ad7daSAndroid Build Coastguard Worker };
54*cc4ad7daSAndroid Build Coastguard Worker 
55*cc4ad7daSAndroid Build Coastguard Worker /* string handling functions and memory allocations                         */
56*cc4ad7daSAndroid Build Coastguard Worker /* ************************************************************************ */
57*cc4ad7daSAndroid Build Coastguard Worker 
memdup(const void * p,size_t n)58*cc4ad7daSAndroid Build Coastguard Worker void *memdup(const void *p, size_t n)
59*cc4ad7daSAndroid Build Coastguard Worker {
60*cc4ad7daSAndroid Build Coastguard Worker 	void *r = malloc(n);
61*cc4ad7daSAndroid Build Coastguard Worker 
62*cc4ad7daSAndroid Build Coastguard Worker 	if (r == NULL)
63*cc4ad7daSAndroid Build Coastguard Worker 		return NULL;
64*cc4ad7daSAndroid Build Coastguard Worker 
65*cc4ad7daSAndroid Build Coastguard Worker 	return memcpy(r, p, n);
66*cc4ad7daSAndroid Build Coastguard Worker }
67*cc4ad7daSAndroid Build Coastguard Worker 
strchr_replace(char * s,char c,char r)68*cc4ad7daSAndroid Build Coastguard Worker char *strchr_replace(char *s, char c, char r)
69*cc4ad7daSAndroid Build Coastguard Worker {
70*cc4ad7daSAndroid Build Coastguard Worker 	char *p;
71*cc4ad7daSAndroid Build Coastguard Worker 
72*cc4ad7daSAndroid Build Coastguard Worker 	for (p = s; *p != '\0'; p++) {
73*cc4ad7daSAndroid Build Coastguard Worker 		if (*p == c)
74*cc4ad7daSAndroid Build Coastguard Worker 			*p = r;
75*cc4ad7daSAndroid Build Coastguard Worker 	}
76*cc4ad7daSAndroid Build Coastguard Worker 
77*cc4ad7daSAndroid Build Coastguard Worker 	return s;
78*cc4ad7daSAndroid Build Coastguard Worker }
79*cc4ad7daSAndroid Build Coastguard Worker 
80*cc4ad7daSAndroid Build Coastguard Worker /* module-related functions                                                 */
81*cc4ad7daSAndroid Build Coastguard Worker /* ************************************************************************ */
alias_normalize(const char * alias,char buf[static PATH_MAX],size_t * len)82*cc4ad7daSAndroid Build Coastguard Worker int alias_normalize(const char *alias, char buf[static PATH_MAX], size_t *len)
83*cc4ad7daSAndroid Build Coastguard Worker {
84*cc4ad7daSAndroid Build Coastguard Worker 	size_t i;
85*cc4ad7daSAndroid Build Coastguard Worker 
86*cc4ad7daSAndroid Build Coastguard Worker 	for (i = 0; i < PATH_MAX - 1; i++) {
87*cc4ad7daSAndroid Build Coastguard Worker 		const char c = alias[i];
88*cc4ad7daSAndroid Build Coastguard Worker 		switch (c) {
89*cc4ad7daSAndroid Build Coastguard Worker 		case '-':
90*cc4ad7daSAndroid Build Coastguard Worker 			buf[i] = '_';
91*cc4ad7daSAndroid Build Coastguard Worker 			break;
92*cc4ad7daSAndroid Build Coastguard Worker 		case ']':
93*cc4ad7daSAndroid Build Coastguard Worker 			return -EINVAL;
94*cc4ad7daSAndroid Build Coastguard Worker 		case '[':
95*cc4ad7daSAndroid Build Coastguard Worker 			while (alias[i] != ']' && alias[i] != '\0') {
96*cc4ad7daSAndroid Build Coastguard Worker 				buf[i] = alias[i];
97*cc4ad7daSAndroid Build Coastguard Worker 				i++;
98*cc4ad7daSAndroid Build Coastguard Worker 			}
99*cc4ad7daSAndroid Build Coastguard Worker 
100*cc4ad7daSAndroid Build Coastguard Worker 			if (alias[i] != ']')
101*cc4ad7daSAndroid Build Coastguard Worker 				return -EINVAL;
102*cc4ad7daSAndroid Build Coastguard Worker 
103*cc4ad7daSAndroid Build Coastguard Worker 			buf[i] = alias[i];
104*cc4ad7daSAndroid Build Coastguard Worker 			break;
105*cc4ad7daSAndroid Build Coastguard Worker 		case '\0':
106*cc4ad7daSAndroid Build Coastguard Worker 			goto finish;
107*cc4ad7daSAndroid Build Coastguard Worker 		default:
108*cc4ad7daSAndroid Build Coastguard Worker 			buf[i] = c;
109*cc4ad7daSAndroid Build Coastguard Worker 		}
110*cc4ad7daSAndroid Build Coastguard Worker 	}
111*cc4ad7daSAndroid Build Coastguard Worker 
112*cc4ad7daSAndroid Build Coastguard Worker finish:
113*cc4ad7daSAndroid Build Coastguard Worker 	buf[i] = '\0';
114*cc4ad7daSAndroid Build Coastguard Worker 	if (len)
115*cc4ad7daSAndroid Build Coastguard Worker 		*len = i;
116*cc4ad7daSAndroid Build Coastguard Worker 
117*cc4ad7daSAndroid Build Coastguard Worker 	return 0;
118*cc4ad7daSAndroid Build Coastguard Worker }
119*cc4ad7daSAndroid Build Coastguard Worker 
120*cc4ad7daSAndroid Build Coastguard Worker /*
121*cc4ad7daSAndroid Build Coastguard Worker  * Replace dashes with underscores.
122*cc4ad7daSAndroid Build Coastguard Worker  * Dashes inside character range patterns (e.g. [0-9]) are left unchanged.
123*cc4ad7daSAndroid Build Coastguard Worker  *
124*cc4ad7daSAndroid Build Coastguard Worker  * For convenience, it returns error if @s is NULL
125*cc4ad7daSAndroid Build Coastguard Worker  */
underscores(char * s)126*cc4ad7daSAndroid Build Coastguard Worker int underscores(char *s)
127*cc4ad7daSAndroid Build Coastguard Worker {
128*cc4ad7daSAndroid Build Coastguard Worker 	unsigned int i;
129*cc4ad7daSAndroid Build Coastguard Worker 
130*cc4ad7daSAndroid Build Coastguard Worker 	if (!s)
131*cc4ad7daSAndroid Build Coastguard Worker 		return -EINVAL;
132*cc4ad7daSAndroid Build Coastguard Worker 
133*cc4ad7daSAndroid Build Coastguard Worker 	for (i = 0; s[i]; i++) {
134*cc4ad7daSAndroid Build Coastguard Worker 		switch (s[i]) {
135*cc4ad7daSAndroid Build Coastguard Worker 		case '-':
136*cc4ad7daSAndroid Build Coastguard Worker 			s[i] = '_';
137*cc4ad7daSAndroid Build Coastguard Worker 			break;
138*cc4ad7daSAndroid Build Coastguard Worker 		case ']':
139*cc4ad7daSAndroid Build Coastguard Worker 			return -EINVAL;
140*cc4ad7daSAndroid Build Coastguard Worker 		case '[':
141*cc4ad7daSAndroid Build Coastguard Worker 			i += strcspn(&s[i], "]");
142*cc4ad7daSAndroid Build Coastguard Worker 			if (!s[i])
143*cc4ad7daSAndroid Build Coastguard Worker 				return -EINVAL;
144*cc4ad7daSAndroid Build Coastguard Worker 			break;
145*cc4ad7daSAndroid Build Coastguard Worker 		}
146*cc4ad7daSAndroid Build Coastguard Worker 	}
147*cc4ad7daSAndroid Build Coastguard Worker 
148*cc4ad7daSAndroid Build Coastguard Worker 	return 0;
149*cc4ad7daSAndroid Build Coastguard Worker }
150*cc4ad7daSAndroid Build Coastguard Worker 
modname_normalize(const char * modname,char buf[static PATH_MAX],size_t * len)151*cc4ad7daSAndroid Build Coastguard Worker char *modname_normalize(const char *modname, char buf[static PATH_MAX], size_t *len)
152*cc4ad7daSAndroid Build Coastguard Worker {
153*cc4ad7daSAndroid Build Coastguard Worker 	size_t s;
154*cc4ad7daSAndroid Build Coastguard Worker 
155*cc4ad7daSAndroid Build Coastguard Worker 	for (s = 0; s < PATH_MAX - 1; s++) {
156*cc4ad7daSAndroid Build Coastguard Worker 		const char c = modname[s];
157*cc4ad7daSAndroid Build Coastguard Worker 		if (c == '-')
158*cc4ad7daSAndroid Build Coastguard Worker 			buf[s] = '_';
159*cc4ad7daSAndroid Build Coastguard Worker 		else if (c == '\0' || c == '.')
160*cc4ad7daSAndroid Build Coastguard Worker 			break;
161*cc4ad7daSAndroid Build Coastguard Worker 		else
162*cc4ad7daSAndroid Build Coastguard Worker 			buf[s] = c;
163*cc4ad7daSAndroid Build Coastguard Worker 	}
164*cc4ad7daSAndroid Build Coastguard Worker 
165*cc4ad7daSAndroid Build Coastguard Worker 	buf[s] = '\0';
166*cc4ad7daSAndroid Build Coastguard Worker 
167*cc4ad7daSAndroid Build Coastguard Worker 	if (len)
168*cc4ad7daSAndroid Build Coastguard Worker 		*len = s;
169*cc4ad7daSAndroid Build Coastguard Worker 
170*cc4ad7daSAndroid Build Coastguard Worker 	return buf;
171*cc4ad7daSAndroid Build Coastguard Worker }
172*cc4ad7daSAndroid Build Coastguard Worker 
path_to_modname(const char * path,char buf[static PATH_MAX],size_t * len)173*cc4ad7daSAndroid Build Coastguard Worker char *path_to_modname(const char *path, char buf[static PATH_MAX], size_t *len)
174*cc4ad7daSAndroid Build Coastguard Worker {
175*cc4ad7daSAndroid Build Coastguard Worker 	char *modname;
176*cc4ad7daSAndroid Build Coastguard Worker 
177*cc4ad7daSAndroid Build Coastguard Worker 	modname = basename(path);
178*cc4ad7daSAndroid Build Coastguard Worker 	if (modname == NULL || modname[0] == '\0')
179*cc4ad7daSAndroid Build Coastguard Worker 		return NULL;
180*cc4ad7daSAndroid Build Coastguard Worker 
181*cc4ad7daSAndroid Build Coastguard Worker 	return modname_normalize(modname, buf, len);
182*cc4ad7daSAndroid Build Coastguard Worker }
183*cc4ad7daSAndroid Build Coastguard Worker 
path_ends_with_kmod_ext(const char * path,size_t len)184*cc4ad7daSAndroid Build Coastguard Worker bool path_ends_with_kmod_ext(const char *path, size_t len)
185*cc4ad7daSAndroid Build Coastguard Worker {
186*cc4ad7daSAndroid Build Coastguard Worker 	const struct kmod_ext *eitr;
187*cc4ad7daSAndroid Build Coastguard Worker 
188*cc4ad7daSAndroid Build Coastguard Worker 	for (eitr = kmod_exts; eitr->ext != NULL; eitr++) {
189*cc4ad7daSAndroid Build Coastguard Worker 		if (len <= eitr->len)
190*cc4ad7daSAndroid Build Coastguard Worker 			continue;
191*cc4ad7daSAndroid Build Coastguard Worker 		if (streq(path + len - eitr->len, eitr->ext))
192*cc4ad7daSAndroid Build Coastguard Worker 			return true;
193*cc4ad7daSAndroid Build Coastguard Worker 	}
194*cc4ad7daSAndroid Build Coastguard Worker 
195*cc4ad7daSAndroid Build Coastguard Worker 	return false;
196*cc4ad7daSAndroid Build Coastguard Worker }
197*cc4ad7daSAndroid Build Coastguard Worker 
198*cc4ad7daSAndroid Build Coastguard Worker /* read-like and fread-like functions                                       */
199*cc4ad7daSAndroid Build Coastguard Worker /* ************************************************************************ */
read_str_safe(int fd,char * buf,size_t buflen)200*cc4ad7daSAndroid Build Coastguard Worker ssize_t read_str_safe(int fd, char *buf, size_t buflen)
201*cc4ad7daSAndroid Build Coastguard Worker {
202*cc4ad7daSAndroid Build Coastguard Worker 	size_t todo = buflen - 1;
203*cc4ad7daSAndroid Build Coastguard Worker 	size_t done = 0;
204*cc4ad7daSAndroid Build Coastguard Worker 
205*cc4ad7daSAndroid Build Coastguard Worker 	assert_cc(EAGAIN == EWOULDBLOCK);
206*cc4ad7daSAndroid Build Coastguard Worker 
207*cc4ad7daSAndroid Build Coastguard Worker 	do {
208*cc4ad7daSAndroid Build Coastguard Worker 		ssize_t r = read(fd, buf + done, todo);
209*cc4ad7daSAndroid Build Coastguard Worker 
210*cc4ad7daSAndroid Build Coastguard Worker 		if (r == 0)
211*cc4ad7daSAndroid Build Coastguard Worker 			break;
212*cc4ad7daSAndroid Build Coastguard Worker 		else if (r > 0) {
213*cc4ad7daSAndroid Build Coastguard Worker 			todo -= r;
214*cc4ad7daSAndroid Build Coastguard Worker 			done += r;
215*cc4ad7daSAndroid Build Coastguard Worker 		} else {
216*cc4ad7daSAndroid Build Coastguard Worker 			if (errno == EAGAIN || errno == EINTR)
217*cc4ad7daSAndroid Build Coastguard Worker 				continue;
218*cc4ad7daSAndroid Build Coastguard Worker 			else
219*cc4ad7daSAndroid Build Coastguard Worker 				return -errno;
220*cc4ad7daSAndroid Build Coastguard Worker 		}
221*cc4ad7daSAndroid Build Coastguard Worker 	} while (todo > 0);
222*cc4ad7daSAndroid Build Coastguard Worker 
223*cc4ad7daSAndroid Build Coastguard Worker 	buf[done] = '\0';
224*cc4ad7daSAndroid Build Coastguard Worker 	return done;
225*cc4ad7daSAndroid Build Coastguard Worker }
226*cc4ad7daSAndroid Build Coastguard Worker 
write_str_safe(int fd,const char * buf,size_t buflen)227*cc4ad7daSAndroid Build Coastguard Worker ssize_t write_str_safe(int fd, const char *buf, size_t buflen)
228*cc4ad7daSAndroid Build Coastguard Worker {
229*cc4ad7daSAndroid Build Coastguard Worker 	size_t todo = buflen;
230*cc4ad7daSAndroid Build Coastguard Worker 	size_t done = 0;
231*cc4ad7daSAndroid Build Coastguard Worker 
232*cc4ad7daSAndroid Build Coastguard Worker 	assert_cc(EAGAIN == EWOULDBLOCK);
233*cc4ad7daSAndroid Build Coastguard Worker 
234*cc4ad7daSAndroid Build Coastguard Worker 	do {
235*cc4ad7daSAndroid Build Coastguard Worker 		ssize_t r = write(fd, buf + done, todo);
236*cc4ad7daSAndroid Build Coastguard Worker 
237*cc4ad7daSAndroid Build Coastguard Worker 		if (r == 0)
238*cc4ad7daSAndroid Build Coastguard Worker 			break;
239*cc4ad7daSAndroid Build Coastguard Worker 		else if (r > 0) {
240*cc4ad7daSAndroid Build Coastguard Worker 			todo -= r;
241*cc4ad7daSAndroid Build Coastguard Worker 			done += r;
242*cc4ad7daSAndroid Build Coastguard Worker 		} else {
243*cc4ad7daSAndroid Build Coastguard Worker 			if (errno == EAGAIN || errno == EINTR)
244*cc4ad7daSAndroid Build Coastguard Worker 				continue;
245*cc4ad7daSAndroid Build Coastguard Worker 			else
246*cc4ad7daSAndroid Build Coastguard Worker 				return -errno;
247*cc4ad7daSAndroid Build Coastguard Worker 		}
248*cc4ad7daSAndroid Build Coastguard Worker 	} while (todo > 0);
249*cc4ad7daSAndroid Build Coastguard Worker 
250*cc4ad7daSAndroid Build Coastguard Worker 	return done;
251*cc4ad7daSAndroid Build Coastguard Worker }
252*cc4ad7daSAndroid Build Coastguard Worker 
read_str_long(int fd,long * value,int base)253*cc4ad7daSAndroid Build Coastguard Worker int read_str_long(int fd, long *value, int base)
254*cc4ad7daSAndroid Build Coastguard Worker {
255*cc4ad7daSAndroid Build Coastguard Worker 	char buf[32], *end;
256*cc4ad7daSAndroid Build Coastguard Worker 	long v;
257*cc4ad7daSAndroid Build Coastguard Worker 	int err;
258*cc4ad7daSAndroid Build Coastguard Worker 
259*cc4ad7daSAndroid Build Coastguard Worker 	*value = 0;
260*cc4ad7daSAndroid Build Coastguard Worker 	err = read_str_safe(fd, buf, sizeof(buf));
261*cc4ad7daSAndroid Build Coastguard Worker 	if (err < 0)
262*cc4ad7daSAndroid Build Coastguard Worker 		return err;
263*cc4ad7daSAndroid Build Coastguard Worker 	errno = 0;
264*cc4ad7daSAndroid Build Coastguard Worker 	v = strtol(buf, &end, base);
265*cc4ad7daSAndroid Build Coastguard Worker 	if (end == buf || !isspace(*end))
266*cc4ad7daSAndroid Build Coastguard Worker 		return -EINVAL;
267*cc4ad7daSAndroid Build Coastguard Worker 
268*cc4ad7daSAndroid Build Coastguard Worker 	*value = v;
269*cc4ad7daSAndroid Build Coastguard Worker 	return 0;
270*cc4ad7daSAndroid Build Coastguard Worker }
271*cc4ad7daSAndroid Build Coastguard Worker 
read_str_ulong(int fd,unsigned long * value,int base)272*cc4ad7daSAndroid Build Coastguard Worker int read_str_ulong(int fd, unsigned long *value, int base)
273*cc4ad7daSAndroid Build Coastguard Worker {
274*cc4ad7daSAndroid Build Coastguard Worker 	char buf[32], *end;
275*cc4ad7daSAndroid Build Coastguard Worker 	long v;
276*cc4ad7daSAndroid Build Coastguard Worker 	int err;
277*cc4ad7daSAndroid Build Coastguard Worker 
278*cc4ad7daSAndroid Build Coastguard Worker 	*value = 0;
279*cc4ad7daSAndroid Build Coastguard Worker 	err = read_str_safe(fd, buf, sizeof(buf));
280*cc4ad7daSAndroid Build Coastguard Worker 	if (err < 0)
281*cc4ad7daSAndroid Build Coastguard Worker 		return err;
282*cc4ad7daSAndroid Build Coastguard Worker 	errno = 0;
283*cc4ad7daSAndroid Build Coastguard Worker 	v = strtoul(buf, &end, base);
284*cc4ad7daSAndroid Build Coastguard Worker 	if (end == buf || !isspace(*end))
285*cc4ad7daSAndroid Build Coastguard Worker 		return -EINVAL;
286*cc4ad7daSAndroid Build Coastguard Worker 	*value = v;
287*cc4ad7daSAndroid Build Coastguard Worker 	return 0;
288*cc4ad7daSAndroid Build Coastguard Worker }
289*cc4ad7daSAndroid Build Coastguard Worker 
290*cc4ad7daSAndroid Build Coastguard Worker /*
291*cc4ad7daSAndroid Build Coastguard Worker  * Read one logical line from a configuration file.
292*cc4ad7daSAndroid Build Coastguard Worker  *
293*cc4ad7daSAndroid Build Coastguard Worker  * Line endings may be escaped with backslashes, to form one logical line from
294*cc4ad7daSAndroid Build Coastguard Worker  * several physical lines.  No end of line character(s) are included in the
295*cc4ad7daSAndroid Build Coastguard Worker  * result.
296*cc4ad7daSAndroid Build Coastguard Worker  *
297*cc4ad7daSAndroid Build Coastguard Worker  * If linenum is not NULL, it is incremented by the number of physical lines
298*cc4ad7daSAndroid Build Coastguard Worker  * which have been read.
299*cc4ad7daSAndroid Build Coastguard Worker  */
freadline_wrapped(FILE * fp,unsigned int * linenum)300*cc4ad7daSAndroid Build Coastguard Worker char *freadline_wrapped(FILE *fp, unsigned int *linenum)
301*cc4ad7daSAndroid Build Coastguard Worker {
302*cc4ad7daSAndroid Build Coastguard Worker 	int size = 256;
303*cc4ad7daSAndroid Build Coastguard Worker 	int i = 0, n = 0;
304*cc4ad7daSAndroid Build Coastguard Worker 	_cleanup_free_ char *buf = malloc(size);
305*cc4ad7daSAndroid Build Coastguard Worker 
306*cc4ad7daSAndroid Build Coastguard Worker 	if (buf == NULL)
307*cc4ad7daSAndroid Build Coastguard Worker 		return NULL;
308*cc4ad7daSAndroid Build Coastguard Worker 
309*cc4ad7daSAndroid Build Coastguard Worker 	for(;;) {
310*cc4ad7daSAndroid Build Coastguard Worker 		int ch = getc_unlocked(fp);
311*cc4ad7daSAndroid Build Coastguard Worker 
312*cc4ad7daSAndroid Build Coastguard Worker 		switch(ch) {
313*cc4ad7daSAndroid Build Coastguard Worker 		case EOF:
314*cc4ad7daSAndroid Build Coastguard Worker 			if (i == 0)
315*cc4ad7daSAndroid Build Coastguard Worker 				return NULL;
316*cc4ad7daSAndroid Build Coastguard Worker 			/* else fall through */
317*cc4ad7daSAndroid Build Coastguard Worker 
318*cc4ad7daSAndroid Build Coastguard Worker 		case '\n':
319*cc4ad7daSAndroid Build Coastguard Worker 			n++;
320*cc4ad7daSAndroid Build Coastguard Worker 
321*cc4ad7daSAndroid Build Coastguard Worker 			{
322*cc4ad7daSAndroid Build Coastguard Worker 				char *ret = buf;
323*cc4ad7daSAndroid Build Coastguard Worker 				ret[i] = '\0';
324*cc4ad7daSAndroid Build Coastguard Worker 				buf = NULL;
325*cc4ad7daSAndroid Build Coastguard Worker 				if (linenum)
326*cc4ad7daSAndroid Build Coastguard Worker 					*linenum += n;
327*cc4ad7daSAndroid Build Coastguard Worker 				return ret;
328*cc4ad7daSAndroid Build Coastguard Worker 			}
329*cc4ad7daSAndroid Build Coastguard Worker 
330*cc4ad7daSAndroid Build Coastguard Worker 		case '\\':
331*cc4ad7daSAndroid Build Coastguard Worker 			ch = getc_unlocked(fp);
332*cc4ad7daSAndroid Build Coastguard Worker 
333*cc4ad7daSAndroid Build Coastguard Worker 			if (ch == '\n') {
334*cc4ad7daSAndroid Build Coastguard Worker 				n++;
335*cc4ad7daSAndroid Build Coastguard Worker 				continue;
336*cc4ad7daSAndroid Build Coastguard Worker 			}
337*cc4ad7daSAndroid Build Coastguard Worker 			/* else fall through */
338*cc4ad7daSAndroid Build Coastguard Worker 
339*cc4ad7daSAndroid Build Coastguard Worker 		default:
340*cc4ad7daSAndroid Build Coastguard Worker 			buf[i++] = ch;
341*cc4ad7daSAndroid Build Coastguard Worker 
342*cc4ad7daSAndroid Build Coastguard Worker 			if (i == size) {
343*cc4ad7daSAndroid Build Coastguard Worker 				char *tmp;
344*cc4ad7daSAndroid Build Coastguard Worker 				size *= 2;
345*cc4ad7daSAndroid Build Coastguard Worker 				tmp = realloc(buf, size);
346*cc4ad7daSAndroid Build Coastguard Worker 				if (!tmp)
347*cc4ad7daSAndroid Build Coastguard Worker 					return NULL;
348*cc4ad7daSAndroid Build Coastguard Worker 				buf = tmp;
349*cc4ad7daSAndroid Build Coastguard Worker 			}
350*cc4ad7daSAndroid Build Coastguard Worker 		}
351*cc4ad7daSAndroid Build Coastguard Worker 	}
352*cc4ad7daSAndroid Build Coastguard Worker }
353*cc4ad7daSAndroid Build Coastguard Worker 
354*cc4ad7daSAndroid Build Coastguard Worker /* path handling functions                                                  */
355*cc4ad7daSAndroid Build Coastguard Worker /* ************************************************************************ */
356*cc4ad7daSAndroid Build Coastguard Worker 
path_is_absolute(const char * p)357*cc4ad7daSAndroid Build Coastguard Worker static bool path_is_absolute(const char *p)
358*cc4ad7daSAndroid Build Coastguard Worker {
359*cc4ad7daSAndroid Build Coastguard Worker 	assert(p != NULL);
360*cc4ad7daSAndroid Build Coastguard Worker 
361*cc4ad7daSAndroid Build Coastguard Worker 	return p[0] == '/';
362*cc4ad7daSAndroid Build Coastguard Worker }
363*cc4ad7daSAndroid Build Coastguard Worker 
path_make_absolute_cwd(const char * p)364*cc4ad7daSAndroid Build Coastguard Worker char *path_make_absolute_cwd(const char *p)
365*cc4ad7daSAndroid Build Coastguard Worker {
366*cc4ad7daSAndroid Build Coastguard Worker 	_cleanup_free_ char *cwd = NULL;
367*cc4ad7daSAndroid Build Coastguard Worker 	size_t plen, cwdlen;
368*cc4ad7daSAndroid Build Coastguard Worker 	char *r;
369*cc4ad7daSAndroid Build Coastguard Worker 
370*cc4ad7daSAndroid Build Coastguard Worker 	if (path_is_absolute(p))
371*cc4ad7daSAndroid Build Coastguard Worker 		return strdup(p);
372*cc4ad7daSAndroid Build Coastguard Worker 
373*cc4ad7daSAndroid Build Coastguard Worker 	cwd = get_current_dir_name();
374*cc4ad7daSAndroid Build Coastguard Worker 	if (!cwd)
375*cc4ad7daSAndroid Build Coastguard Worker 		return NULL;
376*cc4ad7daSAndroid Build Coastguard Worker 
377*cc4ad7daSAndroid Build Coastguard Worker 	plen = strlen(p);
378*cc4ad7daSAndroid Build Coastguard Worker 	cwdlen = strlen(cwd);
379*cc4ad7daSAndroid Build Coastguard Worker 
380*cc4ad7daSAndroid Build Coastguard Worker 	/* cwd + '/' + p + '\0' */
381*cc4ad7daSAndroid Build Coastguard Worker 	r = realloc(cwd, cwdlen + 1 + plen + 1);
382*cc4ad7daSAndroid Build Coastguard Worker 	if (r == NULL)
383*cc4ad7daSAndroid Build Coastguard Worker 		return NULL;
384*cc4ad7daSAndroid Build Coastguard Worker 
385*cc4ad7daSAndroid Build Coastguard Worker 	cwd = NULL;
386*cc4ad7daSAndroid Build Coastguard Worker 	r[cwdlen] = '/';
387*cc4ad7daSAndroid Build Coastguard Worker 	memcpy(&r[cwdlen + 1], p, plen + 1);
388*cc4ad7daSAndroid Build Coastguard Worker 
389*cc4ad7daSAndroid Build Coastguard Worker 	return r;
390*cc4ad7daSAndroid Build Coastguard Worker }
391*cc4ad7daSAndroid Build Coastguard Worker 
is_dir(const char * path)392*cc4ad7daSAndroid Build Coastguard Worker static inline int is_dir(const char *path)
393*cc4ad7daSAndroid Build Coastguard Worker {
394*cc4ad7daSAndroid Build Coastguard Worker 	struct stat st;
395*cc4ad7daSAndroid Build Coastguard Worker 
396*cc4ad7daSAndroid Build Coastguard Worker 	if (stat(path, &st) >= 0)
397*cc4ad7daSAndroid Build Coastguard Worker 		return S_ISDIR(st.st_mode);
398*cc4ad7daSAndroid Build Coastguard Worker 
399*cc4ad7daSAndroid Build Coastguard Worker 	return -errno;
400*cc4ad7daSAndroid Build Coastguard Worker }
401*cc4ad7daSAndroid Build Coastguard Worker 
mkdir_p(const char * path,int len,mode_t mode)402*cc4ad7daSAndroid Build Coastguard Worker int mkdir_p(const char *path, int len, mode_t mode)
403*cc4ad7daSAndroid Build Coastguard Worker {
404*cc4ad7daSAndroid Build Coastguard Worker 	char *start, *end;
405*cc4ad7daSAndroid Build Coastguard Worker 
406*cc4ad7daSAndroid Build Coastguard Worker 	start = strndupa(path, len);
407*cc4ad7daSAndroid Build Coastguard Worker 	end = start + len;
408*cc4ad7daSAndroid Build Coastguard Worker 
409*cc4ad7daSAndroid Build Coastguard Worker 	/*
410*cc4ad7daSAndroid Build Coastguard Worker 	 * scan backwards, replacing '/' with '\0' while the component doesn't
411*cc4ad7daSAndroid Build Coastguard Worker 	 * exist
412*cc4ad7daSAndroid Build Coastguard Worker 	 */
413*cc4ad7daSAndroid Build Coastguard Worker 	for (;;) {
414*cc4ad7daSAndroid Build Coastguard Worker 		int r = is_dir(start);
415*cc4ad7daSAndroid Build Coastguard Worker 		if (r > 0) {
416*cc4ad7daSAndroid Build Coastguard Worker 			end += strlen(end);
417*cc4ad7daSAndroid Build Coastguard Worker 
418*cc4ad7daSAndroid Build Coastguard Worker 			if (end == start + len)
419*cc4ad7daSAndroid Build Coastguard Worker 				return 0;
420*cc4ad7daSAndroid Build Coastguard Worker 
421*cc4ad7daSAndroid Build Coastguard Worker 			/* end != start, since it would be caught on the first
422*cc4ad7daSAndroid Build Coastguard Worker 			 * iteration */
423*cc4ad7daSAndroid Build Coastguard Worker 			*end = '/';
424*cc4ad7daSAndroid Build Coastguard Worker 			break;
425*cc4ad7daSAndroid Build Coastguard Worker 		} else if (r == 0)
426*cc4ad7daSAndroid Build Coastguard Worker 			return -ENOTDIR;
427*cc4ad7daSAndroid Build Coastguard Worker 
428*cc4ad7daSAndroid Build Coastguard Worker 		if (end == start)
429*cc4ad7daSAndroid Build Coastguard Worker 			break;
430*cc4ad7daSAndroid Build Coastguard Worker 
431*cc4ad7daSAndroid Build Coastguard Worker 		*end = '\0';
432*cc4ad7daSAndroid Build Coastguard Worker 
433*cc4ad7daSAndroid Build Coastguard Worker 		/* Find the next component, backwards, discarding extra '/'*/
434*cc4ad7daSAndroid Build Coastguard Worker 		while (end > start && *end != '/')
435*cc4ad7daSAndroid Build Coastguard Worker 			end--;
436*cc4ad7daSAndroid Build Coastguard Worker 
437*cc4ad7daSAndroid Build Coastguard Worker 		while (end > start && *(end - 1) == '/')
438*cc4ad7daSAndroid Build Coastguard Worker 			end--;
439*cc4ad7daSAndroid Build Coastguard Worker 	}
440*cc4ad7daSAndroid Build Coastguard Worker 
441*cc4ad7daSAndroid Build Coastguard Worker 	for (; end < start + len;) {
442*cc4ad7daSAndroid Build Coastguard Worker 		if (mkdir(start, mode) < 0 && errno != EEXIST)
443*cc4ad7daSAndroid Build Coastguard Worker 			return -errno;
444*cc4ad7daSAndroid Build Coastguard Worker 
445*cc4ad7daSAndroid Build Coastguard Worker 		end += strlen(end);
446*cc4ad7daSAndroid Build Coastguard Worker 		*end = '/';
447*cc4ad7daSAndroid Build Coastguard Worker 	}
448*cc4ad7daSAndroid Build Coastguard Worker 
449*cc4ad7daSAndroid Build Coastguard Worker 	return 0;
450*cc4ad7daSAndroid Build Coastguard Worker }
451*cc4ad7daSAndroid Build Coastguard Worker 
mkdir_parents(const char * path,mode_t mode)452*cc4ad7daSAndroid Build Coastguard Worker int mkdir_parents(const char *path, mode_t mode)
453*cc4ad7daSAndroid Build Coastguard Worker {
454*cc4ad7daSAndroid Build Coastguard Worker 	char *end = strrchr(path, '/');
455*cc4ad7daSAndroid Build Coastguard Worker 
456*cc4ad7daSAndroid Build Coastguard Worker 	/* no parent directories */
457*cc4ad7daSAndroid Build Coastguard Worker 	if (end == NULL)
458*cc4ad7daSAndroid Build Coastguard Worker 		return 0;
459*cc4ad7daSAndroid Build Coastguard Worker 
460*cc4ad7daSAndroid Build Coastguard Worker 	return mkdir_p(path, end - path, mode);
461*cc4ad7daSAndroid Build Coastguard Worker }
462*cc4ad7daSAndroid Build Coastguard Worker 
ts_usec(const struct timespec * ts)463*cc4ad7daSAndroid Build Coastguard Worker static unsigned long long ts_usec(const struct timespec *ts)
464*cc4ad7daSAndroid Build Coastguard Worker {
465*cc4ad7daSAndroid Build Coastguard Worker 	return (unsigned long long) ts->tv_sec * USEC_PER_SEC +
466*cc4ad7daSAndroid Build Coastguard Worker 	       (unsigned long long) ts->tv_nsec / NSEC_PER_USEC;
467*cc4ad7daSAndroid Build Coastguard Worker }
468*cc4ad7daSAndroid Build Coastguard Worker 
ts_msec(const struct timespec * ts)469*cc4ad7daSAndroid Build Coastguard Worker static unsigned long long ts_msec(const struct timespec *ts)
470*cc4ad7daSAndroid Build Coastguard Worker {
471*cc4ad7daSAndroid Build Coastguard Worker 	return (unsigned long long) ts->tv_sec * MSEC_PER_SEC +
472*cc4ad7daSAndroid Build Coastguard Worker 	       (unsigned long long) ts->tv_nsec / NSEC_PER_MSEC;
473*cc4ad7daSAndroid Build Coastguard Worker }
474*cc4ad7daSAndroid Build Coastguard Worker 
msec_ts(unsigned long long msec)475*cc4ad7daSAndroid Build Coastguard Worker static struct timespec msec_ts(unsigned long long msec)
476*cc4ad7daSAndroid Build Coastguard Worker {
477*cc4ad7daSAndroid Build Coastguard Worker 	struct timespec ts = {
478*cc4ad7daSAndroid Build Coastguard Worker 		.tv_sec = msec / MSEC_PER_SEC,
479*cc4ad7daSAndroid Build Coastguard Worker 		.tv_nsec = (msec % MSEC_PER_SEC) * NSEC_PER_MSEC,
480*cc4ad7daSAndroid Build Coastguard Worker 	};
481*cc4ad7daSAndroid Build Coastguard Worker 
482*cc4ad7daSAndroid Build Coastguard Worker 	return ts;
483*cc4ad7daSAndroid Build Coastguard Worker }
484*cc4ad7daSAndroid Build Coastguard Worker 
sleep_until_msec(unsigned long long msec)485*cc4ad7daSAndroid Build Coastguard Worker int sleep_until_msec(unsigned long long msec)
486*cc4ad7daSAndroid Build Coastguard Worker {
487*cc4ad7daSAndroid Build Coastguard Worker 	struct timespec ts = msec_ts(msec);
488*cc4ad7daSAndroid Build Coastguard Worker 
489*cc4ad7daSAndroid Build Coastguard Worker 	if (clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &ts, NULL) < 0 &&
490*cc4ad7daSAndroid Build Coastguard Worker 	    errno != EINTR)
491*cc4ad7daSAndroid Build Coastguard Worker 		return -errno;
492*cc4ad7daSAndroid Build Coastguard Worker 
493*cc4ad7daSAndroid Build Coastguard Worker 	return 0;
494*cc4ad7daSAndroid Build Coastguard Worker }
495*cc4ad7daSAndroid Build Coastguard Worker 
496*cc4ad7daSAndroid Build Coastguard Worker /*
497*cc4ad7daSAndroid Build Coastguard Worker  * Exponential retry backoff with tail
498*cc4ad7daSAndroid Build Coastguard Worker  */
get_backoff_delta_msec(unsigned long long t0,unsigned long long tend,unsigned long long * delta)499*cc4ad7daSAndroid Build Coastguard Worker unsigned long long get_backoff_delta_msec(unsigned long long t0,
500*cc4ad7daSAndroid Build Coastguard Worker 					  unsigned long long tend,
501*cc4ad7daSAndroid Build Coastguard Worker 					  unsigned long long *delta)
502*cc4ad7daSAndroid Build Coastguard Worker {
503*cc4ad7daSAndroid Build Coastguard Worker 	unsigned long long t;
504*cc4ad7daSAndroid Build Coastguard Worker 
505*cc4ad7daSAndroid Build Coastguard Worker 	t = now_msec();
506*cc4ad7daSAndroid Build Coastguard Worker 
507*cc4ad7daSAndroid Build Coastguard Worker 	if (!*delta)
508*cc4ad7daSAndroid Build Coastguard Worker 		*delta = 1;
509*cc4ad7daSAndroid Build Coastguard Worker 	else
510*cc4ad7daSAndroid Build Coastguard Worker 		*delta <<= 1;
511*cc4ad7daSAndroid Build Coastguard Worker 
512*cc4ad7daSAndroid Build Coastguard Worker 	while (t + *delta > tend)
513*cc4ad7daSAndroid Build Coastguard Worker 		*delta >>= 1;
514*cc4ad7daSAndroid Build Coastguard Worker 
515*cc4ad7daSAndroid Build Coastguard Worker 	if (!*delta && tend > t)
516*cc4ad7daSAndroid Build Coastguard Worker 		*delta = tend - t;
517*cc4ad7daSAndroid Build Coastguard Worker 
518*cc4ad7daSAndroid Build Coastguard Worker 	return t + *delta;
519*cc4ad7daSAndroid Build Coastguard Worker }
520*cc4ad7daSAndroid Build Coastguard Worker 
now_usec(void)521*cc4ad7daSAndroid Build Coastguard Worker unsigned long long now_usec(void)
522*cc4ad7daSAndroid Build Coastguard Worker {
523*cc4ad7daSAndroid Build Coastguard Worker 	struct timespec ts;
524*cc4ad7daSAndroid Build Coastguard Worker 
525*cc4ad7daSAndroid Build Coastguard Worker 	if (clock_gettime(CLOCK_MONOTONIC, &ts) != 0)
526*cc4ad7daSAndroid Build Coastguard Worker 		return 0;
527*cc4ad7daSAndroid Build Coastguard Worker 
528*cc4ad7daSAndroid Build Coastguard Worker 	return ts_usec(&ts);
529*cc4ad7daSAndroid Build Coastguard Worker }
530*cc4ad7daSAndroid Build Coastguard Worker 
now_msec(void)531*cc4ad7daSAndroid Build Coastguard Worker unsigned long long now_msec(void)
532*cc4ad7daSAndroid Build Coastguard Worker {
533*cc4ad7daSAndroid Build Coastguard Worker 	struct timespec ts;
534*cc4ad7daSAndroid Build Coastguard Worker 
535*cc4ad7daSAndroid Build Coastguard Worker 	if (clock_gettime(CLOCK_MONOTONIC, &ts) != 0)
536*cc4ad7daSAndroid Build Coastguard Worker 		return 0;
537*cc4ad7daSAndroid Build Coastguard Worker 
538*cc4ad7daSAndroid Build Coastguard Worker 	return ts_msec(&ts);
539*cc4ad7daSAndroid Build Coastguard Worker }
540*cc4ad7daSAndroid Build Coastguard Worker 
stat_mstamp(const struct stat * st)541*cc4ad7daSAndroid Build Coastguard Worker unsigned long long stat_mstamp(const struct stat *st)
542*cc4ad7daSAndroid Build Coastguard Worker {
543*cc4ad7daSAndroid Build Coastguard Worker #ifdef HAVE_STRUCT_STAT_ST_MTIM
544*cc4ad7daSAndroid Build Coastguard Worker 	return ts_usec(&st->st_mtim);
545*cc4ad7daSAndroid Build Coastguard Worker #else
546*cc4ad7daSAndroid Build Coastguard Worker 	return (unsigned long long) st->st_mtime;
547*cc4ad7daSAndroid Build Coastguard Worker #endif
548*cc4ad7daSAndroid Build Coastguard Worker }
549