From: Jan Dubois Date: Wed, 15 Feb 2006 17:19:29 +0000 (-0800) Subject: stat() on Windows doesn't handle trailing slashes/backslashes correctly X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=44221b20e58d7d2e060f57de5d83fc6fb49337bd;p=p5sagit%2Fp5-mst-13.2.git stat() on Windows doesn't handle trailing slashes/backslashes correctly From: "Jan Dubois" Message-ID: <017901c63297$08e1e3f0$2217a8c0@candy> p4raw-id: //depot/perl@27200 --- diff --git a/win32/win32.c b/win32/win32.c index 347bff3..41b7045 100644 --- a/win32/win32.c +++ b/win32/win32.c @@ -1169,21 +1169,31 @@ win32_stat(const char *path, Stat_t *sbuf) int res; HANDLE handle; int nlink = 1; + BOOL expect_dir = FALSE; if (l > 1) { switch(path[l - 1]) { /* FindFirstFile() and stat() are buggy with a trailing - * backslash, so change it to a forward slash :-( */ + * slashes, except for the root directory of a drive */ case '\\': - if (l >= sizeof(buffer)) { + case '/': + if (l > sizeof(buffer)) { errno = ENAMETOOLONG; return -1; } - strncpy(buffer, path, l-1); - buffer[l - 1] = '/'; - buffer[l] = '\0'; - path = buffer; + --l; + strncpy(buffer, path, l); + /* remove additional trailing slashes */ + while (l > 1 && (buffer[l-1] == '/' || buffer[l-1] == '\\')) + --l; + /* add back slash if we otherwise end up with just a drive letter */ + if (l == 2 && isALPHA(buffer[0]) && buffer[1] == ':') + buffer[l++] = '\\'; + buffer[l] = '\0'; + path = buffer; + expect_dir = TRUE; break; + /* FindFirstFile() is buggy with "x:", so add a dot :-( */ case ':': if (l == 2 && isALPHA(path[0])) { @@ -1245,6 +1255,10 @@ win32_stat(const char *path, Stat_t *sbuf) return -1; } } + if (expect_dir && !S_ISDIR(sbuf->st_mode)) { + errno = ENOTDIR; + return -1; + } #ifdef __BORLANDC__ if (S_ISDIR(sbuf->st_mode)) sbuf->st_mode |= S_IWRITE | S_IEXEC;