diff --git a/compat/mingw.c b/compat/mingw.c index 274346e5c510ce..1d9f88fa3821d1 100644 --- a/compat/mingw.c +++ b/compat/mingw.c @@ -2687,7 +2687,7 @@ int mingw_accept(int sockfd1, struct sockaddr *sa, socklen_t *sz) #undef rename int mingw_rename(const char *pold, const char *pnew) { - DWORD attrs = INVALID_FILE_ATTRIBUTES, gle; + DWORD attrs = INVALID_FILE_ATTRIBUTES, gle, attrsold; int tries = 0; wchar_t wpold[MAX_LONG_PATH], wpnew[MAX_LONG_PATH]; if (xutftowcs_long_path(wpold, pold) < 0 || @@ -2705,6 +2705,16 @@ int mingw_rename(const char *pold, const char *pnew) if (CopyFileW(wpold, wpnew, FALSE) && !mingw_unlink(pold)) return 0; gle = GetLastError(); + } else if ((attrsold = GetFileAttributesW(wpold)) & FILE_ATTRIBUTE_READONLY) { + /* if file is read-only, change and retry */ + SetFileAttributesW(wpold, attrsold & ~FILE_ATTRIBUTE_READONLY); + if (MoveFileExW(wpold, wpnew, + MOVEFILE_REPLACE_EXISTING | MOVEFILE_COPY_ALLOWED)) { + /* reset attrs on renamed file */ + SetFileAttributesW(wpnew, attrsold); + return 0; + } + gle = GetLastError(); } /* revert file attributes on failure */ @@ -2719,7 +2729,7 @@ int mingw_rename(const char *pold, const char *pnew) if (attrs == INVALID_FILE_ATTRIBUTES && (attrs = GetFileAttributesW(wpnew)) != INVALID_FILE_ATTRIBUTES) { if (attrs & FILE_ATTRIBUTE_DIRECTORY) { - DWORD attrsold = GetFileAttributesW(wpold); + attrsold = GetFileAttributesW(wpold); if (attrsold == INVALID_FILE_ATTRIBUTES || !(attrsold & FILE_ATTRIBUTE_DIRECTORY)) errno = EISDIR;