Cygwin: rmdir: fail if last component is a symlink, as on Linux
If the last component of the directory name is a symlink followed by a
slash, rmdir now fails, following Linux but not POSIX, even if the
symlink resolves to an existing empty directory.
mkdir was similarly changed in 2009 in commit
52dba6a5c4
. Modify a comment to clarify
the purpose of that commit.
Addresses https://cygwin.com/ml/cygwin/2019-09/msg00221.html.
This commit is contained in:
parent
9f24260ee9
commit
d1b5feef82
|
@ -305,15 +305,15 @@ mkdir (const char *dir, mode_t mode)
|
||||||
|
|
||||||
__try
|
__try
|
||||||
{
|
{
|
||||||
/* POSIX says mkdir("symlink-to-missing/") should create the
|
|
||||||
directory "missing", but Linux rejects it with EEXIST. Copy
|
|
||||||
Linux behavior for now. */
|
|
||||||
|
|
||||||
if (!*dir)
|
if (!*dir)
|
||||||
{
|
{
|
||||||
set_errno (ENOENT);
|
set_errno (ENOENT);
|
||||||
__leave;
|
__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. */
|
||||||
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. */
|
||||||
|
@ -351,9 +351,30 @@ rmdir (const char *dir)
|
||||||
{
|
{
|
||||||
int res = -1;
|
int res = -1;
|
||||||
fhandler_base *fh = NULL;
|
fhandler_base *fh = NULL;
|
||||||
|
tmp_pathbuf tp;
|
||||||
|
|
||||||
__try
|
__try
|
||||||
{
|
{
|
||||||
|
if (!*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. */
|
||||||
|
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;
|
||||||
|
dir = buf;
|
||||||
|
while (p > dir && isdirsep (*p))
|
||||||
|
*p-- = '\0';
|
||||||
|
}
|
||||||
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 */;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue