write: Support for MSVC 9.
authorBruno Haible <bruno@clisp.org>
Sat, 24 Sep 2011 14:46:51 +0000 (16:46 +0200)
committerBruno Haible <bruno@clisp.org>
Sat, 24 Sep 2011 14:46:51 +0000 (16:46 +0200)
* 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
doc/posix-functions/write.texi
lib/unistd.in.h
lib/write.c
m4/write.m4
modules/write

index c378e91..df8f6ee 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,20 @@
 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.
        * lib/read.c (read_nothrow): Change return type to 'ssize_t'.
 
index 64ab174..3e8df86 100644 (file)
@@ -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:
index 79b86cb..f53f34b 100644 (file)
@@ -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
    <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
index 64bc535..c3537d5 100644 (file)
 /* 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);
@@ -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
index c39d3d0..4cfff0e 100644 (file)
@@ -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])
+])
index c19f73b..3620741 100644 (file)
@@ -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])