This is the mail archive of the
cygwin-patches
mailing list for the Cygwin project.
[PATCH] Cygwin: mkdir and rmdir: treat drive names specially
- From: Ken Brown <kbrown at cornell dot edu>
- To: "cygwin-patches at cygwin dot com" <cygwin-patches at cygwin dot com>
- Cc: "eblake at redhat dot com" <eblake at redhat dot com>
- Date: Fri, 27 Sep 2019 18:44:17 +0000
- Subject: [PATCH] Cygwin: mkdir and rmdir: treat drive names specially
- Arc-authentication-results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=cornell.edu; dmarc=pass action=none header.from=cornell.edu; dkim=pass header.d=cornell.edu; arc=none
- Arc-message-signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=qGRsYCO7Jd+YUxBVJJEFsn6fJBAxKqiNec5jl0HI62k=; b=eZ24niln957Mee2eQQmBOFtLWOFHhJ2FULpB7/8JY2gp5S/FqLScFn5xZKfQ/t5MFVfAj+si5rO3egJXhoS2IkVfD2V8Lh5GM/91xhz6haMvQJp0bEGcyVmoLaKCLsYE5t51CxFnUFGbkHdfbf2uhPwJsuO0OQHNRI7cMMpYfhzxQ0qtK4HrcM8FT1Aq4M19sOYxfK5MJY6+fC9zY+g8pJrlXO1rTEuiapCTFSqc2Bv+PgCnkVxG1NTswlv9CzFEnmnGOvxS7ixPGPRa8tFk/pFgSdNHrPFigDIuHmmYKgpaeyzpkl2DT4xoNG44TR6bbopL0SvpkLKZCHNC2hlyFg==
- Arc-seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=Pry+my9rR9eosiq5rCFHgDN8n+xxoxLcTaAeLhPg+EJwTwh/DrmrJ+e07mo/ftZ8phvjkzoH3R/+L+N1neOsYtSoIghfRd6otdLcXmGrFWOYyYp8t/XS+TZCMeHelmBcGs9iiTKc//AxCWntwQGI70jLkzR4ZecDzsTPkmZ3nrzX5/56oGYBdngzd/6RRaNAcmR0wlMqSBAcPGudEoFwjS2PCQLaNe793Qzy7IkS42c7SWobhCdQnU8o3xCKU/JZuEDvD2yC9a5EfZetenL+qnLBtOuId1dHtfsGRTDBhGmiLQ1ul6R/CjJShZeLVI4CrqXwSB8XnuX3dY8DVIxbng==
If the directory name has the form 'x:' followed by one or more
slashes or backslashes, and if there's at least one backslash, assume
that the user is referring to 'x:\', the root directory of drive x,
and don't strip the backslash.
Previously all trailing slashes and backslashes were stripped, and the
name was treated as a relative file name containing a literal colon.
Addresses https://cygwin.com/ml/cygwin/2019-08/msg00334.html.
---
winsup/cygwin/dir.cc | 33 ++++++++++++++++++++++++++++-----
1 file changed, 28 insertions(+), 5 deletions(-)
diff --git a/winsup/cygwin/dir.cc b/winsup/cygwin/dir.cc
index 29a9dfa83..3429fe022 100644
--- a/winsup/cygwin/dir.cc
+++ b/winsup/cygwin/dir.cc
@@ -313,15 +313,27 @@ mkdir (const char *dir, mode_t mode)
/* Following Linux, and intentionally ignoring POSIX, do not
resolve the last component of DIR if it is a symlink, even if
DIR has a trailing slash. Achieve this by stripping trailing
- slashes or backslashes. */
+ slashes or backslashes.
+
+ Exception: If DIR == 'x:' followed by one or more slashes or
+ backslashes, and if there's at least one backslash, assume
+ that the user is referring to the root directory of drive x.
+ Retain one backslash in this case. */
if (isdirsep (dir[strlen (dir) - 1]))
{
/* This converts // to /, but since both give EEXIST, we're okay. */
char *buf;
char *p = stpcpy (buf = tp.c_get (), dir) - 1;
+ bool msdos = false;
dir = buf;
while (p > dir && isdirsep (*p))
- *p-- = '\0';
+ {
+ if (*p == '\\')
+ msdos = true;
+ *p-- = '\0';
+ }
+ if (msdos && p == dir + 1 && isdrive (dir))
+ p[1] = '\\';
}
if (!(fh = build_fh_name (dir, PC_SYM_NOFOLLOW)))
__leave; /* errno already set */;
@@ -360,20 +372,31 @@ rmdir (const char *dir)
set_errno (ENOENT);
__leave;
}
-
/* Following Linux, and intentionally ignoring POSIX, do not
resolve the last component of DIR if it is a symlink, even if
DIR has a trailing slash. Achieve this by stripping trailing
- slashes or backslashes. */
+ slashes or backslashes.
+
+ Exception: If DIR == 'x:' followed by one or more slashes or
+ backslashes, and if there's at least one backslash, assume
+ that the user is referring to the root directory of drive x.
+ Retain one backslash in this case. */
if (isdirsep (dir[strlen (dir) - 1]))
{
/* This converts // to /, but since both give ENOTEMPTY,
we're okay. */
char *buf;
char *p = stpcpy (buf = tp.c_get (), dir) - 1;
+ bool msdos = false;
dir = buf;
while (p > dir && isdirsep (*p))
- *p-- = '\0';
+ {
+ if (*p == '\\')
+ msdos = true;
+ *p-- = '\0';
+ }
+ if (msdos && p == dir + 1 && isdrive (dir))
+ p[1] = '\\';
}
if (!(fh = build_fh_name (dir, PC_SYM_NOFOLLOW)))
__leave; /* errno already set */;
--
2.21.0