This is the mail archive of the
cygwin-patches
mailing list for the Cygwin project.
Re: [PATCH v2] Cygwin: rmdir: fail if last component is a symlink, as on Linux
- From: Ken Brown <kbrown at cornell dot edu>
- To: "cygwin-patches at cygwin dot com" <cygwin-patches at cygwin dot com>
- Cc: Eric Blake <eblake at redhat dot com>
- Date: Tue, 24 Sep 2019 19:28:26 +0000
- Subject: Re: [PATCH v2] Cygwin: rmdir: fail if last component is a symlink, as on Linux
- 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=QdoU4suE4RRLsV9y79/intnjnlVP59QPzPht+gyBccA=; b=SObDP/mxM1IAW0LCV0borAEQgB6p+t9z4jffMgvjMjNZjyZ1lqdTfDiHkBgqkNLW3m0SyWQyRffnwqA7LX04jwJbpnHRph8jvuU4nXwpxORbqDKytAAbx8iKq0gCAYTOenB6lctwW4AmeTe1YL6byz4BzsO6+2By/1QQjlo4j0CpaqmFbyHkostfOvjE4cqfl1X9csztyqm3leHybPy5ICHgzQp7U/ezlOW4HuFv3K42I8BzRFnBEkDv0zQLqCe7FwYsbXRM3LwVEul3U7vBD6MwLc8gHw7HoB4MycQlg7s06YDZfIV2JxGdfFXMdM91Rni89hCnaEnpnd8hYZAfsQ==
- Arc-seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=oLOHkALHjwi1GQzBlW9yfyITbFImrX3y+J707cA0hERM9gc/O4DsmOL0hPSFfMUdCH2oOwI4CMKDlXTgV3lVERTmLLhc88BaXJ8WfwUPMcGkZM3yUaTeongvL1XYO4ivKJM6IYrUqQAXwhUpAgzqQ78aGnEUMG6X0dWYYvrnKFld3qeojAjgRh4Xa0sE3QlLhv3EmVuwyTktrbPYDgh/uYQC+6wKY8gaxw2Qb/ekb4XI2GxUbxHEh5xWtrqqJR4J3WuJoliZhC/FAuTMZUM9ZFZR9l/GyiMsOaw0LPuoiobY9Y49s5skBQJ6aJiSAjjGbnJPK88BJiamODvgTV1gnw==
- References: <20190924175530.1565-1-kbrown@cornell.edu> <5a1ced2e-ad71-0765-03af-a7bb421acad0@redhat.com>
On 9/24/2019 2:27 PM, Eric Blake wrote:
> On 9/24/19 12:55 PM, Ken Brown wrote:
>> If the last component of the directory name is a symlink followed by a
>> slash, rmdir should fail, even if the symlink resolves to an existing
>> empty directory.
>>
>> mkdir was similarly fixed in 2009 in commit
>> 52dba6a5c45e8d8ba1e237a15213311dc11d91fb. Modify a comment to clarify
>> the purpose of that commit.
>>
>> Addresses https://cygwin.com/ml/cygwin/2019-09/msg00221.html.
>> ---
>> winsup/cygwin/dir.cc | 27 +++++++++++++++++++++++----
>> 1 file changed, 23 insertions(+), 4 deletions(-)
>>
>> diff --git a/winsup/cygwin/dir.cc b/winsup/cygwin/dir.cc
>> index b757851d5..0e0535891 100644
>> --- a/winsup/cygwin/dir.cc
>> +++ b/winsup/cygwin/dir.cc
>> @@ -305,15 +305,14 @@ mkdir (const char *dir, mode_t mode)
>>
>> __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)
>> {
>> set_errno (ENOENT);
>> __leave;
>> }
>> + /* Following Linux, 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. */
>
> Maybe even "Following Linux, and intentionally ignoring POSIX, do not..."
>
>> +
>> + /* Following Linux, 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)))
>> __leave; /* errno already set */;
>>
>
> Looks okay to me.
Thanks. Does the "intentionally ignoring POSIX" part apply to rmdir also? I
didn't find it easy to decipher POSIX.
Even for mkdir, POSIX says, "If path names a symbolic link, mkdir() shall fail
and set errno to [EEXIST]." See
https://pubs.opengroup.org/onlinepubs/9699919799/functions/mkdir.html#tag_16_325.
But I'm not clear on how POSIX decides whether "path names a symbolic link" in
the case where the last component is a symlink followed by a slash.
Ken