return wbuf;
}
+/*
+ * Use SetFileInformationByHandle(FileDispositionInfo) to force legacy
+ * (non-POSIX) delete semantics. On Windows 11, DeleteFileW() uses POSIX
+ * delete semantics internally, allowing deletion even with active
+ * MapViewOfFile views. This helper simulates Windows 10 behavior where
+ * deletion fails if a file mapping exists.
+ *
+ * Returns nonzero on success (like DeleteFileW), 0 on failure.
+ */
+static int legacy_delete_file(const wchar_t *wpathname)
+{
+ FILE_DISPOSITION_INFO fdi = { TRUE };
+ DWORD gle;
+ HANDLE h = CreateFileW(wpathname, DELETE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE |
+ FILE_SHARE_DELETE,
+ NULL, OPEN_EXISTING,
+ FILE_FLAG_OPEN_REPARSE_POINT, NULL);
+ if (h == INVALID_HANDLE_VALUE)
+ return 0;
+
+ if (SetFileInformationByHandle(h, FileDispositionInfo,
+ &fdi, sizeof(fdi))) {
+ CloseHandle(h);
+ return 1;
+ }
+ gle = GetLastError();
+ CloseHandle(h);
+ SetLastError(gle);
+ return 0;
+}
+
+static int try_delete_file(const wchar_t *wpathname, int use_legacy)
+{
+ if (use_legacy)
+ return legacy_delete_file(wpathname);
+ return DeleteFileW(wpathname);
+}
+
int mingw_unlink(const char *pathname, int handle_in_use_error)
{
+ static int use_legacy_delete = -1;
int tries = 0;
wchar_t wpathname[MAX_PATH];
if (xutftowcs_path(wpathname, pathname) < 0)
return -1;
- if (DeleteFileW(wpathname))
+ if (use_legacy_delete < 0)
+ use_legacy_delete = git_env_bool("GIT_TEST_LEGACY_DELETE", 0);
+
+ if (try_delete_file(wpathname, use_legacy_delete))
return 0;
do {
/* read-only files cannot be removed */
_wchmod(wpathname, 0666);
- if (!_wunlink(wpathname))
+ if (try_delete_file(wpathname, use_legacy_delete))
return 0;
if (!is_file_in_use_error(GetLastError()))
break;