diff options
author | Daniel Pinto <danielpinto52@gmail.com> | 2020-06-03 22:09:42 +0100 |
---|---|---|
committer | Daniel Pinto <danielpinto52@gmail.com> | 2020-07-15 22:01:08 +0100 |
commit | 34fa2c4d0d8117b75c5c52a7c825486eb0284ae0 (patch) | |
tree | 572264180e98fe572d16a42d44f3b60fd4e9f52a /src/lib/fs/conffile.c | |
parent | a7226ca06e20356abb057c29416a9ad969c8d29d (diff) | |
download | tor-34fa2c4d0d8117b75c5c52a7c825486eb0284ae0.tar.gz tor-34fa2c4d0d8117b75c5c52a7c825486eb0284ae0.zip |
Add support for patterns on %include #25140
Also adds generic tor_glob function to expand globs.
Diffstat (limited to 'src/lib/fs/conffile.c')
-rw-r--r-- | src/lib/fs/conffile.c | 141 |
1 files changed, 95 insertions, 46 deletions
diff --git a/src/lib/fs/conffile.c b/src/lib/fs/conffile.c index 9583093c12..f1f6d8ae5f 100644 --- a/src/lib/fs/conffile.c +++ b/src/lib/fs/conffile.c @@ -21,6 +21,8 @@ #include "lib/malloc/malloc.h" #include "lib/string/printf.h" +#include <stdbool.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, @@ -50,62 +52,109 @@ config_get_lines_include(const char *string, config_line_t **result, 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. - */ +/** Returns a list of paths obtained when expading globs in <b>pattern</b>. If + * <b>pattern</b> has no globs, returns a list with <b>pattern</b> if it is an + * existing path or NULL otherwise. If <b>opened_files</b> is provided, adds + * paths opened by glob to it. Returns NULL on failure. */ static smartlist_t * -config_get_file_list(const char *path, smartlist_t *opened_files) +expand_glob(const char *pattern, smartlist_t *opened_files) { - smartlist_t *file_list = smartlist_new(); + smartlist_t *matches = tor_glob(pattern); + if (!matches) { + return NULL; + } - if (opened_files) { - smartlist_add_strdup(opened_files, path); + // if it is not a glob, return error when the path is missing + if (!has_glob(pattern) && smartlist_len(matches) == 0) { + smartlist_free(matches); + return NULL; } - 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); + if (opened_files) { + smartlist_t *glob_opened = get_glob_opened_files(pattern); + if (!glob_opened) { + SMARTLIST_FOREACH(matches, char *, f, tor_free(f)); + smartlist_free(matches); return NULL; } - smartlist_sort_strings(all_files); - SMARTLIST_FOREACH_BEGIN(all_files, char *, f) { - if (f[0] == '.') { - tor_free(f); - continue; - } + smartlist_add_all(opened_files, glob_opened); + smartlist_free(glob_opened); + } + smartlist_sort_strings(matches); + return matches; +} + +/** Returns a list of configuration files present on paths that match + * <b>pattern</b>. The pattern is expanded and then all the paths are + * processed. A path can be a file or a directory. If it is a file, that file + * will be added to the list to be returned. 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 the list to be returned. + * <b>opened_files</b> will have a list of files opened by this function + * if provided. Return NULL on failure. Ignores empty files. + */ +static smartlist_t * +config_get_file_list(const char *pattern, smartlist_t *opened_files) +{ + smartlist_t *glob_matches = expand_glob(pattern, opened_files); + if (!glob_matches) { + return NULL; + } - char *fullname; - tor_asprintf(&fullname, "%s"PATH_SEPARATOR"%s", path, f); - tor_free(f); + bool error_found = false; + smartlist_t *file_list = smartlist_new(); + SMARTLIST_FOREACH_BEGIN(glob_matches, char *, path) { + if (opened_files) { + smartlist_add_strdup(opened_files, path); + } - if (opened_files) { - smartlist_add_strdup(opened_files, fullname); + file_status_t file_type = file_status(path); + if (file_type == FN_FILE) { + smartlist_add_strdup(file_list, path); + } else if (file_type == FN_DIR) { + smartlist_t *all_files = tor_listdir(path); + if (!all_files) { + error_found = true; + break; } - - if (file_status(fullname) != FN_FILE) { - tor_free(fullname); + smartlist_sort_strings(all_files); + SMARTLIST_FOREACH_BEGIN(all_files, char *, f) { + if (f[0] == '.') { + continue; + } + + char *fullname; + tor_asprintf(&fullname, "%s"PATH_SEPARATOR"%s", path, 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_FOREACH(all_files, char *, f, tor_free(f)); + smartlist_free(all_files); + } else if (file_type == FN_EMPTY) { 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 { + } else { + error_found = true; + break; + } + } SMARTLIST_FOREACH_END(path); + SMARTLIST_FOREACH(glob_matches, char *, f, tor_free(f)); + smartlist_free(glob_matches); + + if (error_found) { + SMARTLIST_FOREACH(file_list, char *, f, tor_free(f)); smartlist_free(file_list); - return NULL; + file_list = NULL; } + + return file_list; } /** Creates a list of config lines present on included <b>path</b>. @@ -133,19 +182,19 @@ config_get_included_config(const char *path, int recursion_level, int extended, return 0; } -/** Process an %include <b>path</b> in a config file. Set <b>list</b> to the +/** Process an %include <b>pattern</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_process_include(const char *pattern, 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); + smartlist_t *config_files = config_get_file_list(pattern, opened_lst); if (!config_files) { return -1; } |