diff --git a/changes/bug40318 b/changes/bug40318 new file mode 100644 index 0000000000..cc02f08ca0 --- /dev/null +++ b/changes/bug40318 @@ -0,0 +1,4 @@ + o Minor bugfixes (configuration tests bsd): + - Fix glob processing errors when globs expand to invalid paths on + BSD systems. Fixes bug 40318; bugfix on 0.4.5.1-alpha. Patch by + Daniel Pinto. diff --git a/src/lib/fs/path.c b/src/lib/fs/path.c index 48d610ab7b..81eb3aa661 100644 --- a/src/lib/fs/path.c +++ b/src/lib/fs/path.c @@ -571,7 +571,20 @@ wrap_closedir(void *arg) { closedir(arg); } -#endif /* defined(_WIN32) || ... */ + +/** Function passed to glob to handle processing errors. epath is the + * path that caused the error and eerrno is the errno set by the + * function that failed. We want to ignore ENOENT and ENOTDIR because, in BSD + * systems, these are not ignored automatically, which makes glob fail when + * globs expand to non-existing paths and GLOB_ERR is set. + */ +static int +glob_errfunc(const char *epath, int eerrno) +{ + (void)epath; + return eerrno == ENOENT || eerrno == ENOTDIR ? 0 : -1; +} +#endif /* defined(HAVE_GLOB) */ /** Return a new list containing the paths that match the pattern * pattern. Return NULL on error. On POSIX systems, errno is set by the @@ -591,7 +604,7 @@ tor_glob(const char *pattern) tor_free(pattern_normalized); #elif HAVE_GLOB /* !(defined(_WIN32)) */ glob_t matches; - int flags = GLOB_ERR | GLOB_NOSORT; + int flags = GLOB_NOSORT; #ifdef GLOB_ALTDIRFUNC /* use functions that call sandbox_intern_string */ flags |= GLOB_ALTDIRFUNC; @@ -604,7 +617,10 @@ tor_glob(const char *pattern) matches.gl_stat = &prot_stat; matches.gl_lstat = &prot_lstat; #endif /* defined(GLOB_ALTDIRFUNC) */ - int ret = glob(pattern, flags, NULL, &matches); + // use custom error handler to workaround BSD quirks and do not set GLOB_ERR + // because it would make glob fail on error even if the error handler ignores + // the error + int ret = glob(pattern, flags, glob_errfunc, &matches); if (ret == GLOB_NOMATCH) { return smartlist_new(); } else if (ret != 0) {