bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH 1/4] nonblocking: provide O_NONBLOCK for mingw


From: Eric Blake
Subject: [PATCH 1/4] nonblocking: provide O_NONBLOCK for mingw
Date: Fri, 8 Apr 2011 11:33:00 -0600

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 <address@hidden>
---
 ChangeLog                    |   13 +++++++
 doc/posix-headers/fcntl.texi |    9 ++++-
 lib/fcntl.in.h               |   13 ++++++-
 lib/nonblocking.c            |    2 +-
 lib/open.c                   |    9 +++++
 m4/fcntl_h.m4                |   17 +++++----
 modules/fcntl-h              |    1 +
 modules/nonblocking          |    2 +
 tests/test-fcntl-h.c         |   82 ++++++++++++++++++++++++++++++++++++++++-
 tests/test-open.h            |    6 +++
 10 files changed, 139 insertions(+), 15 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 2c887a6..1af3b71 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,18 @@
 2011-04-08  Eric Blake  <address@hidden>

+       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.
diff --git a/doc/posix-headers/fcntl.texi b/doc/posix-headers/fcntl.texi
index 1b64195..29b61ec 100644
--- a/doc/posix-headers/fcntl.texi
+++ b/doc/posix-headers/fcntl.texi
@@ -9,9 +9,14 @@ fcntl.h
 @itemize
 @item
 @samp{O_CLOEXEC}, @samp{O_DIRECTORY}, @samp{O_DSYNC}, @samp{O_NOCTTY},
address@hidden, @samp{O_NONBLOCK}, @samp{O_RSYNC}, @samp{O_SYNC},
address@hidden, @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.
+
address@hidden
address@hidden is not defined on some platforms.  If the
address@hidden 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.
diff --git a/lib/fcntl.in.h b/lib/fcntl.in.h
index 18cac45..b6521d6 100644
--- a/lib/fcntl.in.h
+++ b/lib/fcntl.in.h
@@ -182,8 +182,7 @@ _GL_WARN_ON_USE (openat, "openat is not portable - "
 #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 @@ _GL_WARN_ON_USE (openat, "openat is not portable - "
 # 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
diff --git a/lib/nonblocking.c b/lib/nonblocking.c
index f28e423..9f7bce9 100644
--- a/lib/nonblocking.c
+++ b/lib/nonblocking.c
@@ -113,7 +113,7 @@ set_nonblocking_flag (int desc, bool value)

 # include <fcntl.h>

-# if !O_NONBLOCK
+# if GNULIB_defined_O_NONBLOCK
 #  error Please port nonblocking to your platform
 # endif

diff --git a/lib/open.c b/lib/open.c
index 2e2cc74..e60b619 100644
--- a/lib/open.c
+++ b/lib/open.c
@@ -63,6 +63,15 @@ open (const char *filename, int flags, ...)
       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";
diff --git a/m4/fcntl_h.m4 b/m4/fcntl_h.m4
index 1ef4f45..c466da4 100644
--- a/m4/fcntl_h.m4
+++ b/m4/fcntl_h.m4
@@ -31,13 +31,14 @@ AC_DEFUN([gl_FCNTL_MODULE_INDICATOR],

 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])
 ])
diff --git a/modules/fcntl-h b/modules/fcntl-h
index 054d15f..45593f6 100644
--- a/modules/fcntl-h
+++ b/modules/fcntl-h
@@ -30,6 +30,7 @@ fcntl.h: fcntl.in.h $(top_builddir)/config.status 
$(CXXDEFS_H) $(ARG_NONNULL_H)
              -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' \
diff --git a/modules/nonblocking b/modules/nonblocking
index 9528405..604cc47 100644
--- a/modules/nonblocking
+++ b/modules/nonblocking
@@ -8,10 +8,12 @@ lib/nonblocking.h
 Depends-on:
 fcntl-h
 ioctl
+open
 stdbool
 sys_socket

 configure.ac:
+gl_FCNTL_MODULE_INDICATOR([nonblocking])

 Makefile.am:
 lib_SOURCES += nonblocking.c
diff --git a/tests/test-fcntl-h.c b/tests/test-fcntl-h.c
index dd20fbb..648701e 100644
--- a/tests/test-fcntl-h.c
+++ b/tests/test-fcntl-h.c
@@ -29,10 +29,88 @@ int o = O_DIRECT | O_DIRECTORY | O_DSYNC | O_NDELAY | 
O_NOATIME | O_NONBLOCK
 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;
 }
diff --git a/tests/test-open.h b/tests/test-open.h
index 3e5c5e1..2ba5d13 100644
--- a/tests/test-open.h
+++ b/tests/test-open.h
@@ -63,6 +63,12 @@ test_open (int (*func) (char const *, int, ...), bool print)
   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)
     {
-- 
1.7.4.2




reply via email to

[Prev in Thread] Current Thread [Next in Thread]