Commit 0b633b1f authored by Jigsaw52's avatar Jigsaw52
Browse files

Improved documentation and comments #25140

parent ac2c4b1e
...@@ -206,9 +206,9 @@ such multiline entries, but they must start at the beginning of a line. ...@@ -206,9 +206,9 @@ such multiline entries, but they must start at the beginning of a line.
Configuration options can be imported from files or folders using the %include Configuration options can be imported from files or folders using the %include
option with the value being a path. This path can have wildcards. Wildcards are option with the value being a path. This path can have wildcards. Wildcards are
expanded first, using lexical order. Then, for each matching file or folder, the expanded first, then sorted using lexical order. Then, for each matching file or
following rules are followed: if the path is a file, the options from the folder, the following rules are followed: if the path is a file, the options from
file will be parsed as if they were written where the %include option is. If the file will be parsed as if they were written where the %include option is. If
the path is a folder, all files on that folder will be parsed following lexical the path is a folder, all files on that folder will be parsed following lexical
order. Files starting with a dot are ignored. Files in subfolders are ignored. order. Files starting with a dot are ignored. Files in subfolders are ignored.
The %include option can be used recursively. The %include option can be used recursively.
......
...@@ -44,13 +44,6 @@ ...@@ -44,13 +44,6 @@
#include <errno.h> #include <errno.h>
#include <string.h> #include <string.h>
#ifdef _WIN32
#define IS_GLOB_CHAR(s,i) (((s)[(i)]) == '*' || ((s)[(i)]) == '?')
#else
#define IS_GLOB_CHAR(s,i) ((((s)[(i)]) == '*' || ((s)[(i)]) == '?') &&\
((i) == 0 || (s)[(i)-1] != '\\')) /* check escape */
#endif
/** Removes enclosing quotes from <b>path</b> and unescapes quotes between the /** Removes enclosing quotes from <b>path</b> and unescapes quotes between the
* enclosing quotes. Backslashes are not unescaped. Return the unquoted * enclosing quotes. Backslashes are not unescaped. Return the unquoted
* <b>path</b> on success or 0 if <b>path</b> is not quoted correctly. */ * <b>path</b> on success or 0 if <b>path</b> is not quoted correctly. */
...@@ -321,8 +314,78 @@ make_path_absolute(const char *fname) ...@@ -321,8 +314,78 @@ make_path_absolute(const char *fname)
#endif /* defined(_WIN32) */ #endif /* defined(_WIN32) */
} }
/** Expands globs in <b>pattern</b> for the path fragment between /* The code below implements tor_glob and get_glob_opened_files. Because it is
* <b>prev_sep</b> and <b>next_sep</b>. Returns NULL on failure. */ * not easy to understand it by looking at individual functions, the big
* picture explanation here should be read first.
*
* Purpose of the functions:
* - tor_glob - recevies a pattern and returns all the paths that result from
* its glob expansion, globs can be present on all path components.
* - get_glob_opened_files - receives a pattern and returns all the paths that
* are opened during its expansion (the paths before any path fragment that
* contains a glob as they have to be opened to check for glob matches). This
* is used to get the paths that have to be added to the seccomp sandbox
* allowed list.
*
* Due to OS API differences explained below, the implementation of tor_glob is
* completly different for Windows and POSIX systems, so we ended up with three
* different implementations:
* - tor_glob for POSIX - as POSIX glob does everything we need, we simply call
* it and process the results. This is completly implemented in tor_glob.
* - tor_glob for WIN32 - because the WIN32 API only supports expanding globs
* in the last path fragment, we need to expand the globs in each path
* fragment manually and call recursively to get the same behaviour as POSIX
* glob. When there are no globs in pattern, we know we are on the last path
* fragment and collect the full path.
* - get_glob_opened_files - because the paths before any path fragment with a
* glob will be opened to check for matches, we need to collect them and we
* need to expand the globs in each path fragments and call recursively until
* we find no more globs.
*
* As seen from the description above, both tor_glob for WIN32 and
* get_glob_opened_files receive a pattern and return a list of paths and have
* to expand all path fragments that contain globs and call themselves
* recursively. The differences are:
* - get_glob_opened_files collects paths before path fragments with globs
* while tor_glob for WIN32 collects full paths resulting from the expansion
* of all globs.
* - get_glob_opened_files can call tor_glob to expand path fragments with
* globs while tor_glob for WIN32 cannot because it IS tor_glob. For tor_glob
* for WIN32, an auxiliary function has to be used for this purpose.
*
* To avoid code duplication, the logic of tor_glob for WIN32 and
* get_glob_opened_files is implemented in get_glob_paths. The differences are
* configured by the extra function parameters:
* - final - if true, returns a list of paths obtained from expanding pattern
* (implements tor_glob). Otherwise, returns the paths before path fragments
* with globs (implements get_glob_opened_files).
* - unglob - function used to expand a path fragment. The function signature
* is defined by the unglob_fn typedef. Two implementations are available:
* - unglob_win32 - uses tor_listdir and PathMatchSpec (for tor_glob WIN32)
* - unglob_opened_files - uses tor_glob (for get_glob_opened_files)
*/
/** Returns true if the character at position <b>pos</b> in <b>pattern</b> is
* considered a glob. Returns false otherwise. Takes escaping into account on
* systems where escaping globs is supported. */
static inline bool
is_glob_char(const char *pattern, int pos)
{
bool is_glob = pattern[pos] == '*' || pattern[pos] == '?';
#ifdef _WIN32
return is_glob;
#else /* !defined(_WIN32) */
bool is_escaped = pos > 0 && pattern[pos-1] == '\\';
return is_glob && !is_escaped;
#endif /* defined(_WIN32) */
}
/** Expands the first path fragment of <b>pattern</b> that contains globs. The
* path fragment is between <b>prev_sep</b> and <b>next_sep</b>. If the path
* fragment is the last fragment of <b>pattern</b>, <b>next_sep</b> will be the
* index of the last char. Returns a list of paths resulting from the glob
* expansion of the path fragment. Anything after <b>next_sep</b> is not
* included in the returned list. Returns NULL on failure. */
typedef struct smartlist_t * unglob_fn(const char *pattern, int prev_sep, typedef struct smartlist_t * unglob_fn(const char *pattern, int prev_sep,
int next_sep); int next_sep);
...@@ -350,7 +413,7 @@ add_non_glob_path(const char *path, struct smartlist_t *result) ...@@ -350,7 +413,7 @@ add_non_glob_path(const char *path, struct smartlist_t *result)
* expand each path fragment. If <b>final</b> is true, the paths are the result * expand each path fragment. If <b>final</b> is true, the paths are the result
* of the glob expansion of <b>pattern</b> (implements tor_glob). Otherwise, * of the glob expansion of <b>pattern</b> (implements tor_glob). Otherwise,
* the paths are the paths opened by glob while expanding <b>pattern</b> * the paths are the paths opened by glob while expanding <b>pattern</b>
* (implements get_glb_opened_files). Returns NULL on failure. */ * (implements get_glob_opened_files). Returns NULL on failure. */
static struct smartlist_t * static struct smartlist_t *
get_glob_paths(const char *pattern, unglob_fn unglob, bool final) get_glob_paths(const char *pattern, unglob_fn unglob, bool final)
{ {
...@@ -360,7 +423,7 @@ get_glob_paths(const char *pattern, unglob_fn unglob, bool final) ...@@ -360,7 +423,7 @@ get_glob_paths(const char *pattern, unglob_fn unglob, bool final)
// find first path fragment with globs // find first path fragment with globs
for (i = 0; pattern[i]; i++) { for (i = 0; pattern[i]; i++) {
is_glob = is_glob || IS_GLOB_CHAR(pattern, i); is_glob = is_glob || is_glob_char(pattern, i);
is_last = !pattern[i+1]; is_last = !pattern[i+1];
is_sep = pattern[i] == *PATH_SEPARATOR || pattern[i] == '/'; is_sep = pattern[i] == *PATH_SEPARATOR || pattern[i] == '/';
if (is_sep || is_last) { if (is_sep || is_last) {
...@@ -422,7 +485,8 @@ end: ...@@ -422,7 +485,8 @@ end:
#ifdef _WIN32 #ifdef _WIN32
/** Expands globs in <b>pattern</b> for the path fragment between /** Expands globs in <b>pattern</b> for the path fragment between
* <b>prev_sep</b> and <b>next_sep</b> using the WIN32 API. Returns NULL on * <b>prev_sep</b> and <b>next_sep</b> using the WIN32 API. Returns NULL on
* failure. Used by the WIN32 implementation of tor_glob. */ * failure. Used by the WIN32 implementation of tor_glob. Implements unglob_fn,
* see its description for more details. */
static struct smartlist_t * static struct smartlist_t *
unglob_win32(const char *pattern, int prev_sep, int next_sep) unglob_win32(const char *pattern, int prev_sep, int next_sep)
{ {
...@@ -450,10 +514,10 @@ unglob_win32(const char *pattern, int prev_sep, int next_sep) ...@@ -450,10 +514,10 @@ unglob_win32(const char *pattern, int prev_sep, int next_sep)
#ifdef UNICODE #ifdef UNICODE
mbstowcs(tpattern, path_curr_glob, MAX_PATH); mbstowcs(tpattern, path_curr_glob, MAX_PATH);
mbstowcs(tfile, full_path, MAX_PATH); mbstowcs(tfile, full_path, MAX_PATH);
#else #else /* !defined(UNICODE) */
strlcpy(tpattern, path_curr_glob, MAX_PATH); strlcpy(tpattern, path_curr_glob, MAX_PATH);
strlcpy(tfile, full_path, MAX_PATH); strlcpy(tfile, full_path, MAX_PATH);
#endif #endif /* defined(UNICODE) */
if (PathMatchSpec(tfile, tpattern)) { if (PathMatchSpec(tfile, tpattern)) {
smartlist_add(result, full_path); smartlist_add(result, full_path);
} else { } else {
...@@ -492,7 +556,8 @@ prot_lstat(const char *pathname, struct stat *buf) ...@@ -492,7 +556,8 @@ prot_lstat(const char *pathname, struct stat *buf)
#endif /* defined(_WIN32) */ #endif /* defined(_WIN32) */
/** Return a new list containing the paths that match the pattern /** Return a new list containing the paths that match the pattern
* <b>pattern</b>. Return NULL on error. * <b>pattern</b>. Return NULL on error. On POSIX systems, errno is set by the
* glob function.
*/ */
struct smartlist_t * struct smartlist_t *
tor_glob(const char *pattern) tor_glob(const char *pattern)
...@@ -548,7 +613,7 @@ has_glob(const char *s) ...@@ -548,7 +613,7 @@ has_glob(const char *s)
{ {
int i; int i;
for (i = 0; s[i]; i++) { for (i = 0; s[i]; i++) {
if (IS_GLOB_CHAR(s, i)) { if (is_glob_char(s, i)) {
return true; return true;
} }
} }
...@@ -557,7 +622,8 @@ has_glob(const char *s) ...@@ -557,7 +622,8 @@ has_glob(const char *s)
/** Expands globs in <b>pattern</b> for the path fragment between /** Expands globs in <b>pattern</b> for the path fragment between
* <b>prev_sep</b> and <b>next_sep</b> using tor_glob. Returns NULL on * <b>prev_sep</b> and <b>next_sep</b> using tor_glob. Returns NULL on
* failure. Used by get_glob_opened_files. */ * failure. Used by get_glob_opened_files. Implements unglob_fn, see its
* description for more details. */
static struct smartlist_t * static struct smartlist_t *
unglob_opened_files(const char *pattern, int prev_sep, int next_sep) unglob_opened_files(const char *pattern, int prev_sep, int next_sep)
{ {
...@@ -565,8 +631,8 @@ unglob_opened_files(const char *pattern, int prev_sep, int next_sep) ...@@ -565,8 +631,8 @@ unglob_opened_files(const char *pattern, int prev_sep, int next_sep)
smartlist_t *result = smartlist_new(); smartlist_t *result = smartlist_new();
// if the following fragments have no globs, we're done // if the following fragments have no globs, we're done
if (has_glob(&pattern[next_sep+1])) { if (has_glob(&pattern[next_sep+1])) {
// if there is a glob after next_sep, we know it is a separator and not the // if there is a glob after next_sep, we know next_sep is a separator and
// last char and glob_path will have the path without the separator // not the last char and glob_path will have the path without the separator
char *glob_path = tor_strndup(pattern, next_sep); char *glob_path = tor_strndup(pattern, next_sep);
smartlist_t *child_paths = tor_glob(glob_path); smartlist_t *child_paths = tor_glob(glob_path);
tor_free(glob_path); tor_free(glob_path);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment