From baa57d2cf9fda82deb2a86960ddcb2dcab6a3917 Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Sat, 30 Sep 2017 10:56:39 +0300 Subject: [PATCH] Fix checking existence of directories on MS-Windows * remake.c (name_mtime) [WINDOWS32]: Emulate Posix behavior of 'stat' with the likes of "foo/" and "foo/.". --- remake.c | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/remake.c b/remake.c index 037ee738..b4bf1cba 100644 --- a/remake.c +++ b/remake.c @@ -1469,7 +1469,45 @@ name_mtime (const char *name) struct stat st; int e; +#if defined(WINDOWS32) + { + char tem[MAXPATHLEN], *tstart, *tend; + const char *p = name + strlen (name); + + /* Remove any trailing slashes and "."/"..". MS-Windows stat + fails on valid directories if NAME ends in a slash, and we need + to emulate the Posix behavior where stat on "foo/" or "foo/." + succeeds ONLY if "foo" is a directory. */ + if (p > name) + { + memcpy (tem, name, p - name + 1); + tstart = tem; + if (tstart[1] == ':') + tstart += 2; + tend = tem + (p - name - 1); + if (*tend == '.' && tend > tstart) + tend--; + if (*tend == '.' && tend > tstart) + tend--; + for ( ; tend > tstart && (*tend == '/' || *tend == '\\'); tend--) + *tend = '\0'; + } + else + { + tem[0] = '\0'; + tend = &tem[0]; + } + + e = stat (tem, &st); + if (e == 0 && !_S_ISDIR (st.st_mode) && tend < tem + (p - name - 1)) + { + errno = ENOTDIR; + e = -1; + } + } +#else EINTRLOOP (e, stat (name, &st)); +#endif if (e == 0) mtime = FILE_TIMESTAMP_STAT_MODTIME (name, st); else if (errno == ENOENT || errno == ENOTDIR) -- 2.47.3