@@ -2706,7 +2706,7 @@ int mingw_accept(int sockfd1, struct sockaddr *sa, socklen_t *sz)
27062706#undef rename
27072707int mingw_rename (const char * pold , const char * pnew )
27082708{
2709- DWORD attrs = INVALID_FILE_ATTRIBUTES , gle ;
2709+ DWORD attrs = INVALID_FILE_ATTRIBUTES , gle , attrsold ;
27102710 int tries = 0 ;
27112711 wchar_t wpold [MAX_LONG_PATH ], wpnew [MAX_LONG_PATH ];
27122712 if (xutftowcs_long_path (wpold , pold ) < 0 ||
@@ -2719,11 +2719,24 @@ int mingw_rename(const char *pold, const char *pnew)
27192719 return 0 ;
27202720 gle = GetLastError ();
27212721
2722- if (gle == ERROR_ACCESS_DENIED && is_inside_windows_container ()) {
2723- /* Fall back to copy to destination & remove source */
2724- if (CopyFileW (wpold , wpnew , FALSE) && !mingw_unlink (pold ))
2725- return 0 ;
2726- gle = GetLastError ();
2722+ if (gle == ERROR_ACCESS_DENIED ) {
2723+ if (is_inside_windows_container ()) {
2724+ /* Fall back to copy to destination & remove source */
2725+ if (CopyFileW (wpold , wpnew , FALSE) && !mingw_unlink (pold ))
2726+ return 0 ;
2727+ gle = GetLastError ();
2728+ } else if ((attrsold = GetFileAttributesW (wpold )) & FILE_ATTRIBUTE_READONLY ) {
2729+ /* if file is read-only, change and retry */
2730+ SetFileAttributesW (wpold , attrsold & ~FILE_ATTRIBUTE_READONLY );
2731+ if (MoveFileExW (wpold , wpnew ,
2732+ MOVEFILE_REPLACE_EXISTING | MOVEFILE_COPY_ALLOWED )) {
2733+ SetFileAttributesW (wpnew , attrsold );
2734+ return 0 ;
2735+ }
2736+ gle = GetLastError ();
2737+ /* revert attribute change on failure */
2738+ SetFileAttributesW (wpold , attrsold );
2739+ }
27272740 }
27282741
27292742 /* revert file attributes on failure */
0 commit comments