blob: 40b7adaa6741addb65062a8a73e0d3d75515a52b [file] [log] [blame]
Lucas De Marchi4462c4a2011-11-29 18:05:43 -02001/*
2 * libkmod - interface to kernel module operations
3 *
4 * Copyright (C) 2011 ProFUSION embedded systems
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
8 * License as published by the Free Software Foundation version 2.1.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
Lucas De Marchi7e317da2011-11-30 19:20:19 -020020#include <assert.h>
Lucas De Marchi4462c4a2011-11-29 18:05:43 -020021#include <stdio.h>
22#include <stdlib.h>
23#include <stddef.h>
24#include <stdarg.h>
25#include <unistd.h>
26#include <errno.h>
27#include <string.h>
28#include <ctype.h>
29
30#include "libkmod.h"
31#include "libkmod-private.h"
32
33/*
34 * Read one logical line from a configuration file.
35 *
36 * Line endings may be escaped with backslashes, to form one logical line from
37 * several physical lines. No end of line character(s) are included in the
38 * result.
39 *
40 * If linenum is not NULL, it is incremented by the number of physical lines
41 * which have been read.
42 */
43char *getline_wrapped(FILE *fp, unsigned int *linenum)
44{
45 int size = 256;
46 int i = 0;
47 char *buf = malloc(size);
Lucas De Marchi28c175e2011-12-12 11:52:59 -020048
Lucas De Marchi4462c4a2011-11-29 18:05:43 -020049 for(;;) {
50 int ch = getc_unlocked(fp);
51
52 switch(ch) {
53 case EOF:
54 if (i == 0) {
55 free(buf);
56 return NULL;
57 }
58 /* else fall through */
59
60 case '\n':
61 if (linenum)
62 (*linenum)++;
63 if (i == size)
64 buf = realloc(buf, size + 1);
65 buf[i] = '\0';
66 return buf;
67
68 case '\\':
69 ch = getc_unlocked(fp);
70
71 if (ch == '\n') {
72 if (linenum)
73 (*linenum)++;
74 continue;
75 }
76 /* else fall through */
77
78 default:
79 buf[i++] = ch;
80
81 if (i == size) {
82 size *= 2;
83 buf = realloc(buf, size);
84 }
85 }
86 }
87}
Lucas De Marchi8185fc92011-11-30 02:14:33 -020088
89/*
90 * Replace dashes with underscores.
91 * Dashes inside character range patterns (e.g. [0-9]) are left unchanged.
92 */
93char *underscores(struct kmod_ctx *ctx, char *s)
94{
95 unsigned int i;
96
97 if (!s)
98 return NULL;
99
100 for (i = 0; s[i]; i++) {
101 switch (s[i]) {
102 case '-':
103 s[i] = '_';
104 break;
105
106 case ']':
107 INFO(ctx, "Unmatched bracket in %s\n", s);
108 break;
109
110 case '[':
111 i += strcspn(&s[i], "]");
112 if (!s[i])
113 INFO(ctx, "Unmatched bracket in %s\n", s);
114 break;
115 }
116 }
117 return s;
118}
119
Lucas De Marchi7e317da2011-11-30 19:20:19 -0200120bool startswith(const char *s, const char *prefix) {
121 size_t sl, pl;
122
123 assert(s);
124 assert(prefix);
125
126 sl = strlen(s);
127 pl = strlen(prefix);
128
129 if (pl == 0)
130 return true;
131
132 if (sl < pl)
133 return false;
134
135 return memcmp(s, prefix, pl) == 0;
136}
Lucas De Marchie22c85f2011-12-02 17:21:18 -0200137
138inline void *memdup(const void *p, size_t n)
139{
140 void *r = malloc(n);
141
142 if (r == NULL)
143 return NULL;
144
145 return memcpy(r, p, n);
146}
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -0200147
148ssize_t read_str_safe(int fd, char *buf, size_t buflen) {
149 size_t todo = buflen;
150 size_t done;
Lucas De Marchi28c175e2011-12-12 11:52:59 -0200151
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -0200152 do {
153 ssize_t r = read(fd, buf, todo);
Lucas De Marchi28c175e2011-12-12 11:52:59 -0200154
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -0200155 if (r == 0)
156 break;
157 else if (r > 0)
158 todo -= r;
159 else {
160 if (errno == EAGAIN || errno == EWOULDBLOCK ||
161 errno == EINTR)
162 continue;
163 else
164 return -errno;
165 }
166 } while (todo > 0);
Lucas De Marchi28c175e2011-12-12 11:52:59 -0200167
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -0200168 done = buflen - todo;
Lucas De Marchi28c175e2011-12-12 11:52:59 -0200169
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -0200170 if (done == 0)
171 buf[0] = '\0';
172 else {
173 if (done < buflen)
174 buf[done] = '\0';
175 else if (buf[done - 1] != '\0')
176 return -ENOSPC;
177 }
Lucas De Marchi28c175e2011-12-12 11:52:59 -0200178
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -0200179 return done;
180}
181
182int read_str_long(int fd, long *value, int base) {
183 char buf[32], *end;
184 long v;
185 int err;
Lucas De Marchi28c175e2011-12-12 11:52:59 -0200186
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -0200187 *value = 0;
188 err = read_str_safe(fd, buf, sizeof(buf));
189 if (err < 0)
190 return err;
191 errno = 0;
192 v = strtol(buf, &end, base);
193 if (end == buf || !isspace(*end))
194 return -EINVAL;
Lucas De Marchi28c175e2011-12-12 11:52:59 -0200195
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -0200196 *value = v;
197 return 0;
198}
199
200int read_str_ulong(int fd, unsigned long *value, int base) {
201 char buf[32], *end;
202 long v;
203 int err;
Lucas De Marchi28c175e2011-12-12 11:52:59 -0200204
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -0200205 *value = 0;
206 err = read_str_safe(fd, buf, sizeof(buf));
207 if (err < 0)
208 return err;
209 errno = 0;
210 v = strtoul(buf, &end, base);
211 if (end == buf || !isspace(*end))
212 return -EINVAL;
213 *value = v;
214 return 0;
215}
Lucas De Marchiafca7802011-12-07 10:59:17 -0200216
217char *strchr_replace(char *s, int c, char r)
218{
219 char *p;
Lucas De Marchi28c175e2011-12-12 11:52:59 -0200220
Gustavo Sverzut Barbieribf8cf142011-12-10 19:45:37 -0200221 for (p = s; *p != '\0'; p++)
222 if (*p == c)
223 *p = r;
Lucas De Marchi28c175e2011-12-12 11:52:59 -0200224
Lucas De Marchiafca7802011-12-07 10:59:17 -0200225 return s;
226}
Lucas De Marchi3a468802011-12-07 13:50:52 -0200227
228bool path_is_absolute(const char *p)
229{
230 assert(p != NULL);
231
232 return p[0] == '/';
233}
Lucas De Marchi06363cc2011-12-07 13:51:40 -0200234
235char *path_make_absolute_cwd(const char *p)
236{
237 char *cwd, *r;
238 size_t plen;
239 size_t cwdlen;
240
241 if (path_is_absolute(p))
242 return strdup(p);
243
244 cwd = get_current_dir_name();
245 if (cwd == NULL)
246 return NULL;
247
248 plen = strlen(p);
249 cwdlen = strlen(cwd);
250
251 /* cwd + '/' + p + '\0' */
252 r = realloc(cwd, cwdlen + 1 + plen + 1);
253 if (r == NULL) {
254 free(cwd);
255 return NULL;
256 }
257
Lucas De Marchi4eb2c0f2011-12-08 10:37:56 -0200258 r[cwdlen] = '/';
259 memcpy(&r[cwdlen + 1], p, plen + 1);
Lucas De Marchi06363cc2011-12-07 13:51:40 -0200260
261 return r;
262}