summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--compat/mingw.c20
-rw-r--r--meson.build4
2 files changed, 23 insertions, 1 deletions
diff --git a/compat/mingw.c b/compat/mingw.c
index 6ea2e7a35b..8a9972a1ca 100644
--- a/compat/mingw.c
+++ b/compat/mingw.c
@@ -21,6 +21,9 @@
#include "gettext.h"
#define SECURITY_WIN32
#include <sspi.h>
+#include <winternl.h>
+
+#define STATUS_DELETE_PENDING ((NTSTATUS) 0xC0000056)
#define HCAST(type, handle) ((type)(intptr_t)handle)
@@ -624,6 +627,8 @@ int mingw_open (const char *filename, int oflags, ...)
wchar_t wfilename[MAX_PATH];
open_fn_t open_fn;
+ DECLARE_PROC_ADDR(ntdll.dll, NTSTATUS, NTAPI, RtlGetLastNtStatus, void);
+
va_start(args, oflags);
mode = va_arg(args, int);
va_end(args);
@@ -647,6 +652,21 @@ int mingw_open (const char *filename, int oflags, ...)
fd = open_fn(wfilename, oflags, mode);
+ /*
+ * Internally, `_wopen()` uses the `CreateFile()` API with CREATE_NEW,
+ * which may error out with ERROR_ACCESS_DENIED and an NtStatus of
+ * STATUS_DELETE_PENDING when the file is scheduled for deletion via
+ * `DeleteFileW()`. The file essentially exists, so we map errno to
+ * EEXIST instead of EACCESS so that callers don't have to special-case
+ * this.
+ *
+ * This fixes issues for example with the lockfile interface when one
+ * process has a lock that it is about to commit or release while
+ * another process wants to acquire it.
+ */
+ if (fd < 0 && create && GetLastError() == ERROR_ACCESS_DENIED &&
+ INIT_PROC_ADDR(RtlGetLastNtStatus) && RtlGetLastNtStatus() == STATUS_DELETE_PENDING)
+ errno = EEXIST;
if (fd < 0 && (oflags & O_ACCMODE) != O_RDONLY && errno == EACCES) {
DWORD attrs = GetFileAttributesW(wfilename);
if (attrs != INVALID_FILE_ATTRIBUTES && (attrs & FILE_ATTRIBUTE_DIRECTORY))
diff --git a/meson.build b/meson.build
index 145d2f7ff9..9f3b5ad676 100644
--- a/meson.build
+++ b/meson.build
@@ -1115,7 +1115,6 @@ if host_machine.system() == 'cygwin'
]
elif host_machine.system() == 'windows'
libgit_sources += [
- 'compat/mingw.c',
'compat/winansi.c',
'compat/win32/dirent.c',
'compat/win32/flush.c',
@@ -1142,6 +1141,9 @@ elif host_machine.system() == 'windows'
libgit_include_directories += 'compat/win32'
if compiler.get_id() == 'msvc'
libgit_include_directories += 'compat/vcbuild/include'
+ libgit_sources += 'compat/msvc.c'
+ else
+ libgit_sources += 'compat/mingw.c'
endif
endif