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.
This commit is contained in:
parent
faf0c0f8b0
commit
1e8370c1c1
|
@ -313,15 +313,27 @@ mkdir (const char *dir, mode_t mode)
|
||||||
/* Following Linux, and intentionally ignoring POSIX, do not
|
/* Following Linux, and intentionally ignoring POSIX, do not
|
||||||
resolve the last component of DIR if it is a symlink, even if
|
resolve the last component of DIR if it is a symlink, even if
|
||||||
DIR has a trailing slash. Achieve this by stripping trailing
|
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]))
|
if (isdirsep (dir[strlen (dir) - 1]))
|
||||||
{
|
{
|
||||||
/* This converts // to /, but since both give EEXIST, we're okay. */
|
/* This converts // to /, but since both give EEXIST, we're okay. */
|
||||||
char *buf;
|
char *buf;
|
||||||
char *p = stpcpy (buf = tp.c_get (), dir) - 1;
|
char *p = stpcpy (buf = tp.c_get (), dir) - 1;
|
||||||
|
bool msdos = false;
|
||||||
dir = buf;
|
dir = buf;
|
||||||
while (p > dir && isdirsep (*p))
|
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)))
|
if (!(fh = build_fh_name (dir, PC_SYM_NOFOLLOW)))
|
||||||
__leave; /* errno already set */;
|
__leave; /* errno already set */;
|
||||||
|
@ -360,20 +372,31 @@ rmdir (const char *dir)
|
||||||
set_errno (ENOENT);
|
set_errno (ENOENT);
|
||||||
__leave;
|
__leave;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Following Linux, and intentionally ignoring POSIX, do not
|
/* Following Linux, and intentionally ignoring POSIX, do not
|
||||||
resolve the last component of DIR if it is a symlink, even if
|
resolve the last component of DIR if it is a symlink, even if
|
||||||
DIR has a trailing slash. Achieve this by stripping trailing
|
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]))
|
if (isdirsep (dir[strlen (dir) - 1]))
|
||||||
{
|
{
|
||||||
/* This converts // to /, but since both give ENOTEMPTY,
|
/* This converts // to /, but since both give ENOTEMPTY,
|
||||||
we're okay. */
|
we're okay. */
|
||||||
char *buf;
|
char *buf;
|
||||||
char *p = stpcpy (buf = tp.c_get (), dir) - 1;
|
char *p = stpcpy (buf = tp.c_get (), dir) - 1;
|
||||||
|
bool msdos = false;
|
||||||
dir = buf;
|
dir = buf;
|
||||||
while (p > dir && isdirsep (*p))
|
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)))
|
if (!(fh = build_fh_name (dir, PC_SYM_NOFOLLOW)))
|
||||||
__leave; /* errno already set */;
|
__leave; /* errno already set */;
|
||||||
|
|
|
@ -87,3 +87,7 @@ Bug Fixes
|
||||||
|
|
||||||
- Fix an assertion failure on an invalid path.
|
- Fix an assertion failure on an invalid path.
|
||||||
Addresses: https://cygwin.com/ml/cygwin/2019-09/msg00228.html
|
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
|
||||||
|
|
Loading…
Reference in New Issue