summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKen Brown <kbrown@cornell.edu>2019-09-27 14:00:52 -0400
committerKen Brown <kbrown@cornell.edu>2019-10-07 16:09:41 -0400
commitc561a625af9bdbcc475214036ebbedbcae1cb702 (patch)
tree9f3e3ab5e56ae074d1d3cd133059ebb03fd66d1f
parente82a0c959a7dcff1560290ec696721f5660b4330 (diff)
downloadcygnal-c561a625af9bdbcc475214036ebbedbcae1cb702.tar.gz
cygnal-c561a625af9bdbcc475214036ebbedbcae1cb702.tar.bz2
cygnal-c561a625af9bdbcc475214036ebbedbcae1cb702.zip
Cygwin: mkdir and rmdir: treat drive names specially
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.
-rw-r--r--winsup/cygwin/dir.cc33
-rw-r--r--winsup/cygwin/release/3.1.04
2 files changed, 32 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 */;
diff --git a/winsup/cygwin/release/3.1.0 b/winsup/cygwin/release/3.1.0
index f3abff10f..3f2f3c86b 100644
--- a/winsup/cygwin/release/3.1.0
+++ b/winsup/cygwin/release/3.1.0
@@ -87,3 +87,7 @@ Bug Fixes
- Fix an assertion failure on an invalid path.
Addresses: https://cygwin.com/ml/cygwin/2019-09/msg00228.html
+
+- If the argument to mkdir(2) or rmdir(2) is 'x:\', don't strip the
+ trailing backslash.
+ Addresses: https://cygwin.com/ml/cygwin/2019-08/msg00334.html