GNUnet 0.22.2
configuration.c
Go to the documentation of this file.
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2006, 2007, 2008, 2009, 2013, 2020, 2021 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
26#include "platform.h"
27#include "gnunet_util_lib.h"
29
30#define LOG(kind, ...) GNUNET_log_from (kind, "util", __VA_ARGS__)
31
32#define LOG_STRERROR_FILE(kind, syscall, filename) \
33 GNUNET_log_from_strerror_file (kind, "util", syscall, filename)
34
39{
44
48 char *key;
49
53 char *val;
54
59
63 unsigned int hint_lineno;
64};
65
66
71{
76
81
85 char *name;
86
94
99
104
109
114};
115
117{
122
126 unsigned int level;
127
129
131
137
142};
143
144
149{
154
159
164
169
173 unsigned int current_nest_level;
174
179
186
191
196
202 const char *restrict_section;
203};
204
205
211{
213
215};
216
217
218void
221{
222 cfg->diagnostics = true;
223}
224
225
228{
230 char *p;
231
233 cfg->pd = pd;
234 /* make certain values from the project data available
235 as PATHS */
238 if (NULL != p)
239 {
241 "PATHS",
242 "DATADIR",
243 p);
244 GNUNET_free (p);
245 }
248 if (NULL != p)
249 {
251 "PATHS",
252 "LIBDIR",
253 p);
254 GNUNET_free (p);
255 }
258 if (NULL != p)
259 {
261 "PATHS",
262 "BINDIR",
263 p);
264 GNUNET_free (p);
265 }
268 if (NULL != p)
269 {
271 "PATHS",
272 "PREFIX",
273 p);
274 GNUNET_free (p);
275 }
278 if (NULL != p)
279 {
281 "PATHS",
282 "LOCALEDIR",
283 p);
284 GNUNET_free (p);
285 }
288 if (NULL != p)
289 {
291 "PATHS",
292 "ICONDIR",
293 p);
294 GNUNET_free (p);
295 }
298 if (NULL != p)
299 {
301 "PATHS",
302 "DOCDIR",
303 p);
304 GNUNET_free (p);
305 }
308 if (NULL != p)
309 {
311 "PATHS",
312 "LIBEXECDIR",
313 p);
314 GNUNET_free (p);
315 }
316 return cfg;
317}
318
319
320void
322{
323 struct ConfigSection *sec;
324 struct ConfigFile *cf;
325
326 while (NULL != (sec = cfg->sections))
328 while (NULL != (cf = cfg->loaded_files_head))
329 {
334 cf);
335 GNUNET_free (cf);
336 }
339}
340
341
344 const char *filename,
346 void *cb_cls)
347{
350
352 if (GNUNET_OK !=
354 filename))
355 {
356 GNUNET_break (0);
358 return GNUNET_SYSERR;
359 }
360 ret = cb (cb_cls,
361 cfg);
363 return ret;
364}
365
366
371{
375 char **files;
376
380 unsigned int files_length;
381};
382
383
395 const char *filename)
396{
397 struct CollectFilesContext *igc = cls;
398
400 igc->files_length,
402 return GNUNET_OK;
403}
404
405
413static struct ConfigSection *
415 const char *section)
416{
417 struct ConfigSection *pos;
418
419 if (NULL == cfg)
420 return NULL;
421
422 pos = cfg->sections;
423 while ((pos != NULL) && (0 != strcasecmp (section, pos->name)))
424 pos = pos->next;
425 return pos;
426}
427
428
429static int
430pstrcmp (const void *a,
431 const void *b)
432{
433 return strcmp (*((const char **) a),
434 *((const char **) b));
435}
436
437
445 const char *path_or_glob,
446 bool path_is_glob,
447 const char *restrict_section,
448 const char *source_filename,
449 unsigned int source_lineno)
450{
451 char *inline_path = NULL;
452 struct GNUNET_CONFIGURATION_Handle *other_cfg = NULL;
453 struct CollectFilesContext igc = {
454 .files = NULL,
455 .files_length = 0,
456 };
457 enum GNUNET_GenericReturnValue fun_ret;
458 unsigned int old_nest_level = cfg->current_nest_level++;
459
460 /* We support the section restriction only for non-globs */
461 GNUNET_assert (! (path_is_glob && (NULL != restrict_section)));
462
463 if (NULL == source_filename)
464 {
466 "Refusing to parse inline configurations, "
467 "not allowed without source filename!\n");
468 fun_ret = GNUNET_SYSERR;
469 goto cleanup;
470 }
471
472 if ('/' == *path_or_glob)
473 inline_path = GNUNET_strdup (path_or_glob);
474 else
475 {
476 /* We compute the canonical, absolute path first,
477 so that relative imports resolve properly with symlinked
478 config files. */
479 char *source_realpath;
480 char *endsep;
481
482 source_realpath = realpath (source_filename,
483 NULL);
484 if (NULL == source_realpath)
485 {
486 /* Couldn't even resolve path of base dir. */
487 GNUNET_break (0);
488 /* failed to parse included config */
489 fun_ret = GNUNET_SYSERR;
490 goto cleanup;
491 }
492 endsep = strrchr (source_realpath, '/');
493 GNUNET_assert (NULL != endsep);
494 *endsep = '\0';
495 GNUNET_asprintf (&inline_path,
496 "%s/%s",
497 source_realpath,
498 path_or_glob);
499 free (source_realpath);
500 }
501
502 if (path_is_glob)
503 {
504 int nret;
505
507 "processing config glob '%s'\n",
508 inline_path);
509
510 nret = GNUNET_DISK_glob (inline_path, collect_files_cb, &igc);
511 if (-1 == nret)
512 {
513 fun_ret = GNUNET_SYSERR;
514 goto cleanup;
515 }
516 GNUNET_assert (nret == igc.files_length);
517 qsort (igc.files, igc.files_length, sizeof (char *), pstrcmp);
518 for (int i = 0; i < nret; i++)
519 {
520 if (GNUNET_OK !=
522 igc.files[i]))
523 {
524 fun_ret = GNUNET_SYSERR;
525 goto cleanup;
526 }
527 }
528 fun_ret = GNUNET_OK;
529 }
530 else if (NULL != restrict_section)
531 {
532 enum GNUNET_GenericReturnValue inner_ret;
533 struct ConfigSection *cs;
534 struct ConfigFile *cf = GNUNET_new (struct ConfigFile);
535
536 inner_ret = GNUNET_DISK_file_test_read (inline_path);
537
538 cs = find_section (cfg, restrict_section);
539
540 if (NULL == cs)
541 {
542 cs = GNUNET_new (struct ConfigSection);
543 cs->name = GNUNET_strdup (restrict_section);
544 cs->next = cfg->sections;
545 cfg->sections = cs;
546 cs->entries = NULL;
547 }
548 if (cfg->diagnostics)
549 {
550 const char *pwname;
551 const char *grname;
552 char *sfn = GNUNET_STRINGS_filename_expand (inline_path);
553 struct stat istat;
554
555 cs->hint_secret_filename = sfn;
556 if (0 == stat (sfn, &istat))
557 {
558 struct passwd *pw = getpwuid (istat.st_uid);
559 struct group *gr = getgrgid (istat.st_gid);
560 pwname = (NULL == pw) ? "<unknown>" : pw->pw_name;
561 grname = (NULL == gr) ? "<unknown>" : gr->gr_name;
562
564 "%s:%s %o",
565 pwname,
566 grname,
567 istat.st_mode);
568 }
569 else
570 {
571 cs->hint_secret_stat = GNUNET_strdup ("<can't stat file>");
572 }
573 if (source_filename)
574 {
575 /* Possible that this secret section has been inlined before */
577 cs->hint_inlined_from_filename = GNUNET_strdup (source_filename);
578 cs->hint_inlined_from_line = source_lineno;
579 }
580 }
581
582 /* Put file in the load list for diagnostics, even if we can't access it. */
583 {
585 cf->source_filename = GNUNET_strdup (inline_path);
586 cf->hint_restrict_section = GNUNET_strdup (restrict_section);
589 cf);
590 }
591
592 if (GNUNET_OK != inner_ret)
593 {
594 cs->inaccessible = true;
595 cf->hint_inaccessible = true;
596 /* File can't be accessed, but that's okay. */
597 fun_ret = GNUNET_OK;
598 goto cleanup;
599 }
600
601 other_cfg = GNUNET_CONFIGURATION_create (cfg->pd);
602 other_cfg->restrict_section = restrict_section;
603 inner_ret = GNUNET_CONFIGURATION_parse (other_cfg,
604 inline_path);
605 if (GNUNET_OK != inner_ret)
606 {
607 cf->hint_inaccessible = true;
608 fun_ret = inner_ret;
609 goto cleanup;
610 }
611
612 cs = find_section (other_cfg,
613 restrict_section);
614 if (NULL == cs)
615 {
617 "Configuration file '%s' loaded with @inline-secret@ "
618 "does not contain section '%s'.\n",
619 inline_path,
620 restrict_section);
621 /* Inlined configuration is accessible but doesn't contain any values.
622 We treat this as if the inlined section was empty, and do not
623 consider it an error. */
624 fun_ret = GNUNET_OK;
625 goto cleanup;
626 }
627 for (struct ConfigEntry *ce = cs->entries;
628 NULL != ce;
629 ce = ce->next)
631 restrict_section,
632 ce->key,
633 ce->val);
634 fun_ret = GNUNET_OK;
635 }
636 else if (GNUNET_OK !=
638 inline_path))
639 {
640 fun_ret = GNUNET_SYSERR;
641 goto cleanup;
642 }
643 else
644 {
645 fun_ret = GNUNET_OK;
646 }
647cleanup:
648 cfg->current_nest_level = old_nest_level;
649 if (NULL != other_cfg)
651 GNUNET_free (inline_path);
652 if (igc.files_length > 0)
653 {
654 for (size_t i = 0; i < igc.files_length; i++)
655 GNUNET_free (igc.files[i]);
657 }
658 return fun_ret;
659}
660
661
670static struct ConfigEntry *
672 const char *section,
673 const char *key)
674{
675 struct ConfigSection *sec;
676 struct ConfigEntry *pos;
677
678 if (NULL == (sec = find_section (cfg, section)))
679 return NULL;
680 if (sec->inaccessible)
681 {
683 "Section '%s' is marked as inaccessible, because the configuration "
684 " file that contains the section can't be read. Attempts to use "
685 "option '%s' will fail.\n",
686 section,
687 key);
688 return NULL;
689 }
690 pos = sec->entries;
691 while ((pos != NULL) && (0 != strcasecmp (key, pos->key)))
692 pos = pos->next;
693 return pos;
694}
695
696
706static void
708 const char *section,
709 const char *option,
710 const char *hint_filename,
711 unsigned int hint_line)
712{
713 struct ConfigEntry *e = find_entry (cfg, section, option);
714 if (! cfg->diagnostics)
715 return;
716 if (! e)
717 return;
719 e->hint_lineno = hint_line;
720}
721
722
725 const char *mem,
726 size_t size,
727 const char *source_filename)
728{
729 size_t line_size;
730 unsigned int nr;
731 size_t r_bytes;
732 size_t to_read;
734 char *section;
735 char *eq;
736 char *tag;
737 char *value;
738 char *line_orig = NULL;
739
740 ret = GNUNET_OK;
741 section = NULL;
742 nr = 0;
743 r_bytes = 0;
744 while (r_bytes < size)
745 {
746 char *pos;
747 char *line;
748 bool emptyline;
749
750 GNUNET_free (line_orig);
751 /* fgets-like behaviour on buffer */
752 to_read = size - r_bytes;
753 pos = memchr (&mem[r_bytes], '\n', to_read);
754 if (NULL == pos)
755 {
756 line_orig = GNUNET_strndup (&mem[r_bytes],
757 line_size = to_read);
758 r_bytes += line_size;
759 }
760 else
761 {
762 line_orig = GNUNET_strndup (&mem[r_bytes],
763 line_size = (pos - &mem[r_bytes]));
764 r_bytes += line_size + 1;
765 }
766 line = line_orig;
767 /* increment line number */
768 nr++;
769 /* tabs and '\r' are whitespace */
770 emptyline = GNUNET_YES;
771 for (size_t i = 0; i < line_size; i++)
772 {
773 if (line[i] == '\t')
774 line[i] = ' ';
775 if (line[i] == '\r')
776 line[i] = ' ';
777 if (' ' != line[i])
778 emptyline = GNUNET_NO;
779 }
780 /* ignore empty lines */
781 if (GNUNET_YES == emptyline)
782 continue;
783
784 /* remove tailing whitespace */
785 for (size_t i = line_size - 1;
786 (i >= 1) && (isspace ((unsigned char) line[i]));
787 i--)
788 line[i] = '\0';
789
790 /* remove leading whitespace */
791 for (; line[0] != '\0' && (isspace ((unsigned char) line[0])); line++)
792 ;
793
794 /* ignore comments */
795 if ( ('#' == line[0]) ||
796 ('%' == line[0]) )
797 continue;
798
799 /* Handle special directives. */
800 if ('@' == line[0])
801 {
802 char *end = strchr (line + 1, '@');
803 char *directive;
804 enum GNUNET_GenericReturnValue directive_ret;
805
806 if (NULL != cfg->restrict_section)
807 {
809 "Illegal directive in line %u (parsing restricted section %s)\n",
810 nr,
813 break;
814 }
815
816 if (NULL == end)
817 {
819 "Bad directive in line %u\n",
820 nr);
822 break;
823 }
824 *end = '\0';
825 directive = line + 1;
826
827 if (0 == strcasecmp (directive,
828 "INLINE"))
829 {
830 const char *path = end + 1;
831
832 /* Skip space before path */
833 for (; isspace (*path); path++)
834 ;
835
836 directive_ret = handle_inline (cfg,
837 path,
838 false,
839 NULL,
840 source_filename,
841 nr);
842 }
843 else if (0 == strcasecmp (directive,
844 "INLINE-MATCHING"))
845 {
846 const char *path = end + 1;
847
848 /* Skip space before path */
849 for (; isspace (*path); path++)
850 ;
851
852 directive_ret = handle_inline (cfg,
853 path,
854 true,
855 NULL,
856 source_filename,
857 nr);
858 }
859 else if (0 == strcasecmp (directive,
860 "INLINE-SECRET"))
861 {
862 char *secname = end + 1;
863 char *secname_end;
864 const char *path;
865
866 /* Skip space before secname */
867 for (; isspace (*secname); secname++)
868 ;
869
870 secname_end = strchr (secname, ' ');
871
872 if (NULL == secname_end)
873 {
875 "Bad inline-secret directive in line %u\n",
876 nr);
878 break;
879 }
880 *secname_end = '\0';
881 path = secname_end + 1;
882
883 /* Skip space before path */
884 for (; isspace (*path); path++)
885 ;
886
887 directive_ret = handle_inline (cfg,
888 path,
889 false,
890 secname,
891 source_filename,
892 nr);
893 }
894 else
895 {
897 "Unknown or malformed directive '%s' in line %u\n",
898 directive,
899 nr);
901 break;
902 }
903 if (GNUNET_OK != directive_ret)
904 {
905 ret = directive_ret;
906 break;
907 }
908 continue;
909 }
910 if ( ('[' == line[0]) &&
911 (']' == line[line_size - 1]) )
912 {
913 /* [value] */
914 line[line_size - 1] = '\0';
915 value = &line[1];
916 GNUNET_free (section);
917 section = GNUNET_strdup (value);
918 continue;
919 }
920 if (NULL != (eq = strchr (line, '=')))
921 {
922
923 if (NULL == section)
924 {
926 "Syntax error while deserializing in line %u (option without section)\n",
927 nr);
929 break;
930 }
931
932 /* tag = value */
933 tag = GNUNET_strndup (line, eq - line);
934 /* remove tailing whitespace */
935 for (int i = strlen (tag) - 1;
936 (i >= 1) && (isspace ((unsigned char) tag[i]));
937 i--)
938 tag[i] = '\0';
939
940 /* Strip whitespace */
941 value = eq + 1;
942 while (isspace ((unsigned char) value[0]))
943 value++;
944 for (int i = strlen (value) - 1;
945 (i >= 1) && (isspace ((unsigned char) value[i]));
946 i--)
947 value[i] = '\0';
948
949 /* remove quotes */
950 if ( ('"' == value[0]) &&
951 ('"' == value[strlen (value) - 1]) )
952 {
953 value[strlen (value) - 1] = '\0';
954 value++;
955 }
957 section,
958 tag,
959 value);
960 if (cfg->diagnostics)
961 {
963 section,
964 tag,
965 source_filename
966 ? source_filename
967 : "<input>",
968 nr);
969 }
970 GNUNET_free (tag);
971 continue;
972 }
973 /* parse error */
975 "Syntax error while deserializing in line %u\n",
976 nr);
978 break;
979 }
980 GNUNET_free (line_orig);
981 GNUNET_free (section);
982 GNUNET_assert ( (GNUNET_OK != ret) ||
983 (r_bytes == size) );
984 return ret;
985}
986
987
990 const char *filename)
991{
992 uint64_t fs64;
993 size_t fs;
994 char *fn;
995 char *mem;
996 int dirty;
998 ssize_t sret;
999
1001 LOG (GNUNET_ERROR_TYPE_DEBUG, "Asked to parse config file `%s'\n", fn);
1002 if (NULL == fn)
1003 return GNUNET_SYSERR;
1004
1005
1006 /* Check for cycles */
1007 {
1008 unsigned int lvl = cfg->current_nest_level;
1009 struct ConfigFile *cf = cfg->loaded_files_tail;
1010 struct ConfigFile *parent = NULL;
1011
1012
1013 for (; NULL != cf; parent = cf, cf = cf->prev)
1014 {
1015 /* Check parents based on level, skipping children of siblings. */
1016 if (cf->level >= lvl)
1017 continue;
1018 lvl = cf->level;
1019 if ( (NULL == cf->source_filename) || (NULL == filename))
1020 continue;
1021 if (0 == strcmp (cf->source_filename, filename))
1022 {
1023 if (NULL == parent)
1024 {
1026 "Forbidden direct cyclic configuration import (%s -> %s)\n",
1027 cf->source_filename,
1028 filename);
1029 }
1030 else
1032 "Forbidden indirect cyclic configuration import (%s -> ... -> %s -> %s)\n",
1033 cf->source_filename,
1034 parent->source_filename,
1035 filename);
1036 GNUNET_free (fn);
1037 return GNUNET_SYSERR;
1038 }
1039 }
1040
1041 }
1042
1043 /* Keep track of loaded files.*/
1044 {
1045 struct ConfigFile *cf = GNUNET_new (struct ConfigFile);
1046
1048 cf->source_filename = GNUNET_strdup (filename ? filename : "<input>");
1051 cf);
1052 }
1053
1054 dirty = cfg->dirty; /* back up value! */
1055 if (GNUNET_SYSERR ==
1057 &fs64,
1058 GNUNET_YES,
1059 GNUNET_YES))
1060 {
1062 "Error while determining the file size of `%s'\n",
1063 fn);
1064 GNUNET_free (fn);
1065 return GNUNET_SYSERR;
1066 }
1067 if (fs64 > SIZE_MAX)
1068 {
1069 GNUNET_break (0); /* File size is more than the heap size */
1070 GNUNET_free (fn);
1071 return GNUNET_SYSERR;
1072 }
1073 fs = fs64;
1074 mem = GNUNET_malloc (fs);
1075 sret = GNUNET_DISK_fn_read (fn, mem, fs);
1076 if ((sret < 0) || (fs != (size_t) sret))
1077 {
1079 "Error while reading file `%s'\n",
1080 fn);
1081 GNUNET_free (fn);
1082 GNUNET_free (mem);
1083 return GNUNET_SYSERR;
1084 }
1086 "Deserializing contents of file `%s'\n",
1087 fn);
1089 mem,
1090 fs,
1091 fn);
1092 if (GNUNET_SYSERR == ret)
1093 {
1095 _ ("Failed to parse configuration file `%s'\n"),
1096 fn);
1097 }
1098 GNUNET_free (fn);
1099 GNUNET_free (mem);
1100 /* restore dirty flag - anything we set in the meantime
1101 * came from disk */
1102 cfg->dirty = dirty;
1103 return ret;
1104}
1105
1106
1109{
1110 return cfg->dirty;
1111}
1112
1113
1121static bool
1122do_skip (const char *sec,
1123 const char *key)
1124{
1125 if (0 != strcasecmp ("PATHS",
1126 sec))
1127 return false;
1128 return ( (0 == strcasecmp ("DATADIR",
1129 key)) ||
1130 (0 == strcasecmp ("LIBDIR",
1131 key)) ||
1132 (0 == strcasecmp ("BINDIR",
1133 key)) ||
1134 (0 == strcasecmp ("PREFIX",
1135 key)) ||
1136 (0 == strcasecmp ("LOCALEDIR",
1137 key)) ||
1138 (0 == strcasecmp ("ICONDIR",
1139 key)) ||
1140 (0 == strcasecmp ("DOCDIR",
1141 key)) ||
1142 (0 == strcasecmp ("DEFAULTCONFIG",
1143 key)) ||
1144 (0 == strcasecmp ("LIBEXECDIR",
1145 key)) );
1146}
1147
1148
1149char *
1151 size_t *size)
1152{
1153 char *mem;
1154 char *cbuf;
1155 char *val;
1156 char *pos;
1157 size_t m_size;
1158 size_t c_size;
1159
1160 /* Pass1 : calculate the buffer size required */
1161 m_size = 0;
1162 for (struct ConfigSection *sec = cfg->sections;
1163 NULL != sec;
1164 sec = sec->next)
1165 {
1166 if (sec->inaccessible)
1167 continue;
1168 /* For each section we need to add 3 characters: {'[',']','\n'} */
1169 m_size += strlen (sec->name) + 3;
1170 for (struct ConfigEntry *ent = sec->entries;
1171 NULL != ent;
1172 ent = ent->next)
1173 {
1174 if (do_skip (sec->name,
1175 ent->key))
1176 continue;
1177 if (NULL != ent->val)
1178 {
1179 /* if val has any '\n' then they occupy +1 character as '\n'->'\\','n' */
1180 pos = ent->val;
1181 while (NULL != (pos = strstr (pos, "\n")))
1182 {
1183 m_size++;
1184 pos++;
1185 }
1186 /* For each key = value pair we need to add 4 characters (2
1187 spaces and 1 equal-to character and 1 new line) */
1188 m_size += strlen (ent->key) + strlen (ent->val) + 4;
1189 }
1190 }
1191 /* A new line after section end */
1192 m_size++;
1193 }
1194
1195 /* Pass2: Allocate memory and write the configuration to it */
1196 mem = GNUNET_malloc (m_size);
1197 c_size = 0;
1198 *size = c_size;
1199 for (struct ConfigSection *sec = cfg->sections;
1200 NULL != sec;
1201 sec = sec->next)
1202 {
1203 int len;
1204
1205 len = GNUNET_asprintf (&cbuf,
1206 "[%s]\n",
1207 sec->name);
1208 GNUNET_assert (0 < len);
1209 GNUNET_memcpy (mem + c_size,
1210 cbuf,
1211 len);
1212 c_size += len;
1213 GNUNET_free (cbuf);
1214 for (struct ConfigEntry *ent = sec->entries;
1215 NULL != ent;
1216 ent = ent->next)
1217 {
1218 if (do_skip (sec->name,
1219 ent->key))
1220 continue;
1221 if (NULL != ent->val)
1222 {
1223 val = GNUNET_malloc (strlen (ent->val) * 2 + 1);
1224 strcpy (val, ent->val);
1225 while (NULL != (pos = strstr (val, "\n")))
1226 {
1227 memmove (&pos[2], &pos[1], strlen (&pos[1]));
1228 pos[0] = '\\';
1229 pos[1] = 'n';
1230 }
1231 len = GNUNET_asprintf (&cbuf, "%s = %s\n", ent->key, val);
1232 GNUNET_free (val);
1233 GNUNET_memcpy (mem + c_size, cbuf, len);
1234 c_size += len;
1235 GNUNET_free (cbuf);
1236 }
1237 }
1238 GNUNET_memcpy (mem + c_size, "\n", 1);
1239 c_size++;
1240 }
1241 GNUNET_assert (c_size == m_size);
1242 *size = c_size;
1243 return mem;
1244}
1245
1246
1255static void
1257 const struct GNUNET_CONFIGURATION_Handle *cfg,
1258 struct GNUNET_Buffer *buf,
1260{
1262 ipk);
1263 const char *ipkname;
1264 switch (ipk)
1265 {
1267 ipkname = "IPK_DATADIR";
1268 break;
1270 ipkname = "IPK_BINDIR";
1271 break;
1273 ipkname = "IPK_LIBDIR";
1274 break;
1276 ipkname = "IPK_PREFIX";
1278 ipkname = "IPK_LOCALEDIR";
1279 break;
1281 ipkname = "IPK_ICONDIR";
1283 ipkname = "IPK_DOCDIR";
1284 break;
1286 ipkname = "IPK_LIBEXECDIR";
1287 break;
1289 ipkname = "IPK_SELF_PREFIX";
1290 break;
1291 default:
1292 ipkname = "??";
1293 break;
1294 }
1296 "# %s = %s\n",
1297 ipkname,
1298 v);
1299 GNUNET_free (v);
1300}
1301
1302
1303char *
1305 const struct GNUNET_CONFIGURATION_Handle *cfg)
1306{
1307 struct GNUNET_Buffer buf = { 0 };
1308
1310 "#\n# Configuration file diagnostics\n#\n");
1312 "# Entry point: %s\n",
1314 "<none>");
1316 "#\n# Files Loaded:\n");
1317
1318 for (struct ConfigFile *cfil = cfg->loaded_files_head;
1319 NULL != cfil;
1320 cfil = cfil->next)
1321 {
1323 "# ");
1324 for (unsigned int i = 0; i < cfil->level; i++)
1326 "+");
1327 if (0 != cfil->level)
1329 " ");
1330
1332 "%s",
1333 cfil->source_filename);
1334
1335 if (NULL != cfil->hint_restrict_section)
1337 " (%s secret section %s)",
1338 cfil->hint_inaccessible
1339 ? "inaccessible"
1340 : "loaded",
1341 cfil->hint_restrict_section);
1342
1344 "\n");
1345 }
1346
1348 "#\n# Installation paths:\n");
1349
1359
1360
1362 "#\n\n");
1363
1364 for (struct ConfigSection *sec = cfg->sections;
1365 NULL != sec;
1366 sec = sec->next)
1367 {
1368 if (sec->hint_secret_filename)
1370 "# secret section from %s\n# secret file stat %s\n",
1371 sec->hint_secret_filename,
1372 sec->hint_secret_stat);
1373 if (sec->hint_inlined_from_filename)
1374 {
1376 "# inlined from %s:%u\n",
1377 sec->hint_inlined_from_filename,
1378 sec->hint_inlined_from_line);
1379 }
1381 "[%s]\n\n",
1382 sec->name);
1383 if (sec->inaccessible)
1384 {
1386 "# <section contents inaccessible>\n\n\n");
1387 continue;
1388 }
1389 for (struct ConfigEntry *ent = sec->entries;
1390 NULL != ent;
1391 ent = ent->next)
1392 {
1393 if (do_skip (sec->name,
1394 ent->key))
1395 continue;
1396 if (NULL != ent->val)
1397 {
1398 char *pos;
1399 char *val = GNUNET_malloc (strlen (ent->val) * 2 + 1);
1400 strcpy (val, ent->val);
1401 while (NULL != (pos = strstr (val, "\n")))
1402 {
1403 memmove (&pos[2], &pos[1], strlen (&pos[1]));
1404 pos[0] = '\\';
1405 pos[1] = 'n';
1406 }
1407 if (NULL != ent->hint_filename)
1408 {
1410 "# %s:%u\n",
1411 ent->hint_filename,
1412 ent->hint_lineno);
1413 }
1415 "%s = %s\n",
1416 ent->key,
1417 val);
1418 GNUNET_free (val);
1419 }
1420 GNUNET_buffer_write_str (&buf, "\n");
1421 }
1422 GNUNET_buffer_write_str (&buf, "\n");
1423 }
1424 return GNUNET_buffer_reap_str (&buf);
1425}
1426
1427
1431 const char *filename)
1432{
1433 char *fn;
1434 char *cfg_buf;
1435 size_t size;
1436
1438 if (fn == NULL)
1439 return GNUNET_SYSERR;
1441 {
1442 GNUNET_free (fn);
1443 return GNUNET_SYSERR;
1444 }
1446 &size);
1447 {
1448 struct GNUNET_DISK_FileHandle *h;
1449
1458 if (NULL == h)
1459 {
1460 GNUNET_free (fn);
1461 GNUNET_free (cfg_buf);
1462 return GNUNET_SYSERR;
1463 }
1464 if (((ssize_t) size) !=
1466 cfg_buf,
1467 size))
1468 {
1470 "write",
1471 fn);
1473 (void) GNUNET_DISK_directory_remove (fn);
1474 GNUNET_free (fn);
1475 GNUNET_free (cfg_buf);
1476 cfg->dirty = GNUNET_SYSERR; /* last write failed */
1477 return GNUNET_SYSERR;
1478 }
1481 }
1482 GNUNET_free (fn);
1483 GNUNET_free (cfg_buf);
1484 cfg->dirty = GNUNET_NO; /* last write succeeded */
1485 return GNUNET_OK;
1486}
1487
1488
1489void
1491 const struct GNUNET_CONFIGURATION_Handle *cfg,
1493 void *iter_cls)
1494{
1495 for (struct ConfigSection *spos = cfg->sections;
1496 NULL != spos;
1497 spos = spos->next)
1498 for (struct ConfigEntry *epos = spos->entries;
1499 NULL != epos;
1500 epos = epos->next)
1501 if (NULL != epos->val)
1502 iter (iter_cls,
1503 spos->name,
1504 epos->key,
1505 epos->val);
1506}
1507
1508
1509void
1511 const struct GNUNET_CONFIGURATION_Handle *cfg,
1512 const char *section,
1514 void *iter_cls)
1515{
1516 struct ConfigSection *spos;
1517 struct ConfigEntry *epos;
1518
1519 spos = cfg->sections;
1520 while ((spos != NULL) && (0 != strcasecmp (spos->name, section)))
1521 spos = spos->next;
1522 if (NULL == spos)
1523 return;
1524 if (spos->inaccessible)
1525 {
1527 "Section '%s' is marked as inaccessible, because the configuration "
1528 " file that contains the section can't be read.\n",
1529 section);
1530 return;
1531 }
1532 for (epos = spos->entries; NULL != epos; epos = epos->next)
1533 if (NULL != epos->val)
1534 iter (iter_cls, spos->name, epos->key, epos->val);
1535}
1536
1537
1538void
1540 const struct GNUNET_CONFIGURATION_Handle *cfg,
1542 void *iter_cls)
1543{
1544 struct ConfigSection *spos;
1545 struct ConfigSection *next;
1546
1547 next = cfg->sections;
1548 while (next != NULL)
1549 {
1550 spos = next;
1551 next = spos->next;
1552 iter (iter_cls, spos->name);
1553 }
1554}
1555
1556
1557void
1559 const char *section)
1560{
1561 struct ConfigSection *spos;
1562 struct ConfigSection *prev;
1563 struct ConfigEntry *ent;
1564
1565 prev = NULL;
1566 spos = cfg->sections;
1567 while (NULL != spos)
1568 {
1569 if (0 == strcasecmp (section, spos->name))
1570 {
1571 if (NULL == prev)
1572 cfg->sections = spos->next;
1573 else
1574 prev->next = spos->next;
1575 while (NULL != (ent = spos->entries))
1576 {
1577 spos->entries = ent->next;
1578 GNUNET_free (ent->key);
1579 GNUNET_free (ent->val);
1581 GNUNET_free (ent);
1582 cfg->dirty = GNUNET_YES;
1583 }
1584 GNUNET_free (spos->name);
1588 GNUNET_free (spos);
1589 return;
1590 }
1591 prev = spos;
1592 spos = spos->next;
1593 }
1594}
1595
1596
1606static void
1607copy_entry (void *cls,
1608 const char *section,
1609 const char *option,
1610 const char *value)
1611{
1612 struct GNUNET_CONFIGURATION_Handle *dst = cls;
1613
1615 section,
1616 option,
1617 value);
1618}
1619
1620
1623 const struct GNUNET_CONFIGURATION_Handle *cfg)
1624{
1626
1629 &copy_entry,
1630 ret);
1631 return ret;
1632}
1633
1634
1645static void
1647 const char *section,
1648 const char *option,
1649 const char *value)
1650{
1651 struct DiffHandle *dh = cls;
1652 struct ConfigEntry *entNew;
1653
1654 entNew = find_entry (dh->cfg_default, section, option);
1655 if ((NULL != entNew) && (NULL != entNew->val) &&
1656 (0 == strcmp (entNew->val, value)))
1657 return;
1659 section,
1660 option,
1661 value);
1662}
1663
1664
1667 const struct GNUNET_CONFIGURATION_Handle *cfg_default,
1668 const struct GNUNET_CONFIGURATION_Handle *cfg_new)
1669{
1670 struct DiffHandle diffHandle;
1671
1672 GNUNET_break (cfg_default->pd == cfg_new->pd);
1673 diffHandle.cfgDiff = GNUNET_CONFIGURATION_create (cfg_new->pd);
1674 diffHandle.cfg_default = cfg_default;
1677 &diffHandle);
1678 return diffHandle.cfgDiff;
1679}
1680
1681
1685 const struct GNUNET_CONFIGURATION_Handle *cfg_new,
1686 const char *filename)
1687{
1688 int ret;
1689 struct GNUNET_CONFIGURATION_Handle *diff;
1690
1691 diff = GNUNET_CONFIGURATION_get_diff (cfg_default, cfg_new);
1694 return ret;
1695}
1696
1697
1698void
1701 const char *section,
1702 const char *option,
1703 const char *value)
1704{
1705 struct ConfigSection *sec;
1706 struct ConfigEntry *e;
1707 char *nv;
1708
1709 e = find_entry (cfg, section, option);
1710 if (NULL != e)
1711 {
1712 if (NULL == value)
1713 {
1714 GNUNET_free (e->val);
1715 e->val = NULL;
1716 }
1717 else
1718 {
1719 nv = GNUNET_strdup (value);
1720 GNUNET_free (e->val);
1721 e->val = nv;
1722 }
1723 return;
1724 }
1725 sec = find_section (cfg, section);
1726 if (sec == NULL)
1727 {
1728 sec = GNUNET_new (struct ConfigSection);
1729 sec->name = GNUNET_strdup (section);
1730 sec->next = cfg->sections;
1731 cfg->sections = sec;
1732 }
1733 e = GNUNET_new (struct ConfigEntry);
1734 e->key = GNUNET_strdup (option);
1735 e->val = GNUNET_strdup (value);
1736 e->next = sec->entries;
1737 sec->entries = e;
1738}
1739
1740
1741void
1743 const char *section,
1744 const char *option,
1745 unsigned long long number)
1746{
1747 char s[64];
1748
1749 GNUNET_snprintf (s,
1750 64,
1751 "%llu",
1752 number);
1754 section,
1755 option,
1756 s);
1757}
1758
1759
1762 const struct GNUNET_CONFIGURATION_Handle *cfg,
1763 const char *section,
1764 const char *option,
1765 unsigned long long *number)
1766{
1767 struct ConfigEntry *e;
1768 char dummy[2];
1769
1770 if (NULL == (e = find_entry (cfg,
1771 section,
1772 option)))
1773 return GNUNET_NO;
1774 if (NULL == e->val)
1775 return GNUNET_NO;
1776 if (1 != sscanf (e->val,
1777 "%llu%1s",
1778 number,
1779 dummy))
1780 return GNUNET_SYSERR;
1781 return GNUNET_OK;
1782}
1783
1784
1785void
1787 const char *section,
1788 const char *option,
1789 float number)
1790{
1791 char s[64];
1792
1793 // TODO FIXME note that this truncates the float
1794 // #9369
1795 const locale_t cl = newlocale (LC_NUMERIC_MASK, "C", (locale_t) 0);
1796 locale_t old_locale = uselocale (cl);
1797 GNUNET_snprintf (s,
1798 64,
1799 "%f",
1800 number);
1801 uselocale (old_locale);
1803 section,
1804 option,
1805 s);
1806}
1807
1808
1811 const struct GNUNET_CONFIGURATION_Handle *cfg,
1812 const char *section,
1813 const char *option,
1814 float *number)
1815{
1816 struct ConfigEntry *e;
1817 char dummy[2];
1818
1819 if (NULL == (e = find_entry (cfg,
1820 section,
1821 option)))
1822 return GNUNET_NO;
1823 if (NULL == e->val)
1824 return GNUNET_NO;
1825 // #9369
1826 const locale_t cl = newlocale (LC_NUMERIC_MASK, "C", (locale_t) 0);
1827 locale_t old_locale = uselocale (cl);
1828 if (1 != sscanf (e->val,
1829 "%f%1s",
1830 number,
1831 dummy))
1832 return GNUNET_SYSERR;
1833 uselocale (old_locale);
1834 return GNUNET_OK;
1835}
1836
1837
1840 const struct GNUNET_CONFIGURATION_Handle *cfg,
1841 const char *section,
1842 const char *option,
1843 struct GNUNET_TIME_Relative *time)
1844{
1845 struct ConfigEntry *e;
1846 int ret;
1847
1848 if (NULL == (e = find_entry (cfg,
1849 section,
1850 option)))
1851 return GNUNET_NO;
1852 if (NULL == e->val)
1853 return GNUNET_NO;
1855 time);
1856 if (GNUNET_OK != ret)
1858 section,
1859 option,
1860 _ ("Not a valid relative time specification"));
1861 return ret;
1862}
1863
1864
1867 const struct GNUNET_CONFIGURATION_Handle *cfg,
1868 const char *section,
1869 const char *option,
1870 unsigned long long *size)
1871{
1872 struct ConfigEntry *e;
1873
1874 if (NULL == (e = find_entry (cfg,
1875 section,
1876 option)))
1877 return GNUNET_NO;
1878 if (NULL == e->val)
1879 return GNUNET_NO;
1881 size);
1882}
1883
1884
1897 const struct GNUNET_CONFIGURATION_Handle *cfg,
1898 const char *section,
1899 const char *option,
1900 char **value)
1901{
1902 struct ConfigEntry *e;
1903
1904 if ( (NULL == (e = find_entry (cfg,
1905 section,
1906 option))) ||
1907 (NULL == e->val) )
1908 {
1909 *value = NULL;
1910 return GNUNET_NO;
1911 }
1912 *value = GNUNET_strdup (e->val);
1913 return GNUNET_OK;
1914}
1915
1916
1919 const struct GNUNET_CONFIGURATION_Handle *cfg,
1920 const char *section,
1921 const char *option,
1922 const char *const *choices,
1923 const char **value)
1924{
1925 struct ConfigEntry *e;
1926 unsigned int i;
1927
1928 if (NULL == (e = find_entry (cfg,
1929 section,
1930 option)))
1931 return GNUNET_NO;
1932 for (i = 0; NULL != choices[i]; i++)
1933 if (0 == strcasecmp (choices[i], e->val))
1934 break;
1935 if (NULL == choices[i])
1936 {
1938 _ ("Configuration value '%s' for '%s'"
1939 " in section '%s' is not in set of legal choices\n"),
1940 e->val,
1941 option,
1942 section);
1943 return GNUNET_SYSERR;
1944 }
1945 *value = choices[i];
1946 return GNUNET_OK;
1947}
1948
1949
1952 const char *section,
1953 const char *option,
1954 void *buf,
1955 size_t buf_size)
1956{
1957 char *enc;
1958 int res;
1959 size_t data_size;
1960
1961 if (GNUNET_OK !=
1962 (res =
1964 section,
1965 option,
1966 &enc)))
1967 return res;
1968 data_size = (strlen (enc) * 5) / 8;
1969 if (data_size != buf_size)
1970 {
1971 GNUNET_free (enc);
1972 return GNUNET_SYSERR;
1973 }
1974 if (GNUNET_OK !=
1976 strlen (enc),
1977 buf,
1978 buf_size))
1979 {
1980 GNUNET_free (enc);
1981 return GNUNET_SYSERR;
1982 }
1983 GNUNET_free (enc);
1984 return GNUNET_OK;
1985}
1986
1987
1990 const char *section,
1991 const char *option)
1992{
1993 struct ConfigEntry *e;
1994
1995 if ( (NULL == (e = find_entry (cfg,
1996 section,
1997 option))) ||
1998 (NULL == e->val) )
1999 return GNUNET_NO;
2000 return GNUNET_YES;
2001}
2002
2003
2019static char *
2021 char *orig,
2022 unsigned int depth)
2023{
2024 char *prefix;
2025 char *result;
2026 char *start;
2027 const char *post;
2028 const char *env;
2029 char *def;
2030 char *end;
2031 unsigned int lopen;
2032 char erased_char;
2033 char *erased_pos;
2034 size_t len;
2035
2036 if (NULL == orig)
2037 return NULL;
2038 if (depth > 128)
2039 {
2041 "Recursive expansion suspected, aborting $-expansion for term `%s'\n",
2042 orig);
2043 return orig;
2044 }
2046 "Asked to $-expand %s\n",
2047 orig);
2048 if ('$' != orig[0])
2049 {
2051 "Doesn't start with $ - not expanding\n");
2052 return orig;
2053 }
2054 erased_char = 0;
2055 erased_pos = NULL;
2056 if ('{' == orig[1])
2057 {
2058 start = &orig[2];
2059 lopen = 1;
2060 end = &orig[1];
2061 while (lopen > 0)
2062 {
2063 end++;
2064 switch (*end)
2065 {
2066 case '}':
2067 lopen--;
2068 break;
2069
2070 case '{':
2071 lopen++;
2072 break;
2073
2074 case '\0':
2076 "Missing closing `}' in option `%s'\n",
2077 orig);
2078 return orig;
2079
2080 default:
2081 break;
2082 }
2083 }
2084 erased_char = *end;
2085 erased_pos = end;
2086 *end = '\0';
2087 post = end + 1;
2088 def = strchr (orig, ':');
2089 if (NULL != def)
2090 {
2091 *def = '\0';
2092 def++;
2093 if (('-' == *def) || ('=' == *def))
2094 def++;
2095 def = GNUNET_strdup (def);
2096 }
2097 }
2098 else
2099 {
2100 int i;
2101
2102 start = &orig[1];
2103 def = NULL;
2104 i = 0;
2105 while ( (orig[i] != '/') &&
2106 (orig[i] != '\\') &&
2107 (orig[i] != '\0') &&
2108 (orig[i] != ' ') )
2109 i++;
2110 if (orig[i] == '\0')
2111 {
2112 post = "";
2113 }
2114 else
2115 {
2116 erased_char = orig[i];
2117 erased_pos = &orig[i];
2118 orig[i] = '\0';
2119 post = &orig[i + 1];
2120 }
2121 }
2123 "Split into `%s' and `%s' with default %s\n",
2124 start,
2125 post,
2126 def);
2127 if (GNUNET_OK !=
2129 "PATHS",
2130 start,
2131 &prefix))
2132 {
2133 if (NULL == (env = getenv (start)))
2134 {
2135 /* try default */
2136 def = expand_dollar (cfg,
2137 def,
2138 depth + 1);
2139 env = def;
2140 }
2141 if (NULL == env)
2142 {
2144 if (erased_pos)
2145 *erased_pos = erased_char;
2147 "Failed to expand `%s' in `%s' as it is neither found in [PATHS] nor defined as an environmental variable\n",
2148 start,
2149 orig);
2151 return orig;
2152 }
2154 }
2156 prefix);
2157 if ((erased_pos) && ('}' != erased_char))
2158 {
2159 len = strlen (prefix) + 1;
2160 prefix = GNUNET_realloc (prefix, len + 1);
2161 prefix[len - 1] = erased_char;
2162 prefix[len] = '\0';
2163 }
2164 result = GNUNET_malloc (strlen (prefix) + strlen (post) + 1);
2165 strcpy (result, prefix);
2166 strcat (result, post);
2167 GNUNET_free (def);
2169 GNUNET_free (orig);
2170 return result;
2171}
2172
2173
2174char *
2176 const struct GNUNET_CONFIGURATION_Handle *cfg,
2177 char *orig)
2178{
2179 char *dup;
2180 size_t i;
2181 size_t len;
2182
2183 for (i = 0; '\0' != orig[i]; i++)
2184 {
2185 if ('$' != orig[i])
2186 continue;
2187 dup = GNUNET_strdup (orig + i);
2188 dup = expand_dollar (cfg, dup, 0);
2189 GNUNET_assert (NULL != dup); /* make compiler happy */
2190 len = strlen (dup) + 1;
2191 orig = GNUNET_realloc (orig, i + len);
2192 GNUNET_memcpy (orig + i, dup, len);
2193 GNUNET_free (dup);
2194 }
2195 return orig;
2196}
2197
2198
2201 const struct GNUNET_CONFIGURATION_Handle *cfg,
2202 const char *section,
2203 const char *option,
2204 char **value)
2205{
2206 char *tmp;
2208
2210 section,
2211 option,
2212 &tmp);
2213 if (GNUNET_OK != ret)
2214 {
2216 "Failed to retrieve filename\n");
2217 *value = NULL;
2218 return ret;
2219 }
2221 tmp);
2223 GNUNET_free (tmp);
2224 if (*value == NULL)
2225 return GNUNET_SYSERR;
2226 return GNUNET_OK;
2227}
2228
2229
2232 const struct GNUNET_CONFIGURATION_Handle *cfg,
2233 const char *section,
2234 const char *option)
2235{
2236 static const char *yesno[] = {
2237 "YES",
2238 "NO",
2239 NULL
2240 };
2241 const char *val;
2243
2244 ret =
2246 section,
2247 option,
2248 yesno,
2249 &val);
2250 if (GNUNET_OK != ret)
2251 return ret;
2252 if (val == yesno[0])
2253 return GNUNET_YES;
2254 return GNUNET_NO;
2255}
2256
2257
2258int
2260 const struct GNUNET_CONFIGURATION_Handle *cfg,
2261 const char *section,
2262 const char *option,
2264 void *cb_cls)
2265{
2266 char *list;
2267 char *pos;
2268 char *end;
2269 char old;
2270 int ret;
2271
2272 if (GNUNET_OK !=
2274 section,
2275 option,
2276 &list))
2277 return 0;
2278 GNUNET_assert (list != NULL);
2279 ret = 0;
2280 pos = list;
2281 while (1)
2282 {
2283 while (pos[0] == ' ')
2284 pos++;
2285 if (strlen (pos) == 0)
2286 break;
2287 end = pos + 1;
2288 while ((end[0] != ' ') && (end[0] != '\0'))
2289 {
2290 if (end[0] == '\\')
2291 {
2292 switch (end[1])
2293 {
2294 case '\\':
2295 case ' ':
2296 memmove (end, &end[1], strlen (&end[1]) + 1);
2297
2298 case '\0':
2299 /* illegal, but just keep it */
2300 break;
2301
2302 default:
2303 /* illegal, but just ignore that there was a '/' */
2304 break;
2305 }
2306 }
2307 end++;
2308 }
2309 old = end[0];
2310 end[0] = '\0';
2311 if (strlen (pos) > 0)
2312 {
2313 ret++;
2314 if ( (NULL != cb) &&
2315 (GNUNET_OK != cb (cb_cls,
2316 pos)))
2317 {
2319 break;
2320 }
2321 }
2322 if (old == '\0')
2323 break;
2324 pos = end + 1;
2325 }
2326 GNUNET_free (list);
2327 return ret;
2328}
2329
2330
2337static char *
2338escape_name (const char *value)
2339{
2340 char *escaped;
2341 const char *rpos;
2342 char *wpos;
2343
2344 escaped = GNUNET_malloc (strlen (value) * 2 + 1);
2345 memset (escaped, 0, strlen (value) * 2 + 1);
2346 rpos = value;
2347 wpos = escaped;
2348 while (rpos[0] != '\0')
2349 {
2350 switch (rpos[0])
2351 {
2352 case '\\':
2353 case ' ':
2354 wpos[0] = '\\';
2355 wpos[1] = rpos[0];
2356 wpos += 2;
2357 break;
2358
2359 default:
2360 wpos[0] = rpos[0];
2361 wpos++;
2362 }
2363 rpos++;
2364 }
2365 return escaped;
2366}
2367
2368
2376static enum GNUNET_GenericReturnValue
2377test_match (void *cls, const char *fn)
2378{
2379 const char *of = cls;
2380
2381 return (0 == strcmp (of, fn))
2383 : GNUNET_OK;
2384}
2385
2386
2390 const char *section,
2391 const char *option,
2392 const char *value)
2393{
2394 char *escaped;
2395 char *old;
2396 char *nw;
2397
2398 if (GNUNET_SYSERR ==
2400 section,
2401 option,
2402 &test_match,
2403 (void *) value))
2404 return GNUNET_NO; /* already exists */
2405 if (GNUNET_OK !=
2406 GNUNET_CONFIGURATION_get_value_string (cfg, section, option, &old))
2407 old = GNUNET_strdup ("");
2408 escaped = escape_name (value);
2409 nw = GNUNET_malloc (strlen (old) + strlen (escaped) + 2);
2410 strcpy (nw, old);
2411 if (strlen (old) > 0)
2412 strcat (nw, " ");
2413 strcat (nw, escaped);
2415 section,
2416 option,
2417 nw);
2418 GNUNET_free (old);
2419 GNUNET_free (nw);
2420 GNUNET_free (escaped);
2421 return GNUNET_OK;
2422}
2423
2424
2428 const char *section,
2429 const char *option,
2430 const char *value)
2431{
2432 char *list;
2433 char *pos;
2434 char *end;
2435 char *match;
2436 char old;
2437
2438 if (GNUNET_OK !=
2440 section,
2441 option,
2442 &list))
2443 return GNUNET_NO;
2444 match = escape_name (value);
2445 pos = list;
2446 while (1)
2447 {
2448 while (pos[0] == ' ')
2449 pos++;
2450 if (strlen (pos) == 0)
2451 break;
2452 end = pos + 1;
2453 while ((end[0] != ' ') && (end[0] != '\0'))
2454 {
2455 if (end[0] == '\\')
2456 {
2457 switch (end[1])
2458 {
2459 case '\\':
2460 case ' ':
2461 end++;
2462 break;
2463
2464 case '\0':
2465 /* illegal, but just keep it */
2466 break;
2467
2468 default:
2469 /* illegal, but just ignore that there was a '/' */
2470 break;
2471 }
2472 }
2473 end++;
2474 }
2475 old = end[0];
2476 end[0] = '\0';
2477 if (0 == strcmp (pos, match))
2478 {
2479 if (old != '\0')
2480 memmove (pos,
2481 &end[1],
2482 strlen (&end[1]) + 1);
2483 else
2484 {
2485 if (pos != list)
2486 pos[-1] = '\0';
2487 else
2488 pos[0] = '\0';
2489 }
2491 section,
2492 option,
2493 list);
2494 GNUNET_free (list);
2495 GNUNET_free (match);
2496 return GNUNET_OK;
2497 }
2498 if (old == '\0')
2499 break;
2500 end[0] = old;
2501 pos = end + 1;
2502 }
2503 GNUNET_free (list);
2504 GNUNET_free (match);
2505 return GNUNET_NO;
2506}
2507
2508
2512 const char *defaults_d)
2513{
2514 struct CollectFilesContext files_context = {
2515 .files = NULL,
2516 .files_length = 0,
2517 };
2518 enum GNUNET_GenericReturnValue fun_ret;
2519
2520 if (GNUNET_SYSERR ==
2521 GNUNET_DISK_directory_scan (defaults_d,
2523 &files_context))
2524 return GNUNET_SYSERR; /* no configuration at all found */
2525 qsort (files_context.files,
2526 files_context.files_length,
2527 sizeof (char *),
2528 pstrcmp);
2529 for (unsigned int i = 0; i < files_context.files_length; i++)
2530 {
2531 char *ext;
2532 const char *filename = files_context.files[i];
2533
2534 /* Examine file extension */
2535 ext = strrchr (filename, '.');
2536 if ((NULL == ext) || (0 != strcmp (ext, ".conf")))
2537 {
2539 "Skipping file `%s'\n",
2540 filename);
2541 fun_ret = GNUNET_OK;
2542 goto cleanup;
2543 }
2545 filename);
2546 if (fun_ret != GNUNET_OK)
2547 break;
2548 }
2549cleanup:
2550 if (files_context.files_length > 0)
2551 {
2552 for (size_t i = 0; i < files_context.files_length; i++)
2553 GNUNET_free (files_context.files[i]);
2554 GNUNET_array_grow (files_context.files,
2555 files_context.files_length,
2556 0);
2557 }
2558 return fun_ret;
2559}
2560
2561
2562char *
2564 const struct GNUNET_OS_ProjectData *pd)
2565{
2566 char *cfg_fn;
2567 const char *xdg = getenv ("XDG_CONFIG_HOME");
2568
2569 if (NULL != xdg)
2570 GNUNET_asprintf (&cfg_fn,
2571 "%s%s%s",
2572 xdg,
2574 pd->config_file);
2575 else
2576 cfg_fn = GNUNET_strdup (pd->user_config_file);
2577
2578 if (GNUNET_OK == GNUNET_DISK_file_test_read (cfg_fn))
2579 return cfg_fn;
2580 GNUNET_free (cfg_fn);
2581
2582 /* Fall back to /etc/ for the default configuration.
2583 Should be okay to use forward slashes here. */
2584
2585 GNUNET_asprintf (&cfg_fn,
2586 "/etc/%s",
2587 pd->config_file);
2588 if (GNUNET_OK ==
2590 return cfg_fn;
2591 GNUNET_free (cfg_fn);
2592
2593 GNUNET_asprintf (&cfg_fn,
2594 "/etc/%s/%s",
2595 pd->project_dirname,
2596 pd->config_file);
2597 if (GNUNET_OK ==
2599 return cfg_fn;
2600
2601 GNUNET_free (cfg_fn);
2602 return NULL;
2603}
2604
2605
2609 const char *filename)
2610{
2611 char *baseconfig;
2612 const char *base_config_varname;
2613
2614 if (cfg->load_called)
2615 {
2616 /* FIXME: Make this a GNUNET_assert later */
2617 GNUNET_break (0);
2619 }
2620 cfg->load_called = true;
2621 if (NULL != filename)
2622 {
2625 }
2626
2627 base_config_varname = cfg->pd->base_config_varname;
2628
2629 if ((NULL != base_config_varname)
2630 && (NULL != (baseconfig = getenv (base_config_varname))))
2631 {
2632 baseconfig = GNUNET_strdup (baseconfig);
2633 }
2634 else
2635 {
2636 char *ipath;
2637
2640 if (NULL == ipath)
2641 {
2642 GNUNET_break (0);
2643 return GNUNET_SYSERR;
2644 }
2645 GNUNET_asprintf (&baseconfig,
2646 "%s%s",
2647 ipath,
2648 "config.d");
2649 GNUNET_free (ipath);
2650 }
2651
2652 {
2653 char *dname = GNUNET_STRINGS_filename_expand (baseconfig);
2654
2655 GNUNET_free (baseconfig);
2656
2657 if ((GNUNET_YES ==
2659 GNUNET_YES)) &&
2660 (GNUNET_SYSERR ==
2662 dname)))
2663 {
2665 "Failed to load base configuration from '%s'\n",
2666 filename);
2667 GNUNET_free (dname);
2668 return GNUNET_SYSERR; /* no configuration at all found */
2669 }
2670 GNUNET_free (dname);
2671 }
2672 if ((NULL != filename) &&
2673 (GNUNET_OK !=
2675 filename)))
2676 {
2677 /* specified configuration not found */
2679 "Failed to load configuration from file '%s'\n",
2680 filename);
2681 return GNUNET_SYSERR;
2682 }
2683 if (((GNUNET_YES !=
2685 "PATHS",
2686 "DEFAULTCONFIG"))) &&
2687 (filename != NULL))
2689 "PATHS",
2690 "DEFAULTCONFIG",
2691 filename);
2692 return GNUNET_OK;
2693}
2694
2695
2704static void
2706 const char *section,
2707 const char *option,
2708 const char *value)
2709{
2710 const struct GNUNET_CONFIGURATION_Handle *cfg = cls;
2711
2712 char *value_fn;
2713 char *fn;
2714
2717 section,
2718 option,
2719 &value_fn));
2720 fn = GNUNET_STRINGS_filename_expand (value_fn);
2721 if (NULL == fn)
2722 fn = value_fn;
2723 else
2724 GNUNET_free (value_fn);
2725 fprintf (stdout,
2726 "%s = %s\n",
2727 option,
2728 fn);
2729 GNUNET_free (fn);
2730}
2731
2732
2741static void
2742print_option (void *cls,
2743 const char *section,
2744 const char *option,
2745 const char *value)
2746{
2747 (void) cls;
2748 (void) section;
2749
2750 fprintf (stdout,
2751 "%s = %s\n",
2752 option,
2753 value);
2754}
2755
2756
2763static void
2765 const char *section)
2766{
2767 (void) cls;
2768 fprintf (stdout,
2769 "%s\n",
2770 section);
2771}
2772
2773
2774void
2776 void *cls,
2777 char *const *args,
2778 const char *cfgfile,
2779 const struct GNUNET_CONFIGURATION_Handle *cfg)
2780{
2781 struct GNUNET_CONFIGURATION_ConfigSettings *cs = cls;
2782 struct GNUNET_CONFIGURATION_Handle *out = NULL;
2783 struct GNUNET_CONFIGURATION_Handle *ncfg = NULL;
2784
2785 (void) args;
2786 if (cs->diagnostics)
2787 {
2788 /* Re-parse the configuration with diagnostics enabled. */
2791 if (GNUNET_OK !=
2793 cfgfile))
2794 {
2795 fprintf (stderr,
2796 _ ("Failed to load config file `%s'"),
2797 cfgfile);
2798 return;
2799 }
2800 cfg = ncfg;
2801 }
2802
2803 if (cs->full)
2804 cs->rewrite = GNUNET_YES;
2805 if (cs->list_sections)
2806 {
2807 fprintf (stderr,
2808 _ ("The following sections are available:\n"));
2811 NULL);
2812 return;
2813 }
2814 if ( (! cs->rewrite) &&
2815 (NULL == cs->section) )
2816 {
2817 char *serialization;
2818
2819 if (! cs->diagnostics)
2820 {
2821 fprintf (stderr,
2822 _ ("%s, %s or %s argument is required\n"),
2823 "--section",
2824 "--list-sections",
2825 "--diagnostics");
2827 return;
2828 }
2830 fprintf (stdout,
2831 "%s",
2832 serialization);
2833 GNUNET_free (serialization);
2834 }
2835 else if ( (NULL != cs->section) &&
2836 (NULL == cs->value) )
2837 {
2838 if (NULL == cs->option)
2839 {
2841 cfg,
2842 cs->section,
2843 cs->is_filename
2845 : &print_option,
2846 (void *) cfg);
2847 }
2848 else
2849 {
2850 char *value;
2851
2852 if (cs->is_filename)
2853 {
2854 if (GNUNET_OK !=
2856 cs->section,
2857 cs->option,
2858 &value))
2859 {
2861 cs->section,
2862 cs->option);
2864 return;
2865 }
2866 }
2867 else
2868 {
2869 if (GNUNET_OK !=
2871 cs->section,
2872 cs->option,
2873 &value))
2874 {
2876 cs->section,
2877 cs->option);
2879 return;
2880 }
2881 }
2882 fprintf (stdout,
2883 "%s\n",
2884 value);
2886 }
2887 }
2888 else if (NULL != cs->section)
2889 {
2890 if (NULL == cs->option)
2891 {
2892 fprintf (stderr,
2893 _ ("--option argument required to set value\n"));
2895 return;
2896 }
2899 cs->section,
2900 cs->option,
2901 cs->value);
2902 cs->rewrite = GNUNET_YES;
2903 }
2904 if (cs->rewrite)
2905 {
2906 char *cfg_fn = NULL;
2907
2908 if (NULL == out)
2910
2911 if (NULL == cfgfile)
2912 {
2913 const char *xdg = getenv ("XDG_CONFIG_HOME");
2914
2915 if (NULL != xdg)
2916 GNUNET_asprintf (&cfg_fn,
2917 "%s%s%s",
2918 xdg,
2920 cfg->pd->config_file);
2921 else
2922 cfg_fn = GNUNET_strdup (cfg->pd->user_config_file);
2923 cfgfile = cfg_fn;
2924 }
2925
2926 if (! cs->full)
2927 {
2928 struct GNUNET_CONFIGURATION_Handle *def;
2929
2931 if (GNUNET_OK !=
2933 NULL))
2934 {
2935 fprintf (stderr,
2936 _ ("failed to load configuration defaults"));
2937 cs->global_ret = 1;
2940 GNUNET_free (cfg_fn);
2941 return;
2942 }
2943 if (GNUNET_OK !=
2945 out,
2946 cfgfile))
2947 cs->global_ret = 2;
2949 }
2950 else
2951 {
2952 if (GNUNET_OK !=
2954 cfgfile))
2955 cs->global_ret = 2;
2956 }
2957 GNUNET_free (cfg_fn);
2958 }
2959 if (NULL != out)
2961 if (NULL != ncfg)
2963}
2964
2965
2966void
2969{
2970 GNUNET_free (cs->option);
2971 GNUNET_free (cs->section);
2972 GNUNET_free (cs->value);
2973}
2974
2975
2976const struct GNUNET_OS_ProjectData *
2978 const struct GNUNET_CONFIGURATION_Handle *cfg)
2979{
2980 return cfg->pd;
2981}
2982
2983
2984/* end of configuration.c */
struct GNUNET_MQ_Envelope * env
Definition: 005.c:1
static bool do_skip(const char *sec, const char *key)
Should we skip this configuration entry when serializing?
static void print_filename_option(void *cls, const char *section, const char *option, const char *value)
Print each option in a given section as a filename.
static struct ConfigEntry * find_entry(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *key)
Find an entry from a configuration.
static enum GNUNET_GenericReturnValue handle_inline(struct GNUNET_CONFIGURATION_Handle *cfg, const char *path_or_glob, bool path_is_glob, const char *restrict_section, const char *source_filename, unsigned int source_lineno)
Handle an inline directive.
static void print_section_name(void *cls, const char *section)
Print out given section name.
static char * escape_name(const char *value)
FIXME.
static void compare_entries(void *cls, const char *section, const char *option, const char *value)
A callback function, compares entries from two configurations (default against a new configuration) a...
static enum GNUNET_GenericReturnValue test_match(void *cls, const char *fn)
FIXME.
static struct ConfigSection * find_section(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section)
Find a section entry from a configuration.
static int pstrcmp(const void *a, const void *b)
static char * expand_dollar(const struct GNUNET_CONFIGURATION_Handle *cfg, char *orig, unsigned int depth)
Expand an expression of the form "$FOO/BAR" to "DIRECTORY/BAR" where either in the "PATHS" section or...
static enum GNUNET_GenericReturnValue collect_files_cb(void *cls, const char *filename)
Function called with a filename.
#define LOG(kind,...)
Definition: configuration.c:30
static void copy_entry(void *cls, const char *section, const char *option, const char *value)
Copy a configuration value to the given target configuration.
static void print_option(void *cls, const char *section, const char *option, const char *value)
Print each option in a given section.
static void dump_os_ipk(const struct GNUNET_CONFIGURATION_Handle *cfg, struct GNUNET_Buffer *buf, enum GNUNET_OS_InstallationPathKind ipk)
Dump an os installation path to a buffer.
static void set_entry_hint(struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, const char *hint_filename, unsigned int hint_line)
Set a configuration hint.
char * getenv()
static struct GNUNET_ARM_Handle * h
Connection with ARM.
Definition: gnunet-arm.c:98
static int start
Set if we are to start default services (including ARM).
Definition: gnunet-arm.c:38
static int list
Set if we should print a list of currently running services.
Definition: gnunet-arm.c:68
static int ret
Final status code.
Definition: gnunet-arm.c:93
static struct GNUNET_CONFIGURATION_Handle * cfg
Our configuration.
Definition: gnunet-arm.c:108
static int end
Set if we are to shutdown all services (including ARM).
Definition: gnunet-arm.c:33
static int prefix
If printing the value of PREFIX has been requested.
Definition: gnunet-config.c:65
static char * line
Desired phone line (string to be converted to a hash).
struct GNUNET_HashCode key
The key used in the DHT.
static void cleanup(void *cls)
Disconnect and shutdown.
Definition: gnunet-did.c:131
static char * filename
static struct GNUNET_FS_Handle * fs
Handle to FS service.
Definition: gnunet-fs.c:35
static OpusEncoder * enc
OPUS encoder.
static struct in_addr dummy
Target "dummy" address of the packet we pretend to respond to.
static char * res
Currently read line or NULL on EOF.
static char * value
Value of the record to add/remove.
static size_t data_size
Number of bytes in data.
static int result
Global testing status.
static struct GNUNET_OS_Process * p
Helper process we started.
Definition: gnunet-uri.c:38
Configuration API.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_data(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, void *buf, size_t buf_size)
Get Crockford32-encoded fixed-size binary data from a configuration.
struct GNUNET_CONFIGURATION_Handle * GNUNET_CONFIGURATION_create(const struct GNUNET_OS_ProjectData *pd)
Create a new configuration object.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_is_dirty(const struct GNUNET_CONFIGURATION_Handle *cfg)
Test if there are configuration options that were changed since the last save.
void GNUNET_CONFIGURATION_set_value_string(struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, const char *value)
Set a configuration value that should be a string.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_append_value_filename(struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, const char *value)
Append a filename to a configuration value that represents a list of filenames.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_filename(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, char **value)
Get a configuration value that should be the name of a file or directory.
void GNUNET_CONFIGURATION_remove_section(struct GNUNET_CONFIGURATION_Handle *cfg, const char *section)
Remove the given section and all options in it.
enum GNUNET_GenericReturnValue(* GNUNET_CONFIGURATION_Callback)(void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg)
Signature of a function to be run with a configuration.
struct GNUNET_CONFIGURATION_Handle * GNUNET_CONFIGURATION_dup(const struct GNUNET_CONFIGURATION_Handle *cfg)
Duplicate an existing configuration object.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_number(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, unsigned long long *number)
Get a configuration value that should be a number.
void GNUNET_CONFIGURATION_iterate_sections(const struct GNUNET_CONFIGURATION_Handle *cfg, GNUNET_CONFIGURATION_SectionIterator iter, void *iter_cls)
Iterate over all sections in the configuration.
void GNUNET_CONFIGURATION_destroy(struct GNUNET_CONFIGURATION_Handle *cfg)
Destroy configuration object.
void GNUNET_CONFIGURATION_config_settings_free(struct GNUNET_CONFIGURATION_ConfigSettings *cs)
Free resources associated with cs.
void GNUNET_CONFIGURATION_iterate(const struct GNUNET_CONFIGURATION_Handle *cfg, GNUNET_CONFIGURATION_Iterator iter, void *iter_cls)
Iterate over all options in the configuration.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_remove_value_filename(struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, const char *value)
Remove a filename from a configuration value that represents a list of filenames.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_parse_and_run(const struct GNUNET_OS_ProjectData *pd, const char *filename, GNUNET_CONFIGURATION_Callback cb, void *cb_cls)
Parse a configuration file filename and run the function cb with the resulting configuration object.
void GNUNET_CONFIGURATION_config_tool_run(void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg)
Main task to run to perform operations typical for gnunet-config as per the configuration settings gi...
void(* GNUNET_CONFIGURATION_SectionIterator)(void *cls, const char *section)
Function to iterate over section.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_deserialize(struct GNUNET_CONFIGURATION_Handle *cfg, const char *mem, size_t size, const char *source_filename)
De-serializes configuration.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_size(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, unsigned long long *size)
Get a configuration value that should be a size in bytes.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_yesno(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option)
Get a configuration value that should be in a set of "YES" or "NO".
char * GNUNET_CONFIGURATION_serialize(const struct GNUNET_CONFIGURATION_Handle *cfg, size_t *size)
Serializes the given configuration.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_time(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, struct GNUNET_TIME_Relative *time)
Get a configuration value that should be a relative time.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_string(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, char **value)
Get a configuration value that should be a string.
void GNUNET_CONFIGURATION_set_value_number(struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, unsigned long long number)
Set a configuration value that should be a number.
char * GNUNET_CONFIGURATION_default_filename(const struct GNUNET_OS_ProjectData *pd)
Return the filename of the default configuration filename that is used when no explicit configuration...
char * GNUNET_CONFIGURATION_expand_dollar(const struct GNUNET_CONFIGURATION_Handle *cfg, char *orig)
Expand an expression of the form "$FOO/BAR" to "DIRECTORY/BAR" where either in the "PATHS" section or...
void GNUNET_CONFIGURATION_set_value_float(struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, float number)
Set a configuration value that should be a float.
const struct GNUNET_OS_ProjectData * GNUNET_CONFIGURATION_get_project_data(const struct GNUNET_CONFIGURATION_Handle *cfg)
Return the project data associated with this configuration.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_load(struct GNUNET_CONFIGURATION_Handle *cfg, const char *filename)
Load configuration.
struct GNUNET_CONFIGURATION_Handle * GNUNET_CONFIGURATION_get_diff(const struct GNUNET_CONFIGURATION_Handle *cfg_default, const struct GNUNET_CONFIGURATION_Handle *cfg_new)
Compute configuration with only entries that have been changed.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_parse(struct GNUNET_CONFIGURATION_Handle *cfg, const char *filename)
Parse a configuration file, add all of the options in the file to the configuration environment.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_float(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, float *number)
Get a configuration value that should be a floating point number.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_load_from(struct GNUNET_CONFIGURATION_Handle *cfg, const char *defaults_d)
Load default configuration.
int GNUNET_CONFIGURATION_iterate_value_filenames(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, GNUNET_FileNameCallback cb, void *cb_cls)
Iterate over the set of filenames stored in a configuration value.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_have_value(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option)
Test if we have a value for a particular option.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_choice(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, const char *const *choices, const char **value)
Get a configuration value that should be in a set of predefined strings.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_write(struct GNUNET_CONFIGURATION_Handle *cfg, const char *filename)
Write configuration file.
void(* GNUNET_CONFIGURATION_Iterator)(void *cls, const char *section, const char *option, const char *value)
Function to iterate over options.
void GNUNET_CONFIGURATION_iterate_section_values(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, GNUNET_CONFIGURATION_Iterator iter, void *iter_cls)
Iterate over values of a section in the configuration.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_write_diffs(const struct GNUNET_CONFIGURATION_Handle *cfg_default, const struct GNUNET_CONFIGURATION_Handle *cfg_new, const char *filename)
Write only configuration entries that have been changed to configuration file.
char * GNUNET_CONFIGURATION_serialize_diagnostics(const struct GNUNET_CONFIGURATION_Handle *cfg)
Serializes the given configuration with diagnostics information.
void GNUNET_CONFIGURATION_enable_diagnostics(struct GNUNET_CONFIGURATION_Handle *cfg)
Enable extra diagnostics.
struct GNUNET_DISK_FileHandle * GNUNET_DISK_file_open(const char *fn, enum GNUNET_DISK_OpenFlags flags, enum GNUNET_DISK_AccessPermissions perm)
Open a file.
Definition: disk.c:1234
int GNUNET_DISK_glob(const char *glob_pattern, GNUNET_FileNameCallback callback, void *callback_cls)
Find all files matching a glob pattern.
Definition: disk.c:1003
ssize_t GNUNET_DISK_file_write(const struct GNUNET_DISK_FileHandle *h, const void *buffer, size_t n)
Write a buffer to a file.
Definition: disk.c:697
enum GNUNET_GenericReturnValue GNUNET_DISK_file_test_read(const char *fil)
Check that fil corresponds to a filename and the file has read permissions.
Definition: disk.c:527
enum GNUNET_GenericReturnValue GNUNET_DISK_file_size(const char *filename, uint64_t *size, int include_symbolic_links, int single_file_mode)
Get the size of the file (or directory) of the given file (in bytes).
Definition: disk.c:222
enum GNUNET_GenericReturnValue GNUNET_DISK_directory_remove(const char *filename)
Remove all files in a directory (rm -rf).
Definition: disk.c:1080
enum GNUNET_GenericReturnValue GNUNET_DISK_directory_test(const char *fil, int is_readable)
Test if fil is a directory and listable.
Definition: disk.c:441
enum GNUNET_GenericReturnValue GNUNET_DISK_file_close(struct GNUNET_DISK_FileHandle *h)
Close an open file.
Definition: disk.c:1308
enum GNUNET_GenericReturnValue GNUNET_DISK_directory_create_for_file(const char *filename)
Create the directory structure for storing a file.
Definition: disk.c:620
ssize_t GNUNET_DISK_fn_read(const char *fn, void *result, size_t len)
Read the contents of a binary file into a buffer.
Definition: disk.c:674
int GNUNET_DISK_directory_scan(const char *dir_name, GNUNET_FileNameCallback callback, void *callback_cls)
Scan a directory for files.
Definition: disk.c:826
@ GNUNET_DISK_OPEN_WRITE
Open the file for writing.
@ GNUNET_DISK_OPEN_TRUNCATE
Truncate file if it exists.
@ GNUNET_DISK_OPEN_CREATE
Create file if it doesn't exist.
@ GNUNET_DISK_PERM_USER_READ
Owner can read.
@ GNUNET_DISK_PERM_GROUP_READ
Group can read.
@ GNUNET_DISK_PERM_GROUP_WRITE
Group can write.
@ GNUNET_DISK_PERM_USER_WRITE
Owner can write.
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
#define GNUNET_CONTAINER_DLL_insert_tail(head, tail, element)
Insert an element at the tail of a DLL.
enum GNUNET_GenericReturnValue(* GNUNET_FileNameCallback)(void *cls, const char *filename)
Function called with a filename.
#define GNUNET_log(kind,...)
char * GNUNET_buffer_reap_str(struct GNUNET_Buffer *buf)
Clear the buffer and return the string it contained.
Definition: buffer.c:123
void GNUNET_buffer_write_fstr(struct GNUNET_Buffer *buf, const char *fmt,...) __attribute__((format(printf
Write a 0-terminated formatted string to a buffer, excluding the 0-terminator.
void GNUNET_buffer_write_str(struct GNUNET_Buffer *buf, const char *str)
Write a 0-terminated string to a buffer, excluding the 0-terminator.
Definition: buffer.c:103
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
GNUNET_GenericReturnValue
Named constants for return values.
@ GNUNET_OK
@ GNUNET_YES
@ GNUNET_NO
@ GNUNET_SYSERR
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur.
void GNUNET_log_config_invalid(enum GNUNET_ErrorType kind, const char *section, const char *option, const char *required)
Log error message about invalid configuration option value.
void GNUNET_log_config_missing(enum GNUNET_ErrorType kind, const char *section, const char *option)
Log error message about missing configuration option.
#define GNUNET_log_strerror_file(level, cmd, filename)
Log an error message at log-level 'level' that indicates a failure of the command 'cmd' with the mess...
@ GNUNET_ERROR_TYPE_WARNING
@ GNUNET_ERROR_TYPE_ERROR
@ GNUNET_ERROR_TYPE_DEBUG
@ GNUNET_ERROR_TYPE_INFO
int int GNUNET_asprintf(char **buf, const char *format,...) __attribute__((format(printf
Like asprintf, just portable.
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
#define GNUNET_array_grow(arr, size, tsize)
Grow a well-typed (!) array.
#define GNUNET_strndup(a, length)
Wrapper around GNUNET_xstrndup_.
int GNUNET_snprintf(char *buf, size_t size, const char *format,...) __attribute__((format(printf
Like snprintf, just aborts if the buffer is of insufficient size.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
#define GNUNET_malloc(size)
Wrapper around malloc.
#define GNUNET_realloc(ptr, size)
Wrapper around realloc.
#define GNUNET_array_append(arr, len, element)
Append an element to an array (growing the array by one).
#define GNUNET_free(ptr)
Wrapper around free.
char * GNUNET_OS_installation_get_path(const struct GNUNET_OS_ProjectData *pd, enum GNUNET_OS_InstallationPathKind dirkind)
Get the path to a specific GNUnet installation directory or, with GNUNET_OS_IPK_SELF_PREFIX,...
GNUNET_OS_InstallationPathKind
Possible installation paths to request.
@ GNUNET_OS_IPK_SELF_PREFIX
Return the installation directory of this application, not the one of the overall GNUnet installation...
@ GNUNET_OS_IPK_ICONDIR
Return the prefix of the path with application icons (share/icons/).
@ GNUNET_OS_IPK_DATADIR
Return the directory where data is installed (share/gnunet/)
@ GNUNET_OS_IPK_DOCDIR
Return the prefix of the path with documentation files, including the license (share/doc/gnunet/).
@ GNUNET_OS_IPK_LOCALEDIR
Return the directory where translations are installed (share/locale/)
@ GNUNET_OS_IPK_LIBDIR
Return the directory where libraries are installed.
@ GNUNET_OS_IPK_PREFIX
Return the "PREFIX" directory given to configure.
@ GNUNET_OS_IPK_BINDIR
Return the directory where the program binaries are installed.
@ GNUNET_OS_IPK_LIBEXECDIR
Return the directory where helper binaries are installed (lib/gnunet/libexec/)
char * GNUNET_STRINGS_filename_expand(const char *fil)
Complete filename (a la shell) from abbrevition.
Definition: strings.c:504
enum GNUNET_GenericReturnValue GNUNET_STRINGS_string_to_data(const char *enc, size_t enclen, void *out, size_t out_size)
Convert CrockfordBase32 encoding back to data.
Definition: strings.c:812
enum GNUNET_GenericReturnValue GNUNET_STRINGS_fancy_time_to_relative(const char *fancy_time, struct GNUNET_TIME_Relative *rtime)
Convert a given fancy human-readable time to our internal representation.
Definition: strings.c:259
enum GNUNET_GenericReturnValue GNUNET_STRINGS_fancy_size_to_bytes(const char *fancy_size, unsigned long long *size)
Convert a given fancy human-readable size to bytes.
Definition: strings.c:235
static unsigned int size
Size of the "table".
Definition: peer.c:68
#define DIR_SEPARATOR_STR
Definition: platform.h:167
#define _(String)
GNU gettext support macro.
Definition: platform.h:179
#define SIZE_MAX
Definition: platform.h:209
#define EXIT_INVALIDARGUMENT
Definition: platform.h:254
#define EXIT_NOTCONFIGURED
Definition: platform.h:270
uint32_t number
Closure to collect_files_cb.
char ** files
Collected files from globbing.
unsigned int files_length
Size of the files array.
configuration entry
Definition: configuration.c:39
char * hint_filename
Diagnostics information for the filename.
Definition: configuration.c:58
struct ConfigEntry * next
This is a linked list.
Definition: configuration.c:43
char * key
key for this entry
Definition: configuration.c:48
unsigned int hint_lineno
Diagnostics information for the line number.
Definition: configuration.c:63
char * val
current, committed value
Definition: configuration.c:53
char * hint_restrict_section
Was this configuration file parsed via @inline-secret@?
struct ConfigFile * next
char * source_filename
Source filename.
bool hint_inaccessible
Was this configuration file inaccessible?
struct ConfigFile * prev
unsigned int level
Level in the tree of loaded config files.
configuration section
Definition: configuration.c:71
char * name
name of the section
Definition: configuration.c:85
char * hint_inlined_from_filename
For secret sections: Where was this inlined from?
struct ConfigEntry * entries
entries in the section
Definition: configuration.c:80
bool inaccessible
Is the configuration section marked as inaccessible?
Definition: configuration.c:93
struct ConfigSection * next
This is a linked list.
Definition: configuration.c:75
char * hint_secret_filename
Diagnostics hint for the secret file.
Definition: configuration.c:98
unsigned int hint_inlined_from_line
For secret sections: Where was this inlined from?
char * hint_secret_stat
Extra information regarding permissions of the secret file.
Used for diffing a configuration object against the default one.
const struct GNUNET_CONFIGURATION_Handle * cfg_default
struct GNUNET_CONFIGURATION_Handle * cfgDiff
Dynamically growing buffer.
Closure for GNUNET_CONFIGURATION_config_tool_run() with settings for what should be done with the con...
int full
Should the generated configuration file contain the whole configuration?
int global_ret
Return value from the operation, to be returned from 'main'.
int diagnostics
Should we give extra diagnostics?
int list_sections
Whether to show the sections.
int rewrite
Should we write out the configuration file, even if no value was changed?
int is_filename
Treat option as a filename.
struct ConfigFile * loaded_files_tail
Linked list of loaded files.
bool load_called
Was the configuration ever loaded via GNUNET_CONFIGURATION_load?
unsigned int current_nest_level
Current nesting level of file loading.
const struct GNUNET_OS_ProjectData * pd
Project data for this configuration object.
struct ConfigSection * sections
Configuration sections.
struct ConfigFile * loaded_files_head
Linked list of loaded files.
char * main_filename
Name of the entry point configuration file.
enum GNUNET_GenericReturnValue dirty
Modification indication since last save GNUNET_NO if clean, GNUNET_YES if dirty, GNUNET_SYSERR on err...
bool diagnostics
Enable diagnostics.
const char * restrict_section
When parsing into this configuration, and this value is non-NULL, only parse sections of the same nam...
Handle used to access files (and pipes).
Project-specific data used to help the OS subsystem find installation paths.
const char * base_config_varname
Name of an environment variable that can be used to override the location from which default configur...
const char * project_dirname
Name of the project that is used in the "libexec" prefix, For example, "gnunet".
const char * user_config_file
Configuration file name to use (if $XDG_CONFIG_HOME is not set).
const char * config_file
Configuration file name (in $XDG_CONFIG_HOME) to use.
Time for relative time used by GNUnet, in microseconds.