GNUnet 0.26.2-125-g53de64302
 
Loading...
Searching...
No Matches
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, 2026 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
115
117{
122
126 unsigned int level;
127
129
131
137
142};
143
144
204
205
216
217
218void
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
683 if (NULL == (sec = find_section (cfg,
684 section)))
685 return NULL;
686 for (struct ConfigEntry *pos = sec->entries;
687 pos != NULL;
688 pos = pos->next)
689 if (0 == strcasecmp (key,
690 pos->key))
691 return pos;
692 if (sec->inaccessible)
693 {
695 "Section '%s' is marked as inaccessible, because the configuration "
696 "file that contains the section can't be read. Attempts to use "
697 "option '%s' will fail.\n",
698 section,
699 key);
700 return NULL;
701 }
702 return NULL;
703}
704
705
715static void
717 const char *section,
718 const char *option,
719 const char *hint_filename,
720 unsigned int hint_line)
721{
722 struct ConfigEntry *e = find_entry (cfg, section, option);
723 if (! cfg->diagnostics)
724 return;
725 if (! e)
726 return;
728 e->hint_lineno = hint_line;
729}
730
731
734 const char *mem,
735 size_t size,
736 const char *source_filename)
737{
738 size_t line_size;
739 unsigned int nr;
740 size_t r_bytes;
741 size_t to_read;
743 char *section;
744 char *eq;
745 char *tag;
746 char *value;
747 char *line_orig = NULL;
748
749 ret = GNUNET_OK;
750 section = NULL;
751 nr = 0;
752 r_bytes = 0;
753 while (r_bytes < size)
754 {
755 const char *pos;
756 char *line;
757 bool emptyline;
758
759 GNUNET_free (line_orig);
760 /* fgets-like behaviour on buffer */
761 to_read = size - r_bytes;
762 pos = memchr (&mem[r_bytes], '\n', to_read);
763 if (NULL == pos)
764 {
765 line_orig = GNUNET_strndup (&mem[r_bytes],
766 line_size = to_read);
767 r_bytes += line_size;
768 }
769 else
770 {
771 line_orig = GNUNET_strndup (&mem[r_bytes],
772 line_size = (pos - &mem[r_bytes]));
773 r_bytes += line_size + 1;
774 }
775 line = line_orig;
776 /* increment line number */
777 nr++;
778 /* tabs and '\r' are whitespace */
779 emptyline = GNUNET_YES;
780 for (size_t i = 0; i < line_size; i++)
781 {
782 if (line[i] == '\t')
783 line[i] = ' ';
784 if (line[i] == '\r')
785 line[i] = ' ';
786 if (' ' != line[i])
787 emptyline = GNUNET_NO;
788 }
789 /* ignore empty lines */
790 if (GNUNET_YES == emptyline)
791 continue;
792
793 /* remove tailing whitespace */
794 for (size_t i = line_size - 1;
795 (i >= 1) && (isspace ((unsigned char) line[i]));
796 i--)
797 line[i] = '\0';
798
799 /* remove leading whitespace */
800 for (; line[0] != '\0' && (isspace ((unsigned char) line[0])); line++)
801 ;
802
803 /* ignore comments */
804 if ( ('#' == line[0]) ||
805 ('%' == line[0]) )
806 continue;
807
808 /* Handle special directives. */
809 if ('@' == line[0])
810 {
811 char *end = strchr (line + 1, '@');
812 char *directive;
813 enum GNUNET_GenericReturnValue directive_ret;
814
815 if (NULL != cfg->restrict_section)
816 {
818 "Illegal directive in line %u (parsing restricted section %s)\n",
819 nr,
822 break;
823 }
824
825 if (NULL == end)
826 {
828 "Bad directive in line %u\n",
829 nr);
831 break;
832 }
833 *end = '\0';
834 directive = line + 1;
835
836 if (0 == strcasecmp (directive,
837 "INLINE"))
838 {
839 const char *path = end + 1;
840
841 /* Skip space before path */
842 for (; isspace (*path); path++)
843 ;
844
845 directive_ret = handle_inline (cfg,
846 path,
847 false,
848 NULL,
849 source_filename,
850 nr);
851 }
852 else if (0 == strcasecmp (directive,
853 "INLINE-MATCHING"))
854 {
855 const char *path = end + 1;
856
857 /* Skip space before path */
858 for (; isspace (*path); path++)
859 ;
860
861 directive_ret = handle_inline (cfg,
862 path,
863 true,
864 NULL,
865 source_filename,
866 nr);
867 }
868 else if (0 == strcasecmp (directive,
869 "INLINE-SECRET"))
870 {
871 char *secname = end + 1;
872 char *secname_end;
873 const char *path;
874
875 /* Skip space before secname */
876 for (; isspace (*secname); secname++)
877 ;
878
879 secname_end = strchr (secname, ' ');
880
881 if (NULL == secname_end)
882 {
884 "Bad inline-secret directive in line %u\n",
885 nr);
887 break;
888 }
889 *secname_end = '\0';
890 path = secname_end + 1;
891
892 /* Skip space before path */
893 for (; isspace (*path); path++)
894 ;
895
896 directive_ret = handle_inline (cfg,
897 path,
898 false,
899 secname,
900 source_filename,
901 nr);
902 }
903 else
904 {
906 "Unknown or malformed directive '%s' in line %u\n",
907 directive,
908 nr);
910 break;
911 }
912 if (GNUNET_OK != directive_ret)
913 {
914 ret = directive_ret;
915 break;
916 }
917 continue;
918 }
919 if ( ('[' == line[0]) &&
920 (']' == line[line_size - 1]) )
921 {
922 /* [value] */
923 line[line_size - 1] = '\0';
924 value = &line[1];
925 GNUNET_free (section);
926 section = GNUNET_strdup (value);
927 continue;
928 }
929 if (NULL != (eq = strchr (line, '=')))
930 {
931
932 if (NULL == section)
933 {
935 "Syntax error while deserializing in line %u (option without section)\n",
936 nr);
938 break;
939 }
940
941 /* tag = value */
942 tag = GNUNET_strndup (line, eq - line);
943 /* remove tailing whitespace */
944 for (int i = strlen (tag) - 1;
945 (i >= 1) && (isspace ((unsigned char) tag[i]));
946 i--)
947 tag[i] = '\0';
948
949 /* Strip whitespace */
950 value = eq + 1;
951 while (isspace ((unsigned char) value[0]))
952 value++;
953 for (int i = strlen (value) - 1;
954 (i >= 1) && (isspace ((unsigned char) value[i]));
955 i--)
956 value[i] = '\0';
957
958 /* remove quotes */
959 if ( ('"' == value[0]) &&
960 ('"' == value[strlen (value) - 1]) )
961 {
962 value[strlen (value) - 1] = '\0';
963 value++;
964 }
966 section,
967 tag,
968 value);
969 if (cfg->diagnostics)
970 {
972 section,
973 tag,
974 source_filename
975 ? source_filename
976 : "<input>",
977 nr);
978 }
979 GNUNET_free (tag);
980 continue;
981 }
982 /* parse error */
984 "Syntax error while deserializing in line %u\n",
985 nr);
987 break;
988 }
989 GNUNET_free (line_orig);
990 GNUNET_free (section);
991 GNUNET_assert ( (GNUNET_OK != ret) ||
992 (r_bytes == size) );
993 return ret;
994}
995
996
999 const char *filename)
1000{
1001 uint64_t fs64;
1002 size_t fs;
1003 char *fn;
1004 char *mem;
1005 int dirty;
1007 ssize_t sret;
1008
1011 "Asked to parse config file `%s'\n",
1012 fn);
1013 if (NULL == fn)
1014 return GNUNET_SYSERR;
1015
1016
1017 /* Check for cycles */
1018 {
1019 unsigned int lvl = cfg->current_nest_level;
1020 struct ConfigFile *cf = cfg->loaded_files_tail;
1021 struct ConfigFile *parent = NULL;
1022
1023
1024 for (; NULL != cf; parent = cf, cf = cf->prev)
1025 {
1026 /* Check parents based on level, skipping children of siblings. */
1027 if (cf->level >= lvl)
1028 continue;
1029 lvl = cf->level;
1030 if ( (NULL == cf->source_filename) ||
1031 (NULL == filename) )
1032 continue;
1033 if (0 == strcmp (cf->source_filename,
1034 filename))
1035 {
1036 if (NULL == parent)
1037 {
1039 "Forbidden direct cyclic configuration import (%s -> %s)\n",
1040 cf->source_filename,
1041 filename);
1042 }
1043 else
1045 "Forbidden indirect cyclic configuration import (%s -> ... -> %s -> %s)\n",
1046 cf->source_filename,
1047 parent->source_filename,
1048 filename);
1049 GNUNET_free (fn);
1050 return GNUNET_SYSERR;
1051 }
1052 }
1053
1054 }
1055
1056 /* Keep track of loaded files.*/
1057 {
1058 struct ConfigFile *cf = GNUNET_new (struct ConfigFile);
1059
1061 cf->source_filename = GNUNET_strdup (filename ? filename : "<input>");
1064 cf);
1065 }
1066
1067 dirty = cfg->dirty; /* back up value! */
1068 if (GNUNET_SYSERR ==
1070 &fs64,
1071 GNUNET_NO,
1072 GNUNET_YES))
1073 {
1075 "Error while determining the file size of `%s'\n",
1076 fn);
1077 GNUNET_free (fn);
1078 return GNUNET_SYSERR;
1079 }
1080 if (fs64 > SIZE_MAX)
1081 {
1082 GNUNET_break (0); /* File size is more than the heap size */
1083 GNUNET_free (fn);
1084 return GNUNET_SYSERR;
1085 }
1086 fs = fs64;
1087 mem = GNUNET_malloc (fs);
1088 sret = GNUNET_DISK_fn_read (fn,
1089 mem,
1090 fs);
1091 if ((sret < 0) || (fs != (size_t) sret))
1092 {
1094 "Error while reading file `%s'\n",
1095 fn);
1096 GNUNET_free (fn);
1097 GNUNET_free (mem);
1098 return GNUNET_SYSERR;
1099 }
1101 "Deserializing contents of file `%s'\n",
1102 fn);
1104 mem,
1105 fs,
1106 fn);
1107 if (GNUNET_SYSERR == ret)
1108 {
1110 _ ("Failed to parse configuration file `%s'\n"),
1111 fn);
1112 }
1113 GNUNET_free (fn);
1114 GNUNET_free (mem);
1115 /* restore dirty flag - anything we set in the meantime
1116 * came from disk */
1117 cfg->dirty = dirty;
1118 return ret;
1119}
1120
1121
1127
1128
1136static bool
1137do_skip (const char *sec,
1138 const char *key)
1139{
1140 if (0 != strcasecmp ("PATHS",
1141 sec))
1142 return false;
1143 return ( (0 == strcasecmp ("DATADIR",
1144 key)) ||
1145 (0 == strcasecmp ("LIBDIR",
1146 key)) ||
1147 (0 == strcasecmp ("BINDIR",
1148 key)) ||
1149 (0 == strcasecmp ("PREFIX",
1150 key)) ||
1151 (0 == strcasecmp ("LOCALEDIR",
1152 key)) ||
1153 (0 == strcasecmp ("ICONDIR",
1154 key)) ||
1155 (0 == strcasecmp ("DOCDIR",
1156 key)) ||
1157 (0 == strcasecmp ("DEFAULTCONFIG",
1158 key)) ||
1159 (0 == strcasecmp ("LIBEXECDIR",
1160 key)) );
1161}
1162
1163
1164char *
1166 size_t *size)
1167{
1168 char *mem;
1169 char *cbuf;
1170 char *val;
1171 char *pos;
1172 size_t m_size;
1173 size_t c_size;
1174
1175 /* Pass1 : calculate the buffer size required */
1176 m_size = 0;
1177 for (struct ConfigSection *sec = cfg->sections;
1178 NULL != sec;
1179 sec = sec->next)
1180 {
1181 if (sec->inaccessible && (NULL == sec->entries))
1182 continue;
1183 /* For each section we need to add 3 characters: {'[',']','\n'} */
1184 m_size += strlen (sec->name) + 3;
1185 for (struct ConfigEntry *ent = sec->entries;
1186 NULL != ent;
1187 ent = ent->next)
1188 {
1189 if (do_skip (sec->name,
1190 ent->key))
1191 continue;
1192 if (NULL != ent->val)
1193 {
1194 /* if val has any '\n' then they occupy +1 character as '\n'->'\\','n' */
1195 pos = ent->val;
1196 while (NULL != (pos = strstr (pos, "\n")))
1197 {
1198 m_size++;
1199 pos++;
1200 }
1201 /* For each key = value pair we need to add 4 characters (2
1202 spaces and 1 equal-to character and 1 new line) */
1203 m_size += strlen (ent->key) + strlen (ent->val) + 4;
1204 }
1205 }
1206 /* A new line after section end */
1207 m_size++;
1208 }
1209
1210 /* Pass2: Allocate memory and write the configuration to it */
1211 mem = GNUNET_malloc (m_size);
1212 c_size = 0;
1213 *size = c_size;
1214 for (struct ConfigSection *sec = cfg->sections;
1215 NULL != sec;
1216 sec = sec->next)
1217 {
1218 int len;
1219
1220 len = GNUNET_asprintf (&cbuf,
1221 "[%s]\n",
1222 sec->name);
1223 GNUNET_assert (0 < len);
1224 GNUNET_memcpy (mem + c_size,
1225 cbuf,
1226 len);
1227 c_size += len;
1228 GNUNET_free (cbuf);
1229 for (struct ConfigEntry *ent = sec->entries;
1230 NULL != ent;
1231 ent = ent->next)
1232 {
1233 if (do_skip (sec->name,
1234 ent->key))
1235 continue;
1236 if (NULL != ent->val)
1237 {
1238 val = GNUNET_malloc (strlen (ent->val) * 2 + 1);
1239 strcpy (val, ent->val);
1240 while (NULL != (pos = strstr (val, "\n")))
1241 {
1242 memmove (&pos[2], &pos[1], strlen (&pos[1]));
1243 pos[0] = '\\';
1244 pos[1] = 'n';
1245 }
1246 len = GNUNET_asprintf (&cbuf, "%s = %s\n", ent->key, val);
1247 GNUNET_free (val);
1248 GNUNET_memcpy (mem + c_size, cbuf, len);
1249 c_size += len;
1250 GNUNET_free (cbuf);
1251 }
1252 }
1253 GNUNET_memcpy (mem + c_size, "\n", 1);
1254 c_size++;
1255 }
1256 GNUNET_assert (c_size == m_size);
1257 *size = c_size;
1258 return mem;
1259}
1260
1261
1270static void
1272 const struct GNUNET_CONFIGURATION_Handle *cfg,
1273 struct GNUNET_Buffer *buf,
1275{
1277 ipk);
1278 const char *ipkname;
1279 switch (ipk)
1280 {
1282 ipkname = "IPK_DATADIR";
1283 break;
1285 ipkname = "IPK_BINDIR";
1286 break;
1288 ipkname = "IPK_LIBDIR";
1289 break;
1291 ipkname = "IPK_PREFIX";
1293 ipkname = "IPK_LOCALEDIR";
1294 break;
1296 ipkname = "IPK_ICONDIR";
1298 ipkname = "IPK_DOCDIR";
1299 break;
1301 ipkname = "IPK_LIBEXECDIR";
1302 break;
1304 ipkname = "IPK_SELF_PREFIX";
1305 break;
1306 default:
1307 ipkname = "??";
1308 break;
1309 }
1311 "# %s = %s\n",
1312 ipkname,
1313 v);
1314 GNUNET_free (v);
1315}
1316
1317
1318char *
1320 const struct GNUNET_CONFIGURATION_Handle *cfg)
1321{
1322 struct GNUNET_Buffer buf = { 0 };
1323
1325 "#\n# Configuration file diagnostics\n#\n");
1327 "# Entry point: %s\n",
1329 "<none>");
1331 "#\n# Files Loaded:\n");
1332
1333 for (struct ConfigFile *cfil = cfg->loaded_files_head;
1334 NULL != cfil;
1335 cfil = cfil->next)
1336 {
1338 "# ");
1339 for (unsigned int i = 0; i < cfil->level; i++)
1341 "+");
1342 if (0 != cfil->level)
1344 " ");
1345
1347 "%s",
1348 cfil->source_filename);
1349
1350 if (NULL != cfil->hint_restrict_section)
1352 " (%s secret section %s)",
1353 cfil->hint_inaccessible
1354 ? "inaccessible"
1355 : "loaded",
1356 cfil->hint_restrict_section);
1357
1359 "\n");
1360 }
1361
1363 "#\n# Installation paths:\n");
1364
1374
1375
1377 "#\n\n");
1378
1379 for (struct ConfigSection *sec = cfg->sections;
1380 NULL != sec;
1381 sec = sec->next)
1382 {
1383 if (sec->hint_secret_filename)
1385 "# secret section from %s\n# secret file stat %s\n",
1386 sec->hint_secret_filename,
1387 sec->hint_secret_stat);
1388 if (sec->hint_inlined_from_filename)
1389 {
1391 "# inlined from %s:%u\n",
1392 sec->hint_inlined_from_filename,
1393 sec->hint_inlined_from_line);
1394 }
1396 "[%s]\n\n",
1397 sec->name);
1398 if (sec->inaccessible && (NULL == sec->entries))
1399 {
1401 "# <section contents inaccessible>\n\n\n");
1402 continue;
1403 }
1404 for (struct ConfigEntry *ent = sec->entries;
1405 NULL != ent;
1406 ent = ent->next)
1407 {
1408 if (do_skip (sec->name,
1409 ent->key))
1410 continue;
1411 if (NULL != ent->val)
1412 {
1413 char *pos;
1414 char *val = GNUNET_malloc (strlen (ent->val) * 2 + 1);
1415 strcpy (val, ent->val);
1416 while (NULL != (pos = strstr (val, "\n")))
1417 {
1418 memmove (&pos[2], &pos[1], strlen (&pos[1]));
1419 pos[0] = '\\';
1420 pos[1] = 'n';
1421 }
1422 if (NULL != ent->hint_filename)
1423 {
1425 "# %s:%u\n",
1426 ent->hint_filename,
1427 ent->hint_lineno);
1428 }
1430 "%s = %s\n",
1431 ent->key,
1432 val);
1433 GNUNET_free (val);
1434 }
1435 GNUNET_buffer_write_str (&buf, "\n");
1436 }
1437 if (sec->inaccessible)
1438 {
1440 "# <additional section contents inaccessible>\n\n\n");
1441 continue;
1442 }
1443
1444 GNUNET_buffer_write_str (&buf, "\n");
1445 }
1446 return GNUNET_buffer_reap_str (&buf);
1447}
1448
1449
1453 const char *filename)
1454{
1455 char *fn;
1456 char *cfg_buf;
1457 size_t size;
1458
1460 if (fn == NULL)
1461 return GNUNET_SYSERR;
1463 {
1464 GNUNET_free (fn);
1465 return GNUNET_SYSERR;
1466 }
1468 &size);
1469 {
1470 struct GNUNET_DISK_FileHandle *h;
1471
1480 if (NULL == h)
1481 {
1482 GNUNET_free (fn);
1483 GNUNET_free (cfg_buf);
1484 return GNUNET_SYSERR;
1485 }
1486 if (((ssize_t) size) !=
1488 cfg_buf,
1489 size))
1490 {
1492 "write",
1493 fn);
1495 (void) GNUNET_DISK_directory_remove (fn);
1496 GNUNET_free (fn);
1497 GNUNET_free (cfg_buf);
1498 cfg->dirty = GNUNET_SYSERR; /* last write failed */
1499 return GNUNET_SYSERR;
1500 }
1503 }
1504 GNUNET_free (fn);
1505 GNUNET_free (cfg_buf);
1506 cfg->dirty = GNUNET_NO; /* last write succeeded */
1507 return GNUNET_OK;
1508}
1509
1510
1511void
1513 const struct GNUNET_CONFIGURATION_Handle *cfg,
1515 void *iter_cls)
1516{
1517 for (struct ConfigSection *spos = cfg->sections;
1518 NULL != spos;
1519 spos = spos->next)
1520 for (struct ConfigEntry *epos = spos->entries;
1521 NULL != epos;
1522 epos = epos->next)
1523 if (NULL != epos->val)
1524 iter (iter_cls,
1525 spos->name,
1526 epos->key,
1527 epos->val);
1528}
1529
1530
1531void
1533 const struct GNUNET_CONFIGURATION_Handle *cfg,
1534 const char *section,
1536 void *iter_cls)
1537{
1538 struct ConfigSection *spos;
1539
1540 spos = cfg->sections;
1541 while ((spos != NULL) && (0 != strcasecmp (spos->name, section)))
1542 spos = spos->next;
1543 if (NULL == spos)
1544 return;
1545 for (struct ConfigEntry *epos = spos->entries;
1546 NULL != epos;
1547 epos = epos->next)
1548 if (NULL != epos->val)
1549 iter (iter_cls,
1550 spos->name,
1551 epos->key,
1552 epos->val);
1553 if (spos->inaccessible)
1554 {
1556 "Section '%s' is marked as inaccessible, because a configuration "
1557 "file that contains the section can't be read.\n",
1558 section);
1559 return;
1560 }
1561}
1562
1563
1564void
1566 const struct GNUNET_CONFIGURATION_Handle *cfg,
1568 void *iter_cls)
1569{
1570 struct ConfigSection *spos;
1571 struct ConfigSection *next;
1572
1573 next = cfg->sections;
1574 while (NULL != next)
1575 {
1576 spos = next;
1577 next = spos->next;
1578 if (spos->inaccessible && (NULL == spos->entries))
1579 continue;
1580 iter (iter_cls,
1581 spos->name);
1582 }
1583}
1584
1585
1586void
1588 const char *section)
1589{
1590 struct ConfigSection *spos;
1591 struct ConfigSection *prev;
1592 struct ConfigEntry *ent;
1593
1594 prev = NULL;
1595 spos = cfg->sections;
1596 while (NULL != spos)
1597 {
1598 if (0 == strcasecmp (section,
1599 spos->name))
1600 {
1601 if (NULL == prev)
1602 cfg->sections = spos->next;
1603 else
1604 prev->next = spos->next;
1605 while (NULL != (ent = spos->entries))
1606 {
1607 spos->entries = ent->next;
1608 GNUNET_free (ent->key);
1609 GNUNET_free (ent->val);
1611 GNUNET_free (ent);
1612 cfg->dirty = GNUNET_YES;
1613 }
1614 GNUNET_free (spos->name);
1618 GNUNET_free (spos);
1619 return;
1620 }
1621 prev = spos;
1622 spos = spos->next;
1623 }
1624}
1625
1626
1636static void
1637copy_entry (void *cls,
1638 const char *section,
1639 const char *option,
1640 const char *value)
1641{
1642 struct GNUNET_CONFIGURATION_Handle *dst = cls;
1643
1645 section,
1646 option,
1647 value);
1648}
1649
1650
1663
1664
1675static void
1677 const char *section,
1678 const char *option,
1679 const char *value)
1680{
1681 struct DiffHandle *dh = cls;
1682 struct ConfigEntry *entNew;
1683
1684 entNew = find_entry (dh->cfg_default, section, option);
1685 if ((NULL != entNew) && (NULL != entNew->val) &&
1686 (0 == strcmp (entNew->val, value)))
1687 return;
1689 section,
1690 option,
1691 value);
1692}
1693
1694
1697 const struct GNUNET_CONFIGURATION_Handle *cfg_default,
1698 const struct GNUNET_CONFIGURATION_Handle *cfg_new)
1699{
1700 struct DiffHandle diffHandle;
1701
1702 GNUNET_break (cfg_default->pd == cfg_new->pd);
1703 diffHandle.cfgDiff = GNUNET_CONFIGURATION_create (cfg_new->pd);
1704 diffHandle.cfg_default = cfg_default;
1707 &diffHandle);
1708 return diffHandle.cfgDiff;
1709}
1710
1711
1715 const struct GNUNET_CONFIGURATION_Handle *cfg_new,
1716 const char *filename)
1717{
1718 int ret;
1719 struct GNUNET_CONFIGURATION_Handle *diff;
1720
1721 diff = GNUNET_CONFIGURATION_get_diff (cfg_default, cfg_new);
1724 return ret;
1725}
1726
1727
1728void
1731 const char *section,
1732 const char *option,
1733 const char *value)
1734{
1735 struct ConfigSection *sec;
1736 struct ConfigEntry *e;
1737 char *nv;
1738
1739 e = find_entry (cfg, section, option);
1740 if (NULL != e)
1741 {
1742 if (NULL == value)
1743 {
1744 GNUNET_free (e->val);
1745 e->val = NULL;
1746 }
1747 else
1748 {
1749 nv = GNUNET_strdup (value);
1750 GNUNET_free (e->val);
1751 e->val = nv;
1752 }
1753 return;
1754 }
1755 sec = find_section (cfg, section);
1756 if (sec == NULL)
1757 {
1758 sec = GNUNET_new (struct ConfigSection);
1759 sec->name = GNUNET_strdup (section);
1760 sec->next = cfg->sections;
1761 cfg->sections = sec;
1762 }
1763 e = GNUNET_new (struct ConfigEntry);
1764 e->key = GNUNET_strdup (option);
1765 e->val = GNUNET_strdup (value);
1766 e->next = sec->entries;
1767 sec->entries = e;
1768}
1769
1770
1771void
1773 const char *section,
1774 const char *option,
1775 unsigned long long number)
1776{
1777 char s[64];
1778
1779 GNUNET_snprintf (s,
1780 64,
1781 "%llu",
1782 number);
1784 section,
1785 option,
1786 s);
1787}
1788
1789
1792 const struct GNUNET_CONFIGURATION_Handle *cfg,
1793 const char *section,
1794 const char *option,
1795 unsigned long long *number)
1796{
1797 struct ConfigEntry *e;
1798 char dummy[2];
1799
1800 if (NULL == (e = find_entry (cfg,
1801 section,
1802 option)))
1803 return GNUNET_NO;
1804 if (NULL == e->val)
1805 return GNUNET_NO;
1806 if (1 != sscanf (e->val,
1807 "%llu%1s",
1808 number,
1809 dummy))
1810 return GNUNET_SYSERR;
1811 return GNUNET_OK;
1812}
1813
1814
1815void
1817 const char *section,
1818 const char *option,
1819 float number)
1820{
1821 char s[64];
1822
1823 /* See: #9369 */
1824 const locale_t cl = newlocale (LC_NUMERIC_MASK,
1825 "C",
1826 (locale_t) 0);
1827 locale_t old_locale = uselocale (cl);
1828 GNUNET_snprintf (s,
1829 64,
1830 "%f",
1831 (double) number);
1832 uselocale (old_locale);
1834 section,
1835 option,
1836 s);
1837}
1838
1839
1842 const struct GNUNET_CONFIGURATION_Handle *cfg,
1843 const char *section,
1844 const char *option,
1845 float *number)
1846{
1847 struct ConfigEntry *e;
1848 char dummy[2];
1849
1850 if (NULL == (e = find_entry (cfg,
1851 section,
1852 option)))
1853 return GNUNET_NO;
1854 if (NULL == e->val)
1855 return GNUNET_NO;
1856 /* See #9369 */
1857 {
1858 const locale_t cl = newlocale (LC_NUMERIC_MASK,
1859 "C",
1860 (locale_t) 0);
1861 locale_t old_locale = uselocale (cl);
1862
1863 if (1 != sscanf (e->val,
1864 "%f%1s",
1865 number,
1866 dummy))
1867 return GNUNET_SYSERR;
1868 uselocale (old_locale);
1869 }
1870 return GNUNET_OK;
1871}
1872
1873
1876 const struct GNUNET_CONFIGURATION_Handle *cfg,
1877 const char *section,
1878 const char *option,
1879 struct GNUNET_TIME_Relative *time)
1880{
1881 struct ConfigEntry *e;
1882 int ret;
1883
1884 if (NULL == (e = find_entry (cfg,
1885 section,
1886 option)))
1887 return GNUNET_NO;
1888 if (NULL == e->val)
1889 return GNUNET_NO;
1891 time);
1892 if (GNUNET_OK != ret)
1894 section,
1895 option,
1896 _ ("Not a valid relative time specification"));
1897 return ret;
1898}
1899
1900
1903 const struct GNUNET_CONFIGURATION_Handle *cfg,
1904 const char *section,
1905 const char *option,
1906 unsigned long long *size)
1907{
1908 struct ConfigEntry *e;
1909
1910 if (NULL == (e = find_entry (cfg,
1911 section,
1912 option)))
1913 return GNUNET_NO;
1914 if (NULL == e->val)
1915 return GNUNET_NO;
1917 size);
1918}
1919
1920
1933 const struct GNUNET_CONFIGURATION_Handle *cfg,
1934 const char *section,
1935 const char *option,
1936 char **value)
1937{
1938 struct ConfigEntry *e;
1939
1940 if ( (NULL == (e = find_entry (cfg,
1941 section,
1942 option))) ||
1943 (NULL == e->val) )
1944 {
1945 *value = NULL;
1946 return GNUNET_NO;
1947 }
1948 *value = GNUNET_strdup (e->val);
1949 return GNUNET_OK;
1950}
1951
1952
1955 const struct GNUNET_CONFIGURATION_Handle *cfg,
1956 const char *section,
1957 const char *option,
1958 const char *const *choices,
1959 const char **value)
1960{
1961 struct ConfigEntry *e;
1962 unsigned int i;
1963
1964 if (NULL == (e = find_entry (cfg,
1965 section,
1966 option)))
1967 return GNUNET_NO;
1968 for (i = 0; NULL != choices[i]; i++)
1969 if (0 == strcasecmp (choices[i], e->val))
1970 break;
1971 if (NULL == choices[i])
1972 {
1974 _ ("Configuration value '%s' for '%s'"
1975 " in section '%s' is not in set of legal choices\n"),
1976 e->val,
1977 option,
1978 section);
1979 return GNUNET_SYSERR;
1980 }
1981 *value = choices[i];
1982 return GNUNET_OK;
1983}
1984
1985
1988 const char *section,
1989 const char *option,
1990 void *buf,
1991 size_t buf_size)
1992{
1993 char *enc;
1994 int res;
1995 size_t data_size;
1996
1997 if (GNUNET_OK !=
1998 (res =
2000 section,
2001 option,
2002 &enc)))
2003 return res;
2004 data_size = (strlen (enc) * 5) / 8;
2005 if (data_size != buf_size)
2006 {
2007 GNUNET_free (enc);
2008 return GNUNET_SYSERR;
2009 }
2010 if (GNUNET_OK !=
2012 strlen (enc),
2013 buf,
2014 buf_size))
2015 {
2016 GNUNET_free (enc);
2017 return GNUNET_SYSERR;
2018 }
2019 GNUNET_free (enc);
2020 return GNUNET_OK;
2021}
2022
2023
2026 const char *section,
2027 const char *option)
2028{
2029 struct ConfigEntry *e;
2030
2031 if ( (NULL == (e = find_entry (cfg,
2032 section,
2033 option))) ||
2034 (NULL == e->val) )
2035 return GNUNET_NO;
2036 return GNUNET_YES;
2037}
2038
2039
2055static char *
2057 char *orig,
2058 unsigned int depth)
2059{
2060 char *prefix;
2061 char *result;
2062 char *start;
2063 const char *post;
2064 const char *env;
2065 char *def;
2066 char *end;
2067 unsigned int lopen;
2068 char erased_char;
2069 char *erased_pos;
2070 size_t len;
2071
2072 if (NULL == orig)
2073 return NULL;
2074 if (depth > 128)
2075 {
2077 "Recursive expansion suspected, aborting $-expansion for term `%s'\n",
2078 orig);
2079 return orig;
2080 }
2082 "Asked to $-expand %s\n",
2083 orig);
2084 if ('$' != orig[0])
2085 {
2087 "Doesn't start with $ - not expanding\n");
2088 return orig;
2089 }
2090 erased_char = 0;
2091 erased_pos = NULL;
2092 if ('{' == orig[1])
2093 {
2094 start = &orig[2];
2095 lopen = 1;
2096 end = &orig[1];
2097 while (lopen > 0)
2098 {
2099 end++;
2100 switch (*end)
2101 {
2102 case '}':
2103 lopen--;
2104 break;
2105
2106 case '{':
2107 lopen++;
2108 break;
2109
2110 case '\0':
2112 "Missing closing `}' in option `%s'\n",
2113 orig);
2114 return orig;
2115
2116 default:
2117 break;
2118 }
2119 }
2120 erased_char = *end;
2121 erased_pos = end;
2122 *end = '\0';
2123 post = end + 1;
2124 def = strchr (orig, ':');
2125 if (NULL != def)
2126 {
2127 *def = '\0';
2128 def++;
2129 if (('-' == *def) || ('=' == *def))
2130 def++;
2131 def = GNUNET_strdup (def);
2132 }
2133 }
2134 else
2135 {
2136 int i;
2137
2138 start = &orig[1];
2139 def = NULL;
2140 i = 0;
2141 while ( (orig[i] != '/') &&
2142 (orig[i] != '\\') &&
2143 (orig[i] != '\0') &&
2144 (orig[i] != ' ') )
2145 i++;
2146 if (orig[i] == '\0')
2147 {
2148 post = "";
2149 }
2150 else
2151 {
2152 erased_char = orig[i];
2153 erased_pos = &orig[i];
2154 orig[i] = '\0';
2155 post = &orig[i + 1];
2156 }
2157 }
2159 "Split into `%s' and `%s' with default %s\n",
2160 start,
2161 post,
2162 def);
2163 if (GNUNET_OK !=
2165 "PATHS",
2166 start,
2167 &prefix))
2168 {
2169 if (NULL == (env = getenv (start)))
2170 {
2171 /* try default */
2172 def = expand_dollar (cfg,
2173 def,
2174 depth + 1);
2175 env = def;
2176 }
2177 if (NULL == env)
2178 {
2180 if (erased_pos)
2181 *erased_pos = erased_char;
2183 "Failed to expand `%s' in `%s' as it is neither found in [PATHS] nor defined as an environmental variable\n",
2184 start,
2185 orig);
2187 return orig;
2188 }
2190 }
2192 prefix);
2193 if ((erased_pos) && ('}' != erased_char))
2194 {
2195 len = strlen (prefix) + 1;
2196 prefix = GNUNET_realloc (prefix, len + 1);
2197 prefix[len - 1] = erased_char;
2198 prefix[len] = '\0';
2199 }
2200 result = GNUNET_malloc (strlen (prefix) + strlen (post) + 1);
2201 strcpy (result, prefix);
2202 strcat (result, post);
2203 GNUNET_free (def);
2205 GNUNET_free (orig);
2206 return result;
2207}
2208
2209
2210char *
2212 const struct GNUNET_CONFIGURATION_Handle *cfg,
2213 char *orig)
2214{
2215 char *dup;
2216 size_t i;
2217 size_t len;
2218
2219 for (i = 0; '\0' != orig[i]; i++)
2220 {
2221 if ('$' != orig[i])
2222 continue;
2223 dup = GNUNET_strdup (orig + i);
2224 dup = expand_dollar (cfg, dup, 0);
2225 GNUNET_assert (NULL != dup); /* make compiler happy */
2226 len = strlen (dup) + 1;
2227 orig = GNUNET_realloc (orig, i + len);
2228 GNUNET_memcpy (orig + i, dup, len);
2229 GNUNET_free (dup);
2230 }
2231 return orig;
2232}
2233
2234
2237 const struct GNUNET_CONFIGURATION_Handle *cfg,
2238 const char *section,
2239 const char *option,
2240 char **value)
2241{
2242 char *tmp;
2244
2246 section,
2247 option,
2248 &tmp);
2249 if (GNUNET_OK != ret)
2250 {
2252 "Failed to retrieve filename\n");
2253 *value = NULL;
2254 return ret;
2255 }
2257 tmp);
2259 GNUNET_free (tmp);
2260 if (*value == NULL)
2261 return GNUNET_SYSERR;
2262 return GNUNET_OK;
2263}
2264
2265
2268 const struct GNUNET_CONFIGURATION_Handle *cfg,
2269 const char *section,
2270 const char *option)
2271{
2272 static const char *yesno[] = {
2273 "YES",
2274 "NO",
2275 NULL
2276 };
2277 const char *val;
2279
2280 ret =
2282 section,
2283 option,
2284 yesno,
2285 &val);
2286 if (GNUNET_OK != ret)
2287 return ret;
2288 if (val == yesno[0])
2289 return GNUNET_YES;
2290 return GNUNET_NO;
2291}
2292
2293
2294int
2296 const struct GNUNET_CONFIGURATION_Handle *cfg,
2297 const char *section,
2298 const char *option,
2300 void *cb_cls)
2301{
2302 char *list;
2303 char *pos;
2304 char *end;
2305 char old;
2306 int ret;
2307
2308 if (GNUNET_OK !=
2310 section,
2311 option,
2312 &list))
2313 return 0;
2314 GNUNET_assert (list != NULL);
2315 ret = 0;
2316 pos = list;
2317 while (1)
2318 {
2319 while (pos[0] == ' ')
2320 pos++;
2321 if (strlen (pos) == 0)
2322 break;
2323 end = pos + 1;
2324 while ((end[0] != ' ') && (end[0] != '\0'))
2325 {
2326 if (end[0] == '\\')
2327 {
2328 switch (end[1])
2329 {
2330 case '\\':
2331 case ' ':
2332 memmove (end, &end[1], strlen (&end[1]) + 1);
2333
2334 case '\0':
2335 /* illegal, but just keep it */
2336 break;
2337
2338 default:
2339 /* illegal, but just ignore that there was a '/' */
2340 break;
2341 }
2342 }
2343 end++;
2344 }
2345 old = end[0];
2346 end[0] = '\0';
2347 if (strlen (pos) > 0)
2348 {
2349 ret++;
2350 if ( (NULL != cb) &&
2351 (GNUNET_OK != cb (cb_cls,
2352 pos)))
2353 {
2355 break;
2356 }
2357 }
2358 if (old == '\0')
2359 break;
2360 pos = end + 1;
2361 }
2362 GNUNET_free (list);
2363 return ret;
2364}
2365
2366
2373static char *
2374escape_name (const char *value)
2375{
2376 char *escaped;
2377 const char *rpos;
2378 char *wpos;
2379
2380 escaped = GNUNET_malloc (strlen (value) * 2 + 1);
2381 memset (escaped, 0, strlen (value) * 2 + 1);
2382 rpos = value;
2383 wpos = escaped;
2384 while (rpos[0] != '\0')
2385 {
2386 switch (rpos[0])
2387 {
2388 case '\\':
2389 case ' ':
2390 wpos[0] = '\\';
2391 wpos[1] = rpos[0];
2392 wpos += 2;
2393 break;
2394
2395 default:
2396 wpos[0] = rpos[0];
2397 wpos++;
2398 }
2399 rpos++;
2400 }
2401 return escaped;
2402}
2403
2404
2412static enum GNUNET_GenericReturnValue
2413test_match (void *cls,
2414 const char *fn)
2415{
2416 const char *of = cls;
2417
2418 return (0 == strcmp (of, fn))
2420 : GNUNET_OK;
2421}
2422
2423
2427 const char *section,
2428 const char *option,
2429 const char *value)
2430{
2431 char *escaped;
2432 char *old;
2433 char *nw;
2434
2435 if (GNUNET_SYSERR ==
2437 section,
2438 option,
2439 &test_match,
2440 (void *) value))
2441 return GNUNET_NO; /* already exists */
2442 if (GNUNET_OK !=
2443 GNUNET_CONFIGURATION_get_value_string (cfg, section, option, &old))
2444 old = GNUNET_strdup ("");
2445 escaped = escape_name (value);
2446 nw = GNUNET_malloc (strlen (old) + strlen (escaped) + 2);
2447 strcpy (nw, old);
2448 if (strlen (old) > 0)
2449 strcat (nw, " ");
2450 strcat (nw, escaped);
2452 section,
2453 option,
2454 nw);
2455 GNUNET_free (old);
2456 GNUNET_free (nw);
2457 GNUNET_free (escaped);
2458 return GNUNET_OK;
2459}
2460
2461
2465 const char *section,
2466 const char *option,
2467 const char *value)
2468{
2469 char *list;
2470 char *pos;
2471 char *end;
2472 char *match;
2473 char old;
2474
2475 if (GNUNET_OK !=
2477 section,
2478 option,
2479 &list))
2480 return GNUNET_NO;
2481 match = escape_name (value);
2482 pos = list;
2483 while (1)
2484 {
2485 while (pos[0] == ' ')
2486 pos++;
2487 if (strlen (pos) == 0)
2488 break;
2489 end = pos + 1;
2490 while ((end[0] != ' ') && (end[0] != '\0'))
2491 {
2492 if (end[0] == '\\')
2493 {
2494 switch (end[1])
2495 {
2496 case '\\':
2497 case ' ':
2498 end++;
2499 break;
2500
2501 case '\0':
2502 /* illegal, but just keep it */
2503 break;
2504
2505 default:
2506 /* illegal, but just ignore that there was a '/' */
2507 break;
2508 }
2509 }
2510 end++;
2511 }
2512 old = end[0];
2513 end[0] = '\0';
2514 if (0 == strcmp (pos, match))
2515 {
2516 if (old != '\0')
2517 memmove (pos,
2518 &end[1],
2519 strlen (&end[1]) + 1);
2520 else
2521 {
2522 if (pos != list)
2523 pos[-1] = '\0';
2524 else
2525 pos[0] = '\0';
2526 }
2528 section,
2529 option,
2530 list);
2531 GNUNET_free (list);
2532 GNUNET_free (match);
2533 return GNUNET_OK;
2534 }
2535 if (old == '\0')
2536 break;
2537 end[0] = old;
2538 pos = end + 1;
2539 }
2540 GNUNET_free (list);
2541 GNUNET_free (match);
2542 return GNUNET_NO;
2543}
2544
2545
2549 const char *defaults_d)
2550{
2551 struct CollectFilesContext files_context = {
2552 .files = NULL,
2553 .files_length = 0,
2554 };
2555 enum GNUNET_GenericReturnValue fun_ret;
2556
2557 if (GNUNET_SYSERR ==
2558 GNUNET_DISK_directory_scan (defaults_d,
2560 &files_context))
2561 return GNUNET_SYSERR; /* no configuration at all found */
2562 qsort (files_context.files,
2563 files_context.files_length,
2564 sizeof (char *),
2565 &pstrcmp);
2566 for (unsigned int i = 0; i < files_context.files_length; i++)
2567 {
2568 const char *ext;
2569 const char *filename = files_context.files[i];
2570
2571 /* Examine file extension */
2572 ext = strrchr (filename, '.');
2573 if ( (NULL == ext) ||
2574 (0 != strcmp (ext,
2575 ".conf")) )
2576 {
2578 "Skipping file `%s'\n",
2579 filename);
2580 fun_ret = GNUNET_OK;
2581 continue;
2582 }
2584 filename);
2585 if (fun_ret != GNUNET_OK)
2586 break;
2587 }
2588 if (files_context.files_length > 0)
2589 {
2590 for (size_t i = 0; i < files_context.files_length; i++)
2591 GNUNET_free (files_context.files[i]);
2592 GNUNET_array_grow (files_context.files,
2593 files_context.files_length,
2594 0);
2595 }
2596 return fun_ret;
2597}
2598
2599
2600char *
2602 const struct GNUNET_OS_ProjectData *pd)
2603{
2604 char *cfg_fn;
2605 const char *xdg = getenv ("XDG_CONFIG_HOME");
2606
2607 if (NULL != xdg)
2608 GNUNET_asprintf (&cfg_fn,
2609 "%s%s%s",
2610 xdg,
2612 pd->config_file);
2613 else
2614 cfg_fn = GNUNET_strdup (pd->user_config_file);
2615
2616 if (GNUNET_OK == GNUNET_DISK_file_test_read (cfg_fn))
2617 return cfg_fn;
2618 GNUNET_free (cfg_fn);
2619
2620 /* Fall back to /etc/ for the default configuration.
2621 Should be okay to use forward slashes here. */
2622
2623 GNUNET_asprintf (&cfg_fn,
2624 "/etc/%s",
2625 pd->config_file);
2626 if (GNUNET_OK ==
2628 return cfg_fn;
2629 GNUNET_free (cfg_fn);
2630
2631 GNUNET_asprintf (&cfg_fn,
2632 "/etc/%s/%s",
2633 pd->project_dirname,
2634 pd->config_file);
2635 if (GNUNET_OK ==
2637 return cfg_fn;
2638
2639 GNUNET_free (cfg_fn);
2640 return NULL;
2641}
2642
2643
2647 const char *filename)
2648{
2649 char *baseconfig;
2650 const char *base_config_varname;
2651
2652 if (cfg->load_called)
2653 {
2654 /* FIXME: Make this a GNUNET_assert later */
2655 GNUNET_break (0);
2657 }
2658 cfg->load_called = true;
2659 if (NULL != filename)
2660 {
2663 }
2664
2665 base_config_varname = cfg->pd->base_config_varname;
2666
2667 if ((NULL != base_config_varname)
2668 && (NULL != (baseconfig = getenv (base_config_varname))))
2669 {
2670 baseconfig = GNUNET_strdup (baseconfig);
2671 }
2672 else
2673 {
2674 char *ipath;
2675
2678 if (NULL == ipath)
2679 {
2680 GNUNET_break (0);
2681 return GNUNET_SYSERR;
2682 }
2683 GNUNET_asprintf (&baseconfig,
2684 "%s%s",
2685 ipath,
2686 "config.d");
2687 GNUNET_free (ipath);
2688 }
2689
2690 {
2691 char *dname = GNUNET_STRINGS_filename_expand (baseconfig);
2692
2693 GNUNET_free (baseconfig);
2694
2695 if ((GNUNET_YES ==
2697 GNUNET_YES)) &&
2698 (GNUNET_SYSERR ==
2700 dname)))
2701 {
2703 "Failed to load base configuration from '%s'\n",
2704 filename);
2705 GNUNET_free (dname);
2706 return GNUNET_SYSERR; /* no configuration at all found */
2707 }
2708 GNUNET_free (dname);
2709 }
2710 if ((NULL != filename) &&
2711 (GNUNET_OK !=
2713 filename)))
2714 {
2715 /* specified configuration not found */
2717 "Failed to load configuration from file '%s'\n",
2718 filename);
2719 return GNUNET_SYSERR;
2720 }
2721 if (((GNUNET_YES !=
2723 "PATHS",
2724 "DEFAULTCONFIG"))) &&
2725 (filename != NULL))
2727 "PATHS",
2728 "DEFAULTCONFIG",
2729 filename);
2730 return GNUNET_OK;
2731}
2732
2733
2742static void
2744 const char *section,
2745 const char *option,
2746 const char *value)
2747{
2748 const struct GNUNET_CONFIGURATION_Handle *cfg = cls;
2749
2750 char *value_fn;
2751 char *fn;
2752
2755 section,
2756 option,
2757 &value_fn));
2758 fn = GNUNET_STRINGS_filename_expand (value_fn);
2759 if (NULL == fn)
2760 fn = value_fn;
2761 else
2762 GNUNET_free (value_fn);
2763 fprintf (stdout,
2764 "%s = %s\n",
2765 option,
2766 fn);
2767 GNUNET_free (fn);
2768}
2769
2770
2779static void
2780print_option (void *cls,
2781 const char *section,
2782 const char *option,
2783 const char *value)
2784{
2785 (void) cls;
2786 (void) section;
2787
2788 fprintf (stdout,
2789 "%s = %s\n",
2790 option,
2791 value);
2792}
2793
2794
2801static void
2803 const char *section)
2804{
2805 (void) cls;
2806 fprintf (stdout,
2807 "%s\n",
2808 section);
2809}
2810
2811
2812void
2814 void *cls,
2815 char *const *args,
2816 const char *cfgfile,
2817 const struct GNUNET_CONFIGURATION_Handle *cfg)
2818{
2819 struct GNUNET_CONFIGURATION_ConfigSettings *cs = cls;
2820 struct GNUNET_CONFIGURATION_Handle *out = NULL;
2821 struct GNUNET_CONFIGURATION_Handle *ncfg = NULL;
2822
2823 (void) args;
2824 if (cs->diagnostics)
2825 {
2826 /* Re-parse the configuration with diagnostics enabled. */
2829 if (GNUNET_OK !=
2831 cfgfile))
2832 {
2833 fprintf (stderr,
2834 _ ("Failed to load config file `%s'"),
2835 cfgfile);
2836 return;
2837 }
2838 cfg = ncfg;
2839 }
2840
2841 if (cs->full)
2842 cs->rewrite = GNUNET_YES;
2843 if (cs->list_sections)
2844 {
2845 fprintf (stderr,
2846 _ ("The following sections are available:\n"));
2849 NULL);
2850 return;
2851 }
2852 if ( (! cs->rewrite) &&
2853 (NULL == cs->section) )
2854 {
2855 char *serialization;
2856
2857 if (! cs->diagnostics)
2858 {
2859 fprintf (stderr,
2860 _ ("%s, %s or %s argument is required\n"),
2861 "--section",
2862 "--list-sections",
2863 "--diagnostics");
2865 return;
2866 }
2868 fprintf (stdout,
2869 "%s",
2870 serialization);
2871 GNUNET_free (serialization);
2872 }
2873 else if ( (NULL != cs->section) &&
2874 (NULL == cs->value) )
2875 {
2876 if (NULL == cs->option)
2877 {
2879 cfg,
2880 cs->section,
2881 cs->is_filename
2883 : &print_option,
2884 (void *) cfg);
2885 }
2886 else
2887 {
2888 char *value;
2889
2890 if (cs->is_filename)
2891 {
2892 if (GNUNET_OK !=
2894 cs->section,
2895 cs->option,
2896 &value))
2897 {
2899 cs->section,
2900 cs->option);
2902 return;
2903 }
2904 }
2905 else
2906 {
2907 if (GNUNET_OK !=
2909 cs->section,
2910 cs->option,
2911 &value))
2912 {
2914 cs->section,
2915 cs->option);
2917 return;
2918 }
2919 }
2920 fprintf (stdout,
2921 "%s\n",
2922 value);
2924 }
2925 }
2926 else if (NULL != cs->section)
2927 {
2928 if (NULL == cs->option)
2929 {
2930 fprintf (stderr,
2931 _ ("--option argument required to set value\n"));
2933 return;
2934 }
2937 cs->section,
2938 cs->option,
2939 cs->value);
2940 cs->rewrite = GNUNET_YES;
2941 }
2942 if (cs->rewrite)
2943 {
2944 char *cfg_fn = NULL;
2945
2946 if (NULL == out)
2948
2949 if (NULL == cfgfile)
2950 {
2951 const char *xdg = getenv ("XDG_CONFIG_HOME");
2952
2953 if (NULL != xdg)
2954 GNUNET_asprintf (&cfg_fn,
2955 "%s%s%s",
2956 xdg,
2958 cfg->pd->config_file);
2959 else
2960 cfg_fn = GNUNET_strdup (cfg->pd->user_config_file);
2961 cfgfile = cfg_fn;
2962 }
2963
2964 if (! cs->full)
2965 {
2966 struct GNUNET_CONFIGURATION_Handle *def;
2967
2969 if (GNUNET_OK !=
2971 NULL))
2972 {
2973 fprintf (stderr,
2974 _ ("failed to load configuration defaults"));
2975 cs->global_ret = 1;
2978 GNUNET_free (cfg_fn);
2979 return;
2980 }
2981 if (GNUNET_OK !=
2983 out,
2984 cfgfile))
2985 cs->global_ret = 2;
2987 }
2988 else
2989 {
2990 if (GNUNET_OK !=
2992 cfgfile))
2993 cs->global_ret = 2;
2994 }
2995 GNUNET_free (cfg_fn);
2996 }
2997 if (NULL != out)
2999 if (NULL != ncfg)
3001}
3002
3003
3004void
3012
3013
3014const struct GNUNET_OS_ProjectData *
3016 const struct GNUNET_CONFIGURATION_Handle *cfg)
3017{
3018 return cfg->pd;
3019}
3020
3021
3022/* 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,...)
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.
static char * line
Desired phone line (string to be converted to a hash).
struct GNUNET_HashCode key
The key used in the DHT.
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 void cleanup()
Cleanup task.
static struct GNUNET_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 all configuration sections.
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:1308
int GNUNET_DISK_glob(const char *glob_pattern, GNUNET_FileNameCallback callback, void *callback_cls)
Find all files matching a glob pattern.
Definition disk.c:1063
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:745
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:565
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:235
enum GNUNET_GenericReturnValue GNUNET_DISK_directory_remove(const char *filename)
Remove all files in a directory (rm -rf).
Definition disk.c:1140
enum GNUNET_GenericReturnValue GNUNET_DISK_directory_test(const char *fil, int is_readable)
Test if fil is a directory and listable.
Definition disk.c:466
enum GNUNET_GenericReturnValue GNUNET_DISK_file_close(struct GNUNET_DISK_FileHandle *h)
Close an open file.
Definition disk.c:1386
enum GNUNET_GenericReturnValue GNUNET_DISK_directory_create_for_file(const char *filename)
Create the directory structure for storing a file.
Definition disk.c:664
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:720
int GNUNET_DISK_directory_scan(const char *dir_name, GNUNET_FileNameCallback callback, void *callback_cls)
Scan a directory for files.
Definition disk.c:881
@ 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:89
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:77
#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:525
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:837
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
char * hint_filename
Diagnostics information for the filename.
struct ConfigEntry * next
This is a linked list.
char * key
key for this entry
unsigned int hint_lineno
Diagnostics information for the line number.
char * val
current, committed value
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
char * name
name of the section
char * hint_inlined_from_filename
For secret sections: Where was this inlined from?
struct ConfigEntry * entries
entries in the section
bool inaccessible
Is the configuration section marked as inaccessible?
struct ConfigSection * next
This is a linked list.
char * hint_secret_filename
Diagnostics hint for the secret file.
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.