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  /* FIXME: Why are we doing this? Needs some commentary! */
2387  GNUNET_OS_init (dpd);
2388 
2390 
2391  /* First, try user configuration. */
2392  if (NULL != xdg)
2393  GNUNET_asprintf (&cfgname, "%s/%s", xdg, pd->config_file);
2394  else
2395  cfgname = GNUNET_strdup (pd->user_config_file);
2396 
2397  /* If user config doesn't exist, try in
2398  /etc/<projdir>/<cfgfile> and /etc/<cfgfile> */
2399  if (GNUNET_OK != GNUNET_DISK_file_test (cfgname))
2400  {
2401  GNUNET_free (cfgname);
2402  GNUNET_asprintf (&cfgname, "/etc/%s", pd->config_file);
2403  }
2404  if (GNUNET_OK != GNUNET_DISK_file_test (cfgname))
2405  {
2406  GNUNET_free (cfgname);
2407  GNUNET_asprintf (&cfgname,
2408  "/etc/%s/%s",
2409  pd->project_dirname,
2410  pd->config_file);
2411  }
2412  if (GNUNET_OK != GNUNET_DISK_file_test (cfgname))
2413  {
2415  "Unable to top-level configuration file.\n");
2416  GNUNET_OS_init (pd);
2418  GNUNET_free (cfgname);
2419  return NULL;
2420  }
2421 
2422  /* We found a configuration file that looks good, try to load it. */
2423 
2425  "Loading top-level configuration from '%s'\n",
2426  cfgname);
2427  if (GNUNET_OK !=
2428  GNUNET_CONFIGURATION_load (cfg, cfgname))
2429  {
2430  GNUNET_OS_init (pd);
2432  GNUNET_free (cfgname);
2433  return NULL;
2434  }
2435  GNUNET_free (cfgname);
2436  GNUNET_OS_init (pd);
2437  return cfg;
2438 }
2439 
2440 
2449 int
2451  const char *filename)
2452 {
2453  char *baseconfig;
2454  const char *base_config_varname;
2455 
2456  if (cfg->load_called)
2457  {
2458  /* FIXME: Make this a GNUNET_assert later */
2459  GNUNET_break (0);
2461  }
2462  cfg->load_called = true;
2463  if (NULL != filename)
2464  {
2467  }
2468 
2469  base_config_varname = GNUNET_OS_project_data_get ()->base_config_varname;
2470 
2471  if ((NULL != base_config_varname)
2472  && (NULL != (baseconfig = getenv (base_config_varname))))
2473  {
2474  baseconfig = GNUNET_strdup (baseconfig);
2475  }
2476  else
2477  {
2478  char *ipath;
2479 
2481  if (NULL == ipath)
2482  {
2483  GNUNET_break (0);
2484  return GNUNET_SYSERR;
2485  }
2486  GNUNET_asprintf (&baseconfig, "%s%s", ipath, "config.d");
2487  GNUNET_free (ipath);
2488  }
2489 
2490  char *dname = GNUNET_STRINGS_filename_expand (baseconfig);
2491  GNUNET_free (baseconfig);
2492 
2493  if ((GNUNET_YES == GNUNET_DISK_directory_test (dname, GNUNET_YES)) &&
2495  {
2497  "Failed to load base configuration from '%s'\n",
2498  filename);
2499  GNUNET_free (dname);
2500  return GNUNET_SYSERR; /* no configuration at all found */
2501  }
2502  GNUNET_free (dname);
2503  if ((NULL != filename) &&
2505  {
2506  /* specified configuration not found */
2508  "Failed to load configuration from file '%s'\n",
2509  filename);
2510  return GNUNET_SYSERR;
2511  }
2512  if (((GNUNET_YES !=
2513  GNUNET_CONFIGURATION_have_value (cfg, "PATHS", "DEFAULTCONFIG"))) &&
2514  (filename != NULL))
2515  GNUNET_CONFIGURATION_set_value_string (cfg, "PATHS", "DEFAULTCONFIG",
2516  filename);
2517  return GNUNET_OK;
2518 }
2519 
2520 
2521 /* 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 struct GNUNET_OS_Process * p
Helper process we started.
Definition: gnunet-qr.c:59
static int result
Global testing status.
static char buf[2048]
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:482
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:775
int 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:260
int 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:284
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.