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