global reindent, now with uncrustify hook enabled
[oweals/gnunet.git] / src / util / configuration.c
index 3d9281e8d2d87fdb07773451685e159baa8d9449..cb6932b1536afc800af7cffc8aacee3a724b3e14 100644 (file)
@@ -1,22 +1,22 @@
 /*
      This file is part of GNUnet.
-     (C) 2006, 2007, 2008, 2009, 2013 Christian Grothoff (and other contributing authors)
+     Copyright (C) 2006, 2007, 2008, 2009, 2013 GNUnet e.V.
 
-     GNUnet is free software; you can redistribute it and/or modify
-     it under the terms of the GNU General Public License as published
-     by the Free Software Foundation; either version 3, or (at your
-     option) any later version.
+     GNUnet is free software: you can redistribute it and/or modify it
+     under the terms of the GNU Affero General Public License as published
+     by the Free Software Foundation, either version 3 of the License,
+     or (at your option) any later version.
 
      GNUnet is distributed in the hope that it will be useful, but
      WITHOUT ANY WARRANTY; without even the implied warranty of
      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-     General Public License for more details.
+     Affero General Public License for more details.
 
-     You should have received a copy of the GNU General Public License
-     along with GNUnet; see the file COPYING.  If not, write to the
-     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-     Boston, MA 02111-1307, USA.
-*/
+     You should have received a copy of the GNU Affero General Public License
+     along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+     SPDX-License-Identifier: AGPL3.0-or-later
+ */
 
 /**
  * @file src/util/configuration.c
  */
 
 #include "platform.h"
-#include "gnunet_util_lib.h"
+#include "gnunet_crypto_lib.h"
+#include "gnunet_strings_lib.h"
+#include "gnunet_configuration_lib.h"
+#include "gnunet_disk_lib.h"
 
-#define LOG(kind,...) GNUNET_log_from (kind, "util", __VA_ARGS__)
+#define LOG(kind, ...) GNUNET_log_from (kind, "util", __VA_ARGS__)
 
-#define LOG_STRERROR_FILE(kind,syscall,filename) GNUNET_log_from_strerror_file (kind, "util", syscall, filename)
+#define LOG_STRERROR_FILE(kind, syscall, filename) \
+  GNUNET_log_from_strerror_file (kind, "util", syscall, filename)
 
 /**
  * @brief configuration entry
  */
 struct ConfigEntry
 {
-
   /**
    * This is a linked list.
    */
@@ -92,7 +95,6 @@ struct GNUNET_CONFIGURATION_Handle
    * #GNUNET_SYSERR on error (i.e. last save failed)
    */
   int dirty;
-
 };
 
 
@@ -136,22 +138,54 @@ GNUNET_CONFIGURATION_destroy (struct GNUNET_CONFIGURATION_Handle *cfg)
 }
 
 
+/**
+ * Parse a configuration file @a filename and run the function
+ * @a cb with the resulting configuration object. Then free the
+ * configuration object and return the status value from @a cb.
+ *
+ * @param filename configuration to parse, NULL for "default"
+ * @param cb function to run
+ * @param cb_cls closure for @a cb
+ * @return #GNUNET_SYSERR if parsing the configuration failed,
+ *   otherwise return value from @a cb.
+ */
+int
+GNUNET_CONFIGURATION_parse_and_run (const char *filename,
+                                    GNUNET_CONFIGURATION_Callback cb,
+                                    void *cb_cls)
+{
+  struct GNUNET_CONFIGURATION_Handle *cfg;
+  int ret;
+
+  cfg = GNUNET_CONFIGURATION_create ();
+  if (GNUNET_OK != GNUNET_CONFIGURATION_load (cfg, filename))
+  {
+    GNUNET_break (0);
+    GNUNET_CONFIGURATION_destroy (cfg);
+    return GNUNET_SYSERR;
+  }
+  ret = cb (cb_cls, cfg);
+  GNUNET_CONFIGURATION_destroy (cfg);
+  return ret;
+}
+
+
 /**
  * De-serializes configuration
  *
  * @param cfg configuration to update
  * @param mem the memory block of serialized configuration
  * @param size the size of the memory block
- * @param allow_inline set to #GNUNET_YES if we recursively load configuration
- *          from inlined configurations; #GNUNET_NO if not and raise warnings
+ * @param basedir set to path from which we recursively load configuration
+ *          from inlined configurations; NULL if not and raise warnings
  *          when we come across them
  * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
  */
 int
 GNUNET_CONFIGURATION_deserialize (struct GNUNET_CONFIGURATION_Handle *cfg,
-                                 const char *mem,
-                                 const size_t size,
-                                 int allow_inline)
+                                  const char *mem,
+                                  size_t size,
+                                  const char *basedir)
 {
   char *line;
   char *line_orig;
@@ -168,7 +202,6 @@ GNUNET_CONFIGURATION_deserialize (struct GNUNET_CONFIGURATION_Handle *cfg,
   char *tag;
   char *value;
 
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "Deserializing config file\n");
   ret = GNUNET_OK;
   section = GNUNET_strdup ("");
   nr = 0;
@@ -187,7 +220,8 @@ GNUNET_CONFIGURATION_deserialize (struct GNUNET_CONFIGURATION_Handle *cfg,
     }
     else
     {
-      line_orig = GNUNET_strndup (&mem[r_bytes], line_size = (pos - &mem[r_bytes]));
+      line_orig =
+        GNUNET_strndup (&mem[r_bytes], line_size = (pos - &mem[r_bytes]));
       r_bytes += line_size + 1;
     }
     line = line_orig;
@@ -209,50 +243,52 @@ GNUNET_CONFIGURATION_deserialize (struct GNUNET_CONFIGURATION_Handle *cfg,
       continue;
 
     /* remove tailing whitespace */
-    for (i = line_size - 1; (i >= 1) && (isspace ((unsigned char) line[i]));i--)
+    for (i = line_size - 1; (i >= 1) && (isspace ((unsigned char) line[i]));
+         i--)
       line[i] = '\0';
 
     /* remove leading whitespace */
-    for (; line[0] != '\0' && (isspace ((unsigned char) line[0])); line++);
+    for (; line[0] != '\0' && (isspace ((unsigned char) line[0])); line++)
+      ;
 
     /* ignore comments */
-    if ( ('#' == line[0]) || ('%' == line[0]) )
+    if (('#' == line[0]) || ('%' == line[0]))
       continue;
 
     /* handle special "@INLINE@" directive */
-    if (0 == strncasecmp (line,
-                         "@INLINE@ ",
-                         strlen ("@INLINE@ ")))
+    if (0 == strncasecmp (line, "@INLINE@ ", strlen ("@INLINE@ ")))
     {
       /* @INLINE@ value */
       value = &line[strlen ("@INLINE@ ")];
-      if (GNUNET_YES == allow_inline)
+      if (NULL != basedir)
       {
-       if (GNUNET_OK != GNUNET_CONFIGURATION_parse (cfg, value))
-       {
-         ret = GNUNET_SYSERR;    /* failed to parse included config */
-         break;
-       }
+        char *fn;
+
+        GNUNET_asprintf (&fn, "%s/%s", basedir, value);
+        if (GNUNET_OK != GNUNET_CONFIGURATION_parse (cfg, fn))
+        {
+          GNUNET_free (fn);
+          ret = GNUNET_SYSERR;         /* failed to parse included config */
+          break;
+        }
+        GNUNET_free (fn);
       }
       else
       {
-       LOG (GNUNET_ERROR_TYPE_DEBUG,
-            "Ignoring parsing @INLINE@ configurations, not allowed!\n");
-       ret = GNUNET_SYSERR;
-       break;
+        LOG (GNUNET_ERROR_TYPE_DEBUG,
+             "Ignoring parsing @INLINE@ configurations, not allowed!\n");
+        ret = GNUNET_SYSERR;
+        break;
       }
       continue;
     }
-    if ( ('[' == line[0]) && (']' == line[line_size - 1]) )
+    if (('[' == line[0]) && (']' == line[line_size - 1]))
     {
       /* [value] */
       line[line_size - 1] = '\0';
       value = &line[1];
       GNUNET_free (section);
       section = GNUNET_strdup (value);
-      LOG (GNUNET_ERROR_TYPE_DEBUG,
-          "Config section `%s'\n",
-          section);
       continue;
     }
     if (NULL != (eq = strchr (line, '=')))
@@ -260,40 +296,40 @@ GNUNET_CONFIGURATION_deserialize (struct GNUNET_CONFIGURATION_Handle *cfg,
       /* tag = value */
       tag = GNUNET_strndup (line, eq - line);
       /* remove tailing whitespace */
-      for (i = strlen (tag) - 1; (i >= 1) && (isspace ((unsigned char) tag[i]));i--)
-       tag[i] = '\0';
+      for (i = strlen (tag) - 1; (i >= 1) && (isspace ((unsigned char) tag[i]));
+           i--)
+        tag[i] = '\0';
 
       /* Strip whitespace */
       value = eq + 1;
       while (isspace ((unsigned char) value[0]))
-       value++;
-      for (i = strlen (value) - 1; (i >= 1) && (isspace ((unsigned char) value[i]));i--)
-       value[i] = '\0';
+        value++;
+      for (i = strlen (value) - 1;
+           (i >= 1) && (isspace ((unsigned char) value[i]));
+           i--)
+        value[i] = '\0';
 
       /* remove quotes */
       i = 0;
-      if ( ('"' == value[0]) &&
-          ('"' == value[strlen (value) - 1]) )
+      if (('"' == value[0]) && ('"' == value[strlen (value) - 1]))
       {
-       value[strlen (value) - 1] = '\0';
-       value++;
+        value[strlen (value) - 1] = '\0';
+        value++;
       }
-      LOG (GNUNET_ERROR_TYPE_DEBUG, "Config value %s=\"%s\"\n", tag, value);
       GNUNET_CONFIGURATION_set_value_string (cfg, section, tag, &value[i]);
       GNUNET_free (tag);
       continue;
     }
     /* parse error */
     LOG (GNUNET_ERROR_TYPE_WARNING,
-        _("Syntax error while deserializing in line %u\n"),
-        nr);
+         _ ("Syntax error while deserializing in line %u\n"),
+         nr);
     ret = GNUNET_SYSERR;
     break;
   }
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "Finished deserializing config\n");
   GNUNET_free_non_null (line_orig);
   GNUNET_free (section);
-  GNUNET_assert ( (GNUNET_OK != ret) || (r_bytes == size) );
+  GNUNET_assert ((GNUNET_OK != ret) || (r_bytes == size));
   return ret;
 }
 
@@ -314,46 +350,47 @@ GNUNET_CONFIGURATION_parse (struct GNUNET_CONFIGURATION_Handle *cfg,
   size_t fs;
   char *fn;
   char *mem;
+  char *endsep;
   int dirty;
   int ret;
+  ssize_t sret;
 
-  LOG (GNUNET_ERROR_TYPE_DEBUG,
-       "Asked to parse config file `%s'\n",
-       filename);
   fn = GNUNET_STRINGS_filename_expand (filename);
-  LOG (GNUNET_ERROR_TYPE_DEBUG,
-       "Config file name expanded to `%s'\n",
-       fn);
-  if (fn == NULL)
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "Asked to parse config file `%s'\n", fn);
+  if (NULL == fn)
     return GNUNET_SYSERR;
-  dirty = cfg->dirty;           /* back up value! */
+  dirty = cfg->dirty; /* back up value! */
   if (GNUNET_SYSERR ==
       GNUNET_DISK_file_size (fn, &fs64, GNUNET_YES, GNUNET_YES))
   {
     LOG (GNUNET_ERROR_TYPE_WARNING,
-        "Error while determining the file size of %s\n", fn);
+         "Error while determining the file size of `%s'\n",
+         fn);
     GNUNET_free (fn);
     return GNUNET_SYSERR;
   }
   if (fs64 > SIZE_MAX)
   {
-    GNUNET_break (0);          /* File size is more than the heap size */
+    GNUNET_break (0);  /* File size is more than the heap size */
     GNUNET_free (fn);
     return GNUNET_SYSERR;
   }
   fs = fs64;
   mem = GNUNET_malloc (fs);
-  if (fs != GNUNET_DISK_fn_read (fn, mem, fs))
+  sret = GNUNET_DISK_fn_read (fn, mem, fs);
+  if ((sret < 0) || (fs != (size_t) sret))
   {
-    LOG (GNUNET_ERROR_TYPE_WARNING,
-        "Error while reading file %s\n", fn);
+    LOG (GNUNET_ERROR_TYPE_WARNING, _ ("Error while reading file `%s'\n"), fn);
     GNUNET_free (fn);
     GNUNET_free (mem);
     return GNUNET_SYSERR;
   }
   LOG (GNUNET_ERROR_TYPE_DEBUG, "Deserializing contents of file `%s'\n", fn);
+  endsep = strrchr (fn, (int) '/');
+  if (NULL != endsep)
+    *endsep = '\0';
+  ret = GNUNET_CONFIGURATION_deserialize (cfg, mem, fs, fn);
   GNUNET_free (fn);
-  ret = GNUNET_CONFIGURATION_deserialize (cfg, mem, fs, GNUNET_YES);
   GNUNET_free (mem);
   /* restore dirty flag - anything we set in the meantime
    * came from disk */
@@ -386,7 +423,7 @@ GNUNET_CONFIGURATION_is_dirty (const struct GNUNET_CONFIGURATION_Handle *cfg)
  */
 char *
 GNUNET_CONFIGURATION_serialize (const struct GNUNET_CONFIGURATION_Handle *cfg,
-                               size_t *size)
+                                size_t *size)
 {
   struct ConfigSection *sec;
   struct ConfigEntry *ent;
@@ -394,11 +431,9 @@ GNUNET_CONFIGURATION_serialize (const struct GNUNET_CONFIGURATION_Handle *cfg,
   char *cbuf;
   char *val;
   char *pos;
-  int len;
   size_t m_size;
   size_t c_size;
 
-
   /* Pass1 : calculate the buffer size required */
   m_size = 0;
   for (sec = cfg->sections; NULL != sec; sec = sec->next)
@@ -409,16 +444,16 @@ GNUNET_CONFIGURATION_serialize (const struct GNUNET_CONFIGURATION_Handle *cfg,
     {
       if (NULL != ent->val)
       {
-       /* if val has any '\n' then they occupy +1 character as '\n'->'\\','n' */
-       pos = ent->val;
-       while (NULL != (pos = strstr (pos, "\n")))
-       {
-         m_size++;
-         pos++;
-       }
-       /* For each key = value pair we need to add 4 characters (2
-          spaces and 1 equal-to character and 1 new line) */
-       m_size += strlen (ent->key) + strlen (ent->val) + 4;
+        /* if val has any '\n' then they occupy +1 character as '\n'->'\\','n' */
+        pos = ent->val;
+        while (NULL != (pos = strstr (pos, "\n")))
+        {
+          m_size++;
+          pos++;
+        }
+        /* For each key = value pair we need to add 4 characters (2
+           spaces and 1 equal-to character and 1 new line) */
+        m_size += strlen (ent->key) + strlen (ent->val) + 4;
       }
     }
     /* A new line after section end */
@@ -432,32 +467,34 @@ GNUNET_CONFIGURATION_serialize (const struct GNUNET_CONFIGURATION_Handle *cfg,
   *size = c_size;
   while (NULL != sec)
   {
+    int len;
+
     len = GNUNET_asprintf (&cbuf, "[%s]\n", sec->name);
     GNUNET_assert (0 < len);
-    memcpy (mem + c_size, cbuf, len);
+    GNUNET_memcpy (mem + c_size, cbuf, len);
     c_size += len;
     GNUNET_free (cbuf);
     for (ent = sec->entries; NULL != ent; ent = ent->next)
     {
       if (NULL != ent->val)
       {
-       val = GNUNET_malloc (strlen (ent->val) * 2 + 1);
-       strcpy (val, ent->val);
+        val = GNUNET_malloc (strlen (ent->val) * 2 + 1);
+        strcpy (val, ent->val);
         while (NULL != (pos = strstr (val, "\n")))
         {
           memmove (&pos[2], &pos[1], strlen (&pos[1]));
           pos[0] = '\\';
           pos[1] = 'n';
         }
-       len = GNUNET_asprintf (&cbuf, "%s = %s\n", ent->key, val);
-       GNUNET_free (val);
-       memcpy (mem + c_size, cbuf, len);
-       c_size += len;
-       GNUNET_free (cbuf);
+        len = GNUNET_asprintf (&cbuf, "%s = %s\n", ent->key, val);
+        GNUNET_free (val);
+        GNUNET_memcpy (mem + c_size, cbuf, len);
+        c_size += len;
+        GNUNET_free (cbuf);
       }
     }
-    memcpy (mem + c_size, "\n", 1);
-    c_size ++;
+    GNUNET_memcpy (mem + c_size, "\n", 1);
+    c_size++;
     sec = sec->next;
   }
   GNUNET_assert (c_size == m_size);
@@ -480,6 +517,7 @@ GNUNET_CONFIGURATION_write (struct GNUNET_CONFIGURATION_Handle *cfg,
   char *fn;
   char *cfg_buf;
   size_t size;
+  ssize_t sret;
 
   fn = GNUNET_STRINGS_filename_expand (filename);
   if (fn == NULL)
@@ -490,22 +528,26 @@ GNUNET_CONFIGURATION_write (struct GNUNET_CONFIGURATION_Handle *cfg,
     return GNUNET_SYSERR;
   }
   cfg_buf = GNUNET_CONFIGURATION_serialize (cfg, &size);
-  if (size != GNUNET_DISK_fn_write (fn, cfg_buf, size,
-                                   GNUNET_DISK_PERM_USER_READ
-                                   | GNUNET_DISK_PERM_USER_WRITE
-                                   | GNUNET_DISK_PERM_GROUP_READ
-                                   | GNUNET_DISK_PERM_GROUP_WRITE))
+  sret = GNUNET_DISK_fn_write (fn,
+                               cfg_buf,
+                               size,
+                               GNUNET_DISK_PERM_USER_READ
+                               | GNUNET_DISK_PERM_USER_WRITE
+                               | GNUNET_DISK_PERM_GROUP_READ
+                               | GNUNET_DISK_PERM_GROUP_WRITE);
+  if ((sret < 0) || (size != (size_t) sret))
   {
     GNUNET_free (fn);
     GNUNET_free (cfg_buf);
     LOG (GNUNET_ERROR_TYPE_WARNING,
-        "Writing configration to file: %s failed\n", filename);
-    cfg->dirty = GNUNET_SYSERR; /* last write failed */
+         "Writing configuration to file `%s' failed\n",
+         filename);
+    cfg->dirty = GNUNET_SYSERR;   /* last write failed */
     return GNUNET_SYSERR;
   }
   GNUNET_free (fn);
   GNUNET_free (cfg_buf);
-  cfg->dirty = GNUNET_NO;       /* last write succeeded */
+  cfg->dirty = GNUNET_NO; /* last write succeeded */
   return GNUNET_OK;
 }
 
@@ -528,7 +570,7 @@ GNUNET_CONFIGURATION_iterate (const struct GNUNET_CONFIGURATION_Handle *cfg,
   for (spos = cfg->sections; NULL != spos; spos = spos->next)
     for (epos = spos->entries; NULL != epos; epos = epos->next)
       if (NULL != epos->val)
-       iter (iter_cls, spos->name, epos->key, epos->val);
+        iter (iter_cls, spos->name, epos->key, epos->val);
 }
 
 
@@ -541,11 +583,11 @@ GNUNET_CONFIGURATION_iterate (const struct GNUNET_CONFIGURATION_Handle *cfg,
  * @param iter_cls closure for @a iter
  */
 void
-GNUNET_CONFIGURATION_iterate_section_values (const struct
-                                             GNUNET_CONFIGURATION_Handle *cfg,
-                                             const char *section,
-                                             GNUNET_CONFIGURATION_Iterator iter,
-                                             void *iter_cls)
+GNUNET_CONFIGURATION_iterate_section_values (
+  const struct GNUNET_CONFIGURATION_Handle *cfg,
+  const char *section,
+  GNUNET_CONFIGURATION_Iterator iter,
+  void *iter_cls)
 {
   struct ConfigSection *spos;
   struct ConfigEntry *epos;
@@ -569,10 +611,10 @@ GNUNET_CONFIGURATION_iterate_section_values (const struct
  * @param iter_cls closure for @a iter
  */
 void
-GNUNET_CONFIGURATION_iterate_sections (const struct GNUNET_CONFIGURATION_Handle
-                                       *cfg,
-                                       GNUNET_CONFIGURATION_Section_Iterator
-                                       iter, void *iter_cls)
+GNUNET_CONFIGURATION_iterate_sections (
+  const struct GNUNET_CONFIGURATION_Handle *cfg,
+  GNUNET_CONFIGURATION_Section_Iterator iter,
+  void *iter_cls)
 {
   struct ConfigSection *spos;
   struct ConfigSection *next;
@@ -676,7 +718,7 @@ GNUNET_CONFIGURATION_dup (const struct GNUNET_CONFIGURATION_Handle *cfg)
  */
 static struct ConfigSection *
 find_section (const struct GNUNET_CONFIGURATION_Handle *cfg,
-             const char *section)
+              const char *section)
 {
   struct ConfigSection *pos;
 
@@ -697,8 +739,8 @@ find_section (const struct GNUNET_CONFIGURATION_Handle *cfg,
  */
 static struct ConfigEntry *
 find_entry (const struct GNUNET_CONFIGURATION_Handle *cfg,
-           const char *section,
-           const char *key)
+            const char *section,
+            const char *key)
 {
   struct ConfigSection *sec;
   struct ConfigEntry *pos;
@@ -726,15 +768,14 @@ static void
 compare_entries (void *cls,
                  const char *section,
                  const char *option,
-                const char *value)
+                 const char *value)
 {
   struct DiffHandle *dh = cls;
   struct ConfigEntry *entNew;
 
   entNew = find_entry (dh->cfg_default, section, option);
-  if ( (NULL != entNew) &&
-       (NULL != entNew->val) &&
-       (0 == strcmp (entNew->val, value)) )
+  if ((NULL != entNew) && (NULL != entNew->val) &&
+      (0 == strcmp (entNew->val, value)))
     return;
   GNUNET_CONFIGURATION_set_value_string (dh->cfgDiff, section, option, value);
 }
@@ -748,8 +789,9 @@ compare_entries (void *cls,
  * @return configuration with only the differences, never NULL
  */
 struct GNUNET_CONFIGURATION_Handle *
-GNUNET_CONFIGURATION_get_diff (const struct GNUNET_CONFIGURATION_Handle *cfg_default,
-                              const struct GNUNET_CONFIGURATION_Handle *cfg_new)
+GNUNET_CONFIGURATION_get_diff (
+  const struct GNUNET_CONFIGURATION_Handle *cfg_default,
+  const struct GNUNET_CONFIGURATION_Handle *cfg_new)
 {
   struct DiffHandle diffHandle;
 
@@ -769,10 +811,10 @@ GNUNET_CONFIGURATION_get_diff (const struct GNUNET_CONFIGURATION_Handle *cfg_def
  * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
  */
 int
-GNUNET_CONFIGURATION_write_diffs (const struct GNUNET_CONFIGURATION_Handle
-                                  *cfg_default,
-                                  const struct GNUNET_CONFIGURATION_Handle
-                                  *cfg_new, const char *filename)
+GNUNET_CONFIGURATION_write_diffs (
+  const struct GNUNET_CONFIGURATION_Handle *cfg_default,
+  const struct GNUNET_CONFIGURATION_Handle *cfg_new,
+  const char *filename)
 {
   int ret;
   struct GNUNET_CONFIGURATION_Handle *diff;
@@ -794,7 +836,8 @@ GNUNET_CONFIGURATION_write_diffs (const struct GNUNET_CONFIGURATION_Handle
  */
 void
 GNUNET_CONFIGURATION_set_value_string (struct GNUNET_CONFIGURATION_Handle *cfg,
-                                       const char *section, const char *option,
+                                       const char *section,
+                                       const char *option,
                                        const char *value)
 {
   struct ConfigSection *sec;
@@ -843,7 +886,8 @@ GNUNET_CONFIGURATION_set_value_string (struct GNUNET_CONFIGURATION_Handle *cfg,
  */
 void
 GNUNET_CONFIGURATION_set_value_number (struct GNUNET_CONFIGURATION_Handle *cfg,
-                                       const char *section, const char *option,
+                                       const char *section,
+                                       const char *option,
                                        unsigned long long number)
 {
   char s[64];
@@ -863,18 +907,49 @@ GNUNET_CONFIGURATION_set_value_number (struct GNUNET_CONFIGURATION_Handle *cfg,
  * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
  */
 int
-GNUNET_CONFIGURATION_get_value_number (const struct GNUNET_CONFIGURATION_Handle
-                                       *cfg, const char *section,
-                                       const char *option,
-                                       unsigned long long *number)
+GNUNET_CONFIGURATION_get_value_number (
+  const struct GNUNET_CONFIGURATION_Handle *cfg,
+  const char *section,
+  const char *option,
+  unsigned long long *number)
+{
+  struct ConfigEntry *e;
+  char dummy[2];
+
+  if (NULL == (e = find_entry (cfg, section, option)))
+    return GNUNET_SYSERR;
+  if (NULL == e->val)
+    return GNUNET_SYSERR;
+  if (1 != sscanf (e->val, "%llu%1s", number, dummy))
+    return GNUNET_SYSERR;
+  return GNUNET_OK;
+}
+
+
+/**
+ * Get a configuration value that should be a floating point number.
+ *
+ * @param cfg configuration to inspect
+ * @param section section of interest
+ * @param option option of interest
+ * @param number where to store the floating value of the option
+ * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
+ */
+int
+GNUNET_CONFIGURATION_get_value_float (
+  const struct GNUNET_CONFIGURATION_Handle *cfg,
+  const char *section,
+  const char *option,
+  float *number)
 {
   struct ConfigEntry *e;
+  char dummy[2];
 
   if (NULL == (e = find_entry (cfg, section, option)))
     return GNUNET_SYSERR;
   if (NULL == e->val)
     return GNUNET_SYSERR;
-  if (1 != SSCANF (e->val, "%llu", number))
+  if (1 != sscanf (e->val, "%f%1s", number, dummy))
     return GNUNET_SYSERR;
   return GNUNET_OK;
 }
@@ -890,18 +965,26 @@ GNUNET_CONFIGURATION_get_value_number (const struct GNUNET_CONFIGURATION_Handle
  * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
  */
 int
-GNUNET_CONFIGURATION_get_value_time (const struct GNUNET_CONFIGURATION_Handle
-                                     *cfg, const char *section,
-                                     const char *option,
-                                     struct GNUNET_TIME_Relative *time)
+GNUNET_CONFIGURATION_get_value_time (
+  const struct GNUNET_CONFIGURATION_Handle *cfg,
+  const char *section,
+  const char *option,
+  struct GNUNET_TIME_Relative *time)
 {
   struct ConfigEntry *e;
+  int ret;
 
   if (NULL == (e = find_entry (cfg, section, option)))
     return GNUNET_SYSERR;
   if (NULL == e->val)
     return GNUNET_SYSERR;
-  return GNUNET_STRINGS_fancy_time_to_relative (e->val, time);
+  ret = GNUNET_STRINGS_fancy_time_to_relative (e->val, time);
+  if (GNUNET_OK != ret)
+    GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
+                               section,
+                               option,
+                               _ ("Not a valid relative time specification"));
+  return ret;
 }
 
 
@@ -915,10 +998,11 @@ GNUNET_CONFIGURATION_get_value_time (const struct GNUNET_CONFIGURATION_Handle
  * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
  */
 int
-GNUNET_CONFIGURATION_get_value_size (const struct GNUNET_CONFIGURATION_Handle *cfg,
-                                     const char *section,
-                                     const char *option,
-                                     unsigned long long *size)
+GNUNET_CONFIGURATION_get_value_size (
+  const struct GNUNET_CONFIGURATION_Handle *cfg,
+  const char *section,
+  const char *option,
+  unsigned long long *size)
 {
   struct ConfigEntry *e;
 
@@ -941,19 +1025,15 @@ GNUNET_CONFIGURATION_get_value_size (const struct GNUNET_CONFIGURATION_Handle *c
  * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
  */
 int
-GNUNET_CONFIGURATION_get_value_string (const struct GNUNET_CONFIGURATION_Handle *cfg,
-                                       const char *section,
-                                       const char *option,
-                                       char **value)
+GNUNET_CONFIGURATION_get_value_string (
+  const struct GNUNET_CONFIGURATION_Handle *cfg,
+  const char *section,
+  const char *option,
+  char **value)
 {
   struct ConfigEntry *e;
 
-  LOG (GNUNET_ERROR_TYPE_DEBUG,
-       "Asked to retrieve string `%s' in section `%s'\n",
-       option,
-       section);
-  if ( (NULL == (e = find_entry (cfg, section, option))) ||
-       (NULL == e->val) )
+  if ((NULL == (e = find_entry (cfg, section, option))) || (NULL == e->val))
   {
     *value = NULL;
     return GNUNET_SYSERR;
@@ -976,11 +1056,12 @@ GNUNET_CONFIGURATION_get_value_string (const struct GNUNET_CONFIGURATION_Handle
  * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
  */
 int
-GNUNET_CONFIGURATION_get_value_choice (const struct GNUNET_CONFIGURATION_Handle *cfg,
-                                       const char *section,
-                                       const char *option,
-                                       const char *const *choices,
-                                       const char **value)
+GNUNET_CONFIGURATION_get_value_choice (
+  const struct GNUNET_CONFIGURATION_Handle *cfg,
+  const char *section,
+  const char *option,
+  const char *const *choices,
+  const char **value)
 {
   struct ConfigEntry *e;
   unsigned int i;
@@ -993,8 +1074,8 @@ GNUNET_CONFIGURATION_get_value_choice (const struct GNUNET_CONFIGURATION_Handle
   if (NULL == choices[i])
   {
     LOG (GNUNET_ERROR_TYPE_ERROR,
-         _("Configuration value '%s' for '%s'"
-           " in section '%s' is not in set of legal choices\n"),
+         _ ("Configuration value '%s' for '%s'"
+            " in section '%s' is not in set of legal choices\n"),
          e->val,
          option,
          section);
@@ -1005,6 +1086,50 @@ GNUNET_CONFIGURATION_get_value_choice (const struct GNUNET_CONFIGURATION_Handle
 }
 
 
+/**
+ * Get crockford32-encoded fixed-size binary data from a configuration.
+ *
+ * @param cfg configuration to access
+ * @param section section to access
+ * @param option option to access
+ * @param buf where to store the decoded binary result
+ * @param buf_size exact number of bytes to store in @a buf
+ * @return #GNUNET_OK on success
+ *         #GNUNET_NO is the value does not exist
+ *         #GNUNET_SYSERR on decoding error
+ */
+int
+GNUNET_CONFIGURATION_get_data (const struct GNUNET_CONFIGURATION_Handle *cfg,
+                               const char *section,
+                               const char *option,
+                               void *buf,
+                               size_t buf_size)
+{
+  char *enc;
+  int res;
+  size_t data_size;
+
+  if (GNUNET_OK !=
+      (res =
+         GNUNET_CONFIGURATION_get_value_string (cfg, section, option, &enc)))
+    return res;
+  data_size = (strlen (enc) * 5) / 8;
+  if (data_size != buf_size)
+  {
+    GNUNET_free (enc);
+    return GNUNET_SYSERR;
+  }
+  if (GNUNET_OK !=
+      GNUNET_STRINGS_string_to_data (enc, strlen (enc), buf, buf_size))
+  {
+    GNUNET_free (enc);
+    return GNUNET_SYSERR;
+  }
+  GNUNET_free (enc);
+  return GNUNET_OK;
+}
+
+
 /**
  * Test if we have a value for a particular option
  *
@@ -1015,7 +1140,8 @@ GNUNET_CONFIGURATION_get_value_choice (const struct GNUNET_CONFIGURATION_Handle
  */
 int
 GNUNET_CONFIGURATION_have_value (const struct GNUNET_CONFIGURATION_Handle *cfg,
-                                 const char *section, const char *option)
+                                 const char *section,
+                                 const char *option)
 {
   struct ConfigEntry *e;
 
@@ -1045,7 +1171,6 @@ expand_dollar (const struct GNUNET_CONFIGURATION_Handle *cfg,
                char *orig,
                unsigned int depth)
 {
-  int i;
   char *prefix;
   char *result;
   char *start;
@@ -1063,16 +1188,15 @@ expand_dollar (const struct GNUNET_CONFIGURATION_Handle *cfg,
   if (depth > 128)
   {
     LOG (GNUNET_ERROR_TYPE_WARNING,
-         _("Recursive expansion suspected, aborting $-expansion for term `%s'\n"),
+         _ (
+           "Recursive expansion suspected, aborting $-expansion for term `%s'\n"),
          orig);
     return orig;
   }
-  LOG (GNUNET_ERROR_TYPE_DEBUG,
-       "Asked to $-expand %s\n", orig);
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "Asked to $-expand %s\n", orig);
   if ('$' != orig[0])
   {
-    LOG (GNUNET_ERROR_TYPE_DEBUG,
-         "Doesn't start with $ - not expanding\n");
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "Doesn't start with $ - not expanding\n");
     return orig;
   }
   erased_char = 0;
@@ -1090,15 +1214,18 @@ expand_dollar (const struct GNUNET_CONFIGURATION_Handle *cfg,
       case '}':
         lopen--;
         break;
+
       case '{':
         lopen++;
         break;
+
       case '\0':
         LOG (GNUNET_ERROR_TYPE_WARNING,
-             _("Missing closing `%s' in option `%s'\n"),
+             _ ("Missing closing `%s' in option `%s'\n"),
              "}",
              orig);
         return orig;
+
       default:
         break;
       }
@@ -1112,21 +1239,20 @@ expand_dollar (const struct GNUNET_CONFIGURATION_Handle *cfg,
     {
       *def = '\0';
       def++;
-      if ( ('-' == *def) ||
-           ('=' == *def) )
+      if (('-' == *def) || ('=' == *def))
         def++;
       def = GNUNET_strdup (def);
     }
   }
   else
   {
+    int i;
+
     start = &orig[1];
     def = NULL;
     i = 0;
-    while ( (orig[i] != '/') &&
-            (orig[i] != '\\') &&
-            (orig[i] != '\0')  &&
-            (orig[i] != ' ') )
+    while ((orig[i] != '/') && (orig[i] != '\\') && (orig[i] != '\0') &&
+           (orig[i] != ' '))
       i++;
     if (orig[i] == '\0')
     {
@@ -1146,19 +1272,10 @@ expand_dollar (const struct GNUNET_CONFIGURATION_Handle *cfg,
        post,
        def);
   if (GNUNET_OK !=
-      GNUNET_CONFIGURATION_get_value_string (cfg,
-                                             "PATHS",
-                                             start,
-                                             &prefix))
+      GNUNET_CONFIGURATION_get_value_string (cfg, "PATHS", start, &prefix))
   {
-    LOG (GNUNET_ERROR_TYPE_DEBUG,
-         "Filename for `%s' is not in PATHS config section\n",
-         start);
     if (NULL == (env = getenv (start)))
     {
-      LOG (GNUNET_ERROR_TYPE_DEBUG,
-           "`%s' is not an environment variable\n",
-           start);
       /* try default */
       def = expand_dollar (cfg, def, depth + 1);
       env = def;
@@ -1169,18 +1286,17 @@ expand_dollar (const struct GNUNET_CONFIGURATION_Handle *cfg,
       if (erased_pos)
         *erased_pos = erased_char;
       LOG (GNUNET_ERROR_TYPE_WARNING,
-           _("Failed to expand `%s' in `%s' as it is neither found in [PATHS] nor defined as an environmental variable\n"),
-           start, orig);
+           _ (
+             "Failed to expand `%s' in `%s' as it is neither found in [PATHS] nor defined as an environmental variable\n"),
+           start,
+           orig);
       GNUNET_free (start);
       return orig;
     }
     prefix = GNUNET_strdup (env);
   }
   prefix = GNUNET_CONFIGURATION_expand_dollar (cfg, prefix);
-  LOG (GNUNET_ERROR_TYPE_DEBUG,
-       "Prefix is `%s'\n",
-       prefix);
-  if ( (erased_pos) && ('}' != erased_char) )
+  if ((erased_pos) && ('}' != erased_char))
   {
     len = strlen (prefix) + 1;
     prefix = GNUNET_realloc (prefix, len + 1);
@@ -1193,9 +1309,6 @@ expand_dollar (const struct GNUNET_CONFIGURATION_Handle *cfg,
   GNUNET_free_non_null (def);
   GNUNET_free (prefix);
   GNUNET_free (orig);
-  LOG (GNUNET_ERROR_TYPE_DEBUG,
-       "Expanded to `%s'\n",
-       result);
   return result;
 }
 
@@ -1217,8 +1330,9 @@ expand_dollar (const struct GNUNET_CONFIGURATION_Handle *cfg,
  * @return $-expanded string
  */
 char *
-GNUNET_CONFIGURATION_expand_dollar (const struct GNUNET_CONFIGURATION_Handle *cfg,
-                                    char *orig)
+GNUNET_CONFIGURATION_expand_dollar (
+  const struct GNUNET_CONFIGURATION_Handle *cfg,
+  char *orig)
 {
   char *dup;
   size_t i;
@@ -1232,7 +1346,7 @@ GNUNET_CONFIGURATION_expand_dollar (const struct GNUNET_CONFIGURATION_Handle *cf
     dup = expand_dollar (cfg, dup, 0);
     len = strlen (dup) + 1;
     orig = GNUNET_realloc (orig, i + len);
-    memcpy (orig + i, dup, len);
+    GNUNET_memcpy (orig + i, dup, len);
     GNUNET_free (dup);
   }
   return orig;
@@ -1250,31 +1364,24 @@ GNUNET_CONFIGURATION_expand_dollar (const struct GNUNET_CONFIGURATION_Handle *cf
  * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
  */
 int
-GNUNET_CONFIGURATION_get_value_filename (const struct GNUNET_CONFIGURATION_Handle *cfg,
-                                         const char *section,
-                                         const char *option,
-                                         char **value)
+GNUNET_CONFIGURATION_get_value_filename (
+  const struct GNUNET_CONFIGURATION_Handle *cfg,
+  const char *section,
+  const char *option,
+  char **value)
 {
   char *tmp;
 
-  LOG (GNUNET_ERROR_TYPE_DEBUG,
-       "Asked to retrieve filename `%s' in section `%s'\n",
-       option,
-       section);
   if (GNUNET_OK !=
       GNUNET_CONFIGURATION_get_value_string (cfg, section, option, &tmp))
   {
-    LOG (GNUNET_ERROR_TYPE_DEBUG,
-         "Failed to retrieve filename\n");
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "Failed to retrieve filename\n");
     *value = NULL;
     return GNUNET_SYSERR;
   }
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "Retrieved filename `%s', $-expanding\n", tmp);
   tmp = GNUNET_CONFIGURATION_expand_dollar (cfg, tmp);
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "Expanded to filename `%s', *nix-expanding\n", tmp);
   *value = GNUNET_STRINGS_filename_expand (tmp);
   GNUNET_free (tmp);
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "Filename result is `%s'\n", *value);
   if (*value == NULL)
     return GNUNET_SYSERR;
   return GNUNET_OK;
@@ -1291,16 +1398,17 @@ GNUNET_CONFIGURATION_get_value_filename (const struct GNUNET_CONFIGURATION_Handl
  * @return #GNUNET_YES, #GNUNET_NO or #GNUNET_SYSERR
  */
 int
-GNUNET_CONFIGURATION_get_value_yesno (const struct GNUNET_CONFIGURATION_Handle *cfg,
-                                      const char *section,
-                                      const char *option)
+GNUNET_CONFIGURATION_get_value_yesno (
+  const struct GNUNET_CONFIGURATION_Handle *cfg,
+  const char *section,
+  const char *option)
 {
   static const char *yesno[] = { "YES", "NO", NULL };
   const char *val;
   int ret;
 
   ret =
-      GNUNET_CONFIGURATION_get_value_choice (cfg, section, option, yesno, &val);
+    GNUNET_CONFIGURATION_get_value_choice (cfg, section, option, yesno, &val);
   if (ret == GNUNET_SYSERR)
     return ret;
   if (val == yesno[0])
@@ -1320,11 +1428,12 @@ GNUNET_CONFIGURATION_get_value_yesno (const struct GNUNET_CONFIGURATION_Handle *
  * @return number of filenames iterated over, -1 on error
  */
 int
-GNUNET_CONFIGURATION_iterate_value_filenames (const struct GNUNET_CONFIGURATION_Handle *cfg,
-                                              const char *section,
-                                              const char *option,
-                                              GNUNET_FileNameCallback cb,
-                                              void *cb_cls)
+GNUNET_CONFIGURATION_iterate_value_filenames (
+  const struct GNUNET_CONFIGURATION_Handle *cfg,
+  const char *section,
+  const char *option,
+  GNUNET_FileNameCallback cb,
+  void *cb_cls)
 {
   char *list;
   char *pos;
@@ -1354,9 +1463,11 @@ GNUNET_CONFIGURATION_iterate_value_filenames (const struct GNUNET_CONFIGURATION_
         case '\\':
         case ' ':
           memmove (end, &end[1], strlen (&end[1]) + 1);
+
         case '\0':
           /* illegal, but just keep it */
           break;
+
         default:
           /* illegal, but just ignore that there was a '/' */
           break;
@@ -1411,6 +1522,7 @@ escape_name (const char *value)
       wpos[1] = rpos[0];
       wpos += 2;
       break;
+
     default:
       wpos[0] = rpos[0];
       wpos++;
@@ -1450,20 +1562,23 @@ test_match (void *cls, const char *fn)
  *         #GNUNET_SYSERR on error
  */
 int
-GNUNET_CONFIGURATION_append_value_filename (struct GNUNET_CONFIGURATION_Handle *cfg,
-                                            const char *section,
-                                            const char *option,
-                                            const char *value)
+GNUNET_CONFIGURATION_append_value_filename (
+  struct GNUNET_CONFIGURATION_Handle *cfg,
+  const char *section,
+  const char *option,
+  const char *value)
 {
   char *escaped;
   char *old;
   char *nw;
 
   if (GNUNET_SYSERR ==
-      GNUNET_CONFIGURATION_iterate_value_filenames (cfg, section, option,
+      GNUNET_CONFIGURATION_iterate_value_filenames (cfg,
+                                                    section,
+                                                    option,
                                                     &test_match,
                                                     (void *) value))
-    return GNUNET_NO;           /* already exists */
+    return GNUNET_NO; /* already exists */
   if (GNUNET_OK !=
       GNUNET_CONFIGURATION_get_value_string (cfg, section, option, &old))
     old = GNUNET_strdup ("");
@@ -1494,10 +1609,11 @@ GNUNET_CONFIGURATION_append_value_filename (struct GNUNET_CONFIGURATION_Handle *
  *         #GNUNET_SYSERR on error
  */
 int
-GNUNET_CONFIGURATION_remove_value_filename (struct GNUNET_CONFIGURATION_Handle
-                                            *cfg, const char *section,
-                                            const char *option,
-                                            const char *value)
+GNUNET_CONFIGURATION_remove_value_filename (
+  struct GNUNET_CONFIGURATION_Handle *cfg,
+  const char *section,
+  const char *option,
+  const char *value)
 {
   char *list;
   char *pos;
@@ -1527,9 +1643,11 @@ GNUNET_CONFIGURATION_remove_value_filename (struct GNUNET_CONFIGURATION_Handle
         case ' ':
           end++;
           break;
+
         case '\0':
           /* illegal, but just keep it */
           break;
+
         default:
           /* illegal, but just ignore that there was a '/' */
           break;
@@ -1579,16 +1697,14 @@ static int
 parse_configuration_file (void *cls, const char *filename)
 {
   struct GNUNET_CONFIGURATION_Handle *cfg = cls;
-  char * ext;
+  char *ext;
   int ret;
 
   /* Examine file extension */
   ext = strrchr (filename, '.');
   if ((NULL == ext) || (0 != strcmp (ext, ".conf")))
   {
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                "Skipping file `%s'\n",
-                filename);
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Skipping file `%s'\n", filename);
     return GNUNET_OK;
   }
 
@@ -1607,54 +1723,11 @@ parse_configuration_file (void *cls, const char *filename)
  */
 int
 GNUNET_CONFIGURATION_load_from (struct GNUNET_CONFIGURATION_Handle *cfg,
-                               const char *defaults_d)
+                                const char *defaults_d)
 {
   if (GNUNET_SYSERR ==
       GNUNET_DISK_directory_scan (defaults_d, &parse_configuration_file, cfg))
-    return GNUNET_SYSERR;       /* no configuration at all found */
-  return GNUNET_OK;
-}
-
-
-/**
- * Load configuration (starts with defaults, then loads
- * system-specific configuration).
- *
- * @param cfg configuration to update
- * @param filename name of the configuration file, NULL to load defaults
- * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
- */
-int
-GNUNET_CONFIGURATION_load (struct GNUNET_CONFIGURATION_Handle *cfg,
-                           const char *filename)
-{
-  char *baseconfig;
-  char *ipath;
-
-  ipath = GNUNET_OS_installation_get_path (GNUNET_OS_IPK_DATADIR);
-  if (NULL == ipath)
-    return GNUNET_SYSERR;
-  baseconfig = NULL;
-  GNUNET_asprintf (&baseconfig, "%s%s", ipath, "config.d");
-  GNUNET_free (ipath);
-  if (GNUNET_SYSERR ==
-      GNUNET_DISK_directory_scan (baseconfig, &parse_configuration_file, cfg))
-  {
-    GNUNET_free (baseconfig);
-    return GNUNET_SYSERR;       /* no configuration at all found */
-  }
-  GNUNET_free (baseconfig);
-  if ((NULL != filename) &&
-      (GNUNET_OK != GNUNET_CONFIGURATION_parse (cfg, filename)))
-  {
-    /* specified configuration not found */
-    return GNUNET_SYSERR;
-  }
-  if (((GNUNET_YES !=
-        GNUNET_CONFIGURATION_have_value (cfg, "PATHS", "DEFAULTCONFIG"))) &&
-      (filename != NULL))
-    GNUNET_CONFIGURATION_set_value_string (cfg, "PATHS", "DEFAULTCONFIG",
-                                           filename);
+    return GNUNET_SYSERR; /* no configuration at all found */
   return GNUNET_OK;
 }