X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=src%2Futil%2Fconfiguration.c;h=85c17cb7d2d1f407d6eb119b3bebf99a4531c530;hb=0ea8e006d5f5ef84e31e000607bd24a23f8fc1ed;hp=569c4adcf9c6964973b2ba74e93c25c596c10d6d;hpb=60c2c502f0a4581a6f25386a8d54adb9cc8b6003;p=oweals%2Fgnunet.git diff --git a/src/util/configuration.c b/src/util/configuration.c index 569c4adcf..85c17cb7d 100644 --- a/src/util/configuration.c +++ b/src/util/configuration.c @@ -99,6 +99,18 @@ struct GNUNET_CONFIGURATION_Handle }; +/** + * Used for diffing a configuration object against + * the default one + */ +struct DiffHandle +{ + const struct GNUNET_CONFIGURATION_Handle *cfgDefault; + struct GNUNET_CONFIGURATION_Handle *cfgDiff; +}; + + + /** * Create a GNUNET_CONFIGURATION_Handle. * @@ -164,6 +176,8 @@ GNUNET_CONFIGURATION_parse (struct GNUNET_CONFIGURATION_Handle *cfg, char *fn; fn = GNUNET_STRINGS_filename_expand (filename); + if (fn == NULL) + return GNUNET_SYSERR; dirty = cfg->dirty; /* back up value! */ if (NULL == (fp = FOPEN (fn, "r"))) { @@ -192,12 +206,12 @@ GNUNET_CONFIGURATION_parse (struct GNUNET_CONFIGURATION_Handle *cfg, if (emptyline == 1) continue; /* remove tailing whitespace */ - for (i = strlen (line) - 1; (i >= 0) && (isspace (line[i])); i--) + for (i = strlen (line) - 1; (i >= 0) && (isspace ( (unsigned char) line[i])); i--) line[i] = '\0'; if (1 == sscanf (line, "@INLINE@ %191[^\n]", value)) { /* @INLINE@ value */ - if (0 != GNUNET_CONFIGURATION_parse (cfg, value)) + if (GNUNET_OK != GNUNET_CONFIGURATION_parse (cfg, value)) ret = GNUNET_SYSERR; /* failed to parse included config */ } else if (1 == sscanf (line, "[%99[^]]]", value)) @@ -211,7 +225,7 @@ GNUNET_CONFIGURATION_parse (struct GNUNET_CONFIGURATION_Handle *cfg, /* tag = value */ /* Strip LF */ i = strlen (value) - 1; - while ((i >= 0) && (isspace (value[i]))) + while ((i >= 0) && (isspace ( (unsigned char) value[i]))) value[i--] = '\0'; /* remove quotes */ i = 0; @@ -278,7 +292,7 @@ GNUNET_CONFIGURATION_is_dirty (const struct GNUNET_CONFIGURATION_Handle *cfg) * @return GNUNET_OK on success, GNUNET_SYSERR on error */ int -GNUNET_CONFIGURATION_write (struct GNUNET_CONFIGURATION_Handle *data, +GNUNET_CONFIGURATION_write (struct GNUNET_CONFIGURATION_Handle *cfg, const char *filename) { struct ConfigSection *sec; @@ -290,6 +304,8 @@ GNUNET_CONFIGURATION_write (struct GNUNET_CONFIGURATION_Handle *data, char *pos; fn = GNUNET_STRINGS_filename_expand (filename); + if (fn == NULL) + return GNUNET_SYSERR; GNUNET_DISK_directory_create_for_file (fn); if (NULL == (fp = FOPEN (fn, "w"))) { @@ -299,7 +315,7 @@ GNUNET_CONFIGURATION_write (struct GNUNET_CONFIGURATION_Handle *data, } GNUNET_free (fn); error = 0; - sec = data->sections; + sec = cfg->sections; while (sec != NULL) { if (0 > fprintf (fp, "[%s]\n", sec->name)) @@ -344,10 +360,10 @@ GNUNET_CONFIGURATION_write (struct GNUNET_CONFIGURATION_Handle *data, GNUNET_assert (0 == fclose (fp)); if (error != 0) { - data->dirty = GNUNET_SYSERR; /* last write failed */ + cfg->dirty = GNUNET_SYSERR; /* last write failed */ return GNUNET_SYSERR; } - data->dirty = GNUNET_NO; /* last write succeeded */ + cfg->dirty = GNUNET_NO; /* last write succeeded */ return GNUNET_OK; } @@ -359,9 +375,10 @@ GNUNET_CONFIGURATION_write (struct GNUNET_CONFIGURATION_Handle *data, * @param iter function to call on each option * @param iter_cls closure for iter */ -void GNUNET_CONFIGURATION_iterate (const struct GNUNET_CONFIGURATION_Handle *cfg, - GNUNET_CONFIGURATION_Iterator iter, - void *iter_cls) +void +GNUNET_CONFIGURATION_iterate (const struct GNUNET_CONFIGURATION_Handle *cfg, + GNUNET_CONFIGURATION_Iterator iter, + void *iter_cls) { struct ConfigSection *spos; struct ConfigEntry *epos; @@ -371,28 +388,27 @@ void GNUNET_CONFIGURATION_iterate (const struct GNUNET_CONFIGURATION_Handle *cfg { epos = spos->entries; while (epos != NULL) - { - iter (iter_cls, spos->name, epos->key, epos->val); - epos = epos->next; - } + { + iter (iter_cls, spos->name, epos->key, epos->val); + epos = epos->next; + } spos = spos->next; } } /** - * FIXME. + * Copy a configuration value to the given target configuration. + * Overwrites existing entries. * * @param cls the destination configuration (struct GNUNET_CONFIGURATION_Handle*) - * @param section FIXME - * @param option FIXME - * @param value FIXME + * @param section section for the value + * @param option option name of the value + * @param value value to copy */ static void copy_entry (void *cls, - const char *section, - const char *option, - const char *value) + const char *section, const char *option, const char *value) { struct GNUNET_CONFIGURATION_Handle *dst = cls; GNUNET_CONFIGURATION_set_value_string (dst, section, option, value); @@ -402,7 +418,7 @@ copy_entry (void *cls, /** * Duplicate an existing configuration object. * - * @param c configuration to duplicate + * @param cfg configuration to duplicate * @return duplicate configuration */ struct GNUNET_CONFIGURATION_Handle * @@ -419,16 +435,17 @@ GNUNET_CONFIGURATION_dup (const struct GNUNET_CONFIGURATION_Handle *cfg) /** * FIXME. * - * @param data FIXME + * @param cfg FIXME * @param section FIXME * @return matching entry, NULL if not found */ static struct ConfigSection * -findSection (const struct GNUNET_CONFIGURATION_Handle *data, const char *section) +findSection (const struct GNUNET_CONFIGURATION_Handle *cfg, + const char *section) { struct ConfigSection *pos; - pos = data->sections; + pos = cfg->sections; while ((pos != NULL) && (0 != strcasecmp (section, pos->name))) pos = pos->next; return pos; @@ -438,19 +455,19 @@ findSection (const struct GNUNET_CONFIGURATION_Handle *data, const char *section /** * FIXME. * - * @param data FIXME + * @param cfg FIXME * @param section FIXME * @param key FIXME * @return matching entry, NULL if not found */ static struct ConfigEntry * -findEntry (const struct GNUNET_CONFIGURATION_Handle *data, +findEntry (const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *key) { struct ConfigSection *sec; struct ConfigEntry *pos; - sec = findSection (data, section); + sec = findSection (cfg, section); if (sec == NULL) return NULL; pos = sec->entries; @@ -460,6 +477,59 @@ findEntry (const struct GNUNET_CONFIGURATION_Handle *data, } +/** + * 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). + * + * @param cls the diff configuration (struct DiffHandle*) + * @param section section for the value (of the default conf.) + * @param option option name of the value (of the default conf.) + * @param value value to copy (of the default conf.) + */ +static void +compareEntries (void *cls, + const char *section, const char *option, const char *value) +{ + struct DiffHandle *dh = cls; + struct ConfigEntry *entNew; + + entNew = findEntry (dh->cfgDefault, section, option); + if ( (entNew != NULL) && + (strcmp (entNew->val, value) == 0) ) + return; + GNUNET_CONFIGURATION_set_value_string (dh->cfgDiff, + section, + option, + value); +} + + +/** + * Write only configuration entries that have been changed to configuration file + * @param cfgDefault default configuration + * @param cfgNew new configuration + * @param filename where to write the configuration diff between default and new + * @return GNUNET_OK on success, GNUNET_SYSERR on error + */ +int +GNUNET_CONFIGURATION_write_diffs (const struct GNUNET_CONFIGURATION_Handle + *cfgDefault, + const struct GNUNET_CONFIGURATION_Handle *cfgNew, + const char *filename) +{ + int ret; + struct DiffHandle diffHandle; + + diffHandle.cfgDiff = GNUNET_CONFIGURATION_create (); + diffHandle.cfgDefault = cfgDefault; + GNUNET_CONFIGURATION_iterate (cfgNew, compareEntries, &diffHandle); + ret = GNUNET_CONFIGURATION_write (diffHandle.cfgDiff, filename); + GNUNET_CONFIGURATION_destroy (diffHandle.cfgDiff); + return ret; +} + + /** * Set a configuration value that should be a string. * @@ -470,27 +540,27 @@ findEntry (const struct GNUNET_CONFIGURATION_Handle *data, */ void GNUNET_CONFIGURATION_set_value_string (struct GNUNET_CONFIGURATION_Handle - *data, + *cfg, const char *section, const char *option, const char *value) { struct ConfigSection *sec; struct ConfigEntry *e; - e = findEntry (data, section, option); + e = findEntry (cfg, section, option); if (e != NULL) { GNUNET_free_non_null (e->val); e->val = GNUNET_strdup (value); return; } - sec = findSection (data, section); + sec = findSection (cfg, section); if (sec == NULL) { sec = GNUNET_malloc (sizeof (struct ConfigSection)); sec->name = GNUNET_strdup (section); - sec->next = data->sections; - data->sections = sec; + sec->next = cfg->sections; + cfg->sections = sec; } e = GNUNET_malloc (sizeof (struct ConfigEntry)); e->key = GNUNET_strdup (option); @@ -530,8 +600,9 @@ GNUNET_CONFIGURATION_set_value_number (struct GNUNET_CONFIGURATION_Handle * @return GNUNET_OK on success, GNUNET_SYSERR on error */ int -GNUNET_CONFIGURATION_get_value_number (const struct GNUNET_CONFIGURATION_Handle - *cfg, const char *section, +GNUNET_CONFIGURATION_get_value_number (const struct + GNUNET_CONFIGURATION_Handle *cfg, + const char *section, const char *option, unsigned long long *number) { @@ -557,17 +628,14 @@ GNUNET_CONFIGURATION_get_value_number (const struct GNUNET_CONFIGURATION_Handle */ int GNUNET_CONFIGURATION_get_value_time (const struct GNUNET_CONFIGURATION_Handle - *cfg, const char *section, - const char *option, - struct GNUNET_TIME_Relative *time) + *cfg, const char *section, + const char *option, + struct GNUNET_TIME_Relative *time) { unsigned long long num; int ret; - ret = GNUNET_CONFIGURATION_get_value_number (cfg, - section, - option, - &num); + ret = GNUNET_CONFIGURATION_get_value_number (cfg, section, option, &num); if (ret == GNUNET_OK) time->value = (uint64_t) num; return ret; @@ -585,8 +653,9 @@ GNUNET_CONFIGURATION_get_value_time (const struct GNUNET_CONFIGURATION_Handle * @return GNUNET_OK on success, GNUNET_SYSERR on error */ int -GNUNET_CONFIGURATION_get_value_string (const struct GNUNET_CONFIGURATION_Handle - *cfg, const char *section, +GNUNET_CONFIGURATION_get_value_string (const struct + GNUNET_CONFIGURATION_Handle *cfg, + const char *section, const char *option, char **value) { struct ConfigEntry *e; @@ -615,8 +684,9 @@ GNUNET_CONFIGURATION_get_value_string (const struct GNUNET_CONFIGURATION_Handle * @return GNUNET_OK on success, GNUNET_SYSERR on error */ int -GNUNET_CONFIGURATION_get_value_choice (const struct GNUNET_CONFIGURATION_Handle - *cfg, const char *section, +GNUNET_CONFIGURATION_get_value_choice (const struct + GNUNET_CONFIGURATION_Handle *cfg, + const char *section, const char *option, const char **choices, const char **value) @@ -655,8 +725,9 @@ GNUNET_CONFIGURATION_get_value_choice (const struct GNUNET_CONFIGURATION_Handle * @return GNUNET_YES if so, GNUNET_NO if not. */ int -GNUNET_CONFIGURATION_have_value (const struct GNUNET_CONFIGURATION_Handle *cfg, - const char *section, const char *option) +GNUNET_CONFIGURATION_have_value (const struct GNUNET_CONFIGURATION_Handle + *cfg, const char *section, + const char *option) { struct ConfigEntry *e; if ((NULL == (e = findEntry (cfg, section, option))) || (e->val == NULL)) @@ -671,12 +742,12 @@ GNUNET_CONFIGURATION_have_value (const struct GNUNET_CONFIGURATION_Handle *cfg, * "FOO" is set to "DIRECTORY". * * @param cfg configuration to use for path expansion - * @param old string to $-expand (will be freed!) + * @param orig string to $-expand (will be freed!) * @return $-expanded string */ char * -GNUNET_CONFIGURATION_expand_dollar (const struct GNUNET_CONFIGURATION_Handle *cfg, - char *orig) +GNUNET_CONFIGURATION_expand_dollar (const struct GNUNET_CONFIGURATION_Handle + *cfg, char *orig) { int i; char *prefix; @@ -698,9 +769,9 @@ GNUNET_CONFIGURATION_expand_dollar (const struct GNUNET_CONFIGURATION_Handle *cf orig[i] = '\0'; post = &orig[i + 1]; } - if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (cfg, - "PATHS", - &orig[1], &prefix)) + if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (cfg, + "PATHS", + &orig[1], &prefix)) { if (NULL == (env = getenv (&orig[1]))) { @@ -732,30 +803,25 @@ GNUNET_CONFIGURATION_expand_dollar (const struct GNUNET_CONFIGURATION_Handle *cf * @return GNUNET_OK on success, GNUNET_SYSERR on error */ int -GNUNET_CONFIGURATION_get_value_filename (const struct GNUNET_CONFIGURATION_Handle - *data, const char *section, +GNUNET_CONFIGURATION_get_value_filename (const struct + GNUNET_CONFIGURATION_Handle *cfg, + const char *section, const char *option, char **value) { - int ret; char *tmp; - tmp = NULL; - ret = GNUNET_CONFIGURATION_get_value_string (data, section, option, &tmp); - if (ret == GNUNET_SYSERR) - return ret; - if (tmp != NULL) - { - tmp = GNUNET_CONFIGURATION_expand_dollar (data, tmp); - *value = GNUNET_STRINGS_filename_expand (tmp); - GNUNET_free (tmp); - if (*value == NULL) - ret = GNUNET_SYSERR; - } - else + if (GNUNET_OK != + GNUNET_CONFIGURATION_get_value_string (cfg, section, option, &tmp)) { *value = NULL; + return GNUNET_SYSERR; } - return ret; + tmp = GNUNET_CONFIGURATION_expand_dollar (cfg, tmp); + *value = GNUNET_STRINGS_filename_expand (tmp); + GNUNET_free (tmp); + if (*value == NULL) + return GNUNET_SYSERR; + return GNUNET_OK; } @@ -769,8 +835,9 @@ GNUNET_CONFIGURATION_get_value_filename (const struct GNUNET_CONFIGURATION_Handl * @return GNUNET_YES, GNUNET_NO or GNUNET_SYSERR */ int -GNUNET_CONFIGURATION_get_value_yesno (const struct GNUNET_CONFIGURATION_Handle *cfg, - const char *section, const char *option) +GNUNET_CONFIGURATION_get_value_yesno (const struct GNUNET_CONFIGURATION_Handle + *cfg, const char *section, + const char *option) { static const char *yesno[] = { "YES", "NO", NULL }; const char *val; @@ -800,7 +867,7 @@ int GNUNET_CONFIGURATION_iterate_value_filenames (const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, - const char *option, + const char *option, GNUNET_FileNameCallback cb, void *cb_cls) { @@ -1054,7 +1121,7 @@ GNUNET_CONFIGURATION_remove_value_filename (struct GNUNET_CONFIGURATION_Handle */ int GNUNET_CONFIGURATION_load (struct GNUNET_CONFIGURATION_Handle *cfg, - const char *cfgfn) + const char *filename) { char *baseconfig; char *ipath; @@ -1068,13 +1135,21 @@ GNUNET_CONFIGURATION_load (struct GNUNET_CONFIGURATION_Handle *cfg, GNUNET_free (ipath); if ((GNUNET_OK != GNUNET_CONFIGURATION_parse (cfg, baseconfig)) || - (!((cfgfn == NULL) || - (GNUNET_OK == GNUNET_CONFIGURATION_parse (cfg, cfgfn))))) + (!((filename == NULL) || + (GNUNET_OK == GNUNET_CONFIGURATION_parse (cfg, filename))))) { GNUNET_free (baseconfig); return GNUNET_SYSERR; } GNUNET_free (baseconfig); + if ( ((GNUNET_YES != GNUNET_CONFIGURATION_have_value (cfg, + "PATHS", + "DEFAULTCONFIG"))) && + (filename != NULL) ) + GNUNET_CONFIGURATION_set_value_string (cfg, + "PATHS", + "DEFAULTCONFIG", + filename); if ((GNUNET_YES == GNUNET_CONFIGURATION_have_value (cfg, "TESTING", "WEAKRANDOM")) &&