Added functions to settings_t to load files dynamically at runtime.
This commit is contained in:
+124
-28
@@ -50,7 +50,7 @@ struct private_settings_t {
|
|||||||
section_t *top;
|
section_t *top;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* text of loaded files
|
* contents of loaded files
|
||||||
*/
|
*/
|
||||||
linked_list_t *files;
|
linked_list_t *files;
|
||||||
};
|
};
|
||||||
@@ -271,7 +271,7 @@ static char *find_value(section_t *section, char *key, va_list args)
|
|||||||
}
|
}
|
||||||
|
|
||||||
METHOD(settings_t, get_str, char*,
|
METHOD(settings_t, get_str, char*,
|
||||||
private_settings_t *this, char *key, char *def, ...)
|
private_settings_t *this, char *key, char *def, ...)
|
||||||
{
|
{
|
||||||
char *value;
|
char *value;
|
||||||
va_list args;
|
va_list args;
|
||||||
@@ -287,7 +287,7 @@ METHOD(settings_t, get_str, char*,
|
|||||||
}
|
}
|
||||||
|
|
||||||
METHOD(settings_t, get_bool, bool,
|
METHOD(settings_t, get_bool, bool,
|
||||||
private_settings_t *this, char *key, bool def, ...)
|
private_settings_t *this, char *key, bool def, ...)
|
||||||
{
|
{
|
||||||
char *value;
|
char *value;
|
||||||
va_list args;
|
va_list args;
|
||||||
@@ -316,7 +316,7 @@ METHOD(settings_t, get_bool, bool,
|
|||||||
}
|
}
|
||||||
|
|
||||||
METHOD(settings_t, get_int, int,
|
METHOD(settings_t, get_int, int,
|
||||||
private_settings_t *this, char *key, int def, ...)
|
private_settings_t *this, char *key, int def, ...)
|
||||||
{
|
{
|
||||||
char *value;
|
char *value;
|
||||||
int intval;
|
int intval;
|
||||||
@@ -338,7 +338,7 @@ METHOD(settings_t, get_int, int,
|
|||||||
}
|
}
|
||||||
|
|
||||||
METHOD(settings_t, get_double, double,
|
METHOD(settings_t, get_double, double,
|
||||||
private_settings_t *this, char *key, double def, ...)
|
private_settings_t *this, char *key, double def, ...)
|
||||||
{
|
{
|
||||||
char *value;
|
char *value;
|
||||||
double dval;
|
double dval;
|
||||||
@@ -360,7 +360,7 @@ METHOD(settings_t, get_double, double,
|
|||||||
}
|
}
|
||||||
|
|
||||||
METHOD(settings_t, get_time, u_int32_t,
|
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;
|
char *value, *endptr;
|
||||||
u_int32_t timeval;
|
u_int32_t timeval;
|
||||||
@@ -406,7 +406,7 @@ static bool section_filter(void *null, section_t **in, char **out)
|
|||||||
}
|
}
|
||||||
|
|
||||||
METHOD(settings_t, create_section_enumerator, enumerator_t*,
|
METHOD(settings_t, create_section_enumerator, enumerator_t*,
|
||||||
private_settings_t *this, char *key, ...)
|
private_settings_t *this, char *key, ...)
|
||||||
{
|
{
|
||||||
section_t *section;
|
section_t *section;
|
||||||
va_list args;
|
va_list args;
|
||||||
@@ -436,7 +436,7 @@ static bool kv_filter(void *null, kv_t **in, char **key,
|
|||||||
}
|
}
|
||||||
|
|
||||||
METHOD(settings_t, create_key_value_enumerator, enumerator_t*,
|
METHOD(settings_t, create_key_value_enumerator, enumerator_t*,
|
||||||
private_settings_t *this, char *key, ...)
|
private_settings_t *this, char *key, ...)
|
||||||
{
|
{
|
||||||
section_t *section;
|
section_t *section;
|
||||||
va_list args;
|
va_list args;
|
||||||
@@ -616,13 +616,13 @@ static bool parse_include(char **text, char **pattern)
|
|||||||
/**
|
/**
|
||||||
* Forward declaration.
|
* 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);
|
char *pattern, section_t *section);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse a 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)
|
char **text, section_t *section)
|
||||||
{
|
{
|
||||||
bool finished = FALSE;
|
bool finished = FALSE;
|
||||||
@@ -632,7 +632,7 @@ static bool parse_section(private_settings_t *this, char *file, int level,
|
|||||||
{
|
{
|
||||||
if (parse_include(text, &value))
|
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);
|
DBG1(DBG_LIB, "failed to include '%s'", value);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
@@ -650,7 +650,7 @@ static bool parse_section(private_settings_t *this, char *file, int level,
|
|||||||
(void**)&sub, key) != SUCCESS)
|
(void**)&sub, key) != SUCCESS)
|
||||||
{
|
{
|
||||||
sub = section_create(key);
|
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,
|
section->sections->insert_last(section->sections,
|
||||||
sub);
|
sub);
|
||||||
@@ -660,7 +660,7 @@ static bool parse_section(private_settings_t *this, char *file, int level,
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{ /* extend the existing section */
|
{ /* extend the existing section */
|
||||||
if (parse_section(this, file, level, &inner, sub))
|
if (parse_section(files, file, level, &inner, sub))
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -707,7 +707,7 @@ static bool parse_section(private_settings_t *this, char *file, int level,
|
|||||||
/**
|
/**
|
||||||
* Parse a file and add the settings to the given section.
|
* 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)
|
section_t *section)
|
||||||
{
|
{
|
||||||
bool success;
|
bool success;
|
||||||
@@ -735,14 +735,14 @@ static bool parse_file(private_settings_t *this, char *file, int level,
|
|||||||
fclose(fd);
|
fclose(fd);
|
||||||
|
|
||||||
pos = text;
|
pos = text;
|
||||||
success = parse_section(this, file, level, &pos, section);
|
success = parse_section(files, file, level, &pos, section);
|
||||||
if (!success)
|
if (!success)
|
||||||
{
|
{
|
||||||
free(text);
|
free(text);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
this->files->insert_last(this->files, text);
|
files->insert_last(files, text);
|
||||||
}
|
}
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
@@ -751,7 +751,7 @@ static bool parse_file(private_settings_t *this, char *file, int level,
|
|||||||
* Load the files matching "pattern", which is resolved with glob(3).
|
* Load the files matching "pattern", which is resolved with glob(3).
|
||||||
* If the pattern is relative, the directory of "file" is used as base.
|
* 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)
|
char *pattern, section_t *section)
|
||||||
{
|
{
|
||||||
bool success = TRUE;
|
bool success = TRUE;
|
||||||
@@ -806,7 +806,7 @@ static bool parse_files(private_settings_t *this, char *file, int level,
|
|||||||
{
|
{
|
||||||
for (expanded = buf.gl_pathv; *expanded != NULL; expanded++)
|
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)
|
if (!success)
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
@@ -817,13 +817,110 @@ static bool parse_files(private_settings_t *this, char *file, int level,
|
|||||||
return success;
|
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)
|
||||||
{
|
{
|
||||||
if (this->top)
|
enumerator_t *sections, *values;
|
||||||
|
section_t *sec;
|
||||||
|
kv_t *kv;
|
||||||
|
|
||||||
|
sections = extension->sections->create_enumerator(extension->sections);
|
||||||
|
while (sections->enumerate(sections, (void**)&sec))
|
||||||
{
|
{
|
||||||
section_destroy(this->top);
|
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)
|
||||||
|
{
|
||||||
|
char *text;
|
||||||
|
linked_list_t *files = linked_list_create();
|
||||||
|
section_t *section = section_create(NULL);
|
||||||
|
|
||||||
|
if (!parse_files(files, NULL, 0, pattern, section))
|
||||||
|
{
|
||||||
|
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);
|
this->files->destroy_function(this->files, (void*)free);
|
||||||
free(this);
|
free(this);
|
||||||
}
|
}
|
||||||
@@ -844,8 +941,11 @@ settings_t *settings_create(char *file)
|
|||||||
.get_bool = _get_bool,
|
.get_bool = _get_bool,
|
||||||
.create_section_enumerator = _create_section_enumerator,
|
.create_section_enumerator = _create_section_enumerator,
|
||||||
.create_key_value_enumerator = _create_key_value_enumerator,
|
.create_key_value_enumerator = _create_key_value_enumerator,
|
||||||
|
.load_files = _load_files,
|
||||||
|
.load_files_section = _load_files_section,
|
||||||
.destroy = _destroy,
|
.destroy = _destroy,
|
||||||
},
|
},
|
||||||
|
.top = section_create(NULL),
|
||||||
.files = linked_list_create(),
|
.files = linked_list_create(),
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -854,12 +954,8 @@ settings_t *settings_create(char *file)
|
|||||||
file = STRONGSWAN_CONF;
|
file = STRONGSWAN_CONF;
|
||||||
}
|
}
|
||||||
|
|
||||||
this->top = section_create(NULL);
|
load_files(this, file);
|
||||||
if (!parse_files(this, NULL, 0, file, this->top))
|
|
||||||
{
|
|
||||||
section_destroy(this->top);
|
|
||||||
this->top = NULL;
|
|
||||||
}
|
|
||||||
return &this->public;
|
return &this->public;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -127,6 +127,39 @@ struct settings_t {
|
|||||||
enumerator_t* (*create_key_value_enumerator)(settings_t *this,
|
enumerator_t* (*create_key_value_enumerator)(settings_t *this,
|
||||||
char *section, ...);
|
char *section, ...);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load settings from the files matching the given pattern.
|
||||||
|
*
|
||||||
|
* Existing sections are extended, existing values replaced, by those found
|
||||||
|
* in the loaded files.
|
||||||
|
*
|
||||||
|
* @note If any of the files matching the pattern fails to load, no settings
|
||||||
|
* are added at all. So it's all or nothing.
|
||||||
|
*
|
||||||
|
* @param pattern file pattern
|
||||||
|
* @return TRUE, if settings were loaded successfully
|
||||||
|
*/
|
||||||
|
bool (*load_files)(settings_t *this, char *pattern);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load settings from the files matching the given pattern.
|
||||||
|
*
|
||||||
|
* Existing sections are extended, existing values replaced, by those found
|
||||||
|
* in the loaded files.
|
||||||
|
*
|
||||||
|
* All settings are loaded relative to the given section.
|
||||||
|
*
|
||||||
|
* @note If any of the files matching the pattern fails to load, no settings
|
||||||
|
* are added at all. So it's all or nothing.
|
||||||
|
*
|
||||||
|
* @param pattern file pattern
|
||||||
|
* @param section section name of parent section, printf style
|
||||||
|
* @param ... argument list for section
|
||||||
|
* @return TRUE, if section is found and settings were loaded successfully
|
||||||
|
*/
|
||||||
|
bool (*load_files_section)(settings_t *this, char *pattern,
|
||||||
|
char *section, ...);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Destroy a settings instance.
|
* Destroy a settings instance.
|
||||||
*/
|
*/
|
||||||
|
|||||||
Reference in New Issue
Block a user