[Top][All Lists]
[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