From e395879b76b260057f48dd54d879df2fc5b2e74d Mon Sep 17 00:00:00 2001 From: Bruno Haible Date: Sat, 24 Sep 2011 16:46:51 +0200 Subject: [PATCH] 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. --- ChangeLog | 15 +++++++++++ doc/posix-functions/write.texi | 3 +++ lib/unistd.in.h | 2 +- lib/write.c | 56 ++++++++++++++++++++++++++++-------------- m4/write.m4 | 12 ++++++++- modules/write | 2 ++ 6 files changed, 70 insertions(+), 20 deletions(-) diff --git a/ChangeLog b/ChangeLog index c378e911b..df8f6eebd 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,20 @@ 2011-09-24 Bruno Haible + 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 + read: Fix last commit. * lib/read.c (read_nothrow): Change return type to 'ssize_t'. diff --git a/doc/posix-functions/write.texi b/doc/posix-functions/write.texi index 64ab17446..3e8df86ae 100644 --- a/doc/posix-functions/write.texi +++ b/doc/posix-functions/write.texi @@ -9,6 +9,9 @@ Gnulib module: write, nonblocking, sigpipe 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: diff --git a/lib/unistd.in.h b/lib/unistd.in.h index 79b86cb0f..f53f34b7e 100644 --- a/lib/unistd.in.h +++ b/lib/unistd.in.h @@ -1449,7 +1449,7 @@ _GL_WARN_ON_USE (usleep, "usleep is unportable - " /* Write up to COUNT bytes starting at BUF to file descriptor FD. See the POSIX:2008 specification . */ -# 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 diff --git a/lib/write.c b/lib/write.c index 64bc5352e..c3537d594 100644 --- a/lib/write.c +++ b/lib/write.c @@ -20,37 +20,58 @@ /* Specification. */ #include -/* 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 +# include +# include -# include -# include -# include +# define WIN32_LEAN_AND_MEAN /* avoid including junk */ +# include -# define WIN32_LEAN_AND_MEAN /* avoid including junk */ -# include +# 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); @@ -101,9 +122,9 @@ rpl_write (int fd, const void *buf, size_t count) } } else -# endif +# endif { -# if GNULIB_SIGPIPE +# if GNULIB_SIGPIPE if (GetLastError () == ERROR_NO_DATA && GetFileType ((HANDLE) _get_osfhandle (fd)) == FILE_TYPE_PIPE) @@ -114,12 +135,11 @@ rpl_write (int fd, const void *buf, size_t count) EINVAL to EPIPE. */ errno = EPIPE; } -# endif +# endif } } return ret; } } -# endif #endif diff --git a/m4/write.m4 b/m4/write.m4 index c39d3d07a..4cfff0e98 100644 --- a/m4/write.m4 +++ b/m4/write.m4 @@ -1,4 +1,4 @@ -# 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, @@ -7,6 +7,10 @@ dnl with or without modifications, as long as this notice is preserved. 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. @@ -23,3 +27,9 @@ AC_DEFUN([gl_FUNC_WRITE], fi ]) ]) + +# Prerequisites of lib/write.c. +AC_DEFUN([gl_PREREQ_WRITE], +[ + AC_REQUIRE([AC_C_INLINE]) +]) diff --git a/modules/write b/modules/write index c19f73b7e..36207418f 100644 --- a/modules/write +++ b/modules/write @@ -8,12 +8,14 @@ m4/write.m4 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]) -- 2.11.0