changeset 34223:4a1c19b03dd1

nonblocking: provide O_NONBLOCK for mingw Mingw is the only known platform that lacks O_NONBLOCK (possibly via the alternate spelling O_NDELAY). But mingw also lacks any files where open() needs to enforce non-blocking behavior, and lacks openat(), so it is relatively simple to provide a non-zero flag. A future patches will make use of O_NONBLOCK for pipe2. * modules/nonblocking (Depends-on): Add open. (configure.ac): Set new witness macro. * m4/fcntl_h.m4 (gl_FCNTL_H_DEFAULTS): Provide default for it. * modules/fcntl-h (Makefile.am): Substitute it. * lib/fcntl.in.h (O_NONBLOCK): Guarantee non-zero definition when nonblocking module is in use. * lib/nonblocking.c: Adjust portability test. * lib/open.c (open): Don't let native open see gnulib flag. * tests/test-fcntl-h.c (main): Enhance test. * tests/test-open.h (test_open): Likewise. * doc/posix-headers/fcntl.texi (fcntl.h): Document the replacement. Signed-off-by: Eric Blake <eblake@redhat.com>
author Eric Blake <eblake@redhat.com>
date Fri, 08 Apr 2011 10:15:54 -0600
parents c94edf5a1c4c
children f678c225705a
files ChangeLog doc/posix-headers/fcntl.texi lib/fcntl.in.h lib/nonblocking.c lib/open.c m4/fcntl_h.m4 modules/fcntl-h modules/nonblocking tests/test-fcntl-h.c tests/test-open.h
diffstat 10 files changed, 139 insertions(+), 15 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Fri Apr 08 08:51:56 2011 -0600
+++ b/ChangeLog	Fri Apr 08 10:15:54 2011 -0600
@@ -1,5 +1,18 @@
 2011-04-08  Eric Blake  <eblake@redhat.com>
 
+	nonblocking: provide O_NONBLOCK for mingw
+	* modules/nonblocking (Depends-on): Add open.
+	(configure.ac): Set new witness macro.
+	* m4/fcntl_h.m4 (gl_FCNTL_H_DEFAULTS): Provide default for it.
+	* modules/fcntl-h (Makefile.am): Substitute it.
+	* lib/fcntl.in.h (O_NONBLOCK): Guarantee non-zero definition when
+	nonblocking module is in use.
+	* lib/nonblocking.c: Adjust portability test.
+	* lib/open.c (open): Don't let native open see gnulib flag.
+	* tests/test-fcntl-h.c (main): Enhance test.
+	* tests/test-open.h (test_open): Likewise.
+	* doc/posix-headers/fcntl.texi (fcntl.h): Document the replacement.
+
 	careadlink: fix compilation error on mingw
 	* lib/careadlinkat.c (standard_allocator): Avoid renaming fields
 	within struct allocator.
--- a/doc/posix-headers/fcntl.texi	Fri Apr 08 08:51:56 2011 -0600
+++ b/doc/posix-headers/fcntl.texi	Fri Apr 08 10:15:54 2011 -0600
@@ -9,9 +9,14 @@
 @itemize
 @item
 @samp{O_CLOEXEC}, @samp{O_DIRECTORY}, @samp{O_DSYNC}, @samp{O_NOCTTY},
-@samp{O_NOFOLLOW}, @samp{O_NONBLOCK}, @samp{O_RSYNC}, @samp{O_SYNC},
+@samp{O_NOFOLLOW}, @samp{O_RSYNC}, @samp{O_SYNC},
 and @samp{O_TTY_INIT} are not defined on some platforms.  Gnulib defines
-these macros to 0.
+these macros to 0, which is generally safe.
+
+@item
+@samp{O_NONBLOCK} is not defined on some platforms.  If the
+@samp{nonblocking} module is in use, gnulib guarantees a working
+non-zero value; otherwise, the gnulib replacement is 0.
 
 @item
 @samp{O_EXEC} and @samp{O_SEARCH} are not defined on some platforms.
--- a/lib/fcntl.in.h	Fri Apr 08 08:51:56 2011 -0600
+++ b/lib/fcntl.in.h	Fri Apr 08 10:15:54 2011 -0600
@@ -182,8 +182,7 @@
 #endif
 
 #if !defined O_CLOEXEC && defined O_NOINHERIT
-/* Mingw spells it `O_NOINHERIT'.  Intentionally leave it
-   undefined if not available.  */
+/* Mingw spells it `O_NOINHERIT'.  */
 # define O_CLOEXEC O_NOINHERIT
 #endif
 
@@ -219,6 +218,16 @@
 # define O_NONBLOCK O_NDELAY
 #endif
 
+#if @GNULIB_NONBLOCKING@
+# if O_NONBLOCK
+#  define GNULIB_defined_O_NONBLOCK 0
+# else
+#  define GNULIB_defined_O_NONBLOCK 1
+#  undef O_NONBLOCK
+#  define O_NONBLOCK 0x40000000
+# endif
+#endif
+
 #ifndef O_NOCTTY
 # define O_NOCTTY 0
 #endif
--- a/lib/nonblocking.c	Fri Apr 08 08:51:56 2011 -0600
+++ b/lib/nonblocking.c	Fri Apr 08 10:15:54 2011 -0600
@@ -113,7 +113,7 @@
 
 # include <fcntl.h>
 
-# if !O_NONBLOCK
+# if GNULIB_defined_O_NONBLOCK
 #  error Please port nonblocking to your platform
 # endif
 
--- a/lib/open.c	Fri Apr 08 08:51:56 2011 -0600
+++ b/lib/open.c	Fri Apr 08 10:15:54 2011 -0600
@@ -63,6 +63,15 @@
       va_end (arg);
     }
 
+#if GNULIB_defined_O_NONBLOCK
+  /* The only known platform that lacks O_NONBLOCK is mingw, but it
+     also lacks named pipes and Unix sockets, which are the only two
+     file types that require non-blocking handling in open().
+     Therefore, it is safe to ignore O_NONBLOCK here.  It is handy
+     that mingw also lacks openat(), so that is also covered here.  */
+  flags &= ~O_NONBLOCK;
+#endif
+
 #if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
   if (strcmp (filename, "/dev/null") == 0)
     filename = "NUL";
--- a/m4/fcntl_h.m4	Fri Apr 08 08:51:56 2011 -0600
+++ b/m4/fcntl_h.m4	Fri Apr 08 10:15:54 2011 -0600
@@ -31,13 +31,14 @@
 
 AC_DEFUN([gl_FCNTL_H_DEFAULTS],
 [
-  GNULIB_FCNTL=0;   AC_SUBST([GNULIB_FCNTL])
-  GNULIB_OPEN=0;    AC_SUBST([GNULIB_OPEN])
-  GNULIB_OPENAT=0;  AC_SUBST([GNULIB_OPENAT])
+  GNULIB_FCNTL=0;        AC_SUBST([GNULIB_FCNTL])
+  GNULIB_NONBLOCKING=0;  AC_SUBST([GNULIB_NONBLOCKING])
+  GNULIB_OPEN=0;         AC_SUBST([GNULIB_OPEN])
+  GNULIB_OPENAT=0;       AC_SUBST([GNULIB_OPENAT])
   dnl Assume proper GNU behavior unless another module says otherwise.
-  HAVE_FCNTL=1;     AC_SUBST([HAVE_FCNTL])
-  HAVE_OPENAT=1;    AC_SUBST([HAVE_OPENAT])
-  REPLACE_FCNTL=0;  AC_SUBST([REPLACE_FCNTL])
-  REPLACE_OPEN=0;   AC_SUBST([REPLACE_OPEN])
-  REPLACE_OPENAT=0; AC_SUBST([REPLACE_OPENAT])
+  HAVE_FCNTL=1;          AC_SUBST([HAVE_FCNTL])
+  HAVE_OPENAT=1;         AC_SUBST([HAVE_OPENAT])
+  REPLACE_FCNTL=0;       AC_SUBST([REPLACE_FCNTL])
+  REPLACE_OPEN=0;        AC_SUBST([REPLACE_OPEN])
+  REPLACE_OPENAT=0;      AC_SUBST([REPLACE_OPENAT])
 ])
--- a/modules/fcntl-h	Fri Apr 08 08:51:56 2011 -0600
+++ b/modules/fcntl-h	Fri Apr 08 10:15:54 2011 -0600
@@ -30,6 +30,7 @@
 	      -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \
 	      -e 's|@''NEXT_FCNTL_H''@|$(NEXT_FCNTL_H)|g' \
 	      -e 's|@''GNULIB_FCNTL''@|$(GNULIB_FCNTL)|g' \
+	      -e 's|@''GNULIB_NONBLOCKING''@|$(GNULIB_NONBLOCKING)|g' \
 	      -e 's|@''GNULIB_OPEN''@|$(GNULIB_OPEN)|g' \
 	      -e 's|@''GNULIB_OPENAT''@|$(GNULIB_OPENAT)|g' \
 	      -e 's|@''HAVE_FCNTL''@|$(HAVE_FCNTL)|g' \
--- a/modules/nonblocking	Fri Apr 08 08:51:56 2011 -0600
+++ b/modules/nonblocking	Fri Apr 08 10:15:54 2011 -0600
@@ -8,10 +8,12 @@
 Depends-on:
 fcntl-h
 ioctl
+open
 stdbool
 sys_socket
 
 configure.ac:
+gl_FCNTL_MODULE_INDICATOR([nonblocking])
 
 Makefile.am:
 lib_SOURCES += nonblocking.c
--- a/tests/test-fcntl-h.c	Fri Apr 08 08:51:56 2011 -0600
+++ b/tests/test-fcntl-h.c	Fri Apr 08 10:15:54 2011 -0600
@@ -29,10 +29,88 @@
 int sk[] = { SEEK_CUR, SEEK_END, SEEK_SET };
 
 /* Check that the FD_* macros are defined.  */
-int fd = FD_CLOEXEC;
+int i = FD_CLOEXEC;
 
 int
 main (void)
 {
-  return 0;
+  /* Ensure no overlap in SEEK_*. */
+  switch (0)
+    {
+    case SEEK_CUR:
+    case SEEK_END:
+    case SEEK_SET:
+      ;
+    }
+
+  /* Ensure no dangerous overlap in non-zero gnulib-defined replacements.  */
+  switch (O_RDONLY)
+    {
+      /* Access modes */
+    case O_RDONLY:
+    case O_WRONLY:
+    case O_RDWR:
+#if O_EXEC && O_EXEC != O_RDONLY
+    case O_EXEC:
+#endif
+#if O_SEARCH && O_EXEC != O_SEARCH && O_SEARCH != O_RDONLY
+    case O_SEARCH:
+#endif
+      i = O_ACCMODE == (O_RDONLY | O_WRONLY | O_RDWR | O_EXEC | O_SEARCH);
+      break;
+
+      /* Everyone should have these */
+    case O_CREAT:
+    case O_EXCL:
+    case O_TRUNC:
+    case O_APPEND:
+      break;
+
+      /* These might be 0 or O_RDONLY, only test non-zero versions.  */
+#if O_CLOEXEC
+    case O_CLOEXEC:
+#endif
+#if O_DIRECT
+    case O_DIRECT:
+#endif
+#if O_DIRECTORY
+    case O_DIRECTORY:
+#endif
+#if O_DSYNC
+    case O_DSYNC:
+#endif
+#if O_NOATIME
+    case O_NOATIME:
+#endif
+#if O_NONBLOCK
+    case O_NONBLOCK:
+#endif
+#if O_NOCTTY
+    case O_NOCTTY:
+#endif
+#if O_NOFOLLOW
+    case O_NOFOLLOW:
+#endif
+#if O_NOLINKS
+    case O_NOLINKS:
+#endif
+#if O_RSYNC && O_RSYNC != O_DSYNC
+    case O_RSYNC:
+#endif
+#if O_SYNC && O_SYNC != O_RSYNC
+    case O_SYNC:
+#endif
+#if O_TTY_INIT
+    case O_TTY_INIT:
+#endif
+#if O_BINARY
+    case O_BINARY:
+#endif
+#if O_TEXT
+    case O_TEXT:
+#endif
+      ;
+    }
+
+  return !i;
 }
--- a/tests/test-open.h	Fri Apr 08 08:51:56 2011 -0600
+++ b/tests/test-open.h	Fri Apr 08 10:15:54 2011 -0600
@@ -63,6 +63,12 @@
   ASSERT (write (fd, "c", 1) == 1);
   ASSERT (close (fd) == 0);
 
+  /* Although O_NONBLOCK on regular files can be ignored, it must not
+     cause a failure.  */
+  fd = func (BASE "file", O_NONBLOCK | O_RDONLY);
+  ASSERT (0 <= fd);
+  ASSERT (close (fd) == 0);
+
   /* Symlink handling, where supported.  */
   if (symlink (BASE "file", BASE "link") != 0)
     {