Line data Source code
1 : /* SPDX-License-Identifier: LGPL-2.1+ */ 2 : 3 : #include <dirent.h> 4 : #include <errno.h> 5 : #include <glob.h> 6 : #include <sys/types.h> 7 : #include <sys/stat.h> 8 : #include <unistd.h> 9 : 10 : #include "dirent-util.h" 11 : #include "errno-util.h" 12 : #include "glob-util.h" 13 : #include "macro.h" 14 : #include "path-util.h" 15 : #include "strv.h" 16 : 17 11 : static void closedir_wrapper(void* v) { 18 11 : (void) closedir(v); 19 11 : } 20 : 21 27 : int safe_glob(const char *path, int flags, glob_t *pglob) { 22 : int k; 23 : 24 : /* We want to set GLOB_ALTDIRFUNC ourselves, don't allow it to be set. */ 25 27 : assert(!(flags & GLOB_ALTDIRFUNC)); 26 : 27 27 : if (!pglob->gl_closedir) 28 24 : pglob->gl_closedir = closedir_wrapper; 29 27 : if (!pglob->gl_readdir) 30 24 : pglob->gl_readdir = (struct dirent *(*)(void *)) readdir_no_dot; 31 27 : if (!pglob->gl_opendir) 32 24 : pglob->gl_opendir = (void *(*)(const char *)) opendir; 33 27 : if (!pglob->gl_lstat) 34 24 : pglob->gl_lstat = lstat; 35 27 : if (!pglob->gl_stat) 36 24 : pglob->gl_stat = stat; 37 : 38 27 : errno = 0; 39 27 : k = glob(path, flags | GLOB_ALTDIRFUNC, NULL, pglob); 40 27 : if (k == GLOB_NOMATCH) 41 22 : return -ENOENT; 42 5 : if (k == GLOB_NOSPACE) 43 0 : return -ENOMEM; 44 5 : if (k != 0) 45 0 : return errno_or_else(EIO); 46 5 : if (strv_isempty(pglob->gl_pathv)) 47 0 : return -ENOENT; 48 : 49 5 : return 0; 50 : } 51 : 52 7 : int glob_exists(const char *path) { 53 7 : _cleanup_globfree_ glob_t g = {}; 54 : int k; 55 : 56 7 : assert(path); 57 : 58 7 : k = safe_glob(path, GLOB_NOSORT|GLOB_BRACE, &g); 59 7 : if (k == -ENOENT) 60 3 : return false; 61 4 : if (k < 0) 62 0 : return k; 63 4 : return true; 64 : } 65 : 66 16 : int glob_extend(char ***strv, const char *path) { 67 16 : _cleanup_globfree_ glob_t g = {}; 68 : int k; 69 : 70 16 : k = safe_glob(path, GLOB_NOSORT|GLOB_BRACE, &g); 71 16 : if (k < 0) 72 16 : return k; 73 : 74 0 : return strv_extend_strv(strv, g.gl_pathv, false); 75 : }