]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/basic/glob-util.c
tree-wide: make new/new0/malloc_multiply/reallocarray safe for size 0
[thirdparty/systemd.git] / src / basic / glob-util.c
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
8 #include "dirent-util.h"
9 #include "glob-util.h"
10 #include "macro.h"
11 #include "path-util.h"
12 #include "strv.h"
13
14 static void closedir_wrapper(void* v) {
15 (void) closedir(v);
16 }
17
18 int safe_glob(const char *path, int flags, glob_t *pglob) {
19 int k;
20
21 /* We want to set GLOB_ALTDIRFUNC ourselves, don't allow it to be set. */
22 assert(!(flags & GLOB_ALTDIRFUNC));
23
24 if (!pglob->gl_closedir)
25 pglob->gl_closedir = closedir_wrapper;
26 if (!pglob->gl_readdir)
27 pglob->gl_readdir = (struct dirent *(*)(void *)) readdir_no_dot;
28 if (!pglob->gl_opendir)
29 pglob->gl_opendir = (void *(*)(const char *)) opendir;
30 if (!pglob->gl_lstat)
31 pglob->gl_lstat = lstat;
32 if (!pglob->gl_stat)
33 pglob->gl_stat = stat;
34
35 errno = 0;
36 k = glob(path, flags | GLOB_ALTDIRFUNC, NULL, pglob);
37
38 if (k == GLOB_NOMATCH)
39 return -ENOENT;
40 if (k == GLOB_NOSPACE)
41 return -ENOMEM;
42 if (k != 0)
43 return errno > 0 ? -errno : -EIO;
44 if (strv_isempty(pglob->gl_pathv))
45 return -ENOENT;
46
47 return 0;
48 }
49
50 int glob_exists(const char *path) {
51 _cleanup_globfree_ glob_t g = {};
52 int k;
53
54 assert(path);
55
56 k = safe_glob(path, GLOB_NOSORT|GLOB_BRACE, &g);
57 if (k == -ENOENT)
58 return false;
59 if (k < 0)
60 return k;
61 return true;
62 }
63
64 int glob_extend(char ***strv, const char *path) {
65 _cleanup_globfree_ glob_t g = {};
66 int k;
67
68 k = safe_glob(path, GLOB_NOSORT|GLOB_BRACE, &g);
69 if (k < 0)
70 return k;
71
72 return strv_extend_strv(strv, g.gl_pathv, false);
73 }