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 onfiguration 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
1247char *
1249 const struct GNUNET_CONFIGURATION_Handle *cfg)
1250{
1251 struct GNUNET_Buffer buf = { 0 };
1252
1254 "#\n# Configuration file diagnostics\n#\n");
1256 "# Entry point: %s\n",
1258 "<none>");
1260 "#\n# Files Loaded:\n");
1261
1262 for (struct ConfigFile *cfil = cfg->loaded_files_head;
1263 NULL != cfil;
1264 cfil = cfil->next)
1265 {
1267 "# ");
1268 for (unsigned int i = 0; i < cfil->level; i++)
1270 "+");
1271 if (0 != cfil->level)
1273 " ");
1274
1276 "%s",
1277 cfil->source_filename);
1278
1279 if (NULL != cfil->hint_restrict_section)
1281 " (%s secret section %s)",
1282 cfil->hint_inaccessible
1283 ? "inaccessible"
1284 : "loaded",
1285 cfil->hint_restrict_section);
1286
1288 "\n");
1289 }
1290
1292 "#\n\n");
1293
1294 for (struct ConfigSection *sec = cfg->sections;
1295 NULL != sec;
1296 sec = sec->next)
1297 {
1298 if (sec->hint_secret_filename)
1300 "# secret section from %s\n# secret file stat %s\n",
1301 sec->hint_secret_filename,
1302 sec->hint_secret_stat);
1303 if (sec->hint_inlined_from_filename)
1304 {
1306 "# inlined from %s:%u\n",
1307 sec->hint_inlined_from_filename,
1308 sec->hint_inlined_from_line);
1309 }
1311 "[%s]\n\n",
1312 sec->name);
1313 if (sec->inaccessible)
1314 {
1316 "# <section contents inaccessible>\n\n\n");
1317 continue;
1318 }
1319 for (struct ConfigEntry *ent = sec->entries;
1320 NULL != ent;
1321 ent = ent->next)
1322 {
1323 if (do_skip (sec->name,
1324 ent->key))
1325 continue;
1326 if (NULL != ent->val)
1327 {
1328 char *pos;
1329 char *val = GNUNET_malloc (strlen (ent->val) * 2 + 1);
1330 strcpy (val, ent->val);
1331 while (NULL != (pos = strstr (val, "\n")))
1332 {
1333 memmove (&pos[2], &pos[1], strlen (&pos[1]));
1334 pos[0] = '\\';
1335 pos[1] = 'n';
1336 }
1337 if (NULL != ent->hint_filename)
1338 {
1340 "# %s:%u\n",
1341 ent->hint_filename,
1342 ent->hint_lineno);
1343 }
1345 "%s = %s\n",
1346 ent->key,
1347 val);
1348 GNUNET_free (val);
1349 }
1350 GNUNET_buffer_write_str (&buf, "\n");
1351 }
1352 GNUNET_buffer_write_str (&buf, "\n");
1353 }
1354 return GNUNET_buffer_reap_str (&buf);
1355}
1356
1357
1361 const char *filename)
1362{
1363 char *fn;
1364 char *cfg_buf;
1365 size_t size;
1366
1368 if (fn == NULL)
1369 return GNUNET_SYSERR;
1371 {
1372 GNUNET_free (fn);
1373 return GNUNET_SYSERR;
1374 }
1376 &size);
1377 {
1378 struct GNUNET_DISK_FileHandle *h;
1379
1388 if (NULL == h)
1389 {
1390 GNUNET_free (fn);
1391 GNUNET_free (cfg_buf);
1392 return GNUNET_SYSERR;
1393 }
1394 if (((ssize_t) size) !=
1396 cfg_buf,
1397 size))
1398 {
1400 "write",
1401 fn);
1403 (void) GNUNET_DISK_directory_remove (fn);
1404 GNUNET_free (fn);
1405 GNUNET_free (cfg_buf);
1406 cfg->dirty = GNUNET_SYSERR; /* last write failed */
1407 return GNUNET_SYSERR;
1408 }
1411 }
1412 GNUNET_free (fn);
1413 GNUNET_free (cfg_buf);
1414 cfg->dirty = GNUNET_NO; /* last write succeeded */
1415 return GNUNET_OK;
1416}
1417
1418
1419void
1421 const struct GNUNET_CONFIGURATION_Handle *cfg,
1423 void *iter_cls)
1424{
1425 for (struct ConfigSection *spos = cfg->sections;
1426 NULL != spos;
1427 spos = spos->next)
1428 for (struct ConfigEntry *epos = spos->entries;
1429 NULL != epos;
1430 epos = epos->next)
1431 if (NULL != epos->val)
1432 iter (iter_cls,
1433 spos->name,
1434 epos->key,
1435 epos->val);
1436}
1437
1438
1439void
1441 const struct GNUNET_CONFIGURATION_Handle *cfg,
1442 const char *section,
1444 void *iter_cls)
1445{
1446 struct ConfigSection *spos;
1447 struct ConfigEntry *epos;
1448
1449 spos = cfg->sections;
1450 while ((spos != NULL) && (0 != strcasecmp (spos->name, section)))
1451 spos = spos->next;
1452 if (NULL == spos)
1453 return;
1454 if (spos->inaccessible)
1455 {
1457 "Section '%s' is marked as inaccessible, because the configuration "
1458 " file that contains the section can't be read.\n",
1459 section);
1460 return;
1461 }
1462 for (epos = spos->entries; NULL != epos; epos = epos->next)
1463 if (NULL != epos->val)
1464 iter (iter_cls, spos->name, epos->key, epos->val);
1465}
1466
1467
1468void
1470 const struct GNUNET_CONFIGURATION_Handle *cfg,
1472 void *iter_cls)
1473{
1474 struct ConfigSection *spos;
1475 struct ConfigSection *next;
1476
1477 next = cfg->sections;
1478 while (next != NULL)
1479 {
1480 spos = next;
1481 next = spos->next;
1482 iter (iter_cls, spos->name);
1483 }
1484}
1485
1486
1487void
1489 const char *section)
1490{
1491 struct ConfigSection *spos;
1492 struct ConfigSection *prev;
1493 struct ConfigEntry *ent;
1494
1495 prev = NULL;
1496 spos = cfg->sections;
1497 while (NULL != spos)
1498 {
1499 if (0 == strcasecmp (section, spos->name))
1500 {
1501 if (NULL == prev)
1502 cfg->sections = spos->next;
1503 else
1504 prev->next = spos->next;
1505 while (NULL != (ent = spos->entries))
1506 {
1507 spos->entries = ent->next;
1508 GNUNET_free (ent->key);
1509 GNUNET_free (ent->val);
1511 GNUNET_free (ent);
1512 cfg->dirty = GNUNET_YES;
1513 }
1514 GNUNET_free (spos->name);
1518 GNUNET_free (spos);
1519 return;
1520 }
1521 prev = spos;
1522 spos = spos->next;
1523 }
1524}
1525
1526
1536static void
1537copy_entry (void *cls,
1538 const char *section,
1539 const char *option,
1540 const char *value)
1541{
1542 struct GNUNET_CONFIGURATION_Handle *dst = cls;
1543
1545 section,
1546 option,
1547 value);
1548}
1549
1550
1553 const struct GNUNET_CONFIGURATION_Handle *cfg)
1554{
1556
1559 &copy_entry,
1560 ret);
1561 return ret;
1562}
1563
1564
1575static void
1577 const char *section,
1578 const char *option,
1579 const char *value)
1580{
1581 struct DiffHandle *dh = cls;
1582 struct ConfigEntry *entNew;
1583
1584 entNew = find_entry (dh->cfg_default, section, option);
1585 if ((NULL != entNew) && (NULL != entNew->val) &&
1586 (0 == strcmp (entNew->val, value)))
1587 return;
1589 section,
1590 option,
1591 value);
1592}
1593
1594
1597 const struct GNUNET_CONFIGURATION_Handle *cfg_default,
1598 const struct GNUNET_CONFIGURATION_Handle *cfg_new)
1599{
1600 struct DiffHandle diffHandle;
1601
1602 GNUNET_break (cfg_default->pd == cfg_new->pd);
1603 diffHandle.cfgDiff = GNUNET_CONFIGURATION_create (cfg_new->pd);
1604 diffHandle.cfg_default = cfg_default;
1607 &diffHandle);
1608 return diffHandle.cfgDiff;
1609}
1610
1611
1615 const struct GNUNET_CONFIGURATION_Handle *cfg_new,
1616 const char *filename)
1617{
1618 int ret;
1619 struct GNUNET_CONFIGURATION_Handle *diff;
1620
1621 diff = GNUNET_CONFIGURATION_get_diff (cfg_default, cfg_new);
1624 return ret;
1625}
1626
1627
1628void
1631 const char *section,
1632 const char *option,
1633 const char *value)
1634{
1635 struct ConfigSection *sec;
1636 struct ConfigEntry *e;
1637 char *nv;
1638
1639 e = find_entry (cfg, section, option);
1640 if (NULL != e)
1641 {
1642 if (NULL == value)
1643 {
1644 GNUNET_free (e->val);
1645 e->val = NULL;
1646 }
1647 else
1648 {
1649 nv = GNUNET_strdup (value);
1650 GNUNET_free (e->val);
1651 e->val = nv;
1652 }
1653 return;
1654 }
1655 sec = find_section (cfg, section);
1656 if (sec == NULL)
1657 {
1658 sec = GNUNET_new (struct ConfigSection);
1659 sec->name = GNUNET_strdup (section);
1660 sec->next = cfg->sections;
1661 cfg->sections = sec;
1662 }
1663 e = GNUNET_new (struct ConfigEntry);
1664 e->key = GNUNET_strdup (option);
1665 e->val = GNUNET_strdup (value);
1666 e->next = sec->entries;
1667 sec->entries = e;
1668}
1669
1670
1671void
1673 const char *section,
1674 const char *option,
1675 unsigned long long number)
1676{
1677 char s[64];
1678
1679 GNUNET_snprintf (s,
1680 64,
1681 "%llu",
1682 number);
1684 section,
1685 option,
1686 s);
1687}
1688
1689
1692 const struct GNUNET_CONFIGURATION_Handle *cfg,
1693 const char *section,
1694 const char *option,
1695 unsigned long long *number)
1696{
1697 struct ConfigEntry *e;
1698 char dummy[2];
1699
1700 if (NULL == (e = find_entry (cfg,
1701 section,
1702 option)))
1703 return GNUNET_NO;
1704 if (NULL == e->val)
1705 return GNUNET_NO;
1706 if (1 != sscanf (e->val,
1707 "%llu%1s",
1708 number,
1709 dummy))
1710 return GNUNET_SYSERR;
1711 return GNUNET_OK;
1712}
1713
1714
1717 const struct GNUNET_CONFIGURATION_Handle *cfg,
1718 const char *section,
1719 const char *option,
1720 float *number)
1721{
1722 struct ConfigEntry *e;
1723 char dummy[2];
1724
1725 if (NULL == (e = find_entry (cfg,
1726 section,
1727 option)))
1728 return GNUNET_NO;
1729 if (NULL == e->val)
1730 return GNUNET_NO;
1731 if (1 != sscanf (e->val,
1732 "%f%1s",
1733 number,
1734 dummy))
1735 return GNUNET_SYSERR;
1736 return GNUNET_OK;
1737}
1738
1739
1742 const struct GNUNET_CONFIGURATION_Handle *cfg,
1743 const char *section,
1744 const char *option,
1745 struct GNUNET_TIME_Relative *time)
1746{
1747 struct ConfigEntry *e;
1748 int ret;
1749
1750 if (NULL == (e = find_entry (cfg,
1751 section,
1752 option)))
1753 return GNUNET_NO;
1754 if (NULL == e->val)
1755 return GNUNET_NO;
1757 time);
1758 if (GNUNET_OK != ret)
1760 section,
1761 option,
1762 _ ("Not a valid relative time specification"));
1763 return ret;
1764}
1765
1766
1769 const struct GNUNET_CONFIGURATION_Handle *cfg,
1770 const char *section,
1771 const char *option,
1772 unsigned long long *size)
1773{
1774 struct ConfigEntry *e;
1775
1776 if (NULL == (e = find_entry (cfg,
1777 section,
1778 option)))
1779 return GNUNET_NO;
1780 if (NULL == e->val)
1781 return GNUNET_NO;
1783 size);
1784}
1785
1786
1799 const struct GNUNET_CONFIGURATION_Handle *cfg,
1800 const char *section,
1801 const char *option,
1802 char **value)
1803{
1804 struct ConfigEntry *e;
1805
1806 if ( (NULL == (e = find_entry (cfg,
1807 section,
1808 option))) ||
1809 (NULL == e->val) )
1810 {
1811 *value = NULL;
1812 return GNUNET_NO;
1813 }
1814 *value = GNUNET_strdup (e->val);
1815 return GNUNET_OK;
1816}
1817
1818
1821 const struct GNUNET_CONFIGURATION_Handle *cfg,
1822 const char *section,
1823 const char *option,
1824 const char *const *choices,
1825 const char **value)
1826{
1827 struct ConfigEntry *e;
1828 unsigned int i;
1829
1830 if (NULL == (e = find_entry (cfg,
1831 section,
1832 option)))
1833 return GNUNET_NO;
1834 for (i = 0; NULL != choices[i]; i++)
1835 if (0 == strcasecmp (choices[i], e->val))
1836 break;
1837 if (NULL == choices[i])
1838 {
1840 _ ("Configuration value '%s' for '%s'"
1841 " in section '%s' is not in set of legal choices\n"),
1842 e->val,
1843 option,
1844 section);
1845 return GNUNET_SYSERR;
1846 }
1847 *value = choices[i];
1848 return GNUNET_OK;
1849}
1850
1851
1854 const char *section,
1855 const char *option,
1856 void *buf,
1857 size_t buf_size)
1858{
1859 char *enc;
1860 int res;
1861 size_t data_size;
1862
1863 if (GNUNET_OK !=
1864 (res =
1866 section,
1867 option,
1868 &enc)))
1869 return res;
1870 data_size = (strlen (enc) * 5) / 8;
1871 if (data_size != buf_size)
1872 {
1873 GNUNET_free (enc);
1874 return GNUNET_SYSERR;
1875 }
1876 if (GNUNET_OK !=
1878 strlen (enc),
1879 buf,
1880 buf_size))
1881 {
1882 GNUNET_free (enc);
1883 return GNUNET_SYSERR;
1884 }
1885 GNUNET_free (enc);
1886 return GNUNET_OK;
1887}
1888
1889
1892 const char *section,
1893 const char *option)
1894{
1895 struct ConfigEntry *e;
1896
1897 if ( (NULL == (e = find_entry (cfg,
1898 section,
1899 option))) ||
1900 (NULL == e->val) )
1901 return GNUNET_NO;
1902 return GNUNET_YES;
1903}
1904
1905
1921static char *
1923 char *orig,
1924 unsigned int depth)
1925{
1926 char *prefix;
1927 char *result;
1928 char *start;
1929 const char *post;
1930 const char *env;
1931 char *def;
1932 char *end;
1933 unsigned int lopen;
1934 char erased_char;
1935 char *erased_pos;
1936 size_t len;
1937
1938 if (NULL == orig)
1939 return NULL;
1940 if (depth > 128)
1941 {
1943 "Recursive expansion suspected, aborting $-expansion for term `%s'\n",
1944 orig);
1945 return orig;
1946 }
1948 "Asked to $-expand %s\n",
1949 orig);
1950 if ('$' != orig[0])
1951 {
1953 "Doesn't start with $ - not expanding\n");
1954 return orig;
1955 }
1956 erased_char = 0;
1957 erased_pos = NULL;
1958 if ('{' == orig[1])
1959 {
1960 start = &orig[2];
1961 lopen = 1;
1962 end = &orig[1];
1963 while (lopen > 0)
1964 {
1965 end++;
1966 switch (*end)
1967 {
1968 case '}':
1969 lopen--;
1970 break;
1971
1972 case '{':
1973 lopen++;
1974 break;
1975
1976 case '\0':
1978 "Missing closing `}' in option `%s'\n",
1979 orig);
1980 return orig;
1981
1982 default:
1983 break;
1984 }
1985 }
1986 erased_char = *end;
1987 erased_pos = end;
1988 *end = '\0';
1989 post = end + 1;
1990 def = strchr (orig, ':');
1991 if (NULL != def)
1992 {
1993 *def = '\0';
1994 def++;
1995 if (('-' == *def) || ('=' == *def))
1996 def++;
1997 def = GNUNET_strdup (def);
1998 }
1999 }
2000 else
2001 {
2002 int i;
2003
2004 start = &orig[1];
2005 def = NULL;
2006 i = 0;
2007 while ( (orig[i] != '/') &&
2008 (orig[i] != '\\') &&
2009 (orig[i] != '\0') &&
2010 (orig[i] != ' ') )
2011 i++;
2012 if (orig[i] == '\0')
2013 {
2014 post = "";
2015 }
2016 else
2017 {
2018 erased_char = orig[i];
2019 erased_pos = &orig[i];
2020 orig[i] = '\0';
2021 post = &orig[i + 1];
2022 }
2023 }
2025 "Split into `%s' and `%s' with default %s\n",
2026 start,
2027 post,
2028 def);
2029 if (GNUNET_OK !=
2031 "PATHS",
2032 start,
2033 &prefix))
2034 {
2035 if (NULL == (env = getenv (start)))
2036 {
2037 /* try default */
2038 def = expand_dollar (cfg,
2039 def,
2040 depth + 1);
2041 env = def;
2042 }
2043 if (NULL == env)
2044 {
2046 if (erased_pos)
2047 *erased_pos = erased_char;
2049 "Failed to expand `%s' in `%s' as it is neither found in [PATHS] nor defined as an environmental variable\n",
2050 start,
2051 orig);
2053 return orig;
2054 }
2056 }
2058 prefix);
2059 if ((erased_pos) && ('}' != erased_char))
2060 {
2061 len = strlen (prefix) + 1;
2062 prefix = GNUNET_realloc (prefix, len + 1);
2063 prefix[len - 1] = erased_char;
2064 prefix[len] = '\0';
2065 }
2066 result = GNUNET_malloc (strlen (prefix) + strlen (post) + 1);
2067 strcpy (result, prefix);
2068 strcat (result, post);
2069 GNUNET_free (def);
2071 GNUNET_free (orig);
2072 return result;
2073}
2074
2075
2076char *
2078 const struct GNUNET_CONFIGURATION_Handle *cfg,
2079 char *orig)
2080{
2081 char *dup;
2082 size_t i;
2083 size_t len;
2084
2085 for (i = 0; '\0' != orig[i]; i++)
2086 {
2087 if ('$' != orig[i])
2088 continue;
2089 dup = GNUNET_strdup (orig + i);
2090 dup = expand_dollar (cfg, dup, 0);
2091 GNUNET_assert (NULL != dup); /* make compiler happy */
2092 len = strlen (dup) + 1;
2093 orig = GNUNET_realloc (orig, i + len);
2094 GNUNET_memcpy (orig + i, dup, len);
2095 GNUNET_free (dup);
2096 }
2097 return orig;
2098}
2099
2100
2103 const struct GNUNET_CONFIGURATION_Handle *cfg,
2104 const char *section,
2105 const char *option,
2106 char **value)
2107{
2108 char *tmp;
2110
2112 section,
2113 option,
2114 &tmp);
2115 if (GNUNET_OK != ret)
2116 {
2118 "Failed to retrieve filename\n");
2119 *value = NULL;
2120 return ret;
2121 }
2123 tmp);
2125 GNUNET_free (tmp);
2126 if (*value == NULL)
2127 return GNUNET_SYSERR;
2128 return GNUNET_OK;
2129}
2130
2131
2134 const struct GNUNET_CONFIGURATION_Handle *cfg,
2135 const char *section,
2136 const char *option)
2137{
2138 static const char *yesno[] = {
2139 "YES",
2140 "NO",
2141 NULL
2142 };
2143 const char *val;
2145
2146 ret =
2148 section,
2149 option,
2150 yesno,
2151 &val);
2152 if (GNUNET_OK != ret)
2153 return ret;
2154 if (val == yesno[0])
2155 return GNUNET_YES;
2156 return GNUNET_NO;
2157}
2158
2159
2160int
2162 const struct GNUNET_CONFIGURATION_Handle *cfg,
2163 const char *section,
2164 const char *option,
2166 void *cb_cls)
2167{
2168 char *list;
2169 char *pos;
2170 char *end;
2171 char old;
2172 int ret;
2173
2174 if (GNUNET_OK !=
2176 section,
2177 option,
2178 &list))
2179 return 0;
2180 GNUNET_assert (list != NULL);
2181 ret = 0;
2182 pos = list;
2183 while (1)
2184 {
2185 while (pos[0] == ' ')
2186 pos++;
2187 if (strlen (pos) == 0)
2188 break;
2189 end = pos + 1;
2190 while ((end[0] != ' ') && (end[0] != '\0'))
2191 {
2192 if (end[0] == '\\')
2193 {
2194 switch (end[1])
2195 {
2196 case '\\':
2197 case ' ':
2198 memmove (end, &end[1], strlen (&end[1]) + 1);
2199
2200 case '\0':
2201 /* illegal, but just keep it */
2202 break;
2203
2204 default:
2205 /* illegal, but just ignore that there was a '/' */
2206 break;
2207 }
2208 }
2209 end++;
2210 }
2211 old = end[0];
2212 end[0] = '\0';
2213 if (strlen (pos) > 0)
2214 {
2215 ret++;
2216 if ( (NULL != cb) &&
2217 (GNUNET_OK != cb (cb_cls,
2218 pos)))
2219 {
2221 break;
2222 }
2223 }
2224 if (old == '\0')
2225 break;
2226 pos = end + 1;
2227 }
2228 GNUNET_free (list);
2229 return ret;
2230}
2231
2232
2239static char *
2240escape_name (const char *value)
2241{
2242 char *escaped;
2243 const char *rpos;
2244 char *wpos;
2245
2246 escaped = GNUNET_malloc (strlen (value) * 2 + 1);
2247 memset (escaped, 0, strlen (value) * 2 + 1);
2248 rpos = value;
2249 wpos = escaped;
2250 while (rpos[0] != '\0')
2251 {
2252 switch (rpos[0])
2253 {
2254 case '\\':
2255 case ' ':
2256 wpos[0] = '\\';
2257 wpos[1] = rpos[0];
2258 wpos += 2;
2259 break;
2260
2261 default:
2262 wpos[0] = rpos[0];
2263 wpos++;
2264 }
2265 rpos++;
2266 }
2267 return escaped;
2268}
2269
2270
2278static enum GNUNET_GenericReturnValue
2279test_match (void *cls, const char *fn)
2280{
2281 const char *of = cls;
2282
2283 return (0 == strcmp (of, fn))
2285 : GNUNET_OK;
2286}
2287
2288
2292 const char *section,
2293 const char *option,
2294 const char *value)
2295{
2296 char *escaped;
2297 char *old;
2298 char *nw;
2299
2300 if (GNUNET_SYSERR ==
2302 section,
2303 option,
2304 &test_match,
2305 (void *) value))
2306 return GNUNET_NO; /* already exists */
2307 if (GNUNET_OK !=
2308 GNUNET_CONFIGURATION_get_value_string (cfg, section, option, &old))
2309 old = GNUNET_strdup ("");
2310 escaped = escape_name (value);
2311 nw = GNUNET_malloc (strlen (old) + strlen (escaped) + 2);
2312 strcpy (nw, old);
2313 if (strlen (old) > 0)
2314 strcat (nw, " ");
2315 strcat (nw, escaped);
2317 section,
2318 option,
2319 nw);
2320 GNUNET_free (old);
2321 GNUNET_free (nw);
2322 GNUNET_free (escaped);
2323 return GNUNET_OK;
2324}
2325
2326
2330 const char *section,
2331 const char *option,
2332 const char *value)
2333{
2334 char *list;
2335 char *pos;
2336 char *end;
2337 char *match;
2338 char old;
2339
2340 if (GNUNET_OK !=
2342 section,
2343 option,
2344 &list))
2345 return GNUNET_NO;
2346 match = escape_name (value);
2347 pos = list;
2348 while (1)
2349 {
2350 while (pos[0] == ' ')
2351 pos++;
2352 if (strlen (pos) == 0)
2353 break;
2354 end = pos + 1;
2355 while ((end[0] != ' ') && (end[0] != '\0'))
2356 {
2357 if (end[0] == '\\')
2358 {
2359 switch (end[1])
2360 {
2361 case '\\':
2362 case ' ':
2363 end++;
2364 break;
2365
2366 case '\0':
2367 /* illegal, but just keep it */
2368 break;
2369
2370 default:
2371 /* illegal, but just ignore that there was a '/' */
2372 break;
2373 }
2374 }
2375 end++;
2376 }
2377 old = end[0];
2378 end[0] = '\0';
2379 if (0 == strcmp (pos, match))
2380 {
2381 if (old != '\0')
2382 memmove (pos,
2383 &end[1],
2384 strlen (&end[1]) + 1);
2385 else
2386 {
2387 if (pos != list)
2388 pos[-1] = '\0';
2389 else
2390 pos[0] = '\0';
2391 }
2393 section,
2394 option,
2395 list);
2396 GNUNET_free (list);
2397 GNUNET_free (match);
2398 return GNUNET_OK;
2399 }
2400 if (old == '\0')
2401 break;
2402 end[0] = old;
2403 pos = end + 1;
2404 }
2405 GNUNET_free (list);
2406 GNUNET_free (match);
2407 return GNUNET_NO;
2408}
2409
2410
2414 const char *defaults_d)
2415{
2416 struct CollectFilesContext files_context = {
2417 .files = NULL,
2418 .files_length = 0,
2419 };
2420 enum GNUNET_GenericReturnValue fun_ret;
2421
2422 if (GNUNET_SYSERR ==
2423 GNUNET_DISK_directory_scan (defaults_d,
2425 &files_context))
2426 return GNUNET_SYSERR; /* no configuration at all found */
2427 qsort (files_context.files,
2428 files_context.files_length,
2429 sizeof (char *),
2430 pstrcmp);
2431 for (unsigned int i = 0; i < files_context.files_length; i++)
2432 {
2433 char *ext;
2434 const char *filename = files_context.files[i];
2435
2436 /* Examine file extension */
2437 ext = strrchr (filename, '.');
2438 if ((NULL == ext) || (0 != strcmp (ext, ".conf")))
2439 {
2441 "Skipping file `%s'\n",
2442 filename);
2443 fun_ret = GNUNET_OK;
2444 goto cleanup;
2445 }
2447 filename);
2448 if (fun_ret != GNUNET_OK)
2449 break;
2450 }
2451cleanup:
2452 if (files_context.files_length > 0)
2453 {
2454 for (size_t i = 0; i < files_context.files_length; i++)
2455 GNUNET_free (files_context.files[i]);
2456 GNUNET_array_grow (files_context.files,
2457 files_context.files_length,
2458 0);
2459 }
2460 return fun_ret;
2461}
2462
2463
2464char *
2466 const struct GNUNET_OS_ProjectData *pd)
2467{
2468 char *cfg_fn;
2469 const char *xdg = getenv ("XDG_CONFIG_HOME");
2470
2471 if (NULL != xdg)
2472 GNUNET_asprintf (&cfg_fn,
2473 "%s%s%s",
2474 xdg,
2476 pd->config_file);
2477 else
2478 cfg_fn = GNUNET_strdup (pd->user_config_file);
2479
2480 if (GNUNET_OK == GNUNET_DISK_file_test_read (cfg_fn))
2481 return cfg_fn;
2482 GNUNET_free (cfg_fn);
2483
2484 /* Fall back to /etc/ for the default configuration.
2485 Should be okay to use forward slashes here. */
2486
2487 GNUNET_asprintf (&cfg_fn,
2488 "/etc/%s",
2489 pd->config_file);
2490 if (GNUNET_OK ==
2492 return cfg_fn;
2493 GNUNET_free (cfg_fn);
2494
2495 GNUNET_asprintf (&cfg_fn,
2496 "/etc/%s/%s",
2497 pd->project_dirname,
2498 pd->config_file);
2499 if (GNUNET_OK ==
2501 return cfg_fn;
2502
2503 GNUNET_free (cfg_fn);
2504 return NULL;
2505}
2506
2507
2511 const char *filename)
2512{
2513 char *baseconfig;
2514 const char *base_config_varname;
2515
2516 if (cfg->load_called)
2517 {
2518 /* FIXME: Make this a GNUNET_assert later */
2519 GNUNET_break (0);
2521 }
2522 cfg->load_called = true;
2523 if (NULL != filename)
2524 {
2527 }
2528
2529 base_config_varname = cfg->pd->base_config_varname;
2530
2531 if ((NULL != base_config_varname)
2532 && (NULL != (baseconfig = getenv (base_config_varname))))
2533 {
2534 baseconfig = GNUNET_strdup (baseconfig);
2535 }
2536 else
2537 {
2538 char *ipath;
2539
2542 if (NULL == ipath)
2543 {
2544 GNUNET_break (0);
2545 return GNUNET_SYSERR;
2546 }
2547 GNUNET_asprintf (&baseconfig,
2548 "%s%s",
2549 ipath,
2550 "config.d");
2551 GNUNET_free (ipath);
2552 }
2553
2554 {
2555 char *dname = GNUNET_STRINGS_filename_expand (baseconfig);
2556
2557 GNUNET_free (baseconfig);
2558
2559 if ((GNUNET_YES ==
2561 GNUNET_YES)) &&
2562 (GNUNET_SYSERR ==
2564 dname)))
2565 {
2567 "Failed to load base configuration from '%s'\n",
2568 filename);
2569 GNUNET_free (dname);
2570 return GNUNET_SYSERR; /* no configuration at all found */
2571 }
2572 GNUNET_free (dname);
2573 }
2574 if ((NULL != filename) &&
2575 (GNUNET_OK !=
2577 filename)))
2578 {
2579 /* specified configuration not found */
2581 "Failed to load configuration from file '%s'\n",
2582 filename);
2583 return GNUNET_SYSERR;
2584 }
2585 if (((GNUNET_YES !=
2587 "PATHS",
2588 "DEFAULTCONFIG"))) &&
2589 (filename != NULL))
2591 "PATHS",
2592 "DEFAULTCONFIG",
2593 filename);
2594 return GNUNET_OK;
2595}
2596
2597
2606static void
2608 const char *section,
2609 const char *option,
2610 const char *value)
2611{
2612 const struct GNUNET_CONFIGURATION_Handle *cfg = cls;
2613
2614 char *value_fn;
2615 char *fn;
2616
2619 section,
2620 option,
2621 &value_fn));
2622 fn = GNUNET_STRINGS_filename_expand (value_fn);
2623 if (NULL == fn)
2624 fn = value_fn;
2625 else
2626 GNUNET_free (value_fn);
2627 fprintf (stdout,
2628 "%s = %s\n",
2629 option,
2630 fn);
2631 GNUNET_free (fn);
2632}
2633
2634
2643static void
2644print_option (void *cls,
2645 const char *section,
2646 const char *option,
2647 const char *value)
2648{
2649 (void) cls;
2650 (void) section;
2651
2652 fprintf (stdout,
2653 "%s = %s\n",
2654 option,
2655 value);
2656}
2657
2658
2665static void
2667 const char *section)
2668{
2669 (void) cls;
2670 fprintf (stdout,
2671 "%s\n",
2672 section);
2673}
2674
2675
2676void
2678 void *cls,
2679 char *const *args,
2680 const char *cfgfile,
2681 const struct GNUNET_CONFIGURATION_Handle *cfg)
2682{
2683 struct GNUNET_CONFIGURATION_ConfigSettings *cs = cls;
2684 struct GNUNET_CONFIGURATION_Handle *out = NULL;
2685 struct GNUNET_CONFIGURATION_Handle *ncfg = NULL;
2686
2687 (void) args;
2688 if (cs->diagnostics)
2689 {
2690 /* Re-parse the configuration with diagnostics enabled. */
2693 if (GNUNET_OK !=
2695 cfgfile))
2696 {
2697 fprintf (stderr,
2698 _ ("Failed to load config file `%s'"),
2699 cfgfile);
2700 return;
2701 }
2702 cfg = ncfg;
2703 }
2704
2705 if (cs->full)
2706 cs->rewrite = GNUNET_YES;
2707 if (cs->list_sections)
2708 {
2709 fprintf (stderr,
2710 _ ("The following sections are available:\n"));
2713 NULL);
2714 return;
2715 }
2716 if ( (! cs->rewrite) &&
2717 (NULL == cs->section) )
2718 {
2719 char *serialization;
2720
2721 if (! cs->diagnostics)
2722 {
2723 fprintf (stderr,
2724 _ ("%s, %s or %s argument is required\n"),
2725 "--section",
2726 "--list-sections",
2727 "--diagnostics");
2729 return;
2730 }
2732 fprintf (stdout,
2733 "%s",
2734 serialization);
2735 GNUNET_free (serialization);
2736 }
2737 else if ( (NULL != cs->section) &&
2738 (NULL == cs->value) )
2739 {
2740 if (NULL == cs->option)
2741 {
2743 cfg,
2744 cs->section,
2745 cs->is_filename
2747 : &print_option,
2748 (void *) cfg);
2749 }
2750 else
2751 {
2752 char *value;
2753
2754 if (cs->is_filename)
2755 {
2756 if (GNUNET_OK !=
2758 cs->section,
2759 cs->option,
2760 &value))
2761 {
2763 cs->section,
2764 cs->option);
2766 return;
2767 }
2768 }
2769 else
2770 {
2771 if (GNUNET_OK !=
2773 cs->section,
2774 cs->option,
2775 &value))
2776 {
2778 cs->section,
2779 cs->option);
2781 return;
2782 }
2783 }
2784 fprintf (stdout,
2785 "%s\n",
2786 value);
2788 }
2789 }
2790 else if (NULL != cs->section)
2791 {
2792 if (NULL == cs->option)
2793 {
2794 fprintf (stderr,
2795 _ ("--option argument required to set value\n"));
2797 return;
2798 }
2801 cs->section,
2802 cs->option,
2803 cs->value);
2804 cs->rewrite = GNUNET_YES;
2805 }
2806 if (cs->rewrite)
2807 {
2808 char *cfg_fn = NULL;
2809
2810 if (NULL == out)
2812
2813 if (NULL == cfgfile)
2814 {
2815 const char *xdg = getenv ("XDG_CONFIG_HOME");
2816
2817 if (NULL != xdg)
2818 GNUNET_asprintf (&cfg_fn,
2819 "%s%s%s",
2820 xdg,
2822 cfg->pd->config_file);
2823 else
2824 cfg_fn = GNUNET_strdup (cfg->pd->user_config_file);
2825 cfgfile = cfg_fn;
2826 }
2827
2828 if (! cs->full)
2829 {
2830 struct GNUNET_CONFIGURATION_Handle *def;
2831
2833 if (GNUNET_OK !=
2835 NULL))
2836 {
2837 fprintf (stderr,
2838 _ ("failed to load configuration defaults"));
2839 cs->global_ret = 1;
2842 GNUNET_free (cfg_fn);
2843 return;
2844 }
2845 if (GNUNET_OK !=
2847 out,
2848 cfgfile))
2849 cs->global_ret = 2;
2851 }
2852 else
2853 {
2854 if (GNUNET_OK !=
2856 cfgfile))
2857 cs->global_ret = 2;
2858 }
2859 GNUNET_free (cfg_fn);
2860 }
2861 if (NULL != out)
2863 if (NULL != ncfg)
2865}
2866
2867
2868void
2871{
2872 GNUNET_free (cs->option);
2873 GNUNET_free (cs->section);
2874 GNUNET_free (cs->value);
2875}
2876
2877
2878const struct GNUNET_OS_ProjectData *
2880 const struct GNUNET_CONFIGURATION_Handle *cfg)
2881{
2882 return cfg->pd;
2883}
2884
2885
2886/* 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 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:130
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...
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:1215
int GNUNET_DISK_glob(const char *glob_pattern, GNUNET_FileNameCallback callback, void *callback_cls)
Find all files matching a glob pattern.
Definition: disk.c:988
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:682
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:513
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:1065
enum GNUNET_GenericReturnValue GNUNET_DISK_directory_test(const char *fil, int is_readable)
Test if fil is a directory and listable.
Definition: disk.c:427
enum GNUNET_GenericReturnValue GNUNET_DISK_file_close(struct GNUNET_DISK_FileHandle *h)
Close an open file.
Definition: disk.c:1289
enum GNUNET_GenericReturnValue GNUNET_DISK_directory_create_for_file(const char *filename)
Create the directory structure for storing a file.
Definition: disk.c:606
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:660
int GNUNET_DISK_directory_scan(const char *dir_name, GNUNET_FileNameCallback callback, void *callback_cls)
Scan a directory for files.
Definition: disk.c:811
@ 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_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:166
#define _(String)
GNU gettext support macro.
Definition: platform.h:178
#define SIZE_MAX
Definition: platform.h:208
#define EXIT_INVALIDARGUMENT
Definition: platform.h:253
#define EXIT_NOTCONFIGURED
Definition: platform.h:269
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.