From: LynX <_LynX@bk.ru>
To: 10284@debbugs.gnu.org
Subject: bug#10284: "Renaming: permission denied" file-error in Windows
Date: Fri, 30 Dec 2011 21:31:26 +0200 [thread overview]
Message-ID: <4EFE118E.5040800@bk.ru> (raw)
In-Reply-To: <E1Rg9JS-0000mS-8c@fencepost.gnu.org>
[-- Attachment #1: Type: text/plain, Size: 3120 bytes --]
Hello Eli,
Thank you for the clarification.
Please review this patch.
--- w32.c.orig 2011-11-26 05:20:20.000000000 +0200
+++ w32.c 2011-12-30 21:22:56.734375000 +0200
@@ -2857,6 +2857,8 @@
{
BOOL result;
char temp[MAX_PATH];
+ int newname_dev;
+ int oldname_dev;
/* MoveFile on Windows 95 doesn't correctly change the short file name
alias in a number of circumstances (it is not easy to predict when
@@ -2873,6 +2875,9 @@
strcpy (temp, map_w32_filename (oldname, NULL));
+ /* volume_info is set indirectly by map_w32_filename */
+ oldname_dev = volume_info.serialnum;
+
if (os_subtype == OS_WIN95)
{
char * o;
@@ -2916,13 +2921,36 @@
all the permutations of shared or subst'd drives, etc.) */
newname = map_w32_filename (newname, NULL);
+
+ /* volume_info is set indirectly by map_w32_filename */
+ newname_dev = volume_info.serialnum;
+
result = rename (temp, newname);
- if (result < 0
- && errno == EEXIST
- && _chmod (newname, 0666) == 0
- && _unlink (newname) == 0)
- result = rename (temp, newname);
+ if (result < 0)
+ {
+
+ if (errno == EACCES
+ && newname_dev != oldname_dev)
+ {
+ /* The implementation of `rename' on Windows does not return
+ errno = EXDEV when you are moving a directory to a different
+ storage device (ex. logical disk). It returns EACCES
+ instead. So here we handle such situations and return EXDEV. */
+ DWORD attributes;
+ if ((attributes = GetFileAttributes(temp)) != -1
+ && attributes & FILE_ATTRIBUTE_DIRECTORY)
+ errno = EXDEV;
+ }
+ else if (errno == EEXIST)
+ {
+ if (_chmod (newname, 0666) != 0)
+ return result;
+ if (_unlink (newname) != 0)
+ return result;
+ result = rename (temp, newname);
+ }
+ }
return result;
}
I've added check whether it is a directory or not, and moved all this
before the unlink operation.
Regards,
LX
29.12.2011 8:18, Eli Zaretskii пишет:
>> Date: Wed, 28 Dec 2011 21:53:39 +0200
>> From: LynX<_LynX@bk.ru>
>>
>> > This first removes the target, and only then compares the device
>> > numbers. Wouldn't it be better to do it the other way around, at
>> > least when the target is a directory? That way, the target is left
>> > intact if the caller doesn't want to copy over the target, and also
>> > the filesystem is left in the same state as on Posix hosts in this
>> > case, i.e. the contract of `rename' is preserved on all systems.
>>
>> You mean that before setting errno to EXDEV we also need to check that
>> target is a directory (since files are moved correctly)?
>
> Yes, but that's not the important part of my comment above. The
> important part is to move the check for different devices _before_ the
> call to _unlink which removes the target file/directory if it exists.
> In other words, we should fail and report EXDEV without risking the
> removal of the target, and let the caller decide what to do with the
> failure. (If the caller decides to leave things unchanged, it will
> not be The Right Thing for us to remove the target.)
>
>
[-- Attachment #2: w32.c.patch --]
[-- Type: text/plain, Size: 1748 bytes --]
--- w32.c.orig 2011-11-26 05:20:20.000000000 +0200
+++ w32.c 2011-12-30 21:22:56.734375000 +0200
@@ -2857,6 +2857,8 @@
{
BOOL result;
char temp[MAX_PATH];
+ int newname_dev;
+ int oldname_dev;
/* MoveFile on Windows 95 doesn't correctly change the short file name
alias in a number of circumstances (it is not easy to predict when
@@ -2873,6 +2875,9 @@
strcpy (temp, map_w32_filename (oldname, NULL));
+ /* volume_info is set indirectly by map_w32_filename */
+ oldname_dev = volume_info.serialnum;
+
if (os_subtype == OS_WIN95)
{
char * o;
@@ -2916,13 +2921,36 @@
all the permutations of shared or subst'd drives, etc.) */
newname = map_w32_filename (newname, NULL);
+
+ /* volume_info is set indirectly by map_w32_filename */
+ newname_dev = volume_info.serialnum;
+
result = rename (temp, newname);
- if (result < 0
- && errno == EEXIST
- && _chmod (newname, 0666) == 0
- && _unlink (newname) == 0)
- result = rename (temp, newname);
+ if (result < 0)
+ {
+
+ if (errno == EACCES
+ && newname_dev != oldname_dev)
+ {
+ /* The implementation of `rename' on Windows does not return
+ errno = EXDEV when you are moving a directory to a different
+ storage device (ex. logical disk). It returns EACCES
+ instead. So here we handle such situations and return EXDEV. */
+ DWORD attributes;
+ if ((attributes = GetFileAttributes(temp)) != -1
+ && attributes & FILE_ATTRIBUTE_DIRECTORY)
+ errno = EXDEV;
+ }
+ else if (errno == EEXIST)
+ {
+ if (_chmod (newname, 0666) != 0)
+ return result;
+ if (_unlink (newname) != 0)
+ return result;
+ result = rename (temp, newname);
+ }
+ }
return result;
}
next prev parent reply other threads:[~2011-12-30 19:31 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <4EE3F66D.2050003@bk.ru>
[not found] ` <83vcpnllo3.fsf@gnu.org>
[not found] ` <4EE46AA1.9010700@cs.ucla.edu>
[not found] ` <E1RZisW-0000Ok-0C@fencepost.gnu.org>
[not found] ` <4EE504C3.3090701@bk.ru>
[not found] ` <83obvfkmt6.fsf@gnu.org>
[not found] ` <4EE5245E.3090803@bk.ru>
[not found] ` <83liqilrs0.fsf@gnu.org>
[not found] ` <4EF6D1CE.7020101@bk.ru>
2011-12-25 9:39 ` bug#10284: "Renaming: permission denied" file-error in Windows Eli Zaretskii
[not found] ` <E1RekZY-0003jE-FO@fencepost.gnu.org>
2011-12-28 19:53 ` LynX
2011-12-29 6:18 ` Eli Zaretskii
2011-12-30 19:31 ` LynX [this message]
2011-12-30 20:23 ` Eli Zaretskii
2011-12-30 21:35 ` LynX
2011-12-31 6:48 ` Eli Zaretskii
2012-01-06 20:46 ` LynX
2012-01-07 9:54 ` Eli Zaretskii
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
List information: https://www.gnu.org/software/emacs/
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=4EFE118E.5040800@bk.ru \
--to=_lynx@bk.ru \
--cc=10284@debbugs.gnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this public inbox
https://git.savannah.gnu.org/cgit/emacs.git
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).