diff options
-rw-r--r-- | src/common/conffile.c | 164 | ||||
-rw-r--r-- | src/common/conffile.h | 17 | ||||
-rw-r--r-- | src/common/confline.c | 168 | ||||
-rw-r--r-- | src/common/confline.h | 20 | ||||
-rw-r--r-- | src/common/include.am | 2 | ||||
-rw-r--r-- | src/or/config.c | 1 | ||||
-rw-r--r-- | src/test/test_config.c | 3 |
7 files changed, 209 insertions, 166 deletions
diff --git a/src/common/conffile.c b/src/common/conffile.c new file mode 100644 index 0000000000..bfb78c35c6 --- /dev/null +++ b/src/common/conffile.c @@ -0,0 +1,164 @@ +/* Copyright (c) 2001 Matej Pfajfar. + * Copyright (c) 2001-2004, Roger Dingledine. + * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. + * Copyright (c) 2007-2018, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +#include "common/compat.h" +#include "common/confline.h" +#include "common/conffile.h" +#include "lib/log/torlog.h" +#include "common/util.h" +#include "lib/container/smartlist.h" + +static smartlist_t *config_get_file_list(const char *path, + smartlist_t *opened_files); +static int config_get_included_config(const char *path, int recursion_level, + int extended, config_line_t **config, + config_line_t **config_last, + smartlist_t *opened_lst); +static int config_process_include(const char *path, int recursion_level, + int extended, config_line_t **list, + config_line_t **list_last, + smartlist_t *opened_lst); + +/** Helper: parse the config string and strdup into key/value + * strings. Set *result to the list, or NULL if parsing the string + * failed. Set *has_include to 1 if <b>result</b> has values from + * %included files. <b>opened_lst</b> will have a list of opened files if + * provided. Return 0 on success, -1 on failure. Warn and ignore any + * misformatted lines. + * + * If <b>extended</b> is set, then treat keys beginning with / and with + as + * indicating "clear" and "append" respectively. */ +int +config_get_lines_include(const char *string, config_line_t **result, + int extended, int *has_include, + smartlist_t *opened_lst) +{ + return config_get_lines_aux(string, result, extended, 1, has_include, + opened_lst, 1, NULL, config_process_include); +} + +/** Adds a list of configuration files present on <b>path</b> to + * <b>file_list</b>. <b>path</b> can be a file or a directory. If it is a file, + * only that file will be added to <b>file_list</b>. If it is a directory, + * all paths for files on that directory root (no recursion) except for files + * whose name starts with a dot will be added to <b>file_list</b>. + * <b>opened_files</b> will have a list of files opened by this function + * if provided. Return 0 on success, -1 on failure. Ignores empty files. + */ +static smartlist_t * +config_get_file_list(const char *path, smartlist_t *opened_files) +{ + smartlist_t *file_list = smartlist_new(); + + if (opened_files) { + smartlist_add_strdup(opened_files, path); + } + + file_status_t file_type = file_status(path); + if (file_type == FN_FILE) { + smartlist_add_strdup(file_list, path); + return file_list; + } else if (file_type == FN_DIR) { + smartlist_t *all_files = tor_listdir(path); + if (!all_files) { + smartlist_free(file_list); + return NULL; + } + smartlist_sort_strings(all_files); + SMARTLIST_FOREACH_BEGIN(all_files, char *, f) { + if (f[0] == '.') { + tor_free(f); + continue; + } + + char *fullname; + tor_asprintf(&fullname, "%s"PATH_SEPARATOR"%s", path, f); + tor_free(f); + + if (opened_files) { + smartlist_add_strdup(opened_files, fullname); + } + + if (file_status(fullname) != FN_FILE) { + tor_free(fullname); + continue; + } + smartlist_add(file_list, fullname); + } SMARTLIST_FOREACH_END(f); + smartlist_free(all_files); + return file_list; + } else if (file_type == FN_EMPTY) { + return file_list; + } else { + smartlist_free(file_list); + return NULL; + } +} + +/** Creates a list of config lines present on included <b>path</b>. + * Set <b>config</b> to the list and <b>config_last</b> to the last element of + * <b>config</b>. <b>opened_lst</b> will have a list of opened files if + * provided. Return 0 on success, -1 on failure. */ +static int +config_get_included_config(const char *path, int recursion_level, int extended, + config_line_t **config, config_line_t **config_last, + smartlist_t *opened_lst) +{ + char *included_conf = read_file_to_str(path, 0, NULL); + if (!included_conf) { + return -1; + } + + if (config_get_lines_aux(included_conf, config, extended, 1, NULL, + opened_lst, recursion_level+1, config_last, + config_process_include) < 0) { + tor_free(included_conf); + return -1; + } + + tor_free(included_conf); + return 0; +} + +/** Process an %include <b>path</b> in a config file. Set <b>list</b> to the + * list of configuration settings obtained and <b>list_last</b> to the last + * element of the same list. <b>opened_lst</b> will have a list of opened + * files if provided. Return 0 on success, -1 on failure. */ +static int +config_process_include(const char *path, int recursion_level, int extended, + config_line_t **list, config_line_t **list_last, + smartlist_t *opened_lst) +{ + config_line_t *ret_list = NULL; + config_line_t **next = &ret_list; + + smartlist_t *config_files = config_get_file_list(path, opened_lst); + if (!config_files) { + return -1; + } + + int rv = -1; + SMARTLIST_FOREACH_BEGIN(config_files, const char *, config_file) { + config_line_t *included_config = NULL; + if (config_get_included_config(config_file, recursion_level, extended, + &included_config, list_last, + opened_lst) < 0) { + goto done; + } + + *next = included_config; + if (*list_last) + next = &(*list_last)->next; + + } SMARTLIST_FOREACH_END(config_file); + *list = ret_list; + rv = 0; + + done: + SMARTLIST_FOREACH(config_files, char *, f, tor_free(f)); + smartlist_free(config_files); + return rv; +} diff --git a/src/common/conffile.h b/src/common/conffile.h new file mode 100644 index 0000000000..bd8250b002 --- /dev/null +++ b/src/common/conffile.h @@ -0,0 +1,17 @@ +/* Copyright (c) 2001 Matej Pfajfar. + * Copyright (c) 2001-2004, Roger Dingledine. + * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. + * Copyright (c) 2007-2018, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +#ifndef TOR_CONFFILE_H +#define TOR_CONFFILE_H + +struct smartlist_t; +struct config_line_t; + +int config_get_lines_include(const char *string, struct config_line_t **result, + int extended, int *has_include, + struct smartlist_t *opened_lst); + +#endif /* !defined(TOR_CONFLINE_H) */ diff --git a/src/common/confline.c b/src/common/confline.c index 9e37bfbdb7..80e5994ce8 100644 --- a/src/common/confline.c +++ b/src/common/confline.c @@ -10,21 +10,6 @@ #include "common/util.h" #include "lib/container/smartlist.h" -static int config_get_lines_aux(const char *string, config_line_t **result, - int extended, int allow_include, - int *has_include, smartlist_t *opened_lst, - int recursion_level, config_line_t **last); -static smartlist_t *config_get_file_list(const char *path, - smartlist_t *opened_files); -static int config_get_included_config(const char *path, int recursion_level, - int extended, config_line_t **config, - config_line_t **config_last, - smartlist_t *opened_lst); -static int config_process_include(const char *path, int recursion_level, - int extended, config_line_t **list, - config_line_t **list_last, - smartlist_t *opened_lst); - /** Helper: allocate a new configuration option mapping 'key' to 'val', * append it to *<b>lst</b>. */ void @@ -86,11 +71,12 @@ config_line_find(const config_line_t *lines, * <b>opened_lst</b> will have a list of opened files if provided. * Returns the a pointer to the last element of the <b>result</b> in * <b>last</b>. */ -static int +int config_get_lines_aux(const char *string, config_line_t **result, int extended, int allow_include, int *has_include, smartlist_t *opened_lst, int recursion_level, - config_line_t **last) + config_line_t **last, + include_handler_fn handle_include) { config_line_t *list = NULL, **next, *list_last = NULL; char *k, *v; @@ -133,13 +119,13 @@ config_get_lines_aux(const char *string, config_line_t **result, int extended, } } - if (allow_include && !strcmp(k, "%include")) { + if (allow_include && !strcmp(k, "%include") && handle_include) { tor_free(k); include_used = 1; config_line_t *include_list; - if (config_process_include(v, recursion_level, extended, &include_list, - &list_last, opened_lst) < 0) { + if (handle_include(v, recursion_level, extended, &include_list, + &list_last, opened_lst) < 0) { log_warn(LD_CONFIG, "Error reading included configuration " "file or directory: \"%s\".", v); config_free_lines(list); @@ -178,152 +164,12 @@ config_get_lines_aux(const char *string, config_line_t **result, int extended, return 0; } -/** Helper: parse the config string and strdup into key/value - * strings. Set *result to the list, or NULL if parsing the string - * failed. Set *has_include to 1 if <b>result</b> has values from - * %included files. <b>opened_lst</b> will have a list of opened files if - * provided. Return 0 on success, -1 on failure. Warn and ignore any - * misformatted lines. - * - * If <b>extended</b> is set, then treat keys beginning with / and with + as - * indicating "clear" and "append" respectively. */ -int -config_get_lines_include(const char *string, config_line_t **result, - int extended, int *has_include, - smartlist_t *opened_lst) -{ - return config_get_lines_aux(string, result, extended, 1, has_include, - opened_lst, 1, NULL); -} - /** Same as config_get_lines_include but does not allow %include */ int config_get_lines(const char *string, config_line_t **result, int extended) { return config_get_lines_aux(string, result, extended, 0, NULL, NULL, 1, - NULL); -} - -/** Adds a list of configuration files present on <b>path</b> to - * <b>file_list</b>. <b>path</b> can be a file or a directory. If it is a file, - * only that file will be added to <b>file_list</b>. If it is a directory, - * all paths for files on that directory root (no recursion) except for files - * whose name starts with a dot will be added to <b>file_list</b>. - * <b>opened_files</b> will have a list of files opened by this function - * if provided. Return 0 on success, -1 on failure. Ignores empty files. - */ -static smartlist_t * -config_get_file_list(const char *path, smartlist_t *opened_files) -{ - smartlist_t *file_list = smartlist_new(); - - if (opened_files) { - smartlist_add_strdup(opened_files, path); - } - - file_status_t file_type = file_status(path); - if (file_type == FN_FILE) { - smartlist_add_strdup(file_list, path); - return file_list; - } else if (file_type == FN_DIR) { - smartlist_t *all_files = tor_listdir(path); - if (!all_files) { - smartlist_free(file_list); - return NULL; - } - smartlist_sort_strings(all_files); - SMARTLIST_FOREACH_BEGIN(all_files, char *, f) { - if (f[0] == '.') { - tor_free(f); - continue; - } - - char *fullname; - tor_asprintf(&fullname, "%s"PATH_SEPARATOR"%s", path, f); - tor_free(f); - - if (opened_files) { - smartlist_add_strdup(opened_files, fullname); - } - - if (file_status(fullname) != FN_FILE) { - tor_free(fullname); - continue; - } - smartlist_add(file_list, fullname); - } SMARTLIST_FOREACH_END(f); - smartlist_free(all_files); - return file_list; - } else if (file_type == FN_EMPTY) { - return file_list; - } else { - smartlist_free(file_list); - return NULL; - } -} - -/** Creates a list of config lines present on included <b>path</b>. - * Set <b>config</b> to the list and <b>config_last</b> to the last element of - * <b>config</b>. <b>opened_lst</b> will have a list of opened files if - * provided. Return 0 on success, -1 on failure. */ -static int -config_get_included_config(const char *path, int recursion_level, int extended, - config_line_t **config, config_line_t **config_last, - smartlist_t *opened_lst) -{ - char *included_conf = read_file_to_str(path, 0, NULL); - if (!included_conf) { - return -1; - } - - if (config_get_lines_aux(included_conf, config, extended, 1, NULL, - opened_lst, recursion_level+1, config_last) < 0) { - tor_free(included_conf); - return -1; - } - - tor_free(included_conf); - return 0; -} - -/** Process an %include <b>path</b> in a config file. Set <b>list</b> to the - * list of configuration settings obtained and <b>list_last</b> to the last - * element of the same list. <b>opened_lst</b> will have a list of opened - * files if provided. Return 0 on success, -1 on failure. */ -static int -config_process_include(const char *path, int recursion_level, int extended, - config_line_t **list, config_line_t **list_last, - smartlist_t *opened_lst) -{ - config_line_t *ret_list = NULL; - config_line_t **next = &ret_list; - - smartlist_t *config_files = config_get_file_list(path, opened_lst); - if (!config_files) { - return -1; - } - - int rv = -1; - SMARTLIST_FOREACH_BEGIN(config_files, const char *, config_file) { - config_line_t *included_config = NULL; - if (config_get_included_config(config_file, recursion_level, extended, - &included_config, list_last, - opened_lst) < 0) { - goto done; - } - - *next = included_config; - if (*list_last) - next = &(*list_last)->next; - - } SMARTLIST_FOREACH_END(config_file); - *list = ret_list; - rv = 0; - - done: - SMARTLIST_FOREACH(config_files, char *, f, tor_free(f)); - smartlist_free(config_files); - return rv; + NULL, NULL); } /** diff --git a/src/common/confline.h b/src/common/confline.h index d1f6fdb7e5..f03faed5eb 100644 --- a/src/common/confline.h +++ b/src/common/confline.h @@ -44,10 +44,6 @@ const config_line_t *config_line_find(const config_line_t *lines, const char *key); int config_lines_eq(config_line_t *a, config_line_t *b); int config_count_key(const config_line_t *a, const char *key); -int config_get_lines(const char *string, config_line_t **result, int extended); -int config_get_lines_include(const char *string, config_line_t **result, - int extended, int *has_include, - struct smartlist_t *opened_lst); void config_free_lines_(config_line_t *front); #define config_free_lines(front) \ do { \ @@ -57,4 +53,20 @@ void config_free_lines_(config_line_t *front); const char *parse_config_line_from_str_verbose(const char *line, char **key_out, char **value_out, const char **err_out); + +int config_get_lines(const char *string, struct config_line_t **result, + int extended); + +typedef int (*include_handler_fn)(const char *, int, int, + struct config_line_t **, + struct config_line_t **, + struct smartlist_t *); + +int config_get_lines_aux(const char *string, struct config_line_t **result, + int extended, + int allow_include, int *has_include, + struct smartlist_t *opened_lst, int recursion_level, + config_line_t **last, + include_handler_fn handle_include); + #endif /* !defined(TOR_CONFLINE_H) */ diff --git a/src/common/include.am b/src/common/include.am index 2360c7f775..4fd3284abc 100644 --- a/src/common/include.am +++ b/src/common/include.am @@ -37,6 +37,7 @@ LIBOR_A_SRC = \ src/common/compat_threads.c \ src/common/compat_time.c \ src/common/confline.c \ + src/common/conffile.c \ src/common/memarea.c \ src/common/util.c \ src/common/util_process.c \ @@ -79,6 +80,7 @@ COMMONHEADERS = \ src/common/compat_libevent.h \ src/common/compat_threads.h \ src/common/compat_time.h \ + src/common/conffile.h \ src/common/confline.h \ src/common/handles.h \ src/common/memarea.h \ diff --git a/src/or/config.c b/src/or/config.c index 98f3ff77b0..b0141b9c0e 100644 --- a/src/or/config.c +++ b/src/or/config.c @@ -111,6 +111,7 @@ #include <shlobj.h> #endif +#include "common/conffile.h" #include "common/procmon.h" #include "or/dirauth/dirvote.h" diff --git a/src/test/test_config.c b/src/test/test_config.c index 5abc97fc3b..dcdaa2ed59 100644 --- a/src/test/test_config.c +++ b/src/test/test_config.c @@ -48,6 +48,8 @@ #include "or/port_cfg_st.h" #include "or/routerinfo_st.h" +#include "common/conffile.h" + static void test_config_addressmap(void *arg) { @@ -5731,4 +5733,3 @@ struct testcase_t config_tests[] = { CONFIG_TEST(compute_max_mem_in_queues, 0), END_OF_TESTCASES }; - |