section_t *top;
/**
- * text of loaded files
+ * contents of loaded files
*/
linked_list_t *files;
};
}
METHOD(settings_t, get_str, char*,
- private_settings_t *this, char *key, char *def, ...)
+ private_settings_t *this, char *key, char *def, ...)
{
char *value;
va_list args;
}
METHOD(settings_t, get_bool, bool,
- private_settings_t *this, char *key, bool def, ...)
+ private_settings_t *this, char *key, bool def, ...)
{
char *value;
va_list args;
}
METHOD(settings_t, get_int, int,
- private_settings_t *this, char *key, int def, ...)
+ private_settings_t *this, char *key, int def, ...)
{
char *value;
int intval;
}
METHOD(settings_t, get_double, double,
- private_settings_t *this, char *key, double def, ...)
+ private_settings_t *this, char *key, double def, ...)
{
char *value;
double dval;
}
METHOD(settings_t, get_time, u_int32_t,
- private_settings_t *this, char *key, u_int32_t def, ...)
+ private_settings_t *this, char *key, u_int32_t def, ...)
{
char *value, *endptr;
u_int32_t timeval;
}
METHOD(settings_t, create_section_enumerator, enumerator_t*,
- private_settings_t *this, char *key, ...)
+ private_settings_t *this, char *key, ...)
{
section_t *section;
va_list args;
}
METHOD(settings_t, create_key_value_enumerator, enumerator_t*,
- private_settings_t *this, char *key, ...)
+ private_settings_t *this, char *key, ...)
{
section_t *section;
va_list args;
/**
* Forward declaration.
*/
-static bool parse_files(private_settings_t *this, char *file, int level,
+static bool parse_files(linked_list_t *files, char *file, int level,
char *pattern, section_t *section);
/**
* Parse a section
*/
-static bool parse_section(private_settings_t *this, char *file, int level,
+static bool parse_section(linked_list_t *files, char *file, int level,
char **text, section_t *section)
{
bool finished = FALSE;
{
if (parse_include(text, &value))
{
- if (!parse_files(this, file, level, value, section))
+ if (!parse_files(files, file, level, value, section))
{
DBG1(DBG_LIB, "failed to include '%s'", value);
return FALSE;
(void**)&sub, key) != SUCCESS)
{
sub = section_create(key);
- if (parse_section(this, file, level, &inner, sub))
+ if (parse_section(files, file, level, &inner, sub))
{
section->sections->insert_last(section->sections,
sub);
}
else
{ /* extend the existing section */
- if (parse_section(this, file, level, &inner, sub))
+ if (parse_section(files, file, level, &inner, sub))
{
continue;
}
/**
* Parse a file and add the settings to the given section.
*/
-static bool parse_file(private_settings_t *this, char *file, int level,
+static bool parse_file(linked_list_t *files, char *file, int level,
section_t *section)
{
bool success;
fclose(fd);
pos = text;
- success = parse_section(this, file, level, &pos, section);
+ success = parse_section(files, file, level, &pos, section);
if (!success)
{
free(text);
}
else
{
- this->files->insert_last(this->files, text);
+ files->insert_last(files, text);
}
return success;
}
* Load the files matching "pattern", which is resolved with glob(3).
* If the pattern is relative, the directory of "file" is used as base.
*/
-static bool parse_files(private_settings_t *this, char *file, int level,
+static bool parse_files(linked_list_t *files, char *file, int level,
char *pattern, section_t *section)
{
bool success = TRUE;
{
for (expanded = buf.gl_pathv; *expanded != NULL; expanded++)
{
- success &= parse_file(this, *expanded, level + 1, section);
+ success &= parse_file(files, *expanded, level + 1, section);
if (!success)
{
break;
return success;
}
-METHOD(settings_t, destroy, void,
- private_settings_t *this)
+/**
+ * Recursivly extends "base" with "extension".
+ */
+static void section_extend(section_t *base, section_t *extension)
+{
+ enumerator_t *sections, *values;
+ section_t *sec;
+ kv_t *kv;
+
+ sections = extension->sections->create_enumerator(extension->sections);
+ while (sections->enumerate(sections, (void**)&sec))
+ {
+ section_t *found;
+ if (base->sections->find_first(base->sections,
+ (linked_list_match_t)section_find, (void**)&found,
+ sec->name) == SUCCESS)
+ {
+ section_extend(found, sec);
+ }
+ else
+ {
+ extension->sections->remove_at(extension->sections, sections);
+ base->sections->insert_last(base->sections, sec);
+ }
+ }
+ sections->destroy(sections);
+
+ values = extension->kv->create_enumerator(extension->kv);
+ while (values->enumerate(values, (void**)&kv))
+ {
+ kv_t *found;
+ if (base->kv->find_first(base->kv, (linked_list_match_t)kv_find,
+ (void**)&found, kv->key) == SUCCESS)
+ {
+ found->value = kv->value;
+ }
+ else
+ {
+ extension->kv->remove_at(extension->kv, values);
+ base->kv->insert_last(base->kv, kv);
+ }
+ }
+ values->destroy(values);
+}
+
+/**
+ * Load settings from files matching the given file pattern.
+ * All sections and values are added relative to "parent".
+ * All files (even included ones) have to be loaded successfully.
+ */
+static bool load_files_internal(private_settings_t *this, section_t *parent,
+ char *pattern)
{
- if (this->top)
+ char *text;
+ linked_list_t *files = linked_list_create();
+ section_t *section = section_create(NULL);
+
+ if (!parse_files(files, NULL, 0, pattern, section))
{
- section_destroy(this->top);
+ files->destroy_function(files, (void*)free);
+ section_destroy(section);
+ return FALSE;
}
+
+ /* extend parent section */
+ section_extend(parent, section);
+ /* move contents of loaded files to main store */
+ while (files->remove_first(files, (void**)&text) == SUCCESS)
+ {
+ this->files->insert_last(this->files, text);
+ }
+
+ section_destroy(section);
+ files->destroy(files);
+ return TRUE;
+}
+
+METHOD(settings_t, load_files, bool,
+ private_settings_t *this, char *pattern)
+{
+ return load_files_internal(this, this->top, pattern);
+}
+
+METHOD(settings_t, load_files_section, bool,
+ private_settings_t *this, char *pattern, char *key, ...)
+{
+ section_t *section;
+ va_list args;
+
+ va_start(args, key);
+ section = find_section(this, this->top, key, args);
+ va_end(args);
+
+ if (!section)
+ {
+ return FALSE;
+ }
+ return load_files_internal(this, section, pattern);
+}
+
+METHOD(settings_t, destroy, void,
+ private_settings_t *this)
+{
+ section_destroy(this->top);
this->files->destroy_function(this->files, (void*)free);
free(this);
}
.get_bool = _get_bool,
.create_section_enumerator = _create_section_enumerator,
.create_key_value_enumerator = _create_key_value_enumerator,
+ .load_files = _load_files,
+ .load_files_section = _load_files_section,
.destroy = _destroy,
},
+ .top = section_create(NULL),
.files = linked_list_create(),
);
file = STRONGSWAN_CONF;
}
- this->top = section_create(NULL);
- if (!parse_files(this, NULL, 0, file, this->top))
- {
- section_destroy(this->top);
- this->top = NULL;
- }
+ load_files(this, file);
+
return &this->public;
}