diff options
author | Daniel Shahaf <danielsh@apache.org> | 2020-01-13 00:27:24 +0000 |
---|---|---|
committer | dana <dana@dana.is> | 2020-01-15 19:20:33 -0600 |
commit | edc04bd94656a152e17f06188bcef172d62a3ad4 (patch) | |
tree | 3f8eb8f9889fe502bd1134ffb1c3a9042b94e0ad | |
parent | e899c21863a69226b4e650940c327a3b460023c0 (diff) | |
download | zsh-edc04bd94656a152e17f06188bcef172d62a3ad4.tar.gz zsh-edc04bd94656a152e17f06188bcef172d62a3ad4.tar.xz zsh-edc04bd94656a152e17f06188bcef172d62a3ad4.zip |
45291: A glob with a trailing slash will now match unreadable/unexecutable directories.
-rw-r--r-- | ChangeLog | 5 | ||||
-rw-r--r-- | Src/glob.c | 49 | ||||
-rw-r--r-- | Test/D02glob.ztst | 2 |
3 files changed, 45 insertions, 11 deletions
diff --git a/ChangeLog b/ChangeLog index 44b45ce07..d6ad77e3b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2020-01-15 dana <dana@dana.is> + + * Daniel: 45291: Src/glob.c, Test/D02glob.ztst: A glob with a + trailing slash will now match unreadable/unexecutable directories. + 2020-01-15 Daniel Shahaf <danielsh@apache.org> * 45288: Completion/Unix/Command/_git: Complete bisect/new as diff --git a/Src/glob.c b/Src/glob.c index f67a376b9..bee890caf 100644 --- a/Src/glob.c +++ b/Src/glob.c @@ -279,11 +279,11 @@ addpath(char *s, int l) * foo/ can be used to reference a non-directory foo. Returns nonzero if * * the file does not exists. */ -/**/ static int statfullpath(const char *s, struct stat *st, int l) { char buf[PATH_MAX+1]; + int check_for_being_a_directory = 0; DPUTS(strlen(s) + !*s + pathpos - pathbufcwd >= PATH_MAX, "BUG: statfullpath(): pathname too long"); @@ -294,16 +294,44 @@ statfullpath(const char *s, struct stat *st, int l) * Don't add the '.' if the path so far is empty, since * then we get bogus empty strings inserted as files. */ - buf[pathpos - pathbufcwd] = '.'; - buf[pathpos - pathbufcwd + 1] = '\0'; - l = 0; + if (st) { + buf[pathpos - pathbufcwd] = '.'; + buf[pathpos - pathbufcwd + 1] = '\0'; + l = 0; + } + else { + check_for_being_a_directory = 1; + } } unmetafy(buf, NULL); - if (!st) { + if (st) { + return l ? lstat(buf, st) : stat(buf, st); + } + else if (check_for_being_a_directory) { + struct stat tmp; + if (stat(buf, &tmp)) + return -1; + + return S_ISDIR(tmp.st_mode) ? 0 : -1; + } + else { char lbuf[1]; - return access(buf, F_OK) && (!l || readlink(buf, lbuf, 1) < 0); + + /* If it exists, signal success. */ + if (access(buf, F_OK) == 0) + return 0; + + /* Would a dangling symlink be good enough? */ + if (l == 0) + return -1; + + /* Is it a dangling symlink? */ + if (readlink(buf, lbuf, 1) >= 0) + return 0; + + /* Guess it doesn't exist, then. */ + return -1; } - return l ? lstat(buf, st) : stat(buf, st); } /* This may be set by qualifier functions to an array of strings to insert @@ -327,11 +355,13 @@ insert(char *s, int checked) if (gf_listtypes || gf_markdirs) { /* Add the type marker to the end of the filename */ mode_t mode; - checked = statted = 1; if (statfullpath(s, &buf, 1)) { unqueue_signals(); return; } + else { + checked = statted = 1; + } mode = buf.st_mode; if (gf_follow) { if (!S_ISLNK(mode) || statfullpath(s, &buf2, 0)) @@ -387,11 +417,10 @@ insert(char *s, int checked) qn = qn->next; } } else if (!checked) { - if (statfullpath(s, &buf, 1)) { + if (statfullpath(s, NULL, 1)) { unqueue_signals(); return; } - statted = 1; news = dyncat(pathbuf, news); } else news = dyncat(pathbuf, news); diff --git a/Test/D02glob.ztst b/Test/D02glob.ztst index 3d7df94c9..b8946c5b1 100644 --- a/Test/D02glob.ztst +++ b/Test/D02glob.ztst @@ -734,7 +734,7 @@ mkdir -m 444 glob.tmp/secret-d444 for 1 in 000 111 444 ; do ln -s secret-d$1 glob.tmp/secret-s$1; done print -rC 2 -- glob.tmp/secret-*/ glob.tmp/secret-*(-/) --f:unreadable directories can be globbed (users/24619, users/24626) +0:unreadable directories can be globbed (users/24619, users/24626) >glob.tmp/secret-d000/ glob.tmp/secret-d000 >glob.tmp/secret-d111/ glob.tmp/secret-d111 >glob.tmp/secret-d444/ glob.tmp/secret-d444 |