GNUnet 0.29.1-dev.1-3-g346358e26
 
Loading...
Searching...
No Matches
configuration.c File Reference
#include "platform.h"
#include "gnunet_util_lib.h"
#include "gnunet_configuration_lib.h"
Include dependency graph for configuration.c:

Go to the source code of this file.

Data Structures

struct  ConfigSource
 source location of a configuration value More...
 
struct  ConfigEntry
 configuration entry More...
 
struct  ConfigSection
 configuration section More...
 
struct  ConfigFile
 
struct  GNUNET_CONFIGURATION_Handle
 configuration data More...
 
struct  DiffHandle
 Used for diffing a configuration object against the default one. More...
 
struct  CollectFilesContext
 Closure to collect_files_cb. More...
 
struct  CleanLine
 One physical assignment line considered for removal. More...
 

Macros

#define LOG(kind, ...)   GNUNET_log_from (kind, "util", __VA_ARGS__)
 
#define LOG_STRERROR_FILE(kind, syscall, filename)    GNUNET_log_from_strerror_file (kind, "util", syscall, filename)
 

Functions

void GNUNET_CONFIGURATION_enable_diagnostics (struct GNUNET_CONFIGURATION_Handle *cfg)
 Enable extra diagnostics.
 
struct GNUNET_CONFIGURATION_HandleGNUNET_CONFIGURATION_create (const struct GNUNET_OS_ProjectData *pd)
 Create a new configuration object.
 
void GNUNET_CONFIGURATION_destroy (struct GNUNET_CONFIGURATION_Handle *cfg)
 Destroy configuration object.
 
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_parse_and_run (const struct GNUNET_OS_ProjectData *pd, const char *filename, GNUNET_CONFIGURATION_Callback cb, void *cb_cls)
 Parse a configuration file filename and run the function cb with the resulting configuration object.
 
static enum GNUNET_GenericReturnValue collect_files_cb (void *cls, const char *filename)
 Function called with a filename.
 
static struct ConfigSectionfind_section (const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section)
 Find a section entry from a configuration.
 
static int pstrcmp (const void *a, const void *b)
 
static void copy_entry_with_sources (struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const struct ConfigEntry *entry)
 Copy an entry parsed through an @inline-secret@ directive, including all diagnostic source information.
 
static enum GNUNET_GenericReturnValue handle_inline (struct GNUNET_CONFIGURATION_Handle *cfg, const char *path_or_glob, bool path_is_glob, const char *restrict_section, const char *source_filename, unsigned int source_lineno)
 Handle an inline directive.
 
static struct ConfigEntryfind_entry (const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *key)
 Find an entry from a configuration.
 
static void add_entry_source (struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, const char *value, const char *filename, unsigned int line)
 Record the source of a configuration value.
 
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_deserialize (struct GNUNET_CONFIGURATION_Handle *cfg, const char *mem, size_t size, const char *source_filename)
 De-serializes configuration.
 
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_parse (struct GNUNET_CONFIGURATION_Handle *cfg, const char *filename)
 Parse a configuration file, add all of the options in the file to the configuration environment.
 
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_is_dirty (const struct GNUNET_CONFIGURATION_Handle *cfg)
 Test if there are configuration options that were changed since the last save.
 
static bool do_skip (const char *sec, const char *key)
 Should we skip this configuration entry when serializing?
 
char * GNUNET_CONFIGURATION_serialize (const struct GNUNET_CONFIGURATION_Handle *cfg, size_t *size)
 Serializes the given configuration.
 
static void dump_os_ipk (const struct GNUNET_CONFIGURATION_Handle *cfg, struct GNUNET_Buffer *buf, enum GNUNET_OS_InstallationPathKind ipk)
 Dump an os installation path to a buffer.
 
static char * serialize_diagnostics (const struct GNUNET_CONFIGURATION_Handle *cfg, bool verbose)
 Serialize configuration diagnostics.
 
char * GNUNET_CONFIGURATION_serialize_diagnostics (const struct GNUNET_CONFIGURATION_Handle *cfg)
 Serializes the given configuration with diagnostics information.
 
char * GNUNET_CONFIGURATION_serialize_diagnostics_verbose (const struct GNUNET_CONFIGURATION_Handle *cfg)
 Serializes the given configuration with verbose diagnostics information, including all source definitions of each value.
 
static enum GNUNET_GenericReturnValue read_file (const char *filename, char **contents, size_t *size)
 
static bool file_hash_matches (const char *filename, const struct GNUNET_HashCode *expected)
 Check that a file still has the expected contents.
 
static enum GNUNET_GenericReturnValue write_buffer_atomic (const char *filename, const char *contents, size_t size, const struct GNUNET_HashCode *expected_hash)
 Atomically replace a file with the given bytes.
 
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_write (struct GNUNET_CONFIGURATION_Handle *cfg, const char *filename)
 Write configuration file.
 
static struct CleanLinefind_clean_line (struct CleanLine *lines, unsigned int lines_length, unsigned int line)
 Find a cleanup record for a physical line.
 
static bool source_is_removed (const struct ConfigSource *source, const char *target, struct CleanLine *lines, unsigned int lines_length)
 Return whether a source is a target line currently marked for removal.
 
static int clean_line_cmp (const void *a, const void *b)
 Sort cleanup records by source line.
 
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_clean_file (const struct GNUNET_CONFIGURATION_Handle *cfg, const char *filename, GNUNET_CONFIGURATION_CleanCallback cb, void *cb_cls, unsigned int *removed)
 Remove redundant option definitions from a parsed configuration file.
 
void GNUNET_CONFIGURATION_iterate (const struct GNUNET_CONFIGURATION_Handle *cfg, GNUNET_CONFIGURATION_Iterator iter, void *iter_cls)
 Iterate over all options in the configuration.
 
void GNUNET_CONFIGURATION_iterate_section_values (const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, GNUNET_CONFIGURATION_Iterator iter, void *iter_cls)
 Iterate over values of a section in the configuration.
 
void GNUNET_CONFIGURATION_iterate_sections (const struct GNUNET_CONFIGURATION_Handle *cfg, GNUNET_CONFIGURATION_SectionIterator iter, void *iter_cls)
 Iterate over all sections in the configuration.
 
void GNUNET_CONFIGURATION_remove_section (struct GNUNET_CONFIGURATION_Handle *cfg, const char *section)
 Remove the given section and all options in it.
 
static void copy_entry (void *cls, const char *section, const char *option, const char *value)
 Copy a configuration value to the given target configuration.
 
struct GNUNET_CONFIGURATION_HandleGNUNET_CONFIGURATION_dup (const struct GNUNET_CONFIGURATION_Handle *cfg)
 Duplicate an existing configuration object.
 
static void compare_entries (void *cls, const char *section, const char *option, const char *value)
 A callback function, compares entries from two configurations (default against a new configuration) and write the diffs in a diff-configuration object (the callback object).
 
struct GNUNET_CONFIGURATION_HandleGNUNET_CONFIGURATION_get_diff (const struct GNUNET_CONFIGURATION_Handle *cfg_default, const struct GNUNET_CONFIGURATION_Handle *cfg_new)
 Compute configuration with only entries that have been changed.
 
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_write_diffs (const struct GNUNET_CONFIGURATION_Handle *cfg_default, const struct GNUNET_CONFIGURATION_Handle *cfg_new, const char *filename)
 Write only configuration entries that have been changed to configuration file.
 
void GNUNET_CONFIGURATION_set_value_string (struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, const char *value)
 Set a configuration value that should be a string.
 
void GNUNET_CONFIGURATION_set_value_number (struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, unsigned long long number)
 Set a configuration value that should be a number.
 
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_number (const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, unsigned long long *number)
 Get a configuration value that should be a number.
 
void GNUNET_CONFIGURATION_set_value_float (struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, float number)
 Set a configuration value that should be a float.
 
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_float (const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, float *number)
 Get a configuration value that should be a floating point number.
 
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_time (const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, struct GNUNET_TIME_Relative *time)
 Get a configuration value that should be a relative time.
 
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_size (const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, unsigned long long *size)
 Get a configuration value that should be a size in bytes.
 
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_string (const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, char **value)
 Get a configuration value that should be a string.
 
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_choice (const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, const char *const *choices, const char **value)
 Get a configuration value that should be in a set of predefined strings.
 
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_data (const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, void *buf, size_t buf_size)
 Get Crockford32-encoded fixed-size binary data from a configuration.
 
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_have_value (const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option)
 Test if we have a value for a particular option.
 
static char * expand_dollar (const struct GNUNET_CONFIGURATION_Handle *cfg, char *orig, unsigned int depth)
 Expand an expression of the form "$FOO/BAR" to "DIRECTORY/BAR" where either in the "PATHS" section or the environment "FOO" is set to "DIRECTORY".
 
char * GNUNET_CONFIGURATION_expand_dollar (const struct GNUNET_CONFIGURATION_Handle *cfg, char *orig)
 Expand an expression of the form "$FOO/BAR" to "DIRECTORY/BAR" where either in the "PATHS" section or the environment "FOO" is set to "DIRECTORY".
 
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_filename (const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, char **value)
 Get a configuration value that should be the name of a file or directory.
 
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_yesno (const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option)
 Get a configuration value that should be in a set of "YES" or "NO".
 
int GNUNET_CONFIGURATION_iterate_value_filenames (const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, GNUNET_FileNameCallback cb, void *cb_cls)
 Iterate over the set of filenames stored in a configuration value.
 
static char * escape_name (const char *value)
 FIXME.
 
static enum GNUNET_GenericReturnValue test_match (void *cls, const char *fn)
 FIXME.
 
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_append_value_filename (struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, const char *value)
 Append a filename to a configuration value that represents a list of filenames.
 
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_remove_value_filename (struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, const char *value)
 Remove a filename from a configuration value that represents a list of filenames.
 
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_load_from (struct GNUNET_CONFIGURATION_Handle *cfg, const char *defaults_d)
 Load default configuration.
 
char * GNUNET_CONFIGURATION_default_filename (const struct GNUNET_OS_ProjectData *pd)
 Return the filename of the default configuration filename that is used when no explicit configuration entry point has been specified.
 
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_load (struct GNUNET_CONFIGURATION_Handle *cfg, const char *filename)
 Load configuration.
 
static void print_filename_option (void *cls, const char *section, const char *option, const char *value)
 Print each option in a given section as a filename.
 
static void print_option (void *cls, const char *section, const char *option, const char *value)
 Print each option in a given section.
 
static void print_section_name (void *cls, const char *section)
 Print out given section name.
 
void GNUNET_CONFIGURATION_config_tool_run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg)
 Main task to run to perform operations typical for gnunet-config as per the configuration settings given in cls.
 
void GNUNET_CONFIGURATION_config_settings_free (struct GNUNET_CONFIGURATION_ConfigSettings *cs)
 Free resources associated with cs.
 
const struct GNUNET_OS_ProjectDataGNUNET_CONFIGURATION_get_project_data (const struct GNUNET_CONFIGURATION_Handle *cfg)
 Return the project data associated with this configuration.
 
char * GNUNET_CONFIGURATION_get_suid_binary_path (const struct GNUNET_OS_ProjectData *pd, const struct GNUNET_CONFIGURATION_Handle *cfg, const char *progname)
 Given the name of a helper, service or daemon binary construct the full path to the binary using the SUID_BINARY_PATH in the PATHS section of the configuration.
 

Macro Definition Documentation

◆ LOG

#define LOG (   kind,
  ... 
)    GNUNET_log_from (kind, "util", __VA_ARGS__)

Definition at line 30 of file configuration.c.

◆ LOG_STRERROR_FILE

#define LOG_STRERROR_FILE (   kind,
  syscall,
  filename 
)     GNUNET_log_from_strerror_file (kind, "util", syscall, filename)

Definition at line 32 of file configuration.c.

38{
42 struct ConfigSource *next;
43
47 char *value;
48
52 char *filename;
53
57 unsigned int lineno;
58};
59
60
64struct ConfigEntry
65{
69 struct ConfigEntry *next;
70
74 char *key;
75
79 char *val;
80
84 struct ConfigSource *sources;
85};
86
87
91struct ConfigSection
92{
96 struct ConfigSection *next;
97
101 struct ConfigEntry *entries;
102
106 char *name;
107
114 bool inaccessible;
115
120
124 char *hint_secret_stat;
125
130
134 unsigned int hint_inlined_from_line;
135};
136
137struct ConfigFile
138{
142 char *source_filename;
143
147 unsigned int level;
148
149 struct ConfigFile *prev;
150
151 struct ConfigFile *next;
152
158
163
168
173};
174
175
180{
184 struct ConfigSection *sections;
185
190
195
199 const struct GNUNET_OS_ProjectData *pd;
200
204 unsigned int current_nest_level;
205
209 bool diagnostics;
210
217
221 bool load_called;
222
226 char *main_filename;
227
233 const char *restrict_section;
234};
235
236
241struct DiffHandle
242{
244
246};
247
248
249void
252{
253 cfg->diagnostics = true;
254}
255
256
259{
261 char *p;
262
264 cfg->pd = pd;
265 /* make certain values from the project data available
266 as PATHS */
269 if (NULL != p)
270 {
272 "PATHS",
273 "DATADIR",
274 p);
275 GNUNET_free (p);
276 }
279 if (NULL != p)
280 {
282 "PATHS",
283 "LIBDIR",
284 p);
285 GNUNET_free (p);
286 }
289 if (NULL != p)
290 {
292 "PATHS",
293 "BINDIR",
294 p);
295 GNUNET_free (p);
296 }
299 if (NULL != p)
300 {
302 "PATHS",
303 "PREFIX",
304 p);
305 GNUNET_free (p);
306 }
309 if (NULL != p)
310 {
312 "PATHS",
313 "LOCALEDIR",
314 p);
315 GNUNET_free (p);
316 }
319 if (NULL != p)
320 {
322 "PATHS",
323 "ICONDIR",
324 p);
325 GNUNET_free (p);
326 }
329 if (NULL != p)
330 {
332 "PATHS",
333 "DOCDIR",
334 p);
335 GNUNET_free (p);
336 }
339 if (NULL != p)
340 {
342 "PATHS",
343 "LIBEXECDIR",
344 p);
345 GNUNET_free (p);
346 }
347 return cfg;
348}
349
350
351void
353{
354 struct ConfigSection *sec;
355 struct ConfigFile *cf;
356
357 while (NULL != (sec = cfg->sections))
359 while (NULL != (cf = cfg->loaded_files_head))
360 {
365 cf);
366 GNUNET_free (cf);
367 }
370}
371
372
375 const char *filename,
377 void *cb_cls)
378{
381
383 if (GNUNET_OK !=
385 filename))
386 {
387 GNUNET_break (0);
389 return GNUNET_SYSERR;
390 }
391 ret = cb (cb_cls,
392 cfg);
394 return ret;
395}
396
397
402{
406 char **files;
407
411 unsigned int files_length;
412};
413
414
425collect_files_cb (void *cls,
426 const char *filename)
427{
428 struct CollectFilesContext *igc = cls;
429
431 igc->files_length,
433 return GNUNET_OK;
434}
435
436
444static struct ConfigSection *
446 const char *section)
447{
448 struct ConfigSection *pos;
449
450 if (NULL == cfg)
451 return NULL;
452 pos = cfg->sections;
453 while ( (NULL != pos) &&
454 (0 != strcasecmp (section,
455 pos->name)) )
456 pos = pos->next;
457 return pos;
458}
459
460
461static int
462pstrcmp (const void *a,
463 const void *b)
464{
465 return strcmp (*((const char **) a),
466 *((const char **) b));
467}
468
469
470static void
472 const char *section,
473 const struct ConfigEntry *entry);
474
475
483 const char *path_or_glob,
484 bool path_is_glob,
485 const char *restrict_section,
486 const char *source_filename,
487 unsigned int source_lineno)
488{
489 char *inline_path = NULL;
490 struct GNUNET_CONFIGURATION_Handle *other_cfg = NULL;
491 struct CollectFilesContext igc = {
492 .files = NULL,
493 .files_length = 0,
494 };
495 enum GNUNET_GenericReturnValue fun_ret;
496 unsigned int old_nest_level = cfg->current_nest_level++;
497
498 /* We support the section restriction only for non-globs */
499 GNUNET_assert (! (path_is_glob && (NULL != restrict_section)));
500
501 if (NULL == source_filename)
502 {
504 "Refusing to parse inline configurations, "
505 "not allowed without source filename!\n");
506 fun_ret = GNUNET_SYSERR;
507 goto cleanup;
508 }
509
510 if ('/' == *path_or_glob)
511 inline_path = GNUNET_strdup (path_or_glob);
512 else
513 {
514 /* We compute the canonical, absolute path first,
515 so that relative imports resolve properly with symlinked
516 config files. */
517 char *source_realpath;
518 char *endsep;
519
520 source_realpath = realpath (source_filename,
521 NULL);
522 if (NULL == source_realpath)
523 {
524 /* Couldn't even resolve path of base dir. */
525 GNUNET_break (0);
526 /* failed to parse included config */
527 fun_ret = GNUNET_SYSERR;
528 goto cleanup;
529 }
530 endsep = strrchr (source_realpath, '/');
531 GNUNET_assert (NULL != endsep);
532 *endsep = '\0';
533 GNUNET_asprintf (&inline_path,
534 "%s/%s",
535 source_realpath,
536 path_or_glob);
537 free (source_realpath);
538 }
539
540 if (path_is_glob)
541 {
542 int nret;
543
545 "processing config glob '%s'\n",
546 inline_path);
547
548 nret = GNUNET_DISK_glob (inline_path,
550 &igc);
551 if (-1 == nret)
552 {
553 fun_ret = GNUNET_SYSERR;
554 goto cleanup;
555 }
556 GNUNET_assert (nret == igc.files_length);
557 qsort (igc.files,
558 igc.files_length,
559 sizeof (char *),
560 &pstrcmp);
561 for (int i = 0; i < nret; i++)
562 {
563 if (GNUNET_OK !=
565 igc.files[i]))
566 {
567 fun_ret = GNUNET_SYSERR;
568 goto cleanup;
569 }
570 }
571 fun_ret = GNUNET_OK;
572 }
573 else if (NULL != restrict_section)
574 {
575 enum GNUNET_GenericReturnValue inner_ret;
576 struct ConfigSection *cs;
577 struct ConfigFile *cf = GNUNET_new (struct ConfigFile);
578
579 inner_ret = GNUNET_DISK_file_test_read (inline_path);
580
581 cs = find_section (cfg, restrict_section);
582
583 if (NULL == cs)
584 {
585 cs = GNUNET_new (struct ConfigSection);
586 cs->name = GNUNET_strdup (restrict_section);
587 cs->next = cfg->sections;
588 cfg->sections = cs;
589 cs->entries = NULL;
590 }
591 if (cfg->diagnostics)
592 {
593 const char *pwname;
594 const char *grname;
595 char *sfn = GNUNET_STRINGS_filename_expand (inline_path);
596 struct stat istat;
597
598 cs->hint_secret_filename = sfn;
599 if (0 == stat (sfn, &istat))
600 {
601 struct passwd *pw = getpwuid (istat.st_uid);
602 struct group *gr = getgrgid (istat.st_gid);
603 pwname = (NULL == pw) ? "<unknown>" : pw->pw_name;
604 grname = (NULL == gr) ? "<unknown>" : gr->gr_name;
605
607 "%s:%s %o",
608 pwname,
609 grname,
610 istat.st_mode);
611 }
612 else
613 {
614 cs->hint_secret_stat = GNUNET_strdup ("<can't stat file>");
615 }
616 if (source_filename)
617 {
618 /* Possible that this secret section has been inlined before */
620 cs->hint_inlined_from_filename = GNUNET_strdup (source_filename);
621 cs->hint_inlined_from_line = source_lineno;
622 }
623 }
624
625 /* Put file in the load list for diagnostics, even if we can't access it. */
626 {
628 cf->source_filename = GNUNET_strdup (inline_path);
629 cf->hint_restrict_section = GNUNET_strdup (restrict_section);
632 cf);
633 }
634
635 if (GNUNET_OK != inner_ret)
636 {
637 cs->inaccessible = true;
638 cf->hint_inaccessible = true;
639 /* File can't be accessed, but that's okay. */
640 fun_ret = GNUNET_OK;
641 goto cleanup;
642 }
643
644 other_cfg = GNUNET_CONFIGURATION_create (cfg->pd);
645 if (cfg->diagnostics)
647 other_cfg->restrict_section = restrict_section;
648 inner_ret = GNUNET_CONFIGURATION_parse (other_cfg,
649 inline_path);
650 if (GNUNET_OK != inner_ret)
651 {
652 cf->hint_inaccessible = true;
653 fun_ret = inner_ret;
654 goto cleanup;
655 }
656
657 cs = find_section (other_cfg,
658 restrict_section);
659 if (NULL == cs)
660 {
662 "Configuration file '%s' loaded with @inline-secret@ "
663 "does not contain section '%s'.\n",
664 inline_path,
665 restrict_section);
666 /* Inlined configuration is accessible but doesn't contain any values.
667 We treat this as if the inlined section was empty, and do not
668 consider it an error. */
669 fun_ret = GNUNET_OK;
670 goto cleanup;
671 }
672 for (struct ConfigEntry *ce = cs->entries;
673 NULL != ce;
674 ce = ce->next)
676 restrict_section,
677 ce);
678 fun_ret = GNUNET_OK;
679 }
680 else if (GNUNET_OK !=
682 inline_path))
683 {
684 fun_ret = GNUNET_SYSERR;
685 goto cleanup;
686 }
687 else
688 {
689 fun_ret = GNUNET_OK;
690 }
691cleanup:
692 cfg->current_nest_level = old_nest_level;
693 if (NULL != other_cfg)
695 GNUNET_free (inline_path);
696 if (igc.files_length > 0)
697 {
698 for (size_t i = 0; i < igc.files_length; i++)
699 GNUNET_free (igc.files[i]);
701 }
702 return fun_ret;
703}
704
705
714static struct ConfigEntry *
716 const char *section,
717 const char *key)
718{
719 struct ConfigSection *sec;
720
721 if (NULL == (sec = find_section (cfg,
722 section)))
723 return NULL;
724 for (struct ConfigEntry *pos = sec->entries;
725 pos != NULL;
726 pos = pos->next)
727 if (0 == strcasecmp (key,
728 pos->key))
729 return pos;
730 if (sec->inaccessible)
731 {
733 "Section '%s' is marked as inaccessible, because the configuration "
734 "file that contains the section can't be read. Attempts to use "
735 "option '%s' will fail.\n",
736 section,
737 key);
738 return NULL;
739 }
740 return NULL;
741}
742
743
754static void
756 const char *section,
757 const char *option,
758 const char *value,
759 const char *filename,
760 unsigned int line)
761{
762 struct ConfigEntry *e;
763 struct ConfigSource *source;
764
765 if (! cfg->diagnostics)
766 return;
767 e = find_entry (cfg,
768 section,
769 option);
770 if (NULL == e)
771 return;
772 source = GNUNET_new (struct ConfigSource);
773 source->value = GNUNET_strdup (value);
774 source->filename = GNUNET_strdup (filename);
775 source->lineno = line;
776 source->next = e->sources;
777 e->sources = source;
778}
779
780
789static void
791 const char *section,
792 const struct ConfigEntry *entry)
793{
794 struct ConfigEntry *dst;
795 struct ConfigSource *head = NULL;
796 struct ConfigSource *tail = NULL;
797
799 section,
800 entry->key,
801 entry->val);
802 if ( (! cfg->diagnostics) ||
803 (NULL == entry->sources) )
804 return;
805 dst = find_entry (cfg,
806 section,
807 entry->key);
808 GNUNET_assert (NULL != dst);
809 for (const struct ConfigSource *pos = entry->sources;
810 NULL != pos;
811 pos = pos->next)
812 {
813 struct ConfigSource *copy = GNUNET_new (struct ConfigSource);
814
815 copy->value = GNUNET_strdup (pos->value);
816 copy->filename = GNUNET_strdup (pos->filename);
817 copy->lineno = pos->lineno;
818 if (NULL == tail)
819 head = copy;
820 else
821 tail->next = copy;
822 tail = copy;
823 }
824 tail->next = dst->sources;
825 dst->sources = head;
826}
827
828
831 const char *mem,
832 size_t size,
833 const char *source_filename)
834{
835 size_t line_size;
836 unsigned int nr;
837 size_t r_bytes;
838 size_t to_read;
840 char *section;
841 char *eq;
842 char *tag;
843 char *value;
844 char *line_orig = NULL;
845
846 ret = GNUNET_OK;
847 section = NULL;
848 nr = 0;
849 r_bytes = 0;
850 while (r_bytes < size)
851 {
852 const char *pos;
853 char *line;
854 bool emptyline;
855
856 GNUNET_free (line_orig);
857 /* fgets-like behaviour on buffer */
858 to_read = size - r_bytes;
859 pos = memchr (&mem[r_bytes], '\n', to_read);
860 if (NULL == pos)
861 {
862 line_orig = GNUNET_strndup (&mem[r_bytes],
863 line_size = to_read);
864 r_bytes += line_size;
865 }
866 else
867 {
868 line_orig = GNUNET_strndup (&mem[r_bytes],
869 line_size = (pos - &mem[r_bytes]));
870 r_bytes += line_size + 1;
871 }
872 line = line_orig;
873 /* increment line number */
874 nr++;
875 /* tabs and '\r' are whitespace */
876 emptyline = GNUNET_YES;
877 for (size_t i = 0; i < line_size; i++)
878 {
879 if (line[i] == '\t')
880 line[i] = ' ';
881 if (line[i] == '\r')
882 line[i] = ' ';
883 if (' ' != line[i])
884 emptyline = GNUNET_NO;
885 }
886 /* ignore empty lines */
887 if (GNUNET_YES == emptyline)
888 continue;
889
890 /* remove tailing whitespace */
891 for (size_t i = line_size - 1;
892 (i >= 1) && (isspace ((unsigned char) line[i]));
893 i--)
894 line[i] = '\0';
895
896 /* remove leading whitespace */
897 for (; line[0] != '\0' && (isspace ((unsigned char) line[0])); line++)
898 ;
899
900 /* ignore comments */
901 if ( ('#' == line[0]) ||
902 ('%' == line[0]) )
903 continue;
904
905 /* Handle special directives. */
906 if ('@' == line[0])
907 {
908 char *end = strchr (line + 1, '@');
909 char *directive;
910 enum GNUNET_GenericReturnValue directive_ret;
911
912 if (NULL != cfg->restrict_section)
913 {
915 "Illegal directive in line %u (parsing restricted section %s)\n",
916 nr,
919 break;
920 }
921
922 if (NULL == end)
923 {
925 "Bad directive in line %u\n",
926 nr);
928 break;
929 }
930 *end = '\0';
931 directive = line + 1;
932
933 if (0 == strcasecmp (directive,
934 "INLINE"))
935 {
936 const char *path = end + 1;
937
938 /* Skip space before path */
939 for (; isspace (*path); path++)
940 ;
941
942 directive_ret = handle_inline (cfg,
943 path,
944 false,
945 NULL,
946 source_filename,
947 nr);
948 }
949 else if (0 == strcasecmp (directive,
950 "INLINE-MATCHING"))
951 {
952 const char *path = end + 1;
953
954 /* Skip space before path */
955 for (; isspace (*path); path++)
956 ;
957
958 directive_ret = handle_inline (cfg,
959 path,
960 true,
961 NULL,
962 source_filename,
963 nr);
964 }
965 else if (0 == strcasecmp (directive,
966 "INLINE-SECRET"))
967 {
968 char *secname = end + 1;
969 char *secname_end;
970 const char *path;
971
972 /* Skip space before secname */
973 for (; isspace (*secname); secname++)
974 ;
975
976 secname_end = strchr (secname, ' ');
977
978 if (NULL == secname_end)
979 {
981 "Bad inline-secret directive in line %u\n",
982 nr);
984 break;
985 }
986 *secname_end = '\0';
987 path = secname_end + 1;
988
989 /* Skip space before path */
990 for (; isspace (*path); path++)
991 ;
992
993 directive_ret = handle_inline (cfg,
994 path,
995 false,
996 secname,
997 source_filename,
998 nr);
999 }
1000 else
1001 {
1003 "Unknown or malformed directive '%s' in line %u\n",
1004 directive,
1005 nr);
1007 break;
1008 }
1009 if (GNUNET_OK != directive_ret)
1010 {
1011 ret = directive_ret;
1012 break;
1013 }
1014 continue;
1015 }
1016 if ( ('[' == line[0]) &&
1017 (']' == line[line_size - 1]) )
1018 {
1019 /* [value] */
1020 line[line_size - 1] = '\0';
1021 value = &line[1];
1022 GNUNET_free (section);
1023 section = GNUNET_strdup (value);
1024 continue;
1025 }
1026 if (NULL != (eq = strchr (line, '=')))
1027 {
1028
1029 if (NULL == section)
1030 {
1032 "Syntax error while deserializing in line %u (option without section)\n",
1033 nr);
1035 break;
1036 }
1037
1038 /* tag = value */
1039 tag = GNUNET_strndup (line, eq - line);
1040 /* remove tailing whitespace */
1041 for (int i = strlen (tag) - 1;
1042 (i >= 1) && (isspace ((unsigned char) tag[i]));
1043 i--)
1044 tag[i] = '\0';
1045
1046 /* Strip whitespace */
1047 value = eq + 1;
1048 while (isspace ((unsigned char) value[0]))
1049 value++;
1050 for (int i = strlen (value) - 1;
1051 (i >= 1) && (isspace ((unsigned char) value[i]));
1052 i--)
1053 value[i] = '\0';
1054
1055 /* remove quotes */
1056 if ( ('"' == value[0]) &&
1057 ('"' == value[strlen (value) - 1]) )
1058 {
1059 value[strlen (value) - 1] = '\0';
1060 value++;
1061 }
1063 section,
1064 tag,
1065 value);
1066 if (cfg->diagnostics)
1067 {
1069 section,
1070 tag,
1071 value,
1072 source_filename
1073 ? source_filename
1074 : "<input>",
1075 nr);
1076 }
1077 GNUNET_free (tag);
1078 continue;
1079 }
1080 /* parse error */
1082 "Syntax error while deserializing in line %u\n",
1083 nr);
1085 break;
1086 }
1087 GNUNET_free (line_orig);
1088 GNUNET_free (section);
1089 GNUNET_assert ( (GNUNET_OK != ret) ||
1090 (r_bytes == size) );
1091 return ret;
1092}
1093
1094
1097 const char *filename)
1098{
1099 struct ConfigFile *loaded_file;
1100 uint64_t fs64;
1101 size_t fs;
1102 char *fn;
1103 char *mem;
1104 int dirty;
1106 ssize_t sret;
1107
1110 "Asked to parse config file `%s'\n",
1111 fn);
1112 if (NULL == fn)
1113 return GNUNET_SYSERR;
1114
1115
1116 /* Check for cycles */
1117 {
1118 unsigned int lvl = cfg->current_nest_level;
1119 struct ConfigFile *cf = cfg->loaded_files_tail;
1120 struct ConfigFile *parent = NULL;
1121
1122
1123 for (; NULL != cf; parent = cf, cf = cf->prev)
1124 {
1125 /* Check parents based on level, skipping children of siblings. */
1126 if (cf->level >= lvl)
1127 continue;
1128 lvl = cf->level;
1129 if ( (NULL == cf->source_filename) ||
1130 (NULL == filename) )
1131 continue;
1132 if (0 == strcmp (cf->source_filename,
1133 filename))
1134 {
1135 if (NULL == parent)
1136 {
1138 "Forbidden direct cyclic configuration import (%s -> %s)\n",
1139 cf->source_filename,
1140 filename);
1141 }
1142 else
1144 "Forbidden indirect cyclic configuration import (%s -> ... -> %s -> %s)\n",
1145 cf->source_filename,
1146 parent->source_filename,
1147 filename);
1148 GNUNET_free (fn);
1149 return GNUNET_SYSERR;
1150 }
1151 }
1152
1153 }
1154
1155 /* Keep track of loaded files.*/
1156 {
1157 loaded_file = GNUNET_new (struct ConfigFile);
1158
1159 loaded_file->level = cfg->current_nest_level;
1160 loaded_file->source_filename = GNUNET_strdup (filename
1161 ? filename
1162 : "<input>");
1165 loaded_file);
1166 }
1167
1168 dirty = cfg->dirty; /* back up value! */
1169 if (GNUNET_SYSERR ==
1171 &fs64,
1172 GNUNET_NO,
1173 GNUNET_YES))
1174 {
1176 "Error while determining the file size of `%s'\n",
1177 fn);
1178 GNUNET_free (fn);
1179 return GNUNET_SYSERR;
1180 }
1181 if (fs64 > SIZE_MAX)
1182 {
1183 GNUNET_break (0); /* File size is more than the heap size */
1184 GNUNET_free (fn);
1185 return GNUNET_SYSERR;
1186 }
1187 fs = fs64;
1188 mem = GNUNET_malloc (fs);
1189 sret = GNUNET_DISK_fn_read (fn,
1190 mem,
1191 fs);
1192 if ((sret < 0) || (fs != (size_t) sret))
1193 {
1195 "Error while reading file `%s'\n",
1196 fn);
1197 GNUNET_free (fn);
1198 GNUNET_free (mem);
1199 return GNUNET_SYSERR;
1200 }
1201 if (cfg->diagnostics)
1202 {
1203 GNUNET_CRYPTO_hash (mem,
1204 fs,
1205 &loaded_file->content_hash);
1206 }
1208 "Deserializing contents of file `%s'\n",
1209 fn);
1211 mem,
1212 fs,
1213 fn);
1214 if (GNUNET_SYSERR == ret)
1215 {
1217 _ ("Failed to parse configuration file `%s'\n"),
1218 fn);
1219 }
1220 else if (cfg->diagnostics)
1221 {
1222 loaded_file->have_content_hash = true;
1223 }
1224 GNUNET_free (fn);
1225 GNUNET_free (mem);
1226 /* restore dirty flag - anything we set in the meantime
1227 * came from disk */
1228 cfg->dirty = dirty;
1229 return ret;
1230}
1231
1232
1235{
1236 return cfg->dirty;
1237}
1238
1239
1247static bool
1248do_skip (const char *sec,
1249 const char *key)
1250{
1251 if (0 != strcasecmp ("PATHS",
1252 sec))
1253 return false;
1254 return ( (0 == strcasecmp ("DATADIR",
1255 key)) ||
1256 (0 == strcasecmp ("LIBDIR",
1257 key)) ||
1258 (0 == strcasecmp ("BINDIR",
1259 key)) ||
1260 (0 == strcasecmp ("PREFIX",
1261 key)) ||
1262 (0 == strcasecmp ("LOCALEDIR",
1263 key)) ||
1264 (0 == strcasecmp ("ICONDIR",
1265 key)) ||
1266 (0 == strcasecmp ("DOCDIR",
1267 key)) ||
1268 (0 == strcasecmp ("DEFAULTCONFIG",
1269 key)) ||
1270 (0 == strcasecmp ("LIBEXECDIR",
1271 key)) );
1272}
1273
1274
1275char *
1277 size_t *size)
1278{
1279 char *mem;
1280 char *cbuf;
1281 char *val;
1282 char *pos;
1283 size_t m_size;
1284 size_t c_size;
1285
1286 /* Pass1 : calculate the buffer size required */
1287 m_size = 0;
1288 for (struct ConfigSection *sec = cfg->sections;
1289 NULL != sec;
1290 sec = sec->next)
1291 {
1292 if (sec->inaccessible && (NULL == sec->entries))
1293 continue;
1294 /* For each section we need to add 3 characters: {'[',']','\n'} */
1295 m_size += strlen (sec->name) + 3;
1296 for (struct ConfigEntry *ent = sec->entries;
1297 NULL != ent;
1298 ent = ent->next)
1299 {
1300 if (do_skip (sec->name,
1301 ent->key))
1302 continue;
1303 if (NULL != ent->val)
1304 {
1305 /* if val has any '\n' then they occupy +1 character as '\n'->'\\','n' */
1306 pos = ent->val;
1307 while (NULL != (pos = strstr (pos, "\n")))
1308 {
1309 m_size++;
1310 pos++;
1311 }
1312 /* For each key = value pair we need to add 4 characters (2
1313 spaces and 1 equal-to character and 1 new line) */
1314 m_size += strlen (ent->key) + strlen (ent->val) + 4;
1315 }
1316 }
1317 /* A new line after section end */
1318 m_size++;
1319 }
1320
1321 /* Pass2: Allocate memory and write the configuration to it */
1322 mem = GNUNET_malloc (m_size);
1323 c_size = 0;
1324 *size = c_size;
1325 for (struct ConfigSection *sec = cfg->sections;
1326 NULL != sec;
1327 sec = sec->next)
1328 {
1329 int len;
1330
1331 len = GNUNET_asprintf (&cbuf,
1332 "[%s]\n",
1333 sec->name);
1334 GNUNET_assert (0 < len);
1335 GNUNET_memcpy (mem + c_size,
1336 cbuf,
1337 len);
1338 c_size += len;
1339 GNUNET_free (cbuf);
1340 for (struct ConfigEntry *ent = sec->entries;
1341 NULL != ent;
1342 ent = ent->next)
1343 {
1344 if (do_skip (sec->name,
1345 ent->key))
1346 continue;
1347 if (NULL != ent->val)
1348 {
1349 val = GNUNET_malloc (strlen (ent->val) * 2 + 1);
1350 strcpy (val, ent->val);
1351 while (NULL != (pos = strstr (val, "\n")))
1352 {
1353 memmove (&pos[2], &pos[1], strlen (&pos[1]));
1354 pos[0] = '\\';
1355 pos[1] = 'n';
1356 }
1357 len = GNUNET_asprintf (&cbuf, "%s = %s\n", ent->key, val);
1358 GNUNET_free (val);
1359 GNUNET_memcpy (mem + c_size, cbuf, len);
1360 c_size += len;
1361 GNUNET_free (cbuf);
1362 }
1363 }
1364 GNUNET_memcpy (mem + c_size, "\n", 1);
1365 c_size++;
1366 }
1367 GNUNET_assert (c_size == m_size);
1368 *size = c_size;
1369 return mem;
1370}
1371
1372
1381static void
1383 const struct GNUNET_CONFIGURATION_Handle *cfg,
1384 struct GNUNET_Buffer *buf,
1386{
1388 ipk);
1389 const char *ipkname;
1390 switch (ipk)
1391 {
1393 ipkname = "IPK_DATADIR";
1394 break;
1396 ipkname = "IPK_BINDIR";
1397 break;
1399 ipkname = "IPK_LIBDIR";
1400 break;
1402 ipkname = "IPK_PREFIX";
1404 ipkname = "IPK_LOCALEDIR";
1405 break;
1407 ipkname = "IPK_ICONDIR";
1409 ipkname = "IPK_DOCDIR";
1410 break;
1412 ipkname = "IPK_LIBEXECDIR";
1413 break;
1415 ipkname = "IPK_SELF_PREFIX";
1416 break;
1417 default:
1418 ipkname = "??";
1419 break;
1420 }
1422 "# %s = %s\n",
1423 ipkname,
1424 v);
1425 GNUNET_free (v);
1426}
1427
1428
1436static char *
1438 bool verbose)
1439{
1440 struct GNUNET_Buffer buf = { 0 };
1441
1443 "#\n# Configuration file diagnostics\n#\n");
1445 "# Entry point: %s\n",
1447 "<none>");
1449 "#\n# Files Loaded:\n");
1450
1451 for (struct ConfigFile *cfil = cfg->loaded_files_head;
1452 NULL != cfil;
1453 cfil = cfil->next)
1454 {
1456 "# ");
1457 for (unsigned int i = 0; i < cfil->level; i++)
1459 "+");
1460 if (0 != cfil->level)
1462 " ");
1463
1465 "%s",
1466 cfil->source_filename);
1467
1468 if (NULL != cfil->hint_restrict_section)
1470 " (%s secret section %s)",
1471 cfil->hint_inaccessible
1472 ? "inaccessible"
1473 : "loaded",
1474 cfil->hint_restrict_section);
1475
1477 "\n");
1478 }
1479
1481 "#\n# Installation paths:\n");
1482
1492
1493
1495 "#\n\n");
1496
1497 for (struct ConfigSection *sec = cfg->sections;
1498 NULL != sec;
1499 sec = sec->next)
1500 {
1501 if (sec->hint_secret_filename)
1503 "# secret section from %s\n# secret file stat %s\n",
1504 sec->hint_secret_filename,
1505 sec->hint_secret_stat);
1506 if (sec->hint_inlined_from_filename)
1507 {
1509 "# inlined from %s:%u\n",
1510 sec->hint_inlined_from_filename,
1511 sec->hint_inlined_from_line);
1512 }
1514 "[%s]\n\n",
1515 sec->name);
1516 if (sec->inaccessible && (NULL == sec->entries))
1517 {
1519 "# <section contents inaccessible>\n\n\n");
1520 continue;
1521 }
1522 for (struct ConfigEntry *ent = sec->entries;
1523 NULL != ent;
1524 ent = ent->next)
1525 {
1526 if (do_skip (sec->name,
1527 ent->key))
1528 continue;
1529 if (NULL != ent->val)
1530 {
1531 char *pos;
1532 char *val = GNUNET_malloc (strlen (ent->val) * 2 + 1);
1533 strcpy (val, ent->val);
1534 while (NULL != (pos = strstr (val, "\n")))
1535 {
1536 memmove (&pos[2], &pos[1], strlen (&pos[1]));
1537 pos[0] = '\\';
1538 pos[1] = 'n';
1539 }
1540 if (NULL != ent->sources)
1541 {
1542 if (verbose &&
1543 (NULL != ent->sources->next))
1544 {
1546 &buf,
1547 "# duplicate definitions (highest precedence first):\n");
1548 for (const struct ConfigSource *source = ent->sources;
1549 NULL != source;
1550 source = source->next)
1551 {
1552 const char *status;
1553
1554 if (source == ent->sources)
1555 status = "effective";
1556 else if (0 == strcmp (source->value,
1557 ent->val))
1558 status = "same value";
1559 else
1560 status = "different value";
1562 &buf,
1563 "# %s:%u (%s)\n",
1564 source->filename,
1565 source->lineno,
1566 status);
1567 }
1568 }
1569 else
1570 {
1572 "# %s:%u\n",
1573 ent->sources->filename,
1574 ent->sources->lineno);
1575 }
1576 }
1578 "%s = %s\n",
1579 ent->key,
1580 val);
1581 GNUNET_free (val);
1582 }
1583 GNUNET_buffer_write_str (&buf, "\n");
1584 }
1585 if (sec->inaccessible)
1586 {
1588 "# <additional section contents inaccessible>\n\n\n");
1589 continue;
1590 }
1591
1592 GNUNET_buffer_write_str (&buf, "\n");
1593 }
1594 return GNUNET_buffer_reap_str (&buf);
1595}
1596
1597
1598char *
1600 const struct GNUNET_CONFIGURATION_Handle *cfg)
1601{
1602 return serialize_diagnostics (cfg,
1603 false);
1604}
1605
1606
1607char *
1609 const struct GNUNET_CONFIGURATION_Handle *cfg)
1610{
1611 return serialize_diagnostics (cfg,
1612 true);
1613}
1614
1615
1616static enum GNUNET_GenericReturnValue
1617read_file (const char *filename,
1618 char **contents,
1619 size_t *size)
1620{
1621 uint64_t fs64;
1622 ssize_t ret;
1623
1624 if ( (GNUNET_SYSERR ==
1626 &fs64,
1627 GNUNET_NO,
1628 GNUNET_YES)) ||
1629 (fs64 > SIZE_MAX) )
1630 return GNUNET_SYSERR;
1631 *size = (size_t) fs64;
1632 *contents = GNUNET_malloc (*size);
1634 *contents,
1635 *size);
1636 if ( (ret < 0) || ((size_t) ret != *size) )
1637 {
1638 GNUNET_free (*contents);
1639 *contents = NULL;
1640 return GNUNET_SYSERR;
1641 }
1642 return GNUNET_OK;
1643}
1644
1645
1653static bool
1654file_hash_matches (const char *filename,
1655 const struct GNUNET_HashCode *expected)
1656{
1657 struct GNUNET_HashCode actual;
1658 char *contents;
1659 size_t size;
1660
1662 &contents,
1663 &size))
1664 return false;
1665 GNUNET_CRYPTO_hash (contents,
1666 size,
1667 &actual);
1668 GNUNET_free (contents);
1669 return 0 == GNUNET_memcmp (&actual,
1670 expected);
1671}
1672
1673
1683static enum GNUNET_GenericReturnValue
1684write_buffer_atomic (const char *filename,
1685 const char *contents,
1686 size_t size,
1687 const struct GNUNET_HashCode *expected_hash)
1688{
1689 char *fn;
1690 char *tfn;
1691
1693 if (fn == NULL)
1694 return GNUNET_SYSERR;
1696 {
1697 GNUNET_free (fn);
1698 return GNUNET_SYSERR;
1699 }
1700 {
1701 /* If @a filename is a symlink, replace what it points at, the way
1702 truncating it in place used to. */
1703 char *rfn = realpath (fn,
1704 NULL);
1705
1706 if (NULL != rfn)
1707 {
1708 GNUNET_free (fn);
1709 fn = GNUNET_strdup (rfn);
1710 free (rfn);
1711 }
1712 }
1713 /* Never rewrite the configuration in place: opening it with O_TRUNC leaves
1714 it observably empty until we have written the new contents, and anyone
1715 parsing the file in that instant -- say a daemon that was just started
1716 with this very configuration -- reads a truncated file and fails. So
1717 write a sibling file and rename(2) it over the target; readers then
1718 always see either the complete old or the complete new configuration. */
1719 GNUNET_asprintf (&tfn,
1720 "%s.%u.tmp",
1721 fn,
1722 (unsigned int) getpid ());
1723 {
1724 struct GNUNET_DISK_FileHandle *h;
1725
1726 h = GNUNET_DISK_file_open (tfn,
1734 if (NULL == h)
1735 {
1736 GNUNET_free (tfn);
1737 GNUNET_free (fn);
1738 return GNUNET_SYSERR;
1739 }
1740 if (((ssize_t) size) !=
1742 contents,
1743 size))
1744 {
1746 "write",
1747 tfn);
1749 (void) unlink (tfn);
1750 GNUNET_free (tfn);
1751 GNUNET_free (fn);
1752 return GNUNET_SYSERR;
1753 }
1754 /* Get the contents onto the disk before the rename publishes them, so
1755 that a crash cannot leave an empty configuration behind. */
1757 {
1759 "fsync",
1760 tfn);
1761 (void) GNUNET_DISK_file_close (h);
1762 (void) unlink (tfn);
1763 GNUNET_free (tfn);
1764 GNUNET_free (fn);
1765 return GNUNET_SYSERR;
1766 }
1768 {
1770 "close",
1771 tfn);
1772 (void) unlink (tfn);
1773 GNUNET_free (tfn);
1774 GNUNET_free (fn);
1775 return GNUNET_SYSERR;
1776 }
1777 }
1778 {
1779 struct stat sbuf;
1780
1781 /* rename(2) replaces the inode, so carry over the permissions of the
1782 configuration we are about to replace (we just created @a tfn). */
1783 if ( (0 == stat (fn,
1784 &sbuf)) &&
1785 (0 != chmod (tfn,
1786 sbuf.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO))) )
1788 "chmod",
1789 tfn);
1790 }
1791 if ( (NULL != expected_hash) &&
1792 (! file_hash_matches (fn,
1793 expected_hash)) )
1794 {
1796 "Configuration file `%s' changed while it was being cleaned\n",
1797 fn);
1798 (void) unlink (tfn);
1799 GNUNET_free (tfn);
1800 GNUNET_free (fn);
1801 return GNUNET_SYSERR;
1802 }
1803 if (0 != rename (tfn,
1804 fn))
1805 {
1807 "rename",
1808 fn);
1809 (void) unlink (tfn);
1810 GNUNET_free (tfn);
1811 GNUNET_free (fn);
1812 return GNUNET_SYSERR;
1813 }
1814 GNUNET_free (tfn);
1815 GNUNET_free (fn);
1816 return GNUNET_OK;
1817}
1818
1819
1823 const char *filename)
1824{
1826 char *cfg_buf;
1827 size_t size;
1828
1830 &size);
1832 cfg_buf,
1833 size,
1834 NULL);
1835 GNUNET_free (cfg_buf);
1837 return ret;
1838}
1839
1840
1844struct CleanLine
1845{
1846 const char *section;
1847 const char *option;
1848 unsigned int line;
1849 bool remove;
1850};
1851
1852
1856static struct CleanLine *
1857find_clean_line (struct CleanLine *lines,
1858 unsigned int lines_length,
1859 unsigned int line)
1860{
1861 for (unsigned int i = 0; i < lines_length; i++)
1862 if (lines[i].line == line)
1863 return &lines[i];
1864 return NULL;
1865}
1866
1867
1871static bool
1873 const char *target,
1874 struct CleanLine *lines,
1875 unsigned int lines_length)
1876{
1877 struct CleanLine *line;
1878
1879 if (0 != strcmp (source->filename,
1880 target))
1881 return false;
1882 line = find_clean_line (lines,
1883 lines_length,
1884 source->lineno);
1885 return (NULL != line) && line->remove;
1886}
1887
1888
1892static int
1893clean_line_cmp (const void *a,
1894 const void *b)
1895{
1896 const struct CleanLine *la = a;
1897 const struct CleanLine *lb = b;
1898
1899 if (la->line < lb->line)
1900 return -1;
1901 if (la->line > lb->line)
1902 return 1;
1903 return 0;
1904}
1905
1906
1909 const struct GNUNET_CONFIGURATION_Handle *cfg,
1910 const char *filename,
1912 void *cb_cls,
1913 unsigned int *removed)
1914{
1915 struct CleanLine *lines = NULL;
1916 unsigned int lines_length = 0;
1917 const struct ConfigFile *parsed_file = NULL;
1918 char *target;
1919 char *contents = NULL;
1920 char *cleaned = NULL;
1921 size_t size;
1922 size_t cleaned_size = 0;
1924
1925 if (NULL != removed)
1926 *removed = 0;
1927 if ( (! cfg->diagnostics) ||
1928 (NULL == filename) )
1929 return GNUNET_SYSERR;
1931 if (NULL == target)
1932 return GNUNET_SYSERR;
1933
1934 for (const struct ConfigFile *cf = cfg->loaded_files_head;
1935 NULL != cf;
1936 cf = cf->next)
1937 {
1938 char *source;
1939
1940 if (! cf->have_content_hash)
1941 continue;
1942 source = GNUNET_STRINGS_filename_expand (cf->source_filename);
1943 if ( (NULL != source) &&
1944 (0 == strcmp (source,
1945 target)) )
1946 parsed_file = cf;
1948 }
1949 if (NULL == parsed_file)
1950 {
1952 "Configuration file `%s' was not parsed with diagnostics enabled\n",
1953 target);
1954 goto cleanup;
1955 }
1956 if (GNUNET_OK != read_file (target,
1957 &contents,
1958 &size))
1959 {
1961 "Configuration file `%s' changed since it was parsed\n",
1962 target);
1963 goto cleanup;
1964 }
1965 {
1966 struct GNUNET_HashCode actual;
1967
1968 GNUNET_CRYPTO_hash (contents,
1969 size,
1970 &actual);
1971 if (0 != GNUNET_memcmp (&actual,
1972 &parsed_file->content_hash))
1973 {
1975 "Configuration file `%s' changed since it was parsed\n",
1976 target);
1977 goto cleanup;
1978 }
1979 }
1980
1981 /* First mark every target definition that has an exact duplicate at a
1982 distinct source location. */
1983 for (const struct ConfigSection *sec = cfg->sections;
1984 NULL != sec;
1985 sec = sec->next)
1986 for (const struct ConfigEntry *ent = sec->entries;
1987 NULL != ent;
1988 ent = ent->next)
1989 for (const struct ConfigSource *source = ent->sources;
1990 NULL != source;
1991 source = source->next)
1992 {
1993 bool duplicate = false;
1994 struct CleanLine line;
1995
1996 if (0 != strcmp (source->filename,
1997 target))
1998 continue;
1999 for (const struct ConfigSource *other = ent->sources;
2000 NULL != other;
2001 other = other->next)
2002 {
2003 if ( (0 == strcmp (source->value,
2004 other->value)) &&
2005 ( (source->lineno != other->lineno) ||
2006 (0 != strcmp (source->filename,
2007 other->filename)) ) )
2008 {
2009 duplicate = true;
2010 break;
2011 }
2012 }
2013 if ( (! duplicate) ||
2014 (NULL != find_clean_line (lines,
2015 lines_length,
2016 source->lineno)) )
2017 continue;
2018 line.section = sec->name;
2019 line.option = ent->key;
2020 line.line = source->lineno;
2021 line.remove = true;
2022 GNUNET_array_append (lines,
2023 lines_length,
2024 line);
2025 }
2026
2027 /* Keep the highest-precedence target duplicate needed to preserve every
2028 effective value after all of the tentative removals. */
2029 for (const struct ConfigSection *sec = cfg->sections;
2030 NULL != sec;
2031 sec = sec->next)
2032 for (const struct ConfigEntry *ent = sec->entries;
2033 NULL != ent;
2034 ent = ent->next)
2035 {
2036 const struct ConfigSource *survivor = NULL;
2037
2038 for (const struct ConfigSource *source = ent->sources;
2039 NULL != source;
2040 source = source->next)
2042 target,
2043 lines,
2044 lines_length))
2045 {
2046 survivor = source;
2047 break;
2048 }
2049 if ( (NULL != survivor) &&
2050 (0 == strcmp (survivor->value,
2051 ent->val)) )
2052 continue;
2053 for (const struct ConfigSource *source = ent->sources;
2054 NULL != source;
2055 source = source->next)
2056 {
2057 struct CleanLine *line;
2058
2059 if ( (0 != strcmp (source->filename,
2060 target)) ||
2061 (0 != strcmp (source->value,
2062 ent->val)) )
2063 continue;
2064 line = find_clean_line (lines,
2065 lines_length,
2066 source->lineno);
2067 if ( (NULL != line) && line->remove)
2068 {
2069 line->remove = false;
2070 break;
2071 }
2072 }
2073 }
2074
2075 if (lines_length > 1)
2076 qsort (lines,
2077 lines_length,
2078 sizeof (*lines),
2080 {
2081 unsigned int remove_count = 0;
2082
2083 for (unsigned int i = 0; i < lines_length; i++)
2084 if (lines[i].remove)
2085 remove_count++;
2086 if (0 == remove_count)
2087 {
2088 if (NULL != removed)
2089 *removed = 0;
2090 ret = GNUNET_OK;
2091 goto cleanup;
2092 }
2093
2094 cleaned = GNUNET_malloc (size);
2095 for (size_t offset = 0, line_number = 1; offset < size; line_number++)
2096 {
2097 size_t end = offset;
2098 struct CleanLine *line;
2099
2100 while ( (end < size) && ('\n' != contents[end]) )
2101 end++;
2102 if (end < size)
2103 end++;
2104 line = find_clean_line (lines,
2105 lines_length,
2106 (unsigned int) line_number);
2107 if ( (NULL == line) || (! line->remove) )
2108 {
2109 GNUNET_memcpy (&cleaned[cleaned_size],
2110 &contents[offset],
2111 end - offset);
2112 cleaned_size += end - offset;
2113 }
2114 offset = end;
2115 }
2116 if (GNUNET_OK !=
2117 write_buffer_atomic (target,
2118 cleaned,
2119 cleaned_size,
2120 &parsed_file->content_hash))
2121 goto cleanup;
2122 if (NULL != removed)
2123 *removed = remove_count;
2124 if (NULL != cb)
2125 for (unsigned int i = 0; i < lines_length; i++)
2126 if (lines[i].remove)
2127 cb (cb_cls,
2128 lines[i].section,
2129 lines[i].option,
2130 lines[i].line);
2131 ret = GNUNET_OK;
2132 }
2133
2134cleanup:
2135 GNUNET_free (cleaned);
2136 GNUNET_free (contents);
2137 GNUNET_array_grow (lines,
2138 lines_length,
2139 0);
2140 GNUNET_free (target);
2141 return ret;
2142}
2143
2144
2145void
2147 const struct GNUNET_CONFIGURATION_Handle *cfg,
2149 void *iter_cls)
2150{
2151 for (struct ConfigSection *spos = cfg->sections;
2152 NULL != spos;
2153 spos = spos->next)
2154 for (struct ConfigEntry *epos = spos->entries;
2155 NULL != epos;
2156 epos = epos->next)
2157 if (NULL != epos->val)
2158 iter (iter_cls,
2159 spos->name,
2160 epos->key,
2161 epos->val);
2162}
2163
2164
2165void
2167 const struct GNUNET_CONFIGURATION_Handle *cfg,
2168 const char *section,
2170 void *iter_cls)
2171{
2172 struct ConfigSection *spos;
2173
2174 spos = cfg->sections;
2175 while ((spos != NULL) && (0 != strcasecmp (spos->name, section)))
2176 spos = spos->next;
2177 if (NULL == spos)
2178 return;
2179 for (struct ConfigEntry *epos = spos->entries;
2180 NULL != epos;
2181 epos = epos->next)
2182 if (NULL != epos->val)
2183 iter (iter_cls,
2184 spos->name,
2185 epos->key,
2186 epos->val);
2187 if (spos->inaccessible)
2188 {
2190 "Section '%s' is marked as inaccessible, because a configuration "
2191 "file that contains the section can't be read.\n",
2192 section);
2193 return;
2194 }
2195}
2196
2197
2198void
2200 const struct GNUNET_CONFIGURATION_Handle *cfg,
2202 void *iter_cls)
2203{
2204 struct ConfigSection *spos;
2205 struct ConfigSection *next;
2206
2207 next = cfg->sections;
2208 while (NULL != next)
2209 {
2210 spos = next;
2211 next = spos->next;
2212 if (spos->inaccessible && (NULL == spos->entries))
2213 continue;
2214 iter (iter_cls,
2215 spos->name);
2216 }
2217}
2218
2219
2220void
2222 const char *section)
2223{
2224 struct ConfigSection *spos;
2225 struct ConfigSection *prev;
2226 struct ConfigEntry *ent;
2227
2228 prev = NULL;
2229 spos = cfg->sections;
2230 while (NULL != spos)
2231 {
2232 if (0 == strcasecmp (section,
2233 spos->name))
2234 {
2235 if (NULL == prev)
2236 cfg->sections = spos->next;
2237 else
2238 prev->next = spos->next;
2239 while (NULL != (ent = spos->entries))
2240 {
2241 struct ConfigSource *source;
2242
2243 spos->entries = ent->next;
2244 GNUNET_free (ent->key);
2245 GNUNET_free (ent->val);
2246 while (NULL != (source = ent->sources))
2247 {
2248 ent->sources = source->next;
2249 GNUNET_free (source->value);
2250 GNUNET_free (source->filename);
2252 }
2253 GNUNET_free (ent);
2254 cfg->dirty = GNUNET_YES;
2255 }
2256 GNUNET_free (spos->name);
2260 GNUNET_free (spos);
2261 return;
2262 }
2263 prev = spos;
2264 spos = spos->next;
2265 }
2266}
2267
2268
2278static void
2279copy_entry (void *cls,
2280 const char *section,
2281 const char *option,
2282 const char *value)
2283{
2284 struct GNUNET_CONFIGURATION_Handle *dst = cls;
2285
2287 section,
2288 option,
2289 value);
2290}
2291
2292
2295 const struct GNUNET_CONFIGURATION_Handle *cfg)
2296{
2298
2301 &copy_entry,
2302 ret);
2303 return ret;
2304}
2305
2306
2317static void
2318compare_entries (void *cls,
2319 const char *section,
2320 const char *option,
2321 const char *value)
2322{
2323 struct DiffHandle *dh = cls;
2324 struct ConfigEntry *entNew;
2325
2326 entNew = find_entry (dh->cfg_default, section, option);
2327 if ((NULL != entNew) && (NULL != entNew->val) &&
2328 (0 == strcmp (entNew->val, value)))
2329 return;
2331 section,
2332 option,
2333 value);
2334}
2335
2336
2339 const struct GNUNET_CONFIGURATION_Handle *cfg_default,
2340 const struct GNUNET_CONFIGURATION_Handle *cfg_new)
2341{
2342 struct DiffHandle diffHandle;
2343
2344 GNUNET_break (cfg_default->pd == cfg_new->pd);
2345 diffHandle.cfgDiff = GNUNET_CONFIGURATION_create (cfg_new->pd);
2346 diffHandle.cfg_default = cfg_default;
2349 &diffHandle);
2350 return diffHandle.cfgDiff;
2351}
2352
2353
2357 const struct GNUNET_CONFIGURATION_Handle *cfg_new,
2358 const char *filename)
2359{
2360 int ret;
2361 struct GNUNET_CONFIGURATION_Handle *diff;
2362
2363 diff = GNUNET_CONFIGURATION_get_diff (cfg_default, cfg_new);
2366 return ret;
2367}
2368
2369
2370void
2373 const char *section,
2374 const char *option,
2375 const char *value)
2376{
2377 struct ConfigSection *sec;
2378 struct ConfigEntry *e;
2379 char *nv;
2380
2381 e = find_entry (cfg, section, option);
2382 if (NULL != e)
2383 {
2384 if (NULL == value)
2385 {
2386 GNUNET_free (e->val);
2387 e->val = NULL;
2388 }
2389 else
2390 {
2391 nv = GNUNET_strdup (value);
2392 GNUNET_free (e->val);
2393 e->val = nv;
2394 }
2395 return;
2396 }
2397 sec = find_section (cfg, section);
2398 if (sec == NULL)
2399 {
2400 sec = GNUNET_new (struct ConfigSection);
2401 sec->name = GNUNET_strdup (section);
2402 sec->next = cfg->sections;
2403 cfg->sections = sec;
2404 }
2405 e = GNUNET_new (struct ConfigEntry);
2406 e->key = GNUNET_strdup (option);
2407 e->val = GNUNET_strdup (value);
2408 e->next = sec->entries;
2409 sec->entries = e;
2410}
2411
2412
2413void
2415 const char *section,
2416 const char *option,
2417 unsigned long long number)
2418{
2419 char s[64];
2420
2421 GNUNET_snprintf (s,
2422 64,
2423 "%llu",
2424 number);
2426 section,
2427 option,
2428 s);
2429}
2430
2431
2434 const struct GNUNET_CONFIGURATION_Handle *cfg,
2435 const char *section,
2436 const char *option,
2437 unsigned long long *number)
2438{
2439 struct ConfigEntry *e;
2440 char dummy[2];
2441
2442 if (NULL == (e = find_entry (cfg,
2443 section,
2444 option)))
2445 return GNUNET_NO;
2446 if (NULL == e->val)
2447 return GNUNET_NO;
2448 if (1 != sscanf (e->val,
2449 "%llu%1s",
2450 number,
2451 dummy))
2452 return GNUNET_SYSERR;
2453 return GNUNET_OK;
2454}
2455
2456
2457void
2459 const char *section,
2460 const char *option,
2461 float number)
2462{
2463 char s[64];
2464
2465 /* See: #9369 */
2466 const locale_t cl = newlocale (LC_NUMERIC_MASK,
2467 "C",
2468 (locale_t) 0);
2469 locale_t old_locale = uselocale (cl);
2470 GNUNET_snprintf (s,
2471 64,
2472 "%f",
2473 (double) number);
2474 uselocale (old_locale);
2476 section,
2477 option,
2478 s);
2479}
2480
2481
2484 const struct GNUNET_CONFIGURATION_Handle *cfg,
2485 const char *section,
2486 const char *option,
2487 float *number)
2488{
2489 struct ConfigEntry *e;
2490 char dummy[2];
2491
2492 if (NULL == (e = find_entry (cfg,
2493 section,
2494 option)))
2495 return GNUNET_NO;
2496 if (NULL == e->val)
2497 return GNUNET_NO;
2498 /* See #9369 */
2499 {
2500 const locale_t cl = newlocale (LC_NUMERIC_MASK,
2501 "C",
2502 (locale_t) 0);
2503 locale_t old_locale = uselocale (cl);
2504
2505 if (1 != sscanf (e->val,
2506 "%f%1s",
2507 number,
2508 dummy))
2509 return GNUNET_SYSERR;
2510 uselocale (old_locale);
2511 }
2512 return GNUNET_OK;
2513}
2514
2515
2518 const struct GNUNET_CONFIGURATION_Handle *cfg,
2519 const char *section,
2520 const char *option,
2521 struct GNUNET_TIME_Relative *time)
2522{
2523 struct ConfigEntry *e;
2524 int ret;
2525
2526 if (NULL == (e = find_entry (cfg,
2527 section,
2528 option)))
2529 return GNUNET_NO;
2530 if (NULL == e->val)
2531 return GNUNET_NO;
2533 time);
2534 if (GNUNET_OK != ret)
2536 section,
2537 option,
2538 _ ("Not a valid relative time specification"));
2539 return ret;
2540}
2541
2542
2545 const struct GNUNET_CONFIGURATION_Handle *cfg,
2546 const char *section,
2547 const char *option,
2548 unsigned long long *size)
2549{
2550 struct ConfigEntry *e;
2551
2552 if (NULL == (e = find_entry (cfg,
2553 section,
2554 option)))
2555 return GNUNET_NO;
2556 if (NULL == e->val)
2557 return GNUNET_NO;
2559 size);
2560}
2561
2562
2575 const struct GNUNET_CONFIGURATION_Handle *cfg,
2576 const char *section,
2577 const char *option,
2578 char **value)
2579{
2580 struct ConfigEntry *e;
2581
2582 if ( (NULL == (e = find_entry (cfg,
2583 section,
2584 option))) ||
2585 (NULL == e->val) )
2586 {
2587 *value = NULL;
2588 return GNUNET_NO;
2589 }
2590 *value = GNUNET_strdup (e->val);
2591 return GNUNET_OK;
2592}
2593
2594
2597 const struct GNUNET_CONFIGURATION_Handle *cfg,
2598 const char *section,
2599 const char *option,
2600 const char *const *choices,
2601 const char **value)
2602{
2603 struct ConfigEntry *e;
2604 unsigned int i;
2605
2606 if (NULL == (e = find_entry (cfg,
2607 section,
2608 option)))
2609 return GNUNET_NO;
2610 for (i = 0; NULL != choices[i]; i++)
2611 if (0 == strcasecmp (choices[i], e->val))
2612 break;
2613 if (NULL == choices[i])
2614 {
2616 _ ("Configuration value '%s' for '%s'"
2617 " in section '%s' is not in set of legal choices\n"),
2618 e->val,
2619 option,
2620 section);
2621 return GNUNET_SYSERR;
2622 }
2623 *value = choices[i];
2624 return GNUNET_OK;
2625}
2626
2627
2630 const char *section,
2631 const char *option,
2632 void *buf,
2633 size_t buf_size)
2634{
2635 char *enc;
2636 int res;
2637 size_t data_size;
2638
2639 if (GNUNET_OK !=
2640 (res =
2642 section,
2643 option,
2644 &enc)))
2645 return res;
2646 data_size = (strlen (enc) * 5) / 8;
2647 if (data_size != buf_size)
2648 {
2649 GNUNET_free (enc);
2650 return GNUNET_SYSERR;
2651 }
2652 if (GNUNET_OK !=
2654 strlen (enc),
2655 buf,
2656 buf_size))
2657 {
2658 GNUNET_free (enc);
2659 return GNUNET_SYSERR;
2660 }
2661 GNUNET_free (enc);
2662 return GNUNET_OK;
2663}
2664
2665
2668 const char *section,
2669 const char *option)
2670{
2671 struct ConfigEntry *e;
2672
2673 if ( (NULL == (e = find_entry (cfg,
2674 section,
2675 option))) ||
2676 (NULL == e->val) )
2677 return GNUNET_NO;
2678 return GNUNET_YES;
2679}
2680
2681
2697static char *
2699 char *orig,
2700 unsigned int depth)
2701{
2702 char *prefix;
2703 char *result;
2704 char *start;
2705 const char *post;
2706 const char *env;
2707 char *def;
2708 char *end;
2709 unsigned int lopen;
2710 char erased_char;
2711 char *erased_pos;
2712 size_t len;
2713
2714 if (NULL == orig)
2715 return NULL;
2716 if (depth > 128)
2717 {
2719 "Recursive expansion suspected, aborting $-expansion for term `%s'\n",
2720 orig);
2721 return orig;
2722 }
2724 "Asked to $-expand %s\n",
2725 orig);
2726 if ('$' != orig[0])
2727 {
2729 "Doesn't start with $ - not expanding\n");
2730 return orig;
2731 }
2732 erased_char = 0;
2733 erased_pos = NULL;
2734 if ('{' == orig[1])
2735 {
2736 start = &orig[2];
2737 lopen = 1;
2738 end = &orig[1];
2739 while (lopen > 0)
2740 {
2741 end++;
2742 switch (*end)
2743 {
2744 case '}':
2745 lopen--;
2746 break;
2747
2748 case '{':
2749 lopen++;
2750 break;
2751
2752 case '\0':
2754 "Missing closing `}' in option `%s'\n",
2755 orig);
2756 return orig;
2757
2758 default:
2759 break;
2760 }
2761 }
2762 erased_char = *end;
2763 erased_pos = end;
2764 *end = '\0';
2765 post = end + 1;
2766 def = strchr (orig, ':');
2767 if (NULL != def)
2768 {
2769 *def = '\0';
2770 def++;
2771 if (('-' == *def) || ('=' == *def))
2772 def++;
2773 def = GNUNET_strdup (def);
2774 }
2775 }
2776 else
2777 {
2778 int i;
2779
2780 start = &orig[1];
2781 def = NULL;
2782 i = 0;
2783 while ( (orig[i] != '/') &&
2784 (orig[i] != '\\') &&
2785 (orig[i] != '\0') &&
2786 (orig[i] != ' ') )
2787 i++;
2788 if (orig[i] == '\0')
2789 {
2790 post = "";
2791 }
2792 else
2793 {
2794 erased_char = orig[i];
2795 erased_pos = &orig[i];
2796 orig[i] = '\0';
2797 post = &orig[i + 1];
2798 }
2799 }
2801 "Split into `%s' and `%s' with default %s\n",
2802 start,
2803 post,
2804 def);
2805 if (GNUNET_OK !=
2807 "PATHS",
2808 start,
2809 &prefix))
2810 {
2811 if (NULL == (env = getenv (start)))
2812 {
2813 /* try default */
2814 def = expand_dollar (cfg,
2815 def,
2816 depth + 1);
2817 env = def;
2818 }
2819 if (NULL == env)
2820 {
2822 if (erased_pos)
2823 *erased_pos = erased_char;
2825 "Failed to expand `%s' in `%s' as it is neither found in [PATHS] nor defined as an environmental variable\n",
2826 start,
2827 orig);
2829 return orig;
2830 }
2832 }
2834 prefix);
2835 if ((erased_pos) && ('}' != erased_char))
2836 {
2837 len = strlen (prefix) + 1;
2838 prefix = GNUNET_realloc (prefix, len + 1);
2839 prefix[len - 1] = erased_char;
2840 prefix[len] = '\0';
2841 }
2842 result = GNUNET_malloc (strlen (prefix) + strlen (post) + 1);
2843 strcpy (result, prefix);
2844 strcat (result, post);
2845 GNUNET_free (def);
2847 GNUNET_free (orig);
2848 return result;
2849}
2850
2851
2852char *
2854 const struct GNUNET_CONFIGURATION_Handle *cfg,
2855 char *orig)
2856{
2857 char *dup;
2858 size_t i;
2859 size_t len;
2860
2861 for (i = 0; '\0' != orig[i]; i++)
2862 {
2863 if ('$' != orig[i])
2864 continue;
2865 dup = GNUNET_strdup (orig + i);
2866 dup = expand_dollar (cfg, dup, 0);
2867 GNUNET_assert (NULL != dup); /* make compiler happy */
2868 len = strlen (dup) + 1;
2869 orig = GNUNET_realloc (orig, i + len);
2870 GNUNET_memcpy (orig + i, dup, len);
2871 GNUNET_free (dup);
2872 }
2873 return orig;
2874}
2875
2876
2879 const struct GNUNET_CONFIGURATION_Handle *cfg,
2880 const char *section,
2881 const char *option,
2882 char **value)
2883{
2884 char *tmp;
2886
2888 section,
2889 option,
2890 &tmp);
2891 if (GNUNET_OK != ret)
2892 {
2894 "Failed to retrieve filename\n");
2895 *value = NULL;
2896 return ret;
2897 }
2899 tmp);
2901 GNUNET_free (tmp);
2902 if (*value == NULL)
2903 return GNUNET_SYSERR;
2904 return GNUNET_OK;
2905}
2906
2907
2910 const struct GNUNET_CONFIGURATION_Handle *cfg,
2911 const char *section,
2912 const char *option)
2913{
2914 static const char *yesno[] = {
2915 "YES",
2916 "NO",
2917 NULL
2918 };
2919 const char *val;
2921
2922 ret =
2924 section,
2925 option,
2926 yesno,
2927 &val);
2928 if (GNUNET_OK != ret)
2929 return ret;
2930 if (val == yesno[0])
2931 return GNUNET_YES;
2932 return GNUNET_NO;
2933}
2934
2935
2936int
2938 const struct GNUNET_CONFIGURATION_Handle *cfg,
2939 const char *section,
2940 const char *option,
2942 void *cb_cls)
2943{
2944 char *list;
2945 char *pos;
2946 char *end;
2947 char old;
2948 int ret;
2949
2950 if (GNUNET_OK !=
2952 section,
2953 option,
2954 &list))
2955 return 0;
2956 GNUNET_assert (list != NULL);
2957 ret = 0;
2958 pos = list;
2959 while (1)
2960 {
2961 while (pos[0] == ' ')
2962 pos++;
2963 if (strlen (pos) == 0)
2964 break;
2965 end = pos + 1;
2966 while ((end[0] != ' ') && (end[0] != '\0'))
2967 {
2968 if (end[0] == '\\')
2969 {
2970 switch (end[1])
2971 {
2972 case '\\':
2973 case ' ':
2974 memmove (end, &end[1], strlen (&end[1]) + 1);
2975
2976 case '\0':
2977 /* illegal, but just keep it */
2978 break;
2979
2980 default:
2981 /* illegal, but just ignore that there was a '/' */
2982 break;
2983 }
2984 }
2985 end++;
2986 }
2987 old = end[0];
2988 end[0] = '\0';
2989 if (strlen (pos) > 0)
2990 {
2991 ret++;
2992 if ( (NULL != cb) &&
2993 (GNUNET_OK != cb (cb_cls,
2994 pos)))
2995 {
2997 break;
2998 }
2999 }
3000 if (old == '\0')
3001 break;
3002 pos = end + 1;
3003 }
3004 GNUNET_free (list);
3005 return ret;
3006}
3007
3008
3015static char *
3016escape_name (const char *value)
3017{
3018 char *escaped;
3019 const char *rpos;
3020 char *wpos;
3021
3022 escaped = GNUNET_malloc (strlen (value) * 2 + 1);
3023 memset (escaped, 0, strlen (value) * 2 + 1);
3024 rpos = value;
3025 wpos = escaped;
3026 while (rpos[0] != '\0')
3027 {
3028 switch (rpos[0])
3029 {
3030 case '\\':
3031 case ' ':
3032 wpos[0] = '\\';
3033 wpos[1] = rpos[0];
3034 wpos += 2;
3035 break;
3036
3037 default:
3038 wpos[0] = rpos[0];
3039 wpos++;
3040 }
3041 rpos++;
3042 }
3043 return escaped;
3044}
3045
3046
3054static enum GNUNET_GenericReturnValue
3055test_match (void *cls,
3056 const char *fn)
3057{
3058 const char *of = cls;
3059
3060 return (0 == strcmp (of, fn))
3062 : GNUNET_OK;
3063}
3064
3065
3069 const char *section,
3070 const char *option,
3071 const char *value)
3072{
3073 char *escaped;
3074 char *old;
3075 char *nw;
3076
3077 if (GNUNET_SYSERR ==
3079 section,
3080 option,
3081 &test_match,
3082 (void *) value))
3083 return GNUNET_NO; /* already exists */
3084 if (GNUNET_OK !=
3085 GNUNET_CONFIGURATION_get_value_string (cfg, section, option, &old))
3086 old = GNUNET_strdup ("");
3087 escaped = escape_name (value);
3088 nw = GNUNET_malloc (strlen (old) + strlen (escaped) + 2);
3089 strcpy (nw, old);
3090 if (strlen (old) > 0)
3091 strcat (nw, " ");
3092 strcat (nw, escaped);
3094 section,
3095 option,
3096 nw);
3097 GNUNET_free (old);
3098 GNUNET_free (nw);
3099 GNUNET_free (escaped);
3100 return GNUNET_OK;
3101}
3102
3103
3107 const char *section,
3108 const char *option,
3109 const char *value)
3110{
3111 char *list;
3112 char *pos;
3113 char *end;
3114 char *match;
3115 char old;
3116
3117 if (GNUNET_OK !=
3119 section,
3120 option,
3121 &list))
3122 return GNUNET_NO;
3123 match = escape_name (value);
3124 pos = list;
3125 while (1)
3126 {
3127 while (pos[0] == ' ')
3128 pos++;
3129 if (strlen (pos) == 0)
3130 break;
3131 end = pos + 1;
3132 while ((end[0] != ' ') && (end[0] != '\0'))
3133 {
3134 if (end[0] == '\\')
3135 {
3136 switch (end[1])
3137 {
3138 case '\\':
3139 case ' ':
3140 end++;
3141 break;
3142
3143 case '\0':
3144 /* illegal, but just keep it */
3145 break;
3146
3147 default:
3148 /* illegal, but just ignore that there was a '/' */
3149 break;
3150 }
3151 }
3152 end++;
3153 }
3154 old = end[0];
3155 end[0] = '\0';
3156 if (0 == strcmp (pos, match))
3157 {
3158 if (old != '\0')
3159 memmove (pos,
3160 &end[1],
3161 strlen (&end[1]) + 1);
3162 else
3163 {
3164 if (pos != list)
3165 pos[-1] = '\0';
3166 else
3167 pos[0] = '\0';
3168 }
3170 section,
3171 option,
3172 list);
3173 GNUNET_free (list);
3174 GNUNET_free (match);
3175 return GNUNET_OK;
3176 }
3177 if (old == '\0')
3178 break;
3179 end[0] = old;
3180 pos = end + 1;
3181 }
3182 GNUNET_free (list);
3183 GNUNET_free (match);
3184 return GNUNET_NO;
3185}
3186
3187
3191 const char *defaults_d)
3192{
3193 struct CollectFilesContext files_context = {
3194 .files = NULL,
3195 .files_length = 0,
3196 };
3197 enum GNUNET_GenericReturnValue fun_ret = GNUNET_NO;
3198
3199 if (GNUNET_SYSERR ==
3200 GNUNET_DISK_directory_scan (defaults_d,
3202 &files_context))
3203 return GNUNET_SYSERR; /* no configuration at all found */
3204 qsort (files_context.files,
3205 files_context.files_length,
3206 sizeof (char *),
3207 &pstrcmp);
3208 for (unsigned int i = 0; i < files_context.files_length; i++)
3209 {
3210 const char *ext;
3211 const char *filename = files_context.files[i];
3212
3213 /* Examine file extension */
3214 ext = strrchr (filename, '.');
3215 if ( (NULL == ext) ||
3216 (0 != strcmp (ext,
3217 ".conf")) )
3218 {
3220 "Skipping file `%s'\n",
3221 filename);
3222 fun_ret = GNUNET_OK;
3223 continue;
3224 }
3226 filename);
3227 if (fun_ret != GNUNET_OK)
3228 break;
3229 }
3230 if (files_context.files_length > 0)
3231 {
3232 for (size_t i = 0; i < files_context.files_length; i++)
3233 GNUNET_free (files_context.files[i]);
3234 GNUNET_array_grow (files_context.files,
3235 files_context.files_length,
3236 0);
3237 }
3238 return fun_ret;
3239}
3240
3241
3242char *
3244 const struct GNUNET_OS_ProjectData *pd)
3245{
3246 char *cfg_fn;
3247 const char *xdg = getenv ("XDG_CONFIG_HOME");
3248
3249 if (NULL != xdg)
3250 GNUNET_asprintf (&cfg_fn,
3251 "%s%s%s",
3252 xdg,
3254 pd->config_file);
3255 else
3256 cfg_fn = GNUNET_strdup (pd->user_config_file);
3257
3258 if (GNUNET_OK == GNUNET_DISK_file_test_read (cfg_fn))
3259 return cfg_fn;
3260 GNUNET_free (cfg_fn);
3261
3262 /* Fall back to /etc/ for the default configuration.
3263 Should be okay to use forward slashes here. */
3264
3265 GNUNET_asprintf (&cfg_fn,
3266 "/etc/%s",
3267 pd->config_file);
3268 if (GNUNET_OK ==
3270 return cfg_fn;
3271 GNUNET_free (cfg_fn);
3272
3273 GNUNET_asprintf (&cfg_fn,
3274 "/etc/%s/%s",
3275 pd->project_dirname,
3276 pd->config_file);
3277 if (GNUNET_OK ==
3279 return cfg_fn;
3280
3281 GNUNET_free (cfg_fn);
3282 return NULL;
3283}
3284
3285
3289 const char *filename)
3290{
3291 char *baseconfig;
3292 const char *base_config_varname;
3293
3294 if (cfg->load_called)
3295 {
3296 /* FIXME: Make this a GNUNET_assert later */
3297 GNUNET_break (0);
3299 }
3300 cfg->load_called = true;
3301 if (NULL != filename)
3302 {
3305 }
3306
3307 base_config_varname = cfg->pd->base_config_varname;
3308
3309 if ((NULL != base_config_varname)
3310 && (NULL != (baseconfig = getenv (base_config_varname))))
3311 {
3312 baseconfig = GNUNET_strdup (baseconfig);
3313 }
3314 else
3315 {
3316 char *ipath;
3317
3320 if (NULL == ipath)
3321 {
3322 GNUNET_break (0);
3323 return GNUNET_SYSERR;
3324 }
3325 GNUNET_asprintf (&baseconfig,
3326 "%s%s",
3327 ipath,
3328 "config.d");
3329 GNUNET_free (ipath);
3330 }
3331
3332 {
3333 char *dname = GNUNET_STRINGS_filename_expand (baseconfig);
3334
3335 GNUNET_free (baseconfig);
3336
3337 if ((GNUNET_YES ==
3339 GNUNET_YES)) &&
3340 (GNUNET_SYSERR ==
3342 dname)))
3343 {
3345 "Failed to load base configuration from '%s'\n",
3346 filename);
3347 GNUNET_free (dname);
3348 return GNUNET_SYSERR; /* no configuration at all found */
3349 }
3350 GNUNET_free (dname);
3351 }
3352 if ((NULL != filename) &&
3353 (GNUNET_OK !=
3355 filename)))
3356 {
3357 /* specified configuration not found */
3359 "Failed to load configuration from file '%s'\n",
3360 filename);
3361 return GNUNET_SYSERR;
3362 }
3363 if (((GNUNET_YES !=
3365 "PATHS",
3366 "DEFAULTCONFIG"))) &&
3367 (filename != NULL))
3369 "PATHS",
3370 "DEFAULTCONFIG",
3371 filename);
3372 return GNUNET_OK;
3373}
3374
3375
3384static void
3385print_filename_option (void *cls,
3386 const char *section,
3387 const char *option,
3388 const char *value)
3389{
3390 const struct GNUNET_CONFIGURATION_Handle *cfg = cls;
3391
3392 char *value_fn;
3393 char *fn;
3394
3397 section,
3398 option,
3399 &value_fn));
3400 fn = GNUNET_STRINGS_filename_expand (value_fn);
3401 if (NULL == fn)
3402 fn = value_fn;
3403 else
3404 GNUNET_free (value_fn);
3405 fprintf (stdout,
3406 "%s = %s\n",
3407 option,
3408 fn);
3409 GNUNET_free (fn);
3410}
3411
3412
3421static void
3422print_option (void *cls,
3423 const char *section,
3424 const char *option,
3425 const char *value)
3426{
3427 (void) cls;
3428 (void) section;
3429
3430 fprintf (stdout,
3431 "%s = %s\n",
3432 option,
3433 value);
3434}
3435
3436
3443static void
3444print_section_name (void *cls,
3445 const char *section)
3446{
3447 (void) cls;
3448 fprintf (stdout,
3449 "%s\n",
3450 section);
3451}
3452
3453
3454void
3456 void *cls,
3457 char *const *args,
3458 const char *cfgfile,
3459 const struct GNUNET_CONFIGURATION_Handle *cfg)
3460{
3461 struct GNUNET_CONFIGURATION_ConfigSettings *cs = cls;
3462 struct GNUNET_CONFIGURATION_Handle *out = NULL;
3463 struct GNUNET_CONFIGURATION_Handle *ncfg = NULL;
3464
3465 (void) args;
3466 if (cs->diagnostics &&
3467 (! cfg->diagnostics))
3468 {
3469 /* Re-parse the configuration with diagnostics enabled. */
3472 if (GNUNET_OK !=
3474 cfgfile))
3475 {
3476 fprintf (stderr,
3477 _ ("Failed to load config file `%s'"),
3478 cfgfile);
3479 return;
3480 }
3481 cfg = ncfg;
3482 }
3483
3484 if (cs->full)
3485 cs->rewrite = GNUNET_YES;
3486 if (cs->list_sections)
3487 {
3488 fprintf (stderr,
3489 _ ("The following sections are available:\n"));
3492 NULL);
3493 return;
3494 }
3495 if ( (! cs->rewrite) &&
3496 (NULL == cs->section) )
3497 {
3498 char *serialization;
3499
3500 if (! cs->diagnostics)
3501 {
3502 fprintf (stderr,
3503 _ ("%s, %s or %s argument is required\n"),
3504 "--section",
3505 "--list-sections",
3506 "--diagnostics");
3508 return;
3509 }
3510 serialization = (cs->diagnostics > 1)
3513 fprintf (stdout,
3514 "%s",
3515 serialization);
3516 GNUNET_free (serialization);
3517 }
3518 else if ( (NULL != cs->section) &&
3519 (NULL == cs->value) )
3520 {
3521 if (NULL == cs->option)
3522 {
3524 cfg,
3525 cs->section,
3526 cs->is_filename
3528 : &print_option,
3529 (void *) cfg);
3530 }
3531 else
3532 {
3533 char *value;
3534
3535 if (cs->is_filename)
3536 {
3537 if (GNUNET_OK !=
3539 cs->section,
3540 cs->option,
3541 &value))
3542 {
3544 cs->section,
3545 cs->option);
3547 return;
3548 }
3549 }
3550 else
3551 {
3552 if (GNUNET_OK !=
3554 cs->section,
3555 cs->option,
3556 &value))
3557 {
3559 cs->section,
3560 cs->option);
3562 return;
3563 }
3564 }
3565 fprintf (stdout,
3566 "%s\n",
3567 value);
3569 }
3570 }
3571 else if (NULL != cs->section)
3572 {
3573 if (NULL == cs->option)
3574 {
3575 fprintf (stderr,
3576 _ ("--option argument required to set value\n"));
3578 return;
3579 }
3582 cs->section,
3583 cs->option,
3584 cs->value);
3585 cs->rewrite = GNUNET_YES;
3586 }
3587 if (cs->rewrite)
3588 {
3589 char *cfg_fn = NULL;
3590
3591 if (NULL == out)
3593
3594 if (NULL == cfgfile)
3595 {
3596 const char *xdg = getenv ("XDG_CONFIG_HOME");
3597
3598 if (NULL != xdg)
3599 GNUNET_asprintf (&cfg_fn,
3600 "%s%s%s",
3601 xdg,
3603 cfg->pd->config_file);
3604 else
3605 cfg_fn = GNUNET_strdup (cfg->pd->user_config_file);
3606 cfgfile = cfg_fn;
3607 }
3608
3609 if (! cs->full)
3610 {
3611 struct GNUNET_CONFIGURATION_Handle *def;
3612
3614 if (GNUNET_OK !=
3616 NULL))
3617 {
3618 fprintf (stderr,
3619 _ ("failed to load configuration defaults"));
3620 cs->global_ret = 1;
3623 GNUNET_free (cfg_fn);
3624 return;
3625 }
3626 if (GNUNET_OK !=
3628 out,
3629 cfgfile))
3630 cs->global_ret = 2;
3632 }
3633 else
3634 {
3635 if (GNUNET_OK !=
3637 cfgfile))
3638 cs->global_ret = 2;
3639 }
3640 GNUNET_free (cfg_fn);
3641 }
3642 if (NULL != out)
3644 if (NULL != ncfg)
3646}
3647
3648
3649void
3652{
3653 GNUNET_free (cs->option);
3654 GNUNET_free (cs->section);
3655 GNUNET_free (cs->value);
3656}
3657
3658
3659const struct GNUNET_OS_ProjectData *
3661 const struct GNUNET_CONFIGURATION_Handle *cfg)
3662{
3663 return cfg->pd;
3664}
3665
3666
3667char *
3669 pd,
3670 const struct
3672 const char *progname)
3673{
3674 static char *cache;
3675 char *binary = NULL;
3676 char *path = NULL;
3677 size_t path_len;
3678
3679 if (GNUNET_YES ==
3681 GNUNET_NO,
3682 NULL,
3683 NULL))
3684 {
3685 return GNUNET_strdup (progname);
3686 }
3687 if (NULL != cache)
3688 path = cache;
3689 else
3691 "PATHS",
3692 "SUID_BINARY_PATH",
3693 &path);
3694 if ( (NULL == path) ||
3695 (0 == strlen (path)) )
3696 {
3697 if (NULL != path)
3698 GNUNET_free (path);
3699 cache = NULL;
3701 progname);
3702 }
3703 path_len = strlen (path);
3704 GNUNET_asprintf (&binary,
3705 "%s%s%s",
3706 path,
3707 (path[path_len - 1] == DIR_SEPARATOR) ? ""
3709 progname);
3710 cache = path;
3711 return binary;
3712}
3713
3714
3715/* end of configuration.c */
struct GNUNET_MQ_Envelope * env
Definition 005.c:1
static bool do_skip(const char *sec, const char *key)
Should we skip this configuration entry when serializing?
static void print_filename_option(void *cls, const char *section, const char *option, const char *value)
Print each option in a given section as a filename.
static bool source_is_removed(const struct ConfigSource *source, const char *target, struct CleanLine *lines, unsigned int lines_length)
Return whether a source is a target line currently marked for removal.
static struct CleanLine * find_clean_line(struct CleanLine *lines, unsigned int lines_length, unsigned int line)
Find a cleanup record for a physical line.
static int clean_line_cmp(const void *a, const void *b)
Sort cleanup records by source line.
static struct ConfigEntry * find_entry(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *key)
Find an entry from a configuration.
static enum GNUNET_GenericReturnValue handle_inline(struct GNUNET_CONFIGURATION_Handle *cfg, const char *path_or_glob, bool path_is_glob, const char *restrict_section, const char *source_filename, unsigned int source_lineno)
Handle an inline directive.
static void print_section_name(void *cls, const char *section)
Print out given section name.
static enum GNUNET_GenericReturnValue read_file(const char *filename, char **contents, size_t *size)
static char * escape_name(const char *value)
FIXME.
static void compare_entries(void *cls, const char *section, const char *option, const char *value)
A callback function, compares entries from two configurations (default against a new configuration) a...
static void add_entry_source(struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, const char *value, const char *filename, unsigned int line)
Record the source of a configuration value.
static char * serialize_diagnostics(const struct GNUNET_CONFIGURATION_Handle *cfg, bool verbose)
Serialize configuration diagnostics.
static enum GNUNET_GenericReturnValue test_match(void *cls, const char *fn)
FIXME.
static struct ConfigSection * find_section(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section)
Find a section entry from a configuration.
static enum GNUNET_GenericReturnValue write_buffer_atomic(const char *filename, const char *contents, size_t size, const struct GNUNET_HashCode *expected_hash)
Atomically replace a file with the given bytes.
static void copy_entry_with_sources(struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const struct ConfigEntry *entry)
Copy an entry parsed through an @inline-secret@ directive, including all diagnostic source informatio...
static int pstrcmp(const void *a, const void *b)
static char * expand_dollar(const struct GNUNET_CONFIGURATION_Handle *cfg, char *orig, unsigned int depth)
Expand an expression of the form "$FOO/BAR" to "DIRECTORY/BAR" where either in the "PATHS" section or...
static enum GNUNET_GenericReturnValue collect_files_cb(void *cls, const char *filename)
Function called with a filename.
#define LOG(kind,...)
static bool file_hash_matches(const char *filename, const struct GNUNET_HashCode *expected)
Check that a file still has the expected contents.
static void copy_entry(void *cls, const char *section, const char *option, const char *value)
Copy a configuration value to the given target configuration.
static void print_option(void *cls, const char *section, const char *option, const char *value)
Print each option in a given section.
static void dump_os_ipk(const struct GNUNET_CONFIGURATION_Handle *cfg, struct GNUNET_Buffer *buf, enum GNUNET_OS_InstallationPathKind ipk)
Dump an os installation path to a buffer.
char * getenv()
static struct GNUNET_ARM_Handle * h
Connection with ARM.
Definition gnunet-arm.c:98
static int start
Set if we are to start default services (including ARM).
Definition gnunet-arm.c:38
static int list
Set if we should print a list of currently running services.
Definition gnunet-arm.c:68
static int ret
Final status code.
Definition gnunet-arm.c:93
static struct GNUNET_CONFIGURATION_Handle * cfg
Our configuration.
Definition gnunet-arm.c:108
static int end
Set if we are to shutdown all services (including ARM).
Definition gnunet-arm.c:33
static int prefix
If printing the value of PREFIX has been requested.
static char * line
Desired phone line (string to be converted to a hash).
static unsigned int verbose
Be verbose.
struct GNUNET_HashCode key
The key used in the DHT.
static char * filename
static struct GNUNET_FS_Handle * fs
Handle to FS service.
Definition gnunet-fs.c:35
static GstElement * source
Appsrc instance into which we write data for the pipeline.
static OpusEncoder * enc
OPUS encoder.
static struct in_addr dummy
Target "dummy" address of the packet we pretend to respond to.
static char * res
Currently read line or NULL on EOF.
static char * value
Value of the record to add/remove.
static size_t data_size
Number of bytes in data.
static int status
The program status; 0 for success.
Definition gnunet-nse.c:39
static int result
Global testing status.
static void cleanup()
Cleanup task.
static struct GNUNET_Process * p
Helper process we started.
Definition gnunet-uri.c:38
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_data(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, void *buf, size_t buf_size)
Get Crockford32-encoded fixed-size binary data from a configuration.
struct GNUNET_CONFIGURATION_Handle * GNUNET_CONFIGURATION_create(const struct GNUNET_OS_ProjectData *pd)
Create a new configuration object.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_is_dirty(const struct GNUNET_CONFIGURATION_Handle *cfg)
Test if there are configuration options that were changed since the last save.
void GNUNET_CONFIGURATION_set_value_string(struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, const char *value)
Set a configuration value that should be a string.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_append_value_filename(struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, const char *value)
Append a filename to a configuration value that represents a list of filenames.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_filename(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, char **value)
Get a configuration value that should be the name of a file or directory.
void GNUNET_CONFIGURATION_remove_section(struct GNUNET_CONFIGURATION_Handle *cfg, const char *section)
Remove the given section and all options in it.
enum GNUNET_GenericReturnValue(* GNUNET_CONFIGURATION_Callback)(void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg)
Signature of a function to be run with a configuration.
struct GNUNET_CONFIGURATION_Handle * GNUNET_CONFIGURATION_dup(const struct GNUNET_CONFIGURATION_Handle *cfg)
Duplicate an existing configuration object.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_number(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, unsigned long long *number)
Get a configuration value that should be a number.
void GNUNET_CONFIGURATION_iterate_sections(const struct GNUNET_CONFIGURATION_Handle *cfg, GNUNET_CONFIGURATION_SectionIterator iter, void *iter_cls)
Iterate over all sections in the configuration.
void GNUNET_CONFIGURATION_destroy(struct GNUNET_CONFIGURATION_Handle *cfg)
Destroy configuration object.
char * GNUNET_CONFIGURATION_get_suid_binary_path(const struct GNUNET_OS_ProjectData *pd, const struct GNUNET_CONFIGURATION_Handle *cfg, const char *progname)
Given the name of a helper, service or daemon binary construct the full path to the binary using the ...
void GNUNET_CONFIGURATION_config_settings_free(struct GNUNET_CONFIGURATION_ConfigSettings *cs)
Free resources associated with cs.
void GNUNET_CONFIGURATION_iterate(const struct GNUNET_CONFIGURATION_Handle *cfg, GNUNET_CONFIGURATION_Iterator iter, void *iter_cls)
Iterate over all options in the configuration.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_remove_value_filename(struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, const char *value)
Remove a filename from a configuration value that represents a list of filenames.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_parse_and_run(const struct GNUNET_OS_ProjectData *pd, const char *filename, GNUNET_CONFIGURATION_Callback cb, void *cb_cls)
Parse a configuration file filename and run the function cb with the resulting configuration object.
void GNUNET_CONFIGURATION_config_tool_run(void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg)
Main task to run to perform operations typical for gnunet-config as per the configuration settings gi...
void(* GNUNET_CONFIGURATION_SectionIterator)(void *cls, const char *section)
Function to iterate over all configuration sections.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_deserialize(struct GNUNET_CONFIGURATION_Handle *cfg, const char *mem, size_t size, const char *source_filename)
De-serializes configuration.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_size(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, unsigned long long *size)
Get a configuration value that should be a size in bytes.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_yesno(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option)
Get a configuration value that should be in a set of "YES" or "NO".
char * GNUNET_CONFIGURATION_serialize(const struct GNUNET_CONFIGURATION_Handle *cfg, size_t *size)
Serializes the given configuration.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_time(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, struct GNUNET_TIME_Relative *time)
Get a configuration value that should be a relative time.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_string(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, char **value)
Get a configuration value that should be a string.
void GNUNET_CONFIGURATION_set_value_number(struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, unsigned long long number)
Set a configuration value that should be a number.
char * GNUNET_CONFIGURATION_default_filename(const struct GNUNET_OS_ProjectData *pd)
Return the filename of the default configuration filename that is used when no explicit configuration...
char * GNUNET_CONFIGURATION_expand_dollar(const struct GNUNET_CONFIGURATION_Handle *cfg, char *orig)
Expand an expression of the form "$FOO/BAR" to "DIRECTORY/BAR" where either in the "PATHS" section or...
void GNUNET_CONFIGURATION_set_value_float(struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, float number)
Set a configuration value that should be a float.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_clean_file(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *filename, GNUNET_CONFIGURATION_CleanCallback cb, void *cb_cls, unsigned int *removed)
Remove redundant option definitions from a parsed configuration file.
const struct GNUNET_OS_ProjectData * GNUNET_CONFIGURATION_get_project_data(const struct GNUNET_CONFIGURATION_Handle *cfg)
Return the project data associated with this configuration.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_load(struct GNUNET_CONFIGURATION_Handle *cfg, const char *filename)
Load configuration.
struct GNUNET_CONFIGURATION_Handle * GNUNET_CONFIGURATION_get_diff(const struct GNUNET_CONFIGURATION_Handle *cfg_default, const struct GNUNET_CONFIGURATION_Handle *cfg_new)
Compute configuration with only entries that have been changed.
char * GNUNET_CONFIGURATION_serialize_diagnostics_verbose(const struct GNUNET_CONFIGURATION_Handle *cfg)
Serializes the given configuration with verbose diagnostics information, including all source definit...
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_parse(struct GNUNET_CONFIGURATION_Handle *cfg, const char *filename)
Parse a configuration file, add all of the options in the file to the configuration environment.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_float(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, float *number)
Get a configuration value that should be a floating point number.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_load_from(struct GNUNET_CONFIGURATION_Handle *cfg, const char *defaults_d)
Load default configuration.
int GNUNET_CONFIGURATION_iterate_value_filenames(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, GNUNET_FileNameCallback cb, void *cb_cls)
Iterate over the set of filenames stored in a configuration value.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_have_value(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option)
Test if we have a value for a particular option.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_choice(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, const char *const *choices, const char **value)
Get a configuration value that should be in a set of predefined strings.
void(* GNUNET_CONFIGURATION_CleanCallback)(void *cls, const char *section, const char *option, unsigned int line)
Function called for each duplicate definition removed by GNUNET_CONFIGURATION_clean_file().
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_write(struct GNUNET_CONFIGURATION_Handle *cfg, const char *filename)
Write configuration file.
void(* GNUNET_CONFIGURATION_Iterator)(void *cls, const char *section, const char *option, const char *value)
Function to iterate over options.
void GNUNET_CONFIGURATION_iterate_section_values(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, GNUNET_CONFIGURATION_Iterator iter, void *iter_cls)
Iterate over values of a section in the configuration.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_write_diffs(const struct GNUNET_CONFIGURATION_Handle *cfg_default, const struct GNUNET_CONFIGURATION_Handle *cfg_new, const char *filename)
Write only configuration entries that have been changed to configuration file.
char * GNUNET_CONFIGURATION_serialize_diagnostics(const struct GNUNET_CONFIGURATION_Handle *cfg)
Serializes the given configuration with diagnostics information.
void GNUNET_CONFIGURATION_enable_diagnostics(struct GNUNET_CONFIGURATION_Handle *cfg)
Enable extra diagnostics.
struct GNUNET_DISK_FileHandle * GNUNET_DISK_file_open(const char *fn, enum GNUNET_DISK_OpenFlags flags, enum GNUNET_DISK_AccessPermissions perm)
Open a file.
Definition disk.c:1308
int GNUNET_DISK_glob(const char *glob_pattern, GNUNET_FileNameCallback callback, void *callback_cls)
Find all files matching a glob pattern.
Definition disk.c:1063
ssize_t GNUNET_DISK_file_write(const struct GNUNET_DISK_FileHandle *h, const void *buffer, size_t n)
Write a buffer to a file.
Definition disk.c:745
enum GNUNET_GenericReturnValue GNUNET_DISK_file_test_read(const char *fil)
Check that fil corresponds to a filename and the file has read permissions.
Definition disk.c:565
enum GNUNET_GenericReturnValue GNUNET_DISK_file_size(const char *filename, uint64_t *size, int include_symbolic_links, int single_file_mode)
Get the size of the file (or directory) of the given file (in bytes).
Definition disk.c:235
enum GNUNET_GenericReturnValue GNUNET_DISK_file_sync(const struct GNUNET_DISK_FileHandle *h)
Write file changes to disk.
Definition disk.c:1507
enum GNUNET_GenericReturnValue GNUNET_DISK_directory_test(const char *fil, int is_readable)
Test if fil is a directory and listable.
Definition disk.c:466
enum GNUNET_GenericReturnValue GNUNET_DISK_file_close(struct GNUNET_DISK_FileHandle *h)
Close an open file.
Definition disk.c:1386
enum GNUNET_GenericReturnValue GNUNET_DISK_directory_create_for_file(const char *filename)
Create the directory structure for storing a file.
Definition disk.c:664
ssize_t GNUNET_DISK_fn_read(const char *fn, void *result, size_t len)
Read the contents of a binary file into a buffer.
Definition disk.c:720
int GNUNET_DISK_directory_scan(const char *dir_name, GNUNET_FileNameCallback callback, void *callback_cls)
Scan a directory for files.
Definition disk.c:881
@ GNUNET_DISK_OPEN_WRITE
Open the file for writing.
@ GNUNET_DISK_OPEN_TRUNCATE
Truncate file if it exists.
@ GNUNET_DISK_OPEN_CREATE
Create file if it doesn't exist.
@ GNUNET_DISK_PERM_USER_READ
Owner can read.
@ GNUNET_DISK_PERM_GROUP_READ
Group can read.
@ GNUNET_DISK_PERM_GROUP_WRITE
Group can write.
@ GNUNET_DISK_PERM_USER_WRITE
Owner can write.
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
#define GNUNET_CONTAINER_DLL_insert_tail(head, tail, element)
Insert an element at the tail of a DLL.
void GNUNET_CRYPTO_hash(const void *block, size_t size, struct GNUNET_HashCode *ret)
Compute hash of a given block.
Definition crypto_hash.c:40
enum GNUNET_GenericReturnValue(* GNUNET_FileNameCallback)(void *cls, const char *filename)
Function called with a filename.
#define GNUNET_log(kind,...)
char * GNUNET_buffer_reap_str(struct GNUNET_Buffer *buf)
Clear the buffer and return the string it contained.
Definition buffer.c:89
void GNUNET_buffer_write_fstr(struct GNUNET_Buffer *buf, const char *fmt,...) __attribute__((format(printf
Write a 0-terminated formatted string to a buffer, excluding the 0-terminator.
#define GNUNET_memcmp(a, b)
Compare memory in a and b, where both must be of the same pointer type.
void GNUNET_buffer_write_str(struct GNUNET_Buffer *buf, const char *str)
Write a 0-terminated string to a buffer, excluding the 0-terminator.
Definition buffer.c:77
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
GNUNET_GenericReturnValue
Named constants for return values.
@ GNUNET_OK
@ GNUNET_YES
@ GNUNET_NO
@ GNUNET_SYSERR
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur.
void GNUNET_log_config_invalid(enum GNUNET_ErrorType kind, const char *section, const char *option, const char *required)
Log error message about invalid configuration option value.
void GNUNET_log_config_missing(enum GNUNET_ErrorType kind, const char *section, const char *option)
Log error message about missing configuration option.
#define GNUNET_log_strerror_file(level, cmd, filename)
Log an error message at log-level 'level' that indicates a failure of the command 'cmd' with the mess...
@ GNUNET_ERROR_TYPE_WARNING
@ GNUNET_ERROR_TYPE_ERROR
@ GNUNET_ERROR_TYPE_DEBUG
@ GNUNET_ERROR_TYPE_INFO
int int GNUNET_asprintf(char **buf, const char *format,...) __attribute__((format(printf
Like asprintf, just portable.
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
#define GNUNET_array_grow(arr, size, tsize)
Grow a well-typed (!) array.
#define GNUNET_strndup(a, length)
Wrapper around GNUNET_xstrndup_.
int GNUNET_snprintf(char *buf, size_t size, const char *format,...) __attribute__((format(printf
Like snprintf, just aborts if the buffer is of insufficient size.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
#define GNUNET_malloc(size)
Wrapper around malloc.
#define GNUNET_realloc(ptr, size)
Wrapper around realloc.
#define GNUNET_array_append(arr, len, element)
Append an element to an array (growing the array by one).
#define GNUNET_free(ptr)
Wrapper around free.
char * GNUNET_OS_installation_get_path(const struct GNUNET_OS_ProjectData *pd, enum GNUNET_OS_InstallationPathKind dirkind)
Get the path to a specific GNUnet installation directory or, with GNUNET_OS_IPK_SELF_PREFIX,...
GNUNET_OS_InstallationPathKind
Possible installation paths to request.
char * GNUNET_OS_get_libexec_binary_path(const struct GNUNET_OS_ProjectData *pd, const char *progname)
Given the name of a gnunet-helper, gnunet-service or gnunet-daemon binary, try to prefix it with the ...
@ GNUNET_OS_IPK_SELF_PREFIX
Return the installation directory of this application, not the one of the overall GNUnet installation...
@ GNUNET_OS_IPK_ICONDIR
Return the prefix of the path with application icons (share/icons/).
@ GNUNET_OS_IPK_DATADIR
Return the directory where data is installed (share/gnunet/)
@ GNUNET_OS_IPK_DOCDIR
Return the prefix of the path with documentation files, including the license (share/doc/gnunet/).
@ GNUNET_OS_IPK_LOCALEDIR
Return the directory where translations are installed (share/locale/)
@ GNUNET_OS_IPK_LIBDIR
Return the directory where libraries are installed.
@ GNUNET_OS_IPK_PREFIX
Return the "PREFIX" directory given to configure.
@ GNUNET_OS_IPK_BINDIR
Return the directory where the program binaries are installed.
@ GNUNET_OS_IPK_LIBEXECDIR
Return the directory where helper binaries are installed (lib/gnunet/libexec/)
char * GNUNET_STRINGS_filename_expand(const char *fil)
Complete filename (a la shell) from abbrevition.
Definition strings.c:531
enum GNUNET_GenericReturnValue GNUNET_STRINGS_string_to_data(const char *enc, size_t enclen, void *out, size_t out_size)
Convert CrockfordBase32 encoding back to data.
Definition strings.c:843
enum GNUNET_GenericReturnValue GNUNET_STRINGS_path_is_absolute(const char *filename, int can_be_uri, int *r_is_uri, char **r_uri_scheme)
Check whether filename is absolute or not, and if it's an URI.
Definition strings.c:1012
enum GNUNET_GenericReturnValue GNUNET_STRINGS_fancy_time_to_relative(const char *fancy_time, struct GNUNET_TIME_Relative *rtime)
Convert a given fancy human-readable time to our internal representation.
Definition strings.c:259
enum GNUNET_GenericReturnValue GNUNET_STRINGS_fancy_size_to_bytes(const char *fancy_size, unsigned long long *size)
Convert a given fancy human-readable size to bytes.
Definition strings.c:235
static unsigned int size
Size of the "table".
Definition peer.c:68
#define DIR_SEPARATOR
Definition platform.h:166
#define DIR_SEPARATOR_STR
Definition platform.h:167
#define _(String)
GNU gettext support macro.
Definition platform.h:179
#define SIZE_MAX
Definition platform.h:213
#define EXIT_INVALIDARGUMENT
Definition platform.h:258
#define EXIT_NOTCONFIGURED
Definition platform.h:274
uint32_t number
One physical assignment line considered for removal.
const char * option
unsigned int line
const char * section
Closure to collect_files_cb.
char ** files
Collected files from globbing.
unsigned int files_length
Size of the files array.
configuration entry
struct ConfigEntry * next
This is a linked list.
char * key
key for this entry
struct ConfigSource * sources
Source definitions retained for diagnostics.
char * val
current, committed value
char * hint_restrict_section
Was this configuration file parsed via @inline-secret@?
struct ConfigFile * next
char * source_filename
Source filename.
bool hint_inaccessible
Was this configuration file inaccessible?
struct ConfigFile * prev
bool have_content_hash
Whether content_hash is available.
unsigned int level
Level in the tree of loaded config files.
struct GNUNET_HashCode content_hash
Hash of the file contents seen while parsing.
configuration section
char * name
name of the section
char * hint_inlined_from_filename
For secret sections: Where was this inlined from?
struct ConfigEntry * entries
entries in the section
bool inaccessible
Is the configuration section marked as inaccessible?
struct ConfigSection * next
This is a linked list.
char * hint_secret_filename
Diagnostics hint for the secret file.
unsigned int hint_inlined_from_line
For secret sections: Where was this inlined from?
char * hint_secret_stat
Extra information regarding permissions of the secret file.
source location of a configuration value
char * value
Value as normalized by the configuration parser.
unsigned int lineno
Line containing the definition.
char * filename
Filename containing the definition.
struct ConfigSource * next
Sources are ordered from highest to lowest precedence.
Used for diffing a configuration object against the default one.
const struct GNUNET_CONFIGURATION_Handle * cfg_default
struct GNUNET_CONFIGURATION_Handle * cfgDiff
Dynamically growing buffer.
Closure for GNUNET_CONFIGURATION_config_tool_run() with settings for what should be done with the con...
int full
Should the generated configuration file contain the whole configuration?
int global_ret
Return value from the operation, to be returned from 'main'.
int list_sections
Whether to show the sections.
int rewrite
Should we write out the configuration file, even if no value was changed?
int is_filename
Treat option as a filename.
unsigned int diagnostics
Diagnostics verbosity.
struct ConfigFile * loaded_files_tail
Linked list of loaded files.
bool load_called
Was the configuration ever loaded via GNUNET_CONFIGURATION_load?
unsigned int current_nest_level
Current nesting level of file loading.
const struct GNUNET_OS_ProjectData * pd
Project data for this configuration object.
struct ConfigSection * sections
Configuration sections.
struct ConfigFile * loaded_files_head
Linked list of loaded files.
char * main_filename
Name of the entry point configuration file.
enum GNUNET_GenericReturnValue dirty
Modification indication since last save GNUNET_NO if clean, GNUNET_YES if dirty, GNUNET_SYSERR on err...
bool diagnostics
Enable diagnostics.
const char * restrict_section
When parsing into this configuration, and this value is non-NULL, only parse sections of the same nam...
Handle used to access files (and pipes).
A 512-bit hashcode.
Project-specific data used to help the OS subsystem find installation paths.
const char * base_config_varname
Name of an environment variable that can be used to override the location from which default configur...
const char * project_dirname
Name of the project that is used in the "libexec" prefix, For example, "gnunet".
const char * user_config_file
Configuration file name to use (if $XDG_CONFIG_HOME is not set).
const char * config_file
Configuration file name (in $XDG_CONFIG_HOME) to use.
Time for relative time used by GNUnet, in microseconds.

Function Documentation

◆ collect_files_cb()

static enum GNUNET_GenericReturnValue collect_files_cb ( void *  cls,
const char *  filename 
)
static

Function called with a filename.

Parameters
clsclosure
filenamecomplete filename (absolute path)
Returns
GNUNET_OK to continue to iterate, GNUNET_NO to stop iteration with no error, GNUNET_SYSERR to abort iteration with error!

Definition at line 426 of file configuration.c.

428{
429 struct CollectFilesContext *igc = cls;
430
432 igc->files_length,
434 return GNUNET_OK;
435}

References filename, CollectFilesContext::files, CollectFilesContext::files_length, GNUNET_array_append, GNUNET_OK, and GNUNET_strdup.

Referenced by GNUNET_CONFIGURATION_load_from(), and handle_inline().

Here is the caller graph for this function:

◆ find_section()

static struct ConfigSection * find_section ( const struct GNUNET_CONFIGURATION_Handle cfg,
const char *  section 
)
static

Find a section entry from a configuration.

Parameters
cfgconfiguration to search in
sectionname of the section to look for
Returns
matching entry, NULL if not found

Definition at line 446 of file configuration.c.

448{
449 struct ConfigSection *pos;
450
451 if (NULL == cfg)
452 return NULL;
453 pos = cfg->sections;
454 while ( (NULL != pos) &&
455 (0 != strcasecmp (section,
456 pos->name)) )
457 pos = pos->next;
458 return pos;
459}

References cfg, ConfigSection::name, ConfigSection::next, and GNUNET_CONFIGURATION_Handle::sections.

Referenced by find_entry(), GNUNET_CONFIGURATION_set_value_string(), and handle_inline().

Here is the caller graph for this function:

◆ pstrcmp()

static int pstrcmp ( const void *  a,
const void *  b 
)
static

Definition at line 463 of file configuration.c.

465{
466 return strcmp (*((const char **) a),
467 *((const char **) b));
468}

Referenced by GNUNET_CONFIGURATION_load_from(), and handle_inline().

Here is the caller graph for this function:

◆ copy_entry_with_sources()

static void copy_entry_with_sources ( struct GNUNET_CONFIGURATION_Handle cfg,
const char *  section,
const struct ConfigEntry entry 
)
static

Copy an entry parsed through an @inline-secret@ directive, including all diagnostic source information.

Parameters
cfgdestination configuration
sectiondestination section
entrysource entry

Definition at line 791 of file configuration.c.

794{
795 struct ConfigEntry *dst;
796 struct ConfigSource *head = NULL;
797 struct ConfigSource *tail = NULL;
798
800 section,
801 entry->key,
802 entry->val);
803 if ( (! cfg->diagnostics) ||
804 (NULL == entry->sources) )
805 return;
806 dst = find_entry (cfg,
807 section,
808 entry->key);
809 GNUNET_assert (NULL != dst);
810 for (const struct ConfigSource *pos = entry->sources;
811 NULL != pos;
812 pos = pos->next)
813 {
814 struct ConfigSource *copy = GNUNET_new (struct ConfigSource);
815
816 copy->value = GNUNET_strdup (pos->value);
817 copy->filename = GNUNET_strdup (pos->filename);
818 copy->lineno = pos->lineno;
819 if (NULL == tail)
820 head = copy;
821 else
822 tail->next = copy;
823 tail = copy;
824 }
825 tail->next = dst->sources;
826 dst->sources = head;
827}

References cfg, GNUNET_CONFIGURATION_Handle::diagnostics, ConfigSource::filename, find_entry(), GNUNET_assert, GNUNET_CONFIGURATION_set_value_string(), GNUNET_new, GNUNET_strdup, ConfigEntry::key, ConfigSource::lineno, ConfigSource::next, ConfigEntry::sources, ConfigEntry::val, and ConfigSource::value.

Referenced by handle_inline().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ handle_inline()

static enum GNUNET_GenericReturnValue handle_inline ( struct GNUNET_CONFIGURATION_Handle cfg,
const char *  path_or_glob,
bool  path_is_glob,
const char *  restrict_section,
const char *  source_filename,
unsigned int  source_lineno 
)
static

Handle an inline directive.

Returns
GNUNET_SYSERR on error, GNUNET_OK otherwise

Definition at line 483 of file configuration.c.

489{
490 char *inline_path = NULL;
491 struct GNUNET_CONFIGURATION_Handle *other_cfg = NULL;
492 struct CollectFilesContext igc = {
493 .files = NULL,
494 .files_length = 0,
495 };
496 enum GNUNET_GenericReturnValue fun_ret;
497 unsigned int old_nest_level = cfg->current_nest_level++;
498
499 /* We support the section restriction only for non-globs */
500 GNUNET_assert (! (path_is_glob && (NULL != restrict_section)));
501
502 if (NULL == source_filename)
503 {
505 "Refusing to parse inline configurations, "
506 "not allowed without source filename!\n");
507 fun_ret = GNUNET_SYSERR;
508 goto cleanup;
509 }
510
511 if ('/' == *path_or_glob)
512 inline_path = GNUNET_strdup (path_or_glob);
513 else
514 {
515 /* We compute the canonical, absolute path first,
516 so that relative imports resolve properly with symlinked
517 config files. */
518 char *source_realpath;
519 char *endsep;
520
521 source_realpath = realpath (source_filename,
522 NULL);
523 if (NULL == source_realpath)
524 {
525 /* Couldn't even resolve path of base dir. */
526 GNUNET_break (0);
527 /* failed to parse included config */
528 fun_ret = GNUNET_SYSERR;
529 goto cleanup;
530 }
531 endsep = strrchr (source_realpath, '/');
532 GNUNET_assert (NULL != endsep);
533 *endsep = '\0';
534 GNUNET_asprintf (&inline_path,
535 "%s/%s",
536 source_realpath,
537 path_or_glob);
538 free (source_realpath);
539 }
540
541 if (path_is_glob)
542 {
543 int nret;
544
546 "processing config glob '%s'\n",
547 inline_path);
548
549 nret = GNUNET_DISK_glob (inline_path,
551 &igc);
552 if (-1 == nret)
553 {
554 fun_ret = GNUNET_SYSERR;
555 goto cleanup;
556 }
557 GNUNET_assert (nret == igc.files_length);
558 qsort (igc.files,
559 igc.files_length,
560 sizeof (char *),
561 &pstrcmp);
562 for (int i = 0; i < nret; i++)
563 {
564 if (GNUNET_OK !=
566 igc.files[i]))
567 {
568 fun_ret = GNUNET_SYSERR;
569 goto cleanup;
570 }
571 }
572 fun_ret = GNUNET_OK;
573 }
574 else if (NULL != restrict_section)
575 {
576 enum GNUNET_GenericReturnValue inner_ret;
577 struct ConfigSection *cs;
578 struct ConfigFile *cf = GNUNET_new (struct ConfigFile);
579
580 inner_ret = GNUNET_DISK_file_test_read (inline_path);
581
582 cs = find_section (cfg, restrict_section);
583
584 if (NULL == cs)
585 {
586 cs = GNUNET_new (struct ConfigSection);
587 cs->name = GNUNET_strdup (restrict_section);
588 cs->next = cfg->sections;
589 cfg->sections = cs;
590 cs->entries = NULL;
591 }
592 if (cfg->diagnostics)
593 {
594 const char *pwname;
595 const char *grname;
596 char *sfn = GNUNET_STRINGS_filename_expand (inline_path);
597 struct stat istat;
598
599 cs->hint_secret_filename = sfn;
600 if (0 == stat (sfn, &istat))
601 {
602 struct passwd *pw = getpwuid (istat.st_uid);
603 struct group *gr = getgrgid (istat.st_gid);
604 pwname = (NULL == pw) ? "<unknown>" : pw->pw_name;
605 grname = (NULL == gr) ? "<unknown>" : gr->gr_name;
606
608 "%s:%s %o",
609 pwname,
610 grname,
611 istat.st_mode);
612 }
613 else
614 {
615 cs->hint_secret_stat = GNUNET_strdup ("<can't stat file>");
616 }
617 if (source_filename)
618 {
619 /* Possible that this secret section has been inlined before */
621 cs->hint_inlined_from_filename = GNUNET_strdup (source_filename);
622 cs->hint_inlined_from_line = source_lineno;
623 }
624 }
625
626 /* Put file in the load list for diagnostics, even if we can't access it. */
627 {
629 cf->source_filename = GNUNET_strdup (inline_path);
630 cf->hint_restrict_section = GNUNET_strdup (restrict_section);
633 cf);
634 }
635
636 if (GNUNET_OK != inner_ret)
637 {
638 cs->inaccessible = true;
639 cf->hint_inaccessible = true;
640 /* File can't be accessed, but that's okay. */
641 fun_ret = GNUNET_OK;
642 goto cleanup;
643 }
644
645 other_cfg = GNUNET_CONFIGURATION_create (cfg->pd);
646 if (cfg->diagnostics)
648 other_cfg->restrict_section = restrict_section;
649 inner_ret = GNUNET_CONFIGURATION_parse (other_cfg,
650 inline_path);
651 if (GNUNET_OK != inner_ret)
652 {
653 cf->hint_inaccessible = true;
654 fun_ret = inner_ret;
655 goto cleanup;
656 }
657
658 cs = find_section (other_cfg,
659 restrict_section);
660 if (NULL == cs)
661 {
663 "Configuration file '%s' loaded with @inline-secret@ "
664 "does not contain section '%s'.\n",
665 inline_path,
666 restrict_section);
667 /* Inlined configuration is accessible but doesn't contain any values.
668 We treat this as if the inlined section was empty, and do not
669 consider it an error. */
670 fun_ret = GNUNET_OK;
671 goto cleanup;
672 }
673 for (struct ConfigEntry *ce = cs->entries;
674 NULL != ce;
675 ce = ce->next)
677 restrict_section,
678 ce);
679 fun_ret = GNUNET_OK;
680 }
681 else if (GNUNET_OK !=
683 inline_path))
684 {
685 fun_ret = GNUNET_SYSERR;
686 goto cleanup;
687 }
688 else
689 {
690 fun_ret = GNUNET_OK;
691 }
692cleanup:
693 cfg->current_nest_level = old_nest_level;
694 if (NULL != other_cfg)
696 GNUNET_free (inline_path);
697 if (igc.files_length > 0)
698 {
699 for (size_t i = 0; i < igc.files_length; i++)
700 GNUNET_free (igc.files[i]);
702 }
703 return fun_ret;
704}

References cfg, cleanup(), collect_files_cb(), copy_entry_with_sources(), GNUNET_CONFIGURATION_Handle::current_nest_level, GNUNET_CONFIGURATION_Handle::diagnostics, ConfigSection::entries, CollectFilesContext::files, CollectFilesContext::files_length, find_section(), GNUNET_array_grow, GNUNET_asprintf(), GNUNET_assert, GNUNET_break, GNUNET_CONFIGURATION_create(), GNUNET_CONFIGURATION_destroy(), GNUNET_CONFIGURATION_enable_diagnostics(), GNUNET_CONFIGURATION_parse(), GNUNET_CONTAINER_DLL_insert_tail, GNUNET_DISK_file_test_read(), GNUNET_DISK_glob(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_INFO, GNUNET_free, GNUNET_new, GNUNET_OK, GNUNET_strdup, GNUNET_STRINGS_filename_expand(), GNUNET_SYSERR, ConfigFile::hint_inaccessible, ConfigSection::hint_inlined_from_filename, ConfigSection::hint_inlined_from_line, ConfigFile::hint_restrict_section, ConfigSection::hint_secret_filename, ConfigSection::hint_secret_stat, ConfigSection::inaccessible, ConfigFile::level, GNUNET_CONFIGURATION_Handle::loaded_files_head, GNUNET_CONFIGURATION_Handle::loaded_files_tail, LOG, ConfigSection::name, ConfigSection::next, GNUNET_CONFIGURATION_Handle::pd, pstrcmp(), GNUNET_CONFIGURATION_Handle::restrict_section, GNUNET_CONFIGURATION_Handle::sections, and ConfigFile::source_filename.

Referenced by GNUNET_CONFIGURATION_deserialize().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ find_entry()

static struct ConfigEntry * find_entry ( const struct GNUNET_CONFIGURATION_Handle cfg,
const char *  section,
const char *  key 
)
static

Find an entry from a configuration.

Parameters
cfghandle to the configuration
sectionsection the option is in
keythe option
Returns
matching entry, NULL if not found

Definition at line 716 of file configuration.c.

719{
720 struct ConfigSection *sec;
721
722 if (NULL == (sec = find_section (cfg,
723 section)))
724 return NULL;
725 for (struct ConfigEntry *pos = sec->entries;
726 pos != NULL;
727 pos = pos->next)
728 if (0 == strcasecmp (key,
729 pos->key))
730 return pos;
731 if (sec->inaccessible)
732 {
734 "Section '%s' is marked as inaccessible, because the configuration "
735 "file that contains the section can't be read. Attempts to use "
736 "option '%s' will fail.\n",
737 section,
738 key);
739 return NULL;
740 }
741 return NULL;
742}

References cfg, ConfigSection::entries, find_section(), GNUNET_ERROR_TYPE_WARNING, ConfigSection::inaccessible, key, and LOG.

Referenced by add_entry_source(), compare_entries(), copy_entry_with_sources(), GNUNET_CONFIGURATION_get_value_choice(), GNUNET_CONFIGURATION_get_value_float(), GNUNET_CONFIGURATION_get_value_number(), GNUNET_CONFIGURATION_get_value_size(), GNUNET_CONFIGURATION_get_value_string(), GNUNET_CONFIGURATION_get_value_time(), GNUNET_CONFIGURATION_have_value(), and GNUNET_CONFIGURATION_set_value_string().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ add_entry_source()

static void add_entry_source ( struct GNUNET_CONFIGURATION_Handle cfg,
const char *  section,
const char *  option,
const char *  value,
const char *  filename,
unsigned int  line 
)
static

Record the source of a configuration value.

Parameters
cfgconfiguration handle
sectionsection
optionconfig option
valueparsed value
filenamesource filename
linesource line

Definition at line 756 of file configuration.c.

762{
763 struct ConfigEntry *e;
764 struct ConfigSource *source;
765
766 if (! cfg->diagnostics)
767 return;
768 e = find_entry (cfg,
769 section,
770 option);
771 if (NULL == e)
772 return;
773 source = GNUNET_new (struct ConfigSource);
774 source->value = GNUNET_strdup (value);
775 source->filename = GNUNET_strdup (filename);
776 source->lineno = line;
777 source->next = e->sources;
778 e->sources = source;
779}

References cfg, GNUNET_CONFIGURATION_Handle::diagnostics, filename, find_entry(), GNUNET_new, GNUNET_strdup, line, source, ConfigEntry::sources, and value.

Referenced by GNUNET_CONFIGURATION_deserialize().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ do_skip()

static bool do_skip ( const char *  sec,
const char *  key 
)
static

Should we skip this configuration entry when serializing?

Parameters
secsection name
keykey
Returns
true if we should skip it

Definition at line 1249 of file configuration.c.

1251{
1252 if (0 != strcasecmp ("PATHS",
1253 sec))
1254 return false;
1255 return ( (0 == strcasecmp ("DATADIR",
1256 key)) ||
1257 (0 == strcasecmp ("LIBDIR",
1258 key)) ||
1259 (0 == strcasecmp ("BINDIR",
1260 key)) ||
1261 (0 == strcasecmp ("PREFIX",
1262 key)) ||
1263 (0 == strcasecmp ("LOCALEDIR",
1264 key)) ||
1265 (0 == strcasecmp ("ICONDIR",
1266 key)) ||
1267 (0 == strcasecmp ("DOCDIR",
1268 key)) ||
1269 (0 == strcasecmp ("DEFAULTCONFIG",
1270 key)) ||
1271 (0 == strcasecmp ("LIBEXECDIR",
1272 key)) );
1273}

References key.

Referenced by GNUNET_CONFIGURATION_serialize(), and serialize_diagnostics().

Here is the caller graph for this function:

◆ dump_os_ipk()

static void dump_os_ipk ( const struct GNUNET_CONFIGURATION_Handle cfg,
struct GNUNET_Buffer buf,
enum GNUNET_OS_InstallationPathKind  ipk 
)
static

Dump an os installation path to a buffer.

Parameters
cfgconfiguration
bufbuffer to write to
ipkwhich path to print

Definition at line 1383 of file configuration.c.

1387{
1389 ipk);
1390 const char *ipkname;
1391 switch (ipk)
1392 {
1394 ipkname = "IPK_DATADIR";
1395 break;
1397 ipkname = "IPK_BINDIR";
1398 break;
1400 ipkname = "IPK_LIBDIR";
1401 break;
1403 ipkname = "IPK_PREFIX";
1405 ipkname = "IPK_LOCALEDIR";
1406 break;
1408 ipkname = "IPK_ICONDIR";
1410 ipkname = "IPK_DOCDIR";
1411 break;
1413 ipkname = "IPK_LIBEXECDIR";
1414 break;
1416 ipkname = "IPK_SELF_PREFIX";
1417 break;
1418 default:
1419 ipkname = "??";
1420 break;
1421 }
1423 "# %s = %s\n",
1424 ipkname,
1425 v);
1426 GNUNET_free (v);
1427}

References cfg, GNUNET_buffer_write_fstr(), GNUNET_free, GNUNET_OS_installation_get_path(), GNUNET_OS_IPK_BINDIR, GNUNET_OS_IPK_DATADIR, GNUNET_OS_IPK_DOCDIR, GNUNET_OS_IPK_ICONDIR, GNUNET_OS_IPK_LIBDIR, GNUNET_OS_IPK_LIBEXECDIR, GNUNET_OS_IPK_LOCALEDIR, GNUNET_OS_IPK_PREFIX, GNUNET_OS_IPK_SELF_PREFIX, and GNUNET_CONFIGURATION_Handle::pd.

Referenced by serialize_diagnostics().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ serialize_diagnostics()

static char * serialize_diagnostics ( const struct GNUNET_CONFIGURATION_Handle cfg,
bool  verbose 
)
static

Serialize configuration diagnostics.

Parameters
cfgconfiguration to serialize
verboseinclude every definition of each value
Returns
allocated diagnostic configuration

Definition at line 1438 of file configuration.c.

1440{
1441 struct GNUNET_Buffer buf = { 0 };
1442
1444 "#\n# Configuration file diagnostics\n#\n");
1446 "# Entry point: %s\n",
1448 "<none>");
1450 "#\n# Files Loaded:\n");
1451
1452 for (struct ConfigFile *cfil = cfg->loaded_files_head;
1453 NULL != cfil;
1454 cfil = cfil->next)
1455 {
1457 "# ");
1458 for (unsigned int i = 0; i < cfil->level; i++)
1460 "+");
1461 if (0 != cfil->level)
1463 " ");
1464
1466 "%s",
1467 cfil->source_filename);
1468
1469 if (NULL != cfil->hint_restrict_section)
1471 " (%s secret section %s)",
1472 cfil->hint_inaccessible
1473 ? "inaccessible"
1474 : "loaded",
1475 cfil->hint_restrict_section);
1476
1478 "\n");
1479 }
1480
1482 "#\n# Installation paths:\n");
1483
1493
1494
1496 "#\n\n");
1497
1498 for (struct ConfigSection *sec = cfg->sections;
1499 NULL != sec;
1500 sec = sec->next)
1501 {
1502 if (sec->hint_secret_filename)
1504 "# secret section from %s\n# secret file stat %s\n",
1505 sec->hint_secret_filename,
1506 sec->hint_secret_stat);
1507 if (sec->hint_inlined_from_filename)
1508 {
1510 "# inlined from %s:%u\n",
1511 sec->hint_inlined_from_filename,
1512 sec->hint_inlined_from_line);
1513 }
1515 "[%s]\n\n",
1516 sec->name);
1517 if (sec->inaccessible && (NULL == sec->entries))
1518 {
1520 "# <section contents inaccessible>\n\n\n");
1521 continue;
1522 }
1523 for (struct ConfigEntry *ent = sec->entries;
1524 NULL != ent;
1525 ent = ent->next)
1526 {
1527 if (do_skip (sec->name,
1528 ent->key))
1529 continue;
1530 if (NULL != ent->val)
1531 {
1532 char *pos;
1533 char *val = GNUNET_malloc (strlen (ent->val) * 2 + 1);
1534 strcpy (val, ent->val);
1535 while (NULL != (pos = strstr (val, "\n")))
1536 {
1537 memmove (&pos[2], &pos[1], strlen (&pos[1]));
1538 pos[0] = '\\';
1539 pos[1] = 'n';
1540 }
1541 if (NULL != ent->sources)
1542 {
1543 if (verbose &&
1544 (NULL != ent->sources->next))
1545 {
1547 &buf,
1548 "# duplicate definitions (highest precedence first):\n");
1549 for (const struct ConfigSource *source = ent->sources;
1550 NULL != source;
1551 source = source->next)
1552 {
1553 const char *status;
1554
1555 if (source == ent->sources)
1556 status = "effective";
1557 else if (0 == strcmp (source->value,
1558 ent->val))
1559 status = "same value";
1560 else
1561 status = "different value";
1563 &buf,
1564 "# %s:%u (%s)\n",
1565 source->filename,
1566 source->lineno,
1567 status);
1568 }
1569 }
1570 else
1571 {
1573 "# %s:%u\n",
1574 ent->sources->filename,
1575 ent->sources->lineno);
1576 }
1577 }
1579 "%s = %s\n",
1580 ent->key,
1581 val);
1582 GNUNET_free (val);
1583 }
1584 GNUNET_buffer_write_str (&buf, "\n");
1585 }
1586 if (sec->inaccessible)
1587 {
1589 "# <additional section contents inaccessible>\n\n\n");
1590 continue;
1591 }
1592
1593 GNUNET_buffer_write_str (&buf, "\n");
1594 }
1595 return GNUNET_buffer_reap_str (&buf);
1596}

References cfg, do_skip(), dump_os_ipk(), GNUNET_buffer_reap_str(), GNUNET_buffer_write_fstr(), GNUNET_buffer_write_str(), GNUNET_free, GNUNET_malloc, GNUNET_OS_IPK_BINDIR, GNUNET_OS_IPK_DATADIR, GNUNET_OS_IPK_DOCDIR, GNUNET_OS_IPK_ICONDIR, GNUNET_OS_IPK_LIBDIR, GNUNET_OS_IPK_LIBEXECDIR, GNUNET_OS_IPK_LOCALEDIR, GNUNET_OS_IPK_PREFIX, GNUNET_OS_IPK_SELF_PREFIX, GNUNET_CONFIGURATION_Handle::loaded_files_head, GNUNET_CONFIGURATION_Handle::main_filename, GNUNET_CONFIGURATION_Handle::sections, source, status, and verbose.

Referenced by GNUNET_CONFIGURATION_serialize_diagnostics(), and GNUNET_CONFIGURATION_serialize_diagnostics_verbose().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ read_file()

static enum GNUNET_GenericReturnValue read_file ( const char *  filename,
char **  contents,
size_t *  size 
)
static

Definition at line 1618 of file configuration.c.

1621{
1622 uint64_t fs64;
1623 ssize_t ret;
1624
1625 if ( (GNUNET_SYSERR ==
1627 &fs64,
1628 GNUNET_NO,
1629 GNUNET_YES)) ||
1630 (fs64 > SIZE_MAX) )
1631 return GNUNET_SYSERR;
1632 *size = (size_t) fs64;
1633 *contents = GNUNET_malloc (*size);
1635 *contents,
1636 *size);
1637 if ( (ret < 0) || ((size_t) ret != *size) )
1638 {
1639 GNUNET_free (*contents);
1640 *contents = NULL;
1641 return GNUNET_SYSERR;
1642 }
1643 return GNUNET_OK;
1644}

References filename, GNUNET_DISK_file_size(), GNUNET_DISK_fn_read(), GNUNET_free, GNUNET_malloc, GNUNET_NO, GNUNET_OK, GNUNET_SYSERR, GNUNET_YES, ret, size, and SIZE_MAX.

Referenced by file_hash_matches(), GNUNET_CONFIGURATION_clean_file(), libgnunet_test_transport_plugin_cmd_udp_backchannel_init(), start_testcase(), start_testcase(), start_testcase(), start_testcase(), start_testcase(), start_testcase(), and start_testcase().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ file_hash_matches()

static bool file_hash_matches ( const char *  filename,
const struct GNUNET_HashCode expected 
)
static

Check that a file still has the expected contents.

Parameters
filenamefile to check
expectedexpected hash
Returns
true on match

Definition at line 1655 of file configuration.c.

1657{
1658 struct GNUNET_HashCode actual;
1659 char *contents;
1660 size_t size;
1661
1663 &contents,
1664 &size))
1665 return false;
1666 GNUNET_CRYPTO_hash (contents,
1667 size,
1668 &actual);
1669 GNUNET_free (contents);
1670 return 0 == GNUNET_memcmp (&actual,
1671 expected);
1672}

References filename, GNUNET_CRYPTO_hash(), GNUNET_free, GNUNET_memcmp, GNUNET_OK, read_file(), and size.

Referenced by write_buffer_atomic().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ write_buffer_atomic()

static enum GNUNET_GenericReturnValue write_buffer_atomic ( const char *  filename,
const char *  contents,
size_t  size,
const struct GNUNET_HashCode expected_hash 
)
static

Atomically replace a file with the given bytes.

Parameters
filenametarget file
contentsnew contents
sizenumber of bytes in contents
expected_hashif non-NULL, require the target to still have this hash
Returns
GNUNET_OK on success

Definition at line 1685 of file configuration.c.

1689{
1690 char *fn;
1691 char *tfn;
1692
1694 if (fn == NULL)
1695 return GNUNET_SYSERR;
1697 {
1698 GNUNET_free (fn);
1699 return GNUNET_SYSERR;
1700 }
1701 {
1702 /* If @a filename is a symlink, replace what it points at, the way
1703 truncating it in place used to. */
1704 char *rfn = realpath (fn,
1705 NULL);
1706
1707 if (NULL != rfn)
1708 {
1709 GNUNET_free (fn);
1710 fn = GNUNET_strdup (rfn);
1711 free (rfn);
1712 }
1713 }
1714 /* Never rewrite the configuration in place: opening it with O_TRUNC leaves
1715 it observably empty until we have written the new contents, and anyone
1716 parsing the file in that instant -- say a daemon that was just started
1717 with this very configuration -- reads a truncated file and fails. So
1718 write a sibling file and rename(2) it over the target; readers then
1719 always see either the complete old or the complete new configuration. */
1720 GNUNET_asprintf (&tfn,
1721 "%s.%u.tmp",
1722 fn,
1723 (unsigned int) getpid ());
1724 {
1725 struct GNUNET_DISK_FileHandle *h;
1726
1727 h = GNUNET_DISK_file_open (tfn,
1735 if (NULL == h)
1736 {
1737 GNUNET_free (tfn);
1738 GNUNET_free (fn);
1739 return GNUNET_SYSERR;
1740 }
1741 if (((ssize_t) size) !=
1743 contents,
1744 size))
1745 {
1747 "write",
1748 tfn);
1750 (void) unlink (tfn);
1751 GNUNET_free (tfn);
1752 GNUNET_free (fn);
1753 return GNUNET_SYSERR;
1754 }
1755 /* Get the contents onto the disk before the rename publishes them, so
1756 that a crash cannot leave an empty configuration behind. */
1758 {
1760 "fsync",
1761 tfn);
1762 (void) GNUNET_DISK_file_close (h);
1763 (void) unlink (tfn);
1764 GNUNET_free (tfn);
1765 GNUNET_free (fn);
1766 return GNUNET_SYSERR;
1767 }
1769 {
1771 "close",
1772 tfn);
1773 (void) unlink (tfn);
1774 GNUNET_free (tfn);
1775 GNUNET_free (fn);
1776 return GNUNET_SYSERR;
1777 }
1778 }
1779 {
1780 struct stat sbuf;
1781
1782 /* rename(2) replaces the inode, so carry over the permissions of the
1783 configuration we are about to replace (we just created @a tfn). */
1784 if ( (0 == stat (fn,
1785 &sbuf)) &&
1786 (0 != chmod (tfn,
1787 sbuf.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO))) )
1789 "chmod",
1790 tfn);
1791 }
1792 if ( (NULL != expected_hash) &&
1793 (! file_hash_matches (fn,
1794 expected_hash)) )
1795 {
1797 "Configuration file `%s' changed while it was being cleaned\n",
1798 fn);
1799 (void) unlink (tfn);
1800 GNUNET_free (tfn);
1801 GNUNET_free (fn);
1802 return GNUNET_SYSERR;
1803 }
1804 if (0 != rename (tfn,
1805 fn))
1806 {
1808 "rename",
1809 fn);
1810 (void) unlink (tfn);
1811 GNUNET_free (tfn);
1812 GNUNET_free (fn);
1813 return GNUNET_SYSERR;
1814 }
1815 GNUNET_free (tfn);
1816 GNUNET_free (fn);
1817 return GNUNET_OK;
1818}

References file_hash_matches(), filename, GNUNET_asprintf(), GNUNET_DISK_directory_create_for_file(), GNUNET_DISK_file_close(), GNUNET_DISK_file_open(), GNUNET_DISK_file_sync(), GNUNET_DISK_file_write(), GNUNET_DISK_OPEN_CREATE, GNUNET_DISK_OPEN_TRUNCATE, GNUNET_DISK_OPEN_WRITE, GNUNET_DISK_PERM_GROUP_READ, GNUNET_DISK_PERM_GROUP_WRITE, GNUNET_DISK_PERM_USER_READ, GNUNET_DISK_PERM_USER_WRITE, GNUNET_ERROR_TYPE_ERROR, GNUNET_ERROR_TYPE_WARNING, GNUNET_free, GNUNET_log_strerror_file, GNUNET_OK, GNUNET_strdup, GNUNET_STRINGS_filename_expand(), GNUNET_SYSERR, h, LOG, and size.

Referenced by GNUNET_CONFIGURATION_clean_file(), and GNUNET_CONFIGURATION_write().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ find_clean_line()

static struct CleanLine * find_clean_line ( struct CleanLine lines,
unsigned int  lines_length,
unsigned int  line 
)
static

Find a cleanup record for a physical line.

Definition at line 1858 of file configuration.c.

1861{
1862 for (unsigned int i = 0; i < lines_length; i++)
1863 if (lines[i].line == line)
1864 return &lines[i];
1865 return NULL;
1866}

References line.

Referenced by GNUNET_CONFIGURATION_clean_file(), and source_is_removed().

Here is the caller graph for this function:

◆ source_is_removed()

static bool source_is_removed ( const struct ConfigSource source,
const char *  target,
struct CleanLine lines,
unsigned int  lines_length 
)
static

Return whether a source is a target line currently marked for removal.

Definition at line 1873 of file configuration.c.

1877{
1878 struct CleanLine *line;
1879
1880 if (0 != strcmp (source->filename,
1881 target))
1882 return false;
1883 line = find_clean_line (lines,
1884 lines_length,
1885 source->lineno);
1886 return (NULL != line) && line->remove;
1887}

References find_clean_line(), line, and source.

Referenced by GNUNET_CONFIGURATION_clean_file().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ clean_line_cmp()

static int clean_line_cmp ( const void *  a,
const void *  b 
)
static

Sort cleanup records by source line.

Definition at line 1894 of file configuration.c.

1896{
1897 const struct CleanLine *la = a;
1898 const struct CleanLine *lb = b;
1899
1900 if (la->line < lb->line)
1901 return -1;
1902 if (la->line > lb->line)
1903 return 1;
1904 return 0;
1905}

References CleanLine::line.

Referenced by GNUNET_CONFIGURATION_clean_file().

Here is the caller graph for this function:

◆ copy_entry()

static void copy_entry ( void *  cls,
const char *  section,
const char *  option,
const char *  value 
)
static

Copy a configuration value to the given target configuration.

Overwrites existing entries.

Parameters
clsthe destination configuration (struct GNUNET_CONFIGURATION_Handle *)
sectionsection for the value
optionoption name of the value
valuevalue to copy

Definition at line 2280 of file configuration.c.

2284{
2285 struct GNUNET_CONFIGURATION_Handle *dst = cls;
2286
2288 section,
2289 option,
2290 value);
2291}

References GNUNET_CONFIGURATION_set_value_string(), and value.

Referenced by GNUNET_CONFIGURATION_dup().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ compare_entries()

static void compare_entries ( void *  cls,
const char *  section,
const char *  option,
const char *  value 
)
static

A callback function, compares entries from two configurations (default against a new configuration) and write the diffs in a diff-configuration object (the callback object).

Parameters
clsthe diff configuration (struct DiffHandle *)
sectionsection for the value (of the default conf.)
optionoption name of the value (of the default conf.)
valuevalue to copy (of the default conf.)

Definition at line 2319 of file configuration.c.

2323{
2324 struct DiffHandle *dh = cls;
2325 struct ConfigEntry *entNew;
2326
2327 entNew = find_entry (dh->cfg_default, section, option);
2328 if ((NULL != entNew) && (NULL != entNew->val) &&
2329 (0 == strcmp (entNew->val, value)))
2330 return;
2332 section,
2333 option,
2334 value);
2335}

References DiffHandle::cfg_default, DiffHandle::cfgDiff, find_entry(), GNUNET_CONFIGURATION_set_value_string(), ConfigEntry::val, and value.

Referenced by GNUNET_CONFIGURATION_get_diff().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ expand_dollar()

static char * expand_dollar ( const struct GNUNET_CONFIGURATION_Handle cfg,
char *  orig,
unsigned int  depth 
)
static

Expand an expression of the form "$FOO/BAR" to "DIRECTORY/BAR" where either in the "PATHS" section or the environment "FOO" is set to "DIRECTORY".

We also support default expansion, i.e. ${VARIABLE:-default} will expand to $VARIABLE if VARIABLE is set in PATHS or the environment, and otherwise to "default". Note that "default" itself can also be a $-expression, thus "${VAR1:-{$VAR2}}" will expand to VAR1 and if that is not defined to VAR2.

Parameters
cfgconfiguration to use for path expansion
origstring to $-expand (will be freed!)
depthrecursion depth, used to detect recursive expansions
Returns
$-expanded string, never NULL unless orig was NULL

Definition at line 2699 of file configuration.c.

2702{
2703 char *prefix;
2704 char *result;
2705 char *start;
2706 const char *post;
2707 const char *env;
2708 char *def;
2709 char *end;
2710 unsigned int lopen;
2711 char erased_char;
2712 char *erased_pos;
2713 size_t len;
2714
2715 if (NULL == orig)
2716 return NULL;
2717 if (depth > 128)
2718 {
2720 "Recursive expansion suspected, aborting $-expansion for term `%s'\n",
2721 orig);
2722 return orig;
2723 }
2725 "Asked to $-expand %s\n",
2726 orig);
2727 if ('$' != orig[0])
2728 {
2730 "Doesn't start with $ - not expanding\n");
2731 return orig;
2732 }
2733 erased_char = 0;
2734 erased_pos = NULL;
2735 if ('{' == orig[1])
2736 {
2737 start = &orig[2];
2738 lopen = 1;
2739 end = &orig[1];
2740 while (lopen > 0)
2741 {
2742 end++;
2743 switch (*end)
2744 {
2745 case '}':
2746 lopen--;
2747 break;
2748
2749 case '{':
2750 lopen++;
2751 break;
2752
2753 case '\0':
2755 "Missing closing `}' in option `%s'\n",
2756 orig);
2757 return orig;
2758
2759 default:
2760 break;
2761 }
2762 }
2763 erased_char = *end;
2764 erased_pos = end;
2765 *end = '\0';
2766 post = end + 1;
2767 def = strchr (orig, ':');
2768 if (NULL != def)
2769 {
2770 *def = '\0';
2771 def++;
2772 if (('-' == *def) || ('=' == *def))
2773 def++;
2774 def = GNUNET_strdup (def);
2775 }
2776 }
2777 else
2778 {
2779 int i;
2780
2781 start = &orig[1];
2782 def = NULL;
2783 i = 0;
2784 while ( (orig[i] != '/') &&
2785 (orig[i] != '\\') &&
2786 (orig[i] != '\0') &&
2787 (orig[i] != ' ') )
2788 i++;
2789 if (orig[i] == '\0')
2790 {
2791 post = "";
2792 }
2793 else
2794 {
2795 erased_char = orig[i];
2796 erased_pos = &orig[i];
2797 orig[i] = '\0';
2798 post = &orig[i + 1];
2799 }
2800 }
2802 "Split into `%s' and `%s' with default %s\n",
2803 start,
2804 post,
2805 def);
2806 if (GNUNET_OK !=
2808 "PATHS",
2809 start,
2810 &prefix))
2811 {
2812 if (NULL == (env = getenv (start)))
2813 {
2814 /* try default */
2815 def = expand_dollar (cfg,
2816 def,
2817 depth + 1);
2818 env = def;
2819 }
2820 if (NULL == env)
2821 {
2823 if (erased_pos)
2824 *erased_pos = erased_char;
2826 "Failed to expand `%s' in `%s' as it is neither found in [PATHS] nor defined as an environmental variable\n",
2827 start,
2828 orig);
2830 return orig;
2831 }
2833 }
2835 prefix);
2836 if ((erased_pos) && ('}' != erased_char))
2837 {
2838 len = strlen (prefix) + 1;
2839 prefix = GNUNET_realloc (prefix, len + 1);
2840 prefix[len - 1] = erased_char;
2841 prefix[len] = '\0';
2842 }
2843 result = GNUNET_malloc (strlen (prefix) + strlen (post) + 1);
2844 strcpy (result, prefix);
2845 strcat (result, post);
2846 GNUNET_free (def);
2848 GNUNET_free (orig);
2849 return result;
2850}

References cfg, end, env, expand_dollar(), getenv(), GNUNET_CONFIGURATION_expand_dollar(), GNUNET_CONFIGURATION_get_value_string(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_WARNING, GNUNET_free, GNUNET_malloc, GNUNET_OK, GNUNET_realloc, GNUNET_strdup, LOG, prefix, result, and start.

Referenced by expand_dollar(), and GNUNET_CONFIGURATION_expand_dollar().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ escape_name()

static char * escape_name ( const char *  value)
static

FIXME.

Parameters
valueFIXME
Returns
FIXME

Definition at line 3017 of file configuration.c.

3018{
3019 char *escaped;
3020 const char *rpos;
3021 char *wpos;
3022
3023 escaped = GNUNET_malloc (strlen (value) * 2 + 1);
3024 memset (escaped, 0, strlen (value) * 2 + 1);
3025 rpos = value;
3026 wpos = escaped;
3027 while (rpos[0] != '\0')
3028 {
3029 switch (rpos[0])
3030 {
3031 case '\\':
3032 case ' ':
3033 wpos[0] = '\\';
3034 wpos[1] = rpos[0];
3035 wpos += 2;
3036 break;
3037
3038 default:
3039 wpos[0] = rpos[0];
3040 wpos++;
3041 }
3042 rpos++;
3043 }
3044 return escaped;
3045}

References GNUNET_malloc, and value.

Referenced by GNUNET_CONFIGURATION_append_value_filename(), and GNUNET_CONFIGURATION_remove_value_filename().

Here is the caller graph for this function:

◆ test_match()

static enum GNUNET_GenericReturnValue test_match ( void *  cls,
const char *  fn 
)
static

FIXME.

Parameters
clsstring we compare with (const char*)
fnfilename we are currently looking at
Returns
GNUNET_OK if the names do not match, GNUNET_SYSERR if they do

Definition at line 3056 of file configuration.c.

3058{
3059 const char *of = cls;
3060
3061 return (0 == strcmp (of, fn))
3063 : GNUNET_OK;
3064}

References GNUNET_OK, and GNUNET_SYSERR.

Referenced by GNUNET_CONFIGURATION_append_value_filename().

Here is the caller graph for this function:

◆ print_filename_option()

static void print_filename_option ( void *  cls,
const char *  section,
const char *  option,
const char *  value 
)
static

Print each option in a given section as a filename.

Parameters
clsclosure
sectionname of the section
optionname of the option
valuevalue of the option

Definition at line 3386 of file configuration.c.

3390{
3391 const struct GNUNET_CONFIGURATION_Handle *cfg = cls;
3392
3393 char *value_fn;
3394 char *fn;
3395
3398 section,
3399 option,
3400 &value_fn));
3401 fn = GNUNET_STRINGS_filename_expand (value_fn);
3402 if (NULL == fn)
3403 fn = value_fn;
3404 else
3405 GNUNET_free (value_fn);
3406 fprintf (stdout,
3407 "%s = %s\n",
3408 option,
3409 fn);
3410 GNUNET_free (fn);
3411}

References cfg, GNUNET_assert, GNUNET_CONFIGURATION_get_value_filename(), GNUNET_free, GNUNET_OK, and GNUNET_STRINGS_filename_expand().

Referenced by GNUNET_CONFIGURATION_config_tool_run().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ print_option()

static void print_option ( void *  cls,
const char *  section,
const char *  option,
const char *  value 
)
static

Print each option in a given section.

Parameters
clsclosure
sectionname of the section
optionname of the option
valuevalue of the option

Definition at line 3423 of file configuration.c.

3427{
3428 (void) cls;
3429 (void) section;
3430
3431 fprintf (stdout,
3432 "%s = %s\n",
3433 option,
3434 value);
3435}

References value.

Referenced by GNUNET_CONFIGURATION_config_tool_run().

Here is the caller graph for this function:

◆ print_section_name()

static void print_section_name ( void *  cls,
const char *  section 
)
static

Print out given section name.

Parameters
clsunused
sectiona section in the configuration file

Definition at line 3445 of file configuration.c.

3447{
3448 (void) cls;
3449 fprintf (stdout,
3450 "%s\n",
3451 section);
3452}

Referenced by GNUNET_CONFIGURATION_config_tool_run().

Here is the caller graph for this function: