GNUnet  0.19.5
configuration.c
Go to the documentation of this file.
1 /*
2  This file is part of GNUnet.
3  Copyright (C) 2006, 2007, 2008, 2009, 2013, 2020, 2021 GNUnet e.V.
4 
5  GNUnet is free software: you can redistribute it and/or modify it
6  under the terms of the GNU Affero General Public License as published
7  by the Free Software Foundation, either version 3 of the License,
8  or (at your option) any later version.
9 
10  GNUnet is distributed in the hope that it will be useful, but
11  WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  Affero General Public License for more details.
14 
15  You should have received a copy of the GNU Affero General Public License
16  along with this program. If not, see <http://www.gnu.org/licenses/>.
17 
18  SPDX-License-Identifier: AGPL3.0-or-later
19  */
26 #include "platform.h"
27 #include "gnunet_util_lib.h"
29 
30 #define LOG(kind, ...) GNUNET_log_from (kind, "util", __VA_ARGS__)
31 
32 #define LOG_STRERROR_FILE(kind, syscall, filename) \
33  GNUNET_log_from_strerror_file (kind, "util", syscall, filename)
34 
39 {
43  struct ConfigEntry *next;
44 
48  char *key;
49 
53  char *val;
54 
59 
63  unsigned int hint_lineno;
64 };
65 
66 
71 {
76 
81 
85  char *name;
86 
94 
99 
104 
109 
114 };
115 
117 {
122 
126  unsigned int level;
127 
128  struct ConfigFile *prev;
129 
130  struct ConfigFile *next;
131 
137 
142 };
143 
144 
149 {
154 
159 
164 
168  unsigned int current_nest_level;
169 
174 
181 
186 
191 
197  const char *restrict_section;
198 };
199 
200 
206 {
208 
210 };
211 
212 
213 void
216 {
217  cfg->diagnostics = true;
218 }
219 
220 
223 {
225  char *p;
226 
228  /* make certain values from the project data available
229  as PATHS */
231  if (NULL != p)
232  {
234  "PATHS",
235  "DATADIR",
236  p);
237  GNUNET_free (p);
238  }
240  if (NULL != p)
241  {
243  "PATHS",
244  "LIBDIR",
245  p);
246  GNUNET_free (p);
247  }
249  if (NULL != p)
250  {
252  "PATHS",
253  "BINDIR",
254  p);
255  GNUNET_free (p);
256  }
258  if (NULL != p)
259  {
261  "PATHS",
262  "PREFIX",
263  p);
264  GNUNET_free (p);
265  }
267  if (NULL != p)
268  {
270  "PATHS",
271  "LOCALEDIR",
272  p);
273  GNUNET_free (p);
274  }
276  if (NULL != p)
277  {
279  "PATHS",
280  "ICONDIR",
281  p);
282  GNUNET_free (p);
283  }
285  if (NULL != p)
286  {
288  "PATHS",
289  "DOCDIR",
290  p);
291  GNUNET_free (p);
292  }
294  if (NULL != p)
295  {
297  "PATHS",
298  "LIBEXECDIR",
299  p);
300  GNUNET_free (p);
301  }
302  return cfg;
303 }
304 
305 
306 void
308 {
309  struct ConfigSection *sec;
310  struct ConfigFile *cf;
311 
312  while (NULL != (sec = cfg->sections))
314  while (NULL != (cf = cfg->loaded_files_head))
315  {
320  cf);
321  GNUNET_free (cf);
322  }
324  GNUNET_free (cfg);
325 }
326 
327 
331  void *cb_cls)
332 {
335 
337  if (GNUNET_OK !=
339  filename))
340  {
341  GNUNET_break (0);
343  return GNUNET_SYSERR;
344  }
345  ret = cb (cb_cls, cfg);
347  return ret;
348 }
349 
350 
355 {
359  char **files;
360 
364  unsigned int files_length;
365 };
366 
367 
377 static int
378 collect_files_cb (void *cls,
379  const char *filename)
380 {
381  struct CollectFilesContext *igc = cls;
382 
384  igc->files_length,
386  return GNUNET_OK;
387 }
388 
389 
397 static struct ConfigSection *
399  const char *section)
400 {
401  struct ConfigSection *pos;
402 
403  pos = cfg->sections;
404  while ((pos != NULL) && (0 != strcasecmp (section, pos->name)))
405  pos = pos->next;
406  return pos;
407 }
408 
409 
410 static int
411 pstrcmp (const void *a, const void *b)
412 {
413  return strcmp (*((const char **) a), *((const char **) b));
414 }
415 
416 
424  const char *path_or_glob,
425  bool path_is_glob,
426  const char *restrict_section,
427  const char *source_filename,
428  unsigned int source_lineno)
429 {
430  char *inline_path = NULL;
431  struct GNUNET_CONFIGURATION_Handle *other_cfg = NULL;
432  struct CollectFilesContext igc = {
433  .files = NULL,
434  .files_length = 0,
435  };
436  enum GNUNET_GenericReturnValue fun_ret;
437  unsigned int old_nest_level = cfg->current_nest_level++;
438 
439  /* We support the section restriction only for non-globs */
440  GNUNET_assert (! (path_is_glob && (NULL != restrict_section)));
441 
442  if (NULL == source_filename)
443  {
445  "Refusing to parse inline configurations, "
446  "not allowed without source filename!\n");
447  fun_ret = GNUNET_SYSERR;
448  goto cleanup;
449  }
450 
451  if ('/' == *path_or_glob)
452  inline_path = GNUNET_strdup (path_or_glob);
453  else
454  {
455  /* We compute the canonical, absolute path first,
456  so that relative imports resolve properly with symlinked
457  config files. */
458  char *source_realpath;
459  char *endsep;
460 
461  source_realpath = realpath (source_filename,
462  NULL);
463  if (NULL == source_realpath)
464  {
465  /* Couldn't even resolve path of base dir. */
466  GNUNET_break (0);
467  /* failed to parse included config */
468  fun_ret = GNUNET_SYSERR;
469  goto cleanup;
470  }
471  endsep = strrchr (source_realpath, '/');
472  GNUNET_assert (NULL != endsep);
473  *endsep = '\0';
474  GNUNET_asprintf (&inline_path,
475  "%s/%s",
476  source_realpath,
477  path_or_glob);
478  free (source_realpath);
479  }
480 
481  if (path_is_glob)
482  {
483  int nret;
484 
486  "processing config glob '%s'\n",
487  inline_path);
488 
489  nret = GNUNET_DISK_glob (inline_path, collect_files_cb, &igc);
490  if (-1 == nret)
491  {
492  fun_ret = GNUNET_SYSERR;
493  goto cleanup;
494  }
495  GNUNET_assert (nret == igc.files_length);
496  qsort (igc.files, igc.files_length, sizeof (char *), pstrcmp);
497  for (int i = 0; i < nret; i++)
498  {
499  if (GNUNET_OK !=
501  igc.files[i]))
502  {
503  fun_ret = GNUNET_SYSERR;
504  goto cleanup;
505  }
506  }
507  fun_ret = GNUNET_OK;
508  }
509  else if (NULL != restrict_section)
510  {
511  enum GNUNET_GenericReturnValue inner_ret;
512  struct ConfigSection *cs;
513  struct ConfigFile *cf = GNUNET_new (struct ConfigFile);
514 
515  inner_ret = GNUNET_DISK_file_test_read (inline_path);
516 
517  cs = find_section (cfg, restrict_section);
518 
519  if (NULL == cs)
520  {
521  cs = GNUNET_new (struct ConfigSection);
522  cs->name = GNUNET_strdup (restrict_section);
523  cs->next = cfg->sections;
524  cfg->sections = cs;
525  cs->entries = NULL;
526  }
527  if (cfg->diagnostics)
528  {
529  char *sfn = GNUNET_STRINGS_filename_expand (inline_path);
530  struct stat istat;
531 
532  cs->hint_secret_filename = sfn;
533  if (0 == stat (sfn, &istat))
534  {
535  struct passwd *pw = getpwuid (istat.st_uid);
536  struct group *gr = getgrgid (istat.st_gid);
537  char *pwname = (NULL == pw) ? "<unknown>" : pw->pw_name;
538  char *grname = (NULL == gr) ? "<unknown>" : gr->gr_name;
539 
541  "%s:%s %o",
542  pwname,
543  grname,
544  istat.st_mode);
545  }
546  else
547  {
548  cs->hint_secret_stat = GNUNET_strdup ("<can't stat file>");
549  }
550  if (source_filename)
551  {
552  /* Possible that this secret section has been inlined before */
554  cs->hint_inlined_from_filename = GNUNET_strdup (source_filename);
555  cs->hint_inlined_from_line = source_lineno;
556  }
557  }
558 
559  /* Put file in the load list for diagnostics, even if we can't access it. */
560  {
562  cf->source_filename = GNUNET_strdup (inline_path);
563  cf->hint_restrict_section = GNUNET_strdup (restrict_section);
566  cf);
567  }
568 
569  if (GNUNET_OK != inner_ret)
570  {
571  cs->inaccessible = true;
572  cf->hint_inaccessible = true;
573  /* File can't be accessed, but that's okay. */
574  fun_ret = GNUNET_OK;
575  goto cleanup;
576  }
577 
578  other_cfg = GNUNET_CONFIGURATION_create ();
579  other_cfg->restrict_section = restrict_section;
580  inner_ret = GNUNET_CONFIGURATION_parse (other_cfg,
581  inline_path);
582  if (GNUNET_OK != inner_ret)
583  {
584  cf->hint_inaccessible = true;
585  fun_ret = inner_ret;
586  goto cleanup;
587  }
588 
589  cs = find_section (other_cfg, restrict_section);
590  if (NULL == cs)
591  {
593  "Configuration file '%s' loaded with @inline-secret@ "
594  "does not contain section '%s'.\n",
595  inline_path,
596  restrict_section);
597  /* Inlined onfiguration is accessible but doesn't contain any values.
598  We treat this as if the inlined section was empty, and do not
599  consider it an error. */
600  fun_ret = GNUNET_OK;
601  goto cleanup;
602  }
603  for (struct ConfigEntry *ce = cs->entries;
604  NULL != ce;
605  ce = ce->next)
607  restrict_section,
608  ce->key,
609  ce->val);
610  fun_ret = GNUNET_OK;
611  }
612  else if (GNUNET_OK !=
614  inline_path))
615  {
616  fun_ret = GNUNET_SYSERR;
617  goto cleanup;
618  }
619  else
620  {
621  fun_ret = GNUNET_OK;
622  }
623 cleanup:
624  cfg->current_nest_level = old_nest_level;
625  if (NULL != other_cfg)
626  GNUNET_CONFIGURATION_destroy (other_cfg);
627  GNUNET_free (inline_path);
628  if (igc.files_length > 0)
629  {
630  for (size_t i = 0; i < igc.files_length; i++)
631  GNUNET_free (igc.files[i]);
632  GNUNET_array_grow (igc.files, igc.files_length, 0);
633  }
634  return fun_ret;
635 }
636 
637 
646 static struct ConfigEntry *
648  const char *section,
649  const char *key)
650 {
651  struct ConfigSection *sec;
652  struct ConfigEntry *pos;
653 
654  if (NULL == (sec = find_section (cfg, section)))
655  return NULL;
656  if (sec->inaccessible)
657  {
659  "Section '%s' is marked as inaccessible, because the configuration "
660  " file that contains the section can't be read. Attempts to use "
661  "option '%s' will fail.\n",
662  section,
663  key);
664  return NULL;
665  }
666  pos = sec->entries;
667  while ((pos != NULL) && (0 != strcasecmp (key, pos->key)))
668  pos = pos->next;
669  return pos;
670 }
671 
672 
682 static void
684  const char *section,
685  const char *option,
686  const char *hint_filename,
687  unsigned int hint_line)
688 {
689  struct ConfigEntry *e = find_entry (cfg, section, option);
690  if (! cfg->diagnostics)
691  return;
692  if (! e)
693  return;
694  e->hint_filename = GNUNET_strdup (hint_filename);
695  e->hint_lineno = hint_line;
696 }
697 
698 
701  const char *mem,
702  size_t size,
703  const char *source_filename)
704 {
705  size_t line_size;
706  unsigned int nr;
707  size_t r_bytes;
708  size_t to_read;
710  char *section;
711  char *eq;
712  char *tag;
713  char *value;
714  char *line_orig = NULL;
715 
716  ret = GNUNET_OK;
717  section = NULL;
718  nr = 0;
719  r_bytes = 0;
720  while (r_bytes < size)
721  {
722  char *pos;
723  char *line;
724  bool emptyline;
725 
726  GNUNET_free (line_orig);
727  /* fgets-like behaviour on buffer */
728  to_read = size - r_bytes;
729  pos = memchr (&mem[r_bytes], '\n', to_read);
730  if (NULL == pos)
731  {
732  line_orig = GNUNET_strndup (&mem[r_bytes],
733  line_size = to_read);
734  r_bytes += line_size;
735  }
736  else
737  {
738  line_orig = GNUNET_strndup (&mem[r_bytes],
739  line_size = (pos - &mem[r_bytes]));
740  r_bytes += line_size + 1;
741  }
742  line = line_orig;
743  /* increment line number */
744  nr++;
745  /* tabs and '\r' are whitespace */
746  emptyline = GNUNET_YES;
747  for (size_t i = 0; i < line_size; i++)
748  {
749  if (line[i] == '\t')
750  line[i] = ' ';
751  if (line[i] == '\r')
752  line[i] = ' ';
753  if (' ' != line[i])
754  emptyline = GNUNET_NO;
755  }
756  /* ignore empty lines */
757  if (GNUNET_YES == emptyline)
758  continue;
759 
760  /* remove tailing whitespace */
761  for (size_t i = line_size - 1;
762  (i >= 1) && (isspace ((unsigned char) line[i]));
763  i--)
764  line[i] = '\0';
765 
766  /* remove leading whitespace */
767  for (; line[0] != '\0' && (isspace ((unsigned char) line[0])); line++)
768  ;
769 
770  /* ignore comments */
771  if ( ('#' == line[0]) ||
772  ('%' == line[0]) )
773  continue;
774 
775  /* Handle special directives. */
776  if ('@' == line[0])
777  {
778  char *end = strchr (line + 1, '@');
779  char *directive;
780  enum GNUNET_GenericReturnValue directive_ret;
781 
782  if (NULL != cfg->restrict_section)
783  {
785  _ (
786  "Illegal directive in line %u (parsing restricted section %s)\n"),
787  nr,
789  ret = GNUNET_SYSERR;
790  break;
791  }
792 
793  if (NULL == end)
794  {
796  _ ("Bad directive in line %u\n"),
797  nr);
798  ret = GNUNET_SYSERR;
799  break;
800  }
801  *end = '\0';
802  directive = line + 1;
803 
804  if (0 == strcasecmp (directive,
805  "INLINE"))
806  {
807  const char *path = end + 1;
808 
809  /* Skip space before path */
810  for (; isspace (*path); path++)
811  ;
812 
813  directive_ret = handle_inline (cfg,
814  path,
815  false,
816  NULL,
817  source_filename,
818  nr);
819  }
820  else if (0 == strcasecmp (directive,
821  "INLINE-MATCHING"))
822  {
823  const char *path = end + 1;
824 
825  /* Skip space before path */
826  for (; isspace (*path); path++)
827  ;
828 
829  directive_ret = handle_inline (cfg,
830  path,
831  true,
832  NULL,
833  source_filename,
834  nr);
835  }
836  else if (0 == strcasecmp (directive,
837  "INLINE-SECRET"))
838  {
839  char *secname = end + 1;
840  char *secname_end;
841  const char *path;
842 
843  /* Skip space before secname */
844  for (; isspace (*secname); secname++)
845  ;
846 
847  secname_end = strchr (secname, ' ');
848 
849  if (NULL == secname_end)
850  {
852  _ ("Bad inline-secret directive in line %u\n"),
853  nr);
854  ret = GNUNET_SYSERR;
855  break;
856  }
857  *secname_end = '\0';
858  path = secname_end + 1;
859 
860  /* Skip space before path */
861  for (; isspace (*path); path++)
862  ;
863 
864  directive_ret = handle_inline (cfg,
865  path,
866  false,
867  secname,
868  source_filename,
869  nr);
870  }
871  else
872  {
874  _ ("Unknown or malformed directive '%s' in line %u\n"),
875  directive,
876  nr);
877  ret = GNUNET_SYSERR;
878  break;
879  }
880  if (GNUNET_OK != directive_ret)
881  {
882  ret = directive_ret;
883  break;
884  }
885  continue;
886  }
887  if ( ('[' == line[0]) &&
888  (']' == line[line_size - 1]) )
889  {
890  /* [value] */
891  line[line_size - 1] = '\0';
892  value = &line[1];
893  GNUNET_free (section);
894  section = GNUNET_strdup (value);
895  continue;
896  }
897  if (NULL != (eq = strchr (line, '=')))
898  {
899  size_t i;
900 
901  if (NULL == section)
902  {
904  _ (
905  "Syntax error while deserializing in line %u (option without section)\n"),
906  nr);
907  ret = GNUNET_SYSERR;
908  break;
909  }
910 
911  /* tag = value */
912  tag = GNUNET_strndup (line, eq - line);
913  /* remove tailing whitespace */
914  for (i = strlen (tag) - 1;
915  (i >= 1) && (isspace ((unsigned char) tag[i]));
916  i--)
917  tag[i] = '\0';
918 
919  /* Strip whitespace */
920  value = eq + 1;
921  while (isspace ((unsigned char) value[0]))
922  value++;
923  for (i = strlen (value) - 1;
924  (i >= 1) && (isspace ((unsigned char) value[i]));
925  i--)
926  value[i] = '\0';
927 
928  /* remove quotes */
929  i = 0;
930  if ( ('"' == value[0]) &&
931  ('"' == value[strlen (value) - 1]) )
932  {
933  value[strlen (value) - 1] = '\0';
934  value++;
935  }
937  section,
938  tag,
939  &value[i]);
940  if (cfg->diagnostics)
941  {
943  section,
944  tag,
945  source_filename
946  ? source_filename
947  : "<input>",
948  nr);
949  }
950  GNUNET_free (tag);
951  continue;
952  }
953  /* parse error */
955  _ ("Syntax error while deserializing in line %u\n"),
956  nr);
957  ret = GNUNET_SYSERR;
958  break;
959  }
960  GNUNET_free (line_orig);
961  GNUNET_free (section);
962  GNUNET_assert ( (GNUNET_OK != ret) ||
963  (r_bytes == size) );
964  return ret;
965 }
966 
967 
970  const char *filename)
971 {
972  uint64_t fs64;
973  size_t fs;
974  char *fn;
975  char *mem;
976  int dirty;
978  ssize_t sret;
979 
981  LOG (GNUNET_ERROR_TYPE_DEBUG, "Asked to parse config file `%s'\n", fn);
982  if (NULL == fn)
983  return GNUNET_SYSERR;
984 
985 
986  /* Check for cycles */
987  {
988  unsigned int lvl = cfg->current_nest_level;
989  struct ConfigFile *cf = cfg->loaded_files_tail;
990  struct ConfigFile *parent = NULL;
991 
992 
993  for (; NULL != cf; parent = cf, cf = cf->prev)
994  {
995  /* Check parents based on level, skipping children of siblings. */
996  if (cf->level >= lvl)
997  continue;
998  lvl = cf->level;
999  if ( (NULL == cf->source_filename) || (NULL == filename))
1000  continue;
1001  if (0 == strcmp (cf->source_filename, filename))
1002  {
1003  if (NULL == parent)
1004  {
1006  "Forbidden direct cyclic configuration import (%s -> %s)\n",
1007  cf->source_filename,
1008  filename);
1009  }
1010  else
1012  "Forbidden indirect cyclic configuration import (%s -> ... -> %s -> %s)\n",
1013  cf->source_filename,
1014  parent->source_filename,
1015  filename);
1016  GNUNET_free (fn);
1017  return GNUNET_SYSERR;
1018  }
1019  }
1020 
1021  }
1022 
1023  /* Keep track of loaded files.*/
1024  {
1025  struct ConfigFile *cf = GNUNET_new (struct ConfigFile);
1026 
1027  cf->level = cfg->current_nest_level;
1028  cf->source_filename = GNUNET_strdup (filename ? filename : "<input>");
1031  cf);
1032  }
1033 
1034  dirty = cfg->dirty; /* back up value! */
1035  if (GNUNET_SYSERR ==
1037  {
1039  "Error while determining the file size of `%s'\n",
1040  fn);
1041  GNUNET_free (fn);
1042  return GNUNET_SYSERR;
1043  }
1044  if (fs64 > SIZE_MAX)
1045  {
1046  GNUNET_break (0); /* File size is more than the heap size */
1047  GNUNET_free (fn);
1048  return GNUNET_SYSERR;
1049  }
1050  fs = fs64;
1051  mem = GNUNET_malloc (fs);
1052  sret = GNUNET_DISK_fn_read (fn, mem, fs);
1053  if ((sret < 0) || (fs != (size_t) sret))
1054  {
1055  LOG (GNUNET_ERROR_TYPE_WARNING, _ ("Error while reading file `%s'\n"), fn);
1056  GNUNET_free (fn);
1057  GNUNET_free (mem);
1058  return GNUNET_SYSERR;
1059  }
1060  LOG (GNUNET_ERROR_TYPE_DEBUG, "Deserializing contents of file `%s'\n", fn);
1062  mem,
1063  fs,
1064  fn);
1065  if (GNUNET_SYSERR == ret)
1066  {
1068  _ ("Failed to parse configuration file `%s'\n"),
1069  fn);
1070  }
1071  GNUNET_free (fn);
1072  GNUNET_free (mem);
1073  /* restore dirty flag - anything we set in the meantime
1074  * came from disk */
1075  cfg->dirty = dirty;
1076  return ret;
1077 }
1078 
1079 
1082 {
1083  return cfg->dirty;
1084 }
1085 
1086 
1094 static bool
1095 do_skip (const char *sec,
1096  const char *key)
1097 {
1098  if (0 != strcasecmp ("PATHS",
1099  sec))
1100  return false;
1101  return ( (0 == strcasecmp ("DATADIR",
1102  key)) ||
1103  (0 == strcasecmp ("LIBDIR",
1104  key)) ||
1105  (0 == strcasecmp ("BINDIR",
1106  key)) ||
1107  (0 == strcasecmp ("PREFIX",
1108  key)) ||
1109  (0 == strcasecmp ("LOCALEDIR",
1110  key)) ||
1111  (0 == strcasecmp ("ICONDIR",
1112  key)) ||
1113  (0 == strcasecmp ("DOCDIR",
1114  key)) ||
1115  (0 == strcasecmp ("DEFAULTCONFIG",
1116  key)) ||
1117  (0 == strcasecmp ("LIBEXECDIR",
1118  key)) );
1119 }
1120 
1121 
1122 char *
1124  size_t *size)
1125 {
1126  char *mem;
1127  char *cbuf;
1128  char *val;
1129  char *pos;
1130  size_t m_size;
1131  size_t c_size;
1132 
1133  /* Pass1 : calculate the buffer size required */
1134  m_size = 0;
1135  for (struct ConfigSection *sec = cfg->sections;
1136  NULL != sec;
1137  sec = sec->next)
1138  {
1139  if (sec->inaccessible)
1140  continue;
1141  /* For each section we need to add 3 characters: {'[',']','\n'} */
1142  m_size += strlen (sec->name) + 3;
1143  for (struct ConfigEntry *ent = sec->entries;
1144  NULL != ent;
1145  ent = ent->next)
1146  {
1147  if (do_skip (sec->name,
1148  ent->key))
1149  continue;
1150  if (NULL != ent->val)
1151  {
1152  /* if val has any '\n' then they occupy +1 character as '\n'->'\\','n' */
1153  pos = ent->val;
1154  while (NULL != (pos = strstr (pos, "\n")))
1155  {
1156  m_size++;
1157  pos++;
1158  }
1159  /* For each key = value pair we need to add 4 characters (2
1160  spaces and 1 equal-to character and 1 new line) */
1161  m_size += strlen (ent->key) + strlen (ent->val) + 4;
1162  }
1163  }
1164  /* A new line after section end */
1165  m_size++;
1166  }
1167 
1168  /* Pass2: Allocate memory and write the configuration to it */
1169  mem = GNUNET_malloc (m_size);
1170  c_size = 0;
1171  *size = c_size;
1172  for (struct ConfigSection *sec = cfg->sections;
1173  NULL != sec;
1174  sec = sec->next)
1175  {
1176  int len;
1177 
1178  len = GNUNET_asprintf (&cbuf,
1179  "[%s]\n",
1180  sec->name);
1181  GNUNET_assert (0 < len);
1182  GNUNET_memcpy (mem + c_size,
1183  cbuf,
1184  len);
1185  c_size += len;
1186  GNUNET_free (cbuf);
1187  for (struct ConfigEntry *ent = sec->entries;
1188  NULL != ent;
1189  ent = ent->next)
1190  {
1191  if (do_skip (sec->name,
1192  ent->key))
1193  continue;
1194  if (NULL != ent->val)
1195  {
1196  val = GNUNET_malloc (strlen (ent->val) * 2 + 1);
1197  strcpy (val, ent->val);
1198  while (NULL != (pos = strstr (val, "\n")))
1199  {
1200  memmove (&pos[2], &pos[1], strlen (&pos[1]));
1201  pos[0] = '\\';
1202  pos[1] = 'n';
1203  }
1204  len = GNUNET_asprintf (&cbuf, "%s = %s\n", ent->key, val);
1205  GNUNET_free (val);
1206  GNUNET_memcpy (mem + c_size, cbuf, len);
1207  c_size += len;
1208  GNUNET_free (cbuf);
1209  }
1210  }
1211  GNUNET_memcpy (mem + c_size, "\n", 1);
1212  c_size++;
1213  }
1214  GNUNET_assert (c_size == m_size);
1215  *size = c_size;
1216  return mem;
1217 }
1218 
1219 
1220 char *
1223 {
1224  struct GNUNET_Buffer buf = { 0 };
1225 
1227  "#\n# Configuration file diagnostics\n#\n");
1229  "# Entry point: %s\n",
1231  "<none>");
1233  "#\n# Files Loaded:\n");
1234 
1235  for (struct ConfigFile *cfil = cfg->loaded_files_head;
1236  NULL != cfil;
1237  cfil = cfil->next)
1238  {
1240  "# ");
1241  for (unsigned int i = 0; i < cfil->level; i++)
1243  "+");
1244  if (0 != cfil->level)
1246  " ");
1247 
1249  "%s",
1250  cfil->source_filename);
1251 
1252  if (NULL != cfil->hint_restrict_section)
1254  " (%s secret section %s)",
1255  cfil->hint_inaccessible
1256  ? "inaccessible"
1257  : "loaded",
1258  cfil->hint_restrict_section);
1259 
1261  "\n");
1262  }
1263 
1265  "#\n\n");
1266 
1267  for (struct ConfigSection *sec = cfg->sections;
1268  NULL != sec;
1269  sec = sec->next)
1270  {
1271  if (sec->hint_secret_filename)
1273  "# secret section from %s\n# secret file stat %s\n",
1274  sec->hint_secret_filename,
1275  sec->hint_secret_stat);
1276  if (sec->hint_inlined_from_filename)
1277  {
1279  "# inlined from %s:%u\n",
1280  sec->hint_inlined_from_filename,
1281  sec->hint_inlined_from_line);
1282  }
1284  "[%s]\n\n",
1285  sec->name);
1286  if (sec->inaccessible)
1287  {
1289  "# <section contents inaccessible>\n\n\n");
1290  continue;
1291  }
1292  for (struct ConfigEntry *ent = sec->entries;
1293  NULL != ent;
1294  ent = ent->next)
1295  {
1296  if (do_skip (sec->name,
1297  ent->key))
1298  continue;
1299  if (NULL != ent->val)
1300  {
1301  char *pos;
1302  char *val = GNUNET_malloc (strlen (ent->val) * 2 + 1);
1303  strcpy (val, ent->val);
1304  while (NULL != (pos = strstr (val, "\n")))
1305  {
1306  memmove (&pos[2], &pos[1], strlen (&pos[1]));
1307  pos[0] = '\\';
1308  pos[1] = 'n';
1309  }
1310  if (NULL != ent->hint_filename)
1311  {
1313  "# %s:%u\n",
1314  ent->hint_filename,
1315  ent->hint_lineno);
1316  }
1318  "%s = %s\n",
1319  ent->key,
1320  val);
1321  GNUNET_free (val);
1322  }
1323  GNUNET_buffer_write_str (&buf, "\n");
1324  }
1325  GNUNET_buffer_write_str (&buf, "\n");
1326  }
1327  return GNUNET_buffer_reap_str (&buf);
1328 }
1329 
1330 
1333  const char *filename)
1334 {
1335  char *fn;
1336  char *cfg_buf;
1337  size_t size;
1338 
1340  if (fn == NULL)
1341  return GNUNET_SYSERR;
1343  {
1344  GNUNET_free (fn);
1345  return GNUNET_SYSERR;
1346  }
1348  &size);
1349  {
1350  struct GNUNET_DISK_FileHandle *h;
1351 
1352  h = GNUNET_DISK_file_open (fn,
1360  if (NULL == h)
1361  {
1362  GNUNET_free (fn);
1363  GNUNET_free (cfg_buf);
1364  return GNUNET_SYSERR;
1365  }
1366  if (((ssize_t) size) !=
1368  cfg_buf,
1369  size))
1370  {
1372  "write",
1373  fn);
1375  (void) GNUNET_DISK_directory_remove (fn);
1376  GNUNET_free (fn);
1377  GNUNET_free (cfg_buf);
1378  cfg->dirty = GNUNET_SYSERR; /* last write failed */
1379  return GNUNET_SYSERR;
1380  }
1383  }
1384  GNUNET_free (fn);
1385  GNUNET_free (cfg_buf);
1386  cfg->dirty = GNUNET_NO; /* last write succeeded */
1387  return GNUNET_OK;
1388 }
1389 
1390 
1391 void
1394  void *iter_cls)
1395 {
1396  for (struct ConfigSection *spos = cfg->sections;
1397  NULL != spos;
1398  spos = spos->next)
1399  for (struct ConfigEntry *epos = spos->entries;
1400  NULL != epos;
1401  epos = epos->next)
1402  if (NULL != epos->val)
1403  iter (iter_cls,
1404  spos->name,
1405  epos->key,
1406  epos->val);
1407 }
1408 
1409 
1410 void
1412  const struct GNUNET_CONFIGURATION_Handle *cfg,
1413  const char *section,
1415  void *iter_cls)
1416 {
1417  struct ConfigSection *spos;
1418  struct ConfigEntry *epos;
1419 
1420  spos = cfg->sections;
1421  while ((spos != NULL) && (0 != strcasecmp (spos->name, section)))
1422  spos = spos->next;
1423  if (NULL == spos)
1424  return;
1425  if (spos->inaccessible)
1426  {
1428  "Section '%s' is marked as inaccessible, because the configuration "
1429  " file that contains the section can't be read.\n",
1430  section);
1431  return;
1432  }
1433  for (epos = spos->entries; NULL != epos; epos = epos->next)
1434  if (NULL != epos->val)
1435  iter (iter_cls, spos->name, epos->key, epos->val);
1436 }
1437 
1438 
1439 void
1441  const struct GNUNET_CONFIGURATION_Handle *cfg,
1443  void *iter_cls)
1444 {
1445  struct ConfigSection *spos;
1446  struct ConfigSection *next;
1447 
1448  next = cfg->sections;
1449  while (next != NULL)
1450  {
1451  spos = next;
1452  next = spos->next;
1453  iter (iter_cls, spos->name);
1454  }
1455 }
1456 
1457 
1458 void
1460  const char *section)
1461 {
1462  struct ConfigSection *spos;
1463  struct ConfigSection *prev;
1464  struct ConfigEntry *ent;
1465 
1466  prev = NULL;
1467  spos = cfg->sections;
1468  while (NULL != spos)
1469  {
1470  if (0 == strcasecmp (section, spos->name))
1471  {
1472  if (NULL == prev)
1473  cfg->sections = spos->next;
1474  else
1475  prev->next = spos->next;
1476  while (NULL != (ent = spos->entries))
1477  {
1478  spos->entries = ent->next;
1479  GNUNET_free (ent->key);
1480  GNUNET_free (ent->val);
1481  GNUNET_free (ent->hint_filename);
1482  GNUNET_free (ent);
1483  cfg->dirty = GNUNET_YES;
1484  }
1485  GNUNET_free (spos->name);
1487  GNUNET_free (spos->hint_secret_stat);
1489  GNUNET_free (spos);
1490  return;
1491  }
1492  prev = spos;
1493  spos = spos->next;
1494  }
1495 }
1496 
1497 
1507 static void
1508 copy_entry (void *cls,
1509  const char *section,
1510  const char *option,
1511  const char *value)
1512 {
1513  struct GNUNET_CONFIGURATION_Handle *dst = cls;
1514 
1515  GNUNET_CONFIGURATION_set_value_string (dst, section, option, value);
1516 }
1517 
1518 
1521 {
1523 
1526  return ret;
1527 }
1528 
1529 
1540 static void
1541 compare_entries (void *cls,
1542  const char *section,
1543  const char *option,
1544  const char *value)
1545 {
1546  struct DiffHandle *dh = cls;
1547  struct ConfigEntry *entNew;
1548 
1549  entNew = find_entry (dh->cfg_default, section, option);
1550  if ((NULL != entNew) && (NULL != entNew->val) &&
1551  (0 == strcmp (entNew->val, value)))
1552  return;
1553  GNUNET_CONFIGURATION_set_value_string (dh->cfgDiff, section, option, value);
1554 }
1555 
1556 
1559  const struct GNUNET_CONFIGURATION_Handle *cfg_default,
1560  const struct GNUNET_CONFIGURATION_Handle *cfg_new)
1561 {
1562  struct DiffHandle diffHandle;
1563 
1564  diffHandle.cfgDiff = GNUNET_CONFIGURATION_create ();
1565  diffHandle.cfg_default = cfg_default;
1566  GNUNET_CONFIGURATION_iterate (cfg_new, &compare_entries, &diffHandle);
1567  return diffHandle.cfgDiff;
1568 }
1569 
1570 
1574  const struct GNUNET_CONFIGURATION_Handle *cfg_new,
1575  const char *filename)
1576 {
1577  int ret;
1578  struct GNUNET_CONFIGURATION_Handle *diff;
1579 
1580  diff = GNUNET_CONFIGURATION_get_diff (cfg_default, cfg_new);
1583  return ret;
1584 }
1585 
1586 
1587 void
1589  const char *section,
1590  const char *option,
1591  const char *value)
1592 {
1593  struct ConfigSection *sec;
1594  struct ConfigEntry *e;
1595  char *nv;
1596 
1597  e = find_entry (cfg, section, option);
1598  if (NULL != e)
1599  {
1600  if (NULL == value)
1601  {
1602  GNUNET_free (e->val);
1603  e->val = NULL;
1604  }
1605  else
1606  {
1607  nv = GNUNET_strdup (value);
1608  GNUNET_free (e->val);
1609  e->val = nv;
1610  }
1611  return;
1612  }
1613  sec = find_section (cfg, section);
1614  if (sec == NULL)
1615  {
1616  sec = GNUNET_new (struct ConfigSection);
1617  sec->name = GNUNET_strdup (section);
1618  sec->next = cfg->sections;
1619  cfg->sections = sec;
1620  }
1621  e = GNUNET_new (struct ConfigEntry);
1622  e->key = GNUNET_strdup (option);
1623  e->val = GNUNET_strdup (value);
1624  e->next = sec->entries;
1625  sec->entries = e;
1626 }
1627 
1628 
1629 void
1631  const char *section,
1632  const char *option,
1633  unsigned long long number)
1634 {
1635  char s[64];
1636 
1637  GNUNET_snprintf (s, 64, "%llu", number);
1638  GNUNET_CONFIGURATION_set_value_string (cfg, section, option, s);
1639 }
1640 
1641 
1644  const struct GNUNET_CONFIGURATION_Handle *cfg,
1645  const char *section,
1646  const char *option,
1647  unsigned long long *number)
1648 {
1649  struct ConfigEntry *e;
1650  char dummy[2];
1651 
1652  if (NULL == (e = find_entry (cfg, section, option)))
1653  return GNUNET_SYSERR;
1654  if (NULL == e->val)
1655  return GNUNET_SYSERR;
1656  if (1 != sscanf (e->val, "%llu%1s", number, dummy))
1657  return GNUNET_SYSERR;
1658  return GNUNET_OK;
1659 }
1660 
1661 
1664  const struct GNUNET_CONFIGURATION_Handle *cfg,
1665  const char *section,
1666  const char *option,
1667  float *number)
1668 {
1669  struct ConfigEntry *e;
1670  char dummy[2];
1671 
1672  if (NULL == (e = find_entry (cfg, section, option)))
1673  return GNUNET_SYSERR;
1674  if (NULL == e->val)
1675  return GNUNET_SYSERR;
1676  if (1 != sscanf (e->val, "%f%1s", number, dummy))
1677  return GNUNET_SYSERR;
1678  return GNUNET_OK;
1679 }
1680 
1681 
1684  const struct GNUNET_CONFIGURATION_Handle *cfg,
1685  const char *section,
1686  const char *option,
1687  struct GNUNET_TIME_Relative *time)
1688 {
1689  struct ConfigEntry *e;
1690  int ret;
1691 
1692  if (NULL == (e = find_entry (cfg, section, option)))
1693  return GNUNET_SYSERR;
1694  if (NULL == e->val)
1695  return GNUNET_SYSERR;
1697  if (GNUNET_OK != ret)
1699  section,
1700  option,
1701  _ ("Not a valid relative time specification"));
1702  return ret;
1703 }
1704 
1705 
1708  const struct GNUNET_CONFIGURATION_Handle *cfg,
1709  const char *section,
1710  const char *option,
1711  unsigned long long *size)
1712 {
1713  struct ConfigEntry *e;
1714 
1715  if (NULL == (e = find_entry (cfg, section, option)))
1716  return GNUNET_SYSERR;
1717  if (NULL == e->val)
1718  return GNUNET_SYSERR;
1719  return GNUNET_STRINGS_fancy_size_to_bytes (e->val, size);
1720 }
1721 
1722 
1735  const struct GNUNET_CONFIGURATION_Handle *cfg,
1736  const char *section,
1737  const char *option,
1738  char **value)
1739 {
1740  struct ConfigEntry *e;
1741 
1742  if ((NULL == (e = find_entry (cfg, section, option))) || (NULL == e->val))
1743  {
1744  *value = NULL;
1745  return GNUNET_SYSERR;
1746  }
1747  *value = GNUNET_strdup (e->val);
1748  return GNUNET_OK;
1749 }
1750 
1751 
1754  const struct GNUNET_CONFIGURATION_Handle *cfg,
1755  const char *section,
1756  const char *option,
1757  const char *const *choices,
1758  const char **value)
1759 {
1760  struct ConfigEntry *e;
1761  unsigned int i;
1762 
1763  if (NULL == (e = find_entry (cfg, section, option)))
1764  return GNUNET_SYSERR;
1765  for (i = 0; NULL != choices[i]; i++)
1766  if (0 == strcasecmp (choices[i], e->val))
1767  break;
1768  if (NULL == choices[i])
1769  {
1771  _ ("Configuration value '%s' for '%s'"
1772  " in section '%s' is not in set of legal choices\n"),
1773  e->val,
1774  option,
1775  section);
1776  return GNUNET_SYSERR;
1777  }
1778  *value = choices[i];
1779  return GNUNET_OK;
1780 }
1781 
1782 
1785  const char *section,
1786  const char *option,
1787  void *buf,
1788  size_t buf_size)
1789 {
1790  char *enc;
1791  int res;
1792  size_t data_size;
1793 
1794  if (GNUNET_OK !=
1795  (res =
1796  GNUNET_CONFIGURATION_get_value_string (cfg, section, option, &enc)))
1797  return res;
1798  data_size = (strlen (enc) * 5) / 8;
1799  if (data_size != buf_size)
1800  {
1801  GNUNET_free (enc);
1802  return GNUNET_SYSERR;
1803  }
1804  if (GNUNET_OK !=
1805  GNUNET_STRINGS_string_to_data (enc, strlen (enc), buf, buf_size))
1806  {
1807  GNUNET_free (enc);
1808  return GNUNET_SYSERR;
1809  }
1810  GNUNET_free (enc);
1811  return GNUNET_OK;
1812 }
1813 
1814 
1817  const char *section,
1818  const char *option)
1819 {
1820  struct ConfigEntry *e;
1821 
1822  if ((NULL == (e = find_entry (cfg, section, option))) || (NULL == e->val))
1823  return GNUNET_NO;
1824  return GNUNET_YES;
1825 }
1826 
1827 
1843 static char *
1845  char *orig,
1846  unsigned int depth)
1847 {
1848  char *prefix;
1849  char *result;
1850  char *start;
1851  const char *post;
1852  const char *env;
1853  char *def;
1854  char *end;
1855  unsigned int lopen;
1856  char erased_char;
1857  char *erased_pos;
1858  size_t len;
1859 
1860  if (NULL == orig)
1861  return NULL;
1862  if (depth > 128)
1863  {
1865  _ (
1866  "Recursive expansion suspected, aborting $-expansion for term `%s'\n"),
1867  orig);
1868  return orig;
1869  }
1870  LOG (GNUNET_ERROR_TYPE_DEBUG, "Asked to $-expand %s\n", orig);
1871  if ('$' != orig[0])
1872  {
1873  LOG (GNUNET_ERROR_TYPE_DEBUG, "Doesn't start with $ - not expanding\n");
1874  return orig;
1875  }
1876  erased_char = 0;
1877  erased_pos = NULL;
1878  if ('{' == orig[1])
1879  {
1880  start = &orig[2];
1881  lopen = 1;
1882  end = &orig[1];
1883  while (lopen > 0)
1884  {
1885  end++;
1886  switch (*end)
1887  {
1888  case '}':
1889  lopen--;
1890  break;
1891 
1892  case '{':
1893  lopen++;
1894  break;
1895 
1896  case '\0':
1898  _ ("Missing closing `%s' in option `%s'\n"),
1899  "}",
1900  orig);
1901  return orig;
1902 
1903  default:
1904  break;
1905  }
1906  }
1907  erased_char = *end;
1908  erased_pos = end;
1909  *end = '\0';
1910  post = end + 1;
1911  def = strchr (orig, ':');
1912  if (NULL != def)
1913  {
1914  *def = '\0';
1915  def++;
1916  if (('-' == *def) || ('=' == *def))
1917  def++;
1918  def = GNUNET_strdup (def);
1919  }
1920  }
1921  else
1922  {
1923  int i;
1924 
1925  start = &orig[1];
1926  def = NULL;
1927  i = 0;
1928  while ((orig[i] != '/') && (orig[i] != '\\') && (orig[i] != '\0') &&
1929  (orig[i] != ' '))
1930  i++;
1931  if (orig[i] == '\0')
1932  {
1933  post = "";
1934  }
1935  else
1936  {
1937  erased_char = orig[i];
1938  erased_pos = &orig[i];
1939  orig[i] = '\0';
1940  post = &orig[i + 1];
1941  }
1942  }
1944  "Split into `%s' and `%s' with default %s\n",
1945  start,
1946  post,
1947  def);
1948  if (GNUNET_OK !=
1950  {
1951  if (NULL == (env = getenv (start)))
1952  {
1953  /* try default */
1954  def = expand_dollar (cfg, def, depth + 1);
1955  env = def;
1956  }
1957  if (NULL == env)
1958  {
1960  if (erased_pos)
1961  *erased_pos = erased_char;
1963  _ (
1964  "Failed to expand `%s' in `%s' as it is neither found in [PATHS] nor defined as an environmental variable\n"),
1965  start,
1966  orig);
1967  GNUNET_free (start);
1968  return orig;
1969  }
1970  prefix = GNUNET_strdup (env);
1971  }
1973  if ((erased_pos) && ('}' != erased_char))
1974  {
1975  len = strlen (prefix) + 1;
1976  prefix = GNUNET_realloc (prefix, len + 1);
1977  prefix[len - 1] = erased_char;
1978  prefix[len] = '\0';
1979  }
1980  result = GNUNET_malloc (strlen (prefix) + strlen (post) + 1);
1981  strcpy (result, prefix);
1982  strcat (result, post);
1983  GNUNET_free (def);
1984  GNUNET_free (prefix);
1985  GNUNET_free (orig);
1986  return result;
1987 }
1988 
1989 
1990 char *
1992  const struct GNUNET_CONFIGURATION_Handle *cfg,
1993  char *orig)
1994 {
1995  char *dup;
1996  size_t i;
1997  size_t len;
1998 
1999  for (i = 0; '\0' != orig[i]; i++)
2000  {
2001  if ('$' != orig[i])
2002  continue;
2003  dup = GNUNET_strdup (orig + i);
2004  dup = expand_dollar (cfg, dup, 0);
2005  GNUNET_assert (NULL != dup); /* make compiler happy */
2006  len = strlen (dup) + 1;
2007  orig = GNUNET_realloc (orig, i + len);
2008  GNUNET_memcpy (orig + i, dup, len);
2009  GNUNET_free (dup);
2010  }
2011  return orig;
2012 }
2013 
2014 
2017  const struct GNUNET_CONFIGURATION_Handle *cfg,
2018  const char *section,
2019  const char *option,
2020  char **value)
2021 {
2022  char *tmp;
2023 
2024  if (GNUNET_OK !=
2025  GNUNET_CONFIGURATION_get_value_string (cfg, section, option, &tmp))
2026  {
2027  LOG (GNUNET_ERROR_TYPE_DEBUG, "Failed to retrieve filename\n");
2028  *value = NULL;
2029  return GNUNET_SYSERR;
2030  }
2033  GNUNET_free (tmp);
2034  if (*value == NULL)
2035  return GNUNET_SYSERR;
2036  return GNUNET_OK;
2037 }
2038 
2039 
2042  const struct GNUNET_CONFIGURATION_Handle *cfg,
2043  const char *section,
2044  const char *option)
2045 {
2046  static const char *yesno[] = { "YES", "NO", NULL };
2047  const char *val;
2048  int ret;
2049 
2050  ret =
2051  GNUNET_CONFIGURATION_get_value_choice (cfg, section, option, yesno, &val);
2052  if (ret == GNUNET_SYSERR)
2053  return ret;
2054  if (val == yesno[0])
2055  return GNUNET_YES;
2056  return GNUNET_NO;
2057 }
2058 
2059 
2060 int
2062  const struct GNUNET_CONFIGURATION_Handle *cfg,
2063  const char *section,
2064  const char *option,
2066  void *cb_cls)
2067 {
2068  char *list;
2069  char *pos;
2070  char *end;
2071  char old;
2072  int ret;
2073 
2074  if (GNUNET_OK !=
2075  GNUNET_CONFIGURATION_get_value_string (cfg, section, option, &list))
2076  return 0;
2077  GNUNET_assert (list != NULL);
2078  ret = 0;
2079  pos = list;
2080  while (1)
2081  {
2082  while (pos[0] == ' ')
2083  pos++;
2084  if (strlen (pos) == 0)
2085  break;
2086  end = pos + 1;
2087  while ((end[0] != ' ') && (end[0] != '\0'))
2088  {
2089  if (end[0] == '\\')
2090  {
2091  switch (end[1])
2092  {
2093  case '\\':
2094  case ' ':
2095  memmove (end, &end[1], strlen (&end[1]) + 1);
2096 
2097  case '\0':
2098  /* illegal, but just keep it */
2099  break;
2100 
2101  default:
2102  /* illegal, but just ignore that there was a '/' */
2103  break;
2104  }
2105  }
2106  end++;
2107  }
2108  old = end[0];
2109  end[0] = '\0';
2110  if (strlen (pos) > 0)
2111  {
2112  ret++;
2113  if ((cb != NULL) && (GNUNET_OK != cb (cb_cls, pos)))
2114  {
2115  ret = GNUNET_SYSERR;
2116  break;
2117  }
2118  }
2119  if (old == '\0')
2120  break;
2121  pos = end + 1;
2122  }
2123  GNUNET_free (list);
2124  return ret;
2125 }
2126 
2127 
2134 static char *
2135 escape_name (const char *value)
2136 {
2137  char *escaped;
2138  const char *rpos;
2139  char *wpos;
2140 
2141  escaped = GNUNET_malloc (strlen (value) * 2 + 1);
2142  memset (escaped, 0, strlen (value) * 2 + 1);
2143  rpos = value;
2144  wpos = escaped;
2145  while (rpos[0] != '\0')
2146  {
2147  switch (rpos[0])
2148  {
2149  case '\\':
2150  case ' ':
2151  wpos[0] = '\\';
2152  wpos[1] = rpos[0];
2153  wpos += 2;
2154  break;
2155 
2156  default:
2157  wpos[0] = rpos[0];
2158  wpos++;
2159  }
2160  rpos++;
2161  }
2162  return escaped;
2163 }
2164 
2165 
2173 static enum GNUNET_GenericReturnValue
2174 test_match (void *cls, const char *fn)
2175 {
2176  const char *of = cls;
2177 
2178  return (0 == strcmp (of, fn)) ? GNUNET_SYSERR : GNUNET_OK;
2179 }
2180 
2181 
2185  const char *section,
2186  const char *option,
2187  const char *value)
2188 {
2189  char *escaped;
2190  char *old;
2191  char *nw;
2192 
2193  if (GNUNET_SYSERR ==
2195  section,
2196  option,
2197  &test_match,
2198  (void *) value))
2199  return GNUNET_NO; /* already exists */
2200  if (GNUNET_OK !=
2201  GNUNET_CONFIGURATION_get_value_string (cfg, section, option, &old))
2202  old = GNUNET_strdup ("");
2203  escaped = escape_name (value);
2204  nw = GNUNET_malloc (strlen (old) + strlen (escaped) + 2);
2205  strcpy (nw, old);
2206  if (strlen (old) > 0)
2207  strcat (nw, " ");
2208  strcat (nw, escaped);
2209  GNUNET_CONFIGURATION_set_value_string (cfg, section, option, nw);
2210  GNUNET_free (old);
2211  GNUNET_free (nw);
2212  GNUNET_free (escaped);
2213  return GNUNET_OK;
2214 }
2215 
2216 
2220  const char *section,
2221  const char *option,
2222  const char *value)
2223 {
2224  char *list;
2225  char *pos;
2226  char *end;
2227  char *match;
2228  char old;
2229 
2230  if (GNUNET_OK !=
2231  GNUNET_CONFIGURATION_get_value_string (cfg, section, option, &list))
2232  return GNUNET_NO;
2233  match = escape_name (value);
2234  pos = list;
2235  while (1)
2236  {
2237  while (pos[0] == ' ')
2238  pos++;
2239  if (strlen (pos) == 0)
2240  break;
2241  end = pos + 1;
2242  while ((end[0] != ' ') && (end[0] != '\0'))
2243  {
2244  if (end[0] == '\\')
2245  {
2246  switch (end[1])
2247  {
2248  case '\\':
2249  case ' ':
2250  end++;
2251  break;
2252 
2253  case '\0':
2254  /* illegal, but just keep it */
2255  break;
2256 
2257  default:
2258  /* illegal, but just ignore that there was a '/' */
2259  break;
2260  }
2261  }
2262  end++;
2263  }
2264  old = end[0];
2265  end[0] = '\0';
2266  if (0 == strcmp (pos, match))
2267  {
2268  if (old != '\0')
2269  memmove (pos, &end[1], strlen (&end[1]) + 1);
2270  else
2271  {
2272  if (pos != list)
2273  pos[-1] = '\0';
2274  else
2275  pos[0] = '\0';
2276  }
2277  GNUNET_CONFIGURATION_set_value_string (cfg, section, option, list);
2278  GNUNET_free (list);
2279  GNUNET_free (match);
2280  return GNUNET_OK;
2281  }
2282  if (old == '\0')
2283  break;
2284  end[0] = old;
2285  pos = end + 1;
2286  }
2287  GNUNET_free (list);
2288  GNUNET_free (match);
2289  return GNUNET_NO;
2290 }
2291 
2292 
2295  const char *defaults_d)
2296 {
2297  struct CollectFilesContext files_context = {
2298  .files = NULL,
2299  .files_length = 0,
2300  };
2301  enum GNUNET_GenericReturnValue fun_ret;
2302 
2303  if (GNUNET_SYSERR ==
2305  &files_context))
2306  return GNUNET_SYSERR; /* no configuration at all found */
2307  qsort (files_context.files,
2308  files_context.files_length,
2309  sizeof (char *),
2310  pstrcmp);
2311  for (unsigned int i = 0; i < files_context.files_length; i++)
2312  {
2313  char *ext;
2314  const char *filename = files_context.files[i];
2315 
2316  /* Examine file extension */
2317  ext = strrchr (filename, '.');
2318  if ((NULL == ext) || (0 != strcmp (ext, ".conf")))
2319  {
2320  GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Skipping file `%s'\n", filename);
2321  fun_ret = GNUNET_OK;
2322  goto cleanup;
2323  }
2325  if (fun_ret != GNUNET_OK)
2326  break;
2327  }
2328 cleanup:
2329  if (files_context.files_length > 0)
2330  {
2331  for (size_t i = 0; i < files_context.files_length; i++)
2332  GNUNET_free (files_context.files[i]);
2333  GNUNET_array_grow (files_context.files,
2334  files_context.files_length,
2335  0);
2336  }
2337  return fun_ret;
2338 }
2339 
2340 
2341 char *
2343 {
2344  char *cfg_fn;
2345  const struct GNUNET_OS_ProjectData *pd = GNUNET_OS_project_data_get ();
2346  const char *xdg = getenv ("XDG_CONFIG_HOME");
2347 
2348  if (NULL != xdg)
2349  GNUNET_asprintf (&cfg_fn,
2350  "%s%s%s",
2351  xdg,
2353  pd->config_file);
2354  else
2355  cfg_fn = GNUNET_strdup (pd->user_config_file);
2356 
2357  if (GNUNET_OK == GNUNET_DISK_file_test_read (cfg_fn))
2358  return cfg_fn;
2359  GNUNET_free (cfg_fn);
2360 
2361  /* Fall back to /etc/ for the default configuration.
2362  Should be okay to use forward slashes here. */
2363 
2364  GNUNET_asprintf (&cfg_fn,
2365  "/etc/%s",
2366  pd->config_file);
2367  if (GNUNET_OK == GNUNET_DISK_file_test_read (cfg_fn))
2368  return cfg_fn;
2369  GNUNET_free (cfg_fn);
2370 
2371  GNUNET_asprintf (&cfg_fn,
2372  "/etc/%s/%s",
2373  pd->project_dirname,
2374  pd->config_file);
2375  if (GNUNET_OK == GNUNET_DISK_file_test_read (cfg_fn))
2376  return cfg_fn;
2377 
2378  GNUNET_free (cfg_fn);
2379  return NULL;
2380 }
2381 
2382 
2385 {
2386  const struct GNUNET_OS_ProjectData *pd = GNUNET_OS_project_data_get ();
2388  const char *xdg = getenv ("XDG_CONFIG_HOME");
2389  char *cfgname = NULL;
2391 
2392  /* Makes sure function implicitly looking at the installation directory (for
2393  example GNUNET_CONFIGURATION_load further down) use GNUnet's environment
2394  instead of the caller's. It's done at the start to make sure as many
2395  functions as possible are directed to the proper paths. */
2396  GNUNET_OS_init (dpd);
2397 
2399 
2400  /* First, try user configuration. */
2401  if (NULL != xdg)
2402  GNUNET_asprintf (&cfgname, "%s/%s", xdg, dpd->config_file);
2403  else
2404  cfgname = GNUNET_strdup (dpd->user_config_file);
2405 
2406  /* If user config doesn't exist, try in
2407  /etc/<projdir>/<cfgfile> and /etc/<cfgfile> */
2408  if (GNUNET_OK != GNUNET_DISK_file_test (cfgname))
2409  {
2410  GNUNET_free (cfgname);
2411  GNUNET_asprintf (&cfgname, "/etc/%s", dpd->config_file);
2412  }
2413  if (GNUNET_OK != GNUNET_DISK_file_test (cfgname))
2414  {
2415  GNUNET_free (cfgname);
2416  GNUNET_asprintf (&cfgname,
2417  "/etc/%s/%s",
2418  dpd->project_dirname,
2419  dpd->config_file);
2420  }
2421  if (GNUNET_OK != GNUNET_DISK_file_test (cfgname))
2422  {
2424  "Unable to top-level configuration file.\n");
2425  GNUNET_OS_init (pd);
2427  GNUNET_free (cfgname);
2428  return NULL;
2429  }
2430 
2431  /* We found a configuration file that looks good, try to load it. */
2432 
2434  "Loading top-level configuration from '%s'\n",
2435  cfgname);
2436  if (GNUNET_OK !=
2437  GNUNET_CONFIGURATION_load (cfg, cfgname))
2438  {
2439  GNUNET_OS_init (pd);
2441  GNUNET_free (cfgname);
2442  return NULL;
2443  }
2444  GNUNET_free (cfgname);
2445  GNUNET_OS_init (pd);
2446  return cfg;
2447 }
2448 
2449 
2458 int
2460  const char *filename)
2461 {
2462  char *baseconfig;
2463  const char *base_config_varname;
2464 
2465  if (cfg->load_called)
2466  {
2467  /* FIXME: Make this a GNUNET_assert later */
2468  GNUNET_break (0);
2470  }
2471  cfg->load_called = true;
2472  if (NULL != filename)
2473  {
2476  }
2477 
2478  base_config_varname = GNUNET_OS_project_data_get ()->base_config_varname;
2479 
2480  if ((NULL != base_config_varname)
2481  && (NULL != (baseconfig = getenv (base_config_varname))))
2482  {
2483  baseconfig = GNUNET_strdup (baseconfig);
2484  }
2485  else
2486  {
2487  char *ipath;
2488 
2490  if (NULL == ipath)
2491  {
2492  GNUNET_break (0);
2493  return GNUNET_SYSERR;
2494  }
2495  GNUNET_asprintf (&baseconfig, "%s%s", ipath, "config.d");
2496  GNUNET_free (ipath);
2497  }
2498 
2499  char *dname = GNUNET_STRINGS_filename_expand (baseconfig);
2500  GNUNET_free (baseconfig);
2501 
2502  if ((GNUNET_YES == GNUNET_DISK_directory_test (dname, GNUNET_YES)) &&
2504  {
2506  "Failed to load base configuration from '%s'\n",
2507  filename);
2508  GNUNET_free (dname);
2509  return GNUNET_SYSERR; /* no configuration at all found */
2510  }
2511  GNUNET_free (dname);
2512  if ((NULL != filename) &&
2514  {
2515  /* specified configuration not found */
2517  "Failed to load configuration from file '%s'\n",
2518  filename);
2519  return GNUNET_SYSERR;
2520  }
2521  if (((GNUNET_YES !=
2522  GNUNET_CONFIGURATION_have_value (cfg, "PATHS", "DEFAULTCONFIG"))) &&
2523  (filename != NULL))
2524  GNUNET_CONFIGURATION_set_value_string (cfg, "PATHS", "DEFAULTCONFIG",
2525  filename);
2526  return GNUNET_OK;
2527 }
2528 
2529 
2530 /* 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 struct ConfigEntry * find_entry(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *key)
Find an entry from a configuration.
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...
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 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 test_match(void *cls, const char *fn)
FIXME.
static int pstrcmp(const void *a, const void *b)
static struct ConfigSection * find_section(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section)
Find a section entry from a configuration.
#define LOG(kind,...)
Definition: configuration.c:30
static char * escape_name(const char *value)
FIXME.
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 int collect_files_cb(void *cls, const char *filename)
Function called with a filename.
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 const struct GNUNET_CONFIGURATION_Handle * cfg
Configuration we are using.
Definition: gnunet-abd.c:36
static int ret
Return value of the commandline.
Definition: gnunet-abd.c:81
static size_t data_size
Number of bytes in data.
Definition: gnunet-abd.c:187
static struct GNUNET_ARM_Handle * h
Connection with ARM.
Definition: gnunet-arm.c:99
static int start
Set if we are to start default services (including ARM).
Definition: gnunet-arm.c:39
static int list
Set if we should print a list of currently running services.
Definition: gnunet-arm.c:69
static int end
Set if we are to shutdown all services (including ARM).
Definition: gnunet-arm.c:34
static struct Experiment * e
static int res
static int prefix
If printing the value of PREFIX has been requested.
Definition: gnunet-config.c:59
static char * line
Desired phone line (string to be converted to a hash).
static void cleanup(void *cls)
Function scheduled as very last function, cleans up after us.
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:37
static OpusEncoder * enc
OPUS encoder.
static struct in_addr dummy
Target "dummy" address of the packet we pretend to respond to.
uint16_t len
length of data (which is always a uint32_t, but presumably this can be used to specify that fewer byt...
static char * value
Value of the record to add/remove.
static int result
Global testing status.
static char buf[2048]
static struct GNUNET_OS_Process * p
Helper process we started.
Definition: gnunet-uri.c:38
Configuration API.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_data(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, void *buf, size_t buf_size)
Get Crockford32-encoded fixed-size binary data from a configuration.
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.
char * GNUNET_CONFIGURATION_serialize_diagnostics(const struct GNUNET_CONFIGURATION_Handle *cfg)
Serializes the given configuration with diagnostics information.
char * GNUNET_CONFIGURATION_serialize(const struct GNUNET_CONFIGURATION_Handle *cfg, size_t *size)
Serializes the given configuration.
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.
struct GNUNET_CONFIGURATION_Handle * GNUNET_CONFIGURATION_default(void)
Return GNUnet's default configuration.
enum GNUNET_GenericReturnValue(* GNUNET_CONFIGURATION_Callback)(void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg)
Signature of a function to be run with a configuration.
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.
struct GNUNET_CONFIGURATION_Handle * GNUNET_CONFIGURATION_create()
Create a new configuration object.
void GNUNET_CONFIGURATION_iterate_sections(const struct GNUNET_CONFIGURATION_Handle *cfg, GNUNET_CONFIGURATION_SectionIterator iter, void *iter_cls)
Iterate over all sections in the configuration.
void GNUNET_CONFIGURATION_destroy(struct GNUNET_CONFIGURATION_Handle *cfg)
Destroy configuration object.
void GNUNET_CONFIGURATION_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.
void(* GNUNET_CONFIGURATION_SectionIterator)(void *cls, const char *section)
Function to iterate over section.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_deserialize(struct GNUNET_CONFIGURATION_Handle *cfg, const char *mem, size_t size, const char *source_filename)
De-serializes configuration.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_size(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, unsigned long long *size)
Get a configuration value that should be a size in bytes.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_yesno(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option)
Get a configuration value that should be in a set of "YES" or "NO".
char * GNUNET_CONFIGURATION_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...
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.
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.
int GNUNET_CONFIGURATION_load(struct GNUNET_CONFIGURATION_Handle *cfg, const char *filename)
Load configuration (starts with defaults, then loads system-specific configuration).
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_parse_and_run(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.
char * GNUNET_CONFIGURATION_default_filename(void)
Return the filename of the default configuration filename that is used when no explicit configuration...
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.
struct GNUNET_CONFIGURATION_Handle * GNUNET_CONFIGURATION_dup(const struct GNUNET_CONFIGURATION_Handle *cfg)
Duplicate an existing configuration object.
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:1237
int GNUNET_DISK_glob(const char *glob_pattern, GNUNET_FileNameCallback callback, void *callback_cls)
Find all files matching a glob pattern.
Definition: disk.c:1009
enum GNUNET_GenericReturnValue GNUNET_DISK_file_test(const char *fil)
Check that fil corresponds to a filename (of a file that exists and that is not a directory).
Definition: disk.c:482
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:686
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:489
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:221
enum GNUNET_GenericReturnValue GNUNET_DISK_directory_remove(const char *filename)
Remove all files in a directory (rm -rf).
Definition: disk.c:1087
enum GNUNET_GenericReturnValue GNUNET_DISK_directory_test(const char *fil, int is_readable)
Test if fil is a directory and listable.
Definition: disk.c:403
enum GNUNET_GenericReturnValue GNUNET_DISK_file_close(struct GNUNET_DISK_FileHandle *h)
Close an open file.
Definition: disk.c:1308
enum GNUNET_GenericReturnValue GNUNET_DISK_directory_create_for_file(const char *filename)
Create the directory structure for storing a file.
Definition: disk.c:582
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:664
int GNUNET_DISK_directory_scan(const char *dir_name, GNUNET_FileNameCallback callback, void *callback_cls)
Scan a directory for files.
Definition: disk.c:814
@ 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.
char * GNUNET_buffer_reap_str(struct GNUNET_Buffer *buf)
Clear the buffer and return the string it contained.
Definition: buffer.c:123
#define GNUNET_log(kind,...)
void GNUNET_buffer_write_fstr(struct GNUNET_Buffer *buf, const char *fmt,...) __attribute__((format(printf
Write a 0-terminated formatted string to a buffer, excluding the 0-terminator.
void GNUNET_buffer_write_str(struct GNUNET_Buffer *buf, const char *str)
Write a 0-terminated string to a buffer, excluding the 0-terminator.
Definition: buffer.c:103
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
GNUNET_GenericReturnValue
Named constants for return values.
@ GNUNET_OK
@ GNUNET_YES
@ GNUNET_NO
@ GNUNET_SYSERR
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur.
void GNUNET_log_config_invalid(enum GNUNET_ErrorType kind, const char *section, const char *option, const char *required)
Log error message about invalid configuration option value.
#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.
const struct GNUNET_OS_ProjectData * GNUNET_OS_project_data_default(void)
Return default project data used by 'libgnunetutil' for GNUnet.
const struct GNUNET_OS_ProjectData * GNUNET_OS_project_data_get(void)
char * GNUNET_OS_installation_get_path(enum GNUNET_OS_InstallationPathKind dirkind)
Get the path to a specific GNUnet installation directory or, with GNUNET_OS_IPK_SELF_PREFIX,...
void GNUNET_OS_init(const struct GNUNET_OS_ProjectData *pd)
Setup OS subsystem with project data.
@ 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:494
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:788
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:260
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:236
static unsigned int size
Size of the "table".
Definition: peer.c:68
#define DIR_SEPARATOR_STR
Definition: platform.h:166
#define _(String)
GNU gettext support macro.
Definition: platform.h:178
#define SIZE_MAX
Definition: platform.h:208
uint32_t number
Closure to collect_files_cb.
char ** files
Collected files from globbing.
unsigned int files_length
Size of the files array.
configuration entry
Definition: configuration.c:39
char * hint_filename
Diagnostics information for the filename.
Definition: configuration.c:58
struct ConfigEntry * next
This is a linked list.
Definition: configuration.c:43
char * key
key for this entry
Definition: configuration.c:48
unsigned int hint_lineno
Diagnostics information for the line number.
Definition: configuration.c:63
char * val
current, committed value
Definition: configuration.c:53
char * hint_restrict_section
Was this configuration file parsed via @inline-secret@?
struct ConfigFile * next
char * source_filename
Source filename.
bool hint_inaccessible
Was this configuration file inaccessible?
struct ConfigFile * prev
unsigned int level
Level in the tree of loaded config files.
configuration section
Definition: configuration.c:71
char * name
name of the section
Definition: configuration.c:85
char * hint_inlined_from_filename
For secret sections: Where was this inlined from?
struct ConfigEntry * entries
entries in the section
Definition: configuration.c:80
bool inaccessible
Is the configuration section marked as inaccessible?
Definition: configuration.c:93
struct ConfigSection * next
This is a linked list.
Definition: configuration.c:75
char * hint_secret_filename
Diagnostics hint for the secret file.
Definition: configuration.c:98
unsigned int hint_inlined_from_line
For secret sections: Where was this inlined from?
char * hint_secret_stat
Extra information regarding permissions of the secret file.
Used for diffing a configuration object against the default one.
const struct GNUNET_CONFIGURATION_Handle * cfg_default
struct GNUNET_CONFIGURATION_Handle * cfgDiff
Dynamically growing buffer.
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.
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.