From 696f6f15697260255146d634e1529202cc4c2b77 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Wed, 27 Jun 2018 16:43:01 -0400 Subject: Split confline into confline and conffile. The "conffile" module knows about includes and filesystem access, whereas confline doesn't. This will make it possible to put these functions into libraries without introducing a cycle. --- src/common/conffile.c | 164 +++++++++++++++++++++++++++++++++++++++++++++++ src/common/conffile.h | 17 +++++ src/common/confline.c | 168 +++---------------------------------------------- src/common/confline.h | 20 ++++-- src/common/include.am | 2 + src/or/config.c | 1 + src/test/test_config.c | 3 +- 7 files changed, 209 insertions(+), 166 deletions(-) create mode 100644 src/common/conffile.c create mode 100644 src/common/conffile.h 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 result has values from + * %included files. opened_lst will have a list of opened files if + * provided. Return 0 on success, -1 on failure. Warn and ignore any + * misformatted lines. + * + * If extended 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 path to + * file_list. path can be a file or a directory. If it is a file, + * only that file will be added to file_list. 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 file_list. + * opened_files 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 path. + * Set config to the list and config_last to the last element of + * config. opened_lst 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 path in a config file. Set list to the + * list of configuration settings obtained and list_last to the last + * element of the same list. opened_lst 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 *lst. */ void @@ -86,11 +71,12 @@ config_line_find(const config_line_t *lines, * opened_lst will have a list of opened files if provided. * Returns the a pointer to the last element of the result in * last. */ -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 result has values from - * %included files. opened_lst will have a list of opened files if - * provided. Return 0 on success, -1 on failure. Warn and ignore any - * misformatted lines. - * - * If extended 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 path to - * file_list. path can be a file or a directory. If it is a file, - * only that file will be added to file_list. 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 file_list. - * opened_files 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 path. - * Set config to the list and config_last to the last element of - * config. opened_lst 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 path in a config file. Set list to the - * list of configuration settings obtained and list_last to the last - * element of the same list. opened_lst 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 #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 }; - -- cgit v1.2.3-54-g00ecf