Merge branch 'master' of git+ssh://gnunet.org/gnunet
[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   /* Pass1 : calculate the buffer size required */
425   m_size = 0;
426   for (sec = cfg->sections; NULL != sec; sec = sec->next)
427   {
428     /* For each section we need to add 3 charaters: {'[',']','\n'} */
429     m_size += strlen (sec->name) + 3;
430     for (ent = sec->entries; NULL != ent; ent = ent->next)
431     {
432       if (NULL != ent->val)
433       {
434         /* if val has any '\n' then they occupy +1 character as '\n'->'\\','n' */
435         pos = ent->val;
436         while (NULL != (pos = strstr (pos, "\n")))
437         {
438           m_size++;
439           pos++;
440         }
441         /* For each key = value pair we need to add 4 characters (2
442            spaces and 1 equal-to character and 1 new line) */
443         m_size += strlen (ent->key) + strlen (ent->val) + 4;
444       }
445     }
446     /* A new line after section end */
447     m_size++;
448   }
449
450   /* Pass2: Allocate memory and write the configuration to it */
451   mem = GNUNET_malloc (m_size);
452   sec = cfg->sections;
453   c_size = 0;
454   *size = c_size;
455   while (NULL != sec)
456   {
457     len = GNUNET_asprintf (&cbuf, "[%s]\n", sec->name);
458     GNUNET_assert (0 < len);
459     GNUNET_memcpy (mem + c_size, cbuf, len);
460     c_size += len;
461     GNUNET_free (cbuf);
462     for (ent = sec->entries; NULL != ent; ent = ent->next)
463     {
464       if (NULL != ent->val)
465       {
466         val = GNUNET_malloc (strlen (ent->val) * 2 + 1);
467         strcpy (val, ent->val);
468         while (NULL != (pos = strstr (val, "\n")))
469         {
470           memmove (&pos[2], &pos[1], strlen (&pos[1]));
471           pos[0] = '\\';
472           pos[1] = 'n';
473         }
474         len = GNUNET_asprintf (&cbuf, "%s = %s\n", ent->key, val);
475         GNUNET_free (val);
476         GNUNET_memcpy (mem + c_size, cbuf, len);
477         c_size += len;
478         GNUNET_free (cbuf);
479       }
480     }
481     GNUNET_memcpy (mem + c_size, "\n", 1);
482     c_size ++;
483     sec = sec->next;
484   }
485   GNUNET_assert (c_size == m_size);
486   *size = c_size;
487   return mem;
488 }
489
490
491 /**
492  * Write configuration file.
493  *
494  * @param cfg configuration to write
495  * @param filename where to write the configuration
496  * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
497  */
498 int
499 GNUNET_CONFIGURATION_write (struct GNUNET_CONFIGURATION_Handle *cfg,
500                             const char *filename)
501 {
502   char *fn;
503   char *cfg_buf;
504   size_t size;
505   ssize_t sret;
506
507   fn = GNUNET_STRINGS_filename_expand (filename);
508   if (fn == NULL)
509     return GNUNET_SYSERR;
510   if (GNUNET_OK != GNUNET_DISK_directory_create_for_file (fn))
511   {
512     GNUNET_free (fn);
513     return GNUNET_SYSERR;
514   }
515   cfg_buf = GNUNET_CONFIGURATION_serialize (cfg, &size);
516   sret = GNUNET_DISK_fn_write (fn, cfg_buf, size,
517                                GNUNET_DISK_PERM_USER_READ
518                                | GNUNET_DISK_PERM_USER_WRITE
519                                | GNUNET_DISK_PERM_GROUP_READ
520                                | GNUNET_DISK_PERM_GROUP_WRITE);
521   if ( (sret < 0) ||
522        (size != (size_t) sret) )
523   {
524     GNUNET_free (fn);
525     GNUNET_free (cfg_buf);
526     LOG (GNUNET_ERROR_TYPE_WARNING,
527          "Writing configration to file `%s' failed\n",
528          filename);
529     cfg->dirty = GNUNET_SYSERR; /* last write failed */
530     return GNUNET_SYSERR;
531   }
532   GNUNET_free (fn);
533   GNUNET_free (cfg_buf);
534   cfg->dirty = GNUNET_NO;       /* last write succeeded */
535   return GNUNET_OK;
536 }
537
538
539 /**
540  * Iterate over all options in the configuration.
541  *
542  * @param cfg configuration to inspect
543  * @param iter function to call on each option
544  * @param iter_cls closure for @a iter
545  */
546 void
547 GNUNET_CONFIGURATION_iterate (const struct GNUNET_CONFIGURATION_Handle *cfg,
548                               GNUNET_CONFIGURATION_Iterator iter,
549                               void *iter_cls)
550 {
551   struct ConfigSection *spos;
552   struct ConfigEntry *epos;
553
554   for (spos = cfg->sections; NULL != spos; spos = spos->next)
555     for (epos = spos->entries; NULL != epos; epos = epos->next)
556       if (NULL != epos->val)
557         iter (iter_cls, spos->name, epos->key, epos->val);
558 }
559
560
561 /**
562  * Iterate over values of a section in the configuration.
563  *
564  * @param cfg configuration to inspect
565  * @param section the section
566  * @param iter function to call on each option
567  * @param iter_cls closure for @a iter
568  */
569 void
570 GNUNET_CONFIGURATION_iterate_section_values (const struct
571                                              GNUNET_CONFIGURATION_Handle *cfg,
572                                              const char *section,
573                                              GNUNET_CONFIGURATION_Iterator iter,
574                                              void *iter_cls)
575 {
576   struct ConfigSection *spos;
577   struct ConfigEntry *epos;
578
579   spos = cfg->sections;
580   while ((spos != NULL) && (0 != strcasecmp (spos->name, section)))
581     spos = spos->next;
582   if (NULL == spos)
583     return;
584   for (epos = spos->entries; NULL != epos; epos = epos->next)
585     if (NULL != epos->val)
586       iter (iter_cls, spos->name, epos->key, epos->val);
587 }
588
589
590 /**
591  * Iterate over all sections in the configuration.
592  *
593  * @param cfg configuration to inspect
594  * @param iter function to call on each section
595  * @param iter_cls closure for @a iter
596  */
597 void
598 GNUNET_CONFIGURATION_iterate_sections (const struct GNUNET_CONFIGURATION_Handle *cfg,
599                                        GNUNET_CONFIGURATION_Section_Iterator iter,
600                                        void *iter_cls)
601 {
602   struct ConfigSection *spos;
603   struct ConfigSection *next;
604
605   next = cfg->sections;
606   while (next != NULL)
607   {
608     spos = next;
609     next = spos->next;
610     iter (iter_cls, spos->name);
611   }
612 }
613
614
615 /**
616  * Remove the given section and all options in it.
617  *
618  * @param cfg configuration to inspect
619  * @param section name of the section to remove
620  */
621 void
622 GNUNET_CONFIGURATION_remove_section (struct GNUNET_CONFIGURATION_Handle *cfg,
623                                      const char *section)
624 {
625   struct ConfigSection *spos;
626   struct ConfigSection *prev;
627   struct ConfigEntry *ent;
628
629   prev = NULL;
630   spos = cfg->sections;
631   while (NULL != spos)
632   {
633     if (0 == strcasecmp (section, spos->name))
634     {
635       if (NULL == prev)
636         cfg->sections = spos->next;
637       else
638         prev->next = spos->next;
639       while (NULL != (ent = spos->entries))
640       {
641         spos->entries = ent->next;
642         GNUNET_free (ent->key);
643         GNUNET_free_non_null (ent->val);
644         GNUNET_free (ent);
645         cfg->dirty = GNUNET_YES;
646       }
647       GNUNET_free (spos->name);
648       GNUNET_free (spos);
649       return;
650     }
651     prev = spos;
652     spos = spos->next;
653   }
654 }
655
656
657 /**
658  * Copy a configuration value to the given target configuration.
659  * Overwrites existing entries.
660  *
661  * @param cls the destination configuration (`struct GNUNET_CONFIGURATION_Handle *`)
662  * @param section section for the value
663  * @param option option name of the value
664  * @param value value to copy
665  */
666 static void
667 copy_entry (void *cls,
668             const char *section,
669             const char *option,
670             const char *value)
671 {
672   struct GNUNET_CONFIGURATION_Handle *dst = cls;
673
674   GNUNET_CONFIGURATION_set_value_string (dst, section, option, value);
675 }
676
677
678 /**
679  * Duplicate an existing configuration object.
680  *
681  * @param cfg configuration to duplicate
682  * @return duplicate configuration
683  */
684 struct GNUNET_CONFIGURATION_Handle *
685 GNUNET_CONFIGURATION_dup (const struct GNUNET_CONFIGURATION_Handle *cfg)
686 {
687   struct GNUNET_CONFIGURATION_Handle *ret;
688
689   ret = GNUNET_CONFIGURATION_create ();
690   GNUNET_CONFIGURATION_iterate (cfg, &copy_entry, ret);
691   return ret;
692 }
693
694
695 /**
696  * Find a section entry from a configuration.
697  *
698  * @param cfg configuration to search in
699  * @param section name of the section to look for
700  * @return matching entry, NULL if not found
701  */
702 static struct ConfigSection *
703 find_section (const struct GNUNET_CONFIGURATION_Handle *cfg,
704               const char *section)
705 {
706   struct ConfigSection *pos;
707
708   pos = cfg->sections;
709   while ((pos != NULL) && (0 != strcasecmp (section, pos->name)))
710     pos = pos->next;
711   return pos;
712 }
713
714
715 /**
716  * Find an entry from a configuration.
717  *
718  * @param cfg handle to the configuration
719  * @param section section the option is in
720  * @param key the option
721  * @return matching entry, NULL if not found
722  */
723 static struct ConfigEntry *
724 find_entry (const struct GNUNET_CONFIGURATION_Handle *cfg,
725            const char *section,
726            const char *key)
727 {
728   struct ConfigSection *sec;
729   struct ConfigEntry *pos;
730
731   if (NULL == (sec = find_section (cfg, section)))
732     return NULL;
733   pos = sec->entries;
734   while ((pos != NULL) && (0 != strcasecmp (key, pos->key)))
735     pos = pos->next;
736   return pos;
737 }
738
739
740 /**
741  * A callback function, compares entries from two configurations
742  * (default against a new configuration) and write the diffs in a
743  * diff-configuration object (the callback object).
744  *
745  * @param cls the diff configuration (`struct DiffHandle *`)
746  * @param section section for the value (of the default conf.)
747  * @param option option name of the value (of the default conf.)
748  * @param value value to copy (of the default conf.)
749  */
750 static void
751 compare_entries (void *cls,
752                  const char *section,
753                  const char *option,
754                  const char *value)
755 {
756   struct DiffHandle *dh = cls;
757   struct ConfigEntry *entNew;
758
759   entNew = find_entry (dh->cfg_default, section, option);
760   if ( (NULL != entNew) &&
761        (NULL != entNew->val) &&
762        (0 == strcmp (entNew->val, value)) )
763     return;
764   GNUNET_CONFIGURATION_set_value_string (dh->cfgDiff, section, option, value);
765 }
766
767
768 /**
769  * Compute configuration with only entries that have been changed
770  *
771  * @param cfg_default original configuration
772  * @param cfg_new new configuration
773  * @return configuration with only the differences, never NULL
774  */
775 struct GNUNET_CONFIGURATION_Handle *
776 GNUNET_CONFIGURATION_get_diff (const struct GNUNET_CONFIGURATION_Handle *cfg_default,
777                                const struct GNUNET_CONFIGURATION_Handle *cfg_new)
778 {
779   struct DiffHandle diffHandle;
780
781   diffHandle.cfgDiff = GNUNET_CONFIGURATION_create ();
782   diffHandle.cfg_default = cfg_default;
783   GNUNET_CONFIGURATION_iterate (cfg_new, &compare_entries, &diffHandle);
784   return diffHandle.cfgDiff;
785 }
786
787
788 /**
789  * Write only configuration entries that have been changed to configuration file
790  *
791  * @param cfg_default default configuration
792  * @param cfg_new new configuration
793  * @param filename where to write the configuration diff between default and new
794  * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
795  */
796 int
797 GNUNET_CONFIGURATION_write_diffs (const struct GNUNET_CONFIGURATION_Handle
798                                   *cfg_default,
799                                   const struct GNUNET_CONFIGURATION_Handle
800                                   *cfg_new, const char *filename)
801 {
802   int ret;
803   struct GNUNET_CONFIGURATION_Handle *diff;
804
805   diff = GNUNET_CONFIGURATION_get_diff (cfg_default, cfg_new);
806   ret = GNUNET_CONFIGURATION_write (diff, filename);
807   GNUNET_CONFIGURATION_destroy (diff);
808   return ret;
809 }
810
811
812 /**
813  * Set a configuration value that should be a string.
814  *
815  * @param cfg configuration to update
816  * @param section section of interest
817  * @param option option of interest
818  * @param value value to set
819  */
820 void
821 GNUNET_CONFIGURATION_set_value_string (struct GNUNET_CONFIGURATION_Handle *cfg,
822                                        const char *section, const char *option,
823                                        const char *value)
824 {
825   struct ConfigSection *sec;
826   struct ConfigEntry *e;
827   char *nv;
828
829   e = find_entry (cfg, section, option);
830   if (NULL != e)
831   {
832     if (NULL == value)
833     {
834       GNUNET_free_non_null (e->val);
835       e->val = NULL;
836     }
837     else
838     {
839       nv = GNUNET_strdup (value);
840       GNUNET_free_non_null (e->val);
841       e->val = nv;
842     }
843     return;
844   }
845   sec = find_section (cfg, section);
846   if (sec == NULL)
847   {
848     sec = GNUNET_new (struct ConfigSection);
849     sec->name = GNUNET_strdup (section);
850     sec->next = cfg->sections;
851     cfg->sections = sec;
852   }
853   e = GNUNET_new (struct ConfigEntry);
854   e->key = GNUNET_strdup (option);
855   e->val = GNUNET_strdup (value);
856   e->next = sec->entries;
857   sec->entries = e;
858 }
859
860
861 /**
862  * Set a configuration value that should be a number.
863  *
864  * @param cfg configuration to update
865  * @param section section of interest
866  * @param option option of interest
867  * @param number value to set
868  */
869 void
870 GNUNET_CONFIGURATION_set_value_number (struct GNUNET_CONFIGURATION_Handle *cfg,
871                                        const char *section,
872                                        const char *option,
873                                        unsigned long long number)
874 {
875   char s[64];
876
877   GNUNET_snprintf (s,
878                    64,
879                    "%llu",
880                    number);
881   GNUNET_CONFIGURATION_set_value_string (cfg,
882                                          section,
883                                          option,
884                                          s);
885 }
886
887
888 /**
889  * Get a configuration value that should be a number.
890  *
891  * @param cfg configuration to inspect
892  * @param section section of interest
893  * @param option option of interest
894  * @param number where to store the numeric value of the option
895  * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
896  */
897 int
898 GNUNET_CONFIGURATION_get_value_number (const struct GNUNET_CONFIGURATION_Handle
899                                        *cfg, const char *section,
900                                        const char *option,
901                                        unsigned long long *number)
902 {
903   struct ConfigEntry *e;
904
905   if (NULL == (e = find_entry (cfg, section, option)))
906     return GNUNET_SYSERR;
907   if (NULL == e->val)
908     return GNUNET_SYSERR;
909   if (1 != SSCANF (e->val, "%llu", number))
910     return GNUNET_SYSERR;
911   return GNUNET_OK;
912 }
913
914 /**
915  * Get a configuration value that should be a floating point number.
916  *
917  * @param cfg configuration to inspect
918  * @param section section of interest
919  * @param option option of interest
920  * @param number where to store the floating value of the option
921  * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
922  */
923 int
924 GNUNET_CONFIGURATION_get_value_float  (const struct GNUNET_CONFIGURATION_Handle
925                                        *cfg, const char *section,
926                                        const char *option,
927                                        float *number)
928 {
929   struct ConfigEntry *e;
930
931   if (NULL == (e = find_entry (cfg, section, option)))
932     return GNUNET_SYSERR;
933   if (NULL == e->val)
934     return GNUNET_SYSERR;
935   if (1 != SSCANF (e->val, "%f", number))
936     return GNUNET_SYSERR;
937   return GNUNET_OK;
938 }
939
940
941
942 /**
943  * Get a configuration value that should be a relative time.
944  *
945  * @param cfg configuration to inspect
946  * @param section section of interest
947  * @param option option of interest
948  * @param time set to the time value stored in the configuration
949  * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
950  */
951 int
952 GNUNET_CONFIGURATION_get_value_time (const struct GNUNET_CONFIGURATION_Handle *cfg,
953                                      const char *section,
954                                      const char *option,
955                                      struct GNUNET_TIME_Relative *time)
956 {
957   struct ConfigEntry *e;
958
959   if (NULL == (e = find_entry (cfg, section, option)))
960     return GNUNET_SYSERR;
961   if (NULL == e->val)
962     return GNUNET_SYSERR;
963   return GNUNET_STRINGS_fancy_time_to_relative (e->val, time);
964 }
965
966
967 /**
968  * Get a configuration value that should be a size in bytes.
969  *
970  * @param cfg configuration to inspect
971  * @param section section of interest
972  * @param option option of interest
973  * @param size set to the size in bytes as stored in the configuration
974  * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
975  */
976 int
977 GNUNET_CONFIGURATION_get_value_size (const struct GNUNET_CONFIGURATION_Handle *cfg,
978                                      const char *section,
979                                      const char *option,
980                                      unsigned long long *size)
981 {
982   struct ConfigEntry *e;
983
984   if (NULL == (e = find_entry (cfg, section, option)))
985     return GNUNET_SYSERR;
986   if (NULL == e->val)
987     return GNUNET_SYSERR;
988   return GNUNET_STRINGS_fancy_size_to_bytes (e->val, size);
989 }
990
991
992 /**
993  * Get a configuration value that should be a string.
994  *
995  * @param cfg configuration to inspect
996  * @param section section of interest
997  * @param option option of interest
998  * @param value will be set to a freshly allocated configuration
999  *        value, or NULL if option is not specified
1000  * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
1001  */
1002 int
1003 GNUNET_CONFIGURATION_get_value_string (const struct GNUNET_CONFIGURATION_Handle *cfg,
1004                                        const char *section,
1005                                        const char *option,
1006                                        char **value)
1007 {
1008   struct ConfigEntry *e;
1009
1010   if ( (NULL == (e = find_entry (cfg, section, option))) ||
1011        (NULL == e->val) )
1012   {
1013     *value = NULL;
1014     return GNUNET_SYSERR;
1015   }
1016   *value = GNUNET_strdup (e->val);
1017   return GNUNET_OK;
1018 }
1019
1020
1021 /**
1022  * Get a configuration value that should be in a set of
1023  * predefined strings
1024  *
1025  * @param cfg configuration to inspect
1026  * @param section section of interest
1027  * @param option option of interest
1028  * @param choices NULL-terminated list of legal values
1029  * @param value will be set to an entry in the legal list,
1030  *        or NULL if option is not specified and no default given
1031  * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
1032  */
1033 int
1034 GNUNET_CONFIGURATION_get_value_choice (const struct GNUNET_CONFIGURATION_Handle *cfg,
1035                                        const char *section,
1036                                        const char *option,
1037                                        const char *const *choices,
1038                                        const char **value)
1039 {
1040   struct ConfigEntry *e;
1041   unsigned int i;
1042
1043   if (NULL == (e = find_entry (cfg, section, option)))
1044     return GNUNET_SYSERR;
1045   for (i = 0; NULL != choices[i]; i++)
1046     if (0 == strcasecmp (choices[i], e->val))
1047       break;
1048   if (NULL == choices[i])
1049   {
1050     LOG (GNUNET_ERROR_TYPE_ERROR,
1051          _("Configuration value '%s' for '%s'"
1052            " in section '%s' is not in set of legal choices\n"),
1053          e->val,
1054          option,
1055          section);
1056     return GNUNET_SYSERR;
1057   }
1058   *value = choices[i];
1059   return GNUNET_OK;
1060 }
1061
1062
1063 /**
1064  * Get crockford32-encoded fixed-size binary data from a configuration.
1065  *
1066  * @param cfg configuration to access
1067  * @param section section to access
1068  * @param option option to access
1069  * @param buf where to store the decoded binary result
1070  * @param buf_size exact number of bytes to store in @a buf
1071  * @return #GNUNET_OK on success
1072  *         #GNUNET_NO is the value does not exist
1073  *         #GNUNET_SYSERR on decoding error
1074  */
1075 int
1076 GNUNET_CONFIGURATION_get_data (const struct GNUNET_CONFIGURATION_Handle *cfg,
1077                                const char *section,
1078                                const char *option,
1079                                void *buf,
1080                                size_t buf_size)
1081 {
1082   char *enc;
1083   int res;
1084   size_t data_size;
1085
1086   if (GNUNET_OK !=
1087       (res = GNUNET_CONFIGURATION_get_value_string (cfg,
1088                                                     section,
1089                                                     option,
1090                                                     &enc)))
1091     return res;
1092   data_size = (strlen (enc) * 5) / 8;
1093   if (data_size != buf_size)
1094   {
1095     GNUNET_free (enc);
1096     return GNUNET_SYSERR;
1097   }
1098   if (GNUNET_OK !=
1099       GNUNET_STRINGS_string_to_data (enc,
1100                                      strlen (enc),
1101                                      buf, buf_size))
1102   {
1103     GNUNET_free (enc);
1104     return GNUNET_SYSERR;
1105   }
1106   GNUNET_free (enc);
1107   return GNUNET_OK;
1108 }
1109
1110
1111 /**
1112  * Test if we have a value for a particular option
1113  *
1114  * @param cfg configuration to inspect
1115  * @param section section of interest
1116  * @param option option of interest
1117  * @return #GNUNET_YES if so, #GNUNET_NO if not.
1118  */
1119 int
1120 GNUNET_CONFIGURATION_have_value (const struct GNUNET_CONFIGURATION_Handle *cfg,
1121                                  const char *section,
1122                                  const char *option)
1123 {
1124   struct ConfigEntry *e;
1125
1126   if ((NULL == (e = find_entry (cfg, section, option))) || (NULL == e->val))
1127     return GNUNET_NO;
1128   return GNUNET_YES;
1129 }
1130
1131
1132 /**
1133  * Expand an expression of the form "$FOO/BAR" to "DIRECTORY/BAR"
1134  * where either in the "PATHS" section or the environtment "FOO" is
1135  * set to "DIRECTORY".  We also support default expansion,
1136  * i.e. ${VARIABLE:-default} will expand to $VARIABLE if VARIABLE is
1137  * set in PATHS or the environment, and otherwise to "default".  Note
1138  * that "default" itself can also be a $-expression, thus
1139  * "${VAR1:-{$VAR2}}" will expand to VAR1 and if that is not defined
1140  * to VAR2.
1141  *
1142  * @param cfg configuration to use for path expansion
1143  * @param orig string to $-expand (will be freed!)
1144  * @param depth recursion depth, used to detect recursive expansions
1145  * @return $-expanded string
1146  */
1147 static char *
1148 expand_dollar (const struct GNUNET_CONFIGURATION_Handle *cfg,
1149                char *orig,
1150                unsigned int depth)
1151 {
1152   int i;
1153   char *prefix;
1154   char *result;
1155   char *start;
1156   const char *post;
1157   const char *env;
1158   char *def;
1159   char *end;
1160   unsigned int lopen;
1161   char erased_char;
1162   char *erased_pos;
1163   size_t len;
1164
1165   if (NULL == orig)
1166     return NULL;
1167   if (depth > 128)
1168   {
1169     LOG (GNUNET_ERROR_TYPE_WARNING,
1170          _("Recursive expansion suspected, aborting $-expansion for term `%s'\n"),
1171          orig);
1172     return orig;
1173   }
1174   LOG (GNUNET_ERROR_TYPE_DEBUG,
1175        "Asked to $-expand %s\n",
1176        orig);
1177   if ('$' != orig[0])
1178   {
1179     LOG (GNUNET_ERROR_TYPE_DEBUG,
1180          "Doesn't start with $ - not expanding\n");
1181     return orig;
1182   }
1183   erased_char = 0;
1184   erased_pos = NULL;
1185   if ('{' == orig[1])
1186   {
1187     start = &orig[2];
1188     lopen = 1;
1189     end = &orig[1];
1190     while (lopen > 0)
1191     {
1192       end++;
1193       switch (*end)
1194       {
1195       case '}':
1196         lopen--;
1197         break;
1198       case '{':
1199         lopen++;
1200         break;
1201       case '\0':
1202         LOG (GNUNET_ERROR_TYPE_WARNING,
1203              _("Missing closing `%s' in option `%s'\n"),
1204              "}",
1205              orig);
1206         return orig;
1207       default:
1208         break;
1209       }
1210     }
1211     erased_char = *end;
1212     erased_pos = end;
1213     *end = '\0';
1214     post = end + 1;
1215     def = strchr (orig, ':');
1216     if (NULL != def)
1217     {
1218       *def = '\0';
1219       def++;
1220       if ( ('-' == *def) ||
1221            ('=' == *def) )
1222         def++;
1223       def = GNUNET_strdup (def);
1224     }
1225   }
1226   else
1227   {
1228     start = &orig[1];
1229     def = NULL;
1230     i = 0;
1231     while ( (orig[i] != '/') &&
1232             (orig[i] != '\\') &&
1233             (orig[i] != '\0')  &&
1234             (orig[i] != ' ') )
1235       i++;
1236     if (orig[i] == '\0')
1237     {
1238       post = "";
1239     }
1240     else
1241     {
1242       erased_char = orig[i];
1243       erased_pos = &orig[i];
1244       orig[i] = '\0';
1245       post = &orig[i + 1];
1246     }
1247   }
1248   LOG (GNUNET_ERROR_TYPE_DEBUG,
1249        "Split into `%s' and `%s' with default %s\n",
1250        start,
1251        post,
1252        def);
1253   if (GNUNET_OK !=
1254       GNUNET_CONFIGURATION_get_value_string (cfg,
1255                                              "PATHS",
1256                                              start,
1257                                              &prefix))
1258   {
1259     if (NULL == (env = getenv (start)))
1260     {
1261       /* try default */
1262       def = expand_dollar (cfg, def, depth + 1);
1263       env = def;
1264     }
1265     if (NULL == env)
1266     {
1267       start = GNUNET_strdup (start);
1268       if (erased_pos)
1269         *erased_pos = erased_char;
1270       LOG (GNUNET_ERROR_TYPE_WARNING,
1271            _("Failed to expand `%s' in `%s' as it is neither found in [PATHS] nor defined as an environmental variable\n"),
1272            start, orig);
1273       GNUNET_free (start);
1274       return orig;
1275     }
1276     prefix = GNUNET_strdup (env);
1277   }
1278   prefix = GNUNET_CONFIGURATION_expand_dollar (cfg, prefix);
1279   if ( (erased_pos) && ('}' != erased_char) )
1280   {
1281     len = strlen (prefix) + 1;
1282     prefix = GNUNET_realloc (prefix, len + 1);
1283     prefix[len - 1] = erased_char;
1284     prefix[len] = '\0';
1285   }
1286   result = GNUNET_malloc (strlen (prefix) + strlen (post) + 1);
1287   strcpy (result, prefix);
1288   strcat (result, post);
1289   GNUNET_free_non_null (def);
1290   GNUNET_free (prefix);
1291   GNUNET_free (orig);
1292   return result;
1293 }
1294
1295
1296 /**
1297  * Expand an expression of the form "$FOO/BAR" to "DIRECTORY/BAR"
1298  * where either in the "PATHS" section or the environtment "FOO" is
1299  * set to "DIRECTORY".  We also support default expansion,
1300  * i.e. ${VARIABLE:-default} will expand to $VARIABLE if VARIABLE is
1301  * set in PATHS or the environment, and otherwise to "default".  Note
1302  * that "default" itself can also be a $-expression, thus
1303  * "${VAR1:-{$VAR2}}" will expand to VAR1 and if that is not defined
1304  * to VAR2.
1305  *
1306  * @param cfg configuration to use for path expansion
1307  * @param orig string to $-expand (will be freed!).  Note that multiple
1308  *          $-expressions can be present in this string.  They will all be
1309  *          $-expanded.
1310  * @return $-expanded string
1311  */
1312 char *
1313 GNUNET_CONFIGURATION_expand_dollar (const struct GNUNET_CONFIGURATION_Handle *cfg,
1314                                     char *orig)
1315 {
1316   char *dup;
1317   size_t i;
1318   size_t len;
1319
1320   for (i = 0; '\0' != orig[i]; i++)
1321   {
1322     if ('$' != orig[i])
1323       continue;
1324     dup = GNUNET_strdup (orig + i);
1325     dup = expand_dollar (cfg, dup, 0);
1326     len = strlen (dup) + 1;
1327     orig = GNUNET_realloc (orig, i + len);
1328     GNUNET_memcpy (orig + i, dup, len);
1329     GNUNET_free (dup);
1330   }
1331   return orig;
1332 }
1333
1334
1335 /**
1336  * Get a configuration value that should be a string.
1337  *
1338  * @param cfg configuration to inspect
1339  * @param section section of interest
1340  * @param option option of interest
1341  * @param value will be set to a freshly allocated configuration
1342  *        value, or NULL if option is not specified
1343  * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
1344  */
1345 int
1346 GNUNET_CONFIGURATION_get_value_filename (const struct GNUNET_CONFIGURATION_Handle *cfg,
1347                                          const char *section,
1348                                          const char *option,
1349                                          char **value)
1350 {
1351   char *tmp;
1352
1353   if (GNUNET_OK !=
1354       GNUNET_CONFIGURATION_get_value_string (cfg, section, option, &tmp))
1355   {
1356     LOG (GNUNET_ERROR_TYPE_DEBUG,
1357          "Failed to retrieve filename\n");
1358     *value = NULL;
1359     return GNUNET_SYSERR;
1360   }
1361   tmp = GNUNET_CONFIGURATION_expand_dollar (cfg, tmp);
1362   *value = GNUNET_STRINGS_filename_expand (tmp);
1363   GNUNET_free (tmp);
1364   if (*value == NULL)
1365     return GNUNET_SYSERR;
1366   return GNUNET_OK;
1367 }
1368
1369
1370 /**
1371  * Get a configuration value that should be in a set of
1372  * "YES" or "NO".
1373  *
1374  * @param cfg configuration to inspect
1375  * @param section section of interest
1376  * @param option option of interest
1377  * @return #GNUNET_YES, #GNUNET_NO or #GNUNET_SYSERR
1378  */
1379 int
1380 GNUNET_CONFIGURATION_get_value_yesno (const struct GNUNET_CONFIGURATION_Handle *cfg,
1381                                       const char *section,
1382                                       const char *option)
1383 {
1384   static const char *yesno[] = { "YES", "NO", NULL };
1385   const char *val;
1386   int ret;
1387
1388   ret =
1389       GNUNET_CONFIGURATION_get_value_choice (cfg, section, option, yesno, &val);
1390   if (ret == GNUNET_SYSERR)
1391     return ret;
1392   if (val == yesno[0])
1393     return GNUNET_YES;
1394   return GNUNET_NO;
1395 }
1396
1397
1398 /**
1399  * Iterate over the set of filenames stored in a configuration value.
1400  *
1401  * @param cfg configuration to inspect
1402  * @param section section of interest
1403  * @param option option of interest
1404  * @param cb function to call on each filename
1405  * @param cb_cls closure for @a cb
1406  * @return number of filenames iterated over, -1 on error
1407  */
1408 int
1409 GNUNET_CONFIGURATION_iterate_value_filenames (const struct GNUNET_CONFIGURATION_Handle *cfg,
1410                                               const char *section,
1411                                               const char *option,
1412                                               GNUNET_FileNameCallback cb,
1413                                               void *cb_cls)
1414 {
1415   char *list;
1416   char *pos;
1417   char *end;
1418   char old;
1419   int ret;
1420
1421   if (GNUNET_OK !=
1422       GNUNET_CONFIGURATION_get_value_string (cfg, section, option, &list))
1423     return 0;
1424   GNUNET_assert (list != NULL);
1425   ret = 0;
1426   pos = list;
1427   while (1)
1428   {
1429     while (pos[0] == ' ')
1430       pos++;
1431     if (strlen (pos) == 0)
1432       break;
1433     end = pos + 1;
1434     while ((end[0] != ' ') && (end[0] != '\0'))
1435     {
1436       if (end[0] == '\\')
1437       {
1438         switch (end[1])
1439         {
1440         case '\\':
1441         case ' ':
1442           memmove (end, &end[1], strlen (&end[1]) + 1);
1443         case '\0':
1444           /* illegal, but just keep it */
1445           break;
1446         default:
1447           /* illegal, but just ignore that there was a '/' */
1448           break;
1449         }
1450       }
1451       end++;
1452     }
1453     old = end[0];
1454     end[0] = '\0';
1455     if (strlen (pos) > 0)
1456     {
1457       ret++;
1458       if ((cb != NULL) && (GNUNET_OK != cb (cb_cls, pos)))
1459       {
1460         ret = GNUNET_SYSERR;
1461         break;
1462       }
1463     }
1464     if (old == '\0')
1465       break;
1466     pos = end + 1;
1467   }
1468   GNUNET_free (list);
1469   return ret;
1470 }
1471
1472
1473 /**
1474  * FIXME.
1475  *
1476  * @param value FIXME
1477  * @return FIXME
1478  */
1479 static char *
1480 escape_name (const char *value)
1481 {
1482   char *escaped;
1483   const char *rpos;
1484   char *wpos;
1485
1486   escaped = GNUNET_malloc (strlen (value) * 2 + 1);
1487   memset (escaped, 0, strlen (value) * 2 + 1);
1488   rpos = value;
1489   wpos = escaped;
1490   while (rpos[0] != '\0')
1491   {
1492     switch (rpos[0])
1493     {
1494     case '\\':
1495     case ' ':
1496       wpos[0] = '\\';
1497       wpos[1] = rpos[0];
1498       wpos += 2;
1499       break;
1500     default:
1501       wpos[0] = rpos[0];
1502       wpos++;
1503     }
1504     rpos++;
1505   }
1506   return escaped;
1507 }
1508
1509
1510 /**
1511  * FIXME.
1512  *
1513  * @param cls string we compare with (const char*)
1514  * @param fn filename we are currently looking at
1515  * @return #GNUNET_OK if the names do not match, #GNUNET_SYSERR if they do
1516  */
1517 static int
1518 test_match (void *cls, const char *fn)
1519 {
1520   const char *of = cls;
1521
1522   return (0 == strcmp (of, fn)) ? GNUNET_SYSERR : GNUNET_OK;
1523 }
1524
1525
1526 /**
1527  * Append a filename to a configuration value that
1528  * represents a list of filenames
1529  *
1530  * @param cfg configuration to update
1531  * @param section section of interest
1532  * @param option option of interest
1533  * @param value filename to append
1534  * @return #GNUNET_OK on success,
1535  *         #GNUNET_NO if the filename already in the list
1536  *         #GNUNET_SYSERR on error
1537  */
1538 int
1539 GNUNET_CONFIGURATION_append_value_filename (struct GNUNET_CONFIGURATION_Handle *cfg,
1540                                             const char *section,
1541                                             const char *option,
1542                                             const char *value)
1543 {
1544   char *escaped;
1545   char *old;
1546   char *nw;
1547
1548   if (GNUNET_SYSERR ==
1549       GNUNET_CONFIGURATION_iterate_value_filenames (cfg, section, option,
1550                                                     &test_match,
1551                                                     (void *) value))
1552     return GNUNET_NO;           /* already exists */
1553   if (GNUNET_OK !=
1554       GNUNET_CONFIGURATION_get_value_string (cfg, section, option, &old))
1555     old = GNUNET_strdup ("");
1556   escaped = escape_name (value);
1557   nw = GNUNET_malloc (strlen (old) + strlen (escaped) + 2);
1558   strcpy (nw, old);
1559   if (strlen (old) > 0)
1560     strcat (nw, " ");
1561   strcat (nw, escaped);
1562   GNUNET_CONFIGURATION_set_value_string (cfg, section, option, nw);
1563   GNUNET_free (old);
1564   GNUNET_free (nw);
1565   GNUNET_free (escaped);
1566   return GNUNET_OK;
1567 }
1568
1569
1570 /**
1571  * Remove a filename from a configuration value that
1572  * represents a list of filenames
1573  *
1574  * @param cfg configuration to update
1575  * @param section section of interest
1576  * @param option option of interest
1577  * @param value filename to remove
1578  * @return #GNUNET_OK on success,
1579  *         #GNUNET_NO if the filename is not in the list,
1580  *         #GNUNET_SYSERR on error
1581  */
1582 int
1583 GNUNET_CONFIGURATION_remove_value_filename (struct GNUNET_CONFIGURATION_Handle
1584                                             *cfg, const char *section,
1585                                             const char *option,
1586                                             const char *value)
1587 {
1588   char *list;
1589   char *pos;
1590   char *end;
1591   char *match;
1592   char old;
1593
1594   if (GNUNET_OK !=
1595       GNUNET_CONFIGURATION_get_value_string (cfg, section, option, &list))
1596     return GNUNET_NO;
1597   match = escape_name (value);
1598   pos = list;
1599   while (1)
1600   {
1601     while (pos[0] == ' ')
1602       pos++;
1603     if (strlen (pos) == 0)
1604       break;
1605     end = pos + 1;
1606     while ((end[0] != ' ') && (end[0] != '\0'))
1607     {
1608       if (end[0] == '\\')
1609       {
1610         switch (end[1])
1611         {
1612         case '\\':
1613         case ' ':
1614           end++;
1615           break;
1616         case '\0':
1617           /* illegal, but just keep it */
1618           break;
1619         default:
1620           /* illegal, but just ignore that there was a '/' */
1621           break;
1622         }
1623       }
1624       end++;
1625     }
1626     old = end[0];
1627     end[0] = '\0';
1628     if (0 == strcmp (pos, match))
1629     {
1630       if (old != '\0')
1631         memmove (pos, &end[1], strlen (&end[1]) + 1);
1632       else
1633       {
1634         if (pos != list)
1635           pos[-1] = '\0';
1636         else
1637           pos[0] = '\0';
1638       }
1639       GNUNET_CONFIGURATION_set_value_string (cfg, section, option, list);
1640       GNUNET_free (list);
1641       GNUNET_free (match);
1642       return GNUNET_OK;
1643     }
1644     if (old == '\0')
1645       break;
1646     end[0] = old;
1647     pos = end + 1;
1648   }
1649   GNUNET_free (list);
1650   GNUNET_free (match);
1651   return GNUNET_NO;
1652 }
1653
1654
1655 /**
1656  * Wrapper around #GNUNET_CONFIGURATION_parse.  Called on each
1657  * file in a directory, we trigger parsing on those files that
1658  * end with ".conf".
1659  *
1660  * @param cls the cfg
1661  * @param filename file to parse
1662  * @return #GNUNET_OK on success
1663  */
1664 static int
1665 parse_configuration_file (void *cls, const char *filename)
1666 {
1667   struct GNUNET_CONFIGURATION_Handle *cfg = cls;
1668   char * ext;
1669   int ret;
1670
1671   /* Examine file extension */
1672   ext = strrchr (filename, '.');
1673   if ((NULL == ext) || (0 != strcmp (ext, ".conf")))
1674   {
1675     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1676                 "Skipping file `%s'\n",
1677                 filename);
1678     return GNUNET_OK;
1679   }
1680
1681   ret = GNUNET_CONFIGURATION_parse (cfg, filename);
1682   return ret;
1683 }
1684
1685
1686 /**
1687  * Load default configuration.  This function will parse the
1688  * defaults from the given defaults_d directory.
1689  *
1690  * @param cfg configuration to update
1691  * @param defaults_d directory with the defaults
1692  * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
1693  */
1694 int
1695 GNUNET_CONFIGURATION_load_from (struct GNUNET_CONFIGURATION_Handle *cfg,
1696                                 const char *defaults_d)
1697 {
1698   if (GNUNET_SYSERR ==
1699       GNUNET_DISK_directory_scan (defaults_d, &parse_configuration_file, cfg))
1700     return GNUNET_SYSERR;       /* no configuration at all found */
1701   return GNUNET_OK;
1702 }
1703
1704
1705 /* end of configuration.c */