GNUnet  0.11.x
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  */
25 #include "platform.h"
26 #include "gnunet_crypto_lib.h"
27 #include "gnunet_strings_lib.h"
28 #include "gnunet_os_lib.h"
30 #include "gnunet_disk_lib.h"
31 #include "gnunet_buffer_lib.h"
32 #include "gnunet_container_lib.h"
33 
34 #define LOG(kind, ...) GNUNET_log_from (kind, "util", __VA_ARGS__)
35 
36 #define LOG_STRERROR_FILE(kind, syscall, filename) \
37  GNUNET_log_from_strerror_file (kind, "util", syscall, filename)
38 
43 {
47  struct ConfigEntry *next;
48 
52  char *key;
53 
57  char *val;
58 
63 
67  unsigned int hint_lineno;
68 };
69 
70 
75 {
80 
85 
89  char *name;
90 
98 
103 
108 
113 
118 };
119 
121 {
126 
130  unsigned int level;
131 
132  struct ConfigFile *prev;
133 
134  struct ConfigFile *next;
135 
141 
146 };
147 
148 
153 {
158 
163 
168 
172  unsigned int current_nest_level;
173 
178 
185 
190 
195 
201  const char *restrict_section;
202 };
203 
204 
210 {
212 
214 };
215 
216 
217 void
220 {
221  cfg->diagnostics = true;
222 }
223 
224 
227 {
229  char *p;
230 
232  /* make certain values from the project data available
233  as PATHS */
235  if (NULL != p)
236  {
238  "PATHS",
239  "DATADIR",
240  p);
241  GNUNET_free (p);
242  }
244  if (NULL != p)
245  {
247  "PATHS",
248  "LIBDIR",
249  p);
250  GNUNET_free (p);
251  }
253  if (NULL != p)
254  {
256  "PATHS",
257  "BINDIR",
258  p);
259  GNUNET_free (p);
260  }
262  if (NULL != p)
263  {
265  "PATHS",
266  "PREFIX",
267  p);
268  GNUNET_free (p);
269  }
271  if (NULL != p)
272  {
274  "PATHS",
275  "LOCALEDIR",
276  p);
277  GNUNET_free (p);
278  }
280  if (NULL != p)
281  {
283  "PATHS",
284  "ICONDIR",
285  p);
286  GNUNET_free (p);
287  }
289  if (NULL != p)
290  {
292  "PATHS",
293  "DOCDIR",
294  p);
295  GNUNET_free (p);
296  }
298  if (NULL != p)
299  {
301  "PATHS",
302  "LIBEXECDIR",
303  p);
304  GNUNET_free (p);
305  }
306  return cfg;
307 }
308 
309 
310 void
312 {
313  struct ConfigSection *sec;
314  struct ConfigFile *cf;
315 
316  while (NULL != (sec = cfg->sections))
318  while (NULL != (cf = cfg->loaded_files_head))
319  {
324  cf);
325  GNUNET_free (cf);
326  }
328  GNUNET_free (cfg);
329 }
330 
331 
335  void *cb_cls)
336 {
339 
341  if (GNUNET_OK !=
343  filename))
344  {
345  GNUNET_break (0);
347  return GNUNET_SYSERR;
348  }
349  ret = cb (cb_cls, cfg);
351  return ret;
352 }
353 
354 
359 {
363  char **files;
364 
368  unsigned int files_length;
369 };
370 
371 
381 static int
382 collect_files_cb (void *cls,
383  const char *filename)
384 {
385  struct CollectFilesContext *igc = cls;
386 
388  igc->files_length,
390  return GNUNET_OK;
391 }
392 
393 
401 static struct ConfigSection *
403  const char *section)
404 {
405  struct ConfigSection *pos;
406 
407  pos = cfg->sections;
408  while ((pos != NULL) && (0 != strcasecmp (section, pos->name)))
409  pos = pos->next;
410  return pos;
411 }
412 
413 
414 static int
415 pstrcmp (const void *a, const void *b)
416 {
417  return strcmp (*((const char **) a), *((const char **) b));
418 }
419 
420 
428  const char *path_or_glob,
429  bool path_is_glob,
430  const char *restrict_section,
431  const char *source_filename,
432  unsigned int source_lineno)
433 {
434  char *inline_path = NULL;
435  struct GNUNET_CONFIGURATION_Handle *other_cfg = NULL;
436  struct CollectFilesContext igc = {
437  .files = NULL,
438  .files_length = 0,
439  };
440  enum GNUNET_GenericReturnValue fun_ret;
441  unsigned int old_nest_level = cfg->current_nest_level++;
442 
443  /* We support the section restriction only for non-globs */
444  GNUNET_assert (! (path_is_glob && (NULL != restrict_section)));
445 
446  if (NULL == source_filename)
447  {
449  "Refusing to parse inline configurations, "
450  "not allowed without source filename!\n");
451  fun_ret = GNUNET_SYSERR;
452  goto cleanup;
453  }
454 
455  if ('/' == *path_or_glob)
456  inline_path = GNUNET_strdup (path_or_glob);
457  else
458  {
459  /* We compute the canonical, absolute path first,
460  so that relative imports resolve properly with symlinked
461  config files. */
462  char *source_realpath;
463  char *endsep;
464 
465  source_realpath = realpath (source_filename,
466  NULL);
467  if (NULL == source_realpath)
468  {
469  /* Couldn't even resolve path of base dir. */
470  GNUNET_break (0);
471  /* failed to parse included config */
472  fun_ret = GNUNET_SYSERR;
473  goto cleanup;
474  }
475  endsep = strrchr (source_realpath, '/');
476  GNUNET_assert (NULL != endsep);
477  *endsep = '\0';
478  GNUNET_asprintf (&inline_path,
479  "%s/%s",
480  source_realpath,
481  path_or_glob);
482  free (source_realpath);
483  }
484 
485  if (path_is_glob)
486  {
487  int nret;
488 
490  "processing config glob '%s'\n",
491  inline_path);
492 
493  nret = GNUNET_DISK_glob (inline_path, collect_files_cb, &igc);
494  if (-1 == nret)
495  {
496  fun_ret = GNUNET_SYSERR;
497  goto cleanup;
498  }
499  GNUNET_assert (nret == igc.files_length);
500  qsort (igc.files, igc.files_length, sizeof (char *), pstrcmp);
501  for (int i = 0; i < nret; i++)
502  {
503  if (GNUNET_OK !=
505  igc.files[i]))
506  {
507  fun_ret = GNUNET_SYSERR;
508  goto cleanup;
509  }
510  }
511  fun_ret = GNUNET_OK;
512  }
513  else if (NULL != restrict_section)
514  {
515  enum GNUNET_GenericReturnValue inner_ret;
516  struct ConfigSection *cs;
517  struct ConfigFile *cf = GNUNET_new (struct ConfigFile);
518 
519  inner_ret = GNUNET_DISK_file_test_read (inline_path);
520 
521  cs = find_section (cfg, restrict_section);
522 
523  if (NULL == cs)
524  {
525  cs = GNUNET_new (struct ConfigSection);
526  cs->name = GNUNET_strdup (restrict_section);
527  cs->next = cfg->sections;
528  cfg->sections = cs;
529  cs->entries = NULL;
530  }
531  if (cfg->diagnostics)
532  {
533  char *sfn = GNUNET_STRINGS_filename_expand (inline_path);
534  struct stat istat;
535 
536  cs->hint_secret_filename = sfn;
537  if (0 == stat (sfn, &istat))
538  {
539  struct passwd *pw = getpwuid (istat.st_uid);
540  struct group *gr = getgrgid (istat.st_gid);
541  char *pwname = (NULL == pw) ? "<unknown>" : pw->pw_name;
542  char *grname = (NULL == gr) ? "<unknown>" : gr->gr_name;
543 
545  "%s:%s %o",
546  pwname,
547  grname,
548  istat.st_mode);
549  }
550  else
551  {
552  cs->hint_secret_stat = GNUNET_strdup ("<can't stat file>");
553  }
554  if (source_filename)
555  {
556  /* Possible that this secret section has been inlined before */
558  cs->hint_inlined_from_filename = GNUNET_strdup (source_filename);
559  cs->hint_inlined_from_line = source_lineno;
560  }
561  }
562 
563  /* Put file in the load list for diagnostics, even if we can't access it. */
564  {
566  cf->source_filename = GNUNET_strdup (inline_path);
567  cf->hint_restrict_section = GNUNET_strdup (restrict_section);
570  cf);
571  }
572 
573  if (GNUNET_OK != inner_ret)
574  {
575  cs->inaccessible = true;
576  cf->hint_inaccessible = true;
577  /* File can't be accessed, but that's okay. */
578  fun_ret = GNUNET_OK;
579  goto cleanup;
580  }
581 
582  other_cfg = GNUNET_CONFIGURATION_create ();
583  other_cfg->restrict_section = restrict_section;
584  inner_ret = GNUNET_CONFIGURATION_parse (other_cfg,
585  inline_path);
586  if (GNUNET_OK != inner_ret)
587  {
588  cf->hint_inaccessible = true;
589  fun_ret = inner_ret;
590  goto cleanup;
591  }
592 
593  cs = find_section (other_cfg, restrict_section);
594  if (NULL == cs)
595  {
597  "Configuration file '%s' loaded with @inline-secret@ "
598  "does not contain section '%s'.\n",
599  inline_path,
600  restrict_section);
601  /* Inlined onfiguration is accessible but doesn't contain any values.
602  We treat this as if the inlined section was empty, and do not
603  consider it an error. */
604  fun_ret = GNUNET_OK;
605  goto cleanup;
606  }
607  for (struct ConfigEntry *ce = cs->entries;
608  NULL != ce;
609  ce = ce->next)
611  restrict_section,
612  ce->key,
613  ce->val);
614  fun_ret = GNUNET_OK;
615  }
616  else if (GNUNET_OK !=
618  inline_path))
619  {
620  fun_ret = GNUNET_SYSERR;
621  goto cleanup;
622  }
623  else
624  {
625  fun_ret = GNUNET_OK;
626  }
627 cleanup:
628  cfg->current_nest_level = old_nest_level;
629  if (NULL != other_cfg)
630  GNUNET_CONFIGURATION_destroy (other_cfg);
631  GNUNET_free (inline_path);
632  if (igc.files_length > 0)
633  {
634  for (size_t i = 0; i < igc.files_length; i++)
635  GNUNET_free (igc.files[i]);
636  GNUNET_array_grow (igc.files, igc.files_length, 0);
637  }
638  return fun_ret;
639 }
640 
641 
650 static struct ConfigEntry *
652  const char *section,
653  const char *key)
654 {
655  struct ConfigSection *sec;
656  struct ConfigEntry *pos;
657 
658  if (NULL == (sec = find_section (cfg, section)))
659  return NULL;
660  if (sec->inaccessible)
661  {
663  "Section '%s' is marked as inaccessible, because the configuration "
664  " file that contains the section can't be read. Attempts to use "
665  "option '%s' will fail.\n",
666  section,
667  key);
668  return NULL;
669  }
670  pos = sec->entries;
671  while ((pos != NULL) && (0 != strcasecmp (key, pos->key)))
672  pos = pos->next;
673  return pos;
674 }
675 
676 
686 static void
688  const char *section,
689  const char *option,
690  const char *hint_filename,
691  unsigned int hint_line)
692 {
693  struct ConfigEntry *e = find_entry (cfg, section, option);
694  if (! cfg->diagnostics)
695  return;
696  if (! e)
697  return;
698  e->hint_filename = GNUNET_strdup (hint_filename);
699  e->hint_lineno = hint_line;
700 }
701 
702 
705  const char *mem,
706  size_t size,
707  const char *source_filename)
708 {
709  size_t line_size;
710  unsigned int nr;
711  size_t r_bytes;
712  size_t to_read;
714  char *section;
715  char *eq;
716  char *tag;
717  char *value;
718  char *line_orig = NULL;
719 
720  ret = GNUNET_OK;
721  section = NULL;
722  nr = 0;
723  r_bytes = 0;
724  while (r_bytes < size)
725  {
726  char *pos;
727  char *line;
728  bool emptyline;
729 
730  GNUNET_free (line_orig);
731  /* fgets-like behaviour on buffer */
732  to_read = size - r_bytes;
733  pos = memchr (&mem[r_bytes], '\n', to_read);
734  if (NULL == pos)
735  {
736  line_orig = GNUNET_strndup (&mem[r_bytes],
737  line_size = to_read);
738  r_bytes += line_size;
739  }
740  else
741  {
742  line_orig = GNUNET_strndup (&mem[r_bytes],
743  line_size = (pos - &mem[r_bytes]));
744  r_bytes += line_size + 1;
745  }
746  line = line_orig;
747  /* increment line number */
748  nr++;
749  /* tabs and '\r' are whitespace */
750  emptyline = GNUNET_YES;
751  for (size_t i = 0; i < line_size; i++)
752  {
753  if (line[i] == '\t')
754  line[i] = ' ';
755  if (line[i] == '\r')
756  line[i] = ' ';
757  if (' ' != line[i])
758  emptyline = GNUNET_NO;
759  }
760  /* ignore empty lines */
761  if (GNUNET_YES == emptyline)
762  continue;
763 
764  /* remove tailing whitespace */
765  for (size_t i = line_size - 1;
766  (i >= 1) && (isspace ((unsigned char) line[i]));
767  i--)
768  line[i] = '\0';
769 
770  /* remove leading whitespace */
771  for (; line[0] != '\0' && (isspace ((unsigned char) line[0])); line++)
772  ;
773 
774  /* ignore comments */
775  if ( ('#' == line[0]) ||
776  ('%' == line[0]) )
777  continue;
778 
779  /* Handle special directives. */
780  if ('@' == line[0])
781  {
782  char *end = strchr (line + 1, '@');
783  char *directive;
784  enum GNUNET_GenericReturnValue directive_ret;
785 
786  if (NULL != cfg->restrict_section)
787  {
789  _ (
790  "Illegal directive in line %u (parsing restricted section %s)\n"),
791  nr,
793  ret = GNUNET_SYSERR;
794  break;
795  }
796 
797  if (NULL == end)
798  {
800  _ ("Bad directive in line %u\n"),
801  nr);
802  ret = GNUNET_SYSERR;
803  break;
804  }
805  *end = '\0';
806  directive = line + 1;
807 
808  if (0 == strcasecmp (directive, "INLINE"))
809  {
810  const char *path = end + 1;
811 
812  /* Skip space before path */
813  for (; isspace (*path); path++)
814  ;
815 
816  directive_ret = handle_inline (cfg,
817  path,
818  false,
819  NULL,
820  source_filename,
821  nr);
822  }
823  else if (0 == strcasecmp (directive, "INLINE-MATCHING"))
824  {
825  const char *path = end + 1;
826 
827  /* Skip space before path */
828  for (; isspace (*path); path++)
829  ;
830 
831  directive_ret = handle_inline (cfg,
832  path,
833  true,
834  NULL,
835  source_filename,
836  nr);
837  }
838  else if (0 == strcasecmp (directive, "INLINE-SECRET"))
839  {
840  char *secname = end + 1;
841  char *secname_end;
842  const char *path;
843 
844  /* Skip space before secname */
845  for (; isspace (*secname); secname++)
846  ;
847 
848  secname_end = strchr (secname, ' ');
849 
850  if (NULL == secname_end)
851  {
853  _ ("Bad inline-secret directive in line %u\n"),
854  nr);
855  ret = GNUNET_SYSERR;
856  break;
857  }
858  *secname_end = '\0';
859  path = secname_end + 1;
860 
861  /* Skip space before path */
862  for (; isspace (*path); path++)
863  ;
864 
865  directive_ret = handle_inline (cfg,
866  path,
867  false,
868  secname,
869  source_filename,
870  nr);
871  }
872  else
873  {
875  _ ("Unknown or malformed directive '%s' in line %u\n"),
876  directive,
877  nr);
878  ret = GNUNET_SYSERR;
879  break;
880  }
881  if (GNUNET_OK != directive_ret)
882  {
883  ret = directive_ret;
884  break;
885  }
886  continue;
887  }
888  if (('[' == line[0]) && (']' == 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]) && ('"' == value[strlen (value) - 1]))
931  {
932  value[strlen (value) - 1] = '\0';
933  value++;
934  }
935  GNUNET_CONFIGURATION_set_value_string (cfg, section, tag, &value[i]);
936  if (cfg->diagnostics)
937  {
939  section,
940  tag,
941  source_filename ? source_filename : "<input>",
942  nr);
943  }
944  GNUNET_free (tag);
945  continue;
946  }
947  /* parse error */
949  _ ("Syntax error while deserializing in line %u\n"),
950  nr);
951  ret = GNUNET_SYSERR;
952  break;
953  }
954  GNUNET_free (line_orig);
955  GNUNET_free (section);
956  GNUNET_assert ( (GNUNET_OK != ret) ||
957  (r_bytes == size) );
958  return ret;
959 }
960 
961 
964  const char *filename)
965 {
966  uint64_t fs64;
967  size_t fs;
968  char *fn;
969  char *mem;
970  int dirty;
972  ssize_t sret;
973 
975  LOG (GNUNET_ERROR_TYPE_DEBUG, "Asked to parse config file `%s'\n", fn);
976  if (NULL == fn)
977  return GNUNET_SYSERR;
978 
979 
980  /* Check for cycles */
981  {
982  unsigned int lvl = cfg->current_nest_level;
983  struct ConfigFile *cf = cfg->loaded_files_tail;
984  struct ConfigFile *parent = NULL;
985 
986 
987  for (; NULL != cf; parent = cf, cf = cf->prev)
988  {
989  /* Check parents based on level, skipping children of siblings. */
990  if (cf->level >= lvl)
991  continue;
992  lvl = cf->level;
993  if ( (NULL == cf->source_filename) || (NULL == filename))
994  continue;
995  if (0 == strcmp (cf->source_filename, filename))
996  {
997  if (NULL == parent)
998  {
1000  "Forbidden direct cyclic configuration import (%s -> %s)\n",
1001  cf->source_filename,
1002  filename);
1003  }
1004  else
1006  "Forbidden indirect cyclic configuration import (%s -> ... -> %s -> %s)\n",
1007  cf->source_filename,
1008  parent->source_filename,
1009  filename);
1010  GNUNET_free (fn);
1011  return GNUNET_SYSERR;
1012  }
1013  }
1014 
1015  }
1016 
1017  /* Keep track of loaded files.*/
1018  {
1019  struct ConfigFile *cf = GNUNET_new (struct ConfigFile);
1020 
1021  cf->level = cfg->current_nest_level;
1022  cf->source_filename = GNUNET_strdup (filename ? filename : "<input>");
1025  cf);
1026  }
1027 
1028  dirty = cfg->dirty; /* back up value! */
1029  if (GNUNET_SYSERR ==
1031  {
1033  "Error while determining the file size of `%s'\n",
1034  fn);
1035  GNUNET_free (fn);
1036  return GNUNET_SYSERR;
1037  }
1038  if (fs64 > SIZE_MAX)
1039  {
1040  GNUNET_break (0); /* File size is more than the heap size */
1041  GNUNET_free (fn);
1042  return GNUNET_SYSERR;
1043  }
1044  fs = fs64;
1045  mem = GNUNET_malloc (fs);
1046  sret = GNUNET_DISK_fn_read (fn, mem, fs);
1047  if ((sret < 0) || (fs != (size_t) sret))
1048  {
1049  LOG (GNUNET_ERROR_TYPE_WARNING, _ ("Error while reading file `%s'\n"), fn);
1050  GNUNET_free (fn);
1051  GNUNET_free (mem);
1052  return GNUNET_SYSERR;
1053  }
1054  LOG (GNUNET_ERROR_TYPE_DEBUG, "Deserializing contents of file `%s'\n", fn);
1056  mem,
1057  fs,
1058  fn);
1059  if (GNUNET_SYSERR == ret)
1060  {
1062  _ ("Failed to parse configuration file `%s'\n"),
1063  fn);
1064  }
1065  GNUNET_free (fn);
1066  GNUNET_free (mem);
1067  /* restore dirty flag - anything we set in the meantime
1068  * came from disk */
1069  cfg->dirty = dirty;
1070  return ret;
1071 }
1072 
1073 
1076 {
1077  return cfg->dirty;
1078 }
1079 
1080 
1088 static bool
1089 do_skip (const char *sec,
1090  const char *key)
1091 {
1092  if (0 != strcasecmp ("PATHS",
1093  sec))
1094  return false;
1095  return ( (0 == strcasecmp ("DATADIR",
1096  key)) ||
1097  (0 == strcasecmp ("LIBDIR",
1098  key)) ||
1099  (0 == strcasecmp ("BINDIR",
1100  key)) ||
1101  (0 == strcasecmp ("PREFIX",
1102  key)) ||
1103  (0 == strcasecmp ("LOCALEDIR",
1104  key)) ||
1105  (0 == strcasecmp ("ICONDIR",
1106  key)) ||
1107  (0 == strcasecmp ("DOCDIR",
1108  key)) ||
1109  (0 == strcasecmp ("DEFAULTCONFIG",
1110  key)) ||
1111  (0 == strcasecmp ("LIBEXECDIR",
1112  key)) );
1113 }
1114 
1115 
1116 char *
1118  size_t *size)
1119 {
1120  char *mem;
1121  char *cbuf;
1122  char *val;
1123  char *pos;
1124  size_t m_size;
1125  size_t c_size;
1126 
1127  /* Pass1 : calculate the buffer size required */
1128  m_size = 0;
1129  for (struct ConfigSection *sec = cfg->sections;
1130  NULL != sec;
1131  sec = sec->next)
1132  {
1133  if (sec->inaccessible)
1134  continue;
1135  /* For each section we need to add 3 characters: {'[',']','\n'} */
1136  m_size += strlen (sec->name) + 3;
1137  for (struct ConfigEntry *ent = sec->entries;
1138  NULL != ent;
1139  ent = ent->next)
1140  {
1141  if (do_skip (sec->name,
1142  ent->key))
1143  continue;
1144  if (NULL != ent->val)
1145  {
1146  /* if val has any '\n' then they occupy +1 character as '\n'->'\\','n' */
1147  pos = ent->val;
1148  while (NULL != (pos = strstr (pos, "\n")))
1149  {
1150  m_size++;
1151  pos++;
1152  }
1153  /* For each key = value pair we need to add 4 characters (2
1154  spaces and 1 equal-to character and 1 new line) */
1155  m_size += strlen (ent->key) + strlen (ent->val) + 4;
1156  }
1157  }
1158  /* A new line after section end */
1159  m_size++;
1160  }
1161 
1162  /* Pass2: Allocate memory and write the configuration to it */
1163  mem = GNUNET_malloc (m_size);
1164  c_size = 0;
1165  *size = c_size;
1166  for (struct ConfigSection *sec = cfg->sections;
1167  NULL != sec;
1168  sec = sec->next)
1169  {
1170  int len;
1171 
1172  len = GNUNET_asprintf (&cbuf,
1173  "[%s]\n",
1174  sec->name);
1175  GNUNET_assert (0 < len);
1176  GNUNET_memcpy (mem + c_size,
1177  cbuf,
1178  len);
1179  c_size += len;
1180  GNUNET_free (cbuf);
1181  for (struct ConfigEntry *ent = sec->entries;
1182  NULL != ent;
1183  ent = ent->next)
1184  {
1185  if (do_skip (sec->name,
1186  ent->key))
1187  continue;
1188  if (NULL != ent->val)
1189  {
1190  val = GNUNET_malloc (strlen (ent->val) * 2 + 1);
1191  strcpy (val, ent->val);
1192  while (NULL != (pos = strstr (val, "\n")))
1193  {
1194  memmove (&pos[2], &pos[1], strlen (&pos[1]));
1195  pos[0] = '\\';
1196  pos[1] = 'n';
1197  }
1198  len = GNUNET_asprintf (&cbuf, "%s = %s\n", ent->key, val);
1199  GNUNET_free (val);
1200  GNUNET_memcpy (mem + c_size, cbuf, len);
1201  c_size += len;
1202  GNUNET_free (cbuf);
1203  }
1204  }
1205  GNUNET_memcpy (mem + c_size, "\n", 1);
1206  c_size++;
1207  }
1208  GNUNET_assert (c_size == m_size);
1209  *size = c_size;
1210  return mem;
1211 }
1212 
1213 
1214 char *
1217 {
1218  struct GNUNET_Buffer buf = { 0 };
1219 
1221  "#\n# Configuration file diagnostics\n#\n");
1223  "# Entry point: %s\n",
1225  "<none>");
1227  "#\n# Files Loaded:\n");
1228 
1229  for (struct ConfigFile *cfil = cfg->loaded_files_head;
1230  NULL != cfil;
1231  cfil = cfil->next)
1232  {
1234  "# ");
1235  for (unsigned int i = 0; i < cfil->level; i++)
1237  "+");
1238  if (0 != cfil->level)
1240  " ");
1241 
1243  "%s",
1244  cfil->source_filename);
1245 
1246  if (NULL != cfil->hint_restrict_section)
1248  " (%s secret section %s)",
1249  cfil->hint_inaccessible
1250  ? "inaccessible"
1251  : "loaded",
1252  cfil->hint_restrict_section);
1253 
1255  "\n");
1256  }
1257 
1259  "#\n\n");
1260 
1261  for (struct ConfigSection *sec = cfg->sections;
1262  NULL != sec;
1263  sec = sec->next)
1264  {
1265  if (sec->hint_secret_filename)
1267  "# secret section from %s\n# secret file stat %s\n",
1268  sec->hint_secret_filename,
1269  sec->hint_secret_stat);
1270  if (sec->hint_inlined_from_filename)
1271  {
1273  "# inlined from %s:%u\n",
1274  sec->hint_inlined_from_filename,
1275  sec->hint_inlined_from_line);
1276  }
1278  "[%s]\n\n",
1279  sec->name);
1280  if (sec->inaccessible)
1281  {
1283  "# <section contents inaccessible>\n\n\n");
1284  continue;
1285  }
1286  for (struct ConfigEntry *ent = sec->entries;
1287  NULL != ent;
1288  ent = ent->next)
1289  {
1290  if (do_skip (sec->name,
1291  ent->key))
1292  continue;
1293  if (NULL != ent->val)
1294  {
1295  char *pos;
1296  char *val = GNUNET_malloc (strlen (ent->val) * 2 + 1);
1297  strcpy (val, ent->val);
1298  while (NULL != (pos = strstr (val, "\n")))
1299  {
1300  memmove (&pos[2], &pos[1], strlen (&pos[1]));
1301  pos[0] = '\\';
1302  pos[1] = 'n';
1303  }
1304  if (NULL != ent->hint_filename)
1305  {
1307  "# %s:%u\n",
1308  ent->hint_filename,
1309  ent->hint_lineno);
1310  }
1312  "%s = %s\n",
1313  ent->key,
1314  val);
1315  GNUNET_free (val);
1316  }
1317  GNUNET_buffer_write_str (&buf, "\n");
1318  }
1319  GNUNET_buffer_write_str (&buf, "\n");
1320  }
1321  return GNUNET_buffer_reap_str (&buf);
1322 }
1323 
1324 
1327  const char *filename)
1328 {
1329  char *fn;
1330  char *cfg_buf;
1331  size_t size;
1332 
1334  if (fn == NULL)
1335  return GNUNET_SYSERR;
1337  {
1338  GNUNET_free (fn);
1339  return GNUNET_SYSERR;
1340  }
1342  &size);
1343  {
1344  struct GNUNET_DISK_FileHandle *h;
1345 
1346  h = GNUNET_DISK_file_open (fn,
1354  if (NULL == h)
1355  {
1356  GNUNET_free (fn);
1357  GNUNET_free (cfg_buf);
1358  return GNUNET_SYSERR;
1359  }
1360  if (((ssize_t) size) !=
1362  cfg_buf,
1363  size))
1364  {
1366  "write",
1367  fn);
1369  (void) GNUNET_DISK_directory_remove (fn);
1370  GNUNET_free (fn);
1371  GNUNET_free (cfg_buf);
1372  cfg->dirty = GNUNET_SYSERR; /* last write failed */
1373  return GNUNET_SYSERR;
1374  }
1377  }
1378  GNUNET_free (fn);
1379  GNUNET_free (cfg_buf);
1380  cfg->dirty = GNUNET_NO; /* last write succeeded */
1381  return GNUNET_OK;
1382 }
1383 
1384 
1385 void
1388  void *iter_cls)
1389 {
1390  for (struct ConfigSection *spos = cfg->sections;
1391  NULL != spos;
1392  spos = spos->next)
1393  for (struct ConfigEntry *epos = spos->entries;
1394  NULL != epos;
1395  epos = epos->next)
1396  if (NULL != epos->val)
1397  iter (iter_cls,
1398  spos->name,
1399  epos->key,
1400  epos->val);
1401 }
1402 
1403 
1404 void
1406  const struct GNUNET_CONFIGURATION_Handle *cfg,
1407  const char *section,
1409  void *iter_cls)
1410 {
1411  struct ConfigSection *spos;
1412  struct ConfigEntry *epos;
1413 
1414  spos = cfg->sections;
1415  while ((spos != NULL) && (0 != strcasecmp (spos->name, section)))
1416  spos = spos->next;
1417  if (NULL == spos)
1418  return;
1419  if (spos->inaccessible)
1420  {
1422  "Section '%s' is marked as inaccessible, because the configuration "
1423  " file that contains the section can't be read.\n",
1424  section);
1425  return;
1426  }
1427  for (epos = spos->entries; NULL != epos; epos = epos->next)
1428  if (NULL != epos->val)
1429  iter (iter_cls, spos->name, epos->key, epos->val);
1430 }
1431 
1432 
1433 void
1435  const struct GNUNET_CONFIGURATION_Handle *cfg,
1437  void *iter_cls)
1438 {
1439  struct ConfigSection *spos;
1440  struct ConfigSection *next;
1441 
1442  next = cfg->sections;
1443  while (next != NULL)
1444  {
1445  spos = next;
1446  next = spos->next;
1447  iter (iter_cls, spos->name);
1448  }
1449 }
1450 
1451 
1452 void
1454  const char *section)
1455 {
1456  struct ConfigSection *spos;
1457  struct ConfigSection *prev;
1458  struct ConfigEntry *ent;
1459 
1460  prev = NULL;
1461  spos = cfg->sections;
1462  while (NULL != spos)
1463  {
1464  if (0 == strcasecmp (section, spos->name))
1465  {
1466  if (NULL == prev)
1467  cfg->sections = spos->next;
1468  else
1469  prev->next = spos->next;
1470  while (NULL != (ent = spos->entries))
1471  {
1472  spos->entries = ent->next;
1473  GNUNET_free (ent->key);
1474  GNUNET_free (ent->val);
1475  GNUNET_free (ent->hint_filename);
1476  GNUNET_free (ent);
1477  cfg->dirty = GNUNET_YES;
1478  }
1479  GNUNET_free (spos->name);
1481  GNUNET_free (spos->hint_secret_stat);
1483  GNUNET_free (spos);
1484  return;
1485  }
1486  prev = spos;
1487  spos = spos->next;
1488  }
1489 }
1490 
1491 
1501 static void
1502 copy_entry (void *cls,
1503  const char *section,
1504  const char *option,
1505  const char *value)
1506 {
1507  struct GNUNET_CONFIGURATION_Handle *dst = cls;
1508 
1509  GNUNET_CONFIGURATION_set_value_string (dst, section, option, value);
1510 }
1511 
1512 
1515 {
1517 
1520  return ret;
1521 }
1522 
1523 
1534 static void
1535 compare_entries (void *cls,
1536  const char *section,
1537  const char *option,
1538  const char *value)
1539 {
1540  struct DiffHandle *dh = cls;
1541  struct ConfigEntry *entNew;
1542 
1543  entNew = find_entry (dh->cfg_default, section, option);
1544  if ((NULL != entNew) && (NULL != entNew->val) &&
1545  (0 == strcmp (entNew->val, value)))
1546  return;
1547  GNUNET_CONFIGURATION_set_value_string (dh->cfgDiff, section, option, value);
1548 }
1549 
1550 
1553  const struct GNUNET_CONFIGURATION_Handle *cfg_default,
1554  const struct GNUNET_CONFIGURATION_Handle *cfg_new)
1555 {
1556  struct DiffHandle diffHandle;
1557 
1558  diffHandle.cfgDiff = GNUNET_CONFIGURATION_create ();
1559  diffHandle.cfg_default = cfg_default;
1560  GNUNET_CONFIGURATION_iterate (cfg_new, &compare_entries, &diffHandle);
1561  return diffHandle.cfgDiff;
1562 }
1563 
1564 
1568  const struct GNUNET_CONFIGURATION_Handle *cfg_new,
1569  const char *filename)
1570 {
1571  int ret;
1572  struct GNUNET_CONFIGURATION_Handle *diff;
1573 
1574  diff = GNUNET_CONFIGURATION_get_diff (cfg_default, cfg_new);
1577  return ret;
1578 }
1579 
1580 
1581 void
1583  const char *section,
1584  const char *option,
1585  const char *value)
1586 {
1587  struct ConfigSection *sec;
1588  struct ConfigEntry *e;
1589  char *nv;
1590 
1591  e = find_entry (cfg, section, option);
1592  if (NULL != e)
1593  {
1594  if (NULL == value)
1595  {
1596  GNUNET_free (e->val);
1597  e->val = NULL;
1598  }
1599  else
1600  {
1601  nv = GNUNET_strdup (value);
1602  GNUNET_free (e->val);
1603  e->val = nv;
1604  }
1605  return;
1606  }
1607  sec = find_section (cfg, section);
1608  if (sec == NULL)
1609  {
1610  sec = GNUNET_new (struct ConfigSection);
1611  sec->name = GNUNET_strdup (section);
1612  sec->next = cfg->sections;
1613  cfg->sections = sec;
1614  }
1615  e = GNUNET_new (struct ConfigEntry);
1616  e->key = GNUNET_strdup (option);
1617  e->val = GNUNET_strdup (value);
1618  e->next = sec->entries;
1619  sec->entries = e;
1620 }
1621 
1622 
1623 void
1625  const char *section,
1626  const char *option,
1627  unsigned long long number)
1628 {
1629  char s[64];
1630 
1631  GNUNET_snprintf (s, 64, "%llu", number);
1632  GNUNET_CONFIGURATION_set_value_string (cfg, section, option, s);
1633 }
1634 
1635 
1638  const struct GNUNET_CONFIGURATION_Handle *cfg,
1639  const char *section,
1640  const char *option,
1641  unsigned long long *number)
1642 {
1643  struct ConfigEntry *e;
1644  char dummy[2];
1645 
1646  if (NULL == (e = find_entry (cfg, section, option)))
1647  return GNUNET_SYSERR;
1648  if (NULL == e->val)
1649  return GNUNET_SYSERR;
1650  if (1 != sscanf (e->val, "%llu%1s", number, dummy))
1651  return GNUNET_SYSERR;
1652  return GNUNET_OK;
1653 }
1654 
1655 
1658  const struct GNUNET_CONFIGURATION_Handle *cfg,
1659  const char *section,
1660  const char *option,
1661  float *number)
1662 {
1663  struct ConfigEntry *e;
1664  char dummy[2];
1665 
1666  if (NULL == (e = find_entry (cfg, section, option)))
1667  return GNUNET_SYSERR;
1668  if (NULL == e->val)
1669  return GNUNET_SYSERR;
1670  if (1 != sscanf (e->val, "%f%1s", number, dummy))
1671  return GNUNET_SYSERR;
1672  return GNUNET_OK;
1673 }
1674 
1675 
1678  const struct GNUNET_CONFIGURATION_Handle *cfg,
1679  const char *section,
1680  const char *option,
1681  struct GNUNET_TIME_Relative *time)
1682 {
1683  struct ConfigEntry *e;
1684  int ret;
1685 
1686  if (NULL == (e = find_entry (cfg, section, option)))
1687  return GNUNET_SYSERR;
1688  if (NULL == e->val)
1689  return GNUNET_SYSERR;
1691  if (GNUNET_OK != ret)
1693  section,
1694  option,
1695  _ ("Not a valid relative time specification"));
1696  return ret;
1697 }
1698 
1699 
1702  const struct GNUNET_CONFIGURATION_Handle *cfg,
1703  const char *section,
1704  const char *option,
1705  unsigned long long *size)
1706 {
1707  struct ConfigEntry *e;
1708 
1709  if (NULL == (e = find_entry (cfg, section, option)))
1710  return GNUNET_SYSERR;
1711  if (NULL == e->val)
1712  return GNUNET_SYSERR;
1713  return GNUNET_STRINGS_fancy_size_to_bytes (e->val, size);
1714 }
1715 
1716 
1729  const struct GNUNET_CONFIGURATION_Handle *cfg,
1730  const char *section,
1731  const char *option,
1732  char **value)
1733 {
1734  struct ConfigEntry *e;
1735 
1736  if ((NULL == (e = find_entry (cfg, section, option))) || (NULL == e->val))
1737  {
1738  *value = NULL;
1739  return GNUNET_SYSERR;
1740  }
1741  *value = GNUNET_strdup (e->val);
1742  return GNUNET_OK;
1743 }
1744 
1745 
1748  const struct GNUNET_CONFIGURATION_Handle *cfg,
1749  const char *section,
1750  const char *option,
1751  const char *const *choices,
1752  const char **value)
1753 {
1754  struct ConfigEntry *e;
1755  unsigned int i;
1756 
1757  if (NULL == (e = find_entry (cfg, section, option)))
1758  return GNUNET_SYSERR;
1759  for (i = 0; NULL != choices[i]; i++)
1760  if (0 == strcasecmp (choices[i], e->val))
1761  break;
1762  if (NULL == choices[i])
1763  {
1765  _ ("Configuration value '%s' for '%s'"
1766  " in section '%s' is not in set of legal choices\n"),
1767  e->val,
1768  option,
1769  section);
1770  return GNUNET_SYSERR;
1771  }
1772  *value = choices[i];
1773  return GNUNET_OK;
1774 }
1775 
1776 
1779  const char *section,
1780  const char *option,
1781  void *buf,
1782  size_t buf_size)
1783 {
1784  char *enc;
1785  int res;
1786  size_t data_size;
1787 
1788  if (GNUNET_OK !=
1789  (res =
1790  GNUNET_CONFIGURATION_get_value_string (cfg, section, option, &enc)))
1791  return res;
1792  data_size = (strlen (enc) * 5) / 8;
1793  if (data_size != buf_size)
1794  {
1795  GNUNET_free (enc);
1796  return GNUNET_SYSERR;
1797  }
1798  if (GNUNET_OK !=
1799  GNUNET_STRINGS_string_to_data (enc, strlen (enc), buf, buf_size))
1800  {
1801  GNUNET_free (enc);
1802  return GNUNET_SYSERR;
1803  }
1804  GNUNET_free (enc);
1805  return GNUNET_OK;
1806 }
1807 
1808 
1811  const char *section,
1812  const char *option)
1813 {
1814  struct ConfigEntry *e;
1815 
1816  if ((NULL == (e = find_entry (cfg, section, option))) || (NULL == e->val))
1817  return GNUNET_NO;
1818  return GNUNET_YES;
1819 }
1820 
1821 
1837 static char *
1839  char *orig,
1840  unsigned int depth)
1841 {
1842  char *prefix;
1843  char *result;
1844  char *start;
1845  const char *post;
1846  const char *env;
1847  char *def;
1848  char *end;
1849  unsigned int lopen;
1850  char erased_char;
1851  char *erased_pos;
1852  size_t len;
1853 
1854  if (NULL == orig)
1855  return NULL;
1856  if (depth > 128)
1857  {
1859  _ (
1860  "Recursive expansion suspected, aborting $-expansion for term `%s'\n"),
1861  orig);
1862  return orig;
1863  }
1864  LOG (GNUNET_ERROR_TYPE_DEBUG, "Asked to $-expand %s\n", orig);
1865  if ('$' != orig[0])
1866  {
1867  LOG (GNUNET_ERROR_TYPE_DEBUG, "Doesn't start with $ - not expanding\n");
1868  return orig;
1869  }
1870  erased_char = 0;
1871  erased_pos = NULL;
1872  if ('{' == orig[1])
1873  {
1874  start = &orig[2];
1875  lopen = 1;
1876  end = &orig[1];
1877  while (lopen > 0)
1878  {
1879  end++;
1880  switch (*end)
1881  {
1882  case '}':
1883  lopen--;
1884  break;
1885 
1886  case '{':
1887  lopen++;
1888  break;
1889 
1890  case '\0':
1892  _ ("Missing closing `%s' in option `%s'\n"),
1893  "}",
1894  orig);
1895  return orig;
1896 
1897  default:
1898  break;
1899  }
1900  }
1901  erased_char = *end;
1902  erased_pos = end;
1903  *end = '\0';
1904  post = end + 1;
1905  def = strchr (orig, ':');
1906  if (NULL != def)
1907  {
1908  *def = '\0';
1909  def++;
1910  if (('-' == *def) || ('=' == *def))
1911  def++;
1912  def = GNUNET_strdup (def);
1913  }
1914  }
1915  else
1916  {
1917  int i;
1918 
1919  start = &orig[1];
1920  def = NULL;
1921  i = 0;
1922  while ((orig[i] != '/') && (orig[i] != '\\') && (orig[i] != '\0') &&
1923  (orig[i] != ' '))
1924  i++;
1925  if (orig[i] == '\0')
1926  {
1927  post = "";
1928  }
1929  else
1930  {
1931  erased_char = orig[i];
1932  erased_pos = &orig[i];
1933  orig[i] = '\0';
1934  post = &orig[i + 1];
1935  }
1936  }
1938  "Split into `%s' and `%s' with default %s\n",
1939  start,
1940  post,
1941  def);
1942  if (GNUNET_OK !=
1944  {
1945  if (NULL == (env = getenv (start)))
1946  {
1947  /* try default */
1948  def = expand_dollar (cfg, def, depth + 1);
1949  env = def;
1950  }
1951  if (NULL == env)
1952  {
1954  if (erased_pos)
1955  *erased_pos = erased_char;
1957  _ (
1958  "Failed to expand `%s' in `%s' as it is neither found in [PATHS] nor defined as an environmental variable\n"),
1959  start,
1960  orig);
1961  GNUNET_free (start);
1962  return orig;
1963  }
1964  prefix = GNUNET_strdup (env);
1965  }
1967  if ((erased_pos) && ('}' != erased_char))
1968  {
1969  len = strlen (prefix) + 1;
1970  prefix = GNUNET_realloc (prefix, len + 1);
1971  prefix[len - 1] = erased_char;
1972  prefix[len] = '\0';
1973  }
1974  result = GNUNET_malloc (strlen (prefix) + strlen (post) + 1);
1975  strcpy (result, prefix);
1976  strcat (result, post);
1977  GNUNET_free (def);
1978  GNUNET_free (prefix);
1979  GNUNET_free (orig);
1980  return result;
1981 }
1982 
1983 
1984 char *
1986  const struct GNUNET_CONFIGURATION_Handle *cfg,
1987  char *orig)
1988 {
1989  char *dup;
1990  size_t i;
1991  size_t len;
1992 
1993  for (i = 0; '\0' != orig[i]; i++)
1994  {
1995  if ('$' != orig[i])
1996  continue;
1997  dup = GNUNET_strdup (orig + i);
1998  dup = expand_dollar (cfg, dup, 0);
1999  GNUNET_assert (NULL != dup); /* make compiler happy */
2000  len = strlen (dup) + 1;
2001  orig = GNUNET_realloc (orig, i + len);
2002  GNUNET_memcpy (orig + i, dup, len);
2003  GNUNET_free (dup);
2004  }
2005  return orig;
2006 }
2007 
2008 
2011  const struct GNUNET_CONFIGURATION_Handle *cfg,
2012  const char *section,
2013  const char *option,
2014  char **value)
2015 {
2016  char *tmp;
2017 
2018  if (GNUNET_OK !=
2019  GNUNET_CONFIGURATION_get_value_string (cfg, section, option, &tmp))
2020  {
2021  LOG (GNUNET_ERROR_TYPE_DEBUG, "Failed to retrieve filename\n");
2022  *value = NULL;
2023  return GNUNET_SYSERR;
2024  }
2027  GNUNET_free (tmp);
2028  if (*value == NULL)
2029  return GNUNET_SYSERR;
2030  return GNUNET_OK;
2031 }
2032 
2033 
2036  const struct GNUNET_CONFIGURATION_Handle *cfg,
2037  const char *section,
2038  const char *option)
2039 {
2040  static const char *yesno[] = { "YES", "NO", NULL };
2041  const char *val;
2042  int ret;
2043 
2044  ret =
2045  GNUNET_CONFIGURATION_get_value_choice (cfg, section, option, yesno, &val);
2046  if (ret == GNUNET_SYSERR)
2047  return ret;
2048  if (val == yesno[0])
2049  return GNUNET_YES;
2050  return GNUNET_NO;
2051 }
2052 
2053 
2054 int
2056  const struct GNUNET_CONFIGURATION_Handle *cfg,
2057  const char *section,
2058  const char *option,
2060  void *cb_cls)
2061 {
2062  char *list;
2063  char *pos;
2064  char *end;
2065  char old;
2066  int ret;
2067 
2068  if (GNUNET_OK !=
2069  GNUNET_CONFIGURATION_get_value_string (cfg, section, option, &list))
2070  return 0;
2071  GNUNET_assert (list != NULL);
2072  ret = 0;
2073  pos = list;
2074  while (1)
2075  {
2076  while (pos[0] == ' ')
2077  pos++;
2078  if (strlen (pos) == 0)
2079  break;
2080  end = pos + 1;
2081  while ((end[0] != ' ') && (end[0] != '\0'))
2082  {
2083  if (end[0] == '\\')
2084  {
2085  switch (end[1])
2086  {
2087  case '\\':
2088  case ' ':
2089  memmove (end, &end[1], strlen (&end[1]) + 1);
2090 
2091  case '\0':
2092  /* illegal, but just keep it */
2093  break;
2094 
2095  default:
2096  /* illegal, but just ignore that there was a '/' */
2097  break;
2098  }
2099  }
2100  end++;
2101  }
2102  old = end[0];
2103  end[0] = '\0';
2104  if (strlen (pos) > 0)
2105  {
2106  ret++;
2107  if ((cb != NULL) && (GNUNET_OK != cb (cb_cls, pos)))
2108  {
2109  ret = GNUNET_SYSERR;
2110  break;
2111  }
2112  }
2113  if (old == '\0')
2114  break;
2115  pos = end + 1;
2116  }
2117  GNUNET_free (list);
2118  return ret;
2119 }
2120 
2121 
2128 static char *
2129 escape_name (const char *value)
2130 {
2131  char *escaped;
2132  const char *rpos;
2133  char *wpos;
2134 
2135  escaped = GNUNET_malloc (strlen (value) * 2 + 1);
2136  memset (escaped, 0, strlen (value) * 2 + 1);
2137  rpos = value;
2138  wpos = escaped;
2139  while (rpos[0] != '\0')
2140  {
2141  switch (rpos[0])
2142  {
2143  case '\\':
2144  case ' ':
2145  wpos[0] = '\\';
2146  wpos[1] = rpos[0];
2147  wpos += 2;
2148  break;
2149 
2150  default:
2151  wpos[0] = rpos[0];
2152  wpos++;
2153  }
2154  rpos++;
2155  }
2156  return escaped;
2157 }
2158 
2159 
2167 static enum GNUNET_GenericReturnValue
2168 test_match (void *cls, const char *fn)
2169 {
2170  const char *of = cls;
2171 
2172  return (0 == strcmp (of, fn)) ? GNUNET_SYSERR : GNUNET_OK;
2173 }
2174 
2175 
2179  const char *section,
2180  const char *option,
2181  const char *value)
2182 {
2183  char *escaped;
2184  char *old;
2185  char *nw;
2186 
2187  if (GNUNET_SYSERR ==
2189  section,
2190  option,
2191  &test_match,
2192  (void *) value))
2193  return GNUNET_NO; /* already exists */
2194  if (GNUNET_OK !=
2195  GNUNET_CONFIGURATION_get_value_string (cfg, section, option, &old))
2196  old = GNUNET_strdup ("");
2197  escaped = escape_name (value);
2198  nw = GNUNET_malloc (strlen (old) + strlen (escaped) + 2);
2199  strcpy (nw, old);
2200  if (strlen (old) > 0)
2201  strcat (nw, " ");
2202  strcat (nw, escaped);
2203  GNUNET_CONFIGURATION_set_value_string (cfg, section, option, nw);
2204  GNUNET_free (old);
2205  GNUNET_free (nw);
2206  GNUNET_free (escaped);
2207  return GNUNET_OK;
2208 }
2209 
2210 
2214  const char *section,
2215  const char *option,
2216  const char *value)
2217 {
2218  char *list;
2219  char *pos;
2220  char *end;
2221  char *match;
2222  char old;
2223 
2224  if (GNUNET_OK !=
2225  GNUNET_CONFIGURATION_get_value_string (cfg, section, option, &list))
2226  return GNUNET_NO;
2227  match = escape_name (value);
2228  pos = list;
2229  while (1)
2230  {
2231  while (pos[0] == ' ')
2232  pos++;
2233  if (strlen (pos) == 0)
2234  break;
2235  end = pos + 1;
2236  while ((end[0] != ' ') && (end[0] != '\0'))
2237  {
2238  if (end[0] == '\\')
2239  {
2240  switch (end[1])
2241  {
2242  case '\\':
2243  case ' ':
2244  end++;
2245  break;
2246 
2247  case '\0':
2248  /* illegal, but just keep it */
2249  break;
2250 
2251  default:
2252  /* illegal, but just ignore that there was a '/' */
2253  break;
2254  }
2255  }
2256  end++;
2257  }
2258  old = end[0];
2259  end[0] = '\0';
2260  if (0 == strcmp (pos, match))
2261  {
2262  if (old != '\0')
2263  memmove (pos, &end[1], strlen (&end[1]) + 1);
2264  else
2265  {
2266  if (pos != list)
2267  pos[-1] = '\0';
2268  else
2269  pos[0] = '\0';
2270  }
2271  GNUNET_CONFIGURATION_set_value_string (cfg, section, option, list);
2272  GNUNET_free (list);
2273  GNUNET_free (match);
2274  return GNUNET_OK;
2275  }
2276  if (old == '\0')
2277  break;
2278  end[0] = old;
2279  pos = end + 1;
2280  }
2281  GNUNET_free (list);
2282  GNUNET_free (match);
2283  return GNUNET_NO;
2284 }
2285 
2286 
2289  const char *defaults_d)
2290 {
2291  struct CollectFilesContext files_context = {
2292  .files = NULL,
2293  .files_length = 0,
2294  };
2295  enum GNUNET_GenericReturnValue fun_ret;
2296 
2297  if (GNUNET_SYSERR ==
2299  &files_context))
2300  return GNUNET_SYSERR; /* no configuration at all found */
2301  qsort (files_context.files,
2302  files_context.files_length,
2303  sizeof (char *),
2304  pstrcmp);
2305  for (unsigned int i = 0; i < files_context.files_length; i++)
2306  {
2307  char *ext;
2308  const char *filename = files_context.files[i];
2309 
2310  /* Examine file extension */
2311  ext = strrchr (filename, '.');
2312  if ((NULL == ext) || (0 != strcmp (ext, ".conf")))
2313  {
2314  GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Skipping file `%s'\n", filename);
2315  fun_ret = GNUNET_OK;
2316  goto cleanup;
2317  }
2319  if (fun_ret != GNUNET_OK)
2320  break;
2321  }
2322 cleanup:
2323  if (files_context.files_length > 0)
2324  {
2325  for (size_t i = 0; i < files_context.files_length; i++)
2326  GNUNET_free (files_context.files[i]);
2327  GNUNET_array_grow (files_context.files,
2328  files_context.files_length,
2329  0);
2330  }
2331  return fun_ret;
2332 }
2333 
2334 
2335 char *
2337 {
2338  char *cfg_fn;
2339  const struct GNUNET_OS_ProjectData *pd = GNUNET_OS_project_data_get ();
2340  const char *xdg = getenv ("XDG_CONFIG_HOME");
2341 
2342  if (NULL != xdg)
2343  GNUNET_asprintf (&cfg_fn,
2344  "%s%s%s",
2345  xdg,
2347  pd->config_file);
2348  else
2349  cfg_fn = GNUNET_strdup (pd->user_config_file);
2350 
2351  if (GNUNET_OK == GNUNET_DISK_file_test_read (cfg_fn))
2352  return cfg_fn;
2353  GNUNET_free (cfg_fn);
2354 
2355  /* Fall back to /etc/ for the default configuration.
2356  Should be okay to use forward slashes here. */
2357 
2358  GNUNET_asprintf (&cfg_fn,
2359  "/etc/%s",
2360  pd->config_file);
2361  if (GNUNET_OK == GNUNET_DISK_file_test_read (cfg_fn))
2362  return cfg_fn;
2363  GNUNET_free (cfg_fn);
2364 
2365  GNUNET_asprintf (&cfg_fn,
2366  "/etc/%s/%s",
2367  pd->project_dirname,
2368  pd->config_file);
2369  if (GNUNET_OK == GNUNET_DISK_file_test_read (cfg_fn))
2370  return cfg_fn;
2371 
2372  GNUNET_free (cfg_fn);
2373  return NULL;
2374 }
2375 
2376 
2379 {
2380  const struct GNUNET_OS_ProjectData *pd = GNUNET_OS_project_data_get ();
2382  const char *xdg = getenv ("XDG_CONFIG_HOME");
2383  char *cfgname = NULL;
2385 
2386  /* Makes sure function implicitly looking at the installation directory (for
2387  example GNUNET_CONFIGURATION_load further down) use GNUnet's environment
2388  instead of the caller's. It's done at the start to make sure as many
2389  functions as possible are directed to the proper paths. */
2390  GNUNET_OS_init (dpd);
2391 
2393 
2394  /* First, try user configuration. */
2395  if (NULL != xdg)
2396  GNUNET_asprintf (&cfgname, "%s/%s", xdg, dpd->config_file);
2397  else
2398  cfgname = GNUNET_strdup (dpd->user_config_file);
2399 
2400  /* If user config doesn't exist, try in
2401  /etc/<projdir>/<cfgfile> and /etc/<cfgfile> */
2402  if (GNUNET_OK != GNUNET_DISK_file_test (cfgname))
2403  {
2404  GNUNET_free (cfgname);
2405  GNUNET_asprintf (&cfgname, "/etc/%s", dpd->config_file);
2406  }
2407  if (GNUNET_OK != GNUNET_DISK_file_test (cfgname))
2408  {
2409  GNUNET_free (cfgname);
2410  GNUNET_asprintf (&cfgname,
2411  "/etc/%s/%s",
2412  dpd->project_dirname,
2413  dpd->config_file);
2414  }
2415  if (GNUNET_OK != GNUNET_DISK_file_test (cfgname))
2416  {
2418  "Unable to top-level configuration file.\n");
2419  GNUNET_OS_init (pd);
2421  GNUNET_free (cfgname);
2422  return NULL;
2423  }
2424 
2425  /* We found a configuration file that looks good, try to load it. */
2426 
2428  "Loading top-level configuration from '%s'\n",
2429  cfgname);
2430  if (GNUNET_OK !=
2431  GNUNET_CONFIGURATION_load (cfg, cfgname))
2432  {
2433  GNUNET_OS_init (pd);
2435  GNUNET_free (cfgname);
2436  return NULL;
2437  }
2438  GNUNET_free (cfgname);
2439  GNUNET_OS_init (pd);
2440  return cfg;
2441 }
2442 
2443 
2452 int
2454  const char *filename)
2455 {
2456  char *baseconfig;
2457  const char *base_config_varname;
2458 
2459  if (cfg->load_called)
2460  {
2461  /* FIXME: Make this a GNUNET_assert later */
2462  GNUNET_break (0);
2464  }
2465  cfg->load_called = true;
2466  if (NULL != filename)
2467  {
2470  }
2471 
2472  base_config_varname = GNUNET_OS_project_data_get ()->base_config_varname;
2473 
2474  if ((NULL != base_config_varname)
2475  && (NULL != (baseconfig = getenv (base_config_varname))))
2476  {
2477  baseconfig = GNUNET_strdup (baseconfig);
2478  }
2479  else
2480  {
2481  char *ipath;
2482 
2484  if (NULL == ipath)
2485  {
2486  GNUNET_break (0);
2487  return GNUNET_SYSERR;
2488  }
2489  GNUNET_asprintf (&baseconfig, "%s%s", ipath, "config.d");
2490  GNUNET_free (ipath);
2491  }
2492 
2493  char *dname = GNUNET_STRINGS_filename_expand (baseconfig);
2494  GNUNET_free (baseconfig);
2495 
2496  if ((GNUNET_YES == GNUNET_DISK_directory_test (dname, GNUNET_YES)) &&
2498  {
2500  "Failed to load base configuration from '%s'\n",
2501  filename);
2502  GNUNET_free (dname);
2503  return GNUNET_SYSERR; /* no configuration at all found */
2504  }
2505  GNUNET_free (dname);
2506  if ((NULL != filename) &&
2508  {
2509  /* specified configuration not found */
2511  "Failed to load configuration from file '%s'\n",
2512  filename);
2513  return GNUNET_SYSERR;
2514  }
2515  if (((GNUNET_YES !=
2516  GNUNET_CONFIGURATION_have_value (cfg, "PATHS", "DEFAULTCONFIG"))) &&
2517  (filename != NULL))
2518  GNUNET_CONFIGURATION_set_value_string (cfg, "PATHS", "DEFAULTCONFIG",
2519  filename);
2520  return GNUNET_OK;
2521 }
2522 
2523 
2524 /* 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:34
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:53
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:36
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:37
char * GNUNET_buffer_reap_str(struct GNUNET_Buffer *buf)
Clear the buffer and return the string it contained.
Definition: buffer.c:123
void GNUNET_buffer_write_fstr(struct GNUNET_Buffer *buf, const char *fmt,...) __attribute__((format(printf
Write a 0-terminated formatted string to a buffer, excluding the 0-terminator.
void GNUNET_buffer_write_str(struct GNUNET_Buffer *buf, const char *str)
Write a 0-terminated string to a buffer, excluding the 0-terminator.
Definition: buffer.c:103
enum GNUNET_GenericReturnValue(* GNUNET_FileNameCallback)(void *cls, const char *filename)
Function called with a filename.
#define GNUNET_log(kind,...)
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
GNUNET_GenericReturnValue
Named constants for return values.
Definition: gnunet_common.h:92
@ GNUNET_OK
Definition: gnunet_common.h:95
@ GNUNET_YES
Definition: gnunet_common.h:97
@ GNUNET_NO
Definition: gnunet_common.h:94
@ GNUNET_SYSERR
Definition: gnunet_common.h:93
cryptographic primitives for GNUnet
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.
void GNUNET_CONFIGURATION_iterate_sections(const struct GNUNET_CONFIGURATION_Handle *cfg, GNUNET_CONFIGURATION_Section_Iterator iter, void *iter_cls)
Iterate over all sections in the configuration.
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_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.
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.
void(* GNUNET_CONFIGURATION_Section_Iterator)(void *cls, const char *section)
Function to iterate over section.
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:1235
int GNUNET_DISK_glob(const char *glob_pattern, GNUNET_FileNameCallback callback, void *callback_cls)
Find all files matching a glob pattern.
Definition: disk.c:1007
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:222
enum GNUNET_GenericReturnValue GNUNET_DISK_directory_remove(const char *filename)
Remove all files in a directory (rm -rf).
Definition: disk.c:1085
enum GNUNET_GenericReturnValue GNUNET_DISK_directory_test(const char *fil, int is_readable)
Test if fil is a directory and listable.
Definition: disk.c:404
enum GNUNET_GenericReturnValue GNUNET_DISK_file_close(struct GNUNET_DISK_FileHandle *h)
Close an open file.
Definition: disk.c:1306
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.
#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:495
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:789
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:261
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:237
static unsigned int size
Size of the "table".
Definition: peer.c:67
#define DIR_SEPARATOR_STR
Definition: platform.h:165
#define _(String)
GNU gettext support macro.
Definition: platform.h:177
#define SIZE_MAX
Definition: platform.h:207
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:43
char * hint_filename
Diagnostics information for the filename.
Definition: configuration.c:62
struct ConfigEntry * next
This is a linked list.
Definition: configuration.c:47
char * key
key for this entry
Definition: configuration.c:52
unsigned int hint_lineno
Diagnostics information for the line number.
Definition: configuration.c:67
char * val
current, committed value
Definition: configuration.c:57
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:75
char * name
name of the section
Definition: configuration.c:89
char * hint_inlined_from_filename
For secret sections: Where was this inlined from?
struct ConfigEntry * entries
entries in the section
Definition: configuration.c:84
bool inaccessible
Is the configuration section marked as inaccessible?
Definition: configuration.c:97
struct ConfigSection * next
This is a linked list.
Definition: configuration.c:79
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
Common buffer management functions.
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.