Skip to content

Commit 0a7214b

Browse files
kbleesdscho
authored andcommitted
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 <[email protected]>
1 parent 7b9f40d commit 0a7214b

File tree

1 file changed

+16
-22
lines changed

1 file changed

+16
-22
lines changed

compat/mingw.c

+16-22
Original file line numberDiff line numberDiff line change
@@ -2491,7 +2491,7 @@ int mingw_accept(int sockfd1, struct sockaddr *sa, socklen_t *sz)
24912491
int mingw_rename(const char *pold, const char *pnew)
24922492
{
24932493
static int supports_file_rename_info_ex = 1;
2494-
DWORD attrs, gle;
2494+
DWORD attrs = INVALID_FILE_ATTRIBUTES, gle;
24952495
int tries = 0;
24962496
wchar_t wpold[MAX_LONG_PATH], wpnew[MAX_LONG_PATH];
24972497
int wpnew_len;
@@ -2502,15 +2502,6 @@ int mingw_rename(const char *pold, const char *pnew)
25022502
if (wpnew_len < 0)
25032503
return -1;
25042504

2505-
/*
2506-
* Try native rename() first to get errno right.
2507-
* It is based on MoveFile(), which cannot overwrite existing files.
2508-
*/
2509-
if (!_wrename(wpold, wpnew))
2510-
return 0;
2511-
if (errno != EEXIST)
2512-
return -1;
2513-
25142505
repeat:
25152506
if (supports_file_rename_info_ex) {
25162507
/*
@@ -2582,13 +2573,22 @@ int mingw_rename(const char *pold, const char *pnew)
25822573
* to retry.
25832574
*/
25842575
} else {
2585-
if (MoveFileExW(wpold, wpnew, MOVEFILE_REPLACE_EXISTING))
2576+
if (MoveFileExW(wpold, wpnew,
2577+
MOVEFILE_REPLACE_EXISTING | MOVEFILE_COPY_ALLOWED))
25862578
return 0;
25872579
gle = GetLastError();
25882580
}
25892581

2590-
/* TODO: translate more errors */
2591-
if (gle == ERROR_ACCESS_DENIED &&
2582+
/* revert file attributes on failure */
2583+
if (attrs != INVALID_FILE_ATTRIBUTES)
2584+
SetFileAttributesW(wpnew, attrs);
2585+
2586+
if (!is_file_in_use_error(gle)) {
2587+
errno = err_win_to_posix(gle);
2588+
return -1;
2589+
}
2590+
2591+
if (attrs == INVALID_FILE_ATTRIBUTES &&
25922592
(attrs = GetFileAttributesW(wpnew)) != INVALID_FILE_ATTRIBUTES) {
25932593
if (attrs & FILE_ATTRIBUTE_DIRECTORY) {
25942594
DWORD attrsold = GetFileAttributesW(wpold);
@@ -2600,16 +2600,10 @@ int mingw_rename(const char *pold, const char *pnew)
26002600
return -1;
26012601
}
26022602
if ((attrs & FILE_ATTRIBUTE_READONLY) &&
2603-
SetFileAttributesW(wpnew, attrs & ~FILE_ATTRIBUTE_READONLY)) {
2604-
if (MoveFileExW(wpold, wpnew, MOVEFILE_REPLACE_EXISTING))
2605-
return 0;
2606-
gle = GetLastError();
2607-
/* revert file attributes on failure */
2608-
SetFileAttributesW(wpnew, attrs);
2609-
}
2603+
SetFileAttributesW(wpnew, attrs & ~FILE_ATTRIBUTE_READONLY))
2604+
goto repeat;
26102605
}
2611-
if (gle == ERROR_ACCESS_DENIED &&
2612-
retry_ask_yes_no(&tries, "Rename from '%s' to '%s' failed. "
2606+
if (retry_ask_yes_no(&tries, "Rename from '%s' to '%s' failed. "
26132607
"Should I try again?", pold, pnew))
26142608
goto repeat;
26152609

0 commit comments

Comments
 (0)