GNUnet 0.29.1-dev.1-3-g346358e26
 
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 *value;
49
53 char *filename;
54
58 unsigned int lineno;
59};
60
61
66{
71
75 char *key;
76
80 char *val;
81
86};
87
88
137
139{
144
148 unsigned int level;
149
151
153
159
164
169
174};
175
176
236
237
248
249
250void
256
257
260{
262 char *p;
263
265 cfg->pd = pd;
266 /* make certain values from the project data available
267 as PATHS */
270 if (NULL != p)
271 {
273 "PATHS",
274 "DATADIR",
275 p);
276 GNUNET_free (p);
277 }
280 if (NULL != p)
281 {
283 "PATHS",
284 "LIBDIR",
285 p);
286 GNUNET_free (p);
287 }
290 if (NULL != p)
291 {
293 "PATHS",
294 "BINDIR",
295 p);
296 GNUNET_free (p);
297 }
300 if (NULL != p)
301 {
303 "PATHS",
304 "PREFIX",
305 p);
306 GNUNET_free (p);
307 }
310 if (NULL != p)
311 {
313 "PATHS",
314 "LOCALEDIR",
315 p);
316 GNUNET_free (p);
317 }
320 if (NULL != p)
321 {
323 "PATHS",
324 "ICONDIR",
325 p);
326 GNUNET_free (p);
327 }
330 if (NULL != p)
331 {
333 "PATHS",
334 "DOCDIR",
335 p);
336 GNUNET_free (p);
337 }
340 if (NULL != p)
341 {
343 "PATHS",
344 "LIBEXECDIR",
345 p);
346 GNUNET_free (p);
347 }
348 return cfg;
349}
350
351
352void
354{
355 struct ConfigSection *sec;
356 struct ConfigFile *cf;
357
358 while (NULL != (sec = cfg->sections))
360 while (NULL != (cf = cfg->loaded_files_head))
361 {
366 cf);
367 GNUNET_free (cf);
368 }
371}
372
373
376 const char *filename,
378 void *cb_cls)
379{
382
384 if (GNUNET_OK !=
386 filename))
387 {
388 GNUNET_break (0);
390 return GNUNET_SYSERR;
391 }
392 ret = cb (cb_cls,
393 cfg);
395 return ret;
396}
397
398
403{
407 char **files;
408
412 unsigned int files_length;
413};
414
415
427 const char *filename)
428{
429 struct CollectFilesContext *igc = cls;
430
432 igc->files_length,
434 return GNUNET_OK;
435}
436
437
445static struct ConfigSection *
447 const char *section)
448{
449 struct ConfigSection *pos;
450
451 if (NULL == cfg)
452 return NULL;
453 pos = cfg->sections;
454 while ( (NULL != pos) &&
455 (0 != strcasecmp (section,
456 pos->name)) )
457 pos = pos->next;
458 return pos;
459}
460
461
462static int
463pstrcmp (const void *a,
464 const void *b)
465{
466 return strcmp (*((const char **) a),
467 *((const char **) b));
468}
469
470
471static void
473 const char *section,
474 const struct ConfigEntry *entry);
475
476
484 const char *path_or_glob,
485 bool path_is_glob,
486 const char *restrict_section,
487 const char *source_filename,
488 unsigned int source_lineno)
489{
490 char *inline_path = NULL;
491 struct GNUNET_CONFIGURATION_Handle *other_cfg = NULL;
492 struct CollectFilesContext igc = {
493 .files = NULL,
494 .files_length = 0,
495 };
496 enum GNUNET_GenericReturnValue fun_ret;
497 unsigned int old_nest_level = cfg->current_nest_level++;
498
499 /* We support the section restriction only for non-globs */
500 GNUNET_assert (! (path_is_glob && (NULL != restrict_section)));
501
502 if (NULL == source_filename)
503 {
505 "Refusing to parse inline configurations, "
506 "not allowed without source filename!\n");
507 fun_ret = GNUNET_SYSERR;
508 goto cleanup;
509 }
510
511 if ('/' == *path_or_glob)
512 inline_path = GNUNET_strdup (path_or_glob);
513 else
514 {
515 /* We compute the canonical, absolute path first,
516 so that relative imports resolve properly with symlinked
517 config files. */
518 char *source_realpath;
519 char *endsep;
520
521 source_realpath = realpath (source_filename,
522 NULL);
523 if (NULL == source_realpath)
524 {
525 /* Couldn't even resolve path of base dir. */
526 GNUNET_break (0);
527 /* failed to parse included config */
528 fun_ret = GNUNET_SYSERR;
529 goto cleanup;
530 }
531 endsep = strrchr (source_realpath, '/');
532 GNUNET_assert (NULL != endsep);
533 *endsep = '\0';
534 GNUNET_asprintf (&inline_path,
535 "%s/%s",
536 source_realpath,
537 path_or_glob);
538 free (source_realpath);
539 }
540
541 if (path_is_glob)
542 {
543 int nret;
544
546 "processing config glob '%s'\n",
547 inline_path);
548
549 nret = GNUNET_DISK_glob (inline_path,
551 &igc);
552 if (-1 == nret)
553 {
554 fun_ret = GNUNET_SYSERR;
555 goto cleanup;
556 }
557 GNUNET_assert (nret == igc.files_length);
558 qsort (igc.files,
559 igc.files_length,
560 sizeof (char *),
561 &pstrcmp);
562 for (int i = 0; i < nret; i++)
563 {
564 if (GNUNET_OK !=
566 igc.files[i]))
567 {
568 fun_ret = GNUNET_SYSERR;
569 goto cleanup;
570 }
571 }
572 fun_ret = GNUNET_OK;
573 }
574 else if (NULL != restrict_section)
575 {
576 enum GNUNET_GenericReturnValue inner_ret;
577 struct ConfigSection *cs;
578 struct ConfigFile *cf = GNUNET_new (struct ConfigFile);
579
580 inner_ret = GNUNET_DISK_file_test_read (inline_path);
581
582 cs = find_section (cfg, restrict_section);
583
584 if (NULL == cs)
585 {
586 cs = GNUNET_new (struct ConfigSection);
587 cs->name = GNUNET_strdup (restrict_section);
588 cs->next = cfg->sections;
589 cfg->sections = cs;
590 cs->entries = NULL;
591 }
592 if (cfg->diagnostics)
593 {
594 const char *pwname;
595 const char *grname;
596 char *sfn = GNUNET_STRINGS_filename_expand (inline_path);
597 struct stat istat;
598
599 cs->hint_secret_filename = sfn;
600 if (0 == stat (sfn, &istat))
601 {
602 struct passwd *pw = getpwuid (istat.st_uid);
603 struct group *gr = getgrgid (istat.st_gid);
604 pwname = (NULL == pw) ? "<unknown>" : pw->pw_name;
605 grname = (NULL == gr) ? "<unknown>" : gr->gr_name;
606
608 "%s:%s %o",
609 pwname,
610 grname,
611 istat.st_mode);
612 }
613 else
614 {
615 cs->hint_secret_stat = GNUNET_strdup ("<can't stat file>");
616 }
617 if (source_filename)
618 {
619 /* Possible that this secret section has been inlined before */
621 cs->hint_inlined_from_filename = GNUNET_strdup (source_filename);
622 cs->hint_inlined_from_line = source_lineno;
623 }
624 }
625
626 /* Put file in the load list for diagnostics, even if we can't access it. */
627 {
629 cf->source_filename = GNUNET_strdup (inline_path);
630 cf->hint_restrict_section = GNUNET_strdup (restrict_section);
633 cf);
634 }
635
636 if (GNUNET_OK != inner_ret)
637 {
638 cs->inaccessible = true;
639 cf->hint_inaccessible = true;
640 /* File can't be accessed, but that's okay. */
641 fun_ret = GNUNET_OK;
642 goto cleanup;
643 }
644
645 other_cfg = GNUNET_CONFIGURATION_create (cfg->pd);
646 if (cfg->diagnostics)
648 other_cfg->restrict_section = restrict_section;
649 inner_ret = GNUNET_CONFIGURATION_parse (other_cfg,
650 inline_path);
651 if (GNUNET_OK != inner_ret)
652 {
653 cf->hint_inaccessible = true;
654 fun_ret = inner_ret;
655 goto cleanup;
656 }
657
658 cs = find_section (other_cfg,
659 restrict_section);
660 if (NULL == cs)
661 {
663 "Configuration file '%s' loaded with @inline-secret@ "
664 "does not contain section '%s'.\n",
665 inline_path,
666 restrict_section);
667 /* Inlined configuration is accessible but doesn't contain any values.
668 We treat this as if the inlined section was empty, and do not
669 consider it an error. */
670 fun_ret = GNUNET_OK;
671 goto cleanup;
672 }
673 for (struct ConfigEntry *ce = cs->entries;
674 NULL != ce;
675 ce = ce->next)
677 restrict_section,
678 ce);
679 fun_ret = GNUNET_OK;
680 }
681 else if (GNUNET_OK !=
683 inline_path))
684 {
685 fun_ret = GNUNET_SYSERR;
686 goto cleanup;
687 }
688 else
689 {
690 fun_ret = GNUNET_OK;
691 }
692cleanup:
693 cfg->current_nest_level = old_nest_level;
694 if (NULL != other_cfg)
696 GNUNET_free (inline_path);
697 if (igc.files_length > 0)
698 {
699 for (size_t i = 0; i < igc.files_length; i++)
700 GNUNET_free (igc.files[i]);
702 }
703 return fun_ret;
704}
705
706
715static struct ConfigEntry *
717 const char *section,
718 const char *key)
719{
720 struct ConfigSection *sec;
721
722 if (NULL == (sec = find_section (cfg,
723 section)))
724 return NULL;
725 for (struct ConfigEntry *pos = sec->entries;
726 pos != NULL;
727 pos = pos->next)
728 if (0 == strcasecmp (key,
729 pos->key))
730 return pos;
731 if (sec->inaccessible)
732 {
734 "Section '%s' is marked as inaccessible, because the configuration "
735 "file that contains the section can't be read. Attempts to use "
736 "option '%s' will fail.\n",
737 section,
738 key);
739 return NULL;
740 }
741 return NULL;
742}
743
744
755static void
757 const char *section,
758 const char *option,
759 const char *value,
760 const char *filename,
761 unsigned int line)
762{
763 struct ConfigEntry *e;
764 struct ConfigSource *source;
765
766 if (! cfg->diagnostics)
767 return;
768 e = find_entry (cfg,
769 section,
770 option);
771 if (NULL == e)
772 return;
773 source = GNUNET_new (struct ConfigSource);
774 source->value = GNUNET_strdup (value);
775 source->filename = GNUNET_strdup (filename);
776 source->lineno = line;
777 source->next = e->sources;
778 e->sources = source;
779}
780
781
790static void
792 const char *section,
793 const struct ConfigEntry *entry)
794{
795 struct ConfigEntry *dst;
796 struct ConfigSource *head = NULL;
797 struct ConfigSource *tail = NULL;
798
800 section,
801 entry->key,
802 entry->val);
803 if ( (! cfg->diagnostics) ||
804 (NULL == entry->sources) )
805 return;
806 dst = find_entry (cfg,
807 section,
808 entry->key);
809 GNUNET_assert (NULL != dst);
810 for (const struct ConfigSource *pos = entry->sources;
811 NULL != pos;
812 pos = pos->next)
813 {
814 struct ConfigSource *copy = GNUNET_new (struct ConfigSource);
815
816 copy->value = GNUNET_strdup (pos->value);
817 copy->filename = GNUNET_strdup (pos->filename);
818 copy->lineno = pos->lineno;
819 if (NULL == tail)
820 head = copy;
821 else
822 tail->next = copy;
823 tail = copy;
824 }
825 tail->next = dst->sources;
826 dst->sources = head;
827}
828
829
832 const char *mem,
833 size_t size,
834 const char *source_filename)
835{
836 size_t line_size;
837 unsigned int nr;
838 size_t r_bytes;
839 size_t to_read;
841 char *section;
842 char *eq;
843 char *tag;
844 char *value;
845 char *line_orig = NULL;
846
847 ret = GNUNET_OK;
848 section = NULL;
849 nr = 0;
850 r_bytes = 0;
851 while (r_bytes < size)
852 {
853 const char *pos;
854 char *line;
855 bool emptyline;
856
857 GNUNET_free (line_orig);
858 /* fgets-like behaviour on buffer */
859 to_read = size - r_bytes;
860 pos = memchr (&mem[r_bytes], '\n', to_read);
861 if (NULL == pos)
862 {
863 line_orig = GNUNET_strndup (&mem[r_bytes],
864 line_size = to_read);
865 r_bytes += line_size;
866 }
867 else
868 {
869 line_orig = GNUNET_strndup (&mem[r_bytes],
870 line_size = (pos - &mem[r_bytes]));
871 r_bytes += line_size + 1;
872 }
873 line = line_orig;
874 /* increment line number */
875 nr++;
876 /* tabs and '\r' are whitespace */
877 emptyline = GNUNET_YES;
878 for (size_t i = 0; i < line_size; i++)
879 {
880 if (line[i] == '\t')
881 line[i] = ' ';
882 if (line[i] == '\r')
883 line[i] = ' ';
884 if (' ' != line[i])
885 emptyline = GNUNET_NO;
886 }
887 /* ignore empty lines */
888 if (GNUNET_YES == emptyline)
889 continue;
890
891 /* remove tailing whitespace */
892 for (size_t i = line_size - 1;
893 (i >= 1) && (isspace ((unsigned char) line[i]));
894 i--)
895 line[i] = '\0';
896
897 /* remove leading whitespace */
898 for (; line[0] != '\0' && (isspace ((unsigned char) line[0])); line++)
899 ;
900
901 /* ignore comments */
902 if ( ('#' == line[0]) ||
903 ('%' == line[0]) )
904 continue;
905
906 /* Handle special directives. */
907 if ('@' == line[0])
908 {
909 char *end = strchr (line + 1, '@');
910 char *directive;
911 enum GNUNET_GenericReturnValue directive_ret;
912
913 if (NULL != cfg->restrict_section)
914 {
916 "Illegal directive in line %u (parsing restricted section %s)\n",
917 nr,
920 break;
921 }
922
923 if (NULL == end)
924 {
926 "Bad directive in line %u\n",
927 nr);
929 break;
930 }
931 *end = '\0';
932 directive = line + 1;
933
934 if (0 == strcasecmp (directive,
935 "INLINE"))
936 {
937 const char *path = end + 1;
938
939 /* Skip space before path */
940 for (; isspace (*path); path++)
941 ;
942
943 directive_ret = handle_inline (cfg,
944 path,
945 false,
946 NULL,
947 source_filename,
948 nr);
949 }
950 else if (0 == strcasecmp (directive,
951 "INLINE-MATCHING"))
952 {
953 const char *path = end + 1;
954
955 /* Skip space before path */
956 for (; isspace (*path); path++)
957 ;
958
959 directive_ret = handle_inline (cfg,
960 path,
961 true,
962 NULL,
963 source_filename,
964 nr);
965 }
966 else if (0 == strcasecmp (directive,
967 "INLINE-SECRET"))
968 {
969 char *secname = end + 1;
970 char *secname_end;
971 const char *path;
972
973 /* Skip space before secname */
974 for (; isspace (*secname); secname++)
975 ;
976
977 secname_end = strchr (secname, ' ');
978
979 if (NULL == secname_end)
980 {
982 "Bad inline-secret directive in line %u\n",
983 nr);
985 break;
986 }
987 *secname_end = '\0';
988 path = secname_end + 1;
989
990 /* Skip space before path */
991 for (; isspace (*path); path++)
992 ;
993
994 directive_ret = handle_inline (cfg,
995 path,
996 false,
997 secname,
998 source_filename,
999 nr);
1000 }
1001 else
1002 {
1004 "Unknown or malformed directive '%s' in line %u\n",
1005 directive,
1006 nr);
1008 break;
1009 }
1010 if (GNUNET_OK != directive_ret)
1011 {
1012 ret = directive_ret;
1013 break;
1014 }
1015 continue;
1016 }
1017 if ( ('[' == line[0]) &&
1018 (']' == line[line_size - 1]) )
1019 {
1020 /* [value] */
1021 line[line_size - 1] = '\0';
1022 value = &line[1];
1023 GNUNET_free (section);
1024 section = GNUNET_strdup (value);
1025 continue;
1026 }
1027 if (NULL != (eq = strchr (line, '=')))
1028 {
1029
1030 if (NULL == section)
1031 {
1033 "Syntax error while deserializing in line %u (option without section)\n",
1034 nr);
1036 break;
1037 }
1038
1039 /* tag = value */
1040 tag = GNUNET_strndup (line, eq - line);
1041 /* remove tailing whitespace */
1042 for (int i = strlen (tag) - 1;
1043 (i >= 1) && (isspace ((unsigned char) tag[i]));
1044 i--)
1045 tag[i] = '\0';
1046
1047 /* Strip whitespace */
1048 value = eq + 1;
1049 while (isspace ((unsigned char) value[0]))
1050 value++;
1051 for (int i = strlen (value) - 1;
1052 (i >= 1) && (isspace ((unsigned char) value[i]));
1053 i--)
1054 value[i] = '\0';
1055
1056 /* remove quotes */
1057 if ( ('"' == value[0]) &&
1058 ('"' == value[strlen (value) - 1]) )
1059 {
1060 value[strlen (value) - 1] = '\0';
1061 value++;
1062 }
1064 section,
1065 tag,
1066 value);
1067 if (cfg->diagnostics)
1068 {
1070 section,
1071 tag,
1072 value,
1073 source_filename
1074 ? source_filename
1075 : "<input>",
1076 nr);
1077 }
1078 GNUNET_free (tag);
1079 continue;
1080 }
1081 /* parse error */
1083 "Syntax error while deserializing in line %u\n",
1084 nr);
1086 break;
1087 }
1088 GNUNET_free (line_orig);
1089 GNUNET_free (section);
1090 GNUNET_assert ( (GNUNET_OK != ret) ||
1091 (r_bytes == size) );
1092 return ret;
1093}
1094
1095
1098 const char *filename)
1099{
1100 struct ConfigFile *loaded_file;
1101 uint64_t fs64;
1102 size_t fs;
1103 char *fn;
1104 char *mem;
1105 int dirty;
1107 ssize_t sret;
1108
1111 "Asked to parse config file `%s'\n",
1112 fn);
1113 if (NULL == fn)
1114 return GNUNET_SYSERR;
1115
1116
1117 /* Check for cycles */
1118 {
1119 unsigned int lvl = cfg->current_nest_level;
1120 struct ConfigFile *cf = cfg->loaded_files_tail;
1121 struct ConfigFile *parent = NULL;
1122
1123
1124 for (; NULL != cf; parent = cf, cf = cf->prev)
1125 {
1126 /* Check parents based on level, skipping children of siblings. */
1127 if (cf->level >= lvl)
1128 continue;
1129 lvl = cf->level;
1130 if ( (NULL == cf->source_filename) ||
1131 (NULL == filename) )
1132 continue;
1133 if (0 == strcmp (cf->source_filename,
1134 filename))
1135 {
1136 if (NULL == parent)
1137 {
1139 "Forbidden direct cyclic configuration import (%s -> %s)\n",
1140 cf->source_filename,
1141 filename);
1142 }
1143 else
1145 "Forbidden indirect cyclic configuration import (%s -> ... -> %s -> %s)\n",
1146 cf->source_filename,
1147 parent->source_filename,
1148 filename);
1149 GNUNET_free (fn);
1150 return GNUNET_SYSERR;
1151 }
1152 }
1153
1154 }
1155
1156 /* Keep track of loaded files.*/
1157 {
1158 loaded_file = GNUNET_new (struct ConfigFile);
1159
1160 loaded_file->level = cfg->current_nest_level;
1161 loaded_file->source_filename = GNUNET_strdup (filename
1162 ? filename
1163 : "<input>");
1166 loaded_file);
1167 }
1168
1169 dirty = cfg->dirty; /* back up value! */
1170 if (GNUNET_SYSERR ==
1172 &fs64,
1173 GNUNET_NO,
1174 GNUNET_YES))
1175 {
1177 "Error while determining the file size of `%s'\n",
1178 fn);
1179 GNUNET_free (fn);
1180 return GNUNET_SYSERR;
1181 }
1182 if (fs64 > SIZE_MAX)
1183 {
1184 GNUNET_break (0); /* File size is more than the heap size */
1185 GNUNET_free (fn);
1186 return GNUNET_SYSERR;
1187 }
1188 fs = fs64;
1189 mem = GNUNET_malloc (fs);
1190 sret = GNUNET_DISK_fn_read (fn,
1191 mem,
1192 fs);
1193 if ((sret < 0) || (fs != (size_t) sret))
1194 {
1196 "Error while reading file `%s'\n",
1197 fn);
1198 GNUNET_free (fn);
1199 GNUNET_free (mem);
1200 return GNUNET_SYSERR;
1201 }
1202 if (cfg->diagnostics)
1203 {
1204 GNUNET_CRYPTO_hash (mem,
1205 fs,
1206 &loaded_file->content_hash);
1207 }
1209 "Deserializing contents of file `%s'\n",
1210 fn);
1212 mem,
1213 fs,
1214 fn);
1215 if (GNUNET_SYSERR == ret)
1216 {
1218 _ ("Failed to parse configuration file `%s'\n"),
1219 fn);
1220 }
1221 else if (cfg->diagnostics)
1222 {
1223 loaded_file->have_content_hash = true;
1224 }
1225 GNUNET_free (fn);
1226 GNUNET_free (mem);
1227 /* restore dirty flag - anything we set in the meantime
1228 * came from disk */
1229 cfg->dirty = dirty;
1230 return ret;
1231}
1232
1233
1239
1240
1248static bool
1249do_skip (const char *sec,
1250 const char *key)
1251{
1252 if (0 != strcasecmp ("PATHS",
1253 sec))
1254 return false;
1255 return ( (0 == strcasecmp ("DATADIR",
1256 key)) ||
1257 (0 == strcasecmp ("LIBDIR",
1258 key)) ||
1259 (0 == strcasecmp ("BINDIR",
1260 key)) ||
1261 (0 == strcasecmp ("PREFIX",
1262 key)) ||
1263 (0 == strcasecmp ("LOCALEDIR",
1264 key)) ||
1265 (0 == strcasecmp ("ICONDIR",
1266 key)) ||
1267 (0 == strcasecmp ("DOCDIR",
1268 key)) ||
1269 (0 == strcasecmp ("DEFAULTCONFIG",
1270 key)) ||
1271 (0 == strcasecmp ("LIBEXECDIR",
1272 key)) );
1273}
1274
1275
1276char *
1278 size_t *size)
1279{
1280 char *mem;
1281 char *cbuf;
1282 char *val;
1283 char *pos;
1284 size_t m_size;
1285 size_t c_size;
1286
1287 /* Pass1 : calculate the buffer size required */
1288 m_size = 0;
1289 for (struct ConfigSection *sec = cfg->sections;
1290 NULL != sec;
1291 sec = sec->next)
1292 {
1293 if (sec->inaccessible && (NULL == sec->entries))
1294 continue;
1295 /* For each section we need to add 3 characters: {'[',']','\n'} */
1296 m_size += strlen (sec->name) + 3;
1297 for (struct ConfigEntry *ent = sec->entries;
1298 NULL != ent;
1299 ent = ent->next)
1300 {
1301 if (do_skip (sec->name,
1302 ent->key))
1303 continue;
1304 if (NULL != ent->val)
1305 {
1306 /* if val has any '\n' then they occupy +1 character as '\n'->'\\','n' */
1307 pos = ent->val;
1308 while (NULL != (pos = strstr (pos, "\n")))
1309 {
1310 m_size++;
1311 pos++;
1312 }
1313 /* For each key = value pair we need to add 4 characters (2
1314 spaces and 1 equal-to character and 1 new line) */
1315 m_size += strlen (ent->key) + strlen (ent->val) + 4;
1316 }
1317 }
1318 /* A new line after section end */
1319 m_size++;
1320 }
1321
1322 /* Pass2: Allocate memory and write the configuration to it */
1323 mem = GNUNET_malloc (m_size);
1324 c_size = 0;
1325 *size = c_size;
1326 for (struct ConfigSection *sec = cfg->sections;
1327 NULL != sec;
1328 sec = sec->next)
1329 {
1330 int len;
1331
1332 len = GNUNET_asprintf (&cbuf,
1333 "[%s]\n",
1334 sec->name);
1335 GNUNET_assert (0 < len);
1336 GNUNET_memcpy (mem + c_size,
1337 cbuf,
1338 len);
1339 c_size += len;
1340 GNUNET_free (cbuf);
1341 for (struct ConfigEntry *ent = sec->entries;
1342 NULL != ent;
1343 ent = ent->next)
1344 {
1345 if (do_skip (sec->name,
1346 ent->key))
1347 continue;
1348 if (NULL != ent->val)
1349 {
1350 val = GNUNET_malloc (strlen (ent->val) * 2 + 1);
1351 strcpy (val, ent->val);
1352 while (NULL != (pos = strstr (val, "\n")))
1353 {
1354 memmove (&pos[2], &pos[1], strlen (&pos[1]));
1355 pos[0] = '\\';
1356 pos[1] = 'n';
1357 }
1358 len = GNUNET_asprintf (&cbuf, "%s = %s\n", ent->key, val);
1359 GNUNET_free (val);
1360 GNUNET_memcpy (mem + c_size, cbuf, len);
1361 c_size += len;
1362 GNUNET_free (cbuf);
1363 }
1364 }
1365 GNUNET_memcpy (mem + c_size, "\n", 1);
1366 c_size++;
1367 }
1368 GNUNET_assert (c_size == m_size);
1369 *size = c_size;
1370 return mem;
1371}
1372
1373
1382static void
1384 const struct GNUNET_CONFIGURATION_Handle *cfg,
1385 struct GNUNET_Buffer *buf,
1387{
1389 ipk);
1390 const char *ipkname;
1391 switch (ipk)
1392 {
1394 ipkname = "IPK_DATADIR";
1395 break;
1397 ipkname = "IPK_BINDIR";
1398 break;
1400 ipkname = "IPK_LIBDIR";
1401 break;
1403 ipkname = "IPK_PREFIX";
1405 ipkname = "IPK_LOCALEDIR";
1406 break;
1408 ipkname = "IPK_ICONDIR";
1410 ipkname = "IPK_DOCDIR";
1411 break;
1413 ipkname = "IPK_LIBEXECDIR";
1414 break;
1416 ipkname = "IPK_SELF_PREFIX";
1417 break;
1418 default:
1419 ipkname = "??";
1420 break;
1421 }
1423 "# %s = %s\n",
1424 ipkname,
1425 v);
1426 GNUNET_free (v);
1427}
1428
1429
1437static char *
1439 bool verbose)
1440{
1441 struct GNUNET_Buffer buf = { 0 };
1442
1444 "#\n# Configuration file diagnostics\n#\n");
1446 "# Entry point: %s\n",
1448 "<none>");
1450 "#\n# Files Loaded:\n");
1451
1452 for (struct ConfigFile *cfil = cfg->loaded_files_head;
1453 NULL != cfil;
1454 cfil = cfil->next)
1455 {
1457 "# ");
1458 for (unsigned int i = 0; i < cfil->level; i++)
1460 "+");
1461 if (0 != cfil->level)
1463 " ");
1464
1466 "%s",
1467 cfil->source_filename);
1468
1469 if (NULL != cfil->hint_restrict_section)
1471 " (%s secret section %s)",
1472 cfil->hint_inaccessible
1473 ? "inaccessible"
1474 : "loaded",
1475 cfil->hint_restrict_section);
1476
1478 "\n");
1479 }
1480
1482 "#\n# Installation paths:\n");
1483
1493
1494
1496 "#\n\n");
1497
1498 for (struct ConfigSection *sec = cfg->sections;
1499 NULL != sec;
1500 sec = sec->next)
1501 {
1502 if (sec->hint_secret_filename)
1504 "# secret section from %s\n# secret file stat %s\n",
1505 sec->hint_secret_filename,
1506 sec->hint_secret_stat);
1507 if (sec->hint_inlined_from_filename)
1508 {
1510 "# inlined from %s:%u\n",
1511 sec->hint_inlined_from_filename,
1512 sec->hint_inlined_from_line);
1513 }
1515 "[%s]\n\n",
1516 sec->name);
1517 if (sec->inaccessible && (NULL == sec->entries))
1518 {
1520 "# <section contents inaccessible>\n\n\n");
1521 continue;
1522 }
1523 for (struct ConfigEntry *ent = sec->entries;
1524 NULL != ent;
1525 ent = ent->next)
1526 {
1527 if (do_skip (sec->name,
1528 ent->key))
1529 continue;
1530 if (NULL != ent->val)
1531 {
1532 char *pos;
1533 char *val = GNUNET_malloc (strlen (ent->val) * 2 + 1);
1534 strcpy (val, ent->val);
1535 while (NULL != (pos = strstr (val, "\n")))
1536 {
1537 memmove (&pos[2], &pos[1], strlen (&pos[1]));
1538 pos[0] = '\\';
1539 pos[1] = 'n';
1540 }
1541 if (NULL != ent->sources)
1542 {
1543 if (verbose &&
1544 (NULL != ent->sources->next))
1545 {
1547 &buf,
1548 "# duplicate definitions (highest precedence first):\n");
1549 for (const struct ConfigSource *source = ent->sources;
1550 NULL != source;
1551 source = source->next)
1552 {
1553 const char *status;
1554
1555 if (source == ent->sources)
1556 status = "effective";
1557 else if (0 == strcmp (source->value,
1558 ent->val))
1559 status = "same value";
1560 else
1561 status = "different value";
1563 &buf,
1564 "# %s:%u (%s)\n",
1565 source->filename,
1566 source->lineno,
1567 status);
1568 }
1569 }
1570 else
1571 {
1573 "# %s:%u\n",
1574 ent->sources->filename,
1575 ent->sources->lineno);
1576 }
1577 }
1579 "%s = %s\n",
1580 ent->key,
1581 val);
1582 GNUNET_free (val);
1583 }
1584 GNUNET_buffer_write_str (&buf, "\n");
1585 }
1586 if (sec->inaccessible)
1587 {
1589 "# <additional section contents inaccessible>\n\n\n");
1590 continue;
1591 }
1592
1593 GNUNET_buffer_write_str (&buf, "\n");
1594 }
1595 return GNUNET_buffer_reap_str (&buf);
1596}
1597
1598
1599char *
1606
1607
1608char *
1615
1616
1617static enum GNUNET_GenericReturnValue
1618read_file (const char *filename,
1619 char **contents,
1620 size_t *size)
1621{
1622 uint64_t fs64;
1623 ssize_t ret;
1624
1625 if ( (GNUNET_SYSERR ==
1627 &fs64,
1628 GNUNET_NO,
1629 GNUNET_YES)) ||
1630 (fs64 > SIZE_MAX) )
1631 return GNUNET_SYSERR;
1632 *size = (size_t) fs64;
1633 *contents = GNUNET_malloc (*size);
1635 *contents,
1636 *size);
1637 if ( (ret < 0) || ((size_t) ret != *size) )
1638 {
1639 GNUNET_free (*contents);
1640 *contents = NULL;
1641 return GNUNET_SYSERR;
1642 }
1643 return GNUNET_OK;
1644}
1645
1646
1654static bool
1656 const struct GNUNET_HashCode *expected)
1657{
1658 struct GNUNET_HashCode actual;
1659 char *contents;
1660 size_t size;
1661
1663 &contents,
1664 &size))
1665 return false;
1666 GNUNET_CRYPTO_hash (contents,
1667 size,
1668 &actual);
1669 GNUNET_free (contents);
1670 return 0 == GNUNET_memcmp (&actual,
1671 expected);
1672}
1673
1674
1684static enum GNUNET_GenericReturnValue
1686 const char *contents,
1687 size_t size,
1688 const struct GNUNET_HashCode *expected_hash)
1689{
1690 char *fn;
1691 char *tfn;
1692
1694 if (fn == NULL)
1695 return GNUNET_SYSERR;
1697 {
1698 GNUNET_free (fn);
1699 return GNUNET_SYSERR;
1700 }
1701 {
1702 /* If @a filename is a symlink, replace what it points at, the way
1703 truncating it in place used to. */
1704 char *rfn = realpath (fn,
1705 NULL);
1706
1707 if (NULL != rfn)
1708 {
1709 GNUNET_free (fn);
1710 fn = GNUNET_strdup (rfn);
1711 free (rfn);
1712 }
1713 }
1714 /* Never rewrite the configuration in place: opening it with O_TRUNC leaves
1715 it observably empty until we have written the new contents, and anyone
1716 parsing the file in that instant -- say a daemon that was just started
1717 with this very configuration -- reads a truncated file and fails. So
1718 write a sibling file and rename(2) it over the target; readers then
1719 always see either the complete old or the complete new configuration. */
1720 GNUNET_asprintf (&tfn,
1721 "%s.%u.tmp",
1722 fn,
1723 (unsigned int) getpid ());
1724 {
1725 struct GNUNET_DISK_FileHandle *h;
1726
1727 h = GNUNET_DISK_file_open (tfn,
1735 if (NULL == h)
1736 {
1737 GNUNET_free (tfn);
1738 GNUNET_free (fn);
1739 return GNUNET_SYSERR;
1740 }
1741 if (((ssize_t) size) !=
1743 contents,
1744 size))
1745 {
1747 "write",
1748 tfn);
1750 (void) unlink (tfn);
1751 GNUNET_free (tfn);
1752 GNUNET_free (fn);
1753 return GNUNET_SYSERR;
1754 }
1755 /* Get the contents onto the disk before the rename publishes them, so
1756 that a crash cannot leave an empty configuration behind. */
1758 {
1760 "fsync",
1761 tfn);
1762 (void) GNUNET_DISK_file_close (h);
1763 (void) unlink (tfn);
1764 GNUNET_free (tfn);
1765 GNUNET_free (fn);
1766 return GNUNET_SYSERR;
1767 }
1769 {
1771 "close",
1772 tfn);
1773 (void) unlink (tfn);
1774 GNUNET_free (tfn);
1775 GNUNET_free (fn);
1776 return GNUNET_SYSERR;
1777 }
1778 }
1779 {
1780 struct stat sbuf;
1781
1782 /* rename(2) replaces the inode, so carry over the permissions of the
1783 configuration we are about to replace (we just created @a tfn). */
1784 if ( (0 == stat (fn,
1785 &sbuf)) &&
1786 (0 != chmod (tfn,
1787 sbuf.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO))) )
1789 "chmod",
1790 tfn);
1791 }
1792 if ( (NULL != expected_hash) &&
1793 (! file_hash_matches (fn,
1794 expected_hash)) )
1795 {
1797 "Configuration file `%s' changed while it was being cleaned\n",
1798 fn);
1799 (void) unlink (tfn);
1800 GNUNET_free (tfn);
1801 GNUNET_free (fn);
1802 return GNUNET_SYSERR;
1803 }
1804 if (0 != rename (tfn,
1805 fn))
1806 {
1808 "rename",
1809 fn);
1810 (void) unlink (tfn);
1811 GNUNET_free (tfn);
1812 GNUNET_free (fn);
1813 return GNUNET_SYSERR;
1814 }
1815 GNUNET_free (tfn);
1816 GNUNET_free (fn);
1817 return GNUNET_OK;
1818}
1819
1820
1824 const char *filename)
1825{
1827 char *cfg_buf;
1828 size_t size;
1829
1831 &size);
1833 cfg_buf,
1834 size,
1835 NULL);
1836 GNUNET_free (cfg_buf);
1838 return ret;
1839}
1840
1841
1846{
1847 const char *section;
1848 const char *option;
1849 unsigned int line;
1851};
1852
1853
1857static struct CleanLine *
1859 unsigned int lines_length,
1860 unsigned int line)
1861{
1862 for (unsigned int i = 0; i < lines_length; i++)
1863 if (lines[i].line == line)
1864 return &lines[i];
1865 return NULL;
1866}
1867
1868
1872static bool
1874 const char *target,
1875 struct CleanLine *lines,
1876 unsigned int lines_length)
1877{
1878 struct CleanLine *line;
1879
1880 if (0 != strcmp (source->filename,
1881 target))
1882 return false;
1883 line = find_clean_line (lines,
1884 lines_length,
1885 source->lineno);
1886 return (NULL != line) && line->remove;
1887}
1888
1889
1893static int
1894clean_line_cmp (const void *a,
1895 const void *b)
1896{
1897 const struct CleanLine *la = a;
1898 const struct CleanLine *lb = b;
1899
1900 if (la->line < lb->line)
1901 return -1;
1902 if (la->line > lb->line)
1903 return 1;
1904 return 0;
1905}
1906
1907
1910 const struct GNUNET_CONFIGURATION_Handle *cfg,
1911 const char *filename,
1913 void *cb_cls,
1914 unsigned int *removed)
1915{
1916 struct CleanLine *lines = NULL;
1917 unsigned int lines_length = 0;
1918 const struct ConfigFile *parsed_file = NULL;
1919 char *target;
1920 char *contents = NULL;
1921 char *cleaned = NULL;
1922 size_t size;
1923 size_t cleaned_size = 0;
1925
1926 if (NULL != removed)
1927 *removed = 0;
1928 if ( (! cfg->diagnostics) ||
1929 (NULL == filename) )
1930 return GNUNET_SYSERR;
1932 if (NULL == target)
1933 return GNUNET_SYSERR;
1934
1935 for (const struct ConfigFile *cf = cfg->loaded_files_head;
1936 NULL != cf;
1937 cf = cf->next)
1938 {
1939 char *source;
1940
1941 if (! cf->have_content_hash)
1942 continue;
1943 source = GNUNET_STRINGS_filename_expand (cf->source_filename);
1944 if ( (NULL != source) &&
1945 (0 == strcmp (source,
1946 target)) )
1947 parsed_file = cf;
1949 }
1950 if (NULL == parsed_file)
1951 {
1953 "Configuration file `%s' was not parsed with diagnostics enabled\n",
1954 target);
1955 goto cleanup;
1956 }
1957 if (GNUNET_OK != read_file (target,
1958 &contents,
1959 &size))
1960 {
1962 "Configuration file `%s' changed since it was parsed\n",
1963 target);
1964 goto cleanup;
1965 }
1966 {
1967 struct GNUNET_HashCode actual;
1968
1969 GNUNET_CRYPTO_hash (contents,
1970 size,
1971 &actual);
1972 if (0 != GNUNET_memcmp (&actual,
1973 &parsed_file->content_hash))
1974 {
1976 "Configuration file `%s' changed since it was parsed\n",
1977 target);
1978 goto cleanup;
1979 }
1980 }
1981
1982 /* First mark every target definition that has an exact duplicate at a
1983 distinct source location. */
1984 for (const struct ConfigSection *sec = cfg->sections;
1985 NULL != sec;
1986 sec = sec->next)
1987 for (const struct ConfigEntry *ent = sec->entries;
1988 NULL != ent;
1989 ent = ent->next)
1990 for (const struct ConfigSource *source = ent->sources;
1991 NULL != source;
1992 source = source->next)
1993 {
1994 bool duplicate = false;
1995 struct CleanLine line;
1996
1997 if (0 != strcmp (source->filename,
1998 target))
1999 continue;
2000 for (const struct ConfigSource *other = ent->sources;
2001 NULL != other;
2002 other = other->next)
2003 {
2004 if ( (0 == strcmp (source->value,
2005 other->value)) &&
2006 ( (source->lineno != other->lineno) ||
2007 (0 != strcmp (source->filename,
2008 other->filename)) ) )
2009 {
2010 duplicate = true;
2011 break;
2012 }
2013 }
2014 if ( (! duplicate) ||
2015 (NULL != find_clean_line (lines,
2016 lines_length,
2017 source->lineno)) )
2018 continue;
2019 line.section = sec->name;
2020 line.option = ent->key;
2021 line.line = source->lineno;
2022 line.remove = true;
2023 GNUNET_array_append (lines,
2024 lines_length,
2025 line);
2026 }
2027
2028 /* Keep the highest-precedence target duplicate needed to preserve every
2029 effective value after all of the tentative removals. */
2030 for (const struct ConfigSection *sec = cfg->sections;
2031 NULL != sec;
2032 sec = sec->next)
2033 for (const struct ConfigEntry *ent = sec->entries;
2034 NULL != ent;
2035 ent = ent->next)
2036 {
2037 const struct ConfigSource *survivor = NULL;
2038
2039 for (const struct ConfigSource *source = ent->sources;
2040 NULL != source;
2041 source = source->next)
2043 target,
2044 lines,
2045 lines_length))
2046 {
2047 survivor = source;
2048 break;
2049 }
2050 if ( (NULL != survivor) &&
2051 (0 == strcmp (survivor->value,
2052 ent->val)) )
2053 continue;
2054 for (const struct ConfigSource *source = ent->sources;
2055 NULL != source;
2056 source = source->next)
2057 {
2058 struct CleanLine *line;
2059
2060 if ( (0 != strcmp (source->filename,
2061 target)) ||
2062 (0 != strcmp (source->value,
2063 ent->val)) )
2064 continue;
2065 line = find_clean_line (lines,
2066 lines_length,
2067 source->lineno);
2068 if ( (NULL != line) && line->remove)
2069 {
2070 line->remove = false;
2071 break;
2072 }
2073 }
2074 }
2075
2076 if (lines_length > 1)
2077 qsort (lines,
2078 lines_length,
2079 sizeof (*lines),
2081 {
2082 unsigned int remove_count = 0;
2083
2084 for (unsigned int i = 0; i < lines_length; i++)
2085 if (lines[i].remove)
2086 remove_count++;
2087 if (0 == remove_count)
2088 {
2089 if (NULL != removed)
2090 *removed = 0;
2091 ret = GNUNET_OK;
2092 goto cleanup;
2093 }
2094
2095 cleaned = GNUNET_malloc (size);
2096 for (size_t offset = 0, line_number = 1; offset < size; line_number++)
2097 {
2098 size_t end = offset;
2099 struct CleanLine *line;
2100
2101 while ( (end < size) && ('\n' != contents[end]) )
2102 end++;
2103 if (end < size)
2104 end++;
2105 line = find_clean_line (lines,
2106 lines_length,
2107 (unsigned int) line_number);
2108 if ( (NULL == line) || (! line->remove) )
2109 {
2110 GNUNET_memcpy (&cleaned[cleaned_size],
2111 &contents[offset],
2112 end - offset);
2113 cleaned_size += end - offset;
2114 }
2115 offset = end;
2116 }
2117 if (GNUNET_OK !=
2118 write_buffer_atomic (target,
2119 cleaned,
2120 cleaned_size,
2121 &parsed_file->content_hash))
2122 goto cleanup;
2123 if (NULL != removed)
2124 *removed = remove_count;
2125 if (NULL != cb)
2126 for (unsigned int i = 0; i < lines_length; i++)
2127 if (lines[i].remove)
2128 cb (cb_cls,
2129 lines[i].section,
2130 lines[i].option,
2131 lines[i].line);
2132 ret = GNUNET_OK;
2133 }
2134
2135cleanup:
2136 GNUNET_free (cleaned);
2137 GNUNET_free (contents);
2138 GNUNET_array_grow (lines,
2139 lines_length,
2140 0);
2141 GNUNET_free (target);
2142 return ret;
2143}
2144
2145
2146void
2148 const struct GNUNET_CONFIGURATION_Handle *cfg,
2150 void *iter_cls)
2151{
2152 for (struct ConfigSection *spos = cfg->sections;
2153 NULL != spos;
2154 spos = spos->next)
2155 for (struct ConfigEntry *epos = spos->entries;
2156 NULL != epos;
2157 epos = epos->next)
2158 if (NULL != epos->val)
2159 iter (iter_cls,
2160 spos->name,
2161 epos->key,
2162 epos->val);
2163}
2164
2165
2166void
2168 const struct GNUNET_CONFIGURATION_Handle *cfg,
2169 const char *section,
2171 void *iter_cls)
2172{
2173 struct ConfigSection *spos;
2174
2175 spos = cfg->sections;
2176 while ((spos != NULL) && (0 != strcasecmp (spos->name, section)))
2177 spos = spos->next;
2178 if (NULL == spos)
2179 return;
2180 for (struct ConfigEntry *epos = spos->entries;
2181 NULL != epos;
2182 epos = epos->next)
2183 if (NULL != epos->val)
2184 iter (iter_cls,
2185 spos->name,
2186 epos->key,
2187 epos->val);
2188 if (spos->inaccessible)
2189 {
2191 "Section '%s' is marked as inaccessible, because a configuration "
2192 "file that contains the section can't be read.\n",
2193 section);
2194 return;
2195 }
2196}
2197
2198
2199void
2201 const struct GNUNET_CONFIGURATION_Handle *cfg,
2203 void *iter_cls)
2204{
2205 struct ConfigSection *spos;
2206 struct ConfigSection *next;
2207
2208 next = cfg->sections;
2209 while (NULL != next)
2210 {
2211 spos = next;
2212 next = spos->next;
2213 if (spos->inaccessible && (NULL == spos->entries))
2214 continue;
2215 iter (iter_cls,
2216 spos->name);
2217 }
2218}
2219
2220
2221void
2223 const char *section)
2224{
2225 struct ConfigSection *spos;
2226 struct ConfigSection *prev;
2227 struct ConfigEntry *ent;
2228
2229 prev = NULL;
2230 spos = cfg->sections;
2231 while (NULL != spos)
2232 {
2233 if (0 == strcasecmp (section,
2234 spos->name))
2235 {
2236 if (NULL == prev)
2237 cfg->sections = spos->next;
2238 else
2239 prev->next = spos->next;
2240 while (NULL != (ent = spos->entries))
2241 {
2242 struct ConfigSource *source;
2243
2244 spos->entries = ent->next;
2245 GNUNET_free (ent->key);
2246 GNUNET_free (ent->val);
2247 while (NULL != (source = ent->sources))
2248 {
2249 ent->sources = source->next;
2250 GNUNET_free (source->value);
2251 GNUNET_free (source->filename);
2253 }
2254 GNUNET_free (ent);
2255 cfg->dirty = GNUNET_YES;
2256 }
2257 GNUNET_free (spos->name);
2261 GNUNET_free (spos);
2262 return;
2263 }
2264 prev = spos;
2265 spos = spos->next;
2266 }
2267}
2268
2269
2279static void
2280copy_entry (void *cls,
2281 const char *section,
2282 const char *option,
2283 const char *value)
2284{
2285 struct GNUNET_CONFIGURATION_Handle *dst = cls;
2286
2288 section,
2289 option,
2290 value);
2291}
2292
2293
2306
2307
2318static void
2320 const char *section,
2321 const char *option,
2322 const char *value)
2323{
2324 struct DiffHandle *dh = cls;
2325 struct ConfigEntry *entNew;
2326
2327 entNew = find_entry (dh->cfg_default, section, option);
2328 if ((NULL != entNew) && (NULL != entNew->val) &&
2329 (0 == strcmp (entNew->val, value)))
2330 return;
2332 section,
2333 option,
2334 value);
2335}
2336
2337
2340 const struct GNUNET_CONFIGURATION_Handle *cfg_default,
2341 const struct GNUNET_CONFIGURATION_Handle *cfg_new)
2342{
2343 struct DiffHandle diffHandle;
2344
2345 GNUNET_break (cfg_default->pd == cfg_new->pd);
2346 diffHandle.cfgDiff = GNUNET_CONFIGURATION_create (cfg_new->pd);
2347 diffHandle.cfg_default = cfg_default;
2350 &diffHandle);
2351 return diffHandle.cfgDiff;
2352}
2353
2354
2358 const struct GNUNET_CONFIGURATION_Handle *cfg_new,
2359 const char *filename)
2360{
2361 int ret;
2362 struct GNUNET_CONFIGURATION_Handle *diff;
2363
2364 diff = GNUNET_CONFIGURATION_get_diff (cfg_default, cfg_new);
2367 return ret;
2368}
2369
2370
2371void
2374 const char *section,
2375 const char *option,
2376 const char *value)
2377{
2378 struct ConfigSection *sec;
2379 struct ConfigEntry *e;
2380 char *nv;
2381
2382 e = find_entry (cfg, section, option);
2383 if (NULL != e)
2384 {
2385 if (NULL == value)
2386 {
2387 GNUNET_free (e->val);
2388 e->val = NULL;
2389 }
2390 else
2391 {
2392 nv = GNUNET_strdup (value);
2393 GNUNET_free (e->val);
2394 e->val = nv;
2395 }
2396 return;
2397 }
2398 sec = find_section (cfg, section);
2399 if (sec == NULL)
2400 {
2401 sec = GNUNET_new (struct ConfigSection);
2402 sec->name = GNUNET_strdup (section);
2403 sec->next = cfg->sections;
2404 cfg->sections = sec;
2405 }
2406 e = GNUNET_new (struct ConfigEntry);
2407 e->key = GNUNET_strdup (option);
2408 e->val = GNUNET_strdup (value);
2409 e->next = sec->entries;
2410 sec->entries = e;
2411}
2412
2413
2414void
2416 const char *section,
2417 const char *option,
2418 unsigned long long number)
2419{
2420 char s[64];
2421
2422 GNUNET_snprintf (s,
2423 64,
2424 "%llu",
2425 number);
2427 section,
2428 option,
2429 s);
2430}
2431
2432
2435 const struct GNUNET_CONFIGURATION_Handle *cfg,
2436 const char *section,
2437 const char *option,
2438 unsigned long long *number)
2439{
2440 struct ConfigEntry *e;
2441 char dummy[2];
2442
2443 if (NULL == (e = find_entry (cfg,
2444 section,
2445 option)))
2446 return GNUNET_NO;
2447 if (NULL == e->val)
2448 return GNUNET_NO;
2449 if (1 != sscanf (e->val,
2450 "%llu%1s",
2451 number,
2452 dummy))
2453 return GNUNET_SYSERR;
2454 return GNUNET_OK;
2455}
2456
2457
2458void
2460 const char *section,
2461 const char *option,
2462 float number)
2463{
2464 char s[64];
2465
2466 /* See: #9369 */
2467 const locale_t cl = newlocale (LC_NUMERIC_MASK,
2468 "C",
2469 (locale_t) 0);
2470 locale_t old_locale = uselocale (cl);
2471 GNUNET_snprintf (s,
2472 64,
2473 "%f",
2474 (double) number);
2475 uselocale (old_locale);
2477 section,
2478 option,
2479 s);
2480}
2481
2482
2485 const struct GNUNET_CONFIGURATION_Handle *cfg,
2486 const char *section,
2487 const char *option,
2488 float *number)
2489{
2490 struct ConfigEntry *e;
2491 char dummy[2];
2492
2493 if (NULL == (e = find_entry (cfg,
2494 section,
2495 option)))
2496 return GNUNET_NO;
2497 if (NULL == e->val)
2498 return GNUNET_NO;
2499 /* See #9369 */
2500 {
2501 const locale_t cl = newlocale (LC_NUMERIC_MASK,
2502 "C",
2503 (locale_t) 0);
2504 locale_t old_locale = uselocale (cl);
2505
2506 if (1 != sscanf (e->val,
2507 "%f%1s",
2508 number,
2509 dummy))
2510 return GNUNET_SYSERR;
2511 uselocale (old_locale);
2512 }
2513 return GNUNET_OK;
2514}
2515
2516
2519 const struct GNUNET_CONFIGURATION_Handle *cfg,
2520 const char *section,
2521 const char *option,
2522 struct GNUNET_TIME_Relative *time)
2523{
2524 struct ConfigEntry *e;
2525 int ret;
2526
2527 if (NULL == (e = find_entry (cfg,
2528 section,
2529 option)))
2530 return GNUNET_NO;
2531 if (NULL == e->val)
2532 return GNUNET_NO;
2534 time);
2535 if (GNUNET_OK != ret)
2537 section,
2538 option,
2539 _ ("Not a valid relative time specification"));
2540 return ret;
2541}
2542
2543
2546 const struct GNUNET_CONFIGURATION_Handle *cfg,
2547 const char *section,
2548 const char *option,
2549 unsigned long long *size)
2550{
2551 struct ConfigEntry *e;
2552
2553 if (NULL == (e = find_entry (cfg,
2554 section,
2555 option)))
2556 return GNUNET_NO;
2557 if (NULL == e->val)
2558 return GNUNET_NO;
2560 size);
2561}
2562
2563
2576 const struct GNUNET_CONFIGURATION_Handle *cfg,
2577 const char *section,
2578 const char *option,
2579 char **value)
2580{
2581 struct ConfigEntry *e;
2582
2583 if ( (NULL == (e = find_entry (cfg,
2584 section,
2585 option))) ||
2586 (NULL == e->val) )
2587 {
2588 *value = NULL;
2589 return GNUNET_NO;
2590 }
2591 *value = GNUNET_strdup (e->val);
2592 return GNUNET_OK;
2593}
2594
2595
2598 const struct GNUNET_CONFIGURATION_Handle *cfg,
2599 const char *section,
2600 const char *option,
2601 const char *const *choices,
2602 const char **value)
2603{
2604 struct ConfigEntry *e;
2605 unsigned int i;
2606
2607 if (NULL == (e = find_entry (cfg,
2608 section,
2609 option)))
2610 return GNUNET_NO;
2611 for (i = 0; NULL != choices[i]; i++)
2612 if (0 == strcasecmp (choices[i], e->val))
2613 break;
2614 if (NULL == choices[i])
2615 {
2617 _ ("Configuration value '%s' for '%s'"
2618 " in section '%s' is not in set of legal choices\n"),
2619 e->val,
2620 option,
2621 section);
2622 return GNUNET_SYSERR;
2623 }
2624 *value = choices[i];
2625 return GNUNET_OK;
2626}
2627
2628
2631 const char *section,
2632 const char *option,
2633 void *buf,
2634 size_t buf_size)
2635{
2636 char *enc;
2637 int res;
2638 size_t data_size;
2639
2640 if (GNUNET_OK !=
2641 (res =
2643 section,
2644 option,
2645 &enc)))
2646 return res;
2647 data_size = (strlen (enc) * 5) / 8;
2648 if (data_size != buf_size)
2649 {
2650 GNUNET_free (enc);
2651 return GNUNET_SYSERR;
2652 }
2653 if (GNUNET_OK !=
2655 strlen (enc),
2656 buf,
2657 buf_size))
2658 {
2659 GNUNET_free (enc);
2660 return GNUNET_SYSERR;
2661 }
2662 GNUNET_free (enc);
2663 return GNUNET_OK;
2664}
2665
2666
2669 const char *section,
2670 const char *option)
2671{
2672 struct ConfigEntry *e;
2673
2674 if ( (NULL == (e = find_entry (cfg,
2675 section,
2676 option))) ||
2677 (NULL == e->val) )
2678 return GNUNET_NO;
2679 return GNUNET_YES;
2680}
2681
2682
2698static char *
2700 char *orig,
2701 unsigned int depth)
2702{
2703 char *prefix;
2704 char *result;
2705 char *start;
2706 const char *post;
2707 const char *env;
2708 char *def;
2709 char *end;
2710 unsigned int lopen;
2711 char erased_char;
2712 char *erased_pos;
2713 size_t len;
2714
2715 if (NULL == orig)
2716 return NULL;
2717 if (depth > 128)
2718 {
2720 "Recursive expansion suspected, aborting $-expansion for term `%s'\n",
2721 orig);
2722 return orig;
2723 }
2725 "Asked to $-expand %s\n",
2726 orig);
2727 if ('$' != orig[0])
2728 {
2730 "Doesn't start with $ - not expanding\n");
2731 return orig;
2732 }
2733 erased_char = 0;
2734 erased_pos = NULL;
2735 if ('{' == orig[1])
2736 {
2737 start = &orig[2];
2738 lopen = 1;
2739 end = &orig[1];
2740 while (lopen > 0)
2741 {
2742 end++;
2743 switch (*end)
2744 {
2745 case '}':
2746 lopen--;
2747 break;
2748
2749 case '{':
2750 lopen++;
2751 break;
2752
2753 case '\0':
2755 "Missing closing `}' in option `%s'\n",
2756 orig);
2757 return orig;
2758
2759 default:
2760 break;
2761 }
2762 }
2763 erased_char = *end;
2764 erased_pos = end;
2765 *end = '\0';
2766 post = end + 1;
2767 def = strchr (orig, ':');
2768 if (NULL != def)
2769 {
2770 *def = '\0';
2771 def++;
2772 if (('-' == *def) || ('=' == *def))
2773 def++;
2774 def = GNUNET_strdup (def);
2775 }
2776 }
2777 else
2778 {
2779 int i;
2780
2781 start = &orig[1];
2782 def = NULL;
2783 i = 0;
2784 while ( (orig[i] != '/') &&
2785 (orig[i] != '\\') &&
2786 (orig[i] != '\0') &&
2787 (orig[i] != ' ') )
2788 i++;
2789 if (orig[i] == '\0')
2790 {
2791 post = "";
2792 }
2793 else
2794 {
2795 erased_char = orig[i];
2796 erased_pos = &orig[i];
2797 orig[i] = '\0';
2798 post = &orig[i + 1];
2799 }
2800 }
2802 "Split into `%s' and `%s' with default %s\n",
2803 start,
2804 post,
2805 def);
2806 if (GNUNET_OK !=
2808 "PATHS",
2809 start,
2810 &prefix))
2811 {
2812 if (NULL == (env = getenv (start)))
2813 {
2814 /* try default */
2815 def = expand_dollar (cfg,
2816 def,
2817 depth + 1);
2818 env = def;
2819 }
2820 if (NULL == env)
2821 {
2823 if (erased_pos)
2824 *erased_pos = erased_char;
2826 "Failed to expand `%s' in `%s' as it is neither found in [PATHS] nor defined as an environmental variable\n",
2827 start,
2828 orig);
2830 return orig;
2831 }
2833 }
2835 prefix);
2836 if ((erased_pos) && ('}' != erased_char))
2837 {
2838 len = strlen (prefix) + 1;
2839 prefix = GNUNET_realloc (prefix, len + 1);
2840 prefix[len - 1] = erased_char;
2841 prefix[len] = '\0';
2842 }
2843 result = GNUNET_malloc (strlen (prefix) + strlen (post) + 1);
2844 strcpy (result, prefix);
2845 strcat (result, post);
2846 GNUNET_free (def);
2848 GNUNET_free (orig);
2849 return result;
2850}
2851
2852
2853char *
2855 const struct GNUNET_CONFIGURATION_Handle *cfg,
2856 char *orig)
2857{
2858 char *dup;
2859 size_t i;
2860 size_t len;
2861
2862 for (i = 0; '\0' != orig[i]; i++)
2863 {
2864 if ('$' != orig[i])
2865 continue;
2866 dup = GNUNET_strdup (orig + i);
2867 dup = expand_dollar (cfg, dup, 0);
2868 GNUNET_assert (NULL != dup); /* make compiler happy */
2869 len = strlen (dup) + 1;
2870 orig = GNUNET_realloc (orig, i + len);
2871 GNUNET_memcpy (orig + i, dup, len);
2872 GNUNET_free (dup);
2873 }
2874 return orig;
2875}
2876
2877
2880 const struct GNUNET_CONFIGURATION_Handle *cfg,
2881 const char *section,
2882 const char *option,
2883 char **value)
2884{
2885 char *tmp;
2887
2889 section,
2890 option,
2891 &tmp);
2892 if (GNUNET_OK != ret)
2893 {
2895 "Failed to retrieve filename\n");
2896 *value = NULL;
2897 return ret;
2898 }
2900 tmp);
2902 GNUNET_free (tmp);
2903 if (*value == NULL)
2904 return GNUNET_SYSERR;
2905 return GNUNET_OK;
2906}
2907
2908
2911 const struct GNUNET_CONFIGURATION_Handle *cfg,
2912 const char *section,
2913 const char *option)
2914{
2915 static const char *yesno[] = {
2916 "YES",
2917 "NO",
2918 NULL
2919 };
2920 const char *val;
2922
2923 ret =
2925 section,
2926 option,
2927 yesno,
2928 &val);
2929 if (GNUNET_OK != ret)
2930 return ret;
2931 if (val == yesno[0])
2932 return GNUNET_YES;
2933 return GNUNET_NO;
2934}
2935
2936
2937int
2939 const struct GNUNET_CONFIGURATION_Handle *cfg,
2940 const char *section,
2941 const char *option,
2943 void *cb_cls)
2944{
2945 char *list;
2946 char *pos;
2947 char *end;
2948 char old;
2949 int ret;
2950
2951 if (GNUNET_OK !=
2953 section,
2954 option,
2955 &list))
2956 return 0;
2957 GNUNET_assert (list != NULL);
2958 ret = 0;
2959 pos = list;
2960 while (1)
2961 {
2962 while (pos[0] == ' ')
2963 pos++;
2964 if (strlen (pos) == 0)
2965 break;
2966 end = pos + 1;
2967 while ((end[0] != ' ') && (end[0] != '\0'))
2968 {
2969 if (end[0] == '\\')
2970 {
2971 switch (end[1])
2972 {
2973 case '\\':
2974 case ' ':
2975 memmove (end, &end[1], strlen (&end[1]) + 1);
2976
2977 case '\0':
2978 /* illegal, but just keep it */
2979 break;
2980
2981 default:
2982 /* illegal, but just ignore that there was a '/' */
2983 break;
2984 }
2985 }
2986 end++;
2987 }
2988 old = end[0];
2989 end[0] = '\0';
2990 if (strlen (pos) > 0)
2991 {
2992 ret++;
2993 if ( (NULL != cb) &&
2994 (GNUNET_OK != cb (cb_cls,
2995 pos)))
2996 {
2998 break;
2999 }
3000 }
3001 if (old == '\0')
3002 break;
3003 pos = end + 1;
3004 }
3005 GNUNET_free (list);
3006 return ret;
3007}
3008
3009
3016static char *
3017escape_name (const char *value)
3018{
3019 char *escaped;
3020 const char *rpos;
3021 char *wpos;
3022
3023 escaped = GNUNET_malloc (strlen (value) * 2 + 1);
3024 memset (escaped, 0, strlen (value) * 2 + 1);
3025 rpos = value;
3026 wpos = escaped;
3027 while (rpos[0] != '\0')
3028 {
3029 switch (rpos[0])
3030 {
3031 case '\\':
3032 case ' ':
3033 wpos[0] = '\\';
3034 wpos[1] = rpos[0];
3035 wpos += 2;
3036 break;
3037
3038 default:
3039 wpos[0] = rpos[0];
3040 wpos++;
3041 }
3042 rpos++;
3043 }
3044 return escaped;
3045}
3046
3047
3055static enum GNUNET_GenericReturnValue
3056test_match (void *cls,
3057 const char *fn)
3058{
3059 const char *of = cls;
3060
3061 return (0 == strcmp (of, fn))
3063 : GNUNET_OK;
3064}
3065
3066
3070 const char *section,
3071 const char *option,
3072 const char *value)
3073{
3074 char *escaped;
3075 char *old;
3076 char *nw;
3077
3078 if (GNUNET_SYSERR ==
3080 section,
3081 option,
3082 &test_match,
3083 (void *) value))
3084 return GNUNET_NO; /* already exists */
3085 if (GNUNET_OK !=
3086 GNUNET_CONFIGURATION_get_value_string (cfg, section, option, &old))
3087 old = GNUNET_strdup ("");
3088 escaped = escape_name (value);
3089 nw = GNUNET_malloc (strlen (old) + strlen (escaped) + 2);
3090 strcpy (nw, old);
3091 if (strlen (old) > 0)
3092 strcat (nw, " ");
3093 strcat (nw, escaped);
3095 section,
3096 option,
3097 nw);
3098 GNUNET_free (old);
3099 GNUNET_free (nw);
3100 GNUNET_free (escaped);
3101 return GNUNET_OK;
3102}
3103
3104
3108 const char *section,
3109 const char *option,
3110 const char *value)
3111{
3112 char *list;
3113 char *pos;
3114 char *end;
3115 char *match;
3116 char old;
3117
3118 if (GNUNET_OK !=
3120 section,
3121 option,
3122 &list))
3123 return GNUNET_NO;
3124 match = escape_name (value);
3125 pos = list;
3126 while (1)
3127 {
3128 while (pos[0] == ' ')
3129 pos++;
3130 if (strlen (pos) == 0)
3131 break;
3132 end = pos + 1;
3133 while ((end[0] != ' ') && (end[0] != '\0'))
3134 {
3135 if (end[0] == '\\')
3136 {
3137 switch (end[1])
3138 {
3139 case '\\':
3140 case ' ':
3141 end++;
3142 break;
3143
3144 case '\0':
3145 /* illegal, but just keep it */
3146 break;
3147
3148 default:
3149 /* illegal, but just ignore that there was a '/' */
3150 break;
3151 }
3152 }
3153 end++;
3154 }
3155 old = end[0];
3156 end[0] = '\0';
3157 if (0 == strcmp (pos, match))
3158 {
3159 if (old != '\0')
3160 memmove (pos,
3161 &end[1],
3162 strlen (&end[1]) + 1);
3163 else
3164 {
3165 if (pos != list)
3166 pos[-1] = '\0';
3167 else
3168 pos[0] = '\0';
3169 }
3171 section,
3172 option,
3173 list);
3174 GNUNET_free (list);
3175 GNUNET_free (match);
3176 return GNUNET_OK;
3177 }
3178 if (old == '\0')
3179 break;
3180 end[0] = old;
3181 pos = end + 1;
3182 }
3183 GNUNET_free (list);
3184 GNUNET_free (match);
3185 return GNUNET_NO;
3186}
3187
3188
3192 const char *defaults_d)
3193{
3194 struct CollectFilesContext files_context = {
3195 .files = NULL,
3196 .files_length = 0,
3197 };
3198 enum GNUNET_GenericReturnValue fun_ret = GNUNET_NO;
3199
3200 if (GNUNET_SYSERR ==
3201 GNUNET_DISK_directory_scan (defaults_d,
3203 &files_context))
3204 return GNUNET_SYSERR; /* no configuration at all found */
3205 qsort (files_context.files,
3206 files_context.files_length,
3207 sizeof (char *),
3208 &pstrcmp);
3209 for (unsigned int i = 0; i < files_context.files_length; i++)
3210 {
3211 const char *ext;
3212 const char *filename = files_context.files[i];
3213
3214 /* Examine file extension */
3215 ext = strrchr (filename, '.');
3216 if ( (NULL == ext) ||
3217 (0 != strcmp (ext,
3218 ".conf")) )
3219 {
3221 "Skipping file `%s'\n",
3222 filename);
3223 fun_ret = GNUNET_OK;
3224 continue;
3225 }
3227 filename);
3228 if (fun_ret != GNUNET_OK)
3229 break;
3230 }
3231 if (files_context.files_length > 0)
3232 {
3233 for (size_t i = 0; i < files_context.files_length; i++)
3234 GNUNET_free (files_context.files[i]);
3235 GNUNET_array_grow (files_context.files,
3236 files_context.files_length,
3237 0);
3238 }
3239 return fun_ret;
3240}
3241
3242
3243char *
3245 const struct GNUNET_OS_ProjectData *pd)
3246{
3247 char *cfg_fn;
3248 const char *xdg = getenv ("XDG_CONFIG_HOME");
3249
3250 if (NULL != xdg)
3251 GNUNET_asprintf (&cfg_fn,
3252 "%s%s%s",
3253 xdg,
3255 pd->config_file);
3256 else
3257 cfg_fn = GNUNET_strdup (pd->user_config_file);
3258
3259 if (GNUNET_OK == GNUNET_DISK_file_test_read (cfg_fn))
3260 return cfg_fn;
3261 GNUNET_free (cfg_fn);
3262
3263 /* Fall back to /etc/ for the default configuration.
3264 Should be okay to use forward slashes here. */
3265
3266 GNUNET_asprintf (&cfg_fn,
3267 "/etc/%s",
3268 pd->config_file);
3269 if (GNUNET_OK ==
3271 return cfg_fn;
3272 GNUNET_free (cfg_fn);
3273
3274 GNUNET_asprintf (&cfg_fn,
3275 "/etc/%s/%s",
3276 pd->project_dirname,
3277 pd->config_file);
3278 if (GNUNET_OK ==
3280 return cfg_fn;
3281
3282 GNUNET_free (cfg_fn);
3283 return NULL;
3284}
3285
3286
3290 const char *filename)
3291{
3292 char *baseconfig;
3293 const char *base_config_varname;
3294
3295 if (cfg->load_called)
3296 {
3297 /* FIXME: Make this a GNUNET_assert later */
3298 GNUNET_break (0);
3300 }
3301 cfg->load_called = true;
3302 if (NULL != filename)
3303 {
3306 }
3307
3308 base_config_varname = cfg->pd->base_config_varname;
3309
3310 if ((NULL != base_config_varname)
3311 && (NULL != (baseconfig = getenv (base_config_varname))))
3312 {
3313 baseconfig = GNUNET_strdup (baseconfig);
3314 }
3315 else
3316 {
3317 char *ipath;
3318
3321 if (NULL == ipath)
3322 {
3323 GNUNET_break (0);
3324 return GNUNET_SYSERR;
3325 }
3326 GNUNET_asprintf (&baseconfig,
3327 "%s%s",
3328 ipath,
3329 "config.d");
3330 GNUNET_free (ipath);
3331 }
3332
3333 {
3334 char *dname = GNUNET_STRINGS_filename_expand (baseconfig);
3335
3336 GNUNET_free (baseconfig);
3337
3338 if ((GNUNET_YES ==
3340 GNUNET_YES)) &&
3341 (GNUNET_SYSERR ==
3343 dname)))
3344 {
3346 "Failed to load base configuration from '%s'\n",
3347 filename);
3348 GNUNET_free (dname);
3349 return GNUNET_SYSERR; /* no configuration at all found */
3350 }
3351 GNUNET_free (dname);
3352 }
3353 if ((NULL != filename) &&
3354 (GNUNET_OK !=
3356 filename)))
3357 {
3358 /* specified configuration not found */
3360 "Failed to load configuration from file '%s'\n",
3361 filename);
3362 return GNUNET_SYSERR;
3363 }
3364 if (((GNUNET_YES !=
3366 "PATHS",
3367 "DEFAULTCONFIG"))) &&
3368 (filename != NULL))
3370 "PATHS",
3371 "DEFAULTCONFIG",
3372 filename);
3373 return GNUNET_OK;
3374}
3375
3376
3385static void
3387 const char *section,
3388 const char *option,
3389 const char *value)
3390{
3391 const struct GNUNET_CONFIGURATION_Handle *cfg = cls;
3392
3393 char *value_fn;
3394 char *fn;
3395
3398 section,
3399 option,
3400 &value_fn));
3401 fn = GNUNET_STRINGS_filename_expand (value_fn);
3402 if (NULL == fn)
3403 fn = value_fn;
3404 else
3405 GNUNET_free (value_fn);
3406 fprintf (stdout,
3407 "%s = %s\n",
3408 option,
3409 fn);
3410 GNUNET_free (fn);
3411}
3412
3413
3422static void
3423print_option (void *cls,
3424 const char *section,
3425 const char *option,
3426 const char *value)
3427{
3428 (void) cls;
3429 (void) section;
3430
3431 fprintf (stdout,
3432 "%s = %s\n",
3433 option,
3434 value);
3435}
3436
3437
3444static void
3446 const char *section)
3447{
3448 (void) cls;
3449 fprintf (stdout,
3450 "%s\n",
3451 section);
3452}
3453
3454
3455void
3457 void *cls,
3458 char *const *args,
3459 const char *cfgfile,
3460 const struct GNUNET_CONFIGURATION_Handle *cfg)
3461{
3462 struct GNUNET_CONFIGURATION_ConfigSettings *cs = cls;
3463 struct GNUNET_CONFIGURATION_Handle *out = NULL;
3464 struct GNUNET_CONFIGURATION_Handle *ncfg = NULL;
3465
3466 (void) args;
3467 if (cs->diagnostics &&
3468 (! cfg->diagnostics))
3469 {
3470 /* Re-parse the configuration with diagnostics enabled. */
3473 if (GNUNET_OK !=
3475 cfgfile))
3476 {
3477 fprintf (stderr,
3478 _ ("Failed to load config file `%s'"),
3479 cfgfile);
3480 return;
3481 }
3482 cfg = ncfg;
3483 }
3484
3485 if (cs->full)
3486 cs->rewrite = GNUNET_YES;
3487 if (cs->list_sections)
3488 {
3489 fprintf (stderr,
3490 _ ("The following sections are available:\n"));
3493 NULL);
3494 return;
3495 }
3496 if ( (! cs->rewrite) &&
3497 (NULL == cs->section) )
3498 {
3499 char *serialization;
3500
3501 if (! cs->diagnostics)
3502 {
3503 fprintf (stderr,
3504 _ ("%s, %s or %s argument is required\n"),
3505 "--section",
3506 "--list-sections",
3507 "--diagnostics");
3509 return;
3510 }
3511 serialization = (cs->diagnostics > 1)
3514 fprintf (stdout,
3515 "%s",
3516 serialization);
3517 GNUNET_free (serialization);
3518 }
3519 else if ( (NULL != cs->section) &&
3520 (NULL == cs->value) )
3521 {
3522 if (NULL == cs->option)
3523 {
3525 cfg,
3526 cs->section,
3527 cs->is_filename
3529 : &print_option,
3530 (void *) cfg);
3531 }
3532 else
3533 {
3534 char *value;
3535
3536 if (cs->is_filename)
3537 {
3538 if (GNUNET_OK !=
3540 cs->section,
3541 cs->option,
3542 &value))
3543 {
3545 cs->section,
3546 cs->option);
3548 return;
3549 }
3550 }
3551 else
3552 {
3553 if (GNUNET_OK !=
3555 cs->section,
3556 cs->option,
3557 &value))
3558 {
3560 cs->section,
3561 cs->option);
3563 return;
3564 }
3565 }
3566 fprintf (stdout,
3567 "%s\n",
3568 value);
3570 }
3571 }
3572 else if (NULL != cs->section)
3573 {
3574 if (NULL == cs->option)
3575 {
3576 fprintf (stderr,
3577 _ ("--option argument required to set value\n"));
3579 return;
3580 }
3583 cs->section,
3584 cs->option,
3585 cs->value);
3586 cs->rewrite = GNUNET_YES;
3587 }
3588 if (cs->rewrite)
3589 {
3590 char *cfg_fn = NULL;
3591
3592 if (NULL == out)
3594
3595 if (NULL == cfgfile)
3596 {
3597 const char *xdg = getenv ("XDG_CONFIG_HOME");
3598
3599 if (NULL != xdg)
3600 GNUNET_asprintf (&cfg_fn,
3601 "%s%s%s",
3602 xdg,
3604 cfg->pd->config_file);
3605 else
3606 cfg_fn = GNUNET_strdup (cfg->pd->user_config_file);
3607 cfgfile = cfg_fn;
3608 }
3609
3610 if (! cs->full)
3611 {
3612 struct GNUNET_CONFIGURATION_Handle *def;
3613
3615 if (GNUNET_OK !=
3617 NULL))
3618 {
3619 fprintf (stderr,
3620 _ ("failed to load configuration defaults"));
3621 cs->global_ret = 1;
3624 GNUNET_free (cfg_fn);
3625 return;
3626 }
3627 if (GNUNET_OK !=
3629 out,
3630 cfgfile))
3631 cs->global_ret = 2;
3633 }
3634 else
3635 {
3636 if (GNUNET_OK !=
3638 cfgfile))
3639 cs->global_ret = 2;
3640 }
3641 GNUNET_free (cfg_fn);
3642 }
3643 if (NULL != out)
3645 if (NULL != ncfg)
3647}
3648
3649
3650void
3658
3659
3660const struct GNUNET_OS_ProjectData *
3662 const struct GNUNET_CONFIGURATION_Handle *cfg)
3663{
3664 return cfg->pd;
3665}
3666
3667
3668char *
3670 pd,
3671 const struct
3673 const char *progname)
3674{
3675 static char *cache;
3676 char *binary = NULL;
3677 char *path = NULL;
3678 size_t path_len;
3679
3680 if (GNUNET_YES ==
3682 GNUNET_NO,
3683 NULL,
3684 NULL))
3685 {
3686 return GNUNET_strdup (progname);
3687 }
3688 if (NULL != cache)
3689 path = cache;
3690 else
3692 "PATHS",
3693 "SUID_BINARY_PATH",
3694 &path);
3695 if ( (NULL == path) ||
3696 (0 == strlen (path)) )
3697 {
3698 if (NULL != path)
3699 GNUNET_free (path);
3700 cache = NULL;
3702 progname);
3703 }
3704 path_len = strlen (path);
3705 GNUNET_asprintf (&binary,
3706 "%s%s%s",
3707 path,
3708 (path[path_len - 1] == DIR_SEPARATOR) ? ""
3710 progname);
3711 cache = path;
3712 return binary;
3713}
3714
3715
3716/* 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 bool source_is_removed(const struct ConfigSource *source, const char *target, struct CleanLine *lines, unsigned int lines_length)
Return whether a source is a target line currently marked for removal.
static struct CleanLine * find_clean_line(struct CleanLine *lines, unsigned int lines_length, unsigned int line)
Find a cleanup record for a physical line.
static int clean_line_cmp(const void *a, const void *b)
Sort cleanup records by source line.
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 enum GNUNET_GenericReturnValue read_file(const char *filename, char **contents, size_t *size)
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 void add_entry_source(struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, const char *value, const char *filename, unsigned int line)
Record the source of a configuration value.
static char * serialize_diagnostics(const struct GNUNET_CONFIGURATION_Handle *cfg, bool verbose)
Serialize configuration diagnostics.
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 enum GNUNET_GenericReturnValue write_buffer_atomic(const char *filename, const char *contents, size_t size, const struct GNUNET_HashCode *expected_hash)
Atomically replace a file with the given bytes.
static void copy_entry_with_sources(struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const struct ConfigEntry *entry)
Copy an entry parsed through an @inline-secret@ directive, including all diagnostic source informatio...
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 bool file_hash_matches(const char *filename, const struct GNUNET_HashCode *expected)
Check that a file still has the expected contents.
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.
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).
static unsigned int verbose
Be verbose.
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 GstElement * source
Appsrc instance into which we write data for the pipeline.
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 status
The program status; 0 for success.
Definition gnunet-nse.c:39
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.
char * GNUNET_CONFIGURATION_get_suid_binary_path(const struct GNUNET_OS_ProjectData *pd, const struct GNUNET_CONFIGURATION_Handle *cfg, const char *progname)
Given the name of a helper, service or daemon binary construct the full path to the binary using the ...
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.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_clean_file(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *filename, GNUNET_CONFIGURATION_CleanCallback cb, void *cb_cls, unsigned int *removed)
Remove redundant option definitions from a parsed configuration file.
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.
char * GNUNET_CONFIGURATION_serialize_diagnostics_verbose(const struct GNUNET_CONFIGURATION_Handle *cfg)
Serializes the given configuration with verbose diagnostics information, including all source definit...
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.
void(* GNUNET_CONFIGURATION_CleanCallback)(void *cls, const char *section, const char *option, unsigned int line)
Function called for each duplicate definition removed by GNUNET_CONFIGURATION_clean_file().
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_file_sync(const struct GNUNET_DISK_FileHandle *h)
Write file changes to disk.
Definition disk.c:1507
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.
void GNUNET_CRYPTO_hash(const void *block, size_t size, struct GNUNET_HashCode *ret)
Compute hash of a given block.
Definition crypto_hash.c:40
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.
#define GNUNET_memcmp(a, b)
Compare memory in a and b, where both must be of the same pointer type.
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.
char * GNUNET_OS_get_libexec_binary_path(const struct GNUNET_OS_ProjectData *pd, const char *progname)
Given the name of a gnunet-helper, gnunet-service or gnunet-daemon binary, try to prefix it with the ...
@ 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:531
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:843
enum GNUNET_GenericReturnValue GNUNET_STRINGS_path_is_absolute(const char *filename, int can_be_uri, int *r_is_uri, char **r_uri_scheme)
Check whether filename is absolute or not, and if it's an URI.
Definition strings.c:1012
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
Definition platform.h:166
#define DIR_SEPARATOR_STR
Definition platform.h:167
#define _(String)
GNU gettext support macro.
Definition platform.h:179
#define SIZE_MAX
Definition platform.h:213
#define EXIT_INVALIDARGUMENT
Definition platform.h:258
#define EXIT_NOTCONFIGURED
Definition platform.h:274
uint32_t number
One physical assignment line considered for removal.
const char * option
unsigned int line
const char * section
Closure to collect_files_cb.
char ** files
Collected files from globbing.
unsigned int files_length
Size of the files array.
configuration entry
struct ConfigEntry * next
This is a linked list.
char * key
key for this entry
struct ConfigSource * sources
Source definitions retained for diagnostics.
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
bool have_content_hash
Whether content_hash is available.
unsigned int level
Level in the tree of loaded config files.
struct GNUNET_HashCode content_hash
Hash of the file contents seen while parsing.
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.
source location of a configuration value
char * value
Value as normalized by the configuration parser.
unsigned int lineno
Line containing the definition.
char * filename
Filename containing the definition.
struct ConfigSource * next
Sources are ordered from highest to lowest precedence.
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 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.
unsigned int diagnostics
Diagnostics verbosity.
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).
A 512-bit hashcode.
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.