@@ -2700,7 +2700,7 @@ int mingw_accept(int sockfd1, struct sockaddr *sa, socklen_t *sz)
2700
2700
#undef rename
2701
2701
int mingw_rename (const char * pold , const char * pnew )
2702
2702
{
2703
- DWORD attrs = INVALID_FILE_ATTRIBUTES , gle ;
2703
+ DWORD attrs = INVALID_FILE_ATTRIBUTES , gle , attrsold ;
2704
2704
int tries = 0 ;
2705
2705
wchar_t wpold [MAX_LONG_PATH ], wpnew [MAX_LONG_PATH ];
2706
2706
if (xutftowcs_long_path (wpold , pold ) < 0 ||
@@ -2713,11 +2713,24 @@ int mingw_rename(const char *pold, const char *pnew)
2713
2713
return 0 ;
2714
2714
gle = GetLastError ();
2715
2715
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
+ }
2721
2734
}
2722
2735
2723
2736
/* revert file attributes on failure */
0 commit comments