mingw: emulate write(2) that fails with a EPIPE
authorJohannes Schindelin <johannes.schindelin@gmx.de>
Thu, 17 Dec 2015 17:08:15 +0000 (18:08 +0100)
committerJunio C Hamano <gitster@pobox.com>
Mon, 21 Dec 2015 16:59:04 +0000 (08:59 -0800)
On Windows, when writing to a pipe fails, errno is always
EINVAL. However, Git expects it to be EPIPE.

According to the documentation, there are two cases in which write()
triggers EINVAL: the buffer is NULL, or the length is odd but the mode
is 16-bit Unicode (the broken pipe is not mentioned as possible cause).
Git never sets the file mode to anything but binary, therefore we know
that errno should actually be EPIPE if it is EINVAL and the buffer is
not NULL.

See https://msdn.microsoft.com/en-us/library/1570wh78.aspx for more
details.

This works around t5571.11 failing with v2.6.4 on Windows.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Acked-by: Johannes Sixt <j6t@kdbg.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
compat/mingw.c
compat/mingw.h
index f74da235f598d8b0346fac8b48c4155f55ae5b81..1d70f649fb17c016c93a7c7f748e6a7271b7d782 100644 (file)
@@ -394,6 +394,23 @@ int mingw_fflush(FILE *stream)
        return ret;
 }
 
+#undef write
+ssize_t mingw_write(int fd, const void *buf, size_t len)
+{
+       ssize_t result = write(fd, buf, len);
+
+       if (result < 0 && errno == EINVAL && buf) {
+               /* check if fd is a pipe */
+               HANDLE h = (HANDLE) _get_osfhandle(fd);
+               if (GetFileType(h) == FILE_TYPE_PIPE)
+                       errno = EPIPE;
+               else
+                       errno = EINVAL;
+       }
+
+       return result;
+}
+
 int mingw_access(const char *filename, int mode)
 {
        wchar_t wfilename[MAX_PATH];
index 738865c6c068ed7d8849aff5a9b533dfb1ef8bab..57ca477d1f100a7ddb1cc9cb693d050e32ae0eb0 100644 (file)
@@ -210,6 +210,9 @@ FILE *mingw_freopen (const char *filename, const char *otype, FILE *stream);
 int mingw_fflush(FILE *stream);
 #define fflush mingw_fflush
 
+ssize_t mingw_write(int fd, const void *buf, size_t len);
+#define write mingw_write
+
 int mingw_access(const char *filename, int mode);
 #undef access
 #define access mingw_access