ctdb-common: Fix compilation issue with strncpy()
[vlendec/samba-autobuild/.git] / ctdb / common / conf.c
1 /*
2    Configuration file handling on top of tini
3
4    Copyright (C) Amitay Isaacs  2017
5
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 3 of the License, or
9    (at your option) any later version.
10
11    This program 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
14    GNU General Public License for more details.
15
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include "replace.h"
21 #include "system/locale.h"
22
23 #include <talloc.h>
24
25 #include "lib/util/dlinklist.h"
26 #include "lib/util/tini.h"
27 #include "lib/util/debug.h"
28
29 #include "common/conf.h"
30
31 struct conf_value {
32         enum conf_type type;
33         union {
34                 const char *string;
35                 int integer;
36                 bool boolean;
37         } data;
38 };
39
40 union conf_pointer {
41         const char **string;
42         int *integer;
43         bool *boolean;
44 };
45
46 struct conf_option {
47         struct conf_option *prev, *next;
48
49         const char *name;
50         enum conf_type type;
51         void *validate;
52
53         struct conf_value default_value;
54         bool default_set;
55
56         struct conf_value *value, *new_value;
57         union conf_pointer ptr;
58         bool temporary_modified;
59 };
60
61 struct conf_section {
62         struct conf_section *prev, *next;
63
64         const char *name;
65         conf_validate_section_fn validate;
66         struct conf_option *option;
67 };
68
69 struct conf_context {
70         const char *filename;
71         struct conf_section *section;
72         bool define_failed;
73         bool ignore_unknown;
74         bool reload;
75         bool validation_active;
76 };
77
78 /*
79  * Functions related to conf_value
80  */
81
82 static int string_to_string(TALLOC_CTX *mem_ctx,
83                             const char *str,
84                             const char **str_val)
85 {
86         char *t;
87
88         if (str == NULL) {
89                 return EINVAL;
90         }
91
92         t = talloc_strdup(mem_ctx, str);
93         if (t == NULL) {
94                 return ENOMEM;
95         }
96
97         *str_val = t;
98         return 0;
99 }
100
101 static int string_to_integer(const char *str, int *int_val)
102 {
103         long t;
104         char *endptr = NULL;
105
106         if (str == NULL) {
107                 return EINVAL;
108         }
109
110         t = strtol(str, &endptr, 0);
111         if (*str != '\0' || endptr == NULL) {
112                 if (t < 0 || t > INT_MAX) {
113                         return EINVAL;
114                 }
115
116                 *int_val = (int)t;
117                 return 0;
118         }
119
120         return EINVAL;
121 }
122
123 static int string_to_boolean(const char *str, bool *bool_val)
124 {
125         if (strcasecmp(str, "true") == 0) {
126                 *bool_val = true;
127                 return 0;
128         }
129
130         if (strcasecmp(str, "false") == 0) {
131                 *bool_val = false;
132                 return 0;
133         }
134
135         return EINVAL;
136 }
137
138 static int conf_value_from_string(TALLOC_CTX *mem_ctx,
139                                   const char *str,
140                                   struct conf_value *value)
141 {
142         int ret;
143
144         switch (value->type) {
145         case CONF_STRING:
146                 ret = string_to_string(mem_ctx, str, &value->data.string);
147                 break;
148
149         case CONF_INTEGER:
150                 ret = string_to_integer(str, &value->data.integer);
151                 break;
152
153         case CONF_BOOLEAN:
154                 ret = string_to_boolean(str, &value->data.boolean);
155                 break;
156
157         default:
158                 return ENOENT;
159         }
160
161         return ret;
162 }
163
164 static bool conf_value_compare(struct conf_value *old, struct conf_value *new)
165 {
166         if (old == NULL || new == NULL) {
167                 return false;
168         }
169
170         if (old->type != new->type) {
171                 return false;
172         }
173
174         switch (old->type) {
175         case CONF_STRING:
176                 if (old->data.string == NULL && new->data.string == NULL) {
177                         return true;
178                 }
179                 if (old->data.string != NULL && new->data.string != NULL) {
180                         if (strcmp(old->data.string, new->data.string) == 0) {
181                                 return true;
182                         }
183                 }
184                 break;
185
186         case CONF_INTEGER:
187                 if (old->data.integer == new->data.integer) {
188                         return true;
189                 }
190                 break;
191
192         case CONF_BOOLEAN:
193                 if (old->data.boolean == new->data.boolean) {
194                         return true;
195                 }
196                 break;
197         }
198
199         return false;
200 }
201
202 static int conf_value_copy(TALLOC_CTX *mem_ctx,
203                            struct conf_value *src,
204                            struct conf_value *dst)
205 {
206         if (src->type != dst->type) {
207                 return EINVAL;
208         }
209
210         switch (src->type) {
211         case CONF_STRING:
212                 if (dst->data.string != NULL) {
213                         talloc_free(discard_const(dst->data.string));
214                 }
215                 if (src->data.string == NULL) {
216                         dst->data.string = NULL;
217                 } else {
218                         dst->data.string = talloc_strdup(
219                                 mem_ctx, src->data.string);
220                         if (dst->data.string == NULL) {
221                                 return ENOMEM;
222                         }
223                 }
224                 break;
225
226         case CONF_INTEGER:
227                 dst->data.integer = src->data.integer;
228                 break;
229
230         case CONF_BOOLEAN:
231                 dst->data.boolean = src->data.boolean;
232                 break;
233
234         default:
235                 return ENOENT;
236         }
237
238         return 0;
239 }
240
241 static void conf_value_dump(const char *key,
242                             struct conf_value *value,
243                             bool is_default,
244                             bool is_temporary,
245                             FILE *fp)
246 {
247         if ((value->type == CONF_STRING && value->data.string == NULL) ||
248             is_default) {
249                 fprintf(fp, "\t# %s = ", key);
250         } else {
251                 fprintf(fp, "\t%s = ", key);
252         }
253
254         switch (value->type) {
255         case CONF_STRING:
256                 if (value->data.string != NULL) {
257                         fprintf(fp, "%s", value->data.string);
258                 }
259                 break;
260
261         case CONF_INTEGER:
262                 fprintf(fp, "%d", value->data.integer);
263                 break;
264
265         case CONF_BOOLEAN:
266                 fprintf(fp, "%s", (value->data.boolean ? "true" : "false"));
267                 break;
268         }
269
270         if (is_temporary) {
271                 fprintf(fp, " # temporary");
272         }
273
274         fprintf(fp, "\n");
275 }
276
277 /*
278  * Functions related to conf_option
279  */
280
281 static struct conf_option *conf_option_find(struct conf_section *s,
282                                             const char *key)
283 {
284         struct conf_option *opt;
285
286         for (opt = s->option; opt != NULL; opt = opt->next) {
287                 if (strcmp(opt->name, key) == 0) {
288                         return opt;
289                 }
290         }
291
292         return NULL;
293 }
294
295 static void conf_option_set_ptr_value(struct conf_option *opt)
296 {
297         switch (opt->type) {
298         case CONF_STRING:
299                 if (opt->ptr.string != NULL) {
300                         *(opt->ptr.string) = opt->value->data.string;
301                 }
302                 break;
303
304         case CONF_INTEGER:
305                 if (opt->ptr.integer != NULL) {
306                         *(opt->ptr.integer) = opt->value->data.integer;
307                 }
308                 break;
309
310         case CONF_BOOLEAN:
311                 if (opt->ptr.boolean != NULL) {
312                         *(opt->ptr.boolean) = opt->value->data.boolean;
313                 }
314                 break;
315         }
316 }
317
318 static void conf_option_default(struct conf_option *opt);
319
320 static int conf_option_add(struct conf_section *s,
321                            const char *key,
322                            enum conf_type type,
323                            void *validate,
324                            struct conf_option **popt)
325 {
326         struct conf_option *opt;
327
328         opt = conf_option_find(s, key);
329         if (opt != NULL) {
330                 D_ERR("conf: option \"%s\" already exists\n", key);
331                 return EEXIST;
332         }
333
334         opt = talloc_zero(s, struct conf_option);
335         if (opt == NULL) {
336                 return ENOMEM;
337         }
338
339         opt->name = talloc_strdup(opt, key);
340         if (opt->name == NULL) {
341                 talloc_free(opt);
342                 return ENOMEM;
343         }
344
345         opt->type = type;
346         opt->validate = validate;
347
348         DLIST_ADD_END(s->option, opt);
349
350         if (popt != NULL) {
351                 *popt = opt;
352         }
353
354         return 0;
355 }
356
357 static int conf_option_set_default(struct conf_option *opt,
358                                    struct conf_value *default_value)
359 {
360         int ret;
361
362         opt->default_value.type = opt->type;
363
364         ret = conf_value_copy(opt, default_value, &opt->default_value);
365         if (ret != 0) {
366                 return ret;
367         }
368
369         opt->default_set = true;
370         opt->temporary_modified = false;
371
372         return 0;
373 }
374
375 static void conf_option_set_ptr(struct conf_option *opt,
376                                 union conf_pointer *ptr)
377 {
378         opt->ptr = *ptr;
379 }
380
381 static bool conf_option_validate_string(struct conf_option *opt,
382                                         struct conf_value *value,
383                                         enum conf_update_mode mode)
384 {
385         conf_validate_string_option_fn validate =
386                 (conf_validate_string_option_fn)opt->validate;
387
388         return validate(opt->name,
389                         opt->value->data.string,
390                         value->data.string,
391                         mode);
392 }
393
394 static bool conf_option_validate_integer(struct conf_option *opt,
395                                          struct conf_value *value,
396                                          enum conf_update_mode mode)
397 {
398         conf_validate_integer_option_fn validate =
399                 (conf_validate_integer_option_fn)opt->validate;
400
401         return validate(opt->name,
402                         opt->value->data.integer,
403                         value->data.integer,
404                         mode);
405 }
406
407 static bool conf_option_validate_boolean(struct conf_option *opt,
408                                          struct conf_value *value,
409                                          enum conf_update_mode mode)
410 {
411         conf_validate_boolean_option_fn validate =
412                 (conf_validate_boolean_option_fn)opt->validate;
413
414         return validate(opt->name,
415                         opt->value->data.boolean,
416                         value->data.boolean,
417                         mode);
418 }
419
420 static bool conf_option_validate(struct conf_option *opt,
421                                  struct conf_value *value,
422                                  enum conf_update_mode mode)
423 {
424         int ret;
425
426         if (opt->validate == NULL) {
427                 return true;
428         }
429
430         switch (opt->type) {
431         case CONF_STRING:
432                 ret = conf_option_validate_string(opt, value, mode);
433                 break;
434
435         case CONF_INTEGER:
436                 ret = conf_option_validate_integer(opt, value, mode);
437                 break;
438
439         case CONF_BOOLEAN:
440                 ret = conf_option_validate_boolean(opt, value, mode);
441                 break;
442
443         default:
444                 ret = EINVAL;
445         }
446
447         return ret;
448 }
449
450 static bool conf_option_same_value(struct conf_option *opt,
451                                    struct conf_value *new_value)
452 {
453         return conf_value_compare(opt->value, new_value);
454 }
455
456 static int conf_option_new_value(struct conf_option *opt,
457                                  struct conf_value *new_value,
458                                  enum conf_update_mode mode)
459 {
460         int ret;
461         bool ok;
462
463         if (opt->new_value != &opt->default_value) {
464                 TALLOC_FREE(opt->new_value);
465         }
466
467         if (new_value == &opt->default_value) {
468                 /*
469                  * This happens only during load/reload. Set the value to
470                  * default value, so if the config option is dropped from
471                  * config file, then it get's reset to default.
472                  */
473                 opt->new_value = &opt->default_value;
474         } else {
475                 ok = conf_option_validate(opt, new_value, mode);
476                 if (!ok) {
477                         D_ERR("conf: validation for option \"%s\" failed\n",
478                               opt->name);
479                         return EINVAL;
480                 }
481
482                 opt->new_value = talloc_zero(opt, struct conf_value);
483                 if (opt->new_value == NULL) {
484                         return ENOMEM;
485                 }
486
487                 opt->new_value->type = opt->value->type;
488                 ret = conf_value_copy(opt, new_value, opt->new_value);
489                 if (ret != 0) {
490                         return ret;
491                 }
492         }
493
494         conf_option_set_ptr_value(opt);
495
496         if (new_value != &opt->default_value) {
497                 if (mode == CONF_MODE_API) {
498                         opt->temporary_modified = true;
499                 } else {
500                         opt->temporary_modified = false;
501                 }
502         }
503
504         return 0;
505 }
506
507 static int conf_option_new_default_value(struct conf_option *opt,
508                                          enum conf_update_mode mode)
509 {
510         return conf_option_new_value(opt, &opt->default_value, mode);
511 }
512
513 static void conf_option_default(struct conf_option *opt)
514 {
515         if (! opt->default_set) {
516                 return;
517         }
518
519         if (opt->value != &opt->default_value) {
520                 TALLOC_FREE(opt->value);
521         }
522
523         opt->value = &opt->default_value;
524         conf_option_set_ptr_value(opt);
525 }
526
527 static void conf_option_reset(struct conf_option *opt)
528 {
529         if (opt->new_value != &opt->default_value) {
530                 TALLOC_FREE(opt->new_value);
531         }
532
533         conf_option_set_ptr_value(opt);
534 }
535
536 static void conf_option_update(struct conf_option *opt)
537 {
538         if (opt->new_value == NULL) {
539                 return;
540         }
541
542         if (opt->value != &opt->default_value) {
543                 TALLOC_FREE(opt->value);
544         }
545
546         opt->value = opt->new_value;
547         opt->new_value = NULL;
548
549         conf_option_set_ptr_value(opt);
550 }
551
552 static void conf_option_reset_temporary(struct conf_option *opt)
553 {
554         opt->temporary_modified = false;
555 }
556
557 static bool conf_option_is_default(struct conf_option *opt)
558 {
559         return (opt->value == &opt->default_value);
560 }
561
562 static void conf_option_dump(struct conf_option *opt, FILE *fp)
563 {
564         bool is_default;
565
566         is_default = conf_option_is_default(opt);
567
568         conf_value_dump(opt->name,
569                         opt->value,
570                         is_default,
571                         opt->temporary_modified,
572                         fp);
573 }
574
575 /*
576  * Functions related to conf_section
577  */
578
579 static struct conf_section *conf_section_find(struct conf_context *conf,
580                                               const char *section)
581 {
582         struct conf_section *s;
583
584         for (s = conf->section; s != NULL; s = s->next) {
585                 if (strcasecmp(s->name, section) == 0) {
586                         return s;
587                 }
588         }
589
590         return NULL;
591 }
592
593 static int conf_section_add(struct conf_context *conf,
594                             const char *section,
595                             conf_validate_section_fn validate)
596 {
597         struct conf_section *s;
598
599         s = conf_section_find(conf, section);
600         if (s != NULL) {
601                 return EEXIST;
602         }
603
604         s = talloc_zero(conf, struct conf_section);
605         if (s == NULL) {
606                 return ENOMEM;
607         }
608
609         s->name = talloc_strdup(s, section);
610         if (s->name == NULL) {
611                 talloc_free(s);
612                 return ENOMEM;
613         }
614
615         s->validate = validate;
616
617         DLIST_ADD_END(conf->section, s);
618         return 0;
619 }
620
621 static bool conf_section_validate(struct conf_context *conf,
622                                   struct conf_section *s,
623                                   enum conf_update_mode mode)
624 {
625         bool ok;
626
627         if (s->validate == NULL) {
628                 return true;
629         }
630
631         ok = s->validate(conf, s->name, mode);
632         if (!ok) {
633                 D_ERR("conf: validation for section [%s] failed\n", s->name);
634         }
635
636         return ok;
637 }
638
639 static void conf_section_dump(struct conf_section *s, FILE *fp)
640 {
641         fprintf(fp, "[%s]\n", s->name);
642 }
643
644 /*
645  * Functions related to conf_context
646  */
647
648 static void conf_all_default(struct conf_context *conf)
649 {
650         struct conf_section *s;
651         struct conf_option *opt;
652
653         for (s = conf->section; s != NULL; s = s->next) {
654                 for (opt = s->option; opt != NULL; opt = opt->next) {
655                         conf_option_default(opt);
656                 }
657         }
658 }
659
660 static int conf_all_temporary_default(struct conf_context *conf,
661                                       enum conf_update_mode mode)
662 {
663         struct conf_section *s;
664         struct conf_option *opt;
665         int ret;
666
667         for (s = conf->section; s != NULL; s = s->next) {
668                 for (opt = s->option; opt != NULL; opt = opt->next) {
669                         ret = conf_option_new_default_value(opt, mode);
670                         if (ret != 0) {
671                                 return ret;
672                         }
673                 }
674         }
675
676         return 0;
677 }
678
679 static void conf_all_reset(struct conf_context *conf)
680 {
681         struct conf_section *s;
682         struct conf_option *opt;
683
684         for (s = conf->section; s != NULL; s = s->next) {
685                 for (opt = s->option; opt != NULL; opt = opt->next) {
686                         conf_option_reset(opt);
687                 }
688         }
689 }
690
691 static void conf_all_update(struct conf_context *conf)
692 {
693         struct conf_section *s;
694         struct conf_option *opt;
695
696         for (s = conf->section; s != NULL; s = s->next) {
697                 for (opt = s->option; opt != NULL; opt = opt->next) {
698                         conf_option_update(opt);
699                         conf_option_reset_temporary(opt);
700                 }
701         }
702 }
703
704 /*
705  * API functions
706  */
707
708 int conf_init(TALLOC_CTX *mem_ctx, struct conf_context **result)
709 {
710         struct conf_context *conf;
711
712         conf = talloc_zero(mem_ctx, struct conf_context);
713         if (conf == NULL) {
714                 return ENOMEM;
715         }
716
717         conf->define_failed = false;
718
719         *result = conf;
720         return 0;
721 }
722
723 void conf_define_section(struct conf_context *conf,
724                          const char *section,
725                          conf_validate_section_fn validate)
726 {
727         int ret;
728
729         if (conf->define_failed) {
730                 return;
731         }
732
733         if (section == NULL) {
734                 conf->define_failed = true;
735                 return;
736         }
737
738         ret = conf_section_add(conf, section, validate);
739         if (ret != 0) {
740                 conf->define_failed = true;
741                 return;
742         }
743 }
744
745 static struct conf_option *conf_define(struct conf_context *conf,
746                                        const char *section,
747                                        const char *key,
748                                        enum conf_type type,
749                                        conf_validate_string_option_fn validate)
750 {
751         struct conf_section *s;
752         struct conf_option *opt;
753         int ret;
754
755         s = conf_section_find(conf, section);
756         if (s == NULL) {
757                 D_ERR("conf: unknown section [%s]\n", section);
758                 return NULL;
759         }
760
761         if (key == NULL) {
762                 D_ERR("conf: option name null in section [%s]\n", section);
763                 return NULL;
764         }
765
766         ret = conf_option_add(s, key, type, validate, &opt);
767         if (ret != 0) {
768                 return NULL;
769         }
770
771         return opt;
772 }
773
774 static void conf_define_post(struct conf_context *conf,
775                              struct conf_option *opt,
776                              struct conf_value *default_value)
777 {
778         int ret;
779
780         ret = conf_option_set_default(opt, default_value);
781         if (ret != 0) {
782                 conf->define_failed = true;
783                 return;
784         }
785
786         conf_option_default(opt);
787 }
788
789 void conf_define_string(struct conf_context *conf,
790                         const char *section,
791                         const char *key,
792                         const char *default_str_val,
793                         conf_validate_string_option_fn validate)
794 {
795         struct conf_option *opt;
796         struct conf_value default_value;
797
798         if (! conf_valid(conf)) {
799                 return;
800         }
801
802         opt = conf_define(conf, section, key, CONF_STRING, validate);
803         if (opt == NULL) {
804                 conf->define_failed = true;
805                 return;
806         }
807
808         default_value.type = CONF_STRING;
809         default_value.data.string = default_str_val;
810
811         conf_define_post(conf, opt, &default_value);
812 }
813
814 void conf_define_integer(struct conf_context *conf,
815                          const char *section,
816                          const char *key,
817                          const int default_int_val,
818                          conf_validate_integer_option_fn validate)
819 {
820         struct conf_option *opt;
821         struct conf_value default_value;
822
823         if (! conf_valid(conf)) {
824                 return;
825         }
826
827         opt = conf_define(conf, section, key, CONF_INTEGER, (void *)validate);
828         if (opt == NULL) {
829                 conf->define_failed = true;
830                 return;
831         }
832
833         default_value.type = CONF_INTEGER;
834         default_value.data.integer = default_int_val;
835
836         conf_define_post(conf, opt, &default_value);
837 }
838
839
840 void conf_define_boolean(struct conf_context *conf,
841                          const char *section,
842                          const char *key,
843                          const bool default_bool_val,
844                          conf_validate_boolean_option_fn validate)
845 {
846         struct conf_option *opt;
847         struct conf_value default_value;
848
849         if (! conf_valid(conf)) {
850                 return;
851         }
852
853         opt = conf_define(conf, section, key, CONF_BOOLEAN, (void *)validate);
854         if (opt == NULL) {
855                 conf->define_failed = true;
856                 return;
857         }
858
859         default_value.type = CONF_BOOLEAN;
860         default_value.data.boolean = default_bool_val;
861
862         conf_define_post(conf, opt, &default_value);
863 }
864
865 static struct conf_option *_conf_option(struct conf_context *conf,
866                                         const char *section,
867                                         const char *key)
868 {
869         struct conf_section *s;
870         struct conf_option *opt;
871
872         s = conf_section_find(conf, section);
873         if (s == NULL) {
874                 return NULL;
875         }
876
877         opt = conf_option_find(s, key);
878         return opt;
879 }
880
881 void conf_assign_string_pointer(struct conf_context *conf,
882                                 const char *section,
883                                 const char *key,
884                                 const char **str_ptr)
885 {
886         struct conf_option *opt;
887         union conf_pointer ptr;
888
889         opt = _conf_option(conf, section, key);
890         if (opt == NULL) {
891                 D_ERR("conf: unknown option [%s] -> \"%s\"\n", section, key);
892                 conf->define_failed = true;
893                 return;
894         }
895
896         if (opt->type != CONF_STRING) {
897                 conf->define_failed = true;
898                 return;
899         }
900
901         ptr.string = str_ptr;
902         conf_option_set_ptr(opt, &ptr);
903         conf_option_set_ptr_value(opt);
904 }
905
906 void conf_assign_integer_pointer(struct conf_context *conf,
907                                  const char *section,
908                                  const char *key,
909                                  int *int_ptr)
910 {
911         struct conf_option *opt;
912         union conf_pointer ptr;
913
914         opt = _conf_option(conf, section, key);
915         if (opt == NULL) {
916                 D_ERR("conf: unknown option [%s] -> \"%s\"\n", section, key);
917                 conf->define_failed = true;
918                 return;
919         }
920
921         if (opt->type != CONF_INTEGER) {
922                 conf->define_failed = true;
923                 return;
924         }
925
926         ptr.integer = int_ptr;
927         conf_option_set_ptr(opt, &ptr);
928         conf_option_set_ptr_value(opt);
929 }
930
931 void conf_assign_boolean_pointer(struct conf_context *conf,
932                                  const char *section,
933                                  const char *key,
934                                  bool *bool_ptr)
935 {
936         struct conf_option *opt;
937         union conf_pointer ptr;
938
939         opt = _conf_option(conf, section, key);
940         if (opt == NULL) {
941                 D_ERR("conf: unknown option [%s] -> \"%s\"\n", section, key);
942                 conf->define_failed = true;
943                 return;
944         }
945
946         if (opt->type != CONF_BOOLEAN) {
947                 conf->define_failed = true;
948                 return;
949         }
950
951         ptr.boolean = bool_ptr;
952         conf_option_set_ptr(opt, &ptr);
953         conf_option_set_ptr_value(opt);
954 }
955
956 bool conf_query(struct conf_context *conf,
957                 const char *section,
958                 const char *key,
959                 enum conf_type *type)
960 {
961         struct conf_section *s;
962         struct conf_option *opt;
963
964         if (! conf_valid(conf)) {
965                 return false;
966         }
967
968         s = conf_section_find(conf, section);
969         if (s == NULL) {
970                 return false;
971         }
972
973         opt = conf_option_find(s, key);
974         if (opt == NULL) {
975                 return false;
976         }
977
978         if (type != NULL) {
979                 *type = opt->type;
980         }
981         return true;
982 }
983
984 bool conf_valid(struct conf_context *conf)
985 {
986         if (conf->define_failed) {
987                 return false;
988         }
989
990         return true;
991 }
992
993 void conf_set_defaults(struct conf_context *conf)
994 {
995         conf_all_default(conf);
996 }
997
998 struct conf_load_state {
999         struct conf_context *conf;
1000         struct conf_section *s;
1001         enum conf_update_mode mode;
1002         int err;
1003 };
1004
1005 static bool conf_load_section(const char *section, void *private_data);
1006 static bool conf_load_option(const char *name,
1007                              const char *value_str,
1008                              void *private_data);
1009
1010 static int conf_load_internal(struct conf_context *conf)
1011 {
1012         struct conf_load_state state;
1013         FILE *fp;
1014         int ret;
1015         bool ok;
1016
1017         state = (struct conf_load_state) {
1018                 .conf = conf,
1019                 .mode = (conf->reload ? CONF_MODE_RELOAD : CONF_MODE_LOAD),
1020         };
1021
1022         ret = conf_all_temporary_default(conf, state.mode);
1023         if (ret != 0) {
1024                 return ret;
1025         }
1026
1027         fp = fopen(conf->filename, "r");
1028         if (fp == NULL) {
1029                 return errno;
1030         }
1031
1032         ok = tini_parse(fp,
1033                         false,
1034                         conf_load_section,
1035                         conf_load_option,
1036                         &state);
1037         fclose(fp);
1038         if (!ok) {
1039                 goto fail;
1040         }
1041
1042         /* Process the last section */
1043         if (state.s != NULL) {
1044                 ok = conf_section_validate(conf, state.s, state.mode);
1045                 if (!ok) {
1046                         state.err = EINVAL;
1047                         goto fail;
1048                 }
1049         }
1050
1051         conf_all_update(conf);
1052         return 0;
1053
1054 fail:
1055         conf_all_reset(conf);
1056         return state.err;
1057 }
1058
1059 static bool conf_load_section(const char *section, void *private_data)
1060 {
1061         struct conf_load_state *state =
1062                 (struct conf_load_state *)private_data;
1063         bool ok;
1064
1065         if (state->s != NULL) {
1066                 ok = conf_section_validate(state->conf, state->s, state->mode);
1067                 if (!ok) {
1068                         state->err = EINVAL;
1069                         return false;
1070                 }
1071         }
1072
1073         state->s = conf_section_find(state->conf, section);
1074         if (state->s == NULL) {
1075                 if (state->conf->ignore_unknown) {
1076                         D_DEBUG("conf: ignoring unknown section [%s]\n",
1077                                 section);
1078                 } else {
1079                         D_ERR("conf: unknown section [%s]\n", section);
1080                         state->err = EINVAL;
1081                         return false;
1082                 }
1083         }
1084
1085         return true;
1086 }
1087
1088 static bool conf_load_option(const char *name,
1089                              const char *value_str,
1090                              void *private_data)
1091 {
1092         struct conf_load_state *state =
1093                 (struct conf_load_state *)private_data;
1094         struct conf_option *opt;
1095         TALLOC_CTX *tmp_ctx;
1096         struct conf_value value;
1097         int ret;
1098         bool ok;
1099
1100         if (state->s == NULL) {
1101                 if (state->conf->ignore_unknown) {
1102                         D_DEBUG("conf: ignoring unknown option \"%s\"\n",
1103                                 name);
1104                         return true;
1105                 } else {
1106                         D_ERR("conf: unknown option \"%s\"\n", name);
1107                         state->err = EINVAL;
1108                         return false;
1109                 }
1110         }
1111
1112         opt = conf_option_find(state->s, name);
1113         if (opt == NULL) {
1114                 if (state->conf->ignore_unknown) {
1115                         return true;
1116                 } else {
1117                         state->err = ENOENT;
1118                         return false;
1119                 }
1120         }
1121
1122         tmp_ctx = talloc_new(state->conf);
1123         if (tmp_ctx == NULL) {
1124                 state->err = ENOMEM;
1125                 return false;
1126         }
1127
1128         value.type = opt->type;
1129         ret = conf_value_from_string(tmp_ctx, value_str, &value);
1130         if (ret != 0) {
1131                 talloc_free(tmp_ctx);
1132                 state->err = ret;
1133                 return false;
1134         }
1135
1136         ok = conf_option_same_value(opt, &value);
1137         if (ok) {
1138                 goto done;
1139         }
1140
1141         ret = conf_option_new_value(opt, &value, state->mode);
1142         if (ret != 0) {
1143                 talloc_free(tmp_ctx);
1144                 state->err = ret;
1145                 return false;
1146         }
1147
1148 done:
1149         talloc_free(tmp_ctx);
1150         return true;
1151
1152 }
1153
1154 int conf_load(struct conf_context *conf,
1155               const char *filename,
1156               bool ignore_unknown)
1157 {
1158         conf->filename = talloc_strdup(conf, filename);
1159         if (conf->filename == NULL) {
1160                 return ENOMEM;
1161         }
1162
1163         conf->ignore_unknown = ignore_unknown;
1164
1165         D_NOTICE("Reading config file %s\n", filename);
1166
1167         return conf_load_internal(conf);
1168 }
1169
1170 int conf_reload(struct conf_context *conf)
1171 {
1172         int ret;
1173
1174         if (conf->filename == NULL) {
1175                 return EPERM;
1176         }
1177
1178         D_NOTICE("Re-reading config file %s\n", conf->filename);
1179
1180         conf->reload = true;
1181         ret = conf_load_internal(conf);
1182         conf->reload = false;
1183
1184         return ret;
1185 }
1186
1187 static int conf_set(struct conf_context *conf,
1188                     const char *section,
1189                     const char *key,
1190                     struct conf_value *value)
1191 {
1192         struct conf_section *s;
1193         struct conf_option *opt;
1194         int ret;
1195         bool ok;
1196
1197         s = conf_section_find(conf, section);
1198         if (s == NULL) {
1199                 return ENOENT;
1200         }
1201
1202         opt = conf_option_find(s, key);
1203         if (opt == NULL) {
1204                 return ENOENT;
1205         }
1206
1207         if (opt->type != value->type) {
1208                 return ENOENT;
1209         }
1210
1211         ok = conf_option_same_value(opt, value);
1212         if (ok) {
1213                 return 0;
1214         }
1215
1216         ret = conf_option_new_value(opt, value, CONF_MODE_API);
1217         if (ret != 0) {
1218                 conf_option_reset(opt);
1219                 return ret;
1220         }
1221
1222         ok = conf_section_validate(conf, s, CONF_MODE_API);
1223         if (!ok) {
1224                 conf_option_reset(opt);
1225                 return EINVAL;
1226         }
1227
1228         conf_option_update(opt);
1229         return 0;
1230 }
1231
1232 int conf_set_string(struct conf_context *conf,
1233                     const char *section,
1234                     const char *key,
1235                     const char *str_val)
1236 {
1237         struct conf_value value;
1238
1239         value.type = CONF_STRING;
1240         value.data.string = str_val;
1241
1242         return conf_set(conf, section, key, &value);
1243 }
1244
1245 int conf_set_integer(struct conf_context *conf,
1246                      const char *section,
1247                      const char *key,
1248                      int int_val)
1249 {
1250         struct conf_value value;
1251
1252         value.type = CONF_INTEGER;
1253         value.data.integer = int_val;
1254
1255         return conf_set(conf, section, key, &value);
1256 }
1257
1258 int conf_set_boolean(struct conf_context *conf,
1259                      const char *section,
1260                      const char *key,
1261                      bool bool_val)
1262 {
1263         struct conf_value value;
1264
1265         value.type = CONF_BOOLEAN;
1266         value.data.boolean = bool_val;
1267
1268         return conf_set(conf, section, key, &value);
1269 }
1270
1271 static int conf_get(struct conf_context *conf,
1272                     const char *section,
1273                     const char *key,
1274                     enum conf_type type,
1275                     const struct conf_value **value,
1276                     bool *is_default)
1277 {
1278         struct conf_section *s;
1279         struct conf_option *opt;
1280
1281         s = conf_section_find(conf, section);
1282         if (s == NULL) {
1283                 return ENOENT;
1284         }
1285
1286         opt = conf_option_find(s, key);
1287         if (opt == NULL) {
1288                 return ENOENT;
1289         }
1290
1291         if (opt->type != type) {
1292                 return EINVAL;
1293         }
1294
1295         *value = opt->value;
1296         if (is_default != NULL) {
1297                 *is_default = conf_option_is_default(opt);
1298         }
1299
1300         return 0;
1301 }
1302
1303 int conf_get_string(struct conf_context *conf,
1304                     const char *section,
1305                     const char *key,
1306                     const char **str_val,
1307                     bool *is_default)
1308 {
1309         const struct conf_value *value;
1310         int ret;
1311
1312         ret = conf_get(conf, section, key, CONF_STRING, &value, is_default);
1313         if (ret != 0) {
1314                 return ret;
1315         }
1316
1317         *str_val = value->data.string;
1318         return 0;
1319 }
1320
1321 int conf_get_integer(struct conf_context *conf,
1322                      const char *section,
1323                      const char *key,
1324                      int *int_val,
1325                      bool *is_default)
1326 {
1327         const struct conf_value *value;
1328         int ret;
1329
1330         ret = conf_get(conf, section, key, CONF_INTEGER, &value, is_default);
1331         if (ret != 0) {
1332                 return ret;
1333         }
1334
1335         *int_val = value->data.integer;
1336         return 0;
1337 }
1338
1339 int conf_get_boolean(struct conf_context *conf,
1340                      const char *section,
1341                      const char *key,
1342                      bool *bool_val,
1343                      bool *is_default)
1344 {
1345         const struct conf_value *value;
1346         int ret;
1347
1348         ret = conf_get(conf, section, key, CONF_BOOLEAN, &value, is_default);
1349         if (ret != 0) {
1350                 return ret;
1351         }
1352
1353         *bool_val = value->data.boolean;
1354         return 0;
1355 }
1356
1357 void conf_dump(struct conf_context *conf, FILE *fp)
1358 {
1359         struct conf_section *s;
1360         struct conf_option *opt;
1361
1362         for (s = conf->section; s != NULL; s = s->next) {
1363                 conf_section_dump(s, fp);
1364                 for (opt = s->option; opt != NULL; opt = opt->next) {
1365                         conf_option_dump(opt, fp);
1366                 }
1367         }
1368 }