X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=src%2Futil%2Fconfiguration.c;h=978765970c80fbb69857b7da4cc21fc0849f805c;hb=46ac0cea02fe1949d76b86c7a0750f9e7854fef6;hp=250f9d3d513014dca06a4977383ed6fdddbad696;hpb=660c6da4fcbca6bd2cb15599dfe3c6d53b890c7f;p=oweals%2Fgnunet.git diff --git a/src/util/configuration.c b/src/util/configuration.c index 250f9d3d5..978765970 100644 --- a/src/util/configuration.c +++ b/src/util/configuration.c @@ -98,13 +98,14 @@ struct GNUNET_CONFIGURATION_Handle }; + /** * Used for diffing a configuration object against * the default one */ -struct GNUNNET_CONFIGURATION_Diff_Handle +struct DiffHandle { - struct GNUNET_CONFIGURATION_Handle *cfgNew; + const struct GNUNET_CONFIGURATION_Handle *cfgDefault; struct GNUNET_CONFIGURATION_Handle *cfgDiff; }; @@ -131,21 +132,9 @@ void GNUNET_CONFIGURATION_destroy (struct GNUNET_CONFIGURATION_Handle *cfg) { struct ConfigSection *sec; - struct ConfigEntry *ent; while (NULL != (sec = cfg->sections)) - { - cfg->sections = sec->next; - while (NULL != (ent = sec->entries)) - { - sec->entries = ent->next; - GNUNET_free (ent->key); - GNUNET_free_non_null (ent->val); - GNUNET_free (ent); - } - GNUNET_free (sec->name); - GNUNET_free (sec); - } + GNUNET_CONFIGURATION_remove_section (cfg, sec->name); GNUNET_free (cfg); } @@ -175,6 +164,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"))) { @@ -203,12 +194,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)) @@ -222,7 +213,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; @@ -301,7 +292,13 @@ GNUNET_CONFIGURATION_write (struct GNUNET_CONFIGURATION_Handle *cfg, char *pos; fn = GNUNET_STRINGS_filename_expand (filename); - GNUNET_DISK_directory_create_for_file (fn); + if (fn == NULL) + return GNUNET_SYSERR; + if (GNUNET_OK != GNUNET_DISK_directory_create_for_file (fn)) + { + GNUNET_free (fn); + return GNUNET_SYSERR; + } if (NULL == (fp = FOPEN (fn, "w"))) { GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "fopen", fn); @@ -392,6 +389,72 @@ GNUNET_CONFIGURATION_iterate (const struct GNUNET_CONFIGURATION_Handle *cfg, } +/** + * Iterate over all sections in the configuration. + * + * @param cfg configuration to inspect + * @param iter function to call on each section + * @param iter_cls closure for iter + */ +void +GNUNET_CONFIGURATION_iterate_sections (const struct GNUNET_CONFIGURATION_Handle *cfg, + GNUNET_CONFIGURATION_Section_Iterator iter, + void *iter_cls) +{ + struct ConfigSection *spos; + struct ConfigSection *next; + + next = cfg->sections; + while (next != NULL) + { + spos = next; + next = spos->next; + iter (iter_cls, spos->name); + } +} + +/** + * Remove the given section and all options in it. + * + * @param cfg configuration to inspect + * @param section name of the section to remove + */ +void GNUNET_CONFIGURATION_remove_section (struct GNUNET_CONFIGURATION_Handle *cfg, + const char *section) +{ + struct ConfigSection *spos; + struct ConfigSection *prev; + struct ConfigEntry *ent; + + prev = NULL; + spos = cfg->sections; + while (spos != NULL) + { + if (0 == strcmp (section, + spos->name)) + { + if (prev == NULL) + cfg->sections = spos->next; + else + prev->next = spos->next; + while (NULL != (ent = spos->entries)) + { + spos->entries = ent->next; + GNUNET_free (ent->key); + GNUNET_free_non_null (ent->val); + GNUNET_free (ent); + cfg->dirty = GNUNET_YES; + } + GNUNET_free (spos->name); + GNUNET_free (spos); + return; + } + prev = spos; + spos = spos->next; + } +} + + /** * Copy a configuration value to the given target configuration. * Overwrites existing entries. @@ -448,11 +511,11 @@ findSection (const struct GNUNET_CONFIGURATION_Handle *cfg, /** - * FIXME. + * Find an entry from a configuration. * - * @param cfg FIXME - * @param section FIXME - * @param key FIXME + * @param cfg handle to the configuration + * @param section section the option is in + * @param key the option * @return matching entry, NULL if not found */ static struct ConfigEntry * @@ -473,88 +536,30 @@ 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 (ConfigurationDiffHandle*) + * 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.) */ -void +static void compareEntries (void *cls, const char *section, const char *option, const char *value) { - struct ConfigSection *secNew; + struct DiffHandle *dh = cls; struct ConfigEntry *entNew; - struct GNUNNET_CONFIGURATION_Diff_Handle *cfgDiff = - (struct GNUNNET_CONFIGURATION_Diff_Handle *) cls; - - secNew = findSection (cfgDiff->cfgNew, section); - entNew = findEntry (cfgDiff->cfgNew, section, option); - if (secNew && strcmp (entNew->val, value) != 0) - { - /* Value in the new configuration has been changed */ - /* Add the changed value to the diff configuration object */ - struct ConfigEntry *diffEntry = NULL; - struct ConfigSection *diffSection = NULL; - - diffSection = cfgDiff->cfgDiff->sections; - if (diffSection == NULL) - { - /* First section */ - diffSection = GNUNET_malloc (sizeof (struct ConfigSection)); - memcpy (diffSection, secNew, sizeof (struct ConfigSection)); - cfgDiff->cfgDiff->sections = diffSection; - diffSection->entries = NULL; - diffSection->next = NULL; - } - else - { - while ((strcmp (diffSection->name, secNew->name) != 0) - && (diffSection->next != NULL)) - { - diffSection = diffSection->next; - } - if (strcmp (diffSection->name, secNew->name) != 0) - { - /* Section not found in diffs configuration */ - diffSection->next = - GNUNET_malloc (sizeof (struct ConfigSection)); - memcpy (diffSection->next, secNew, - sizeof (struct ConfigSection)); - diffSection->next->entries = NULL; - diffSection->next->next = NULL; - } - else - { - diffEntry = diffSection->entries; - } - } - - if (diffEntry == NULL) - { - /* First Entry */ - diffEntry = GNUNET_malloc (sizeof (struct ConfigEntry)); - memcpy (diffEntry, entNew, sizeof (struct ConfigEntry)); - if (diffSection->next == NULL) - /* The first Entry of the first Section */ - diffSection->entries = diffEntry; - else - /* The first entry of the non-first Section */ - diffSection->next->entries = diffEntry; - diffEntry->next = NULL; - } - else - { - while (diffEntry->next != NULL) - { - diffEntry = diffEntry->next; - } - diffEntry->next = GNUNET_malloc (sizeof (struct ConfigEntry)); - memcpy (diffEntry->next, entNew, sizeof (struct ConfigEntry)); - diffEntry->next->next = NULL; - } - } + + 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); } @@ -566,21 +571,18 @@ compareEntries (void *cls, * @return GNUNET_OK on success, GNUNET_SYSERR on error */ int -GNUNET_CONFIGURATION_write_diffs (struct GNUNET_CONFIGURATION_Handle +GNUNET_CONFIGURATION_write_diffs (const struct GNUNET_CONFIGURATION_Handle *cfgDefault, - struct GNUNET_CONFIGURATION_Handle *cfgNew, + const struct GNUNET_CONFIGURATION_Handle *cfgNew, const char *filename) { int ret; - struct GNUNNET_CONFIGURATION_Diff_Handle diffHandle; - diffHandle.cfgDiff = GNUNET_CONFIGURATION_create (); - diffHandle.cfgDiff->sections = NULL; - diffHandle.cfgNew = cfgNew; - GNUNET_CONFIGURATION_iterate (cfgDefault, compareEntries, &diffHandle); + struct DiffHandle diffHandle; + diffHandle.cfgDiff = GNUNET_CONFIGURATION_create (); + diffHandle.cfgDefault = cfgDefault; + GNUNET_CONFIGURATION_iterate (cfgNew, compareEntries, &diffHandle); ret = GNUNET_CONFIGURATION_write (diffHandle.cfgDiff, filename); - - /* Housekeeping */ GNUNET_CONFIGURATION_destroy (diffHandle.cfgDiff); return ret; } @@ -688,13 +690,22 @@ GNUNET_CONFIGURATION_get_value_time (const struct GNUNET_CONFIGURATION_Handle const char *option, struct GNUNET_TIME_Relative *time) { + struct ConfigEntry *e; unsigned long long num; - int ret; - ret = GNUNET_CONFIGURATION_get_value_number (cfg, section, option, &num); - if (ret == GNUNET_OK) - time->value = (uint64_t) num; - return ret; + e = findEntry (cfg, section, option); + if (e == NULL) + return GNUNET_SYSERR; + if ( (0 == strcasecmp (e->val, "infinity")) || + (0 == strcasecmp (e->val, "forever")) ) + { + *time = GNUNET_TIME_UNIT_FOREVER_REL; + return GNUNET_OK; + } + if (1 != SSCANF (e->val, "%llu", &num)) + return GNUNET_SYSERR; + time->rel_value = (uint64_t) num; + return GNUNET_OK; } @@ -825,9 +836,9 @@ GNUNET_CONFIGURATION_expand_dollar (const struct GNUNET_CONFIGURATION_Handle 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]))) { @@ -864,26 +875,20 @@ GNUNET_CONFIGURATION_get_value_filename (const struct 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; } @@ -1079,7 +1084,8 @@ GNUNET_CONFIGURATION_append_value_filename (struct GNUNET_CONFIGURATION_Handle escaped = escape_name (value); nw = GNUNET_malloc (strlen (old) + strlen (escaped) + 2); strcpy (nw, old); - strcat (nw, " "); + if (strlen (old) > 0) + strcat (nw, " "); strcat (nw, escaped); GNUNET_CONFIGURATION_set_value_string (cfg, section, option, nw); GNUNET_free (old); @@ -1148,23 +1154,26 @@ GNUNET_CONFIGURATION_remove_value_filename (struct GNUNET_CONFIGURATION_Handle } old = end[0]; end[0] = '\0'; - if (strlen (pos) > 0) - { - if (0 == strcmp (pos, match)) - { - memmove (pos, &end[1], strlen (&end[1]) + 1); - - if (pos != list) - pos[-1] = ' '; /* previously changed to "\0" */ - GNUNET_CONFIGURATION_set_value_string (cfg, - section, option, list); - GNUNET_free (list); - GNUNET_free (match); - return GNUNET_OK; - } - } + if (0 == strcmp (pos, match)) + { + if (old != '\0') + memmove (pos, &end[1], strlen (&end[1]) + 1); + else + { + if (pos != list) + pos[-1] = '\0'; + else + pos[0] = '\0'; + } + GNUNET_CONFIGURATION_set_value_string (cfg, + section, option, list); + GNUNET_free (list); + GNUNET_free (match); + return GNUNET_OK; + } if (old == '\0') break; + end[0] = old; pos = end + 1; } GNUNET_free (list); @@ -1178,7 +1187,7 @@ GNUNET_CONFIGURATION_remove_value_filename (struct GNUNET_CONFIGURATION_Handle * system-specific configuration). * * @param cfg configuration to update - * @param filename name of the configuration file + * @param filename name of the configuration file, NULL to load defaults * @return GNUNET_OK on success, GNUNET_SYSERR on error */ int @@ -1201,9 +1210,17 @@ GNUNET_CONFIGURATION_load (struct GNUNET_CONFIGURATION_Handle *cfg, (GNUNET_OK == GNUNET_CONFIGURATION_parse (cfg, filename))))) { GNUNET_free (baseconfig); - return GNUNET_SYSERR; + return (filename == NULL) ? GNUNET_OK : 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")) &&