]>
Commit | Line | Data |
---|---|---|
d6c9574f | 1 | /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ |
ed5bcfbe | 2 | |
a7334b09 LP |
3 | /*** |
4 | This file is part of systemd. | |
5 | ||
6 | Copyright 2010 Lennart Poettering | |
7 | ||
8 | systemd is free software; you can redistribute it and/or modify it | |
9 | under the terms of the GNU General Public License as published by | |
10 | the Free Software Foundation; either version 2 of the License, or | |
11 | (at your option) any later version. | |
12 | ||
13 | systemd is distributed in the hope that it will be useful, but | |
14 | WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
16 | General Public License for more details. | |
17 | ||
18 | You should have received a copy of the GNU General Public License | |
19 | along with systemd; If not, see <http://www.gnu.org/licenses/>. | |
20 | ***/ | |
21 | ||
ed5bcfbe LP |
22 | #include <string.h> |
23 | #include <stdio.h> | |
24 | #include <errno.h> | |
25 | #include <assert.h> | |
26 | #include <stdlib.h> | |
27 | ||
28 | #include "conf-parser.h" | |
29 | #include "util.h" | |
30 | #include "macro.h" | |
57d42a5f | 31 | #include "strv.h" |
16354eff | 32 | #include "log.h" |
ed5bcfbe | 33 | |
f975e971 LP |
34 | int config_item_table_lookup( |
35 | void *table, | |
ed5bcfbe | 36 | const char *section, |
ed5bcfbe | 37 | const char *lvalue, |
f975e971 LP |
38 | ConfigParserCallback *func, |
39 | int *ltype, | |
40 | void **data, | |
ed5bcfbe LP |
41 | void *userdata) { |
42 | ||
f975e971 LP |
43 | ConfigTableItem *t; |
44 | ||
45 | assert(table); | |
ed5bcfbe | 46 | assert(lvalue); |
f975e971 LP |
47 | assert(func); |
48 | assert(ltype); | |
49 | assert(data); | |
ed5bcfbe | 50 | |
f975e971 | 51 | for (t = table; t->lvalue; t++) { |
ed5bcfbe | 52 | |
f975e971 | 53 | if (!streq(lvalue, t->lvalue)) |
ed5bcfbe LP |
54 | continue; |
55 | ||
f975e971 | 56 | if (!streq_ptr(section, t->section)) |
ed5bcfbe LP |
57 | continue; |
58 | ||
f975e971 LP |
59 | *func = t->parse; |
60 | *ltype = t->ltype; | |
61 | *data = t->data; | |
62 | return 1; | |
63 | } | |
ed5bcfbe | 64 | |
f975e971 LP |
65 | return 0; |
66 | } | |
10e87ee7 | 67 | |
f975e971 LP |
68 | int config_item_perf_lookup( |
69 | void *table, | |
70 | const char *section, | |
71 | const char *lvalue, | |
72 | ConfigParserCallback *func, | |
73 | int *ltype, | |
74 | void **data, | |
75 | void *userdata) { | |
76 | ||
77 | ConfigPerfItemLookup lookup = (ConfigPerfItemLookup) table; | |
78 | const ConfigPerfItem *p; | |
79 | ||
80 | assert(table); | |
81 | assert(lvalue); | |
82 | assert(func); | |
83 | assert(ltype); | |
84 | assert(data); | |
85 | ||
86 | if (!section) | |
87 | p = lookup(lvalue, strlen(lvalue)); | |
88 | else { | |
89 | char *key; | |
90 | ||
44d91056 LP |
91 | key = join(section, ".", lvalue, NULL); |
92 | if (!key) | |
f975e971 LP |
93 | return -ENOMEM; |
94 | ||
95 | p = lookup(key, strlen(key)); | |
96 | free(key); | |
ed5bcfbe LP |
97 | } |
98 | ||
f975e971 LP |
99 | if (!p) |
100 | return 0; | |
101 | ||
102 | *func = p->parse; | |
103 | *ltype = p->ltype; | |
104 | *data = (uint8_t*) userdata + p->offset; | |
105 | return 1; | |
106 | } | |
107 | ||
108 | /* Run the user supplied parser for an assignment */ | |
109 | static int next_assignment( | |
110 | const char *filename, | |
111 | unsigned line, | |
112 | ConfigItemLookup lookup, | |
113 | void *table, | |
114 | const char *section, | |
115 | const char *lvalue, | |
116 | const char *rvalue, | |
117 | bool relaxed, | |
118 | void *userdata) { | |
119 | ||
120 | ConfigParserCallback func = NULL; | |
121 | int ltype = 0; | |
122 | void *data = NULL; | |
123 | int r; | |
124 | ||
125 | assert(filename); | |
126 | assert(line > 0); | |
127 | assert(lookup); | |
128 | assert(lvalue); | |
129 | assert(rvalue); | |
130 | ||
131 | r = lookup(table, section, lvalue, &func, <ype, &data, userdata); | |
132 | if (r < 0) | |
133 | return r; | |
134 | ||
d937fbbd LP |
135 | if (r > 0) { |
136 | if (func) | |
137 | return func(filename, line, section, lvalue, ltype, rvalue, data, userdata); | |
138 | ||
139 | return 0; | |
140 | } | |
f975e971 | 141 | |
46205bb6 | 142 | /* Warn about unknown non-extension fields. */ |
10e87ee7 | 143 | if (!relaxed && !startswith(lvalue, "X-")) |
f975e971 | 144 | log_info("[%s:%u] Unknown lvalue '%s' in section '%s'. Ignoring.", filename, line, lvalue, section); |
46205bb6 | 145 | |
f1857be0 | 146 | return 0; |
ed5bcfbe LP |
147 | } |
148 | ||
ed5bcfbe | 149 | /* Parse a variable assignment line */ |
f975e971 LP |
150 | static int parse_line( |
151 | const char *filename, | |
152 | unsigned line, | |
153 | const char *sections, | |
154 | ConfigItemLookup lookup, | |
155 | void *table, | |
156 | bool relaxed, | |
157 | char **section, | |
158 | char *l, | |
159 | void *userdata) { | |
160 | ||
b2aa81ef | 161 | char *e; |
ed5bcfbe | 162 | |
f975e971 LP |
163 | assert(filename); |
164 | assert(line > 0); | |
165 | assert(lookup); | |
166 | assert(l); | |
167 | ||
b2aa81ef | 168 | l = strstrip(l); |
ed5bcfbe | 169 | |
b2aa81ef | 170 | if (!*l) |
ed5bcfbe | 171 | return 0; |
1ea86b18 | 172 | |
b2aa81ef | 173 | if (strchr(COMMENTS, *l)) |
1ea86b18 | 174 | return 0; |
ed5bcfbe | 175 | |
b2aa81ef LP |
176 | if (startswith(l, ".include ")) { |
177 | char *fn; | |
ed5bcfbe LP |
178 | int r; |
179 | ||
f975e971 LP |
180 | fn = file_in_same_dir(filename, strstrip(l+9)); |
181 | if (!fn) | |
b2aa81ef | 182 | return -ENOMEM; |
ed5bcfbe | 183 | |
f975e971 | 184 | r = config_parse(fn, NULL, sections, lookup, table, relaxed, userdata); |
b2aa81ef LP |
185 | free(fn); |
186 | ||
ed5bcfbe LP |
187 | return r; |
188 | } | |
189 | ||
b2aa81ef | 190 | if (*l == '[') { |
ed5bcfbe LP |
191 | size_t k; |
192 | char *n; | |
193 | ||
b2aa81ef | 194 | k = strlen(l); |
ed5bcfbe LP |
195 | assert(k > 0); |
196 | ||
b2aa81ef | 197 | if (l[k-1] != ']') { |
16354eff | 198 | log_error("[%s:%u] Invalid section header.", filename, line); |
ed5bcfbe LP |
199 | return -EBADMSG; |
200 | } | |
201 | ||
f975e971 LP |
202 | n = strndup(l+1, k-2); |
203 | if (!n) | |
ed5bcfbe LP |
204 | return -ENOMEM; |
205 | ||
f975e971 | 206 | if (sections && !nulstr_contains(sections, n)) { |
42f4e3c4 | 207 | |
f975e971 LP |
208 | if (!relaxed) |
209 | log_info("[%s:%u] Unknown section '%s'. Ignoring.", filename, line, n); | |
210 | ||
211 | free(n); | |
212 | *section = NULL; | |
213 | } else { | |
214 | free(*section); | |
215 | *section = n; | |
216 | } | |
ed5bcfbe LP |
217 | |
218 | return 0; | |
219 | } | |
220 | ||
f975e971 | 221 | if (sections && !*section) |
10e87ee7 LP |
222 | return 0; |
223 | ||
f975e971 LP |
224 | e = strchr(l, '='); |
225 | if (!e) { | |
16354eff | 226 | log_error("[%s:%u] Missing '='.", filename, line); |
ed5bcfbe LP |
227 | return -EBADMSG; |
228 | } | |
229 | ||
230 | *e = 0; | |
231 | e++; | |
232 | ||
f975e971 LP |
233 | return next_assignment( |
234 | filename, | |
235 | line, | |
236 | lookup, | |
237 | table, | |
238 | *section, | |
239 | strstrip(l), | |
240 | strstrip(e), | |
241 | relaxed, | |
242 | userdata); | |
ed5bcfbe LP |
243 | } |
244 | ||
245 | /* Go through the file and parse each line */ | |
f975e971 LP |
246 | int config_parse( |
247 | const char *filename, | |
248 | FILE *f, | |
249 | const char *sections, | |
250 | ConfigItemLookup lookup, | |
251 | void *table, | |
252 | bool relaxed, | |
253 | void *userdata) { | |
254 | ||
ed5bcfbe LP |
255 | unsigned line = 0; |
256 | char *section = NULL; | |
ed5bcfbe | 257 | int r; |
63ad1ab4 | 258 | bool ours = false; |
3dab2943 | 259 | char *continuation = NULL; |
ed5bcfbe LP |
260 | |
261 | assert(filename); | |
f975e971 | 262 | assert(lookup); |
ed5bcfbe | 263 | |
87f0e418 | 264 | if (!f) { |
f975e971 LP |
265 | f = fopen(filename, "re"); |
266 | if (!f) { | |
87f0e418 LP |
267 | r = -errno; |
268 | log_error("Failed to open configuration file '%s': %s", filename, strerror(-r)); | |
269 | goto finish; | |
270 | } | |
63ad1ab4 LP |
271 | |
272 | ours = true; | |
ed5bcfbe LP |
273 | } |
274 | ||
275 | while (!feof(f)) { | |
3dab2943 LP |
276 | char l[LINE_MAX], *p, *c = NULL, *e; |
277 | bool escaped = false; | |
ed5bcfbe LP |
278 | |
279 | if (!fgets(l, sizeof(l), f)) { | |
280 | if (feof(f)) | |
281 | break; | |
282 | ||
283 | r = -errno; | |
16354eff | 284 | log_error("Failed to read configuration file '%s': %s", filename, strerror(-r)); |
ed5bcfbe LP |
285 | goto finish; |
286 | } | |
287 | ||
3dab2943 LP |
288 | truncate_nl(l); |
289 | ||
290 | if (continuation) { | |
f975e971 LP |
291 | c = strappend(continuation, l); |
292 | if (!c) { | |
3dab2943 LP |
293 | r = -ENOMEM; |
294 | goto finish; | |
295 | } | |
296 | ||
297 | free(continuation); | |
298 | continuation = NULL; | |
299 | p = c; | |
300 | } else | |
301 | p = l; | |
302 | ||
303 | for (e = p; *e; e++) { | |
304 | if (escaped) | |
305 | escaped = false; | |
306 | else if (*e == '\\') | |
307 | escaped = true; | |
308 | } | |
309 | ||
310 | if (escaped) { | |
311 | *(e-1) = ' '; | |
312 | ||
313 | if (c) | |
314 | continuation = c; | |
f975e971 LP |
315 | else { |
316 | continuation = strdup(l); | |
8ea913b2 | 317 | if (!continuation) { |
f975e971 LP |
318 | r = -ENOMEM; |
319 | goto finish; | |
320 | } | |
3dab2943 LP |
321 | } |
322 | ||
323 | continue; | |
324 | } | |
325 | ||
f975e971 LP |
326 | r = parse_line(filename, |
327 | ++line, | |
328 | sections, | |
329 | lookup, | |
330 | table, | |
331 | relaxed, | |
332 | §ion, | |
333 | p, | |
334 | userdata); | |
3dab2943 LP |
335 | free(c); |
336 | ||
337 | if (r < 0) | |
ed5bcfbe LP |
338 | goto finish; |
339 | } | |
340 | ||
341 | r = 0; | |
342 | ||
343 | finish: | |
344 | free(section); | |
3dab2943 | 345 | free(continuation); |
ed5bcfbe | 346 | |
63ad1ab4 | 347 | if (f && ours) |
ed5bcfbe LP |
348 | fclose(f); |
349 | ||
350 | return r; | |
351 | } | |
352 | ||
353 | int config_parse_int( | |
354 | const char *filename, | |
355 | unsigned line, | |
356 | const char *section, | |
357 | const char *lvalue, | |
2b583ce6 | 358 | int ltype, |
ed5bcfbe LP |
359 | const char *rvalue, |
360 | void *data, | |
361 | void *userdata) { | |
362 | ||
363 | int *i = data; | |
364 | int r; | |
365 | ||
366 | assert(filename); | |
367 | assert(lvalue); | |
368 | assert(rvalue); | |
369 | assert(data); | |
370 | ||
371 | if ((r = safe_atoi(rvalue, i)) < 0) { | |
f975e971 LP |
372 | log_error("[%s:%u] Failed to parse numeric value, ingoring: %s", filename, line, rvalue); |
373 | return 0; | |
ed5bcfbe LP |
374 | } |
375 | ||
376 | return 0; | |
377 | } | |
378 | ||
916abb21 LP |
379 | int config_parse_long( |
380 | const char *filename, | |
381 | unsigned line, | |
382 | const char *section, | |
383 | const char *lvalue, | |
384 | int ltype, | |
385 | const char *rvalue, | |
386 | void *data, | |
387 | void *userdata) { | |
388 | ||
389 | long *i = data; | |
390 | int r; | |
391 | ||
392 | assert(filename); | |
393 | assert(lvalue); | |
394 | assert(rvalue); | |
395 | assert(data); | |
396 | ||
397 | if ((r = safe_atoli(rvalue, i)) < 0) { | |
f975e971 LP |
398 | log_error("[%s:%u] Failed to parse numeric value, ignoring: %s", filename, line, rvalue); |
399 | return 0; | |
916abb21 LP |
400 | } |
401 | ||
402 | return 0; | |
403 | } | |
404 | ||
ec863ba6 LP |
405 | int config_parse_uint64( |
406 | const char *filename, | |
407 | unsigned line, | |
408 | const char *section, | |
409 | const char *lvalue, | |
2b583ce6 | 410 | int ltype, |
ec863ba6 LP |
411 | const char *rvalue, |
412 | void *data, | |
413 | void *userdata) { | |
414 | ||
415 | uint64_t *u = data; | |
416 | int r; | |
417 | ||
418 | assert(filename); | |
419 | assert(lvalue); | |
420 | assert(rvalue); | |
421 | assert(data); | |
422 | ||
423 | if ((r = safe_atou64(rvalue, u)) < 0) { | |
f975e971 LP |
424 | log_error("[%s:%u] Failed to parse numeric value, ignoring: %s", filename, line, rvalue); |
425 | return 0; | |
ec863ba6 LP |
426 | } |
427 | ||
428 | return 0; | |
429 | } | |
430 | ||
ed5bcfbe LP |
431 | int config_parse_unsigned( |
432 | const char *filename, | |
433 | unsigned line, | |
434 | const char *section, | |
435 | const char *lvalue, | |
2b583ce6 | 436 | int ltype, |
ed5bcfbe LP |
437 | const char *rvalue, |
438 | void *data, | |
439 | void *userdata) { | |
440 | ||
441 | unsigned *u = data; | |
442 | int r; | |
443 | ||
444 | assert(filename); | |
445 | assert(lvalue); | |
446 | assert(rvalue); | |
447 | assert(data); | |
448 | ||
449 | if ((r = safe_atou(rvalue, u)) < 0) { | |
16354eff | 450 | log_error("[%s:%u] Failed to parse numeric value: %s", filename, line, rvalue); |
ed5bcfbe LP |
451 | return r; |
452 | } | |
453 | ||
454 | return 0; | |
455 | } | |
456 | ||
457 | int config_parse_size( | |
458 | const char *filename, | |
459 | unsigned line, | |
460 | const char *section, | |
461 | const char *lvalue, | |
2b583ce6 | 462 | int ltype, |
ed5bcfbe LP |
463 | const char *rvalue, |
464 | void *data, | |
465 | void *userdata) { | |
466 | ||
467 | size_t *sz = data; | |
468 | unsigned u; | |
469 | int r; | |
470 | ||
471 | assert(filename); | |
472 | assert(lvalue); | |
473 | assert(rvalue); | |
474 | assert(data); | |
475 | ||
476 | if ((r = safe_atou(rvalue, &u)) < 0) { | |
f975e971 LP |
477 | log_error("[%s:%u] Failed to parse numeric value, ignoring: %s", filename, line, rvalue); |
478 | return 0; | |
ed5bcfbe LP |
479 | } |
480 | ||
481 | *sz = (size_t) u; | |
482 | return 0; | |
483 | } | |
484 | ||
485 | int config_parse_bool( | |
486 | const char *filename, | |
487 | unsigned line, | |
488 | const char *section, | |
489 | const char *lvalue, | |
2b583ce6 | 490 | int ltype, |
ed5bcfbe LP |
491 | const char *rvalue, |
492 | void *data, | |
493 | void *userdata) { | |
494 | ||
495 | int k; | |
496 | bool *b = data; | |
497 | ||
498 | assert(filename); | |
499 | assert(lvalue); | |
500 | assert(rvalue); | |
501 | assert(data); | |
502 | ||
503 | if ((k = parse_boolean(rvalue)) < 0) { | |
f975e971 LP |
504 | log_error("[%s:%u] Failed to parse boolean value, ignoring: %s", filename, line, rvalue); |
505 | return 0; | |
ed5bcfbe LP |
506 | } |
507 | ||
508 | *b = !!k; | |
509 | return 0; | |
510 | } | |
511 | ||
512 | int config_parse_string( | |
513 | const char *filename, | |
514 | unsigned line, | |
515 | const char *section, | |
516 | const char *lvalue, | |
2b583ce6 | 517 | int ltype, |
ed5bcfbe LP |
518 | const char *rvalue, |
519 | void *data, | |
520 | void *userdata) { | |
521 | ||
522 | char **s = data; | |
523 | char *n; | |
524 | ||
525 | assert(filename); | |
526 | assert(lvalue); | |
527 | assert(rvalue); | |
528 | assert(data); | |
529 | ||
530 | if (*rvalue) { | |
531 | if (!(n = strdup(rvalue))) | |
532 | return -ENOMEM; | |
533 | } else | |
534 | n = NULL; | |
535 | ||
536 | free(*s); | |
537 | *s = n; | |
538 | ||
539 | return 0; | |
540 | } | |
57d42a5f | 541 | |
034c6ed7 LP |
542 | int config_parse_path( |
543 | const char *filename, | |
544 | unsigned line, | |
545 | const char *section, | |
546 | const char *lvalue, | |
2b583ce6 | 547 | int ltype, |
034c6ed7 LP |
548 | const char *rvalue, |
549 | void *data, | |
550 | void *userdata) { | |
551 | ||
552 | char **s = data; | |
553 | char *n; | |
554 | ||
555 | assert(filename); | |
556 | assert(lvalue); | |
557 | assert(rvalue); | |
558 | assert(data); | |
559 | ||
15ae422b | 560 | if (!path_is_absolute(rvalue)) { |
f975e971 LP |
561 | log_error("[%s:%u] Not an absolute path, ignoring: %s", filename, line, rvalue); |
562 | return 0; | |
034c6ed7 LP |
563 | } |
564 | ||
565 | if (!(n = strdup(rvalue))) | |
566 | return -ENOMEM; | |
567 | ||
01f78473 LP |
568 | path_kill_slashes(n); |
569 | ||
034c6ed7 LP |
570 | free(*s); |
571 | *s = n; | |
572 | ||
573 | return 0; | |
574 | } | |
57d42a5f LP |
575 | |
576 | int config_parse_strv( | |
577 | const char *filename, | |
578 | unsigned line, | |
579 | const char *section, | |
580 | const char *lvalue, | |
2b583ce6 | 581 | int ltype, |
57d42a5f LP |
582 | const char *rvalue, |
583 | void *data, | |
584 | void *userdata) { | |
585 | ||
586 | char*** sv = data; | |
587 | char **n; | |
588 | char *w; | |
589 | unsigned k; | |
590 | size_t l; | |
591 | char *state; | |
592 | ||
593 | assert(filename); | |
594 | assert(lvalue); | |
595 | assert(rvalue); | |
596 | assert(data); | |
597 | ||
598 | k = strv_length(*sv); | |
034c6ed7 | 599 | FOREACH_WORD_QUOTED(w, l, rvalue, state) |
57d42a5f LP |
600 | k++; |
601 | ||
602 | if (!(n = new(char*, k+1))) | |
603 | return -ENOMEM; | |
604 | ||
3251df7d LP |
605 | if (*sv) |
606 | for (k = 0; (*sv)[k]; k++) | |
607 | n[k] = (*sv)[k]; | |
7418040c LP |
608 | else |
609 | k = 0; | |
3251df7d | 610 | |
034c6ed7 | 611 | FOREACH_WORD_QUOTED(w, l, rvalue, state) |
f60f22df | 612 | if (!(n[k++] = cunescape_length(w, l))) |
57d42a5f LP |
613 | goto fail; |
614 | ||
615 | n[k] = NULL; | |
616 | free(*sv); | |
617 | *sv = n; | |
618 | ||
619 | return 0; | |
620 | ||
621 | fail: | |
622 | for (; k > 0; k--) | |
623 | free(n[k-1]); | |
034c6ed7 | 624 | free(n); |
57d42a5f LP |
625 | |
626 | return -ENOMEM; | |
627 | } | |
15ae422b LP |
628 | |
629 | int config_parse_path_strv( | |
630 | const char *filename, | |
631 | unsigned line, | |
632 | const char *section, | |
633 | const char *lvalue, | |
2b583ce6 | 634 | int ltype, |
15ae422b LP |
635 | const char *rvalue, |
636 | void *data, | |
637 | void *userdata) { | |
638 | ||
639 | char*** sv = data; | |
640 | char **n; | |
641 | char *w; | |
642 | unsigned k; | |
643 | size_t l; | |
644 | char *state; | |
645 | int r; | |
646 | ||
647 | assert(filename); | |
648 | assert(lvalue); | |
649 | assert(rvalue); | |
650 | assert(data); | |
651 | ||
652 | k = strv_length(*sv); | |
653 | FOREACH_WORD_QUOTED(w, l, rvalue, state) | |
654 | k++; | |
655 | ||
656 | if (!(n = new(char*, k+1))) | |
657 | return -ENOMEM; | |
658 | ||
659 | k = 0; | |
660 | if (*sv) | |
661 | for (; (*sv)[k]; k++) | |
662 | n[k] = (*sv)[k]; | |
663 | ||
664 | FOREACH_WORD_QUOTED(w, l, rvalue, state) { | |
f60f22df | 665 | if (!(n[k] = cunescape_length(w, l))) { |
15ae422b LP |
666 | r = -ENOMEM; |
667 | goto fail; | |
668 | } | |
669 | ||
670 | if (!path_is_absolute(n[k])) { | |
f975e971 LP |
671 | log_error("[%s:%u] Not an absolute path, ignoring: %s", filename, line, rvalue); |
672 | free(n[k]); | |
673 | continue; | |
15ae422b LP |
674 | } |
675 | ||
01f78473 LP |
676 | path_kill_slashes(n[k]); |
677 | ||
15ae422b LP |
678 | k++; |
679 | } | |
680 | ||
681 | n[k] = NULL; | |
682 | free(*sv); | |
683 | *sv = n; | |
684 | ||
685 | return 0; | |
686 | ||
687 | fail: | |
688 | free(n[k]); | |
689 | for (; k > 0; k--) | |
690 | free(n[k-1]); | |
691 | free(n); | |
692 | ||
693 | return r; | |
694 | } | |
f975e971 LP |
695 | |
696 | int config_parse_usec( | |
697 | const char *filename, | |
698 | unsigned line, | |
699 | const char *section, | |
700 | const char *lvalue, | |
701 | int ltype, | |
702 | const char *rvalue, | |
703 | void *data, | |
704 | void *userdata) { | |
705 | ||
706 | usec_t *usec = data; | |
707 | ||
708 | assert(filename); | |
709 | assert(lvalue); | |
710 | assert(rvalue); | |
711 | assert(data); | |
712 | ||
713 | if (parse_usec(rvalue, usec) < 0) { | |
714 | log_error("[%s:%u] Failed to parse time value, ignoring: %s", filename, line, rvalue); | |
715 | return 0; | |
716 | } | |
717 | ||
718 | return 0; | |
719 | } | |
720 | ||
721 | int config_parse_mode( | |
722 | const char *filename, | |
723 | unsigned line, | |
724 | const char *section, | |
725 | const char *lvalue, | |
726 | int ltype, | |
727 | const char *rvalue, | |
728 | void *data, | |
729 | void *userdata) { | |
730 | ||
731 | mode_t *m = data; | |
732 | long l; | |
733 | char *x = NULL; | |
734 | ||
735 | assert(filename); | |
736 | assert(lvalue); | |
737 | assert(rvalue); | |
738 | assert(data); | |
739 | ||
740 | errno = 0; | |
741 | l = strtol(rvalue, &x, 8); | |
742 | if (!x || *x || errno) { | |
743 | log_error("[%s:%u] Failed to parse mode value, ignoring: %s", filename, line, rvalue); | |
744 | return 0; | |
745 | } | |
746 | ||
747 | if (l < 0000 || l > 07777) { | |
748 | log_error("[%s:%u] mode value out of range, ignoring: %s", filename, line, rvalue); | |
749 | return 0; | |
750 | } | |
751 | ||
752 | *m = (mode_t) l; | |
753 | return 0; | |
754 | } | |
e6960940 LP |
755 | |
756 | int config_parse_bytes( | |
757 | const char *filename, | |
758 | unsigned line, | |
759 | const char *section, | |
760 | const char *lvalue, | |
761 | int ltype, | |
762 | const char *rvalue, | |
763 | void *data, | |
764 | void *userdata) { | |
765 | ||
2edfe21d | 766 | off_t *bytes = data; |
e6960940 LP |
767 | |
768 | assert(filename); | |
769 | assert(lvalue); | |
770 | assert(rvalue); | |
771 | assert(data); | |
772 | ||
773 | assert_cc(sizeof(off_t) == sizeof(uint64_t)); | |
774 | ||
775 | if (parse_bytes(rvalue, bytes) < 0) { | |
776 | log_error("[%s:%u] Failed to parse bytes value, ignoring: %s", filename, line, rvalue); | |
777 | return 0; | |
778 | } | |
779 | ||
780 | return 0; | |
781 | } |