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 
33 #define LOG(kind, ...) GNUNET_log_from (kind, "util", __VA_ARGS__)
34 
35 #define LOG_STRERROR_FILE(kind, syscall, filename) \
36  GNUNET_log_from_strerror_file (kind, "util", syscall, filename)
37 
42 {
46  struct ConfigEntry *next;
47 
51  char *key;
52 
56  char *val;
57 
62 
66  unsigned int hint_lineno;
67 };
68 
69 
74 {
79 
84 
88  char *name;
89 
97 
102 
107 
112 };
113 
114 
119 {
124 
129 
136 
141 };
142 
143 
149 {
151 
153 };
154 
155 
156 void
159 {
160  cfg->diagnostics = true;
161 }
162 
163 
166 {
168  char *p;
169 
171  /* make certain values from the project data available
172  as PATHS */
174  if (NULL != p)
175  {
177  "PATHS",
178  "DATADIR",
179  p);
180  GNUNET_free (p);
181  }
183  if (NULL != p)
184  {
186  "PATHS",
187  "LIBDIR",
188  p);
189  GNUNET_free (p);
190  }
192  if (NULL != p)
193  {
195  "PATHS",
196  "BINDIR",
197  p);
198  GNUNET_free (p);
199  }
201  if (NULL != p)
202  {
204  "PATHS",
205  "PREFIX",
206  p);
207  GNUNET_free (p);
208  }
210  if (NULL != p)
211  {
213  "PATHS",
214  "LOCALEDIR",
215  p);
216  GNUNET_free (p);
217  }
219  if (NULL != p)
220  {
222  "PATHS",
223  "ICONDIR",
224  p);
225  GNUNET_free (p);
226  }
228  if (NULL != p)
229  {
231  "PATHS",
232  "DOCDIR",
233  p);
234  GNUNET_free (p);
235  }
237  if (NULL != p)
238  {
240  "PATHS",
241  "LIBEXECDIR",
242  p);
243  GNUNET_free (p);
244  }
245  return cfg;
246 }
247 
248 
249 void
251 {
252  struct ConfigSection *sec;
253 
254  while (NULL != (sec = cfg->sections))
256  GNUNET_free (cfg);
257 }
258 
259 
263  void *cb_cls)
264 {
267 
269  if (GNUNET_OK != GNUNET_CONFIGURATION_load (cfg, filename))
270  {
271  GNUNET_break (0);
273  return GNUNET_SYSERR;
274  }
275  ret = cb (cb_cls, cfg);
277  return ret;
278 }
279 
280 
285 {
290 };
291 
292 
302 static int
303 inline_glob_cb (void *cls,
304  const char *filename)
305 {
306  struct InlineGlobClosure *igc = cls;
307 
309  "Reading globbed config file '%s'\n",
310  filename);
311 
312  if (GNUNET_OK !=
314  filename))
315  {
316  return GNUNET_SYSERR;
317  }
318  return GNUNET_OK;
319 }
320 
321 
329 static struct ConfigSection *
331  const char *section)
332 {
333  struct ConfigSection *pos;
334 
335  pos = cfg->sections;
336  while ((pos != NULL) && (0 != strcasecmp (section, pos->name)))
337  pos = pos->next;
338  return pos;
339 }
340 
341 
349  const char *path_or_glob,
350  bool path_is_glob,
351  const char *restrict_section,
352  const char *source_filename,
353  unsigned int source_lineno)
354 {
355  char *inline_path;
356 
357  /* We support the section restriction only for non-globs */
358  GNUNET_assert (! (path_is_glob && (NULL != restrict_section)));
359 
360  if (NULL == source_filename)
361  {
363  "Refusing to parse inline configurations, "
364  "not allowed without source filename!\n");
365  return GNUNET_SYSERR;
366  }
367  if ('/' == *path_or_glob)
368  inline_path = GNUNET_strdup (path_or_glob);
369  else
370  {
371  /* We compute the canonical, absolute path first,
372  so that relative imports resolve properly with symlinked
373  config files. */
374  char *source_realpath;
375  char *endsep;
376 
377  source_realpath = realpath (source_filename,
378  NULL);
379  if (NULL == source_realpath)
380  {
381  /* Couldn't even resolve path of base dir. */
382  GNUNET_break (0);
383  /* failed to parse included config */
384  return GNUNET_SYSERR;
385  }
386  endsep = strrchr (source_realpath, '/');
387  GNUNET_assert (NULL != endsep);
388  *endsep = '\0';
389  GNUNET_asprintf (&inline_path,
390  "%s/%s",
391  source_realpath,
392  path_or_glob);
393  free (source_realpath);
394  }
395  if (path_is_glob)
396  {
397  int nret;
398  struct InlineGlobClosure igc = {
399  .cfg = cfg,
400  };
401 
403  "processing config glob '%s'\n",
404  inline_path);
405 
406  nret = GNUNET_DISK_glob (inline_path, inline_glob_cb, &igc);
407  if (-1 == nret)
408  {
409  GNUNET_free (inline_path);
410  return GNUNET_SYSERR;
411  }
412  }
413  else if (NULL != restrict_section)
414  {
415  struct GNUNET_CONFIGURATION_Handle *other_cfg;
416  enum GNUNET_GenericReturnValue fret;
417  struct ConfigSection *cs;
418 
419  fret = GNUNET_DISK_file_test_read (inline_path);
420 
421  cs = find_section (cfg, restrict_section);
422 
423  if (NULL == cs)
424  {
425  cs = GNUNET_new (struct ConfigSection);
426  cs->name = GNUNET_strdup (restrict_section);
427  cs->next = cfg->sections;
428  cfg->sections = cs;
429  cs->entries = NULL;
430  }
431  if (cfg->diagnostics)
432  {
433  if (NULL != inline_path)
434  cs->hint_secret_filename = GNUNET_strdup (inline_path);
435  if (source_filename)
436  {
437  cs->hint_inlined_from_filename = GNUNET_strdup (source_filename);
438  cs->hint_inlined_from_line = source_lineno;
439  }
440  }
441 
442  if (GNUNET_OK != fret)
443  {
444  cs->inaccessible = true;
445  GNUNET_free (inline_path);
446  return GNUNET_OK;
447  }
448 
449  other_cfg = GNUNET_CONFIGURATION_create ();
450  if (GNUNET_OK != GNUNET_CONFIGURATION_parse (other_cfg,
451  inline_path))
452  {
453  GNUNET_free (inline_path);
454  GNUNET_CONFIGURATION_destroy (other_cfg);
455  return GNUNET_SYSERR;
456  }
457 
458  cs = find_section (other_cfg, restrict_section);
459  if (NULL == cs)
460  {
462  "inlined configuration '%s' does not contain section '%s'\n",
463  inline_path,
464  restrict_section);
465  GNUNET_free (inline_path);
466  GNUNET_free (other_cfg);
467  return GNUNET_SYSERR;
468  }
469  for (struct ConfigEntry *ce = cs->entries;
470  NULL != ce;
471  ce = ce->next)
473  restrict_section,
474  ce->key,
475  ce->val);
476  GNUNET_CONFIGURATION_destroy (other_cfg);
477  }
478  else if (GNUNET_OK !=
480  inline_path))
481  {
482  GNUNET_free (inline_path);
483  return GNUNET_SYSERR;
484  }
485  GNUNET_free (inline_path);
486  return GNUNET_OK;
487 }
488 
489 
498 static struct ConfigEntry *
500  const char *section,
501  const char *key)
502 {
503  struct ConfigSection *sec;
504  struct ConfigEntry *pos;
505 
506  if (NULL == (sec = find_section (cfg, section)))
507  return NULL;
508  if (sec->inaccessible)
509  {
511  "Section '%s' is marked as inaccessible, because the configuration "
512  " file that contains the section can't be read. Attempts to use "
513  "option '%s' will fail.\n",
514  section,
515  key);
516  return NULL;
517  }
518  pos = sec->entries;
519  while ((pos != NULL) && (0 != strcasecmp (key, pos->key)))
520  pos = pos->next;
521  return pos;
522 }
523 
524 
534 static void
536  const char *section,
537  const char *option,
538  const char *hint_filename,
539  unsigned int hint_line)
540 {
541  struct ConfigEntry *e = find_entry (cfg, section, option);
542  if (! cfg->diagnostics)
543  return;
544  if (! e)
545  return;
546  e->hint_filename = GNUNET_strdup (hint_filename);
547  e->hint_lineno = hint_line;
548 }
549 
550 
553  const char *mem,
554  size_t size,
555  const char *source_filename)
556 {
557  size_t line_size;
558  unsigned int nr;
559  size_t r_bytes;
560  size_t to_read;
562  char *section;
563  char *eq;
564  char *tag;
565  char *value;
566  char *line_orig = NULL;
567 
568  ret = GNUNET_OK;
569  section = NULL;
570  nr = 0;
571  r_bytes = 0;
572  while (r_bytes < size)
573  {
574  char *pos;
575  char *line;
576  bool emptyline;
577 
578  GNUNET_free (line_orig);
579  /* fgets-like behaviour on buffer */
580  to_read = size - r_bytes;
581  pos = memchr (&mem[r_bytes], '\n', to_read);
582  if (NULL == pos)
583  {
584  line_orig = GNUNET_strndup (&mem[r_bytes],
585  line_size = to_read);
586  r_bytes += line_size;
587  }
588  else
589  {
590  line_orig = GNUNET_strndup (&mem[r_bytes],
591  line_size = (pos - &mem[r_bytes]));
592  r_bytes += line_size + 1;
593  }
594  line = line_orig;
595  /* increment line number */
596  nr++;
597  /* tabs and '\r' are whitespace */
598  emptyline = GNUNET_YES;
599  for (size_t i = 0; i < line_size; i++)
600  {
601  if (line[i] == '\t')
602  line[i] = ' ';
603  if (line[i] == '\r')
604  line[i] = ' ';
605  if (' ' != line[i])
606  emptyline = GNUNET_NO;
607  }
608  /* ignore empty lines */
609  if (GNUNET_YES == emptyline)
610  continue;
611 
612  /* remove tailing whitespace */
613  for (size_t i = line_size - 1;
614  (i >= 1) && (isspace ((unsigned char) line[i]));
615  i--)
616  line[i] = '\0';
617 
618  /* remove leading whitespace */
619  for (; line[0] != '\0' && (isspace ((unsigned char) line[0])); line++)
620  ;
621 
622  /* ignore comments */
623  if ( ('#' == line[0]) ||
624  ('%' == line[0]) )
625  continue;
626 
627  /* Handle special directives. */
628  if ('@' == line[0])
629  {
630  char *end = strchr (line + 1, '@');
631  char *directive;
632  enum GNUNET_GenericReturnValue directive_ret;
633 
634  if (NULL == end)
635  {
637  _ ("Bad directive in line %u\n"),
638  nr);
639  ret = GNUNET_SYSERR;
640  break;
641  }
642  *end = '\0';
643  directive = line + 1;
644 
645  if (0 == strcasecmp (directive, "INLINE"))
646  {
647  const char *path = end + 1;
648 
649  /* Skip space before path */
650  for (; isspace (*path); path++)
651  ;
652 
653  directive_ret = handle_inline (cfg,
654  path,
655  false,
656  NULL,
657  source_filename,
658  nr);
659  }
660  else if (0 == strcasecmp (directive, "INLINE-MATCHING"))
661  {
662  const char *path = end + 1;
663 
664  /* Skip space before path */
665  for (; isspace (*path); path++)
666  ;
667 
668  directive_ret = handle_inline (cfg,
669  path,
670  true,
671  NULL,
672  source_filename,
673  nr);
674  }
675  else if (0 == strcasecmp (directive, "INLINE-SECRET"))
676  {
677  char *secname = end + 1;
678  char *secname_end;
679  const char *path;
680 
681  /* Skip space before secname */
682  for (; isspace (*secname); secname++)
683  ;
684 
685  secname_end = strchr (secname, ' ');
686 
687  if (NULL == secname_end)
688  {
690  _ ("Bad inline-secret directive in line %u\n"),
691  nr);
692  ret = GNUNET_SYSERR;
693  break;
694  }
695  *secname_end = '\0';
696  path = secname_end + 1;
697 
698  /* Skip space before path */
699  for (; isspace (*path); path++)
700  ;
701 
702  directive_ret = handle_inline (cfg,
703  path,
704  false,
705  secname,
706  source_filename,
707  nr);
708  }
709  else
710  {
712  _ ("Unknown or malformed directive '%s' in line %u\n"),
713  directive,
714  nr);
715  ret = GNUNET_SYSERR;
716  break;
717  }
718  if (GNUNET_OK != directive_ret)
719  {
721  _ ("Bad directive '%s' in line %u\n"),
722  directive,
723  nr);
724  ret = GNUNET_SYSERR;
725  break;
726  }
727  continue;
728  }
729  if (('[' == line[0]) && (']' == line[line_size - 1]))
730  {
731  /* [value] */
732  line[line_size - 1] = '\0';
733  value = &line[1];
734  GNUNET_free (section);
735  section = GNUNET_strdup (value);
736  continue;
737  }
738  if (NULL != (eq = strchr (line, '=')))
739  {
740  size_t i;
741 
742  /* tag = value */
743  tag = GNUNET_strndup (line, eq - line);
744  /* remove tailing whitespace */
745  for (i = strlen (tag) - 1;
746  (i >= 1) && (isspace ((unsigned char) tag[i]));
747  i--)
748  tag[i] = '\0';
749 
750  /* Strip whitespace */
751  value = eq + 1;
752  while (isspace ((unsigned char) value[0]))
753  value++;
754  for (i = strlen (value) - 1;
755  (i >= 1) && (isspace ((unsigned char) value[i]));
756  i--)
757  value[i] = '\0';
758 
759  /* remove quotes */
760  i = 0;
761  if (('"' == value[0]) && ('"' == value[strlen (value) - 1]))
762  {
763  value[strlen (value) - 1] = '\0';
764  value++;
765  }
766  GNUNET_CONFIGURATION_set_value_string (cfg, section, tag, &value[i]);
767  if (cfg->diagnostics)
768  {
769  set_entry_hint (cfg,
770  section,
771  tag,
772  source_filename ? source_filename : "<input>",
773  nr);
774  }
775  GNUNET_free (tag);
776  continue;
777  }
778  /* parse error */
780  _ ("Syntax error while deserializing in line %u\n"),
781  nr);
782  ret = GNUNET_SYSERR;
783  break;
784  }
785  GNUNET_free (line_orig);
786  GNUNET_free (section);
787  GNUNET_assert ( (GNUNET_OK != ret) ||
788  (r_bytes == size) );
789  return ret;
790 }
791 
792 
795  const char *filename)
796 {
797  uint64_t fs64;
798  size_t fs;
799  char *fn;
800  char *mem;
801  int dirty;
803  ssize_t sret;
804 
805  fn = GNUNET_STRINGS_filename_expand (filename);
806  LOG (GNUNET_ERROR_TYPE_DEBUG, "Asked to parse config file `%s'\n", fn);
807  if (NULL == fn)
808  return GNUNET_SYSERR;
809  dirty = cfg->dirty; /* back up value! */
810  if (GNUNET_SYSERR ==
812  {
814  "Error while determining the file size of `%s'\n",
815  fn);
816  GNUNET_free (fn);
817  return GNUNET_SYSERR;
818  }
819  if (fs64 > SIZE_MAX)
820  {
821  GNUNET_break (0); /* File size is more than the heap size */
822  GNUNET_free (fn);
823  return GNUNET_SYSERR;
824  }
825  fs = fs64;
826  mem = GNUNET_malloc (fs);
827  sret = GNUNET_DISK_fn_read (fn, mem, fs);
828  if ((sret < 0) || (fs != (size_t) sret))
829  {
830  LOG (GNUNET_ERROR_TYPE_WARNING, _ ("Error while reading file `%s'\n"), fn);
831  GNUNET_free (fn);
832  GNUNET_free (mem);
833  return GNUNET_SYSERR;
834  }
835  LOG (GNUNET_ERROR_TYPE_DEBUG, "Deserializing contents of file `%s'\n", fn);
837  mem,
838  fs,
839  fn);
840  if (GNUNET_OK != ret)
841  {
843  _ ("Failed to parse configuration file `%s'\n"),
844  fn);
845  }
846  GNUNET_free (fn);
847  GNUNET_free (mem);
848  /* restore dirty flag - anything we set in the meantime
849  * came from disk */
850  cfg->dirty = dirty;
851  return ret;
852 }
853 
854 
857 {
858  return cfg->dirty;
859 }
860 
861 
869 static bool
870 do_skip (const char *sec,
871  const char *key)
872 {
873  if (0 != strcasecmp ("PATHS",
874  sec))
875  return false;
876  return ( (0 == strcasecmp ("DATADIR",
877  key)) ||
878  (0 == strcasecmp ("LIBDIR",
879  key)) ||
880  (0 == strcasecmp ("BINDIR",
881  key)) ||
882  (0 == strcasecmp ("PREFIX",
883  key)) ||
884  (0 == strcasecmp ("LOCALEDIR",
885  key)) ||
886  (0 == strcasecmp ("ICONDIR",
887  key)) ||
888  (0 == strcasecmp ("DOCDIR",
889  key)) ||
890  (0 == strcasecmp ("DEFAULTCONFIG",
891  key)) ||
892  (0 == strcasecmp ("LIBEXECDIR",
893  key)) );
894 }
895 
896 
897 char *
899  size_t *size)
900 {
901  char *mem;
902  char *cbuf;
903  char *val;
904  char *pos;
905  size_t m_size;
906  size_t c_size;
907 
908  /* Pass1 : calculate the buffer size required */
909  m_size = 0;
910  for (struct ConfigSection *sec = cfg->sections;
911  NULL != sec;
912  sec = sec->next)
913  {
914  if (sec->inaccessible)
915  continue;
916  /* For each section we need to add 3 characters: {'[',']','\n'} */
917  m_size += strlen (sec->name) + 3;
918  for (struct ConfigEntry *ent = sec->entries;
919  NULL != ent;
920  ent = ent->next)
921  {
922  if (do_skip (sec->name,
923  ent->key))
924  continue;
925  if (NULL != ent->val)
926  {
927  /* if val has any '\n' then they occupy +1 character as '\n'->'\\','n' */
928  pos = ent->val;
929  while (NULL != (pos = strstr (pos, "\n")))
930  {
931  m_size++;
932  pos++;
933  }
934  /* For each key = value pair we need to add 4 characters (2
935  spaces and 1 equal-to character and 1 new line) */
936  m_size += strlen (ent->key) + strlen (ent->val) + 4;
937  }
938  }
939  /* A new line after section end */
940  m_size++;
941  }
942 
943  /* Pass2: Allocate memory and write the configuration to it */
944  mem = GNUNET_malloc (m_size);
945  c_size = 0;
946  *size = c_size;
947  for (struct ConfigSection *sec = cfg->sections;
948  NULL != sec;
949  sec = sec->next)
950  {
951  int len;
952 
953  len = GNUNET_asprintf (&cbuf,
954  "[%s]\n",
955  sec->name);
956  GNUNET_assert (0 < len);
957  GNUNET_memcpy (mem + c_size,
958  cbuf,
959  len);
960  c_size += len;
961  GNUNET_free (cbuf);
962  for (struct ConfigEntry *ent = sec->entries;
963  NULL != ent;
964  ent = ent->next)
965  {
966  if (do_skip (sec->name,
967  ent->key))
968  continue;
969  if (NULL != ent->val)
970  {
971  val = GNUNET_malloc (strlen (ent->val) * 2 + 1);
972  strcpy (val, ent->val);
973  while (NULL != (pos = strstr (val, "\n")))
974  {
975  memmove (&pos[2], &pos[1], strlen (&pos[1]));
976  pos[0] = '\\';
977  pos[1] = 'n';
978  }
979  len = GNUNET_asprintf (&cbuf, "%s = %s\n", ent->key, val);
980  GNUNET_free (val);
981  GNUNET_memcpy (mem + c_size, cbuf, len);
982  c_size += len;
983  GNUNET_free (cbuf);
984  }
985  }
986  GNUNET_memcpy (mem + c_size, "\n", 1);
987  c_size++;
988  }
989  GNUNET_assert (c_size == m_size);
990  *size = c_size;
991  return mem;
992 }
993 
994 char *
997 {
998  struct GNUNET_Buffer buf = { 0 };
999 
1000  for (struct ConfigSection *sec = cfg->sections;
1001  NULL != sec;
1002  sec = sec->next)
1003  {
1004  if (sec->hint_secret_filename)
1006  "# secret section from %s\n",
1007  sec->hint_secret_filename);
1008  if (sec->hint_inlined_from_filename)
1009  {
1011  "# inlined from %s:%u\n",
1012  sec->hint_inlined_from_filename,
1013  sec->hint_inlined_from_line);
1014  }
1016  "[%s]\n",
1017  sec->name);
1018  if (sec->inaccessible)
1019  {
1021  "# <section contents inaccessible>\n\n");
1022  continue;
1023  }
1024  for (struct ConfigEntry *ent = sec->entries;
1025  NULL != ent;
1026  ent = ent->next)
1027  {
1028  if (do_skip (sec->name,
1029  ent->key))
1030  continue;
1031  if (NULL != ent->val)
1032  {
1033  char *pos;
1034  char *val = GNUNET_malloc (strlen (ent->val) * 2 + 1);
1035  strcpy (val, ent->val);
1036  while (NULL != (pos = strstr (val, "\n")))
1037  {
1038  memmove (&pos[2], &pos[1], strlen (&pos[1]));
1039  pos[0] = '\\';
1040  pos[1] = 'n';
1041  }
1042  if (NULL != ent->hint_filename)
1043  {
1045  "# %s:%u\n",
1046  ent->hint_filename,
1047  ent->hint_lineno);
1048  }
1050  "%s = %s\n",
1051  ent->key,
1052  val);
1053  GNUNET_free (val);
1054  }
1055  GNUNET_buffer_write_str (&buf, "\n");
1056  }
1057  GNUNET_buffer_write_str (&buf, "\n");
1058  }
1059  return GNUNET_buffer_reap_str (&buf);
1060 }
1061 
1064  const char *filename)
1065 {
1066  char *fn;
1067  char *cfg_buf;
1068  size_t size;
1069 
1070  fn = GNUNET_STRINGS_filename_expand (filename);
1071  if (fn == NULL)
1072  return GNUNET_SYSERR;
1074  {
1075  GNUNET_free (fn);
1076  return GNUNET_SYSERR;
1077  }
1078  cfg_buf = GNUNET_CONFIGURATION_serialize (cfg,
1079  &size);
1080  {
1081  struct GNUNET_DISK_FileHandle *h;
1082 
1083  h = GNUNET_DISK_file_open (fn,
1091  if (NULL == h)
1092  {
1093  GNUNET_free (fn);
1094  GNUNET_free (cfg_buf);
1095  return GNUNET_SYSERR;
1096  }
1097  if (((ssize_t) size) !=
1099  cfg_buf,
1100  size))
1101  {
1103  "write",
1104  fn);
1106  (void) GNUNET_DISK_directory_remove (fn);
1107  GNUNET_free (fn);
1108  GNUNET_free (cfg_buf);
1109  cfg->dirty = GNUNET_SYSERR; /* last write failed */
1110  return GNUNET_SYSERR;
1111  }
1114  }
1115  GNUNET_free (fn);
1116  GNUNET_free (cfg_buf);
1117  cfg->dirty = GNUNET_NO; /* last write succeeded */
1118  return GNUNET_OK;
1119 }
1120 
1121 
1122 void
1125  void *iter_cls)
1126 {
1127  for (struct ConfigSection *spos = cfg->sections;
1128  NULL != spos;
1129  spos = spos->next)
1130  for (struct ConfigEntry *epos = spos->entries;
1131  NULL != epos;
1132  epos = epos->next)
1133  if (NULL != epos->val)
1134  iter (iter_cls,
1135  spos->name,
1136  epos->key,
1137  epos->val);
1138 }
1139 
1140 
1141 void
1143  const struct GNUNET_CONFIGURATION_Handle *cfg,
1144  const char *section,
1146  void *iter_cls)
1147 {
1148  struct ConfigSection *spos;
1149  struct ConfigEntry *epos;
1150 
1151  spos = cfg->sections;
1152  while ((spos != NULL) && (0 != strcasecmp (spos->name, section)))
1153  spos = spos->next;
1154  if (NULL == spos)
1155  return;
1156  if (spos->inaccessible)
1157  {
1159  "Section '%s' is marked as inaccessible, because the configuration "
1160  " file that contains the section can't be read.\n",
1161  section);
1162  return;
1163  }
1164  for (epos = spos->entries; NULL != epos; epos = epos->next)
1165  if (NULL != epos->val)
1166  iter (iter_cls, spos->name, epos->key, epos->val);
1167 }
1168 
1169 
1170 void
1172  const struct GNUNET_CONFIGURATION_Handle *cfg,
1174  void *iter_cls)
1175 {
1176  struct ConfigSection *spos;
1177  struct ConfigSection *next;
1178 
1179  next = cfg->sections;
1180  while (next != NULL)
1181  {
1182  spos = next;
1183  next = spos->next;
1184  iter (iter_cls, spos->name);
1185  }
1186 }
1187 
1188 
1189 void
1191  const char *section)
1192 {
1193  struct ConfigSection *spos;
1194  struct ConfigSection *prev;
1195  struct ConfigEntry *ent;
1196 
1197  prev = NULL;
1198  spos = cfg->sections;
1199  while (NULL != spos)
1200  {
1201  if (0 == strcasecmp (section, spos->name))
1202  {
1203  if (NULL == prev)
1204  cfg->sections = spos->next;
1205  else
1206  prev->next = spos->next;
1207  while (NULL != (ent = spos->entries))
1208  {
1209  spos->entries = ent->next;
1210  GNUNET_free (ent->key);
1211  GNUNET_free (ent->val);
1212  GNUNET_free (ent->hint_filename);
1213  GNUNET_free (ent);
1214  cfg->dirty = GNUNET_YES;
1215  }
1216  GNUNET_free (spos->name);
1219  GNUNET_free (spos);
1220  return;
1221  }
1222  prev = spos;
1223  spos = spos->next;
1224  }
1225 }
1226 
1227 
1237 static void
1238 copy_entry (void *cls,
1239  const char *section,
1240  const char *option,
1241  const char *value)
1242 {
1243  struct GNUNET_CONFIGURATION_Handle *dst = cls;
1244 
1245  GNUNET_CONFIGURATION_set_value_string (dst, section, option, value);
1246 }
1247 
1248 
1251 {
1253 
1254  ret = GNUNET_CONFIGURATION_create ();
1256  return ret;
1257 }
1258 
1259 
1270 static void
1271 compare_entries (void *cls,
1272  const char *section,
1273  const char *option,
1274  const char *value)
1275 {
1276  struct DiffHandle *dh = cls;
1277  struct ConfigEntry *entNew;
1278 
1279  entNew = find_entry (dh->cfg_default, section, option);
1280  if ((NULL != entNew) && (NULL != entNew->val) &&
1281  (0 == strcmp (entNew->val, value)))
1282  return;
1283  GNUNET_CONFIGURATION_set_value_string (dh->cfgDiff, section, option, value);
1284 }
1285 
1286 
1289  const struct GNUNET_CONFIGURATION_Handle *cfg_default,
1290  const struct GNUNET_CONFIGURATION_Handle *cfg_new)
1291 {
1292  struct DiffHandle diffHandle;
1293 
1294  diffHandle.cfgDiff = GNUNET_CONFIGURATION_create ();
1295  diffHandle.cfg_default = cfg_default;
1296  GNUNET_CONFIGURATION_iterate (cfg_new, &compare_entries, &diffHandle);
1297  return diffHandle.cfgDiff;
1298 }
1299 
1300 
1304  const struct GNUNET_CONFIGURATION_Handle *cfg_new,
1305  const char *filename)
1306 {
1307  int ret;
1308  struct GNUNET_CONFIGURATION_Handle *diff;
1309 
1310  diff = GNUNET_CONFIGURATION_get_diff (cfg_default, cfg_new);
1311  ret = GNUNET_CONFIGURATION_write (diff, filename);
1313  return ret;
1314 }
1315 
1316 
1317 void
1319  const char *section,
1320  const char *option,
1321  const char *value)
1322 {
1323  struct ConfigSection *sec;
1324  struct ConfigEntry *e;
1325  char *nv;
1326 
1327  e = find_entry (cfg, section, option);
1328  if (NULL != e)
1329  {
1330  if (NULL == value)
1331  {
1332  GNUNET_free (e->val);
1333  e->val = NULL;
1334  }
1335  else
1336  {
1337  nv = GNUNET_strdup (value);
1338  GNUNET_free (e->val);
1339  e->val = nv;
1340  }
1341  return;
1342  }
1343  sec = find_section (cfg, section);
1344  if (sec == NULL)
1345  {
1346  sec = GNUNET_new (struct ConfigSection);
1347  sec->name = GNUNET_strdup (section);
1348  sec->next = cfg->sections;
1349  cfg->sections = sec;
1350  }
1351  e = GNUNET_new (struct ConfigEntry);
1352  e->key = GNUNET_strdup (option);
1353  e->val = GNUNET_strdup (value);
1354  e->next = sec->entries;
1355  sec->entries = e;
1356 }
1357 
1358 
1359 void
1361  const char *section,
1362  const char *option,
1363  unsigned long long number)
1364 {
1365  char s[64];
1366 
1367  GNUNET_snprintf (s, 64, "%llu", number);
1368  GNUNET_CONFIGURATION_set_value_string (cfg, section, option, s);
1369 }
1370 
1371 
1374  const struct GNUNET_CONFIGURATION_Handle *cfg,
1375  const char *section,
1376  const char *option,
1377  unsigned long long *number)
1378 {
1379  struct ConfigEntry *e;
1380  char dummy[2];
1381 
1382  if (NULL == (e = find_entry (cfg, section, option)))
1383  return GNUNET_SYSERR;
1384  if (NULL == e->val)
1385  return GNUNET_SYSERR;
1386  if (1 != sscanf (e->val, "%llu%1s", number, dummy))
1387  return GNUNET_SYSERR;
1388  return GNUNET_OK;
1389 }
1390 
1391 
1394  const struct GNUNET_CONFIGURATION_Handle *cfg,
1395  const char *section,
1396  const char *option,
1397  float *number)
1398 {
1399  struct ConfigEntry *e;
1400  char dummy[2];
1401 
1402  if (NULL == (e = find_entry (cfg, section, option)))
1403  return GNUNET_SYSERR;
1404  if (NULL == e->val)
1405  return GNUNET_SYSERR;
1406  if (1 != sscanf (e->val, "%f%1s", number, dummy))
1407  return GNUNET_SYSERR;
1408  return GNUNET_OK;
1409 }
1410 
1411 
1414  const struct GNUNET_CONFIGURATION_Handle *cfg,
1415  const char *section,
1416  const char *option,
1417  struct GNUNET_TIME_Relative *time)
1418 {
1419  struct ConfigEntry *e;
1420  int ret;
1421 
1422  if (NULL == (e = find_entry (cfg, section, option)))
1423  return GNUNET_SYSERR;
1424  if (NULL == e->val)
1425  return GNUNET_SYSERR;
1426  ret = GNUNET_STRINGS_fancy_time_to_relative (e->val, time);
1427  if (GNUNET_OK != ret)
1429  section,
1430  option,
1431  _ ("Not a valid relative time specification"));
1432  return ret;
1433 }
1434 
1435 
1438  const struct GNUNET_CONFIGURATION_Handle *cfg,
1439  const char *section,
1440  const char *option,
1441  unsigned long long *size)
1442 {
1443  struct ConfigEntry *e;
1444 
1445  if (NULL == (e = find_entry (cfg, section, option)))
1446  return GNUNET_SYSERR;
1447  if (NULL == e->val)
1448  return GNUNET_SYSERR;
1449  return GNUNET_STRINGS_fancy_size_to_bytes (e->val, size);
1450 }
1451 
1452 
1465  const struct GNUNET_CONFIGURATION_Handle *cfg,
1466  const char *section,
1467  const char *option,
1468  char **value)
1469 {
1470  struct ConfigEntry *e;
1471 
1472  if ((NULL == (e = find_entry (cfg, section, option))) || (NULL == e->val))
1473  {
1474  *value = NULL;
1475  return GNUNET_SYSERR;
1476  }
1477  *value = GNUNET_strdup (e->val);
1478  return GNUNET_OK;
1479 }
1480 
1481 
1484  const struct GNUNET_CONFIGURATION_Handle *cfg,
1485  const char *section,
1486  const char *option,
1487  const char *const *choices,
1488  const char **value)
1489 {
1490  struct ConfigEntry *e;
1491  unsigned int i;
1492 
1493  if (NULL == (e = find_entry (cfg, section, option)))
1494  return GNUNET_SYSERR;
1495  for (i = 0; NULL != choices[i]; i++)
1496  if (0 == strcasecmp (choices[i], e->val))
1497  break;
1498  if (NULL == choices[i])
1499  {
1501  _ ("Configuration value '%s' for '%s'"
1502  " in section '%s' is not in set of legal choices\n"),
1503  e->val,
1504  option,
1505  section);
1506  return GNUNET_SYSERR;
1507  }
1508  *value = choices[i];
1509  return GNUNET_OK;
1510 }
1511 
1512 
1515  const char *section,
1516  const char *option,
1517  void *buf,
1518  size_t buf_size)
1519 {
1520  char *enc;
1521  int res;
1522  size_t data_size;
1523 
1524  if (GNUNET_OK !=
1525  (res =
1526  GNUNET_CONFIGURATION_get_value_string (cfg, section, option, &enc)))
1527  return res;
1528  data_size = (strlen (enc) * 5) / 8;
1529  if (data_size != buf_size)
1530  {
1531  GNUNET_free (enc);
1532  return GNUNET_SYSERR;
1533  }
1534  if (GNUNET_OK !=
1535  GNUNET_STRINGS_string_to_data (enc, strlen (enc), buf, buf_size))
1536  {
1537  GNUNET_free (enc);
1538  return GNUNET_SYSERR;
1539  }
1540  GNUNET_free (enc);
1541  return GNUNET_OK;
1542 }
1543 
1544 
1547  const char *section,
1548  const char *option)
1549 {
1550  struct ConfigEntry *e;
1551 
1552  if ((NULL == (e = find_entry (cfg, section, option))) || (NULL == e->val))
1553  return GNUNET_NO;
1554  return GNUNET_YES;
1555 }
1556 
1557 
1573 static char *
1575  char *orig,
1576  unsigned int depth)
1577 {
1578  char *prefix;
1579  char *result;
1580  char *start;
1581  const char *post;
1582  const char *env;
1583  char *def;
1584  char *end;
1585  unsigned int lopen;
1586  char erased_char;
1587  char *erased_pos;
1588  size_t len;
1589 
1590  if (NULL == orig)
1591  return NULL;
1592  if (depth > 128)
1593  {
1595  _ (
1596  "Recursive expansion suspected, aborting $-expansion for term `%s'\n"),
1597  orig);
1598  return orig;
1599  }
1600  LOG (GNUNET_ERROR_TYPE_DEBUG, "Asked to $-expand %s\n", orig);
1601  if ('$' != orig[0])
1602  {
1603  LOG (GNUNET_ERROR_TYPE_DEBUG, "Doesn't start with $ - not expanding\n");
1604  return orig;
1605  }
1606  erased_char = 0;
1607  erased_pos = NULL;
1608  if ('{' == orig[1])
1609  {
1610  start = &orig[2];
1611  lopen = 1;
1612  end = &orig[1];
1613  while (lopen > 0)
1614  {
1615  end++;
1616  switch (*end)
1617  {
1618  case '}':
1619  lopen--;
1620  break;
1621 
1622  case '{':
1623  lopen++;
1624  break;
1625 
1626  case '\0':
1628  _ ("Missing closing `%s' in option `%s'\n"),
1629  "}",
1630  orig);
1631  return orig;
1632 
1633  default:
1634  break;
1635  }
1636  }
1637  erased_char = *end;
1638  erased_pos = end;
1639  *end = '\0';
1640  post = end + 1;
1641  def = strchr (orig, ':');
1642  if (NULL != def)
1643  {
1644  *def = '\0';
1645  def++;
1646  if (('-' == *def) || ('=' == *def))
1647  def++;
1648  def = GNUNET_strdup (def);
1649  }
1650  }
1651  else
1652  {
1653  int i;
1654 
1655  start = &orig[1];
1656  def = NULL;
1657  i = 0;
1658  while ((orig[i] != '/') && (orig[i] != '\\') && (orig[i] != '\0') &&
1659  (orig[i] != ' '))
1660  i++;
1661  if (orig[i] == '\0')
1662  {
1663  post = "";
1664  }
1665  else
1666  {
1667  erased_char = orig[i];
1668  erased_pos = &orig[i];
1669  orig[i] = '\0';
1670  post = &orig[i + 1];
1671  }
1672  }
1674  "Split into `%s' and `%s' with default %s\n",
1675  start,
1676  post,
1677  def);
1678  if (GNUNET_OK !=
1679  GNUNET_CONFIGURATION_get_value_string (cfg, "PATHS", start, &prefix))
1680  {
1681  if (NULL == (env = getenv (start)))
1682  {
1683  /* try default */
1684  def = expand_dollar (cfg, def, depth + 1);
1685  env = def;
1686  }
1687  if (NULL == env)
1688  {
1689  start = GNUNET_strdup (start);
1690  if (erased_pos)
1691  *erased_pos = erased_char;
1693  _ (
1694  "Failed to expand `%s' in `%s' as it is neither found in [PATHS] nor defined as an environmental variable\n"),
1695  start,
1696  orig);
1697  GNUNET_free (start);
1698  return orig;
1699  }
1700  prefix = GNUNET_strdup (env);
1701  }
1702  prefix = GNUNET_CONFIGURATION_expand_dollar (cfg, prefix);
1703  if ((erased_pos) && ('}' != erased_char))
1704  {
1705  len = strlen (prefix) + 1;
1706  prefix = GNUNET_realloc (prefix, len + 1);
1707  prefix[len - 1] = erased_char;
1708  prefix[len] = '\0';
1709  }
1710  result = GNUNET_malloc (strlen (prefix) + strlen (post) + 1);
1711  strcpy (result, prefix);
1712  strcat (result, post);
1713  GNUNET_free (def);
1714  GNUNET_free (prefix);
1715  GNUNET_free (orig);
1716  return result;
1717 }
1718 
1719 
1720 char *
1722  const struct GNUNET_CONFIGURATION_Handle *cfg,
1723  char *orig)
1724 {
1725  char *dup;
1726  size_t i;
1727  size_t len;
1728 
1729  for (i = 0; '\0' != orig[i]; i++)
1730  {
1731  if ('$' != orig[i])
1732  continue;
1733  dup = GNUNET_strdup (orig + i);
1734  dup = expand_dollar (cfg, dup, 0);
1735  GNUNET_assert (NULL != dup); /* make compiler happy */
1736  len = strlen (dup) + 1;
1737  orig = GNUNET_realloc (orig, i + len);
1738  GNUNET_memcpy (orig + i, dup, len);
1739  GNUNET_free (dup);
1740  }
1741  return orig;
1742 }
1743 
1744 
1747  const struct GNUNET_CONFIGURATION_Handle *cfg,
1748  const char *section,
1749  const char *option,
1750  char **value)
1751 {
1752  char *tmp;
1753 
1754  if (GNUNET_OK !=
1755  GNUNET_CONFIGURATION_get_value_string (cfg, section, option, &tmp))
1756  {
1757  LOG (GNUNET_ERROR_TYPE_DEBUG, "Failed to retrieve filename\n");
1758  *value = NULL;
1759  return GNUNET_SYSERR;
1760  }
1761  tmp = GNUNET_CONFIGURATION_expand_dollar (cfg, tmp);
1762  *value = GNUNET_STRINGS_filename_expand (tmp);
1763  GNUNET_free (tmp);
1764  if (*value == NULL)
1765  return GNUNET_SYSERR;
1766  return GNUNET_OK;
1767 }
1768 
1769 
1772  const struct GNUNET_CONFIGURATION_Handle *cfg,
1773  const char *section,
1774  const char *option)
1775 {
1776  static const char *yesno[] = { "YES", "NO", NULL };
1777  const char *val;
1778  int ret;
1779 
1780  ret =
1781  GNUNET_CONFIGURATION_get_value_choice (cfg, section, option, yesno, &val);
1782  if (ret == GNUNET_SYSERR)
1783  return ret;
1784  if (val == yesno[0])
1785  return GNUNET_YES;
1786  return GNUNET_NO;
1787 }
1788 
1789 
1790 int
1792  const struct GNUNET_CONFIGURATION_Handle *cfg,
1793  const char *section,
1794  const char *option,
1796  void *cb_cls)
1797 {
1798  char *list;
1799  char *pos;
1800  char *end;
1801  char old;
1802  int ret;
1803 
1804  if (GNUNET_OK !=
1805  GNUNET_CONFIGURATION_get_value_string (cfg, section, option, &list))
1806  return 0;
1807  GNUNET_assert (list != NULL);
1808  ret = 0;
1809  pos = list;
1810  while (1)
1811  {
1812  while (pos[0] == ' ')
1813  pos++;
1814  if (strlen (pos) == 0)
1815  break;
1816  end = pos + 1;
1817  while ((end[0] != ' ') && (end[0] != '\0'))
1818  {
1819  if (end[0] == '\\')
1820  {
1821  switch (end[1])
1822  {
1823  case '\\':
1824  case ' ':
1825  memmove (end, &end[1], strlen (&end[1]) + 1);
1826 
1827  case '\0':
1828  /* illegal, but just keep it */
1829  break;
1830 
1831  default:
1832  /* illegal, but just ignore that there was a '/' */
1833  break;
1834  }
1835  }
1836  end++;
1837  }
1838  old = end[0];
1839  end[0] = '\0';
1840  if (strlen (pos) > 0)
1841  {
1842  ret++;
1843  if ((cb != NULL) && (GNUNET_OK != cb (cb_cls, pos)))
1844  {
1845  ret = GNUNET_SYSERR;
1846  break;
1847  }
1848  }
1849  if (old == '\0')
1850  break;
1851  pos = end + 1;
1852  }
1853  GNUNET_free (list);
1854  return ret;
1855 }
1856 
1857 
1864 static char *
1865 escape_name (const char *value)
1866 {
1867  char *escaped;
1868  const char *rpos;
1869  char *wpos;
1870 
1871  escaped = GNUNET_malloc (strlen (value) * 2 + 1);
1872  memset (escaped, 0, strlen (value) * 2 + 1);
1873  rpos = value;
1874  wpos = escaped;
1875  while (rpos[0] != '\0')
1876  {
1877  switch (rpos[0])
1878  {
1879  case '\\':
1880  case ' ':
1881  wpos[0] = '\\';
1882  wpos[1] = rpos[0];
1883  wpos += 2;
1884  break;
1885 
1886  default:
1887  wpos[0] = rpos[0];
1888  wpos++;
1889  }
1890  rpos++;
1891  }
1892  return escaped;
1893 }
1894 
1895 
1903 static enum GNUNET_GenericReturnValue
1904 test_match (void *cls, const char *fn)
1905 {
1906  const char *of = cls;
1907 
1908  return (0 == strcmp (of, fn)) ? GNUNET_SYSERR : GNUNET_OK;
1909 }
1910 
1911 
1915  const char *section,
1916  const char *option,
1917  const char *value)
1918 {
1919  char *escaped;
1920  char *old;
1921  char *nw;
1922 
1923  if (GNUNET_SYSERR ==
1925  section,
1926  option,
1927  &test_match,
1928  (void *) value))
1929  return GNUNET_NO; /* already exists */
1930  if (GNUNET_OK !=
1931  GNUNET_CONFIGURATION_get_value_string (cfg, section, option, &old))
1932  old = GNUNET_strdup ("");
1933  escaped = escape_name (value);
1934  nw = GNUNET_malloc (strlen (old) + strlen (escaped) + 2);
1935  strcpy (nw, old);
1936  if (strlen (old) > 0)
1937  strcat (nw, " ");
1938  strcat (nw, escaped);
1939  GNUNET_CONFIGURATION_set_value_string (cfg, section, option, nw);
1940  GNUNET_free (old);
1941  GNUNET_free (nw);
1942  GNUNET_free (escaped);
1943  return GNUNET_OK;
1944 }
1945 
1946 
1950  const char *section,
1951  const char *option,
1952  const char *value)
1953 {
1954  char *list;
1955  char *pos;
1956  char *end;
1957  char *match;
1958  char old;
1959 
1960  if (GNUNET_OK !=
1961  GNUNET_CONFIGURATION_get_value_string (cfg, section, option, &list))
1962  return GNUNET_NO;
1963  match = escape_name (value);
1964  pos = list;
1965  while (1)
1966  {
1967  while (pos[0] == ' ')
1968  pos++;
1969  if (strlen (pos) == 0)
1970  break;
1971  end = pos + 1;
1972  while ((end[0] != ' ') && (end[0] != '\0'))
1973  {
1974  if (end[0] == '\\')
1975  {
1976  switch (end[1])
1977  {
1978  case '\\':
1979  case ' ':
1980  end++;
1981  break;
1982 
1983  case '\0':
1984  /* illegal, but just keep it */
1985  break;
1986 
1987  default:
1988  /* illegal, but just ignore that there was a '/' */
1989  break;
1990  }
1991  }
1992  end++;
1993  }
1994  old = end[0];
1995  end[0] = '\0';
1996  if (0 == strcmp (pos, match))
1997  {
1998  if (old != '\0')
1999  memmove (pos, &end[1], strlen (&end[1]) + 1);
2000  else
2001  {
2002  if (pos != list)
2003  pos[-1] = '\0';
2004  else
2005  pos[0] = '\0';
2006  }
2007  GNUNET_CONFIGURATION_set_value_string (cfg, section, option, list);
2008  GNUNET_free (list);
2009  GNUNET_free (match);
2010  return GNUNET_OK;
2011  }
2012  if (old == '\0')
2013  break;
2014  end[0] = old;
2015  pos = end + 1;
2016  }
2017  GNUNET_free (list);
2018  GNUNET_free (match);
2019  return GNUNET_NO;
2020 }
2021 
2022 
2032 static enum GNUNET_GenericReturnValue
2033 parse_configuration_file (void *cls, const char *filename)
2034 {
2035  struct GNUNET_CONFIGURATION_Handle *cfg = cls;
2036  char *ext;
2037 
2038  /* Examine file extension */
2039  ext = strrchr (filename, '.');
2040  if ((NULL == ext) || (0 != strcmp (ext, ".conf")))
2041  {
2042  GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Skipping file `%s'\n", filename);
2043  return GNUNET_OK;
2044  }
2045 
2046  return GNUNET_CONFIGURATION_parse (cfg, filename);
2047 }
2048 
2049 
2052  const char *defaults_d)
2053 {
2054  if (GNUNET_SYSERR ==
2056  return GNUNET_SYSERR; /* no configuration at all found */
2057  return GNUNET_OK;
2058 }
2059 
2060 
2063 {
2064  const struct GNUNET_OS_ProjectData *pd = GNUNET_OS_project_data_get ();
2066  const char *xdg = getenv ("XDG_CONFIG_HOME");
2067  char *cfgname = NULL;
2069 
2070  /* FIXME: Why are we doing this? Needs some commentary! */
2071  GNUNET_OS_init (dpd);
2072 
2073  cfg = GNUNET_CONFIGURATION_create ();
2074 
2075  /* First, try user configuration. */
2076  if (NULL != xdg)
2077  GNUNET_asprintf (&cfgname, "%s/%s", xdg, pd->config_file);
2078  else
2079  cfgname = GNUNET_strdup (pd->user_config_file);
2080 
2081  /* If user config doesn't exist, try in
2082  /etc/<projdir>/<cfgfile> and /etc/<cfgfile> */
2083  if (GNUNET_OK != GNUNET_DISK_file_test (cfgname))
2084  {
2085  GNUNET_free (cfgname);
2086  GNUNET_asprintf (&cfgname, "/etc/%s", pd->config_file);
2087  }
2088  if (GNUNET_OK != GNUNET_DISK_file_test (cfgname))
2089  {
2090  GNUNET_free (cfgname);
2091  GNUNET_asprintf (&cfgname, "/etc/%s/%s", pd->project_dirname,
2092  pd->config_file);
2093  }
2094  if (GNUNET_OK != GNUNET_DISK_file_test (cfgname))
2095  {
2097  "Unable to top-level configuration file.\n");
2098  GNUNET_OS_init (pd);
2100  GNUNET_free (cfgname);
2101  return NULL;
2102  }
2103 
2104  /* We found a configuration file that looks good, try to load it. */
2105 
2107  "Loading top-level configuration from '%s'\n",
2108  cfgname);
2109  if (GNUNET_OK !=
2110  GNUNET_CONFIGURATION_load (cfg, cfgname))
2111  {
2112  GNUNET_OS_init (pd);
2114  GNUNET_free (cfgname);
2115  return NULL;
2116  }
2117  GNUNET_free (cfgname);
2118  GNUNET_OS_init (pd);
2119  return cfg;
2120 }
2121 
2122 
2123 /* end of configuration.c */
static enum GNUNET_GenericReturnValue test_match(void *cls, const char *fn)
FIXME.
enum GNUNET_GenericReturnValue dirty
Modification indication since last save GNUNET_NO if clean, GNUNET_YES if dirty, GNUNET_SYSERR on err...
void(* GNUNET_CONFIGURATION_Section_Iterator)(void *cls, const char *section)
Function to iterate over section.
Return the directory where translations are installed (share/locale/)
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_DISK_file_test_read(const char *fil)
Check that fil corresponds to a filename and the file has read permissions.
Definition: disk.c:489
const char * config_file
Configuration file name (in $XDG_CONFIG_HOME) to use.
Create file if it doesn&#39;t exist.
Project-specific data used to help the OS subsystem find installation paths.
static const struct GNUNET_CONFIGURATION_Handle * cfg
Configuration we are using.
Definition: gnunet-abd.c:36
static int end
Set if we are to shutdown all services (including ARM).
Definition: gnunet-arm.c:34
unsigned int hint_lineno
Diagnostics information for the line number.
Definition: configuration.c:66
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.
static char * escape_name(const char *value)
FIXME.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_load(struct GNUNET_CONFIGURATION_Handle *cfg, const char *filename)
Load 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...
void GNUNET_CONFIGURATION_iterate(const struct GNUNET_CONFIGURATION_Handle *cfg, GNUNET_CONFIGURATION_Iterator iter, void *iter_cls)
Iterate over all options in the configuration.
Return the directory where libraries are installed.
static bool do_skip(const char *sec, const char *key)
Should we skip this configuration entry when serializing?
const char * project_dirname
Name of the project that is used in the "libexec" prefix, For example, "gnunet".
static int start
Set if we are to start default services (including ARM).
Definition: gnunet-arm.c:39
static size_t data_size
Number of bytes in data.
Definition: gnunet-abd.c:187
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...
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
bool diagnostics
Enable diagnostics.
enum GNUNET_GenericReturnValue GNUNET_DISK_file_close(struct GNUNET_DISK_FileHandle *h)
Close an open file.
Definition: disk.c:1283
char * GNUNET_buffer_reap_str(struct GNUNET_Buffer *buf)
Clear the buffer and return the string it contained.
Definition: buffer.c:123
struct ConfigEntry * entries
entries in the section
Definition: configuration.c:83
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
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.
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.
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
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.
static int ret
Return value of the commandline.
Definition: gnunet-abd.c:81
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.
GNUNET_GenericReturnValue
Named constants for return values.
Definition: gnunet_common.h:83
static struct Experiment * e
void(* GNUNET_CONFIGURATION_Iterator)(void *cls, const char *section, const char *option, const char *value)
Function to iterate over options.
const char * user_config_file
Configuration file name to use (if $XDG_CONFIG_HOME is not set).
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
const struct GNUNET_OS_ProjectData * GNUNET_OS_project_data_default(void)
Return default project data used by &#39;libgnunetutil&#39; for GNUnet.
configuration entry
Definition: configuration.c:41
#define GNUNET_new(type)
Allocate a struct or union of the given type.
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.
struct GNUNET_CONFIGURATION_Handle * GNUNET_CONFIGURATION_create()
Create a new configuration object.
char * GNUNET_CONFIGURATION_serialize_diagnostics(const struct GNUNET_CONFIGURATION_Handle *cfg)
Serializes the given configuration with diagnostics information.
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.
int GNUNET_DISK_directory_scan(const char *dir_name, GNUNET_FileNameCallback callback, void *callback_cls)
Scan a directory for files.
Definition: disk.c:814
static struct ConfigEntry * find_entry(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *key)
Find an entry from a configuration.
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_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.
char * hint_filename
Diagnostics information for the filename.
Definition: configuration.c:61
Closure to inline_glob_cb.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_write(struct GNUNET_CONFIGURATION_Handle *cfg, const char *filename)
Write configuration file.
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
#define SIZE_MAX
Definition: platform.h:213
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
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.
static struct GNUNET_ARM_Handle * h
Connection with ARM.
Definition: gnunet-arm.c:99
struct GNUNET_CONFIGURATION_Handle * cfgDiff
uint32_t number
#define _(String)
GNU gettext support macro.
Definition: platform.h:178
static char * section
Name of the section.
Definition: gnunet-config.c:33
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.
struct GNUNET_CONFIGURATION_Handle * GNUNET_CONFIGURATION_default(void)
Return GNUnet&#39;s default configuration.
Return the "PREFIX" directory given to configure.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_append_value_filename(struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, const char *value)
Append a filename to a configuration value that represents a list of filenames.
char * name
name of the section
Definition: configuration.c:88
cryptographic primitives for GNUnet
struct GNUNET_CONFIGURATION_Handle * cfg
Configuration to read inlined configuration into.
static struct GNUNET_OS_Process * p
Helper process we started.
Definition: gnunet-qr.c:59
static char * line
Desired phone line (string to be converted to a hash).
static struct ConfigSection * find_section(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section)
Find a section entry from a configuration.
Return the prefix of the path with documentation files, including the license (share/doc/gnunet/).
static char * value
Value of the record to add/remove.
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.
#define GNUNET_log_strerror_file(level, cmd, filename)
Log an error message at log-level &#39;level&#39; that indicates a failure of the command &#39;cmd&#39; with the mess...
static char * fn
Filename of the unique file.
#define GNUNET_realloc(ptr, size)
Wrapper around realloc.
Truncate file if it exists.
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
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, the current running apps installation directory.
void GNUNET_CONFIGURATION_remove_section(struct GNUNET_CONFIGURATION_Handle *cfg, const char *section)
Remove the given section and all options in it.
void GNUNET_CONFIGURATION_destroy(struct GNUNET_CONFIGURATION_Handle *cfg)
Destroy configuration object.
static char * option
Name of the option.
Definition: gnunet-config.c:38
static char buf[2048]
static char * filename
int GNUNET_DISK_glob(const char *glob_pattern, GNUNET_FileNameCallback callback, void *callback_cls)
Find all files matching a glob pattern.
Definition: disk.c:997
static int result
Global testing status.
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.
static void compare_entries(void *cls, const char *section, const char *option, const char *value)
A callback function, compares entries from two configurations (default against a new configuration) a...
static void copy_entry(void *cls, const char *section, const char *option, const char *value)
Copy a configuration value to the given target configuration.
struct ConfigSection * sections
Configuration sections.
Return the directory where helper binaries are installed (lib/gnunet/libexec/)
#define LOG(kind,...)
Definition: configuration.c:33
static int res
int int GNUNET_asprintf(char **buf, const char *format,...) __attribute__((format(printf
Like asprintf, just portable.
unsigned int hint_inlined_from_line
For secret sections: Where was this inlined from?
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
static unsigned int size
Size of the "table".
Definition: peer.c:67
Open the file for writing.
struct ConfigEntry * next
This is a linked list.
Definition: configuration.c:46
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_have_value(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option)
Test if we have a value for a particular option.
configuration section
Definition: configuration.c:73
char * GNUNET_STRINGS_filename_expand(const char *fil)
Complete filename (a la shell) from abbrevition.
Definition: strings.c:482
char * getenv()
struct GNUNET_MQ_Envelope * env
Definition: 005.c:1
Used for diffing a configuration object against the default one.
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 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 struct GNUNET_FS_Handle * fs
Handle to FS service.
Definition: gnunet-fs.c:36
char * main_filename
Name of the entry point configuration file.
bool inaccessible
Is the configuration section marked as inaccessible?
Definition: configuration.c:96
struct GNUNET_CONFIGURATION_Handle * GNUNET_CONFIGURATION_dup(const struct GNUNET_CONFIGURATION_Handle *cfg)
Duplicate an existing configuration object.
static struct in_addr dummy
Target "dummy" address of the packet we pretend to respond to.
static enum GNUNET_GenericReturnValue parse_configuration_file(void *cls, const char *filename)
Wrapper around GNUNET_CONFIGURATION_parse.
char * GNUNET_CONFIGURATION_serialize(const struct GNUNET_CONFIGURATION_Handle *cfg, size_t *size)
Serializes the given configuration.
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
Return the directory where the program binaries are installed.
#define GNUNET_strndup(a, length)
Wrapper around GNUNET_xstrndup_.
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.
configuration data
char * key
key for this entry
Definition: configuration.c:51
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.
static OpusEncoder * enc
OPUS encoder.
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.
enum GNUNET_GenericReturnValue(* GNUNET_FileNameCallback)(void *cls, const char *filename)
Function called with a filename.
#define GNUNET_log(kind,...)
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_load_from(struct GNUNET_CONFIGURATION_Handle *cfg, const char *defaults_d)
Load default configuration.
const struct GNUNET_OS_ProjectData * GNUNET_OS_project_data_get(void)
enum GNUNET_GenericReturnValue(* GNUNET_CONFIGURATION_Callback)(void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg)
Signature of a function to be run with a configuration.
char * hint_secret_filename
Diagnostics hint for the inaccessible file.
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".
void GNUNET_OS_init(const struct GNUNET_OS_ProjectData *pd)
Setup OS subsystem with project data.
const struct GNUNET_CONFIGURATION_Handle * cfg_default
enum GNUNET_GenericReturnValue GNUNET_DISK_directory_remove(const char *filename)
Remove all files in a directory (rm -rf).
Definition: disk.c:1062
Return the prefix of the path with application icons (share/icons/).
enum GNUNET_GenericReturnValue GNUNET_DISK_directory_create_for_file(const char *filename)
Create the directory structure for storing a file.
Definition: disk.c:582
Common buffer management functions.
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.
void GNUNET_CONFIGURATION_enable_diagnostics(struct GNUNET_CONFIGURATION_Handle *cfg)
Enable extra diagnostics.
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
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...
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.
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:1212
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.
struct ConfigSection * next
This is a linked list.
Definition: configuration.c:78
Handle used to access files (and pipes).
static int list
Set if we should print a list of currently running services.
Definition: gnunet-arm.c:69
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
#define GNUNET_malloc(size)
Wrapper around malloc.
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
char * val
current, committed value
Definition: configuration.c:56
Return the directory where data is installed (share/gnunet/)
#define GNUNET_free(ptr)
Wrapper around free.
Time for relative time used by GNUnet, in microseconds.
uint16_t len
length of data (which is always a uint32_t, but presumably this can be used to specify that fewer byt...
char * hint_inlined_from_filename
For secret sections: Where was this inlined from?
static int inline_glob_cb(void *cls, const char *filename)
Function called with a filename.
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...