@@ -2700,7 +2700,7 @@ int mingw_accept(int sockfd1, struct sockaddr *sa, socklen_t *sz)
27002700#undef rename
27012701int mingw_rename (const char * pold , const char * pnew )
27022702{
2703- DWORD attrs = INVALID_FILE_ATTRIBUTES , gle ;
2703+ DWORD attrs = INVALID_FILE_ATTRIBUTES , gle , attrsold ;
27042704 int tries = 0 ;
27052705 wchar_t wpold [MAX_LONG_PATH ], wpnew [MAX_LONG_PATH ];
27062706 if (xutftowcs_long_path (wpold , pold ) < 0 ||
@@ -2713,11 +2713,24 @@ int mingw_rename(const char *pold, const char *pnew)
27132713 return 0 ;
27142714 gle = GetLastError ();
27152715
2716- if (gle == ERROR_ACCESS_DENIED && is_inside_windows_container ()) {
2717- /* Fall back to copy to destination & remove source */
2718- if (CopyFileW (wpold , wpnew , FALSE) && !mingw_unlink (pold ))
2719- return 0 ;
2720- gle = GetLastError ();
2716+ if (gle == ERROR_ACCESS_DENIED ) {
2717+ if (is_inside_windows_container ()) {
2718+ /* Fall back to copy to destination & remove source */
2719+ if (CopyFileW (wpold , wpnew , FALSE) && !mingw_unlink (pold ))
2720+ return 0 ;
2721+ gle = GetLastError ();
2722+ } else if ((attrsold = GetFileAttributesW (wpold )) & FILE_ATTRIBUTE_READONLY ) {
2723+ /* if file is read-only, change and retry */
2724+ SetFileAttributesW (wpold , attrsold & ~FILE_ATTRIBUTE_READONLY );
2725+ if (MoveFileExW (wpold , wpnew ,
2726+ MOVEFILE_REPLACE_EXISTING | MOVEFILE_COPY_ALLOWED )) {
2727+ SetFileAttributesW (wpnew , attrsold );
2728+ return 0 ;
2729+ }
2730+ gle = GetLastError ();
2731+ /* revert attribute change on failure */
2732+ SetFileAttributesW (wpold , attrsold );
2733+ }
27212734 }
27222735
27232736 /* revert file attributes on failure */
0 commit comments