diff options
author | Ismael Luceno <ismael@iodev.co.uk> | 2019-07-25 23:50:48 +0200 |
---|---|---|
committer | Rich Felker <dalias@aerifal.cx> | 2019-08-06 14:03:31 -0400 |
commit | 49eacf29d29fa704b2feda879978ae64a825358c (patch) | |
tree | 9197460fce02c8e15a59f65fa60ecd7098db2cb0 /src/regex | |
parent | f522de81ac88dddb58266c15bcfaa044c4065e19 (diff) | |
download | musl-49eacf29d29fa704b2feda879978ae64a825358c.tar.gz musl-49eacf29d29fa704b2feda879978ae64a825358c.tar.bz2 musl-49eacf29d29fa704b2feda879978ae64a825358c.tar.xz musl-49eacf29d29fa704b2feda879978ae64a825358c.zip |
glob: implement GLOB_TILDE and GLOB_TILDE_CHECK
Diffstat (limited to 'src/regex')
-rw-r--r-- | src/regex/glob.c | 42 |
1 files changed, 41 insertions, 1 deletions
diff --git a/src/regex/glob.c b/src/regex/glob.c index aa1c6a44..58248675 100644 --- a/src/regex/glob.c +++ b/src/regex/glob.c @@ -8,6 +8,8 @@ #include <stdlib.h> #include <errno.h> #include <stddef.h> +#include <unistd.h> +#include <pwd.h> struct match { @@ -182,6 +184,39 @@ static int sort(const void *a, const void *b) return strcmp(*(const char **)a, *(const char **)b); } +static int expand_tilde(char **pat, char *buf, size_t *pos) +{ + char *p = *pat + 1; + size_t i = 0; + + char delim, *name_end = __strchrnul(p, '/'); + if ((delim = *name_end)) *name_end++ = 0; + *pat = name_end; + + char *home = *p ? NULL : getenv("HOME"); + if (!home) { + struct passwd pw, *res; + switch (*p ? getpwnam_r(p, &pw, buf, PATH_MAX, &res) + : getpwuid_r(getuid(), &pw, buf, PATH_MAX, &res)) { + case ENOMEM: + return GLOB_NOSPACE; + case 0: + if (!res) + default: + return GLOB_NOMATCH; + } + home = pw.pw_dir; + } + while (i < PATH_MAX - 2 && *home) + buf[i++] = *home++; + if (*home) + return GLOB_NOMATCH; + if ((buf[i] = delim)) + buf[++i] = 0; + *pos = i; + return 0; +} + int glob(const char *restrict pat, int flags, int (*errfunc)(const char *path, int err), glob_t *restrict g) { struct match head = { .next = NULL }, *tail = &head; @@ -202,7 +237,12 @@ int glob(const char *restrict pat, int flags, int (*errfunc)(const char *path, i char *p = strdup(pat); if (!p) return GLOB_NOSPACE; buf[0] = 0; - error = do_glob(buf, 0, 0, p, flags, errfunc, &tail); + size_t pos = 0; + char *s = p; + if ((flags & (GLOB_TILDE | GLOB_TILDE_CHECK)) && *p == '~') + error = expand_tilde(&s, buf, &pos); + if (!error) + error = do_glob(buf, pos, 0, s, flags, errfunc, &tail); free(p); } |