summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: 3eb91bf)
raw | patch | inline | side by side (parent: 3eb91bf)
author | Johannes Sixt <j6t@kdbg.org> | |
Wed, 19 Nov 2008 16:25:27 +0000 (17:25 +0100) | ||
committer | Junio C Hamano <gitster@pobox.com> | |
Mon, 24 Nov 2008 03:26:42 +0000 (19:26 -0800) |
On POSIX, rename() can replace files that are not writable. On Windows,
however, read-only files cannot be replaced without additional efforts:
We have to make the destination writable first.
Since the situations where the destination is read-only are rare, we do not
make the destination writable on every invocation, but only if the first
try to rename a file failed with an "access denied" error.
Signed-off-by: Johannes Sixt <j6t@kdbg.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
however, read-only files cannot be replaced without additional efforts:
We have to make the destination writable first.
Since the situations where the destination is read-only are rare, we do not
make the destination writable on every invocation, but only if the first
try to rename a file failed with an "access denied" error.
Signed-off-by: Johannes Sixt <j6t@kdbg.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
compat/mingw.c | patch | blob | history |
diff --git a/compat/mingw.c b/compat/mingw.c
index 772cad510d5d260fdf33b4f7d6ff79f9f3367b05..45733f9e04eb87409a896898cb5a92b37e87a920 100644 (file)
--- a/compat/mingw.c
+++ b/compat/mingw.c
#undef rename
int mingw_rename(const char *pold, const char *pnew)
{
+ DWORD attrs;
+
/*
* Try native rename() first to get errno right.
* It is based on MoveFile(), which cannot overwrite existing files.
if (MoveFileEx(pold, pnew, MOVEFILE_REPLACE_EXISTING))
return 0;
/* TODO: translate more errors */
- if (GetLastError() == ERROR_ACCESS_DENIED) {
- DWORD attrs = GetFileAttributes(pnew);
- if (attrs != INVALID_FILE_ATTRIBUTES && (attrs & FILE_ATTRIBUTE_DIRECTORY)) {
+ if (GetLastError() == ERROR_ACCESS_DENIED &&
+ (attrs = GetFileAttributes(pnew)) != INVALID_FILE_ATTRIBUTES) {
+ if (attrs & FILE_ATTRIBUTE_DIRECTORY) {
errno = EISDIR;
return -1;
}
+ if ((attrs & FILE_ATTRIBUTE_READONLY) &&
+ SetFileAttributes(pnew, attrs & ~FILE_ATTRIBUTE_READONLY)) {
+ if (MoveFileEx(pold, pnew, MOVEFILE_REPLACE_EXISTING))
+ return 0;
+ /* revert file attributes on failure */
+ SetFileAttributes(pnew, attrs);
+ }
}
errno = EACCES;
return -1;