From 5667376edc9cc68c1ed40f985c6d2174dfaeb64c Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Sun, 28 Apr 2013 20:53:36 +0300 Subject: Fix Savannah bug #37065 with $(wildcard foo/*/.) returning non-directories. dir.c (local_stat) [WINDOWS32]: Use the wrapper on MS-Windows. If the argument ends in "dir/.", make sure the parent dir exists and is indeed a directory. Fixes Savannah bug #37065. --- dir.c | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) (limited to 'dir.c') diff --git a/dir.c b/dir.c index 59b2a8c..dc0ef76 100644 --- a/dir.c +++ b/dir.c @@ -1185,8 +1185,11 @@ ansi_free (void *p) /* On 64 bit ReliantUNIX (5.44 and above) in LFS mode, stat() is actually a * macro for stat64(). If stat is a macro, make a local wrapper function to * invoke it. + * + * On MS-Windows, stat() "succeeds" for foo/bar/. where foo/bar is a + * regular file; fix that here. */ -#ifndef stat +#if !defined(stat) && !defined(WINDOWS32) # ifndef VMS int stat (const char *path, struct stat *sbuf); # endif @@ -1196,6 +1199,23 @@ static int local_stat (const char *path, struct stat *buf) { int e; +#ifdef WINDOWS32 + size_t plen = strlen (path); + + /* Make sure the parent of "." exists and is a directory, not a + file. This is because 'stat' on Windows normalizes the argument + foo/. => foo without checking first that foo is a directory. */ + if (plen > 1 && path[plen - 1] == '.' + && (path[plen - 2] == '/' || path[plen - 2] == '\\')) + { + char parent[MAXPATHLEN]; + + strncpy (parent, path, plen - 2); + parent[plen - 2] = '\0'; + if (stat (parent, buf) < 0 || !_S_ISDIR (buf->st_mode)) + return -1; + } +#endif EINTRLOOP (e, stat (path, buf)); return e; -- cgit v1.2.3