]> git.ipfire.org Git - thirdparty/kmod.git/blame - libkmod/libkmod-util.c
build-sys: require xsltproc when manpages are enabled
[thirdparty/kmod.git] / libkmod / libkmod-util.c
CommitLineData
4462c4ac
LDM
1/*
2 * libkmod - interface to kernel module operations
3 *
a66a6a99 4 * Copyright (C) 2011-2012 ProFUSION embedded systems
4462c4ac
LDM
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
cb451f35
LDM
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
4462c4ac
LDM
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
7e317da3 21#include <assert.h>
4462c4ac
LDM
22#include <stdio.h>
23#include <stdlib.h>
24#include <stddef.h>
25#include <stdarg.h>
26#include <unistd.h>
27#include <errno.h>
28#include <string.h>
29#include <ctype.h>
30
31#include "libkmod.h"
32#include "libkmod-private.h"
33
34/*
35 * Read one logical line from a configuration file.
36 *
37 * Line endings may be escaped with backslashes, to form one logical line from
38 * several physical lines. No end of line character(s) are included in the
39 * result.
40 *
41 * If linenum is not NULL, it is incremented by the number of physical lines
42 * which have been read.
43 */
44char *getline_wrapped(FILE *fp, unsigned int *linenum)
45{
46 int size = 256;
47 int i = 0;
48 char *buf = malloc(size);
28c175ed 49
16984562
LP
50 if (buf == NULL)
51 return NULL;
52
4462c4ac
LDM
53 for(;;) {
54 int ch = getc_unlocked(fp);
55
56 switch(ch) {
57 case EOF:
58 if (i == 0) {
59 free(buf);
60 return NULL;
61 }
62 /* else fall through */
63
64 case '\n':
65 if (linenum)
66 (*linenum)++;
67 if (i == size)
68 buf = realloc(buf, size + 1);
69 buf[i] = '\0';
70 return buf;
71
72 case '\\':
73 ch = getc_unlocked(fp);
74
75 if (ch == '\n') {
76 if (linenum)
77 (*linenum)++;
78 continue;
79 }
80 /* else fall through */
81
82 default:
83 buf[i++] = ch;
84
85 if (i == size) {
86 size *= 2;
87 buf = realloc(buf, size);
88 }
89 }
90 }
91}
8185fc91 92
6daceb2f 93inline int alias_normalize(const char *alias, char buf[PATH_MAX], size_t *len)
b148b860
LDM
94{
95 size_t s;
96
6daceb2f 97 for (s = 0; s < PATH_MAX - 1; s++) {
b148b860
LDM
98 const char c = alias[s];
99 switch (c) {
100 case '-':
101 buf[s] = '_';
102 break;
103 case ']':
104 return -EINVAL;
105 case '[':
9901cfe2 106 while (alias[s] != ']' && alias[s] != '\0') {
647200fb 107 buf[s] = alias[s];
b148b860 108 s++;
647200fb 109 }
b148b860
LDM
110
111 if (alias[s] != ']')
112 return -EINVAL;
113
647200fb 114 buf[s] = alias[s];
b148b860
LDM
115 break;
116 case '\0':
b148b860
LDM
117 goto finish;
118 default:
119 buf[s] = c;
120 }
121 }
122
123finish:
124 buf[s] = '\0';
125
126 if (len)
127 *len = s;
128
129 return 0;
130}
131
6daceb2f 132inline char *modname_normalize(const char *modname, char buf[PATH_MAX],
a4848e24
LDM
133 size_t *len)
134{
135 size_t s;
136
6daceb2f 137 for (s = 0; s < PATH_MAX - 1; s++) {
a4848e24
LDM
138 const char c = modname[s];
139 if (c == '-')
140 buf[s] = '_';
141 else if (c == '\0' || c == '.')
142 break;
143 else
144 buf[s] = c;
145 }
146
147 buf[s] = '\0';
148
149 if (len)
150 *len = s;
151
152 return buf;
153}
154
6daceb2f 155char *path_to_modname(const char *path, char buf[PATH_MAX], size_t *len)
a4848e24
LDM
156{
157 char *modname;
158
159 modname = basename(path);
160 if (modname == NULL || modname[0] == '\0')
161 return NULL;
162
163 return modname_normalize(modname, buf, len);
164}
165
e22c85f3
LDM
166inline void *memdup(const void *p, size_t n)
167{
168 void *r = malloc(n);
169
170 if (r == NULL)
171 return NULL;
172
173 return memcpy(r, p, n);
174}
f12ae3c4 175
7a973b0c
LDM
176ssize_t read_str_safe(int fd, char *buf, size_t buflen)
177{
67179941
GSB
178 size_t todo = buflen - 1;
179 size_t done = 0;
28c175ed 180
f12ae3c4 181 do {
67179941 182 ssize_t r = read(fd, buf + done, todo);
28c175ed 183
f12ae3c4
GSB
184 if (r == 0)
185 break;
67179941 186 else if (r > 0) {
f12ae3c4 187 todo -= r;
67179941
GSB
188 done += r;
189 } else {
f12ae3c4 190 if (errno == EAGAIN || errno == EWOULDBLOCK ||
7a973b0c 191 errno == EINTR)
f12ae3c4
GSB
192 continue;
193 else
194 return -errno;
195 }
196 } while (todo > 0);
28c175ed 197
67179941 198 buf[done] = '\0';
f12ae3c4
GSB
199 return done;
200}
201
f1cbf3cf
LDM
202ssize_t write_str_safe(int fd, const char *buf, size_t buflen)
203{
204 size_t todo = buflen;
205 size_t done = 0;
206
207 do {
208 ssize_t r = write(fd, buf + done, todo);
209
210 if (r == 0)
211 break;
212 else if (r > 0) {
213 todo -= r;
214 done += r;
215 } else {
216 if (errno == EAGAIN || errno == EWOULDBLOCK ||
217 errno == EINTR)
218 continue;
219 else
220 return -errno;
221 }
222 } while (todo > 0);
223
224 return done;
225}
226
7a973b0c
LDM
227int read_str_long(int fd, long *value, int base)
228{
f12ae3c4
GSB
229 char buf[32], *end;
230 long v;
231 int err;
28c175ed 232
f12ae3c4
GSB
233 *value = 0;
234 err = read_str_safe(fd, buf, sizeof(buf));
235 if (err < 0)
236 return err;
237 errno = 0;
238 v = strtol(buf, &end, base);
239 if (end == buf || !isspace(*end))
240 return -EINVAL;
28c175ed 241
f12ae3c4
GSB
242 *value = v;
243 return 0;
244}
245
7a973b0c
LDM
246int read_str_ulong(int fd, unsigned long *value, int base)
247{
f12ae3c4
GSB
248 char buf[32], *end;
249 long v;
250 int err;
28c175ed 251
f12ae3c4
GSB
252 *value = 0;
253 err = read_str_safe(fd, buf, sizeof(buf));
254 if (err < 0)
255 return err;
256 errno = 0;
257 v = strtoul(buf, &end, base);
258 if (end == buf || !isspace(*end))
259 return -EINVAL;
260 *value = v;
261 return 0;
262}
afca7801
LDM
263
264char *strchr_replace(char *s, int c, char r)
265{
266 char *p;
28c175ed 267
bf8cf148
GSB
268 for (p = s; *p != '\0'; p++)
269 if (*p == c)
270 *p = r;
28c175ed 271
afca7801
LDM
272 return s;
273}
3a468809
LDM
274
275bool path_is_absolute(const char *p)
276{
277 assert(p != NULL);
278
279 return p[0] == '/';
280}
06363cc1
LDM
281
282char *path_make_absolute_cwd(const char *p)
283{
284 char *cwd, *r;
285 size_t plen;
286 size_t cwdlen;
287
288 if (path_is_absolute(p))
289 return strdup(p);
290
291 cwd = get_current_dir_name();
292 if (cwd == NULL)
293 return NULL;
294
295 plen = strlen(p);
296 cwdlen = strlen(cwd);
297
298 /* cwd + '/' + p + '\0' */
299 r = realloc(cwd, cwdlen + 1 + plen + 1);
300 if (r == NULL) {
301 free(cwd);
302 return NULL;
303 }
304
4eb2c0fc
LDM
305 r[cwdlen] = '/';
306 memcpy(&r[cwdlen + 1], p, plen + 1);
06363cc1
LDM
307
308 return r;
309}
0b29ef6f
LDM
310
311#define USEC_PER_SEC 1000000ULL
312#define NSEC_PER_USEC 1000ULL
535c541e
LDM
313unsigned long long ts_usec(const struct timespec *ts)
314{
315 return (unsigned long long) ts->tv_sec * USEC_PER_SEC +
316 (unsigned long long) ts->tv_nsec / NSEC_PER_USEC;
317}
318
6068aaae 319unsigned long long stat_mstamp(const struct stat *st)
0b29ef6f 320{
6068aaae 321#ifdef HAVE_STRUCT_STAT_ST_MTIM
535c541e 322 return ts_usec(&st->st_mtim);
6068aaae
LDM
323#else
324 return (unsigned long long) st->st_mtime;
325#endif
0b29ef6f 326}