GNUnet 0.28.1-dev.2-13-g57ceb9dfb
 
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 *tfn;
1457 char *cfg_buf;
1458 size_t size;
1459
1461 if (fn == NULL)
1462 return GNUNET_SYSERR;
1464 {
1465 GNUNET_free (fn);
1466 return GNUNET_SYSERR;
1467 }
1468 {
1469 /* If @a filename is a symlink, replace what it points at, the way
1470 truncating it in place used to. */
1471 char *rfn = realpath (fn,
1472 NULL);
1473
1474 if (NULL != rfn)
1475 {
1476 GNUNET_free (fn);
1477 fn = GNUNET_strdup (rfn);
1478 free (rfn);
1479 }
1480 }
1482 &size);
1483 /* Never rewrite the configuration in place: opening it with O_TRUNC leaves
1484 it observably empty until we have written the new contents, and anyone
1485 parsing the file in that instant -- say a daemon that was just started
1486 with this very configuration -- reads a truncated file and fails. So
1487 write a sibling file and rename(2) it over the target; readers then
1488 always see either the complete old or the complete new configuration. */
1489 GNUNET_asprintf (&tfn,
1490 "%s.%u.tmp",
1491 fn,
1492 (unsigned int) getpid ());
1493 {
1494 struct GNUNET_DISK_FileHandle *h;
1495
1496 h = GNUNET_DISK_file_open (tfn,
1504 if (NULL == h)
1505 {
1506 GNUNET_free (tfn);
1507 GNUNET_free (fn);
1508 GNUNET_free (cfg_buf);
1509 return GNUNET_SYSERR;
1510 }
1511 if (((ssize_t) size) !=
1513 cfg_buf,
1514 size))
1515 {
1517 "write",
1518 tfn);
1520 (void) unlink (tfn);
1521 GNUNET_free (tfn);
1522 GNUNET_free (fn);
1523 GNUNET_free (cfg_buf);
1524 cfg->dirty = GNUNET_SYSERR; /* last write failed */
1525 return GNUNET_SYSERR;
1526 }
1527 /* Get the contents onto the disk before the rename publishes them, so
1528 that a crash cannot leave an empty configuration behind. */
1529 (void) GNUNET_DISK_file_sync (h);
1532 }
1533 {
1534 struct stat sbuf;
1535
1536 /* rename(2) replaces the inode, so carry over the permissions of the
1537 configuration we are about to replace (we just created @a tfn). */
1538 if ( (0 == stat (fn,
1539 &sbuf)) &&
1540 (0 != chmod (tfn,
1541 sbuf.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO))) )
1543 "chmod",
1544 tfn);
1545 }
1546 if (0 != rename (tfn,
1547 fn))
1548 {
1550 "rename",
1551 fn);
1552 (void) unlink (tfn);
1553 GNUNET_free (tfn);
1554 GNUNET_free (fn);
1555 GNUNET_free (cfg_buf);
1556 cfg->dirty = GNUNET_SYSERR; /* last write failed */
1557 return GNUNET_SYSERR;
1558 }
1559 GNUNET_free (tfn);
1560 GNUNET_free (fn);
1561 GNUNET_free (cfg_buf);
1562 cfg->dirty = GNUNET_NO; /* last write succeeded */
1563 return GNUNET_OK;
1564}
1565
1566
1567void
1569 const struct GNUNET_CONFIGURATION_Handle *cfg,
1571 void *iter_cls)
1572{
1573 for (struct ConfigSection *spos = cfg->sections;
1574 NULL != spos;
1575 spos = spos->next)
1576 for (struct ConfigEntry *epos = spos->entries;
1577 NULL != epos;
1578 epos = epos->next)
1579 if (NULL != epos->val)
1580 iter (iter_cls,
1581 spos->name,
1582 epos->key,
1583 epos->val);
1584}
1585
1586
1587void
1589 const struct GNUNET_CONFIGURATION_Handle *cfg,
1590 const char *section,
1592 void *iter_cls)
1593{
1594 struct ConfigSection *spos;
1595
1596 spos = cfg->sections;
1597 while ((spos != NULL) && (0 != strcasecmp (spos->name, section)))
1598 spos = spos->next;
1599 if (NULL == spos)
1600 return;
1601 for (struct ConfigEntry *epos = spos->entries;
1602 NULL != epos;
1603 epos = epos->next)
1604 if (NULL != epos->val)
1605 iter (iter_cls,
1606 spos->name,
1607 epos->key,
1608 epos->val);
1609 if (spos->inaccessible)
1610 {
1612 "Section '%s' is marked as inaccessible, because a configuration "
1613 "file that contains the section can't be read.\n",
1614 section);
1615 return;
1616 }
1617}
1618
1619
1620void
1622 const struct GNUNET_CONFIGURATION_Handle *cfg,
1624 void *iter_cls)
1625{
1626 struct ConfigSection *spos;
1627 struct ConfigSection *next;
1628
1629 next = cfg->sections;
1630 while (NULL != next)
1631 {
1632 spos = next;
1633 next = spos->next;
1634 if (spos->inaccessible && (NULL == spos->entries))
1635 continue;
1636 iter (iter_cls,
1637 spos->name);
1638 }
1639}
1640
1641
1642void
1644 const char *section)
1645{
1646 struct ConfigSection *spos;
1647 struct ConfigSection *prev;
1648 struct ConfigEntry *ent;
1649
1650 prev = NULL;
1651 spos = cfg->sections;
1652 while (NULL != spos)
1653 {
1654 if (0 == strcasecmp (section,
1655 spos->name))
1656 {
1657 if (NULL == prev)
1658 cfg->sections = spos->next;
1659 else
1660 prev->next = spos->next;
1661 while (NULL != (ent = spos->entries))
1662 {
1663 spos->entries = ent->next;
1664 GNUNET_free (ent->key);
1665 GNUNET_free (ent->val);
1667 GNUNET_free (ent);
1668 cfg->dirty = GNUNET_YES;
1669 }
1670 GNUNET_free (spos->name);
1674 GNUNET_free (spos);
1675 return;
1676 }
1677 prev = spos;
1678 spos = spos->next;
1679 }
1680}
1681
1682
1692static void
1693copy_entry (void *cls,
1694 const char *section,
1695 const char *option,
1696 const char *value)
1697{
1698 struct GNUNET_CONFIGURATION_Handle *dst = cls;
1699
1701 section,
1702 option,
1703 value);
1704}
1705
1706
1719
1720
1731static void
1733 const char *section,
1734 const char *option,
1735 const char *value)
1736{
1737 struct DiffHandle *dh = cls;
1738 struct ConfigEntry *entNew;
1739
1740 entNew = find_entry (dh->cfg_default, section, option);
1741 if ((NULL != entNew) && (NULL != entNew->val) &&
1742 (0 == strcmp (entNew->val, value)))
1743 return;
1745 section,
1746 option,
1747 value);
1748}
1749
1750
1753 const struct GNUNET_CONFIGURATION_Handle *cfg_default,
1754 const struct GNUNET_CONFIGURATION_Handle *cfg_new)
1755{
1756 struct DiffHandle diffHandle;
1757
1758 GNUNET_break (cfg_default->pd == cfg_new->pd);
1759 diffHandle.cfgDiff = GNUNET_CONFIGURATION_create (cfg_new->pd);
1760 diffHandle.cfg_default = cfg_default;
1763 &diffHandle);
1764 return diffHandle.cfgDiff;
1765}
1766
1767
1771 const struct GNUNET_CONFIGURATION_Handle *cfg_new,
1772 const char *filename)
1773{
1774 int ret;
1775 struct GNUNET_CONFIGURATION_Handle *diff;
1776
1777 diff = GNUNET_CONFIGURATION_get_diff (cfg_default, cfg_new);
1780 return ret;
1781}
1782
1783
1784void
1787 const char *section,
1788 const char *option,
1789 const char *value)
1790{
1791 struct ConfigSection *sec;
1792 struct ConfigEntry *e;
1793 char *nv;
1794
1795 e = find_entry (cfg, section, option);
1796 if (NULL != e)
1797 {
1798 if (NULL == value)
1799 {
1800 GNUNET_free (e->val);
1801 e->val = NULL;
1802 }
1803 else
1804 {
1805 nv = GNUNET_strdup (value);
1806 GNUNET_free (e->val);
1807 e->val = nv;
1808 }
1809 return;
1810 }
1811 sec = find_section (cfg, section);
1812 if (sec == NULL)
1813 {
1814 sec = GNUNET_new (struct ConfigSection);
1815 sec->name = GNUNET_strdup (section);
1816 sec->next = cfg->sections;
1817 cfg->sections = sec;
1818 }
1819 e = GNUNET_new (struct ConfigEntry);
1820 e->key = GNUNET_strdup (option);
1821 e->val = GNUNET_strdup (value);
1822 e->next = sec->entries;
1823 sec->entries = e;
1824}
1825
1826
1827void
1829 const char *section,
1830 const char *option,
1831 unsigned long long number)
1832{
1833 char s[64];
1834
1835 GNUNET_snprintf (s,
1836 64,
1837 "%llu",
1838 number);
1840 section,
1841 option,
1842 s);
1843}
1844
1845
1848 const struct GNUNET_CONFIGURATION_Handle *cfg,
1849 const char *section,
1850 const char *option,
1851 unsigned long long *number)
1852{
1853 struct ConfigEntry *e;
1854 char dummy[2];
1855
1856 if (NULL == (e = find_entry (cfg,
1857 section,
1858 option)))
1859 return GNUNET_NO;
1860 if (NULL == e->val)
1861 return GNUNET_NO;
1862 if (1 != sscanf (e->val,
1863 "%llu%1s",
1864 number,
1865 dummy))
1866 return GNUNET_SYSERR;
1867 return GNUNET_OK;
1868}
1869
1870
1871void
1873 const char *section,
1874 const char *option,
1875 float number)
1876{
1877 char s[64];
1878
1879 /* See: #9369 */
1880 const locale_t cl = newlocale (LC_NUMERIC_MASK,
1881 "C",
1882 (locale_t) 0);
1883 locale_t old_locale = uselocale (cl);
1884 GNUNET_snprintf (s,
1885 64,
1886 "%f",
1887 (double) number);
1888 uselocale (old_locale);
1890 section,
1891 option,
1892 s);
1893}
1894
1895
1898 const struct GNUNET_CONFIGURATION_Handle *cfg,
1899 const char *section,
1900 const char *option,
1901 float *number)
1902{
1903 struct ConfigEntry *e;
1904 char dummy[2];
1905
1906 if (NULL == (e = find_entry (cfg,
1907 section,
1908 option)))
1909 return GNUNET_NO;
1910 if (NULL == e->val)
1911 return GNUNET_NO;
1912 /* See #9369 */
1913 {
1914 const locale_t cl = newlocale (LC_NUMERIC_MASK,
1915 "C",
1916 (locale_t) 0);
1917 locale_t old_locale = uselocale (cl);
1918
1919 if (1 != sscanf (e->val,
1920 "%f%1s",
1921 number,
1922 dummy))
1923 return GNUNET_SYSERR;
1924 uselocale (old_locale);
1925 }
1926 return GNUNET_OK;
1927}
1928
1929
1932 const struct GNUNET_CONFIGURATION_Handle *cfg,
1933 const char *section,
1934 const char *option,
1935 struct GNUNET_TIME_Relative *time)
1936{
1937 struct ConfigEntry *e;
1938 int ret;
1939
1940 if (NULL == (e = find_entry (cfg,
1941 section,
1942 option)))
1943 return GNUNET_NO;
1944 if (NULL == e->val)
1945 return GNUNET_NO;
1947 time);
1948 if (GNUNET_OK != ret)
1950 section,
1951 option,
1952 _ ("Not a valid relative time specification"));
1953 return ret;
1954}
1955
1956
1959 const struct GNUNET_CONFIGURATION_Handle *cfg,
1960 const char *section,
1961 const char *option,
1962 unsigned long long *size)
1963{
1964 struct ConfigEntry *e;
1965
1966 if (NULL == (e = find_entry (cfg,
1967 section,
1968 option)))
1969 return GNUNET_NO;
1970 if (NULL == e->val)
1971 return GNUNET_NO;
1973 size);
1974}
1975
1976
1989 const struct GNUNET_CONFIGURATION_Handle *cfg,
1990 const char *section,
1991 const char *option,
1992 char **value)
1993{
1994 struct ConfigEntry *e;
1995
1996 if ( (NULL == (e = find_entry (cfg,
1997 section,
1998 option))) ||
1999 (NULL == e->val) )
2000 {
2001 *value = NULL;
2002 return GNUNET_NO;
2003 }
2004 *value = GNUNET_strdup (e->val);
2005 return GNUNET_OK;
2006}
2007
2008
2011 const struct GNUNET_CONFIGURATION_Handle *cfg,
2012 const char *section,
2013 const char *option,
2014 const char *const *choices,
2015 const char **value)
2016{
2017 struct ConfigEntry *e;
2018 unsigned int i;
2019
2020 if (NULL == (e = find_entry (cfg,
2021 section,
2022 option)))
2023 return GNUNET_NO;
2024 for (i = 0; NULL != choices[i]; i++)
2025 if (0 == strcasecmp (choices[i], e->val))
2026 break;
2027 if (NULL == choices[i])
2028 {
2030 _ ("Configuration value '%s' for '%s'"
2031 " in section '%s' is not in set of legal choices\n"),
2032 e->val,
2033 option,
2034 section);
2035 return GNUNET_SYSERR;
2036 }
2037 *value = choices[i];
2038 return GNUNET_OK;
2039}
2040
2041
2044 const char *section,
2045 const char *option,
2046 void *buf,
2047 size_t buf_size)
2048{
2049 char *enc;
2050 int res;
2051 size_t data_size;
2052
2053 if (GNUNET_OK !=
2054 (res =
2056 section,
2057 option,
2058 &enc)))
2059 return res;
2060 data_size = (strlen (enc) * 5) / 8;
2061 if (data_size != buf_size)
2062 {
2063 GNUNET_free (enc);
2064 return GNUNET_SYSERR;
2065 }
2066 if (GNUNET_OK !=
2068 strlen (enc),
2069 buf,
2070 buf_size))
2071 {
2072 GNUNET_free (enc);
2073 return GNUNET_SYSERR;
2074 }
2075 GNUNET_free (enc);
2076 return GNUNET_OK;
2077}
2078
2079
2082 const char *section,
2083 const char *option)
2084{
2085 struct ConfigEntry *e;
2086
2087 if ( (NULL == (e = find_entry (cfg,
2088 section,
2089 option))) ||
2090 (NULL == e->val) )
2091 return GNUNET_NO;
2092 return GNUNET_YES;
2093}
2094
2095
2111static char *
2113 char *orig,
2114 unsigned int depth)
2115{
2116 char *prefix;
2117 char *result;
2118 char *start;
2119 const char *post;
2120 const char *env;
2121 char *def;
2122 char *end;
2123 unsigned int lopen;
2124 char erased_char;
2125 char *erased_pos;
2126 size_t len;
2127
2128 if (NULL == orig)
2129 return NULL;
2130 if (depth > 128)
2131 {
2133 "Recursive expansion suspected, aborting $-expansion for term `%s'\n",
2134 orig);
2135 return orig;
2136 }
2138 "Asked to $-expand %s\n",
2139 orig);
2140 if ('$' != orig[0])
2141 {
2143 "Doesn't start with $ - not expanding\n");
2144 return orig;
2145 }
2146 erased_char = 0;
2147 erased_pos = NULL;
2148 if ('{' == orig[1])
2149 {
2150 start = &orig[2];
2151 lopen = 1;
2152 end = &orig[1];
2153 while (lopen > 0)
2154 {
2155 end++;
2156 switch (*end)
2157 {
2158 case '}':
2159 lopen--;
2160 break;
2161
2162 case '{':
2163 lopen++;
2164 break;
2165
2166 case '\0':
2168 "Missing closing `}' in option `%s'\n",
2169 orig);
2170 return orig;
2171
2172 default:
2173 break;
2174 }
2175 }
2176 erased_char = *end;
2177 erased_pos = end;
2178 *end = '\0';
2179 post = end + 1;
2180 def = strchr (orig, ':');
2181 if (NULL != def)
2182 {
2183 *def = '\0';
2184 def++;
2185 if (('-' == *def) || ('=' == *def))
2186 def++;
2187 def = GNUNET_strdup (def);
2188 }
2189 }
2190 else
2191 {
2192 int i;
2193
2194 start = &orig[1];
2195 def = NULL;
2196 i = 0;
2197 while ( (orig[i] != '/') &&
2198 (orig[i] != '\\') &&
2199 (orig[i] != '\0') &&
2200 (orig[i] != ' ') )
2201 i++;
2202 if (orig[i] == '\0')
2203 {
2204 post = "";
2205 }
2206 else
2207 {
2208 erased_char = orig[i];
2209 erased_pos = &orig[i];
2210 orig[i] = '\0';
2211 post = &orig[i + 1];
2212 }
2213 }
2215 "Split into `%s' and `%s' with default %s\n",
2216 start,
2217 post,
2218 def);
2219 if (GNUNET_OK !=
2221 "PATHS",
2222 start,
2223 &prefix))
2224 {
2225 if (NULL == (env = getenv (start)))
2226 {
2227 /* try default */
2228 def = expand_dollar (cfg,
2229 def,
2230 depth + 1);
2231 env = def;
2232 }
2233 if (NULL == env)
2234 {
2236 if (erased_pos)
2237 *erased_pos = erased_char;
2239 "Failed to expand `%s' in `%s' as it is neither found in [PATHS] nor defined as an environmental variable\n",
2240 start,
2241 orig);
2243 return orig;
2244 }
2246 }
2248 prefix);
2249 if ((erased_pos) && ('}' != erased_char))
2250 {
2251 len = strlen (prefix) + 1;
2252 prefix = GNUNET_realloc (prefix, len + 1);
2253 prefix[len - 1] = erased_char;
2254 prefix[len] = '\0';
2255 }
2256 result = GNUNET_malloc (strlen (prefix) + strlen (post) + 1);
2257 strcpy (result, prefix);
2258 strcat (result, post);
2259 GNUNET_free (def);
2261 GNUNET_free (orig);
2262 return result;
2263}
2264
2265
2266char *
2268 const struct GNUNET_CONFIGURATION_Handle *cfg,
2269 char *orig)
2270{
2271 char *dup;
2272 size_t i;
2273 size_t len;
2274
2275 for (i = 0; '\0' != orig[i]; i++)
2276 {
2277 if ('$' != orig[i])
2278 continue;
2279 dup = GNUNET_strdup (orig + i);
2280 dup = expand_dollar (cfg, dup, 0);
2281 GNUNET_assert (NULL != dup); /* make compiler happy */
2282 len = strlen (dup) + 1;
2283 orig = GNUNET_realloc (orig, i + len);
2284 GNUNET_memcpy (orig + i, dup, len);
2285 GNUNET_free (dup);
2286 }
2287 return orig;
2288}
2289
2290
2293 const struct GNUNET_CONFIGURATION_Handle *cfg,
2294 const char *section,
2295 const char *option,
2296 char **value)
2297{
2298 char *tmp;
2300
2302 section,
2303 option,
2304 &tmp);
2305 if (GNUNET_OK != ret)
2306 {
2308 "Failed to retrieve filename\n");
2309 *value = NULL;
2310 return ret;
2311 }
2313 tmp);
2315 GNUNET_free (tmp);
2316 if (*value == NULL)
2317 return GNUNET_SYSERR;
2318 return GNUNET_OK;
2319}
2320
2321
2324 const struct GNUNET_CONFIGURATION_Handle *cfg,
2325 const char *section,
2326 const char *option)
2327{
2328 static const char *yesno[] = {
2329 "YES",
2330 "NO",
2331 NULL
2332 };
2333 const char *val;
2335
2336 ret =
2338 section,
2339 option,
2340 yesno,
2341 &val);
2342 if (GNUNET_OK != ret)
2343 return ret;
2344 if (val == yesno[0])
2345 return GNUNET_YES;
2346 return GNUNET_NO;
2347}
2348
2349
2350int
2352 const struct GNUNET_CONFIGURATION_Handle *cfg,
2353 const char *section,
2354 const char *option,
2356 void *cb_cls)
2357{
2358 char *list;
2359 char *pos;
2360 char *end;
2361 char old;
2362 int ret;
2363
2364 if (GNUNET_OK !=
2366 section,
2367 option,
2368 &list))
2369 return 0;
2370 GNUNET_assert (list != NULL);
2371 ret = 0;
2372 pos = list;
2373 while (1)
2374 {
2375 while (pos[0] == ' ')
2376 pos++;
2377 if (strlen (pos) == 0)
2378 break;
2379 end = pos + 1;
2380 while ((end[0] != ' ') && (end[0] != '\0'))
2381 {
2382 if (end[0] == '\\')
2383 {
2384 switch (end[1])
2385 {
2386 case '\\':
2387 case ' ':
2388 memmove (end, &end[1], strlen (&end[1]) + 1);
2389
2390 case '\0':
2391 /* illegal, but just keep it */
2392 break;
2393
2394 default:
2395 /* illegal, but just ignore that there was a '/' */
2396 break;
2397 }
2398 }
2399 end++;
2400 }
2401 old = end[0];
2402 end[0] = '\0';
2403 if (strlen (pos) > 0)
2404 {
2405 ret++;
2406 if ( (NULL != cb) &&
2407 (GNUNET_OK != cb (cb_cls,
2408 pos)))
2409 {
2411 break;
2412 }
2413 }
2414 if (old == '\0')
2415 break;
2416 pos = end + 1;
2417 }
2418 GNUNET_free (list);
2419 return ret;
2420}
2421
2422
2429static char *
2430escape_name (const char *value)
2431{
2432 char *escaped;
2433 const char *rpos;
2434 char *wpos;
2435
2436 escaped = GNUNET_malloc (strlen (value) * 2 + 1);
2437 memset (escaped, 0, strlen (value) * 2 + 1);
2438 rpos = value;
2439 wpos = escaped;
2440 while (rpos[0] != '\0')
2441 {
2442 switch (rpos[0])
2443 {
2444 case '\\':
2445 case ' ':
2446 wpos[0] = '\\';
2447 wpos[1] = rpos[0];
2448 wpos += 2;
2449 break;
2450
2451 default:
2452 wpos[0] = rpos[0];
2453 wpos++;
2454 }
2455 rpos++;
2456 }
2457 return escaped;
2458}
2459
2460
2468static enum GNUNET_GenericReturnValue
2469test_match (void *cls,
2470 const char *fn)
2471{
2472 const char *of = cls;
2473
2474 return (0 == strcmp (of, fn))
2476 : GNUNET_OK;
2477}
2478
2479
2483 const char *section,
2484 const char *option,
2485 const char *value)
2486{
2487 char *escaped;
2488 char *old;
2489 char *nw;
2490
2491 if (GNUNET_SYSERR ==
2493 section,
2494 option,
2495 &test_match,
2496 (void *) value))
2497 return GNUNET_NO; /* already exists */
2498 if (GNUNET_OK !=
2499 GNUNET_CONFIGURATION_get_value_string (cfg, section, option, &old))
2500 old = GNUNET_strdup ("");
2501 escaped = escape_name (value);
2502 nw = GNUNET_malloc (strlen (old) + strlen (escaped) + 2);
2503 strcpy (nw, old);
2504 if (strlen (old) > 0)
2505 strcat (nw, " ");
2506 strcat (nw, escaped);
2508 section,
2509 option,
2510 nw);
2511 GNUNET_free (old);
2512 GNUNET_free (nw);
2513 GNUNET_free (escaped);
2514 return GNUNET_OK;
2515}
2516
2517
2521 const char *section,
2522 const char *option,
2523 const char *value)
2524{
2525 char *list;
2526 char *pos;
2527 char *end;
2528 char *match;
2529 char old;
2530
2531 if (GNUNET_OK !=
2533 section,
2534 option,
2535 &list))
2536 return GNUNET_NO;
2537 match = escape_name (value);
2538 pos = list;
2539 while (1)
2540 {
2541 while (pos[0] == ' ')
2542 pos++;
2543 if (strlen (pos) == 0)
2544 break;
2545 end = pos + 1;
2546 while ((end[0] != ' ') && (end[0] != '\0'))
2547 {
2548 if (end[0] == '\\')
2549 {
2550 switch (end[1])
2551 {
2552 case '\\':
2553 case ' ':
2554 end++;
2555 break;
2556
2557 case '\0':
2558 /* illegal, but just keep it */
2559 break;
2560
2561 default:
2562 /* illegal, but just ignore that there was a '/' */
2563 break;
2564 }
2565 }
2566 end++;
2567 }
2568 old = end[0];
2569 end[0] = '\0';
2570 if (0 == strcmp (pos, match))
2571 {
2572 if (old != '\0')
2573 memmove (pos,
2574 &end[1],
2575 strlen (&end[1]) + 1);
2576 else
2577 {
2578 if (pos != list)
2579 pos[-1] = '\0';
2580 else
2581 pos[0] = '\0';
2582 }
2584 section,
2585 option,
2586 list);
2587 GNUNET_free (list);
2588 GNUNET_free (match);
2589 return GNUNET_OK;
2590 }
2591 if (old == '\0')
2592 break;
2593 end[0] = old;
2594 pos = end + 1;
2595 }
2596 GNUNET_free (list);
2597 GNUNET_free (match);
2598 return GNUNET_NO;
2599}
2600
2601
2605 const char *defaults_d)
2606{
2607 struct CollectFilesContext files_context = {
2608 .files = NULL,
2609 .files_length = 0,
2610 };
2611 enum GNUNET_GenericReturnValue fun_ret = GNUNET_NO;
2612
2613 if (GNUNET_SYSERR ==
2614 GNUNET_DISK_directory_scan (defaults_d,
2616 &files_context))
2617 return GNUNET_SYSERR; /* no configuration at all found */
2618 qsort (files_context.files,
2619 files_context.files_length,
2620 sizeof (char *),
2621 &pstrcmp);
2622 for (unsigned int i = 0; i < files_context.files_length; i++)
2623 {
2624 const char *ext;
2625 const char *filename = files_context.files[i];
2626
2627 /* Examine file extension */
2628 ext = strrchr (filename, '.');
2629 if ( (NULL == ext) ||
2630 (0 != strcmp (ext,
2631 ".conf")) )
2632 {
2634 "Skipping file `%s'\n",
2635 filename);
2636 fun_ret = GNUNET_OK;
2637 continue;
2638 }
2640 filename);
2641 if (fun_ret != GNUNET_OK)
2642 break;
2643 }
2644 if (files_context.files_length > 0)
2645 {
2646 for (size_t i = 0; i < files_context.files_length; i++)
2647 GNUNET_free (files_context.files[i]);
2648 GNUNET_array_grow (files_context.files,
2649 files_context.files_length,
2650 0);
2651 }
2652 return fun_ret;
2653}
2654
2655
2656char *
2658 const struct GNUNET_OS_ProjectData *pd)
2659{
2660 char *cfg_fn;
2661 const char *xdg = getenv ("XDG_CONFIG_HOME");
2662
2663 if (NULL != xdg)
2664 GNUNET_asprintf (&cfg_fn,
2665 "%s%s%s",
2666 xdg,
2668 pd->config_file);
2669 else
2670 cfg_fn = GNUNET_strdup (pd->user_config_file);
2671
2672 if (GNUNET_OK == GNUNET_DISK_file_test_read (cfg_fn))
2673 return cfg_fn;
2674 GNUNET_free (cfg_fn);
2675
2676 /* Fall back to /etc/ for the default configuration.
2677 Should be okay to use forward slashes here. */
2678
2679 GNUNET_asprintf (&cfg_fn,
2680 "/etc/%s",
2681 pd->config_file);
2682 if (GNUNET_OK ==
2684 return cfg_fn;
2685 GNUNET_free (cfg_fn);
2686
2687 GNUNET_asprintf (&cfg_fn,
2688 "/etc/%s/%s",
2689 pd->project_dirname,
2690 pd->config_file);
2691 if (GNUNET_OK ==
2693 return cfg_fn;
2694
2695 GNUNET_free (cfg_fn);
2696 return NULL;
2697}
2698
2699
2703 const char *filename)
2704{
2705 char *baseconfig;
2706 const char *base_config_varname;
2707
2708 if (cfg->load_called)
2709 {
2710 /* FIXME: Make this a GNUNET_assert later */
2711 GNUNET_break (0);
2713 }
2714 cfg->load_called = true;
2715 if (NULL != filename)
2716 {
2719 }
2720
2721 base_config_varname = cfg->pd->base_config_varname;
2722
2723 if ((NULL != base_config_varname)
2724 && (NULL != (baseconfig = getenv (base_config_varname))))
2725 {
2726 baseconfig = GNUNET_strdup (baseconfig);
2727 }
2728 else
2729 {
2730 char *ipath;
2731
2734 if (NULL == ipath)
2735 {
2736 GNUNET_break (0);
2737 return GNUNET_SYSERR;
2738 }
2739 GNUNET_asprintf (&baseconfig,
2740 "%s%s",
2741 ipath,
2742 "config.d");
2743 GNUNET_free (ipath);
2744 }
2745
2746 {
2747 char *dname = GNUNET_STRINGS_filename_expand (baseconfig);
2748
2749 GNUNET_free (baseconfig);
2750
2751 if ((GNUNET_YES ==
2753 GNUNET_YES)) &&
2754 (GNUNET_SYSERR ==
2756 dname)))
2757 {
2759 "Failed to load base configuration from '%s'\n",
2760 filename);
2761 GNUNET_free (dname);
2762 return GNUNET_SYSERR; /* no configuration at all found */
2763 }
2764 GNUNET_free (dname);
2765 }
2766 if ((NULL != filename) &&
2767 (GNUNET_OK !=
2769 filename)))
2770 {
2771 /* specified configuration not found */
2773 "Failed to load configuration from file '%s'\n",
2774 filename);
2775 return GNUNET_SYSERR;
2776 }
2777 if (((GNUNET_YES !=
2779 "PATHS",
2780 "DEFAULTCONFIG"))) &&
2781 (filename != NULL))
2783 "PATHS",
2784 "DEFAULTCONFIG",
2785 filename);
2786 return GNUNET_OK;
2787}
2788
2789
2798static void
2800 const char *section,
2801 const char *option,
2802 const char *value)
2803{
2804 const struct GNUNET_CONFIGURATION_Handle *cfg = cls;
2805
2806 char *value_fn;
2807 char *fn;
2808
2811 section,
2812 option,
2813 &value_fn));
2814 fn = GNUNET_STRINGS_filename_expand (value_fn);
2815 if (NULL == fn)
2816 fn = value_fn;
2817 else
2818 GNUNET_free (value_fn);
2819 fprintf (stdout,
2820 "%s = %s\n",
2821 option,
2822 fn);
2823 GNUNET_free (fn);
2824}
2825
2826
2835static void
2836print_option (void *cls,
2837 const char *section,
2838 const char *option,
2839 const char *value)
2840{
2841 (void) cls;
2842 (void) section;
2843
2844 fprintf (stdout,
2845 "%s = %s\n",
2846 option,
2847 value);
2848}
2849
2850
2857static void
2859 const char *section)
2860{
2861 (void) cls;
2862 fprintf (stdout,
2863 "%s\n",
2864 section);
2865}
2866
2867
2868void
2870 void *cls,
2871 char *const *args,
2872 const char *cfgfile,
2873 const struct GNUNET_CONFIGURATION_Handle *cfg)
2874{
2875 struct GNUNET_CONFIGURATION_ConfigSettings *cs = cls;
2876 struct GNUNET_CONFIGURATION_Handle *out = NULL;
2877 struct GNUNET_CONFIGURATION_Handle *ncfg = NULL;
2878
2879 (void) args;
2880 if (cs->diagnostics)
2881 {
2882 /* Re-parse the configuration with diagnostics enabled. */
2885 if (GNUNET_OK !=
2887 cfgfile))
2888 {
2889 fprintf (stderr,
2890 _ ("Failed to load config file `%s'"),
2891 cfgfile);
2892 return;
2893 }
2894 cfg = ncfg;
2895 }
2896
2897 if (cs->full)
2898 cs->rewrite = GNUNET_YES;
2899 if (cs->list_sections)
2900 {
2901 fprintf (stderr,
2902 _ ("The following sections are available:\n"));
2905 NULL);
2906 return;
2907 }
2908 if ( (! cs->rewrite) &&
2909 (NULL == cs->section) )
2910 {
2911 char *serialization;
2912
2913 if (! cs->diagnostics)
2914 {
2915 fprintf (stderr,
2916 _ ("%s, %s or %s argument is required\n"),
2917 "--section",
2918 "--list-sections",
2919 "--diagnostics");
2921 return;
2922 }
2924 fprintf (stdout,
2925 "%s",
2926 serialization);
2927 GNUNET_free (serialization);
2928 }
2929 else if ( (NULL != cs->section) &&
2930 (NULL == cs->value) )
2931 {
2932 if (NULL == cs->option)
2933 {
2935 cfg,
2936 cs->section,
2937 cs->is_filename
2939 : &print_option,
2940 (void *) cfg);
2941 }
2942 else
2943 {
2944 char *value;
2945
2946 if (cs->is_filename)
2947 {
2948 if (GNUNET_OK !=
2950 cs->section,
2951 cs->option,
2952 &value))
2953 {
2955 cs->section,
2956 cs->option);
2958 return;
2959 }
2960 }
2961 else
2962 {
2963 if (GNUNET_OK !=
2965 cs->section,
2966 cs->option,
2967 &value))
2968 {
2970 cs->section,
2971 cs->option);
2973 return;
2974 }
2975 }
2976 fprintf (stdout,
2977 "%s\n",
2978 value);
2980 }
2981 }
2982 else if (NULL != cs->section)
2983 {
2984 if (NULL == cs->option)
2985 {
2986 fprintf (stderr,
2987 _ ("--option argument required to set value\n"));
2989 return;
2990 }
2993 cs->section,
2994 cs->option,
2995 cs->value);
2996 cs->rewrite = GNUNET_YES;
2997 }
2998 if (cs->rewrite)
2999 {
3000 char *cfg_fn = NULL;
3001
3002 if (NULL == out)
3004
3005 if (NULL == cfgfile)
3006 {
3007 const char *xdg = getenv ("XDG_CONFIG_HOME");
3008
3009 if (NULL != xdg)
3010 GNUNET_asprintf (&cfg_fn,
3011 "%s%s%s",
3012 xdg,
3014 cfg->pd->config_file);
3015 else
3016 cfg_fn = GNUNET_strdup (cfg->pd->user_config_file);
3017 cfgfile = cfg_fn;
3018 }
3019
3020 if (! cs->full)
3021 {
3022 struct GNUNET_CONFIGURATION_Handle *def;
3023
3025 if (GNUNET_OK !=
3027 NULL))
3028 {
3029 fprintf (stderr,
3030 _ ("failed to load configuration defaults"));
3031 cs->global_ret = 1;
3034 GNUNET_free (cfg_fn);
3035 return;
3036 }
3037 if (GNUNET_OK !=
3039 out,
3040 cfgfile))
3041 cs->global_ret = 2;
3043 }
3044 else
3045 {
3046 if (GNUNET_OK !=
3048 cfgfile))
3049 cs->global_ret = 2;
3050 }
3051 GNUNET_free (cfg_fn);
3052 }
3053 if (NULL != out)
3055 if (NULL != ncfg)
3057}
3058
3059
3060void
3068
3069
3070const struct GNUNET_OS_ProjectData *
3072 const struct GNUNET_CONFIGURATION_Handle *cfg)
3073{
3074 return cfg->pd;
3075}
3076
3077
3078char *
3080 pd,
3081 const struct
3083 const char *progname)
3084{
3085 static char *cache;
3086 char *binary = NULL;
3087 char *path = NULL;
3088 size_t path_len;
3089
3090 if (GNUNET_YES ==
3092 GNUNET_NO,
3093 NULL,
3094 NULL))
3095 {
3096 return GNUNET_strdup (progname);
3097 }
3098 if (NULL != cache)
3099 path = cache;
3100 else
3102 "PATHS",
3103 "SUID_BINARY_PATH",
3104 &path);
3105 if ( (NULL == path) ||
3106 (0 == strlen (path)) )
3107 {
3108 if (NULL != path)
3109 GNUNET_free (path);
3110 cache = NULL;
3112 progname);
3113 }
3114 path_len = strlen (path);
3115 GNUNET_asprintf (&binary,
3116 "%s%s%s",
3117 path,
3118 (path[path_len - 1] == DIR_SEPARATOR) ? ""
3120 progname);
3121 cache = path;
3122 return binary;
3123}
3124
3125
3126/* 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.
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.
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_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.
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.
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
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.