Skip to content

Commit cc22fae

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 70514cf commit cc22fae

File tree

1 file changed

+17
-22
lines changed

1 file changed

+17
-22
lines changed

compat/mingw.c

Lines changed: 17 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1729,28 +1729,29 @@ int mingw_accept(int sockfd1, struct sockaddr *sa, socklen_t *sz)
17291729
#undef rename
17301730
int mingw_rename(const char *pold, const char *pnew)
17311731
{
1732-
DWORD attrs, gle;
1732+
DWORD attrs = INVALID_FILE_ATTRIBUTES, gle;
17331733
int tries = 0;
17341734
wchar_t wpold[MAX_LONG_PATH], wpnew[MAX_LONG_PATH];
17351735
if (xutftowcs_long_path(wpold, pold) < 0 ||
17361736
xutftowcs_long_path(wpnew, pnew) < 0)
17371737
return -1;
17381738

1739-
/*
1740-
* Try native rename() first to get errno right.
1741-
* It is based on MoveFile(), which cannot overwrite existing files.
1742-
*/
1743-
if (!_wrename(wpold, wpnew))
1744-
return 0;
1745-
if (errno != EEXIST)
1746-
return -1;
17471739
repeat:
1748-
if (MoveFileExW(wpold, wpnew, MOVEFILE_REPLACE_EXISTING))
1740+
if (MoveFileExW(wpold, wpnew,
1741+
MOVEFILE_REPLACE_EXISTING | MOVEFILE_COPY_ALLOWED))
17491742
return 0;
1750-
/* TODO: translate more errors */
17511743
gle = GetLastError();
1752-
if (gle == ERROR_ACCESS_DENIED &&
1753-
(attrs = GetFileAttributesW(wpnew)) != INVALID_FILE_ATTRIBUTES) {
1744+
1745+
/* revert file attributes on failure */
1746+
if (attrs != INVALID_FILE_ATTRIBUTES)
1747+
SetFileAttributesW(wpnew, attrs);
1748+
1749+
if (!is_file_in_use_error(gle)) {
1750+
errno = err_win_to_posix(gle);
1751+
return -1;
1752+
}
1753+
1754+
if ((attrs = GetFileAttributesW(wpnew)) != INVALID_FILE_ATTRIBUTES) {
17541755
if (attrs & FILE_ATTRIBUTE_DIRECTORY) {
17551756
DWORD attrsold = GetFileAttributesW(wpold);
17561757
if (attrsold == INVALID_FILE_ATTRIBUTES ||
@@ -1761,16 +1762,10 @@ int mingw_rename(const char *pold, const char *pnew)
17611762
return -1;
17621763
}
17631764
if ((attrs & FILE_ATTRIBUTE_READONLY) &&
1764-
SetFileAttributesW(wpnew, attrs & ~FILE_ATTRIBUTE_READONLY)) {
1765-
if (MoveFileExW(wpold, wpnew, MOVEFILE_REPLACE_EXISTING))
1766-
return 0;
1767-
gle = GetLastError();
1768-
/* revert file attributes on failure */
1769-
SetFileAttributesW(wpnew, attrs);
1770-
}
1765+
SetFileAttributesW(wpnew, attrs & ~FILE_ATTRIBUTE_READONLY))
1766+
goto repeat;
17711767
}
1772-
if (gle == ERROR_ACCESS_DENIED &&
1773-
retry_ask_yes_no(&tries, "Rename from '%s' to '%s' failed. "
1768+
if (retry_ask_yes_no(&tries, "Rename from '%s' to '%s' failed. "
17741769
"Should I try again?", pold, pnew))
17751770
goto repeat;
17761771

0 commit comments

Comments
 (0)