mirror of
https://github.com/git-for-windows/git.git
synced 2026-05-31 02:17:14 -05:00
Win32: mingw_rename: support renaming symlinks
MSVCRT's _wrename() cannot rename symlinks over existing files: it returns success without doing anything. Newer MSVCR*.dll versions probably do not have this problem: according to CRT sources, they just call MoveFileEx() with the MOVEFILE_COPY_ALLOWED flag. Get rid of _wrename() and call MoveFileEx() with proper error handling. Signed-off-by: Karsten Blees <blees@dcon.de>
This commit is contained in:
committed by
Johannes Schindelin
parent
d3df2807d0
commit
87b35ec1dc
@@ -2491,7 +2491,7 @@ int mingw_accept(int sockfd1, struct sockaddr *sa, socklen_t *sz)
|
|||||||
int mingw_rename(const char *pold, const char *pnew)
|
int mingw_rename(const char *pold, const char *pnew)
|
||||||
{
|
{
|
||||||
static int supports_file_rename_info_ex = 1;
|
static int supports_file_rename_info_ex = 1;
|
||||||
DWORD attrs, gle;
|
DWORD attrs = INVALID_FILE_ATTRIBUTES, gle;
|
||||||
int tries = 0;
|
int tries = 0;
|
||||||
wchar_t wpold[MAX_LONG_PATH], wpnew[MAX_LONG_PATH];
|
wchar_t wpold[MAX_LONG_PATH], wpnew[MAX_LONG_PATH];
|
||||||
int wpnew_len;
|
int wpnew_len;
|
||||||
@@ -2502,15 +2502,6 @@ int mingw_rename(const char *pold, const char *pnew)
|
|||||||
if (wpnew_len < 0)
|
if (wpnew_len < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
/*
|
|
||||||
* Try native rename() first to get errno right.
|
|
||||||
* It is based on MoveFile(), which cannot overwrite existing files.
|
|
||||||
*/
|
|
||||||
if (!_wrename(wpold, wpnew))
|
|
||||||
return 0;
|
|
||||||
if (errno != EEXIST)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
repeat:
|
repeat:
|
||||||
if (supports_file_rename_info_ex) {
|
if (supports_file_rename_info_ex) {
|
||||||
/*
|
/*
|
||||||
@@ -2582,13 +2573,22 @@ repeat:
|
|||||||
* to retry.
|
* to retry.
|
||||||
*/
|
*/
|
||||||
} else {
|
} else {
|
||||||
if (MoveFileExW(wpold, wpnew, MOVEFILE_REPLACE_EXISTING))
|
if (MoveFileExW(wpold, wpnew,
|
||||||
|
MOVEFILE_REPLACE_EXISTING | MOVEFILE_COPY_ALLOWED))
|
||||||
return 0;
|
return 0;
|
||||||
gle = GetLastError();
|
gle = GetLastError();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TODO: translate more errors */
|
/* revert file attributes on failure */
|
||||||
if (gle == ERROR_ACCESS_DENIED &&
|
if (attrs != INVALID_FILE_ATTRIBUTES)
|
||||||
|
SetFileAttributesW(wpnew, attrs);
|
||||||
|
|
||||||
|
if (!is_file_in_use_error(gle)) {
|
||||||
|
errno = err_win_to_posix(gle);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attrs == INVALID_FILE_ATTRIBUTES &&
|
||||||
(attrs = GetFileAttributesW(wpnew)) != INVALID_FILE_ATTRIBUTES) {
|
(attrs = GetFileAttributesW(wpnew)) != INVALID_FILE_ATTRIBUTES) {
|
||||||
if (attrs & FILE_ATTRIBUTE_DIRECTORY) {
|
if (attrs & FILE_ATTRIBUTE_DIRECTORY) {
|
||||||
DWORD attrsold = GetFileAttributesW(wpold);
|
DWORD attrsold = GetFileAttributesW(wpold);
|
||||||
@@ -2600,16 +2600,10 @@ repeat:
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if ((attrs & FILE_ATTRIBUTE_READONLY) &&
|
if ((attrs & FILE_ATTRIBUTE_READONLY) &&
|
||||||
SetFileAttributesW(wpnew, attrs & ~FILE_ATTRIBUTE_READONLY)) {
|
SetFileAttributesW(wpnew, attrs & ~FILE_ATTRIBUTE_READONLY))
|
||||||
if (MoveFileExW(wpold, wpnew, MOVEFILE_REPLACE_EXISTING))
|
goto repeat;
|
||||||
return 0;
|
|
||||||
gle = GetLastError();
|
|
||||||
/* revert file attributes on failure */
|
|
||||||
SetFileAttributesW(wpnew, attrs);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (gle == ERROR_ACCESS_DENIED &&
|
if (retry_ask_yes_no(&tries, "Rename from '%s' to '%s' failed. "
|
||||||
retry_ask_yes_no(&tries, "Rename from '%s' to '%s' failed. "
|
|
||||||
"Should I try again?", pold, pnew))
|
"Should I try again?", pold, pnew))
|
||||||
goto repeat;
|
goto repeat;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user