GNUnet 0.24.1-15-gab6ed22f1
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 pos = cfg->sections;
422 while ( (NULL != pos) &&
423 (0 != strcasecmp (section,
424 pos->name)) )
425 pos = pos->next;
426 return pos;
427}
428
429
430static int
431pstrcmp (const void *a,
432 const void *b)
433{
434 return strcmp (*((const char **) a),
435 *((const char **) b));
436}
437
438
446 const char *path_or_glob,
447 bool path_is_glob,
448 const char *restrict_section,
449 const char *source_filename,
450 unsigned int source_lineno)
451{
452 char *inline_path = NULL;
453 struct GNUNET_CONFIGURATION_Handle *other_cfg = NULL;
454 struct CollectFilesContext igc = {
455 .files = NULL,
456 .files_length = 0,
457 };
458 enum GNUNET_GenericReturnValue fun_ret;
459 unsigned int old_nest_level = cfg->current_nest_level++;
460
461 /* We support the section restriction only for non-globs */
462 GNUNET_assert (! (path_is_glob && (NULL != restrict_section)));
463
464 if (NULL == source_filename)
465 {
467 "Refusing to parse inline configurations, "
468 "not allowed without source filename!\n");
469 fun_ret = GNUNET_SYSERR;
470 goto cleanup;
471 }
472
473 if ('/' == *path_or_glob)
474 inline_path = GNUNET_strdup (path_or_glob);
475 else
476 {
477 /* We compute the canonical, absolute path first,
478 so that relative imports resolve properly with symlinked
479 config files. */
480 char *source_realpath;
481 char *endsep;
482
483 source_realpath = realpath (source_filename,
484 NULL);
485 if (NULL == source_realpath)
486 {
487 /* Couldn't even resolve path of base dir. */
488 GNUNET_break (0);
489 /* failed to parse included config */
490 fun_ret = GNUNET_SYSERR;
491 goto cleanup;
492 }
493 endsep = strrchr (source_realpath, '/');
494 GNUNET_assert (NULL != endsep);
495 *endsep = '\0';
496 GNUNET_asprintf (&inline_path,
497 "%s/%s",
498 source_realpath,
499 path_or_glob);
500 free (source_realpath);
501 }
502
503 if (path_is_glob)
504 {
505 int nret;
506
508 "processing config glob '%s'\n",
509 inline_path);
510
511 nret = GNUNET_DISK_glob (inline_path,
513 &igc);
514 if (-1 == nret)
515 {
516 fun_ret = GNUNET_SYSERR;
517 goto cleanup;
518 }
519 GNUNET_assert (nret == igc.files_length);
520 qsort (igc.files,
521 igc.files_length,
522 sizeof (char *),
523 &pstrcmp);
524 for (int i = 0; i < nret; i++)
525 {
526 if (GNUNET_OK !=
528 igc.files[i]))
529 {
530 fun_ret = GNUNET_SYSERR;
531 goto cleanup;
532 }
533 }
534 fun_ret = GNUNET_OK;
535 }
536 else if (NULL != restrict_section)
537 {
538 enum GNUNET_GenericReturnValue inner_ret;
539 struct ConfigSection *cs;
540 struct ConfigFile *cf = GNUNET_new (struct ConfigFile);
541
542 inner_ret = GNUNET_DISK_file_test_read (inline_path);
543
544 cs = find_section (cfg, restrict_section);
545
546 if (NULL == cs)
547 {
548 cs = GNUNET_new (struct ConfigSection);
549 cs->name = GNUNET_strdup (restrict_section);
550 cs->next = cfg->sections;
551 cfg->sections = cs;
552 cs->entries = NULL;
553 }
554 if (cfg->diagnostics)
555 {
556 const char *pwname;
557 const char *grname;
558 char *sfn = GNUNET_STRINGS_filename_expand (inline_path);
559 struct stat istat;
560
561 cs->hint_secret_filename = sfn;
562 if (0 == stat (sfn, &istat))
563 {
564 struct passwd *pw = getpwuid (istat.st_uid);
565 struct group *gr = getgrgid (istat.st_gid);
566 pwname = (NULL == pw) ? "<unknown>" : pw->pw_name;
567 grname = (NULL == gr) ? "<unknown>" : gr->gr_name;
568
570 "%s:%s %o",
571 pwname,
572 grname,
573 istat.st_mode);
574 }
575 else
576 {
577 cs->hint_secret_stat = GNUNET_strdup ("<can't stat file>");
578 }
579 if (source_filename)
580 {
581 /* Possible that this secret section has been inlined before */
583 cs->hint_inlined_from_filename = GNUNET_strdup (source_filename);
584 cs->hint_inlined_from_line = source_lineno;
585 }
586 }
587
588 /* Put file in the load list for diagnostics, even if we can't access it. */
589 {
591 cf->source_filename = GNUNET_strdup (inline_path);
592 cf->hint_restrict_section = GNUNET_strdup (restrict_section);
595 cf);
596 }
597
598 if (GNUNET_OK != inner_ret)
599 {
600 cs->inaccessible = true;
601 cf->hint_inaccessible = true;
602 /* File can't be accessed, but that's okay. */
603 fun_ret = GNUNET_OK;
604 goto cleanup;
605 }
606
607 other_cfg = GNUNET_CONFIGURATION_create (cfg->pd);
608 other_cfg->restrict_section = restrict_section;
609 inner_ret = GNUNET_CONFIGURATION_parse (other_cfg,
610 inline_path);
611 if (GNUNET_OK != inner_ret)
612 {
613 cf->hint_inaccessible = true;
614 fun_ret = inner_ret;
615 goto cleanup;
616 }
617
618 cs = find_section (other_cfg,
619 restrict_section);
620 if (NULL == cs)
621 {
623 "Configuration file '%s' loaded with @inline-secret@ "
624 "does not contain section '%s'.\n",
625 inline_path,
626 restrict_section);
627 /* Inlined configuration is accessible but doesn't contain any values.
628 We treat this as if the inlined section was empty, and do not
629 consider it an error. */
630 fun_ret = GNUNET_OK;
631 goto cleanup;
632 }
633 for (struct ConfigEntry *ce = cs->entries;
634 NULL != ce;
635 ce = ce->next)
637 restrict_section,
638 ce->key,
639 ce->val);
640 fun_ret = GNUNET_OK;
641 }
642 else if (GNUNET_OK !=
644 inline_path))
645 {
646 fun_ret = GNUNET_SYSERR;
647 goto cleanup;
648 }
649 else
650 {
651 fun_ret = GNUNET_OK;
652 }
653cleanup:
654 cfg->current_nest_level = old_nest_level;
655 if (NULL != other_cfg)
657 GNUNET_free (inline_path);
658 if (igc.files_length > 0)
659 {
660 for (size_t i = 0; i < igc.files_length; i++)
661 GNUNET_free (igc.files[i]);
663 }
664 return fun_ret;
665}
666
667
676static struct ConfigEntry *
678 const char *section,
679 const char *key)
680{
681 struct ConfigSection *sec;
682 struct ConfigEntry *pos;
683
684 if (NULL == (sec = find_section (cfg, section)))
685 return NULL;
686 if (sec->inaccessible)
687 {
689 "Section '%s' is marked as inaccessible, because the configuration "
690 "file that contains the section can't be read. Attempts to use "
691 "option '%s' will fail.\n",
692 section,
693 key);
694 return NULL;
695 }
696 pos = sec->entries;
697 while ((pos != NULL) && (0 != strcasecmp (key, pos->key)))
698 pos = pos->next;
699 return pos;
700}
701
702
712static void
714 const char *section,
715 const char *option,
716 const char *hint_filename,
717 unsigned int hint_line)
718{
719 struct ConfigEntry *e = find_entry (cfg, section, option);
720 if (! cfg->diagnostics)
721 return;
722 if (! e)
723 return;
725 e->hint_lineno = hint_line;
726}
727
728
731 const char *mem,
732 size_t size,
733 const char *source_filename)
734{
735 size_t line_size;
736 unsigned int nr;
737 size_t r_bytes;
738 size_t to_read;
740 char *section;
741 char *eq;
742 char *tag;
743 char *value;
744 char *line_orig = NULL;
745
746 ret = GNUNET_OK;
747 section = NULL;
748 nr = 0;
749 r_bytes = 0;
750 while (r_bytes < size)
751 {
752 char *pos;
753 char *line;
754 bool emptyline;
755
756 GNUNET_free (line_orig);
757 /* fgets-like behaviour on buffer */
758 to_read = size - r_bytes;
759 pos = memchr (&mem[r_bytes], '\n', to_read);
760 if (NULL == pos)
761 {
762 line_orig = GNUNET_strndup (&mem[r_bytes],
763 line_size = to_read);
764 r_bytes += line_size;
765 }
766 else
767 {
768 line_orig = GNUNET_strndup (&mem[r_bytes],
769 line_size = (pos - &mem[r_bytes]));
770 r_bytes += line_size + 1;
771 }
772 line = line_orig;
773 /* increment line number */
774 nr++;
775 /* tabs and '\r' are whitespace */
776 emptyline = GNUNET_YES;
777 for (size_t i = 0; i < line_size; i++)
778 {
779 if (line[i] == '\t')
780 line[i] = ' ';
781 if (line[i] == '\r')
782 line[i] = ' ';
783 if (' ' != line[i])
784 emptyline = GNUNET_NO;
785 }
786 /* ignore empty lines */
787 if (GNUNET_YES == emptyline)
788 continue;
789
790 /* remove tailing whitespace */
791 for (size_t i = line_size - 1;
792 (i >= 1) && (isspace ((unsigned char) line[i]));
793 i--)
794 line[i] = '\0';
795
796 /* remove leading whitespace */
797 for (; line[0] != '\0' && (isspace ((unsigned char) line[0])); line++)
798 ;
799
800 /* ignore comments */
801 if ( ('#' == line[0]) ||
802 ('%' == line[0]) )
803 continue;
804
805 /* Handle special directives. */
806 if ('@' == line[0])
807 {
808 char *end = strchr (line + 1, '@');
809 char *directive;
810 enum GNUNET_GenericReturnValue directive_ret;
811
812 if (NULL != cfg->restrict_section)
813 {
815 "Illegal directive in line %u (parsing restricted section %s)\n",
816 nr,
819 break;
820 }
821
822 if (NULL == end)
823 {
825 "Bad directive in line %u\n",
826 nr);
828 break;
829 }
830 *end = '\0';
831 directive = line + 1;
832
833 if (0 == strcasecmp (directive,
834 "INLINE"))
835 {
836 const char *path = end + 1;
837
838 /* Skip space before path */
839 for (; isspace (*path); path++)
840 ;
841
842 directive_ret = handle_inline (cfg,
843 path,
844 false,
845 NULL,
846 source_filename,
847 nr);
848 }
849 else if (0 == strcasecmp (directive,
850 "INLINE-MATCHING"))
851 {
852 const char *path = end + 1;
853
854 /* Skip space before path */
855 for (; isspace (*path); path++)
856 ;
857
858 directive_ret = handle_inline (cfg,
859 path,
860 true,
861 NULL,
862 source_filename,
863 nr);
864 }
865 else if (0 == strcasecmp (directive,
866 "INLINE-SECRET"))
867 {
868 char *secname = end + 1;
869 char *secname_end;
870 const char *path;
871
872 /* Skip space before secname */
873 for (; isspace (*secname); secname++)
874 ;
875
876 secname_end = strchr (secname, ' ');
877
878 if (NULL == secname_end)
879 {
881 "Bad inline-secret directive in line %u\n",
882 nr);
884 break;
885 }
886 *secname_end = '\0';
887 path = secname_end + 1;
888
889 /* Skip space before path */
890 for (; isspace (*path); path++)
891 ;
892
893 directive_ret = handle_inline (cfg,
894 path,
895 false,
896 secname,
897 source_filename,
898 nr);
899 }
900 else
901 {
903 "Unknown or malformed directive '%s' in line %u\n",
904 directive,
905 nr);
907 break;
908 }
909 if (GNUNET_OK != directive_ret)
910 {
911 ret = directive_ret;
912 break;
913 }
914 continue;
915 }
916 if ( ('[' == line[0]) &&
917 (']' == line[line_size - 1]) )
918 {
919 /* [value] */
920 line[line_size - 1] = '\0';
921 value = &line[1];
922 GNUNET_free (section);
923 section = GNUNET_strdup (value);
924 continue;
925 }
926 if (NULL != (eq = strchr (line, '=')))
927 {
928
929 if (NULL == section)
930 {
932 "Syntax error while deserializing in line %u (option without section)\n",
933 nr);
935 break;
936 }
937
938 /* tag = value */
939 tag = GNUNET_strndup (line, eq - line);
940 /* remove tailing whitespace */
941 for (int i = strlen (tag) - 1;
942 (i >= 1) && (isspace ((unsigned char) tag[i]));
943 i--)
944 tag[i] = '\0';
945
946 /* Strip whitespace */
947 value = eq + 1;
948 while (isspace ((unsigned char) value[0]))
949 value++;
950 for (int i = strlen (value) - 1;
951 (i >= 1) && (isspace ((unsigned char) value[i]));
952 i--)
953 value[i] = '\0';
954
955 /* remove quotes */
956 if ( ('"' == value[0]) &&
957 ('"' == value[strlen (value) - 1]) )
958 {
959 value[strlen (value) - 1] = '\0';
960 value++;
961 }
963 section,
964 tag,
965 value);
966 if (cfg->diagnostics)
967 {
969 section,
970 tag,
971 source_filename
972 ? source_filename
973 : "<input>",
974 nr);
975 }
976 GNUNET_free (tag);
977 continue;
978 }
979 /* parse error */
981 "Syntax error while deserializing in line %u\n",
982 nr);
984 break;
985 }
986 GNUNET_free (line_orig);
987 GNUNET_free (section);
988 GNUNET_assert ( (GNUNET_OK != ret) ||
989 (r_bytes == size) );
990 return ret;
991}
992
993
996 const char *filename)
997{
998 uint64_t fs64;
999 size_t fs;
1000 char *fn;
1001 char *mem;
1002 int dirty;
1004 ssize_t sret;
1005
1008 "Asked to parse config file `%s'\n",
1009 fn);
1010 if (NULL == fn)
1011 return GNUNET_SYSERR;
1012
1013
1014 /* Check for cycles */
1015 {
1016 unsigned int lvl = cfg->current_nest_level;
1017 struct ConfigFile *cf = cfg->loaded_files_tail;
1018 struct ConfigFile *parent = NULL;
1019
1020
1021 for (; NULL != cf; parent = cf, cf = cf->prev)
1022 {
1023 /* Check parents based on level, skipping children of siblings. */
1024 if (cf->level >= lvl)
1025 continue;
1026 lvl = cf->level;
1027 if ( (NULL == cf->source_filename) ||
1028 (NULL == filename) )
1029 continue;
1030 if (0 == strcmp (cf->source_filename,
1031 filename))
1032 {
1033 if (NULL == parent)
1034 {
1036 "Forbidden direct cyclic configuration import (%s -> %s)\n",
1037 cf->source_filename,
1038 filename);
1039 }
1040 else
1042 "Forbidden indirect cyclic configuration import (%s -> ... -> %s -> %s)\n",
1043 cf->source_filename,
1044 parent->source_filename,
1045 filename);
1046 GNUNET_free (fn);
1047 return GNUNET_SYSERR;
1048 }
1049 }
1050
1051 }
1052
1053 /* Keep track of loaded files.*/
1054 {
1055 struct ConfigFile *cf = GNUNET_new (struct ConfigFile);
1056
1058 cf->source_filename = GNUNET_strdup (filename ? filename : "<input>");
1061 cf);
1062 }
1063
1064 dirty = cfg->dirty; /* back up value! */
1065 if (GNUNET_SYSERR ==
1067 &fs64,
1068 GNUNET_YES,
1069 GNUNET_YES))
1070 {
1072 "Error while determining the file size of `%s'\n",
1073 fn);
1074 GNUNET_free (fn);
1075 return GNUNET_SYSERR;
1076 }
1077 if (fs64 > SIZE_MAX)
1078 {
1079 GNUNET_break (0); /* File size is more than the heap size */
1080 GNUNET_free (fn);
1081 return GNUNET_SYSERR;
1082 }
1083 fs = fs64;
1084 mem = GNUNET_malloc (fs);
1085 sret = GNUNET_DISK_fn_read (fn,
1086 mem,
1087 fs);
1088 if ((sret < 0) || (fs != (size_t) sret))
1089 {
1091 "Error while reading file `%s'\n",
1092 fn);
1093 GNUNET_free (fn);
1094 GNUNET_free (mem);
1095 return GNUNET_SYSERR;
1096 }
1098 "Deserializing contents of file `%s'\n",
1099 fn);
1101 mem,
1102 fs,
1103 fn);
1104 if (GNUNET_SYSERR == ret)
1105 {
1107 _ ("Failed to parse configuration file `%s'\n"),
1108 fn);
1109 }
1110 GNUNET_free (fn);
1111 GNUNET_free (mem);
1112 /* restore dirty flag - anything we set in the meantime
1113 * came from disk */
1114 cfg->dirty = dirty;
1115 return ret;
1116}
1117
1118
1121{
1122 return cfg->dirty;
1123}
1124
1125
1133static bool
1134do_skip (const char *sec,
1135 const char *key)
1136{
1137 if (0 != strcasecmp ("PATHS",
1138 sec))
1139 return false;
1140 return ( (0 == strcasecmp ("DATADIR",
1141 key)) ||
1142 (0 == strcasecmp ("LIBDIR",
1143 key)) ||
1144 (0 == strcasecmp ("BINDIR",
1145 key)) ||
1146 (0 == strcasecmp ("PREFIX",
1147 key)) ||
1148 (0 == strcasecmp ("LOCALEDIR",
1149 key)) ||
1150 (0 == strcasecmp ("ICONDIR",
1151 key)) ||
1152 (0 == strcasecmp ("DOCDIR",
1153 key)) ||
1154 (0 == strcasecmp ("DEFAULTCONFIG",
1155 key)) ||
1156 (0 == strcasecmp ("LIBEXECDIR",
1157 key)) );
1158}
1159
1160
1161char *
1163 size_t *size)
1164{
1165 char *mem;
1166 char *cbuf;
1167 char *val;
1168 char *pos;
1169 size_t m_size;
1170 size_t c_size;
1171
1172 /* Pass1 : calculate the buffer size required */
1173 m_size = 0;
1174 for (struct ConfigSection *sec = cfg->sections;
1175 NULL != sec;
1176 sec = sec->next)
1177 {
1178 if (sec->inaccessible)
1179 continue;
1180 /* For each section we need to add 3 characters: {'[',']','\n'} */
1181 m_size += strlen (sec->name) + 3;
1182 for (struct ConfigEntry *ent = sec->entries;
1183 NULL != ent;
1184 ent = ent->next)
1185 {
1186 if (do_skip (sec->name,
1187 ent->key))
1188 continue;
1189 if (NULL != ent->val)
1190 {
1191 /* if val has any '\n' then they occupy +1 character as '\n'->'\\','n' */
1192 pos = ent->val;
1193 while (NULL != (pos = strstr (pos, "\n")))
1194 {
1195 m_size++;
1196 pos++;
1197 }
1198 /* For each key = value pair we need to add 4 characters (2
1199 spaces and 1 equal-to character and 1 new line) */
1200 m_size += strlen (ent->key) + strlen (ent->val) + 4;
1201 }
1202 }
1203 /* A new line after section end */
1204 m_size++;
1205 }
1206
1207 /* Pass2: Allocate memory and write the configuration to it */
1208 mem = GNUNET_malloc (m_size);
1209 c_size = 0;
1210 *size = c_size;
1211 for (struct ConfigSection *sec = cfg->sections;
1212 NULL != sec;
1213 sec = sec->next)
1214 {
1215 int len;
1216
1217 len = GNUNET_asprintf (&cbuf,
1218 "[%s]\n",
1219 sec->name);
1220 GNUNET_assert (0 < len);
1221 GNUNET_memcpy (mem + c_size,
1222 cbuf,
1223 len);
1224 c_size += len;
1225 GNUNET_free (cbuf);
1226 for (struct ConfigEntry *ent = sec->entries;
1227 NULL != ent;
1228 ent = ent->next)
1229 {
1230 if (do_skip (sec->name,
1231 ent->key))
1232 continue;
1233 if (NULL != ent->val)
1234 {
1235 val = GNUNET_malloc (strlen (ent->val) * 2 + 1);
1236 strcpy (val, ent->val);
1237 while (NULL != (pos = strstr (val, "\n")))
1238 {
1239 memmove (&pos[2], &pos[1], strlen (&pos[1]));
1240 pos[0] = '\\';
1241 pos[1] = 'n';
1242 }
1243 len = GNUNET_asprintf (&cbuf, "%s = %s\n", ent->key, val);
1244 GNUNET_free (val);
1245 GNUNET_memcpy (mem + c_size, cbuf, len);
1246 c_size += len;
1247 GNUNET_free (cbuf);
1248 }
1249 }
1250 GNUNET_memcpy (mem + c_size, "\n", 1);
1251 c_size++;
1252 }
1253 GNUNET_assert (c_size == m_size);
1254 *size = c_size;
1255 return mem;
1256}
1257
1258
1267static void
1269 const struct GNUNET_CONFIGURATION_Handle *cfg,
1270 struct GNUNET_Buffer *buf,
1272{
1274 ipk);
1275 const char *ipkname;
1276 switch (ipk)
1277 {
1279 ipkname = "IPK_DATADIR";
1280 break;
1282 ipkname = "IPK_BINDIR";
1283 break;
1285 ipkname = "IPK_LIBDIR";
1286 break;
1288 ipkname = "IPK_PREFIX";
1290 ipkname = "IPK_LOCALEDIR";
1291 break;
1293 ipkname = "IPK_ICONDIR";
1295 ipkname = "IPK_DOCDIR";
1296 break;
1298 ipkname = "IPK_LIBEXECDIR";
1299 break;
1301 ipkname = "IPK_SELF_PREFIX";
1302 break;
1303 default:
1304 ipkname = "??";
1305 break;
1306 }
1308 "# %s = %s\n",
1309 ipkname,
1310 v);
1311 GNUNET_free (v);
1312}
1313
1314
1315char *
1317 const struct GNUNET_CONFIGURATION_Handle *cfg)
1318{
1319 struct GNUNET_Buffer buf = { 0 };
1320
1322 "#\n# Configuration file diagnostics\n#\n");
1324 "# Entry point: %s\n",
1326 "<none>");
1328 "#\n# Files Loaded:\n");
1329
1330 for (struct ConfigFile *cfil = cfg->loaded_files_head;
1331 NULL != cfil;
1332 cfil = cfil->next)
1333 {
1335 "# ");
1336 for (unsigned int i = 0; i < cfil->level; i++)
1338 "+");
1339 if (0 != cfil->level)
1341 " ");
1342
1344 "%s",
1345 cfil->source_filename);
1346
1347 if (NULL != cfil->hint_restrict_section)
1349 " (%s secret section %s)",
1350 cfil->hint_inaccessible
1351 ? "inaccessible"
1352 : "loaded",
1353 cfil->hint_restrict_section);
1354
1356 "\n");
1357 }
1358
1360 "#\n# Installation paths:\n");
1361
1371
1372
1374 "#\n\n");
1375
1376 for (struct ConfigSection *sec = cfg->sections;
1377 NULL != sec;
1378 sec = sec->next)
1379 {
1380 if (sec->hint_secret_filename)
1382 "# secret section from %s\n# secret file stat %s\n",
1383 sec->hint_secret_filename,
1384 sec->hint_secret_stat);
1385 if (sec->hint_inlined_from_filename)
1386 {
1388 "# inlined from %s:%u\n",
1389 sec->hint_inlined_from_filename,
1390 sec->hint_inlined_from_line);
1391 }
1393 "[%s]\n\n",
1394 sec->name);
1395 if (sec->inaccessible)
1396 {
1398 "# <section contents inaccessible>\n\n\n");
1399 continue;
1400 }
1401 for (struct ConfigEntry *ent = sec->entries;
1402 NULL != ent;
1403 ent = ent->next)
1404 {
1405 if (do_skip (sec->name,
1406 ent->key))
1407 continue;
1408 if (NULL != ent->val)
1409 {
1410 char *pos;
1411 char *val = GNUNET_malloc (strlen (ent->val) * 2 + 1);
1412 strcpy (val, ent->val);
1413 while (NULL != (pos = strstr (val, "\n")))
1414 {
1415 memmove (&pos[2], &pos[1], strlen (&pos[1]));
1416 pos[0] = '\\';
1417 pos[1] = 'n';
1418 }
1419 if (NULL != ent->hint_filename)
1420 {
1422 "# %s:%u\n",
1423 ent->hint_filename,
1424 ent->hint_lineno);
1425 }
1427 "%s = %s\n",
1428 ent->key,
1429 val);
1430 GNUNET_free (val);
1431 }
1432 GNUNET_buffer_write_str (&buf, "\n");
1433 }
1434 GNUNET_buffer_write_str (&buf, "\n");
1435 }
1436 return GNUNET_buffer_reap_str (&buf);
1437}
1438
1439
1443 const char *filename)
1444{
1445 char *fn;
1446 char *cfg_buf;
1447 size_t size;
1448
1450 if (fn == NULL)
1451 return GNUNET_SYSERR;
1453 {
1454 GNUNET_free (fn);
1455 return GNUNET_SYSERR;
1456 }
1458 &size);
1459 {
1460 struct GNUNET_DISK_FileHandle *h;
1461
1470 if (NULL == h)
1471 {
1472 GNUNET_free (fn);
1473 GNUNET_free (cfg_buf);
1474 return GNUNET_SYSERR;
1475 }
1476 if (((ssize_t) size) !=
1478 cfg_buf,
1479 size))
1480 {
1482 "write",
1483 fn);
1485 (void) GNUNET_DISK_directory_remove (fn);
1486 GNUNET_free (fn);
1487 GNUNET_free (cfg_buf);
1488 cfg->dirty = GNUNET_SYSERR; /* last write failed */
1489 return GNUNET_SYSERR;
1490 }
1493 }
1494 GNUNET_free (fn);
1495 GNUNET_free (cfg_buf);
1496 cfg->dirty = GNUNET_NO; /* last write succeeded */
1497 return GNUNET_OK;
1498}
1499
1500
1501void
1503 const struct GNUNET_CONFIGURATION_Handle *cfg,
1505 void *iter_cls)
1506{
1507 for (struct ConfigSection *spos = cfg->sections;
1508 NULL != spos;
1509 spos = spos->next)
1510 for (struct ConfigEntry *epos = spos->entries;
1511 NULL != epos;
1512 epos = epos->next)
1513 if (NULL != epos->val)
1514 iter (iter_cls,
1515 spos->name,
1516 epos->key,
1517 epos->val);
1518}
1519
1520
1521void
1523 const struct GNUNET_CONFIGURATION_Handle *cfg,
1524 const char *section,
1526 void *iter_cls)
1527{
1528 struct ConfigSection *spos;
1529
1530 spos = cfg->sections;
1531 while ((spos != NULL) && (0 != strcasecmp (spos->name, section)))
1532 spos = spos->next;
1533 if (NULL == spos)
1534 return;
1535 if (spos->inaccessible)
1536 {
1538 "Section '%s' is marked as inaccessible, because the configuration "
1539 "file that contains the section can't be read.\n",
1540 section);
1541 return;
1542 }
1543 for (struct ConfigEntry *epos = spos->entries;
1544 NULL != epos;
1545 epos = epos->next)
1546 if (NULL != epos->val)
1547 iter (iter_cls,
1548 spos->name,
1549 epos->key,
1550 epos->val);
1551}
1552
1553
1554void
1556 const struct GNUNET_CONFIGURATION_Handle *cfg,
1558 void *iter_cls)
1559{
1560 struct ConfigSection *spos;
1561 struct ConfigSection *next;
1562
1563 next = cfg->sections;
1564 while (next != NULL)
1565 {
1566 spos = next;
1567 next = spos->next;
1568 if (! spos->inaccessible)
1569 iter (iter_cls,
1570 spos->name);
1571 }
1572}
1573
1574
1575void
1577 const char *section)
1578{
1579 struct ConfigSection *spos;
1580 struct ConfigSection *prev;
1581 struct ConfigEntry *ent;
1582
1583 prev = NULL;
1584 spos = cfg->sections;
1585 while (NULL != spos)
1586 {
1587 if (0 == strcasecmp (section,
1588 spos->name))
1589 {
1590 if (NULL == prev)
1591 cfg->sections = spos->next;
1592 else
1593 prev->next = spos->next;
1594 while (NULL != (ent = spos->entries))
1595 {
1596 spos->entries = ent->next;
1597 GNUNET_free (ent->key);
1598 GNUNET_free (ent->val);
1600 GNUNET_free (ent);
1601 cfg->dirty = GNUNET_YES;
1602 }
1603 GNUNET_free (spos->name);
1607 GNUNET_free (spos);
1608 return;
1609 }
1610 prev = spos;
1611 spos = spos->next;
1612 }
1613}
1614
1615
1625static void
1626copy_entry (void *cls,
1627 const char *section,
1628 const char *option,
1629 const char *value)
1630{
1631 struct GNUNET_CONFIGURATION_Handle *dst = cls;
1632
1634 section,
1635 option,
1636 value);
1637}
1638
1639
1642 const struct GNUNET_CONFIGURATION_Handle *cfg)
1643{
1645
1648 &copy_entry,
1649 ret);
1650 return ret;
1651}
1652
1653
1664static void
1666 const char *section,
1667 const char *option,
1668 const char *value)
1669{
1670 struct DiffHandle *dh = cls;
1671 struct ConfigEntry *entNew;
1672
1673 entNew = find_entry (dh->cfg_default, section, option);
1674 if ((NULL != entNew) && (NULL != entNew->val) &&
1675 (0 == strcmp (entNew->val, value)))
1676 return;
1678 section,
1679 option,
1680 value);
1681}
1682
1683
1686 const struct GNUNET_CONFIGURATION_Handle *cfg_default,
1687 const struct GNUNET_CONFIGURATION_Handle *cfg_new)
1688{
1689 struct DiffHandle diffHandle;
1690
1691 GNUNET_break (cfg_default->pd == cfg_new->pd);
1692 diffHandle.cfgDiff = GNUNET_CONFIGURATION_create (cfg_new->pd);
1693 diffHandle.cfg_default = cfg_default;
1696 &diffHandle);
1697 return diffHandle.cfgDiff;
1698}
1699
1700
1704 const struct GNUNET_CONFIGURATION_Handle *cfg_new,
1705 const char *filename)
1706{
1707 int ret;
1708 struct GNUNET_CONFIGURATION_Handle *diff;
1709
1710 diff = GNUNET_CONFIGURATION_get_diff (cfg_default, cfg_new);
1713 return ret;
1714}
1715
1716
1717void
1720 const char *section,
1721 const char *option,
1722 const char *value)
1723{
1724 struct ConfigSection *sec;
1725 struct ConfigEntry *e;
1726 char *nv;
1727
1728 e = find_entry (cfg, section, option);
1729 if (NULL != e)
1730 {
1731 if (NULL == value)
1732 {
1733 GNUNET_free (e->val);
1734 e->val = NULL;
1735 }
1736 else
1737 {
1738 nv = GNUNET_strdup (value);
1739 GNUNET_free (e->val);
1740 e->val = nv;
1741 }
1742 return;
1743 }
1744 sec = find_section (cfg, section);
1745 if (sec == NULL)
1746 {
1747 sec = GNUNET_new (struct ConfigSection);
1748 sec->name = GNUNET_strdup (section);
1749 sec->next = cfg->sections;
1750 cfg->sections = sec;
1751 }
1752 e = GNUNET_new (struct ConfigEntry);
1753 e->key = GNUNET_strdup (option);
1754 e->val = GNUNET_strdup (value);
1755 e->next = sec->entries;
1756 sec->entries = e;
1757}
1758
1759
1760void
1762 const char *section,
1763 const char *option,
1764 unsigned long long number)
1765{
1766 char s[64];
1767
1768 GNUNET_snprintf (s,
1769 64,
1770 "%llu",
1771 number);
1773 section,
1774 option,
1775 s);
1776}
1777
1778
1781 const struct GNUNET_CONFIGURATION_Handle *cfg,
1782 const char *section,
1783 const char *option,
1784 unsigned long long *number)
1785{
1786 struct ConfigEntry *e;
1787 char dummy[2];
1788
1789 if (NULL == (e = find_entry (cfg,
1790 section,
1791 option)))
1792 return GNUNET_NO;
1793 if (NULL == e->val)
1794 return GNUNET_NO;
1795 if (1 != sscanf (e->val,
1796 "%llu%1s",
1797 number,
1798 dummy))
1799 return GNUNET_SYSERR;
1800 return GNUNET_OK;
1801}
1802
1803
1804void
1806 const char *section,
1807 const char *option,
1808 float number)
1809{
1810 char s[64];
1811
1812 /* See: #9369 */
1813 const locale_t cl = newlocale (LC_NUMERIC_MASK,
1814 "C",
1815 (locale_t) 0);
1816 locale_t old_locale = uselocale (cl);
1817 GNUNET_snprintf (s,
1818 64,
1819 "%f",
1820 (double) number);
1821 uselocale (old_locale);
1823 section,
1824 option,
1825 s);
1826}
1827
1828
1831 const struct GNUNET_CONFIGURATION_Handle *cfg,
1832 const char *section,
1833 const char *option,
1834 float *number)
1835{
1836 struct ConfigEntry *e;
1837 char dummy[2];
1838
1839 if (NULL == (e = find_entry (cfg,
1840 section,
1841 option)))
1842 return GNUNET_NO;
1843 if (NULL == e->val)
1844 return GNUNET_NO;
1845 /* See #9369 */
1846 {
1847 const locale_t cl = newlocale (LC_NUMERIC_MASK,
1848 "C",
1849 (locale_t) 0);
1850 locale_t old_locale = uselocale (cl);
1851
1852 if (1 != sscanf (e->val,
1853 "%f%1s",
1854 number,
1855 dummy))
1856 return GNUNET_SYSERR;
1857 uselocale (old_locale);
1858 }
1859 return GNUNET_OK;
1860}
1861
1862
1865 const struct GNUNET_CONFIGURATION_Handle *cfg,
1866 const char *section,
1867 const char *option,
1868 struct GNUNET_TIME_Relative *time)
1869{
1870 struct ConfigEntry *e;
1871 int ret;
1872
1873 if (NULL == (e = find_entry (cfg,
1874 section,
1875 option)))
1876 return GNUNET_NO;
1877 if (NULL == e->val)
1878 return GNUNET_NO;
1880 time);
1881 if (GNUNET_OK != ret)
1883 section,
1884 option,
1885 _ ("Not a valid relative time specification"));
1886 return ret;
1887}
1888
1889
1892 const struct GNUNET_CONFIGURATION_Handle *cfg,
1893 const char *section,
1894 const char *option,
1895 unsigned long long *size)
1896{
1897 struct ConfigEntry *e;
1898
1899 if (NULL == (e = find_entry (cfg,
1900 section,
1901 option)))
1902 return GNUNET_NO;
1903 if (NULL == e->val)
1904 return GNUNET_NO;
1906 size);
1907}
1908
1909
1922 const struct GNUNET_CONFIGURATION_Handle *cfg,
1923 const char *section,
1924 const char *option,
1925 char **value)
1926{
1927 struct ConfigEntry *e;
1928
1929 if ( (NULL == (e = find_entry (cfg,
1930 section,
1931 option))) ||
1932 (NULL == e->val) )
1933 {
1934 *value = NULL;
1935 return GNUNET_NO;
1936 }
1937 *value = GNUNET_strdup (e->val);
1938 return GNUNET_OK;
1939}
1940
1941
1944 const struct GNUNET_CONFIGURATION_Handle *cfg,
1945 const char *section,
1946 const char *option,
1947 const char *const *choices,
1948 const char **value)
1949{
1950 struct ConfigEntry *e;
1951 unsigned int i;
1952
1953 if (NULL == (e = find_entry (cfg,
1954 section,
1955 option)))
1956 return GNUNET_NO;
1957 for (i = 0; NULL != choices[i]; i++)
1958 if (0 == strcasecmp (choices[i], e->val))
1959 break;
1960 if (NULL == choices[i])
1961 {
1963 _ ("Configuration value '%s' for '%s'"
1964 " in section '%s' is not in set of legal choices\n"),
1965 e->val,
1966 option,
1967 section);
1968 return GNUNET_SYSERR;
1969 }
1970 *value = choices[i];
1971 return GNUNET_OK;
1972}
1973
1974
1977 const char *section,
1978 const char *option,
1979 void *buf,
1980 size_t buf_size)
1981{
1982 char *enc;
1983 int res;
1984 size_t data_size;
1985
1986 if (GNUNET_OK !=
1987 (res =
1989 section,
1990 option,
1991 &enc)))
1992 return res;
1993 data_size = (strlen (enc) * 5) / 8;
1994 if (data_size != buf_size)
1995 {
1996 GNUNET_free (enc);
1997 return GNUNET_SYSERR;
1998 }
1999 if (GNUNET_OK !=
2001 strlen (enc),
2002 buf,
2003 buf_size))
2004 {
2005 GNUNET_free (enc);
2006 return GNUNET_SYSERR;
2007 }
2008 GNUNET_free (enc);
2009 return GNUNET_OK;
2010}
2011
2012
2015 const char *section,
2016 const char *option)
2017{
2018 struct ConfigEntry *e;
2019
2020 if ( (NULL == (e = find_entry (cfg,
2021 section,
2022 option))) ||
2023 (NULL == e->val) )
2024 return GNUNET_NO;
2025 return GNUNET_YES;
2026}
2027
2028
2044static char *
2046 char *orig,
2047 unsigned int depth)
2048{
2049 char *prefix;
2050 char *result;
2051 char *start;
2052 const char *post;
2053 const char *env;
2054 char *def;
2055 char *end;
2056 unsigned int lopen;
2057 char erased_char;
2058 char *erased_pos;
2059 size_t len;
2060
2061 if (NULL == orig)
2062 return NULL;
2063 if (depth > 128)
2064 {
2066 "Recursive expansion suspected, aborting $-expansion for term `%s'\n",
2067 orig);
2068 return orig;
2069 }
2071 "Asked to $-expand %s\n",
2072 orig);
2073 if ('$' != orig[0])
2074 {
2076 "Doesn't start with $ - not expanding\n");
2077 return orig;
2078 }
2079 erased_char = 0;
2080 erased_pos = NULL;
2081 if ('{' == orig[1])
2082 {
2083 start = &orig[2];
2084 lopen = 1;
2085 end = &orig[1];
2086 while (lopen > 0)
2087 {
2088 end++;
2089 switch (*end)
2090 {
2091 case '}':
2092 lopen--;
2093 break;
2094
2095 case '{':
2096 lopen++;
2097 break;
2098
2099 case '\0':
2101 "Missing closing `}' in option `%s'\n",
2102 orig);
2103 return orig;
2104
2105 default:
2106 break;
2107 }
2108 }
2109 erased_char = *end;
2110 erased_pos = end;
2111 *end = '\0';
2112 post = end + 1;
2113 def = strchr (orig, ':');
2114 if (NULL != def)
2115 {
2116 *def = '\0';
2117 def++;
2118 if (('-' == *def) || ('=' == *def))
2119 def++;
2120 def = GNUNET_strdup (def);
2121 }
2122 }
2123 else
2124 {
2125 int i;
2126
2127 start = &orig[1];
2128 def = NULL;
2129 i = 0;
2130 while ( (orig[i] != '/') &&
2131 (orig[i] != '\\') &&
2132 (orig[i] != '\0') &&
2133 (orig[i] != ' ') )
2134 i++;
2135 if (orig[i] == '\0')
2136 {
2137 post = "";
2138 }
2139 else
2140 {
2141 erased_char = orig[i];
2142 erased_pos = &orig[i];
2143 orig[i] = '\0';
2144 post = &orig[i + 1];
2145 }
2146 }
2148 "Split into `%s' and `%s' with default %s\n",
2149 start,
2150 post,
2151 def);
2152 if (GNUNET_OK !=
2154 "PATHS",
2155 start,
2156 &prefix))
2157 {
2158 if (NULL == (env = getenv (start)))
2159 {
2160 /* try default */
2161 def = expand_dollar (cfg,
2162 def,
2163 depth + 1);
2164 env = def;
2165 }
2166 if (NULL == env)
2167 {
2169 if (erased_pos)
2170 *erased_pos = erased_char;
2172 "Failed to expand `%s' in `%s' as it is neither found in [PATHS] nor defined as an environmental variable\n",
2173 start,
2174 orig);
2176 return orig;
2177 }
2179 }
2181 prefix);
2182 if ((erased_pos) && ('}' != erased_char))
2183 {
2184 len = strlen (prefix) + 1;
2185 prefix = GNUNET_realloc (prefix, len + 1);
2186 prefix[len - 1] = erased_char;
2187 prefix[len] = '\0';
2188 }
2189 result = GNUNET_malloc (strlen (prefix) + strlen (post) + 1);
2190 strcpy (result, prefix);
2191 strcat (result, post);
2192 GNUNET_free (def);
2194 GNUNET_free (orig);
2195 return result;
2196}
2197
2198
2199char *
2201 const struct GNUNET_CONFIGURATION_Handle *cfg,
2202 char *orig)
2203{
2204 char *dup;
2205 size_t i;
2206 size_t len;
2207
2208 for (i = 0; '\0' != orig[i]; i++)
2209 {
2210 if ('$' != orig[i])
2211 continue;
2212 dup = GNUNET_strdup (orig + i);
2213 dup = expand_dollar (cfg, dup, 0);
2214 GNUNET_assert (NULL != dup); /* make compiler happy */
2215 len = strlen (dup) + 1;
2216 orig = GNUNET_realloc (orig, i + len);
2217 GNUNET_memcpy (orig + i, dup, len);
2218 GNUNET_free (dup);
2219 }
2220 return orig;
2221}
2222
2223
2226 const struct GNUNET_CONFIGURATION_Handle *cfg,
2227 const char *section,
2228 const char *option,
2229 char **value)
2230{
2231 char *tmp;
2233
2235 section,
2236 option,
2237 &tmp);
2238 if (GNUNET_OK != ret)
2239 {
2241 "Failed to retrieve filename\n");
2242 *value = NULL;
2243 return ret;
2244 }
2246 tmp);
2248 GNUNET_free (tmp);
2249 if (*value == NULL)
2250 return GNUNET_SYSERR;
2251 return GNUNET_OK;
2252}
2253
2254
2257 const struct GNUNET_CONFIGURATION_Handle *cfg,
2258 const char *section,
2259 const char *option)
2260{
2261 static const char *yesno[] = {
2262 "YES",
2263 "NO",
2264 NULL
2265 };
2266 const char *val;
2268
2269 ret =
2271 section,
2272 option,
2273 yesno,
2274 &val);
2275 if (GNUNET_OK != ret)
2276 return ret;
2277 if (val == yesno[0])
2278 return GNUNET_YES;
2279 return GNUNET_NO;
2280}
2281
2282
2283int
2285 const struct GNUNET_CONFIGURATION_Handle *cfg,
2286 const char *section,
2287 const char *option,
2289 void *cb_cls)
2290{
2291 char *list;
2292 char *pos;
2293 char *end;
2294 char old;
2295 int ret;
2296
2297 if (GNUNET_OK !=
2299 section,
2300 option,
2301 &list))
2302 return 0;
2303 GNUNET_assert (list != NULL);
2304 ret = 0;
2305 pos = list;
2306 while (1)
2307 {
2308 while (pos[0] == ' ')
2309 pos++;
2310 if (strlen (pos) == 0)
2311 break;
2312 end = pos + 1;
2313 while ((end[0] != ' ') && (end[0] != '\0'))
2314 {
2315 if (end[0] == '\\')
2316 {
2317 switch (end[1])
2318 {
2319 case '\\':
2320 case ' ':
2321 memmove (end, &end[1], strlen (&end[1]) + 1);
2322
2323 case '\0':
2324 /* illegal, but just keep it */
2325 break;
2326
2327 default:
2328 /* illegal, but just ignore that there was a '/' */
2329 break;
2330 }
2331 }
2332 end++;
2333 }
2334 old = end[0];
2335 end[0] = '\0';
2336 if (strlen (pos) > 0)
2337 {
2338 ret++;
2339 if ( (NULL != cb) &&
2340 (GNUNET_OK != cb (cb_cls,
2341 pos)))
2342 {
2344 break;
2345 }
2346 }
2347 if (old == '\0')
2348 break;
2349 pos = end + 1;
2350 }
2351 GNUNET_free (list);
2352 return ret;
2353}
2354
2355
2362static char *
2363escape_name (const char *value)
2364{
2365 char *escaped;
2366 const char *rpos;
2367 char *wpos;
2368
2369 escaped = GNUNET_malloc (strlen (value) * 2 + 1);
2370 memset (escaped, 0, strlen (value) * 2 + 1);
2371 rpos = value;
2372 wpos = escaped;
2373 while (rpos[0] != '\0')
2374 {
2375 switch (rpos[0])
2376 {
2377 case '\\':
2378 case ' ':
2379 wpos[0] = '\\';
2380 wpos[1] = rpos[0];
2381 wpos += 2;
2382 break;
2383
2384 default:
2385 wpos[0] = rpos[0];
2386 wpos++;
2387 }
2388 rpos++;
2389 }
2390 return escaped;
2391}
2392
2393
2401static enum GNUNET_GenericReturnValue
2402test_match (void *cls,
2403 const char *fn)
2404{
2405 const char *of = cls;
2406
2407 return (0 == strcmp (of, fn))
2409 : GNUNET_OK;
2410}
2411
2412
2416 const char *section,
2417 const char *option,
2418 const char *value)
2419{
2420 char *escaped;
2421 char *old;
2422 char *nw;
2423
2424 if (GNUNET_SYSERR ==
2426 section,
2427 option,
2428 &test_match,
2429 (void *) value))
2430 return GNUNET_NO; /* already exists */
2431 if (GNUNET_OK !=
2432 GNUNET_CONFIGURATION_get_value_string (cfg, section, option, &old))
2433 old = GNUNET_strdup ("");
2434 escaped = escape_name (value);
2435 nw = GNUNET_malloc (strlen (old) + strlen (escaped) + 2);
2436 strcpy (nw, old);
2437 if (strlen (old) > 0)
2438 strcat (nw, " ");
2439 strcat (nw, escaped);
2441 section,
2442 option,
2443 nw);
2444 GNUNET_free (old);
2445 GNUNET_free (nw);
2446 GNUNET_free (escaped);
2447 return GNUNET_OK;
2448}
2449
2450
2454 const char *section,
2455 const char *option,
2456 const char *value)
2457{
2458 char *list;
2459 char *pos;
2460 char *end;
2461 char *match;
2462 char old;
2463
2464 if (GNUNET_OK !=
2466 section,
2467 option,
2468 &list))
2469 return GNUNET_NO;
2470 match = escape_name (value);
2471 pos = list;
2472 while (1)
2473 {
2474 while (pos[0] == ' ')
2475 pos++;
2476 if (strlen (pos) == 0)
2477 break;
2478 end = pos + 1;
2479 while ((end[0] != ' ') && (end[0] != '\0'))
2480 {
2481 if (end[0] == '\\')
2482 {
2483 switch (end[1])
2484 {
2485 case '\\':
2486 case ' ':
2487 end++;
2488 break;
2489
2490 case '\0':
2491 /* illegal, but just keep it */
2492 break;
2493
2494 default:
2495 /* illegal, but just ignore that there was a '/' */
2496 break;
2497 }
2498 }
2499 end++;
2500 }
2501 old = end[0];
2502 end[0] = '\0';
2503 if (0 == strcmp (pos, match))
2504 {
2505 if (old != '\0')
2506 memmove (pos,
2507 &end[1],
2508 strlen (&end[1]) + 1);
2509 else
2510 {
2511 if (pos != list)
2512 pos[-1] = '\0';
2513 else
2514 pos[0] = '\0';
2515 }
2517 section,
2518 option,
2519 list);
2520 GNUNET_free (list);
2521 GNUNET_free (match);
2522 return GNUNET_OK;
2523 }
2524 if (old == '\0')
2525 break;
2526 end[0] = old;
2527 pos = end + 1;
2528 }
2529 GNUNET_free (list);
2530 GNUNET_free (match);
2531 return GNUNET_NO;
2532}
2533
2534
2538 const char *defaults_d)
2539{
2540 struct CollectFilesContext files_context = {
2541 .files = NULL,
2542 .files_length = 0,
2543 };
2544 enum GNUNET_GenericReturnValue fun_ret;
2545
2546 if (GNUNET_SYSERR ==
2547 GNUNET_DISK_directory_scan (defaults_d,
2549 &files_context))
2550 return GNUNET_SYSERR; /* no configuration at all found */
2551 qsort (files_context.files,
2552 files_context.files_length,
2553 sizeof (char *),
2554 &pstrcmp);
2555 for (unsigned int i = 0; i < files_context.files_length; i++)
2556 {
2557 char *ext;
2558 const char *filename = files_context.files[i];
2559
2560 /* Examine file extension */
2561 ext = strrchr (filename, '.');
2562 if ( (NULL == ext) ||
2563 (0 != strcmp (ext,
2564 ".conf")) )
2565 {
2567 "Skipping file `%s'\n",
2568 filename);
2569 fun_ret = GNUNET_OK;
2570 continue;
2571 }
2573 filename);
2574 if (fun_ret != GNUNET_OK)
2575 break;
2576 }
2577cleanup:
2578 if (files_context.files_length > 0)
2579 {
2580 for (size_t i = 0; i < files_context.files_length; i++)
2581 GNUNET_free (files_context.files[i]);
2582 GNUNET_array_grow (files_context.files,
2583 files_context.files_length,
2584 0);
2585 }
2586 return fun_ret;
2587}
2588
2589
2590char *
2592 const struct GNUNET_OS_ProjectData *pd)
2593{
2594 char *cfg_fn;
2595 const char *xdg = getenv ("XDG_CONFIG_HOME");
2596
2597 if (NULL != xdg)
2598 GNUNET_asprintf (&cfg_fn,
2599 "%s%s%s",
2600 xdg,
2602 pd->config_file);
2603 else
2604 cfg_fn = GNUNET_strdup (pd->user_config_file);
2605
2606 if (GNUNET_OK == GNUNET_DISK_file_test_read (cfg_fn))
2607 return cfg_fn;
2608 GNUNET_free (cfg_fn);
2609
2610 /* Fall back to /etc/ for the default configuration.
2611 Should be okay to use forward slashes here. */
2612
2613 GNUNET_asprintf (&cfg_fn,
2614 "/etc/%s",
2615 pd->config_file);
2616 if (GNUNET_OK ==
2618 return cfg_fn;
2619 GNUNET_free (cfg_fn);
2620
2621 GNUNET_asprintf (&cfg_fn,
2622 "/etc/%s/%s",
2623 pd->project_dirname,
2624 pd->config_file);
2625 if (GNUNET_OK ==
2627 return cfg_fn;
2628
2629 GNUNET_free (cfg_fn);
2630 return NULL;
2631}
2632
2633
2637 const char *filename)
2638{
2639 char *baseconfig;
2640 const char *base_config_varname;
2641
2642 if (cfg->load_called)
2643 {
2644 /* FIXME: Make this a GNUNET_assert later */
2645 GNUNET_break (0);
2647 }
2648 cfg->load_called = true;
2649 if (NULL != filename)
2650 {
2653 }
2654
2655 base_config_varname = cfg->pd->base_config_varname;
2656
2657 if ((NULL != base_config_varname)
2658 && (NULL != (baseconfig = getenv (base_config_varname))))
2659 {
2660 baseconfig = GNUNET_strdup (baseconfig);
2661 }
2662 else
2663 {
2664 char *ipath;
2665
2668 if (NULL == ipath)
2669 {
2670 GNUNET_break (0);
2671 return GNUNET_SYSERR;
2672 }
2673 GNUNET_asprintf (&baseconfig,
2674 "%s%s",
2675 ipath,
2676 "config.d");
2677 GNUNET_free (ipath);
2678 }
2679
2680 {
2681 char *dname = GNUNET_STRINGS_filename_expand (baseconfig);
2682
2683 GNUNET_free (baseconfig);
2684
2685 if ((GNUNET_YES ==
2687 GNUNET_YES)) &&
2688 (GNUNET_SYSERR ==
2690 dname)))
2691 {
2693 "Failed to load base configuration from '%s'\n",
2694 filename);
2695 GNUNET_free (dname);
2696 return GNUNET_SYSERR; /* no configuration at all found */
2697 }
2698 GNUNET_free (dname);
2699 }
2700 if ((NULL != filename) &&
2701 (GNUNET_OK !=
2703 filename)))
2704 {
2705 /* specified configuration not found */
2707 "Failed to load configuration from file '%s'\n",
2708 filename);
2709 return GNUNET_SYSERR;
2710 }
2711 if (((GNUNET_YES !=
2713 "PATHS",
2714 "DEFAULTCONFIG"))) &&
2715 (filename != NULL))
2717 "PATHS",
2718 "DEFAULTCONFIG",
2719 filename);
2720 return GNUNET_OK;
2721}
2722
2723
2732static void
2734 const char *section,
2735 const char *option,
2736 const char *value)
2737{
2738 const struct GNUNET_CONFIGURATION_Handle *cfg = cls;
2739
2740 char *value_fn;
2741 char *fn;
2742
2745 section,
2746 option,
2747 &value_fn));
2748 fn = GNUNET_STRINGS_filename_expand (value_fn);
2749 if (NULL == fn)
2750 fn = value_fn;
2751 else
2752 GNUNET_free (value_fn);
2753 fprintf (stdout,
2754 "%s = %s\n",
2755 option,
2756 fn);
2757 GNUNET_free (fn);
2758}
2759
2760
2769static void
2770print_option (void *cls,
2771 const char *section,
2772 const char *option,
2773 const char *value)
2774{
2775 (void) cls;
2776 (void) section;
2777
2778 fprintf (stdout,
2779 "%s = %s\n",
2780 option,
2781 value);
2782}
2783
2784
2791static void
2793 const char *section)
2794{
2795 (void) cls;
2796 fprintf (stdout,
2797 "%s\n",
2798 section);
2799}
2800
2801
2802void
2804 void *cls,
2805 char *const *args,
2806 const char *cfgfile,
2807 const struct GNUNET_CONFIGURATION_Handle *cfg)
2808{
2809 struct GNUNET_CONFIGURATION_ConfigSettings *cs = cls;
2810 struct GNUNET_CONFIGURATION_Handle *out = NULL;
2811 struct GNUNET_CONFIGURATION_Handle *ncfg = NULL;
2812
2813 (void) args;
2814 if (cs->diagnostics)
2815 {
2816 /* Re-parse the configuration with diagnostics enabled. */
2819 if (GNUNET_OK !=
2821 cfgfile))
2822 {
2823 fprintf (stderr,
2824 _ ("Failed to load config file `%s'"),
2825 cfgfile);
2826 return;
2827 }
2828 cfg = ncfg;
2829 }
2830
2831 if (cs->full)
2832 cs->rewrite = GNUNET_YES;
2833 if (cs->list_sections)
2834 {
2835 fprintf (stderr,
2836 _ ("The following sections are available:\n"));
2839 NULL);
2840 return;
2841 }
2842 if ( (! cs->rewrite) &&
2843 (NULL == cs->section) )
2844 {
2845 char *serialization;
2846
2847 if (! cs->diagnostics)
2848 {
2849 fprintf (stderr,
2850 _ ("%s, %s or %s argument is required\n"),
2851 "--section",
2852 "--list-sections",
2853 "--diagnostics");
2855 return;
2856 }
2858 fprintf (stdout,
2859 "%s",
2860 serialization);
2861 GNUNET_free (serialization);
2862 }
2863 else if ( (NULL != cs->section) &&
2864 (NULL == cs->value) )
2865 {
2866 if (NULL == cs->option)
2867 {
2869 cfg,
2870 cs->section,
2871 cs->is_filename
2873 : &print_option,
2874 (void *) cfg);
2875 }
2876 else
2877 {
2878 char *value;
2879
2880 if (cs->is_filename)
2881 {
2882 if (GNUNET_OK !=
2884 cs->section,
2885 cs->option,
2886 &value))
2887 {
2889 cs->section,
2890 cs->option);
2892 return;
2893 }
2894 }
2895 else
2896 {
2897 if (GNUNET_OK !=
2899 cs->section,
2900 cs->option,
2901 &value))
2902 {
2904 cs->section,
2905 cs->option);
2907 return;
2908 }
2909 }
2910 fprintf (stdout,
2911 "%s\n",
2912 value);
2914 }
2915 }
2916 else if (NULL != cs->section)
2917 {
2918 if (NULL == cs->option)
2919 {
2920 fprintf (stderr,
2921 _ ("--option argument required to set value\n"));
2923 return;
2924 }
2927 cs->section,
2928 cs->option,
2929 cs->value);
2930 cs->rewrite = GNUNET_YES;
2931 }
2932 if (cs->rewrite)
2933 {
2934 char *cfg_fn = NULL;
2935
2936 if (NULL == out)
2938
2939 if (NULL == cfgfile)
2940 {
2941 const char *xdg = getenv ("XDG_CONFIG_HOME");
2942
2943 if (NULL != xdg)
2944 GNUNET_asprintf (&cfg_fn,
2945 "%s%s%s",
2946 xdg,
2948 cfg->pd->config_file);
2949 else
2950 cfg_fn = GNUNET_strdup (cfg->pd->user_config_file);
2951 cfgfile = cfg_fn;
2952 }
2953
2954 if (! cs->full)
2955 {
2956 struct GNUNET_CONFIGURATION_Handle *def;
2957
2959 if (GNUNET_OK !=
2961 NULL))
2962 {
2963 fprintf (stderr,
2964 _ ("failed to load configuration defaults"));
2965 cs->global_ret = 1;
2968 GNUNET_free (cfg_fn);
2969 return;
2970 }
2971 if (GNUNET_OK !=
2973 out,
2974 cfgfile))
2975 cs->global_ret = 2;
2977 }
2978 else
2979 {
2980 if (GNUNET_OK !=
2982 cfgfile))
2983 cs->global_ret = 2;
2984 }
2985 GNUNET_free (cfg_fn);
2986 }
2987 if (NULL != out)
2989 if (NULL != ncfg)
2991}
2992
2993
2994void
2997{
2998 GNUNET_free (cs->option);
2999 GNUNET_free (cs->section);
3000 GNUNET_free (cs->value);
3001}
3002
3003
3004const struct GNUNET_OS_ProjectData *
3006 const struct GNUNET_CONFIGURATION_Handle *cfg)
3007{
3008 return cfg->pd;
3009}
3010
3011
3012/* 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:1248
int GNUNET_DISK_glob(const char *glob_pattern, GNUNET_FileNameCallback callback, void *callback_cls)
Find all files matching a glob pattern.
Definition: disk.c:1011
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:700
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:530
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:225
enum GNUNET_GenericReturnValue GNUNET_DISK_directory_remove(const char *filename)
Remove all files in a directory (rm -rf).
Definition: disk.c:1088
enum GNUNET_GenericReturnValue GNUNET_DISK_directory_test(const char *fil, int is_readable)
Test if fil is a directory and listable.
Definition: disk.c:444
enum GNUNET_GenericReturnValue GNUNET_DISK_file_close(struct GNUNET_DISK_FileHandle *h)
Close an open file.
Definition: disk.c:1322
enum GNUNET_GenericReturnValue GNUNET_DISK_directory_create_for_file(const char *filename)
Create the directory structure for storing a file.
Definition: disk.c:623
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:677
int GNUNET_DISK_directory_scan(const char *dir_name, GNUNET_FileNameCallback callback, void *callback_cls)
Scan a directory for files.
Definition: disk.c:829
@ 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:816
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.