Merge branch 'settings-parser'
[strongswan.git] / src / libstrongswan / settings / settings.c
1 /*
2 * Copyright (C) 2010-2014 Tobias Brunner
3 * Copyright (C) 2008 Martin Willi
4 * Hochschule fuer Technik Rapperswil
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * for more details.
15 */
16
17 #define _GNU_SOURCE
18 #include <string.h>
19 #include <stdarg.h>
20 #include <stdio.h>
21 #include <errno.h>
22 #include <limits.h>
23 #include <sys/types.h>
24 #include <sys/stat.h>
25 #include <unistd.h>
26
27 #include "settings.h"
28 #include "settings_types.h"
29
30 #include "collections/array.h"
31 #include "collections/hashtable.h"
32 #include "collections/linked_list.h"
33 #include "threading/rwlock.h"
34 #include "utils/debug.h"
35
36 typedef struct private_settings_t private_settings_t;
37
38 /**
39 * Parse function provided by the generated parser.
40 */
41 bool settings_parser_parse_file(section_t *root, char *name);
42
43 /**
44 * Private data of settings
45 */
46 struct private_settings_t {
47
48 /**
49 * Public interface
50 */
51 settings_t public;
52
53 /**
54 * Top level section
55 */
56 section_t *top;
57
58 /**
59 * Contents of replaced settings (char*)
60 *
61 * FIXME: This is required because the pointer returned by get_str()
62 * is not refcounted. Might cause ever increasing usage stats.
63 */
64 array_t *contents;
65
66 /**
67 * Lock to safely access the settings
68 */
69 rwlock_t *lock;
70 };
71
72 /**
73 * Print a format key, but consume already processed arguments
74 */
75 static bool print_key(char *buf, int len, char *start, char *key, va_list args)
76 {
77 va_list copy;
78 char *pos = start;
79 bool res;
80
81 va_copy(copy, args);
82 while (TRUE)
83 {
84 pos = memchr(pos, '%', key - pos);
85 if (!pos)
86 {
87 break;
88 }
89 pos++;
90 switch (*pos)
91 {
92 case 'd':
93 va_arg(copy, int);
94 break;
95 case 's':
96 va_arg(copy, char*);
97 break;
98 case 'N':
99 va_arg(copy, enum_name_t*);
100 va_arg(copy, int);
101 break;
102 case '%':
103 break;
104 default:
105 DBG1(DBG_CFG, "settings with %%%c not supported!", *pos);
106 break;
107 }
108 pos++;
109 }
110 res = vsnprintf(buf, len, key, copy) < len;
111 va_end(copy);
112 return res;
113 }
114
115 /**
116 * Find a section by a given key, using buffered key, reusable buffer.
117 * If "ensure" is TRUE, the sections are created if they don't exist.
118 */
119 static section_t *find_section_buffered(section_t *section,
120 char *start, char *key, va_list args, char *buf, int len,
121 bool ensure)
122 {
123 char *pos;
124 section_t *found = NULL;
125
126 if (section == NULL)
127 {
128 return NULL;
129 }
130 pos = strchr(key, '.');
131 if (pos)
132 {
133 *pos = '\0';
134 pos++;
135 }
136 if (!print_key(buf, len, start, key, args))
137 {
138 return NULL;
139 }
140 if (!strlen(buf))
141 {
142 found = section;
143 }
144 else if (array_bsearch(section->sections, buf, settings_section_find,
145 &found) == -1)
146 {
147 if (ensure)
148 {
149 found = settings_section_create(strdup(buf));
150 settings_section_add(section, found, NULL);
151 }
152 }
153 if (found && pos)
154 {
155 return find_section_buffered(found, start, pos, args, buf, len, ensure);
156 }
157 return found;
158 }
159
160 /**
161 * Find all sections via a given key considering fallbacks, using buffered key,
162 * reusable buffer.
163 */
164 static void find_sections_buffered(section_t *section, char *start, char *key,
165 va_list args, char *buf, int len, array_t **sections)
166 {
167 section_t *found = NULL, *fallback;
168 char *pos;
169 int i;
170
171 if (!section)
172 {
173 return;
174 }
175 pos = strchr(key, '.');
176 if (pos)
177 {
178 *pos = '\0';
179 }
180 if (!print_key(buf, len, start, key, args))
181 {
182 return;
183 }
184 if (pos)
185 { /* restore so we can follow fallbacks */
186 *pos = '.';
187 }
188 if (!strlen(buf))
189 {
190 found = section;
191 }
192 else
193 {
194 array_bsearch(section->sections, buf, settings_section_find, &found);
195 }
196 if (found)
197 {
198 if (pos)
199 {
200 find_sections_buffered(found, start, pos+1, args, buf, len,
201 sections);
202 }
203 else
204 {
205 array_insert_create(sections, ARRAY_TAIL, found);
206 for (i = 0; i < array_count(found->fallbacks); i++)
207 {
208 array_get(found->fallbacks, i, &fallback);
209 array_insert_create(sections, ARRAY_TAIL, fallback);
210 }
211 }
212 }
213 if (section->fallbacks)
214 {
215 for (i = 0; i < array_count(section->fallbacks); i++)
216 {
217 array_get(section->fallbacks, i, &fallback);
218 find_sections_buffered(fallback, start, key, args, buf, len,
219 sections);
220 }
221 }
222 }
223
224 /**
225 * Ensure that the section with the given key exists (thread-safe).
226 */
227 static section_t *ensure_section(private_settings_t *this, section_t *section,
228 const char *key, va_list args)
229 {
230 char buf[128], keybuf[512];
231 section_t *found;
232
233 if (snprintf(keybuf, sizeof(keybuf), "%s", key) >= sizeof(keybuf))
234 {
235 return NULL;
236 }
237 /* we might have to change the tree */
238 this->lock->write_lock(this->lock);
239 found = find_section_buffered(section, keybuf, keybuf, args, buf,
240 sizeof(buf), TRUE);
241 this->lock->unlock(this->lock);
242 return found;
243 }
244
245 /**
246 * Find a section by a given key with its fallbacks (not thread-safe!).
247 * Sections are returned in depth-first order (array is allocated). NULL is
248 * returned if no sections are found.
249 */
250 static array_t *find_sections(private_settings_t *this, section_t *section,
251 char *key, va_list args)
252 {
253 char buf[128], keybuf[512];
254 array_t *sections = NULL;
255
256 if (snprintf(keybuf, sizeof(keybuf), "%s", key) >= sizeof(keybuf))
257 {
258 return NULL;
259 }
260 find_sections_buffered(section, keybuf, keybuf, args, buf,
261 sizeof(buf), &sections);
262 return sections;
263 }
264
265 /**
266 * Check if the given fallback section already exists
267 */
268 static bool fallback_exists(section_t *section, section_t *fallback)
269 {
270 if (section == fallback)
271 {
272 return TRUE;
273 }
274 else if (section->fallbacks)
275 {
276 section_t *existing;
277 int i;
278
279 for (i = 0; i < array_count(section->fallbacks); i++)
280 {
281 array_get(section->fallbacks, i, &existing);
282 if (existing == fallback)
283 {
284 return TRUE;
285 }
286 }
287 }
288 return FALSE;
289 }
290
291 /**
292 * Ensure that the section with the given key exists and add the given fallback
293 * section (thread-safe).
294 */
295 static void add_fallback_to_section(private_settings_t *this,
296 section_t *section, const char *key, va_list args,
297 section_t *fallback)
298 {
299 char buf[128], keybuf[512];
300 section_t *found;
301
302 if (snprintf(keybuf, sizeof(keybuf), "%s", key) >= sizeof(keybuf))
303 {
304 return;
305 }
306 this->lock->write_lock(this->lock);
307 found = find_section_buffered(section, keybuf, keybuf, args, buf,
308 sizeof(buf), TRUE);
309 if (!fallback_exists(found, fallback))
310 {
311 /* to ensure sections referred to as fallback are not purged, we create
312 * the array there too */
313 if (!fallback->fallbacks)
314 {
315 fallback->fallbacks = array_create(0, 0);
316 }
317 array_insert_create(&found->fallbacks, ARRAY_TAIL, fallback);
318 }
319 this->lock->unlock(this->lock);
320 }
321
322 /**
323 * Find the key/value pair for a key, using buffered key, reusable buffer
324 * If "ensure" is TRUE, the sections (and key/value pair) are created if they
325 * don't exist.
326 * Fallbacks are only considered if "ensure" is FALSE.
327 */
328 static kv_t *find_value_buffered(section_t *section, char *start, char *key,
329 va_list args, char *buf, int len, bool ensure)
330 {
331 int i;
332 char *pos;
333 kv_t *kv = NULL;
334 section_t *found = NULL;
335
336 if (section == NULL)
337 {
338 return NULL;
339 }
340
341 pos = strchr(key, '.');
342 if (pos)
343 {
344 *pos = '\0';
345 if (!print_key(buf, len, start, key, args))
346 {
347 return NULL;
348 }
349 /* restore so we can retry for fallbacks */
350 *pos = '.';
351 if (!strlen(buf))
352 {
353 found = section;
354 }
355 else if (array_bsearch(section->sections, buf, settings_section_find,
356 &found) == -1)
357 {
358 if (ensure)
359 {
360 found = settings_section_create(strdup(buf));
361 settings_section_add(section, found, NULL);
362 }
363 }
364 if (found)
365 {
366 kv = find_value_buffered(found, start, pos+1, args, buf, len,
367 ensure);
368 }
369 if (!kv && !ensure && section->fallbacks)
370 {
371 for (i = 0; !kv && i < array_count(section->fallbacks); i++)
372 {
373 array_get(section->fallbacks, i, &found);
374 kv = find_value_buffered(found, start, key, args, buf, len,
375 ensure);
376 }
377 }
378 }
379 else
380 {
381 if (!print_key(buf, len, start, key, args))
382 {
383 return NULL;
384 }
385 if (array_bsearch(section->kv, buf, settings_kv_find, &kv) == -1)
386 {
387 if (ensure)
388 {
389 kv = settings_kv_create(strdup(buf), NULL);
390 settings_kv_add(section, kv, NULL);
391 }
392 else if (section->fallbacks)
393 {
394 for (i = 0; !kv && i < array_count(section->fallbacks); i++)
395 {
396 array_get(section->fallbacks, i, &found);
397 kv = find_value_buffered(found, start, key, args, buf, len,
398 ensure);
399 }
400 }
401 }
402 }
403 return kv;
404 }
405
406 /**
407 * Find the string value for a key (thread-safe).
408 */
409 static char *find_value(private_settings_t *this, section_t *section,
410 char *key, va_list args)
411 {
412 char buf[128], keybuf[512], *value = NULL;
413 kv_t *kv;
414
415 if (snprintf(keybuf, sizeof(keybuf), "%s", key) >= sizeof(keybuf))
416 {
417 return NULL;
418 }
419 this->lock->read_lock(this->lock);
420 kv = find_value_buffered(section, keybuf, keybuf, args, buf, sizeof(buf),
421 FALSE);
422 if (kv)
423 {
424 value = kv->value;
425 }
426 this->lock->unlock(this->lock);
427 return value;
428 }
429
430 /**
431 * Set a value to a copy of the given string (thread-safe).
432 */
433 static void set_value(private_settings_t *this, section_t *section,
434 char *key, va_list args, char *value)
435 {
436 char buf[128], keybuf[512];
437 kv_t *kv;
438
439 if (snprintf(keybuf, sizeof(keybuf), "%s", key) >= sizeof(keybuf))
440 {
441 return;
442 }
443 this->lock->write_lock(this->lock);
444 kv = find_value_buffered(section, keybuf, keybuf, args, buf, sizeof(buf),
445 TRUE);
446 if (kv)
447 {
448 settings_kv_set(kv, strdupnull(value), this->contents);
449 }
450 this->lock->unlock(this->lock);
451 }
452
453 METHOD(settings_t, get_str, char*,
454 private_settings_t *this, char *key, char *def, ...)
455 {
456 char *value;
457 va_list args;
458
459 va_start(args, def);
460 value = find_value(this, this->top, key, args);
461 va_end(args);
462 if (value)
463 {
464 return value;
465 }
466 return def;
467 }
468
469 /**
470 * Described in header
471 */
472 inline bool settings_value_as_bool(char *value, bool def)
473 {
474 if (value)
475 {
476 if (strcaseeq(value, "1") ||
477 strcaseeq(value, "yes") ||
478 strcaseeq(value, "true") ||
479 strcaseeq(value, "enabled"))
480 {
481 return TRUE;
482 }
483 else if (strcaseeq(value, "0") ||
484 strcaseeq(value, "no") ||
485 strcaseeq(value, "false") ||
486 strcaseeq(value, "disabled"))
487 {
488 return FALSE;
489 }
490 }
491 return def;
492 }
493
494 METHOD(settings_t, get_bool, bool,
495 private_settings_t *this, char *key, bool def, ...)
496 {
497 char *value;
498 va_list args;
499
500 va_start(args, def);
501 value = find_value(this, this->top, key, args);
502 va_end(args);
503 return settings_value_as_bool(value, def);
504 }
505
506 /**
507 * Described in header
508 */
509 inline int settings_value_as_int(char *value, int def)
510 {
511 int intval;
512 if (value)
513 {
514 errno = 0;
515 intval = strtol(value, NULL, 10);
516 if (errno == 0)
517 {
518 return intval;
519 }
520 }
521 return def;
522 }
523
524 METHOD(settings_t, get_int, int,
525 private_settings_t *this, char *key, int def, ...)
526 {
527 char *value;
528 va_list args;
529
530 va_start(args, def);
531 value = find_value(this, this->top, key, args);
532 va_end(args);
533 return settings_value_as_int(value, def);
534 }
535
536 /**
537 * Described in header
538 */
539 inline double settings_value_as_double(char *value, double def)
540 {
541 double dval;
542 if (value)
543 {
544 errno = 0;
545 dval = strtod(value, NULL);
546 if (errno == 0)
547 {
548 return dval;
549 }
550 }
551 return def;
552 }
553
554 METHOD(settings_t, get_double, double,
555 private_settings_t *this, char *key, double def, ...)
556 {
557 char *value;
558 va_list args;
559
560 va_start(args, def);
561 value = find_value(this, this->top, key, args);
562 va_end(args);
563 return settings_value_as_double(value, def);
564 }
565
566 /**
567 * Described in header
568 */
569 inline u_int32_t settings_value_as_time(char *value, u_int32_t def)
570 {
571 char *endptr;
572 u_int32_t timeval;
573 if (value)
574 {
575 errno = 0;
576 timeval = strtoul(value, &endptr, 10);
577 if (errno == 0)
578 {
579 switch (*endptr)
580 {
581 case 'd': /* time in days */
582 timeval *= 24 * 3600;
583 break;
584 case 'h': /* time in hours */
585 timeval *= 3600;
586 break;
587 case 'm': /* time in minutes */
588 timeval *= 60;
589 break;
590 case 's': /* time in seconds */
591 default:
592 break;
593 }
594 return timeval;
595 }
596 }
597 return def;
598 }
599
600 METHOD(settings_t, get_time, u_int32_t,
601 private_settings_t *this, char *key, u_int32_t def, ...)
602 {
603 char *value;
604 va_list args;
605
606 va_start(args, def);
607 value = find_value(this, this->top, key, args);
608 va_end(args);
609 return settings_value_as_time(value, def);
610 }
611
612 METHOD(settings_t, set_str, void,
613 private_settings_t *this, char *key, char *value, ...)
614 {
615 va_list args;
616 va_start(args, value);
617 set_value(this, this->top, key, args, value);
618 va_end(args);
619 }
620
621 METHOD(settings_t, set_bool, void,
622 private_settings_t *this, char *key, bool value, ...)
623 {
624 va_list args;
625 va_start(args, value);
626 set_value(this, this->top, key, args, value ? "1" : "0");
627 va_end(args);
628 }
629
630 METHOD(settings_t, set_int, void,
631 private_settings_t *this, char *key, int value, ...)
632 {
633 char val[16];
634 va_list args;
635 va_start(args, value);
636 if (snprintf(val, sizeof(val), "%d", value) < sizeof(val))
637 {
638 set_value(this, this->top, key, args, val);
639 }
640 va_end(args);
641 }
642
643 METHOD(settings_t, set_double, void,
644 private_settings_t *this, char *key, double value, ...)
645 {
646 char val[64];
647 va_list args;
648 va_start(args, value);
649 if (snprintf(val, sizeof(val), "%f", value) < sizeof(val))
650 {
651 set_value(this, this->top, key, args, val);
652 }
653 va_end(args);
654 }
655
656 METHOD(settings_t, set_time, void,
657 private_settings_t *this, char *key, u_int32_t value, ...)
658 {
659 char val[16];
660 va_list args;
661 va_start(args, value);
662 if (snprintf(val, sizeof(val), "%u", value) < sizeof(val))
663 {
664 set_value(this, this->top, key, args, val);
665 }
666 va_end(args);
667 }
668
669 METHOD(settings_t, set_default_str, bool,
670 private_settings_t *this, char *key, char *value, ...)
671 {
672 char *old;
673 va_list args;
674
675 va_start(args, value);
676 old = find_value(this, this->top, key, args);
677 va_end(args);
678
679 if (!old)
680 {
681 va_start(args, value);
682 set_value(this, this->top, key, args, value);
683 va_end(args);
684 return TRUE;
685 }
686 return FALSE;
687 }
688
689 /**
690 * Data for enumerators
691 */
692 typedef struct {
693 /** settings_t instance */
694 private_settings_t *settings;
695 /** sections to enumerate */
696 array_t *sections;
697 /** sections/keys that were already enumerated */
698 hashtable_t *seen;
699 } enumerator_data_t;
700
701 /**
702 * Destroy enumerator data
703 */
704 static void enumerator_destroy(enumerator_data_t *this)
705 {
706 this->settings->lock->unlock(this->settings->lock);
707 this->seen->destroy(this->seen);
708 array_destroy(this->sections);
709 free(this);
710 }
711
712 /**
713 * Enumerate section names, not sections
714 */
715 static bool section_filter(hashtable_t *seen, section_t **in, char **out)
716 {
717 *out = (*in)->name;
718 if (seen->get(seen, *out))
719 {
720 return FALSE;
721 }
722 seen->put(seen, *out, *out);
723 return TRUE;
724 }
725
726 /**
727 * Enumerate sections of the given section
728 */
729 static enumerator_t *section_enumerator(section_t *section,
730 enumerator_data_t *data)
731 {
732 return enumerator_create_filter(
733 array_create_enumerator(section->sections_order),
734 (void*)section_filter, data->seen, NULL);
735 }
736
737 METHOD(settings_t, create_section_enumerator, enumerator_t*,
738 private_settings_t *this, char *key, ...)
739 {
740 enumerator_data_t *data;
741 array_t *sections;
742 va_list args;
743
744 this->lock->read_lock(this->lock);
745 va_start(args, key);
746 sections = find_sections(this, this->top, key, args);
747 va_end(args);
748
749 if (!sections)
750 {
751 this->lock->unlock(this->lock);
752 return enumerator_create_empty();
753 }
754 INIT(data,
755 .settings = this,
756 .sections = sections,
757 .seen = hashtable_create(hashtable_hash_str, hashtable_equals_str, 8),
758 );
759 return enumerator_create_nested(array_create_enumerator(sections),
760 (void*)section_enumerator, data, (void*)enumerator_destroy);
761 }
762
763 /**
764 * Enumerate key and values, not kv_t entries
765 */
766 static bool kv_filter(hashtable_t *seen, kv_t **in, char **key,
767 void *none, char **value)
768 {
769 *key = (*in)->key;
770 if (seen->get(seen, *key) || !(*in)->value)
771 {
772 return FALSE;
773 }
774 *value = (*in)->value;
775 seen->put(seen, *key, *key);
776 return TRUE;
777 }
778
779 /**
780 * Enumerate key/value pairs of the given section
781 */
782 static enumerator_t *kv_enumerator(section_t *section, enumerator_data_t *data)
783 {
784 return enumerator_create_filter(array_create_enumerator(section->kv_order),
785 (void*)kv_filter, data->seen, NULL);
786 }
787
788 METHOD(settings_t, create_key_value_enumerator, enumerator_t*,
789 private_settings_t *this, char *key, ...)
790 {
791 enumerator_data_t *data;
792 array_t *sections;
793 va_list args;
794
795 this->lock->read_lock(this->lock);
796 va_start(args, key);
797 sections = find_sections(this, this->top, key, args);
798 va_end(args);
799
800 if (!sections)
801 {
802 this->lock->unlock(this->lock);
803 return enumerator_create_empty();
804 }
805 INIT(data,
806 .settings = this,
807 .sections = sections,
808 .seen = hashtable_create(hashtable_hash_str, hashtable_equals_str, 8),
809 );
810 return enumerator_create_nested(array_create_enumerator(sections),
811 (void*)kv_enumerator, data, (void*)enumerator_destroy);
812 }
813
814 METHOD(settings_t, add_fallback, void,
815 private_settings_t *this, const char *key, const char *fallback, ...)
816 {
817 section_t *section;
818 va_list args;
819
820 /* find/create the fallback */
821 va_start(args, fallback);
822 section = ensure_section(this, this->top, fallback, args);
823 va_end(args);
824
825 va_start(args, fallback);
826 add_fallback_to_section(this, this->top, key, args, section);
827 va_end(args);
828 }
829
830 /**
831 * Load settings from files matching the given file pattern.
832 * All sections and values are added relative to "parent".
833 * All files (even included ones) have to be loaded successfully.
834 * If merge is FALSE the contents of parent are replaced with the parsed
835 * contents, otherwise they are merged together.
836 */
837 static bool load_files_internal(private_settings_t *this, section_t *parent,
838 char *pattern, bool merge)
839 {
840 section_t *section;
841
842 if (pattern == NULL || !pattern[0])
843 { /* TODO: Clear parent if merge is FALSE? */
844 return FALSE;
845 }
846
847 section = settings_section_create(NULL);
848 if (!settings_parser_parse_file(section, pattern))
849 {
850 settings_section_destroy(section, NULL);
851 return FALSE;
852 }
853
854 this->lock->write_lock(this->lock);
855 settings_section_extend(parent, section, this->contents, !merge);
856 this->lock->unlock(this->lock);
857
858 settings_section_destroy(section, NULL);
859 return TRUE;
860 }
861
862 METHOD(settings_t, load_files, bool,
863 private_settings_t *this, char *pattern, bool merge)
864 {
865 return load_files_internal(this, this->top, pattern, merge);
866 }
867
868 METHOD(settings_t, load_files_section, bool,
869 private_settings_t *this, char *pattern, bool merge, char *key, ...)
870 {
871 section_t *section;
872 va_list args;
873
874 va_start(args, key);
875 section = ensure_section(this, this->top, key, args);
876 va_end(args);
877
878 if (!section)
879 {
880 return FALSE;
881 }
882 return load_files_internal(this, section, pattern, merge);
883 }
884
885 METHOD(settings_t, destroy, void,
886 private_settings_t *this)
887 {
888 settings_section_destroy(this->top, NULL);
889 array_destroy_function(this->contents, (void*)free, NULL);
890 this->lock->destroy(this->lock);
891 free(this);
892 }
893
894 /*
895 * see header file
896 */
897 settings_t *settings_create(char *file)
898 {
899 private_settings_t *this;
900
901 INIT(this,
902 .public = {
903 .get_str = _get_str,
904 .get_int = _get_int,
905 .get_double = _get_double,
906 .get_time = _get_time,
907 .get_bool = _get_bool,
908 .set_str = _set_str,
909 .set_int = _set_int,
910 .set_double = _set_double,
911 .set_time = _set_time,
912 .set_bool = _set_bool,
913 .set_default_str = _set_default_str,
914 .create_section_enumerator = _create_section_enumerator,
915 .create_key_value_enumerator = _create_key_value_enumerator,
916 .add_fallback = _add_fallback,
917 .load_files = _load_files,
918 .load_files_section = _load_files_section,
919 .destroy = _destroy,
920 },
921 .top = settings_section_create(NULL),
922 .contents = array_create(0, 0),
923 .lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
924 );
925
926 load_files(this, file, FALSE);
927
928 return &this->public;
929 }