diff options
Diffstat (limited to 'src/libstrongswan/settings.c')
-rw-r--r-- | src/libstrongswan/settings.c | 113 |
1 files changed, 80 insertions, 33 deletions
diff --git a/src/libstrongswan/settings.c b/src/libstrongswan/settings.c index bd279f51d..8a2248b46 100644 --- a/src/libstrongswan/settings.c +++ b/src/libstrongswan/settings.c @@ -20,8 +20,14 @@ #include <stdio.h> #include <errno.h> #include <limits.h> -#include <glob.h> #include <libgen.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> + +#ifdef HAVE_GLOB_H +#include <glob.h> +#endif /* HAVE_GLOB_H */ #include "settings.h" @@ -146,6 +152,17 @@ static void section_destroy(section_t *this) } /** + * Purge contents of a section + */ +static void section_purge(section_t *this) +{ + this->kv->destroy_function(this->kv, (void*)kv_destroy); + this->kv = linked_list_create(); + this->sections->destroy_function(this->sections, (void*)section_destroy); + this->sections = linked_list_create(); +} + +/** * callback to find a section by name */ static bool section_find(section_t *this, char *name) @@ -914,14 +931,30 @@ static bool parse_file(linked_list_t *contents, char *file, int level, { bool success; char *text, *pos; + struct stat st; FILE *fd; int len; DBG2(DBG_LIB, "loading config file '%s'", file); + if (stat(file, &st) == -1) + { + if (errno == ENOENT) + { + DBG2(DBG_LIB, "'%s' does not exist, ignored", file); + return TRUE; + } + DBG1(DBG_LIB, "failed to stat '%s': %s", file, strerror(errno)); + return FALSE; + } + else if (!S_ISREG(st.st_mode)) + { + DBG1(DBG_LIB, "'%s' is not a regular file", file); + return FALSE; + } fd = fopen(file, "r"); if (fd == NULL) { - DBG1(DBG_LIB, "'%s' does not exist or is not readable", file); + DBG1(DBG_LIB, "'%s' is not readable", file); return FALSE; } fseek(fd, 0, SEEK_END); @@ -950,16 +983,15 @@ static bool parse_file(linked_list_t *contents, 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 + * available. * If the pattern is relative, the directory of "file" is used as base. */ static bool parse_files(linked_list_t *contents, char *file, int level, char *pattern, section_t *section) { bool success = TRUE; - int status; - glob_t buf; - char **expanded, pat[PATH_MAX]; + char pat[PATH_MAX]; if (level > MAX_INCLUSION_LEVEL) { @@ -994,28 +1026,39 @@ static bool parse_files(linked_list_t *contents, char *file, int level, } free(dir); } - status = glob(pat, GLOB_ERR, NULL, &buf); - if (status == GLOB_NOMATCH) - { - DBG2(DBG_LIB, "no files found matching '%s', ignored", pat); - } - else if (status != 0) +#ifdef HAVE_GLOB_H { - DBG1(DBG_LIB, "expanding file pattern '%s' failed", pat); - success = FALSE; - } - else - { - for (expanded = buf.gl_pathv; *expanded != NULL; expanded++) + int status; + glob_t buf; + + status = glob(pat, GLOB_ERR, NULL, &buf); + if (status == GLOB_NOMATCH) + { + DBG2(DBG_LIB, "no files found matching '%s', ignored", pat); + } + else if (status != 0) { - success &= parse_file(contents, *expanded, level + 1, section); - if (!success) + DBG1(DBG_LIB, "expanding file pattern '%s' failed", pat); + success = FALSE; + } + else + { + char **expanded; + for (expanded = buf.gl_pathv; *expanded != NULL; expanded++) { - break; + success &= parse_file(contents, *expanded, level + 1, section); + if (!success) + { + break; + } } } + globfree(&buf); } - globfree(&buf); +#else /* HAVE_GLOB_H */ + /* if glob(3) is not available, try to load pattern directly */ + success = parse_file(contents, pat, level + 1, section); +#endif /* HAVE_GLOB_H */ return success; } @@ -1070,12 +1113,17 @@ static void section_extend(section_t *base, section_t *extension) * 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 *pattern, bool merge) { char *text; linked_list_t *contents = linked_list_create(); section_t *section = section_create(NULL); + if (pattern == NULL) + { + pattern = STRONGSWAN_CONF; + } + if (!parse_files(contents, NULL, 0, pattern, section)) { contents->destroy_function(contents, (void*)free); @@ -1084,6 +1132,10 @@ static bool load_files_internal(private_settings_t *this, section_t *parent, } this->lock->write_lock(this->lock); + if (!merge) + { + section_purge(parent); + } /* extend parent section */ section_extend(parent, section); /* move contents of loaded files to main store */ @@ -1099,13 +1151,13 @@ static bool load_files_internal(private_settings_t *this, section_t *parent, } METHOD(settings_t, load_files, bool, - private_settings_t *this, char *pattern) + private_settings_t *this, char *pattern, bool merge) { - return load_files_internal(this, this->top, pattern); + return load_files_internal(this, this->top, pattern, merge); } METHOD(settings_t, load_files_section, bool, - private_settings_t *this, char *pattern, char *key, ...) + private_settings_t *this, char *pattern, bool merge, char *key, ...) { section_t *section; va_list args; @@ -1118,7 +1170,7 @@ METHOD(settings_t, load_files_section, bool, { return FALSE; } - return load_files_internal(this, section, pattern); + return load_files_internal(this, section, pattern, merge); } METHOD(settings_t, destroy, void, @@ -1160,12 +1212,7 @@ settings_t *settings_create(char *file) .lock = rwlock_create(RWLOCK_TYPE_DEFAULT), ); - if (file == NULL) - { - file = STRONGSWAN_CONF; - } - - load_files(this, file); + load_files(this, file, FALSE); return &this->public; } |