X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=src%2Futil%2Fconfiguration.c;h=85c17cb7d2d1f407d6eb119b3bebf99a4531c530;hb=0ea8e006d5f5ef84e31e000607bd24a23f8fc1ed;hp=2541a79f455486d408f8324d003c550e99a64e7e;hpb=aa907f2d51d9409635e5d1438b67efa6857a4c69;p=oweals%2Fgnunet.git diff --git a/src/util/configuration.c b/src/util/configuration.c index 2541a79f4..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; @@ -290,6 +304,8 @@ GNUNET_CONFIGURATION_write (struct GNUNET_CONFIGURATION_Handle *cfg, 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"))) { @@ -344,10 +360,10 @@ GNUNET_CONFIGURATION_write (struct GNUNET_CONFIGURATION_Handle *cfg, GNUNET_assert (0 == fclose (fp)); if (error != 0) { - cfg->dirty = GNUNET_SYSERR; /* last write failed */ + cfg->dirty = GNUNET_SYSERR; /* last write failed */ return GNUNET_SYSERR; } - cfg->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 *cfg, * @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,10 +388,10 @@ 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; } } @@ -391,9 +408,7 @@ void GNUNET_CONFIGURATION_iterate (const struct GNUNET_CONFIGURATION_Handle *cfg */ 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); @@ -425,7 +440,8 @@ GNUNET_CONFIGURATION_dup (const struct GNUNET_CONFIGURATION_Handle *cfg) * @return matching entry, NULL if not found */ static struct ConfigSection * -findSection (const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section) +findSection (const struct GNUNET_CONFIGURATION_Handle *cfg, + const char *section) { struct ConfigSection *pos; @@ -461,6 +477,59 @@ findEntry (const struct GNUNET_CONFIGURATION_Handle *cfg, } +/** + * 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. * @@ -531,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) { @@ -558,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; @@ -586,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; @@ -616,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) @@ -656,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)) @@ -676,8 +746,8 @@ GNUNET_CONFIGURATION_have_value (const struct GNUNET_CONFIGURATION_Handle *cfg, * @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; @@ -699,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]))) { @@ -733,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 - *cfg, 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 (cfg, section, option, &tmp); - if (ret == GNUNET_SYSERR) - return ret; - if (tmp != NULL) - { - tmp = GNUNET_CONFIGURATION_expand_dollar (cfg, 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; } @@ -770,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; @@ -801,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) { @@ -1076,6 +1142,14 @@ GNUNET_CONFIGURATION_load (struct GNUNET_CONFIGURATION_Handle *cfg, 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")) &&