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