diff options
| author | Johannes Schindelin <johannes.schindelin@gmx.de> | 2025-12-17 14:18:39 +0000 |
|---|---|---|
| committer | Junio C Hamano <gitster@pobox.com> | 2025-12-18 08:18:12 +0900 |
| commit | 6fa50cc4a1979fb8a2f77a026e307d6336a09172 (patch) | |
| tree | 9bd7625cf20f903ffdd7444f5c9efb663c020118 /compat/mingw.c | |
| parent | b90a926371bbb45b2abd27241a8ef682f1450b99 (diff) | |
| download | git-6fa50cc4a1979fb8a2f77a026e307d6336a09172.tar.xz | |
mingw: special-case `open(symlink, O_CREAT | O_EXCL)`
The `_wopen()` function would gladly follow a symbolic link to a
non-existent file and create it when given above-mentioned flags.
Git expects the `open()` call to fail, though. So let's add yet another
work-around to pretend that Windows behaves according to POSIX, see:
https://pubs.opengroup.org/onlinepubs/007904875/functions/open.html#:~:text=If%20O_CREAT%20and%20O_EXCL%20are,set%2C%20the%20result%20is%20undefined.
This is required to let t4115.8(--reject removes .rej symlink if it
exists) pass on Windows when enabling the MSYS2 runtime's symbolic link
support.
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'compat/mingw.c')
| -rw-r--r-- | compat/mingw.c | 14 |
1 files changed, 14 insertions, 0 deletions
diff --git a/compat/mingw.c b/compat/mingw.c index 90ba5cea9d..ba1b7b6dd1 100644 --- a/compat/mingw.c +++ b/compat/mingw.c @@ -629,6 +629,7 @@ int mingw_open (const char *filename, int oflags, ...) int fd, create = (oflags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL); wchar_t wfilename[MAX_PATH]; open_fn_t open_fn; + WIN32_FILE_ATTRIBUTE_DATA fdata; DECLARE_PROC_ADDR(ntdll.dll, NTSTATUS, NTAPI, RtlGetLastNtStatus, void); @@ -653,6 +654,19 @@ int mingw_open (const char *filename, int oflags, ...) else if (xutftowcs_path(wfilename, filename) < 0) return -1; + /* + * When `symlink` exists and is a symbolic link pointing to a + * non-existing file, `_wopen(symlink, O_CREAT | O_EXCL)` would + * create that file. Not what we want: Linux would say `EEXIST` + * in that instance, which is therefore what Git expects. + */ + if (create && + GetFileAttributesExW(wfilename, GetFileExInfoStandard, &fdata) && + (fdata.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)) { + errno = EEXIST; + return -1; + } + fd = open_fn(wfilename, oflags, mode); /* |
