@@ -2706,7 +2706,7 @@ int mingw_accept(int sockfd1, struct sockaddr *sa, socklen_t *sz)
2706
2706
#undef rename
2707
2707
int mingw_rename (const char * pold , const char * pnew )
2708
2708
{
2709
- DWORD attrs = INVALID_FILE_ATTRIBUTES , gle ;
2709
+ DWORD attrs = INVALID_FILE_ATTRIBUTES , gle , attrsold ;
2710
2710
int tries = 0 ;
2711
2711
wchar_t wpold [MAX_LONG_PATH ], wpnew [MAX_LONG_PATH ];
2712
2712
if (xutftowcs_long_path (wpold , pold ) < 0 ||
@@ -2719,11 +2719,24 @@ int mingw_rename(const char *pold, const char *pnew)
2719
2719
return 0 ;
2720
2720
gle = GetLastError ();
2721
2721
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
+ }
2727
2740
}
2728
2741
2729
2742
/* revert file attributes on failure */
0 commit comments