Fix glob processing on BSD systems. #40318

On Linux systems, glob automatically ignores the errors ENOENT and
ENOTDIR because they are expected during glob expansion. But BSD
systems do not ignore these, resulting in glob failing when globs
expand to invalid paths. This is fixed by adding a custom error
handler that ignores only these two errors and removing the
GLOB_ERR flag as it makes glob fail even if the error handler
ignores the error and is unnecessary as the error handler will
make glob fail on all other errors anyway.
This commit is contained in:
Daniel Pinto 2021-03-25 01:23:04 +00:00
parent c359c3056b
commit 36768b5756
2 changed files with 22 additions and 2 deletions

4
changes/bug40318 Normal file
View File

@ -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.

View File

@ -571,6 +571,19 @@ wrap_closedir(void *arg)
{ {
closedir(arg); closedir(arg);
} }
/** Function passed to glob to handle processing errors. <b>epath</b> is the
* path that caused the error and <b>eerrno</b> 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) */ #endif /* defined(HAVE_GLOB) */
/** Return a new list containing the paths that match the pattern /** Return a new list containing the paths that match the pattern
@ -591,7 +604,7 @@ tor_glob(const char *pattern)
tor_free(pattern_normalized); tor_free(pattern_normalized);
#elif HAVE_GLOB /* !(defined(_WIN32)) */ #elif HAVE_GLOB /* !(defined(_WIN32)) */
glob_t matches; glob_t matches;
int flags = GLOB_ERR | GLOB_NOSORT; int flags = GLOB_NOSORT;
#ifdef GLOB_ALTDIRFUNC #ifdef GLOB_ALTDIRFUNC
/* use functions that call sandbox_intern_string */ /* use functions that call sandbox_intern_string */
flags |= GLOB_ALTDIRFUNC; flags |= GLOB_ALTDIRFUNC;
@ -604,7 +617,10 @@ tor_glob(const char *pattern)
matches.gl_stat = &prot_stat; matches.gl_stat = &prot_stat;
matches.gl_lstat = &prot_lstat; matches.gl_lstat = &prot_lstat;
#endif /* defined(GLOB_ALTDIRFUNC) */ #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) { if (ret == GLOB_NOMATCH) {
return smartlist_new(); return smartlist_new();
} else if (ret != 0) { } else if (ret != 0) {