diff options
| author | Junio C Hamano <gitster@pobox.com> | 2025-04-15 13:50:15 -0700 |
|---|---|---|
| committer | Junio C Hamano <gitster@pobox.com> | 2025-04-15 13:50:15 -0700 |
| commit | d5baf636a431c54d0f306ed98775797c171373b2 (patch) | |
| tree | 783d5e94b552614b4b31838ddfdb6d7687a8b7e2 /compat/mingw.c | |
| parent | Merge branch 'kn/reflog-drop' (diff) | |
| parent | compat/mingw: fix EACCESS when opening files with `O_CREAT | O_EXCL` (diff) | |
| download | git-d5baf636a431c54d0f306ed98775797c171373b2.tar.gz git-d5baf636a431c54d0f306ed98775797c171373b2.zip | |
Merge branch 'ps/mingw-creat-excl-fix'
Fix lockfile contention in reftable code on Windows.
* ps/mingw-creat-excl-fix:
compat/mingw: fix EACCESS when opening files with `O_CREAT | O_EXCL`
meson: fix compat sources when compiling with MSVC
Diffstat (limited to 'compat/mingw.c')
| -rw-r--r-- | compat/mingw.c | 20 |
1 files changed, 20 insertions, 0 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)) |
