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