summaryrefslogtreecommitdiff
path: root/Src/glob.c
diff options
context:
space:
mode:
authorDaniel Shahaf <danielsh@apache.org>2020-03-07 21:50:46 +0000
committerDaniel Shahaf <danielsh@apache.org>2020-03-07 21:50:46 +0000
commitb5f05b29ba3d8884cdcb344fd6e5f62aeaa9a3fc (patch)
tree7142dec586d8f1fb3b9333ff50d6e1083a7b7460 /Src/glob.c
parentdd50f125b5eb65896642d2ff664adefd33f1004c (diff)
parent4ce0cff5e91608598adf4a72318fc868681e398d (diff)
downloadzsh-b5f05b29ba3d8884cdcb344fd6e5f62aeaa9a3fc.tar.gz
zsh-b5f05b29ba3d8884cdcb344fd6e5f62aeaa9a3fc.zip
Merge remote-tracking branch 'origin/5.9'
* origin/5.9: unposted: Move a new incompatibility notice. unposted: Fix trailing whitespace in test expectations. 45342: Add tests for interaction between autoloadable parameters and module loading. 45313: _git: Support completion from outside of a worktree when --git-dir/--work-tree are specified on the command line 45304: Do execute the always block even when the try/always block itself is the last command. 45292: D02glob: Add regression test for macOS stat(2) misbehaviour 45291: A glob with a trailing slash will now match unreadable/unexecutable directories. 45288: _git: Complete bisect/new as well as bisect/bad. 45246: Make --disable-multibyte warn, since the test suite fails in that configuration. 45213: Make --enable-gdbm default to false, rather than default to true with an unavoidable warning. unposted (follow-up to 45131): Extra testing by Mikael 45137: zformat: Allow the specifying minimum width and a dot with an empty maximum width. 45138: Add zformat unit tests. 45131: Make a function that redefines itself preserve its tracedness.
Diffstat (limited to 'Src/glob.c')
-rw-r--r--Src/glob.c49
1 files changed, 39 insertions, 10 deletions
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);