fix timeout of test_service, misc signed/unsigned and unused argument issues
[oweals/gnunet.git] / src / util / configuration.c
1 /*
2      This file is part of GNUnet.
3      Copyright (C) 2006, 2007, 2008, 2009, 2013 GNUnet e.V.
4
5      GNUnet is free software; you can redistribute it and/or modify
6      it under the terms of the GNU General Public License as published
7      by the Free Software Foundation; either version 3, or (at your
8      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      General Public License for more details.
14
15      You should have received a copy of the GNU General Public License
16      along with GNUnet; see the file COPYING.  If not, write to the
17      Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18      Boston, MA 02110-1301, USA.
19 */
20
21 /**
22  * @file src/util/configuration.c
23  * @brief configuration management
24  * @author Christian Grothoff
25  */
26
27 #include "platform.h"
28 #include "gnunet_crypto_lib.h"
29 #include "gnunet_strings_lib.h"
30 #include "gnunet_configuration_lib.h"
31 #include "gnunet_disk_lib.h"
32
33 #define LOG(kind,...) GNUNET_log_from (kind, "util", __VA_ARGS__)
34
35 #define LOG_STRERROR_FILE(kind,syscall,filename) GNUNET_log_from_strerror_file (kind, "util", syscall, filename)
36
37 /**
38  * @brief configuration entry
39  */
40 struct ConfigEntry
41 {
42
43   /**
44    * This is a linked list.
45    */
46   struct ConfigEntry *next;
47
48   /**
49    * key for this entry
50    */
51   char *key;
52
53   /**
54    * current, commited value
55    */
56   char *val;
57 };
58
59
60 /**
61  * @brief configuration section
62  */
63 struct ConfigSection
64 {
65   /**
66    * This is a linked list.
67    */
68   struct ConfigSection *next;
69
70   /**
71    * entries in the section
72    */
73   struct ConfigEntry *entries;
74
75   /**
76    * name of the section
77    */
78   char *name;
79 };
80
81
82 /**
83  * @brief configuration data
84  */
85 struct GNUNET_CONFIGURATION_Handle
86 {
87   /**
88    * Configuration sections.
89    */
90   struct ConfigSection *sections;
91
92   /**
93    * Modification indication since last save
94    * #GNUNET_NO if clean, #GNUNET_YES if dirty,
95    * #GNUNET_SYSERR on error (i.e. last save failed)
96    */
97   int dirty;
98
99 };
100
101
102 /**
103  * Used for diffing a configuration object against
104  * the default one
105  */
106 struct DiffHandle
107 {
108   const struct GNUNET_CONFIGURATION_Handle *cfg_default;
109
110   struct GNUNET_CONFIGURATION_Handle *cfgDiff;
111 };
112
113
114 /**
115  * Create a GNUNET_CONFIGURATION_Handle.
116  *
117  * @return fresh configuration object
118  */
119 struct GNUNET_CONFIGURATION_Handle *
120 GNUNET_CONFIGURATION_create ()
121 {
122   return GNUNET_new (struct GNUNET_CONFIGURATION_Handle);
123 }
124
125
126 /**
127  * Destroy configuration object.
128  *
129  * @param cfg configuration to destroy
130  */
131 void
132 GNUNET_CONFIGURATION_destroy (struct GNUNET_CONFIGURATION_Handle *cfg)
133 {
134   struct ConfigSection *sec;
135
136   while (NULL != (sec = cfg->sections))
137     GNUNET_CONFIGURATION_remove_section (cfg, sec->name);
138   GNUNET_free (cfg);
139 }
140
141
142 /**
143  * De-serializes configuration
144  *
145  * @param cfg configuration to update
146  * @param mem the memory block of serialized configuration
147  * @param size the size of the memory block
148  * @param basedir set to path from which we recursively load configuration
149  *          from inlined configurations; NULL if not and raise warnings
150  *          when we come across them
151  * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
152  */
153 int
154 GNUNET_CONFIGURATION_deserialize (struct GNUNET_CONFIGURATION_Handle *cfg,
155                                   const char *mem,
156                                   size_t size,
157                                   const char *basedir)
158 {
159   char *line;
160   char *line_orig;
161   size_t line_size;
162   char *pos;
163   unsigned int nr;
164   size_t r_bytes;
165   size_t to_read;
166   size_t i;
167   int emptyline;
168   int ret;
169   char *section;
170   char *eq;
171   char *tag;
172   char *value;
173
174   ret = GNUNET_OK;
175   section = GNUNET_strdup ("");
176   nr = 0;
177   r_bytes = 0;
178   line_orig = NULL;
179   while (r_bytes < size)
180   {
181     GNUNET_free_non_null (line_orig);
182     /* fgets-like behaviour on buffer */
183     to_read = size - r_bytes;
184     pos = memchr (&mem[r_bytes], '\n', to_read);
185     if (NULL == pos)
186     {
187       line_orig = GNUNET_strndup (&mem[r_bytes], line_size = to_read);
188       r_bytes += line_size;
189     }
190     else
191     {
192       line_orig = GNUNET_strndup (&mem[r_bytes], line_size = (pos - &mem[r_bytes]));
193       r_bytes += line_size + 1;
194     }
195     line = line_orig;
196     /* increment line number */
197     nr++;
198     /* tabs and '\r' are whitespace */
199     emptyline = GNUNET_YES;
200     for (i = 0; i < line_size; i++)
201     {
202       if (line[i] == '\t')
203         line[i] = ' ';
204       if (line[i] == '\r')
205         line[i] = ' ';
206       if (' ' != line[i])
207         emptyline = GNUNET_NO;
208     }
209     /* ignore empty lines */
210     if (GNUNET_YES == emptyline)
211       continue;
212
213     /* remove tailing whitespace */
214     for (i = line_size - 1; (i >= 1) && (isspace ((unsigned char) line[i]));i--)
215       line[i] = '\0';
216
217     /* remove leading whitespace */
218     for (; line[0] != '\0' && (isspace ((unsigned char) line[0])); line++);
219
220     /* ignore comments */
221     if ( ('#' == line[0]) || ('%' == line[0]) )
222       continue;
223
224     /* handle special "@INLINE@" directive */
225     if (0 == strncasecmp (line,
226                           "@INLINE@ ",
227                           strlen ("@INLINE@ ")))
228     {
229       /* @INLINE@ value */
230       value = &line[strlen ("@INLINE@ ")];
231       if (NULL != basedir)
232       {
233         char *fn;
234
235         GNUNET_asprintf (&fn,
236                          "%s/%s",
237                          basedir,
238                          value);        
239         if (GNUNET_OK !=
240             GNUNET_CONFIGURATION_parse (cfg,
241                                         fn))
242         {
243           GNUNET_free (fn);
244           ret = GNUNET_SYSERR;    /* failed to parse included config */
245           break;
246         }
247         GNUNET_free (fn);
248       }
249       else
250       {
251         LOG (GNUNET_ERROR_TYPE_DEBUG,
252              "Ignoring parsing @INLINE@ configurations, not allowed!\n");
253         ret = GNUNET_SYSERR;
254         break;
255       }
256       continue;
257     }
258     if ( ('[' == line[0]) && (']' == line[line_size - 1]) )
259     {
260       /* [value] */
261       line[line_size - 1] = '\0';
262       value = &line[1];
263       GNUNET_free (section);
264       section = GNUNET_strdup (value);
265       continue;
266     }
267     if (NULL != (eq = strchr (line, '=')))
268     {
269       /* tag = value */
270       tag = GNUNET_strndup (line, eq - line);
271       /* remove tailing whitespace */
272       for (i = strlen (tag) - 1; (i >= 1) && (isspace ((unsigned char) tag[i]));i--)
273         tag[i] = '\0';
274
275       /* Strip whitespace */
276       value = eq + 1;
277       while (isspace ((unsigned char) value[0]))
278         value++;
279       for (i = strlen (value) - 1; (i >= 1) && (isspace ((unsigned char) value[i]));i--)
280         value[i] = '\0';
281
282       /* remove quotes */
283       i = 0;
284       if ( ('"' == value[0]) &&
285            ('"' == value[strlen (value) - 1]) )
286       {
287         value[strlen (value) - 1] = '\0';
288         value++;
289       }
290       GNUNET_CONFIGURATION_set_value_string (cfg, section, tag, &value[i]);
291       GNUNET_free (tag);
292       continue;
293     }
294     /* parse error */
295     LOG (GNUNET_ERROR_TYPE_WARNING,
296          _("Syntax error while deserializing in line %u\n"),
297          nr);
298     ret = GNUNET_SYSERR;
299     break;
300   }
301   GNUNET_free_non_null (line_orig);
302   GNUNET_free (section);
303   GNUNET_assert ( (GNUNET_OK != ret) || (r_bytes == size) );
304   return ret;
305 }
306
307
308 /**
309  * Parse a configuration file, add all of the options in the
310  * file to the configuration environment.
311  *
312  * @param cfg configuration to update
313  * @param filename name of the configuration file
314  * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
315  */
316 int
317 GNUNET_CONFIGURATION_parse (struct GNUNET_CONFIGURATION_Handle *cfg,
318                             const char *filename)
319 {
320   uint64_t fs64;
321   size_t fs;
322   char *fn;
323   char *mem;
324   char *endsep;
325   int dirty;
326   int ret;
327   ssize_t sret;
328
329   fn = GNUNET_STRINGS_filename_expand (filename);
330   LOG (GNUNET_ERROR_TYPE_DEBUG,
331        "Asked to parse config file `%s'\n",
332        fn);
333   if (NULL == fn)
334     return GNUNET_SYSERR;
335   dirty = cfg->dirty;           /* back up value! */
336   if (GNUNET_SYSERR ==
337       GNUNET_DISK_file_size (fn,
338                              &fs64,
339                              GNUNET_YES,
340                              GNUNET_YES))
341   {
342     LOG (GNUNET_ERROR_TYPE_WARNING,
343          "Error while determining the file size of `%s'\n",
344          fn);
345     GNUNET_free (fn);
346     return GNUNET_SYSERR;
347   }
348   if (fs64 > SIZE_MAX)
349   {
350     GNUNET_break (0);           /* File size is more than the heap size */
351     GNUNET_free (fn);
352     return GNUNET_SYSERR;
353   }
354   fs = fs64;
355   mem = GNUNET_malloc (fs);
356   sret = GNUNET_DISK_fn_read (fn,
357                               mem,
358                               fs);
359   if ( (sret < 0) ||
360        (fs != (size_t) sret) )
361   {
362     LOG (GNUNET_ERROR_TYPE_WARNING,
363          _("Error while reading file `%s'\n"),
364          fn);
365     GNUNET_free (fn);
366     GNUNET_free (mem);
367     return GNUNET_SYSERR;
368   }
369   LOG (GNUNET_ERROR_TYPE_DEBUG,
370        "Deserializing contents of file `%s'\n",
371        fn);
372   endsep = strrchr (fn, (int) '/');
373   if (NULL != endsep)
374     *endsep = '\0';
375   ret = GNUNET_CONFIGURATION_deserialize (cfg,
376                                           mem,
377                                           fs,
378                                           fn);
379   GNUNET_free (fn);
380   GNUNET_free (mem);
381   /* restore dirty flag - anything we set in the meantime
382    * came from disk */
383   cfg->dirty = dirty;
384   return ret;
385 }
386
387
388 /**
389  * Test if there are configuration options that were
390  * changed since the last save.
391  *
392  * @param cfg configuration to inspect
393  * @return #GNUNET_NO if clean, #GNUNET_YES if dirty, #GNUNET_SYSERR on error (i.e. last save failed)
394  */
395 int
396 GNUNET_CONFIGURATION_is_dirty (const struct GNUNET_CONFIGURATION_Handle *cfg)
397 {
398   return cfg->dirty;
399 }
400
401
402 /**
403  * Serializes the given configuration.
404  *
405  * @param cfg configuration to serialize
406  * @param size will be set to the size of the serialized memory block
407  * @return the memory block where the serialized configuration is
408  *           present. This memory should be freed by the caller
409  */
410 char *
411 GNUNET_CONFIGURATION_serialize (const struct GNUNET_CONFIGURATION_Handle *cfg,
412                                 size_t *size)
413 {
414   struct ConfigSection *sec;
415   struct ConfigEntry *ent;
416   char *mem;
417   char *cbuf;
418   char *val;
419   char *pos;
420   int len;
421   size_t m_size;
422   size_t c_size;
423
424
425   /* Pass1 : calculate the buffer size required */
426   m_size = 0;
427   for (sec = cfg->sections; NULL != sec; sec = sec->next)
428   {
429     /* For each section we need to add 3 charaters: {'[',']','\n'} */
430     m_size += strlen (sec->name) + 3;
431     for (ent = sec->entries; NULL != ent; ent = ent->next)
432     {
433       if (NULL != ent->val)
434       {
435         /* if val has any '\n' then they occupy +1 character as '\n'->'\\','n' */
436         pos = ent->val;
437         while (NULL != (pos = strstr (pos, "\n")))
438         {
439           m_size++;
440           pos++;
441         }
442         /* For each key = value pair we need to add 4 characters (2
443            spaces and 1 equal-to character and 1 new line) */
444         m_size += strlen (ent->key) + strlen (ent->val) + 4;
445       }
446     }
447     /* A new line after section end */
448     m_size++;
449   }
450
451   /* Pass2: Allocate memory and write the configuration to it */
452   mem = GNUNET_malloc (m_size);
453   sec = cfg->sections;
454   c_size = 0;
455   *size = c_size;
456   while (NULL != sec)
457   {
458     len = GNUNET_asprintf (&cbuf, "[%s]\n", sec->name);
459     GNUNET_assert (0 < len);
460     GNUNET_memcpy (mem + c_size, cbuf, len);
461     c_size += len;
462     GNUNET_free (cbuf);
463     for (ent = sec->entries; NULL != ent; ent = ent->next)
464     {
465       if (NULL != ent->val)
466       {
467         val = GNUNET_malloc (strlen (ent->val) * 2 + 1);
468         strcpy (val, ent->val);
469         while (NULL != (pos = strstr (val, "\n")))
470         {
471           memmove (&pos[2], &pos[1], strlen (&pos[1]));
472           pos[0] = '\\';
473           pos[1] = 'n';
474         }
475         len = GNUNET_asprintf (&cbuf, "%s = %s\n", ent->key, val);
476         GNUNET_free (val);
477         GNUNET_memcpy (mem + c_size, cbuf, len);
478         c_size += len;
479         GNUNET_free (cbuf);
480       }
481     }
482     GNUNET_memcpy (mem + c_size, "\n", 1);
483     c_size ++;
484     sec = sec->next;
485   }
486   GNUNET_assert (c_size == m_size);
487   *size = c_size;
488   return mem;
489 }
490
491
492 /**
493  * Write configuration file.
494  *
495  * @param cfg configuration to write
496  * @param filename where to write the configuration
497  * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
498  */
499 int
500 GNUNET_CONFIGURATION_write (struct GNUNET_CONFIGURATION_Handle *cfg,
501                             const char *filename)
502 {
503   char *fn;
504   char *cfg_buf;
505   size_t size;
506   ssize_t sret;
507
508   fn = GNUNET_STRINGS_filename_expand (filename);
509   if (fn == NULL)
510     return GNUNET_SYSERR;
511   if (GNUNET_OK != GNUNET_DISK_directory_create_for_file (fn))
512   {
513     GNUNET_free (fn);
514     return GNUNET_SYSERR;
515   }
516   cfg_buf = GNUNET_CONFIGURATION_serialize (cfg, &size);
517   sret = GNUNET_DISK_fn_write (fn, cfg_buf, size,
518                                GNUNET_DISK_PERM_USER_READ
519                                | GNUNET_DISK_PERM_USER_WRITE
520                                | GNUNET_DISK_PERM_GROUP_READ
521                                | GNUNET_DISK_PERM_GROUP_WRITE);
522   if ( (sret < 0) ||
523        (size != (size_t) sret) )
524   {
525     GNUNET_free (fn);
526     GNUNET_free (cfg_buf);
527     LOG (GNUNET_ERROR_TYPE_WARNING,
528          "Writing configration to file `%s' failed\n",
529          filename);
530     cfg->dirty = GNUNET_SYSERR; /* last write failed */
531     return GNUNET_SYSERR;
532   }
533   GNUNET_free (fn);
534   GNUNET_free (cfg_buf);
535   cfg->dirty = GNUNET_NO;       /* last write succeeded */
536   return GNUNET_OK;
537 }
538
539
540 /**
541  * Iterate over all options in the configuration.
542  *
543  * @param cfg configuration to inspect
544  * @param iter function to call on each option
545  * @param iter_cls closure for @a iter
546  */
547 void
548 GNUNET_CONFIGURATION_iterate (const struct GNUNET_CONFIGURATION_Handle *cfg,
549                               GNUNET_CONFIGURATION_Iterator iter,
550                               void *iter_cls)
551 {
552   struct ConfigSection *spos;
553   struct ConfigEntry *epos;
554
555   for (spos = cfg->sections; NULL != spos; spos = spos->next)
556     for (epos = spos->entries; NULL != epos; epos = epos->next)
557       if (NULL != epos->val)
558         iter (iter_cls, spos->name, epos->key, epos->val);
559 }
560
561
562 /**
563  * Iterate over values of a section in the configuration.
564  *
565  * @param cfg configuration to inspect
566  * @param section the section
567  * @param iter function to call on each option
568  * @param iter_cls closure for @a iter
569  */
570 void
571 GNUNET_CONFIGURATION_iterate_section_values (const struct
572                                              GNUNET_CONFIGURATION_Handle *cfg,
573                                              const char *section,
574                                              GNUNET_CONFIGURATION_Iterator iter,
575                                              void *iter_cls)
576 {
577   struct ConfigSection *spos;
578   struct ConfigEntry *epos;
579
580   spos = cfg->sections;
581   while ((spos != NULL) && (0 != strcasecmp (spos->name, section)))
582     spos = spos->next;
583   if (NULL == spos)
584     return;
585   for (epos = spos->entries; NULL != epos; epos = epos->next)
586     if (NULL != epos->val)
587       iter (iter_cls, spos->name, epos->key, epos->val);
588 }
589
590
591 /**
592  * Iterate over all sections in the configuration.
593  *
594  * @param cfg configuration to inspect
595  * @param iter function to call on each section
596  * @param iter_cls closure for @a iter
597  */
598 void
599 GNUNET_CONFIGURATION_iterate_sections (const struct GNUNET_CONFIGURATION_Handle *cfg,
600                                        GNUNET_CONFIGURATION_Section_Iterator iter,
601                                        void *iter_cls)
602 {
603   struct ConfigSection *spos;
604   struct ConfigSection *next;
605
606   next = cfg->sections;
607   while (next != NULL)
608   {
609     spos = next;
610     next = spos->next;
611     iter (iter_cls, spos->name);
612   }
613 }
614
615
616 /**
617  * Remove the given section and all options in it.
618  *
619  * @param cfg configuration to inspect
620  * @param section name of the section to remove
621  */
622 void
623 GNUNET_CONFIGURATION_remove_section (struct GNUNET_CONFIGURATION_Handle *cfg,
624                                      const char *section)
625 {
626   struct ConfigSection *spos;
627   struct ConfigSection *prev;
628   struct ConfigEntry *ent;
629
630   prev = NULL;
631   spos = cfg->sections;
632   while (NULL != spos)
633   {
634     if (0 == strcasecmp (section, spos->name))
635     {
636       if (NULL == prev)
637         cfg->sections = spos->next;
638       else
639         prev->next = spos->next;
640       while (NULL != (ent = spos->entries))
641       {
642         spos->entries = ent->next;
643         GNUNET_free (ent->key);
644         GNUNET_free_non_null (ent->val);
645         GNUNET_free (ent);
646         cfg->dirty = GNUNET_YES;
647       }
648       GNUNET_free (spos->name);
649       GNUNET_free (spos);
650       return;
651     }
652     prev = spos;
653     spos = spos->next;
654   }
655 }
656
657
658 /**
659  * Copy a configuration value to the given target configuration.
660  * Overwrites existing entries.
661  *
662  * @param cls the destination configuration (`struct GNUNET_CONFIGURATION_Handle *`)
663  * @param section section for the value
664  * @param option option name of the value
665  * @param value value to copy
666  */
667 static void
668 copy_entry (void *cls,
669             const char *section,
670             const char *option,
671             const char *value)
672 {
673   struct GNUNET_CONFIGURATION_Handle *dst = cls;
674
675   GNUNET_CONFIGURATION_set_value_string (dst, section, option, value);
676 }
677
678
679 /**
680  * Duplicate an existing configuration object.
681  *
682  * @param cfg configuration to duplicate
683  * @return duplicate configuration
684  */
685 struct GNUNET_CONFIGURATION_Handle *
686 GNUNET_CONFIGURATION_dup (const struct GNUNET_CONFIGURATION_Handle *cfg)
687 {
688   struct GNUNET_CONFIGURATION_Handle *ret;
689
690   ret = GNUNET_CONFIGURATION_create ();
691   GNUNET_CONFIGURATION_iterate (cfg, &copy_entry, ret);
692   return ret;
693 }
694
695
696 /**
697  * Find a section entry from a configuration.
698  *
699  * @param cfg configuration to search in
700  * @param section name of the section to look for
701  * @return matching entry, NULL if not found
702  */
703 static struct ConfigSection *
704 find_section (const struct GNUNET_CONFIGURATION_Handle *cfg,
705               const char *section)
706 {
707   struct ConfigSection *pos;
708
709   pos = cfg->sections;
710   while ((pos != NULL) && (0 != strcasecmp (section, pos->name)))
711     pos = pos->next;
712   return pos;
713 }
714
715
716 /**
717  * Find an entry from a configuration.
718  *
719  * @param cfg handle to the configuration
720  * @param section section the option is in
721  * @param key the option
722  * @return matching entry, NULL if not found
723  */
724 static struct ConfigEntry *
725 find_entry (const struct GNUNET_CONFIGURATION_Handle *cfg,
726            const char *section,
727            const char *key)
728 {
729   struct ConfigSection *sec;
730   struct ConfigEntry *pos;
731
732   if (NULL == (sec = find_section (cfg, section)))
733     return NULL;
734   pos = sec->entries;
735   while ((pos != NULL) && (0 != strcasecmp (key, pos->key)))
736     pos = pos->next;
737   return pos;
738 }
739
740
741 /**
742  * A callback function, compares entries from two configurations
743  * (default against a new configuration) and write the diffs in a
744  * diff-configuration object (the callback object).
745  *
746  * @param cls the diff configuration (`struct DiffHandle *`)
747  * @param section section for the value (of the default conf.)
748  * @param option option name of the value (of the default conf.)
749  * @param value value to copy (of the default conf.)
750  */
751 static void
752 compare_entries (void *cls,
753                  const char *section,
754                  const char *option,
755                  const char *value)
756 {
757   struct DiffHandle *dh = cls;
758   struct ConfigEntry *entNew;
759
760   entNew = find_entry (dh->cfg_default, section, option);
761   if ( (NULL != entNew) &&
762        (NULL != entNew->val) &&
763        (0 == strcmp (entNew->val, value)) )
764     return;
765   GNUNET_CONFIGURATION_set_value_string (dh->cfgDiff, section, option, value);
766 }
767
768
769 /**
770  * Compute configuration with only entries that have been changed
771  *
772  * @param cfg_default original configuration
773  * @param cfg_new new configuration
774  * @return configuration with only the differences, never NULL
775  */
776 struct GNUNET_CONFIGURATION_Handle *
777 GNUNET_CONFIGURATION_get_diff (const struct GNUNET_CONFIGURATION_Handle *cfg_default,
778                                const struct GNUNET_CONFIGURATION_Handle *cfg_new)
779 {
780   struct DiffHandle diffHandle;
781
782   diffHandle.cfgDiff = GNUNET_CONFIGURATION_create ();
783   diffHandle.cfg_default = cfg_default;
784   GNUNET_CONFIGURATION_iterate (cfg_new, &compare_entries, &diffHandle);
785   return diffHandle.cfgDiff;
786 }
787
788
789 /**
790  * Write only configuration entries that have been changed to configuration file
791  *
792  * @param cfg_default default configuration
793  * @param cfg_new new configuration
794  * @param filename where to write the configuration diff between default and new
795  * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
796  */
797 int
798 GNUNET_CONFIGURATION_write_diffs (const struct GNUNET_CONFIGURATION_Handle
799                                   *cfg_default,
800                                   const struct GNUNET_CONFIGURATION_Handle
801                                   *cfg_new, const char *filename)
802 {
803   int ret;
804   struct GNUNET_CONFIGURATION_Handle *diff;
805
806   diff = GNUNET_CONFIGURATION_get_diff (cfg_default, cfg_new);
807   ret = GNUNET_CONFIGURATION_write (diff, filename);
808   GNUNET_CONFIGURATION_destroy (diff);
809   return ret;
810 }
811
812
813 /**
814  * Set a configuration value that should be a string.
815  *
816  * @param cfg configuration to update
817  * @param section section of interest
818  * @param option option of interest
819  * @param value value to set
820  */
821 void
822 GNUNET_CONFIGURATION_set_value_string (struct GNUNET_CONFIGURATION_Handle *cfg,
823                                        const char *section, const char *option,
824                                        const char *value)
825 {
826   struct ConfigSection *sec;
827   struct ConfigEntry *e;
828   char *nv;
829
830   e = find_entry (cfg, section, option);
831   if (NULL != e)
832   {
833     if (NULL == value)
834     {
835       GNUNET_free_non_null (e->val);
836       e->val = NULL;
837     }
838     else
839     {
840       nv = GNUNET_strdup (value);
841       GNUNET_free_non_null (e->val);
842       e->val = nv;
843     }
844     return;
845   }
846   sec = find_section (cfg, section);
847   if (sec == NULL)
848   {
849     sec = GNUNET_new (struct ConfigSection);
850     sec->name = GNUNET_strdup (section);
851     sec->next = cfg->sections;
852     cfg->sections = sec;
853   }
854   e = GNUNET_new (struct ConfigEntry);
855   e->key = GNUNET_strdup (option);
856   e->val = GNUNET_strdup (value);
857   e->next = sec->entries;
858   sec->entries = e;
859 }
860
861
862 /**
863  * Set a configuration value that should be a number.
864  *
865  * @param cfg configuration to update
866  * @param section section of interest
867  * @param option option of interest
868  * @param number value to set
869  */
870 void
871 GNUNET_CONFIGURATION_set_value_number (struct GNUNET_CONFIGURATION_Handle *cfg,
872                                        const char *section,
873                                        const char *option,
874                                        unsigned long long number)
875 {
876   char s[64];
877
878   GNUNET_snprintf (s,
879                    64,
880                    "%llu",
881                    number);
882   GNUNET_CONFIGURATION_set_value_string (cfg,
883                                          section,
884                                          option,
885                                          s);
886 }
887
888
889 /**
890  * Get a configuration value that should be a number.
891  *
892  * @param cfg configuration to inspect
893  * @param section section of interest
894  * @param option option of interest
895  * @param number where to store the numeric value of the option
896  * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
897  */
898 int
899 GNUNET_CONFIGURATION_get_value_number (const struct GNUNET_CONFIGURATION_Handle
900                                        *cfg, const char *section,
901                                        const char *option,
902                                        unsigned long long *number)
903 {
904   struct ConfigEntry *e;
905
906   if (NULL == (e = find_entry (cfg, section, option)))
907     return GNUNET_SYSERR;
908   if (NULL == e->val)
909     return GNUNET_SYSERR;
910   if (1 != SSCANF (e->val, "%llu", number))
911     return GNUNET_SYSERR;
912   return GNUNET_OK;
913 }
914
915 /**
916  * Get a configuration value that should be a floating point number.
917  *
918  * @param cfg configuration to inspect
919  * @param section section of interest
920  * @param option option of interest
921  * @param number where to store the floating value of the option
922  * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
923  */
924 int
925 GNUNET_CONFIGURATION_get_value_float  (const struct GNUNET_CONFIGURATION_Handle
926                                        *cfg, const char *section,
927                                        const char *option,
928                                        float *number)
929 {
930   struct ConfigEntry *e;
931
932   if (NULL == (e = find_entry (cfg, section, option)))
933     return GNUNET_SYSERR;
934   if (NULL == e->val)
935     return GNUNET_SYSERR;
936   if (1 != SSCANF (e->val, "%f", number))
937     return GNUNET_SYSERR;
938   return GNUNET_OK;
939 }
940
941
942
943 /**
944  * Get a configuration value that should be a relative time.
945  *
946  * @param cfg configuration to inspect
947  * @param section section of interest
948  * @param option option of interest
949  * @param time set to the time value stored in the configuration
950  * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
951  */
952 int
953 GNUNET_CONFIGURATION_get_value_time (const struct GNUNET_CONFIGURATION_Handle *cfg,
954                                      const char *section,
955                                      const char *option,
956                                      struct GNUNET_TIME_Relative *time)
957 {
958   struct ConfigEntry *e;
959
960   if (NULL == (e = find_entry (cfg, section, option)))
961     return GNUNET_SYSERR;
962   if (NULL == e->val)
963     return GNUNET_SYSERR;
964   return GNUNET_STRINGS_fancy_time_to_relative (e->val, time);
965 }
966
967
968 /**
969  * Get a configuration value that should be a size in bytes.
970  *
971  * @param cfg configuration to inspect
972  * @param section section of interest
973  * @param option option of interest
974  * @param size set to the size in bytes as stored in the configuration
975  * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
976  */
977 int
978 GNUNET_CONFIGURATION_get_value_size (const struct GNUNET_CONFIGURATION_Handle *cfg,
979                                      const char *section,
980                                      const char *option,
981                                      unsigned long long *size)
982 {
983   struct ConfigEntry *e;
984
985   if (NULL == (e = find_entry (cfg, section, option)))
986     return GNUNET_SYSERR;
987   if (NULL == e->val)
988     return GNUNET_SYSERR;
989   return GNUNET_STRINGS_fancy_size_to_bytes (e->val, size);
990 }
991
992
993 /**
994  * Get a configuration value that should be a string.
995  *
996  * @param cfg configuration to inspect
997  * @param section section of interest
998  * @param option option of interest
999  * @param value will be set to a freshly allocated configuration
1000  *        value, or NULL if option is not specified
1001  * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
1002  */
1003 int
1004 GNUNET_CONFIGURATION_get_value_string (const struct GNUNET_CONFIGURATION_Handle *cfg,
1005                                        const char *section,
1006                                        const char *option,
1007                                        char **value)
1008 {
1009   struct ConfigEntry *e;
1010
1011   if ( (NULL == (e = find_entry (cfg, section, option))) ||
1012        (NULL == e->val) )
1013   {
1014     *value = NULL;
1015     return GNUNET_SYSERR;
1016   }
1017   *value = GNUNET_strdup (e->val);
1018   return GNUNET_OK;
1019 }
1020
1021
1022 /**
1023  * Get a configuration value that should be in a set of
1024  * predefined strings
1025  *
1026  * @param cfg configuration to inspect
1027  * @param section section of interest
1028  * @param option option of interest
1029  * @param choices NULL-terminated list of legal values
1030  * @param value will be set to an entry in the legal list,
1031  *        or NULL if option is not specified and no default given
1032  * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
1033  */
1034 int
1035 GNUNET_CONFIGURATION_get_value_choice (const struct GNUNET_CONFIGURATION_Handle *cfg,
1036                                        const char *section,
1037                                        const char *option,
1038                                        const char *const *choices,
1039                                        const char **value)
1040 {
1041   struct ConfigEntry *e;
1042   unsigned int i;
1043
1044   if (NULL == (e = find_entry (cfg, section, option)))
1045     return GNUNET_SYSERR;
1046   for (i = 0; NULL != choices[i]; i++)
1047     if (0 == strcasecmp (choices[i], e->val))
1048       break;
1049   if (NULL == choices[i])
1050   {
1051     LOG (GNUNET_ERROR_TYPE_ERROR,
1052          _("Configuration value '%s' for '%s'"
1053            " in section '%s' is not in set of legal choices\n"),
1054          e->val,
1055          option,
1056          section);
1057     return GNUNET_SYSERR;
1058   }
1059   *value = choices[i];
1060   return GNUNET_OK;
1061 }
1062
1063
1064 /**
1065  * Get crockford32-encoded fixed-size binary data from a configuration.
1066  *
1067  * @param cfg configuration to access
1068  * @param section section to access
1069  * @param option option to access
1070  * @param buf where to store the decoded binary result
1071  * @param buf_size exact number of bytes to store in @a buf
1072  * @return #GNUNET_OK on success
1073  *         #GNUNET_NO is the value does not exist
1074  *         #GNUNET_SYSERR on decoding error
1075  */
1076 int
1077 GNUNET_CONFIGURATION_get_data (const struct GNUNET_CONFIGURATION_Handle *cfg,
1078                                const char *section,
1079                                const char *option,
1080                                void *buf,
1081                                size_t buf_size)
1082 {
1083   char *enc;
1084   int res;
1085   size_t data_size;
1086
1087   if (GNUNET_OK !=
1088       (res = GNUNET_CONFIGURATION_get_value_string (cfg,
1089                                                     section,
1090                                                     option,
1091                                                     &enc)))
1092     return res;
1093   data_size = (strlen (enc) * 5) / 8;
1094   if (data_size != buf_size)
1095   {
1096     GNUNET_free (enc);
1097     return GNUNET_SYSERR;
1098   }
1099   if (GNUNET_OK !=
1100       GNUNET_STRINGS_string_to_data (enc,
1101                                      strlen (enc),
1102                                      buf, buf_size))
1103   {
1104     GNUNET_free (enc);
1105     return GNUNET_SYSERR;
1106   }
1107   GNUNET_free (enc);
1108   return GNUNET_OK;
1109 }
1110
1111
1112 /**
1113  * Test if we have a value for a particular option
1114  *
1115  * @param cfg configuration to inspect
1116  * @param section section of interest
1117  * @param option option of interest
1118  * @return #GNUNET_YES if so, #GNUNET_NO if not.
1119  */
1120 int
1121 GNUNET_CONFIGURATION_have_value (const struct GNUNET_CONFIGURATION_Handle *cfg,
1122                                  const char *section,
1123                                  const char *option)
1124 {
1125   struct ConfigEntry *e;
1126
1127   if ((NULL == (e = find_entry (cfg, section, option))) || (NULL == e->val))
1128     return GNUNET_NO;
1129   return GNUNET_YES;
1130 }
1131
1132
1133 /**
1134  * Expand an expression of the form "$FOO/BAR" to "DIRECTORY/BAR"
1135  * where either in the "PATHS" section or the environtment "FOO" is
1136  * set to "DIRECTORY".  We also support default expansion,
1137  * i.e. ${VARIABLE:-default} will expand to $VARIABLE if VARIABLE is
1138  * set in PATHS or the environment, and otherwise to "default".  Note
1139  * that "default" itself can also be a $-expression, thus
1140  * "${VAR1:-{$VAR2}}" will expand to VAR1 and if that is not defined
1141  * to VAR2.
1142  *
1143  * @param cfg configuration to use for path expansion
1144  * @param orig string to $-expand (will be freed!)
1145  * @param depth recursion depth, used to detect recursive expansions
1146  * @return $-expanded string
1147  */
1148 static char *
1149 expand_dollar (const struct GNUNET_CONFIGURATION_Handle *cfg,
1150                char *orig,
1151                unsigned int depth)
1152 {
1153   int i;
1154   char *prefix;
1155   char *result;
1156   char *start;
1157   const char *post;
1158   const char *env;
1159   char *def;
1160   char *end;
1161   unsigned int lopen;
1162   char erased_char;
1163   char *erased_pos;
1164   size_t len;
1165
1166   if (NULL == orig)
1167     return NULL;
1168   if (depth > 128)
1169   {
1170     LOG (GNUNET_ERROR_TYPE_WARNING,
1171          _("Recursive expansion suspected, aborting $-expansion for term `%s'\n"),
1172          orig);
1173     return orig;
1174   }
1175   LOG (GNUNET_ERROR_TYPE_DEBUG,
1176        "Asked to $-expand %s\n",
1177        orig);
1178   if ('$' != orig[0])
1179   {
1180     LOG (GNUNET_ERROR_TYPE_DEBUG,
1181          "Doesn't start with $ - not expanding\n");
1182     return orig;
1183   }
1184   erased_char = 0;
1185   erased_pos = NULL;
1186   if ('{' == orig[1])
1187   {
1188     start = &orig[2];
1189     lopen = 1;
1190     end = &orig[1];
1191     while (lopen > 0)
1192     {
1193       end++;
1194       switch (*end)
1195       {
1196       case '}':
1197         lopen--;
1198         break;
1199       case '{':
1200         lopen++;
1201         break;
1202       case '\0':
1203         LOG (GNUNET_ERROR_TYPE_WARNING,
1204              _("Missing closing `%s' in option `%s'\n"),
1205              "}",
1206              orig);
1207         return orig;
1208       default:
1209         break;
1210       }
1211     }
1212     erased_char = *end;
1213     erased_pos = end;
1214     *end = '\0';
1215     post = end + 1;
1216     def = strchr (orig, ':');
1217     if (NULL != def)
1218     {
1219       *def = '\0';
1220       def++;
1221       if ( ('-' == *def) ||
1222            ('=' == *def) )
1223         def++;
1224       def = GNUNET_strdup (def);
1225     }
1226   }
1227   else
1228   {
1229     start = &orig[1];
1230     def = NULL;
1231     i = 0;
1232     while ( (orig[i] != '/') &&
1233             (orig[i] != '\\') &&
1234             (orig[i] != '\0')  &&
1235             (orig[i] != ' ') )
1236       i++;
1237     if (orig[i] == '\0')
1238     {
1239       post = "";
1240     }
1241     else
1242     {
1243       erased_char = orig[i];
1244       erased_pos = &orig[i];
1245       orig[i] = '\0';
1246       post = &orig[i + 1];
1247     }
1248   }
1249   LOG (GNUNET_ERROR_TYPE_DEBUG,
1250        "Split into `%s' and `%s' with default %s\n",
1251        start,
1252        post,
1253        def);
1254   if (GNUNET_OK !=
1255       GNUNET_CONFIGURATION_get_value_string (cfg,
1256                                              "PATHS",
1257                                              start,
1258                                              &prefix))
1259   {
1260     if (NULL == (env = getenv (start)))
1261     {
1262       /* try default */
1263       def = expand_dollar (cfg, def, depth + 1);
1264       env = def;
1265     }
1266     if (NULL == env)
1267     {
1268       start = GNUNET_strdup (start);
1269       if (erased_pos)
1270         *erased_pos = erased_char;
1271       LOG (GNUNET_ERROR_TYPE_WARNING,
1272            _("Failed to expand `%s' in `%s' as it is neither found in [PATHS] nor defined as an environmental variable\n"),
1273            start, orig);
1274       GNUNET_free (start);
1275       return orig;
1276     }
1277     prefix = GNUNET_strdup (env);
1278   }
1279   prefix = GNUNET_CONFIGURATION_expand_dollar (cfg, prefix);
1280   if ( (erased_pos) && ('}' != erased_char) )
1281   {
1282     len = strlen (prefix) + 1;
1283     prefix = GNUNET_realloc (prefix, len + 1);
1284     prefix[len - 1] = erased_char;
1285     prefix[len] = '\0';
1286   }
1287   result = GNUNET_malloc (strlen (prefix) + strlen (post) + 1);
1288   strcpy (result, prefix);
1289   strcat (result, post);
1290   GNUNET_free_non_null (def);
1291   GNUNET_free (prefix);
1292   GNUNET_free (orig);
1293   return result;
1294 }
1295
1296
1297 /**
1298  * Expand an expression of the form "$FOO/BAR" to "DIRECTORY/BAR"
1299  * where either in the "PATHS" section or the environtment "FOO" is
1300  * set to "DIRECTORY".  We also support default expansion,
1301  * i.e. ${VARIABLE:-default} will expand to $VARIABLE if VARIABLE is
1302  * set in PATHS or the environment, and otherwise to "default".  Note
1303  * that "default" itself can also be a $-expression, thus
1304  * "${VAR1:-{$VAR2}}" will expand to VAR1 and if that is not defined
1305  * to VAR2.
1306  *
1307  * @param cfg configuration to use for path expansion
1308  * @param orig string to $-expand (will be freed!).  Note that multiple
1309  *          $-expressions can be present in this string.  They will all be
1310  *          $-expanded.
1311  * @return $-expanded string
1312  */
1313 char *
1314 GNUNET_CONFIGURATION_expand_dollar (const struct GNUNET_CONFIGURATION_Handle *cfg,
1315                                     char *orig)
1316 {
1317   char *dup;
1318   size_t i;
1319   size_t len;
1320
1321   for (i = 0; '\0' != orig[i]; i++)
1322   {
1323     if ('$' != orig[i])
1324       continue;
1325     dup = GNUNET_strdup (orig + i);
1326     dup = expand_dollar (cfg, dup, 0);
1327     len = strlen (dup) + 1;
1328     orig = GNUNET_realloc (orig, i + len);
1329     GNUNET_memcpy (orig + i, dup, len);
1330     GNUNET_free (dup);
1331   }
1332   return orig;
1333 }
1334
1335
1336 /**
1337  * Get a configuration value that should be a string.
1338  *
1339  * @param cfg configuration to inspect
1340  * @param section section of interest
1341  * @param option option of interest
1342  * @param value will be set to a freshly allocated configuration
1343  *        value, or NULL if option is not specified
1344  * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
1345  */
1346 int
1347 GNUNET_CONFIGURATION_get_value_filename (const struct GNUNET_CONFIGURATION_Handle *cfg,
1348                                          const char *section,
1349                                          const char *option,
1350                                          char **value)
1351 {
1352   char *tmp;
1353
1354   if (GNUNET_OK !=
1355       GNUNET_CONFIGURATION_get_value_string (cfg, section, option, &tmp))
1356   {
1357     LOG (GNUNET_ERROR_TYPE_DEBUG,
1358          "Failed to retrieve filename\n");
1359     *value = NULL;
1360     return GNUNET_SYSERR;
1361   }
1362   tmp = GNUNET_CONFIGURATION_expand_dollar (cfg, tmp);
1363   *value = GNUNET_STRINGS_filename_expand (tmp);
1364   GNUNET_free (tmp);
1365   if (*value == NULL)
1366     return GNUNET_SYSERR;
1367   return GNUNET_OK;
1368 }
1369
1370
1371 /**
1372  * Get a configuration value that should be in a set of
1373  * "YES" or "NO".
1374  *
1375  * @param cfg configuration to inspect
1376  * @param section section of interest
1377  * @param option option of interest
1378  * @return #GNUNET_YES, #GNUNET_NO or #GNUNET_SYSERR
1379  */
1380 int
1381 GNUNET_CONFIGURATION_get_value_yesno (const struct GNUNET_CONFIGURATION_Handle *cfg,
1382                                       const char *section,
1383                                       const char *option)
1384 {
1385   static const char *yesno[] = { "YES", "NO", NULL };
1386   const char *val;
1387   int ret;
1388
1389   ret =
1390       GNUNET_CONFIGURATION_get_value_choice (cfg, section, option, yesno, &val);
1391   if (ret == GNUNET_SYSERR)
1392     return ret;
1393   if (val == yesno[0])
1394     return GNUNET_YES;
1395   return GNUNET_NO;
1396 }
1397
1398
1399 /**
1400  * Iterate over the set of filenames stored in a configuration value.
1401  *
1402  * @param cfg configuration to inspect
1403  * @param section section of interest
1404  * @param option option of interest
1405  * @param cb function to call on each filename
1406  * @param cb_cls closure for @a cb
1407  * @return number of filenames iterated over, -1 on error
1408  */
1409 int
1410 GNUNET_CONFIGURATION_iterate_value_filenames (const struct GNUNET_CONFIGURATION_Handle *cfg,
1411                                               const char *section,
1412                                               const char *option,
1413                                               GNUNET_FileNameCallback cb,
1414                                               void *cb_cls)
1415 {
1416   char *list;
1417   char *pos;
1418   char *end;
1419   char old;
1420   int ret;
1421
1422   if (GNUNET_OK !=
1423       GNUNET_CONFIGURATION_get_value_string (cfg, section, option, &list))
1424     return 0;
1425   GNUNET_assert (list != NULL);
1426   ret = 0;
1427   pos = list;
1428   while (1)
1429   {
1430     while (pos[0] == ' ')
1431       pos++;
1432     if (strlen (pos) == 0)
1433       break;
1434     end = pos + 1;
1435     while ((end[0] != ' ') && (end[0] != '\0'))
1436     {
1437       if (end[0] == '\\')
1438       {
1439         switch (end[1])
1440         {
1441         case '\\':
1442         case ' ':
1443           memmove (end, &end[1], strlen (&end[1]) + 1);
1444         case '\0':
1445           /* illegal, but just keep it */
1446           break;
1447         default:
1448           /* illegal, but just ignore that there was a '/' */
1449           break;
1450         }
1451       }
1452       end++;
1453     }
1454     old = end[0];
1455     end[0] = '\0';
1456     if (strlen (pos) > 0)
1457     {
1458       ret++;
1459       if ((cb != NULL) && (GNUNET_OK != cb (cb_cls, pos)))
1460       {
1461         ret = GNUNET_SYSERR;
1462         break;
1463       }
1464     }
1465     if (old == '\0')
1466       break;
1467     pos = end + 1;
1468   }
1469   GNUNET_free (list);
1470   return ret;
1471 }
1472
1473
1474 /**
1475  * FIXME.
1476  *
1477  * @param value FIXME
1478  * @return FIXME
1479  */
1480 static char *
1481 escape_name (const char *value)
1482 {
1483   char *escaped;
1484   const char *rpos;
1485   char *wpos;
1486
1487   escaped = GNUNET_malloc (strlen (value) * 2 + 1);
1488   memset (escaped, 0, strlen (value) * 2 + 1);
1489   rpos = value;
1490   wpos = escaped;
1491   while (rpos[0] != '\0')
1492   {
1493     switch (rpos[0])
1494     {
1495     case '\\':
1496     case ' ':
1497       wpos[0] = '\\';
1498       wpos[1] = rpos[0];
1499       wpos += 2;
1500       break;
1501     default:
1502       wpos[0] = rpos[0];
1503       wpos++;
1504     }
1505     rpos++;
1506   }
1507   return escaped;
1508 }
1509
1510
1511 /**
1512  * FIXME.
1513  *
1514  * @param cls string we compare with (const char*)
1515  * @param fn filename we are currently looking at
1516  * @return #GNUNET_OK if the names do not match, #GNUNET_SYSERR if they do
1517  */
1518 static int
1519 test_match (void *cls, const char *fn)
1520 {
1521   const char *of = cls;
1522
1523   return (0 == strcmp (of, fn)) ? GNUNET_SYSERR : GNUNET_OK;
1524 }
1525
1526
1527 /**
1528  * Append a filename to a configuration value that
1529  * represents a list of filenames
1530  *
1531  * @param cfg configuration to update
1532  * @param section section of interest
1533  * @param option option of interest
1534  * @param value filename to append
1535  * @return #GNUNET_OK on success,
1536  *         #GNUNET_NO if the filename already in the list
1537  *         #GNUNET_SYSERR on error
1538  */
1539 int
1540 GNUNET_CONFIGURATION_append_value_filename (struct GNUNET_CONFIGURATION_Handle *cfg,
1541                                             const char *section,
1542                                             const char *option,
1543                                             const char *value)
1544 {
1545   char *escaped;
1546   char *old;
1547   char *nw;
1548
1549   if (GNUNET_SYSERR ==
1550       GNUNET_CONFIGURATION_iterate_value_filenames (cfg, section, option,
1551                                                     &test_match,
1552                                                     (void *) value))
1553     return GNUNET_NO;           /* already exists */
1554   if (GNUNET_OK !=
1555       GNUNET_CONFIGURATION_get_value_string (cfg, section, option, &old))
1556     old = GNUNET_strdup ("");
1557   escaped = escape_name (value);
1558   nw = GNUNET_malloc (strlen (old) + strlen (escaped) + 2);
1559   strcpy (nw, old);
1560   if (strlen (old) > 0)
1561     strcat (nw, " ");
1562   strcat (nw, escaped);
1563   GNUNET_CONFIGURATION_set_value_string (cfg, section, option, nw);
1564   GNUNET_free (old);
1565   GNUNET_free (nw);
1566   GNUNET_free (escaped);
1567   return GNUNET_OK;
1568 }
1569
1570
1571 /**
1572  * Remove a filename from a configuration value that
1573  * represents a list of filenames
1574  *
1575  * @param cfg configuration to update
1576  * @param section section of interest
1577  * @param option option of interest
1578  * @param value filename to remove
1579  * @return #GNUNET_OK on success,
1580  *         #GNUNET_NO if the filename is not in the list,
1581  *         #GNUNET_SYSERR on error
1582  */
1583 int
1584 GNUNET_CONFIGURATION_remove_value_filename (struct GNUNET_CONFIGURATION_Handle
1585                                             *cfg, const char *section,
1586                                             const char *option,
1587                                             const char *value)
1588 {
1589   char *list;
1590   char *pos;
1591   char *end;
1592   char *match;
1593   char old;
1594
1595   if (GNUNET_OK !=
1596       GNUNET_CONFIGURATION_get_value_string (cfg, section, option, &list))
1597     return GNUNET_NO;
1598   match = escape_name (value);
1599   pos = list;
1600   while (1)
1601   {
1602     while (pos[0] == ' ')
1603       pos++;
1604     if (strlen (pos) == 0)
1605       break;
1606     end = pos + 1;
1607     while ((end[0] != ' ') && (end[0] != '\0'))
1608     {
1609       if (end[0] == '\\')
1610       {
1611         switch (end[1])
1612         {
1613         case '\\':
1614         case ' ':
1615           end++;
1616           break;
1617         case '\0':
1618           /* illegal, but just keep it */
1619           break;
1620         default:
1621           /* illegal, but just ignore that there was a '/' */
1622           break;
1623         }
1624       }
1625       end++;
1626     }
1627     old = end[0];
1628     end[0] = '\0';
1629     if (0 == strcmp (pos, match))
1630     {
1631       if (old != '\0')
1632         memmove (pos, &end[1], strlen (&end[1]) + 1);
1633       else
1634       {
1635         if (pos != list)
1636           pos[-1] = '\0';
1637         else
1638           pos[0] = '\0';
1639       }
1640       GNUNET_CONFIGURATION_set_value_string (cfg, section, option, list);
1641       GNUNET_free (list);
1642       GNUNET_free (match);
1643       return GNUNET_OK;
1644     }
1645     if (old == '\0')
1646       break;
1647     end[0] = old;
1648     pos = end + 1;
1649   }
1650   GNUNET_free (list);
1651   GNUNET_free (match);
1652   return GNUNET_NO;
1653 }
1654
1655
1656 /**
1657  * Wrapper around #GNUNET_CONFIGURATION_parse.  Called on each
1658  * file in a directory, we trigger parsing on those files that
1659  * end with ".conf".
1660  *
1661  * @param cls the cfg
1662  * @param filename file to parse
1663  * @return #GNUNET_OK on success
1664  */
1665 static int
1666 parse_configuration_file (void *cls, const char *filename)
1667 {
1668   struct GNUNET_CONFIGURATION_Handle *cfg = cls;
1669   char * ext;
1670   int ret;
1671
1672   /* Examine file extension */
1673   ext = strrchr (filename, '.');
1674   if ((NULL == ext) || (0 != strcmp (ext, ".conf")))
1675   {
1676     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1677                 "Skipping file `%s'\n",
1678                 filename);
1679     return GNUNET_OK;
1680   }
1681
1682   ret = GNUNET_CONFIGURATION_parse (cfg, filename);
1683   return ret;
1684 }
1685
1686
1687 /**
1688  * Load default configuration.  This function will parse the
1689  * defaults from the given defaults_d directory.
1690  *
1691  * @param cfg configuration to update
1692  * @param defaults_d directory with the defaults
1693  * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
1694  */
1695 int
1696 GNUNET_CONFIGURATION_load_from (struct GNUNET_CONFIGURATION_Handle *cfg,
1697                                 const char *defaults_d)
1698 {
1699   if (GNUNET_SYSERR ==
1700       GNUNET_DISK_directory_scan (defaults_d, &parse_configuration_file, cfg))
1701     return GNUNET_SYSERR;       /* no configuration at all found */
1702   return GNUNET_OK;
1703 }
1704
1705
1706 /* end of configuration.c */