+2011-09-24 Bruno Haible <bruno@clisp.org>
+
+ write: Support for MSVC 9.
+ * lib/unistd.in.h (write): Replace also when GNULIB_UNISTD_H_NONBLOCKING
+ is not 1.
+ * lib/write.c (write_nothrow): New function.
+ (rpl_write): Define also when GNULIB_NONBLOCKING or GNULIB_SIGPIPE is
+ not 1. Use write_nothrow.
+ * m4/write.m4 (gl_FUNC_WRITE): Replace read if the platform has an
+ invalid parameter handler.
+ (gl_PREREQ_WRITE): New macro.
+ * modules/write (Depends-on): Add msvc-inval.
+ (configure.ac): Invoke gl_PREREQ_WRITE.
+ * doc/posix-functions/write.texi: Mention the problem on MSVC.
+
2011-09-24 Bruno Haible <bruno@clisp.org>
read: Fix last commit.
Portability problems fixed by Gnulib module @code{stdio}, together with module @code{nonblocking}:
@itemize
@item
+This function crashes when invoked with invalid arguments on some platforms:
+MSVC 9.
+@item
When writing to a non-blocking pipe whose buffer is full, this function fails
with @code{errno} being set to @code{ENOSPC} instead of @code{EAGAIN} on some
platforms:
/* Write up to COUNT bytes starting at BUF to file descriptor FD.
See the POSIX:2008 specification
<http://pubs.opengroup.org/onlinepubs/9699919799/functions/write.html>. */
-# if @REPLACE_WRITE@ && (@GNULIB_UNISTD_H_NONBLOCKING@ || @GNULIB_UNISTD_H_SIGPIPE@)
+# if @REPLACE_WRITE@
# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
# undef write
# define write rpl_write
/* Specification. */
#include <unistd.h>
-/* Replace this function only if module 'nonblocking' or module 'sigpipe' is
- requested. */
-#if GNULIB_NONBLOCKING || GNULIB_SIGPIPE
-
/* On native Windows platforms, SIGPIPE does not exist. When write() is
called on a pipe with no readers, WriteFile() fails with error
GetLastError() = ERROR_NO_DATA, and write() in consequence fails with
error EINVAL. */
-# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
+#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
+
+# include <errno.h>
+# include <signal.h>
+# include <io.h>
-# include <errno.h>
-# include <signal.h>
-# include <io.h>
+# define WIN32_LEAN_AND_MEAN /* avoid including junk */
+# include <windows.h>
-# define WIN32_LEAN_AND_MEAN /* avoid including junk */
-# include <windows.h>
+# include "msvc-inval.h"
+# include "msvc-nothrow.h"
-# include "msvc-nothrow.h"
+# undef write
+
+# if HAVE_MSVC_INVALID_PARAMETER_HANDLER
+static inline ssize_t
+write_nothrow (int fd, const void *buf, size_t count)
+{
+ ssize_t result;
+
+ TRY_MSVC_INVAL
+ {
+ result = write (fd, buf, count);
+ }
+ CATCH_MSVC_INVAL
+ {
+ result = -1;
+ errno = EBADF;
+ }
+ DONE_MSVC_INVAL;
+
+ return result;
+}
+# else
+# define write_nothrow write
+# endif
ssize_t
rpl_write (int fd, const void *buf, size_t count)
-#undef write
{
for (;;)
{
- ssize_t ret = write (fd, buf, count);
+ ssize_t ret = write_nothrow (fd, buf, count);
if (ret < 0)
{
-# if GNULIB_NONBLOCKING
+# if GNULIB_NONBLOCKING
if (errno == ENOSPC)
{
HANDLE h = (HANDLE) _get_osfhandle (fd);
}
}
else
-# endif
+# endif
{
-# if GNULIB_SIGPIPE
+# if GNULIB_SIGPIPE
if (GetLastError () == ERROR_NO_DATA
&& GetFileType ((HANDLE) _get_osfhandle (fd))
== FILE_TYPE_PIPE)
EINVAL to EPIPE. */
errno = EPIPE;
}
-# endif
+# endif
}
}
return ret;
}
}
-# endif
#endif
-# write.m4 serial 3
+# write.m4 serial 4
dnl Copyright (C) 2008-2011 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
AC_DEFUN([gl_FUNC_WRITE],
[
AC_REQUIRE([gl_UNISTD_H_DEFAULTS])
+ AC_REQUIRE([gl_MSVC_INVAL])
+ if test $HAVE_MSVC_INVALID_PARAMETER_HANDLER = 1; then
+ REPLACE_WRITE=1
+ fi
dnl This ifdef is just an optimization, to avoid performing a configure
dnl check whose result is not used. It does not make the test of
dnl GNULIB_UNISTD_H_SIGPIPE or GNULIB_SIGPIPE redundant.
fi
])
])
+
+# Prerequisites of lib/write.c.
+AC_DEFUN([gl_PREREQ_WRITE],
+[
+ AC_REQUIRE([AC_C_INLINE])
+])
Depends-on:
unistd
raise [test $REPLACE_WRITE = 1]
+msvc-inval [test $REPLACE_WRITE = 1]
msvc-nothrow [test $REPLACE_WRITE = 1]
configure.ac:
gl_FUNC_WRITE
if test $REPLACE_WRITE = 1; then
AC_LIBOBJ([write])
+ gl_PREREQ_WRITE
fi
gl_UNISTD_MODULE_INDICATOR([write])