Mercurial > hg > octave-kai > gnulib-hg
changeset 12455:dbc90a3fc4ed
fcntl: work around cygwin bug in F_DUPFD
fcntl(0,F_DUPFD,10000000) mistakenly failed with EMFILE
instead of EINVAL, and fcntl(0,F_DUPFD,-1) mistakenly passed.
* m4/fcntl.m4 (gl_REPLACE_FCNTL): New macro.
(gl_FUNC_FCNTL): Use it. Test for F_DUPFD bug.
* lib/fcntl.c (rpl_fcntl) <F_DUPFD>: Work around it.
<F_DUPFD_CLOEXEC>: Reduce calls to _gl_register_dup.
* doc/posix-functions/fcntl.texi (fcntl): Document it.
Signed-off-by: Eric Blake <ebb9@byu.net>
author | Eric Blake <ebb9@byu.net> |
---|---|
date | Tue, 08 Dec 2009 12:10:52 -0700 |
parents | f7624052e60d |
children | f3aceada3c52 |
files | ChangeLog doc/posix-functions/fcntl.texi lib/fcntl.c m4/fcntl.m4 |
diffstat | 4 files changed, 82 insertions(+), 12 deletions(-) [+] |
line wrap: on
line diff
--- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,12 @@ 2009-12-16 Eric Blake <ebb9@byu.net> + fcntl: work around cygwin bug in F_DUPFD + * m4/fcntl.m4 (gl_REPLACE_FCNTL): New macro. + (gl_FUNC_FCNTL): Use it. Test for F_DUPFD bug. + * lib/fcntl.c (rpl_fcntl) <F_DUPFD>: Work around it. + <F_DUPFD_CLOEXEC>: Reduce calls to _gl_register_dup. + * doc/posix-functions/fcntl.texi (fcntl): Document it. + fcntl: support F_DUPFD_CLOEXEC on systems with fcntl * modules/fcntl (Files): List new files. (configure.ac): Run a test.
--- a/doc/posix-functions/fcntl.texi +++ b/doc/posix-functions/fcntl.texi @@ -15,6 +15,11 @@ IRIX 6.5, OSF/1 5.1, Solaris 10, Cygwin 1.7.1, mingw, Interix 3.5, BeOS. Note that the gnulib replacement code is functional but not atomic. + +@item +The @code{F_DUPFD} action of this function does not reject +out-of-range targets properly on some platforms: +Cygwin 1.5.x. @end itemize Portability problems not fixed by Gnulib:
--- a/lib/fcntl.c +++ b/lib/fcntl.c @@ -35,6 +35,10 @@ handles the following actions, and forwards all others on to the native fcntl. + F_DUPFD - duplicate FD, with int ARG being the minimum target fd. + If successful, return the duplicate, which will be inheritable; + otherwise return -1 and set errno. + F_DUPFD_CLOEXEC - duplicate FD, with int ARG being the minimum target fd. If successful, return the duplicate, which will not be inheritable; otherwise return -1 and set errno. */ @@ -47,6 +51,26 @@ va_start (arg, action); switch (action) { + +#if FCNTL_DUPFD_BUGGY || REPLACE_FCHDIR + case F_DUPFD: + { + int target = va_arg (arg, int); + /* Detect invalid target; needed for cygwin 1.5.x. */ + if (target < 0 || getdtablesize () <= target) + errno = EINVAL; + else + { + result = fcntl (fd, action, target); +# if REPLACE_FCHDIR + if (0 <= result) + result = _gl_register_dup (fd, result); +# endif + } + break; + } /* F_DUPFD */ +#endif /* FCNTL_DUPFD_BUGGY || REPLACE_FCHDIR */ + case F_DUPFD_CLOEXEC: { int target = va_arg (arg, int); @@ -63,17 +87,23 @@ { result = fcntl (fd, action, target); if (0 <= result || errno != EINVAL) - have_dupfd_cloexec = 1; + { + have_dupfd_cloexec = 1; +#if REPLACE_FCHDIR + if (0 <= result) + result = _gl_register_dup (fd, result); +#endif + } else { - result = fcntl (fd, F_DUPFD, target); + result = rpl_fcntl (fd, F_DUPFD, target); if (result < 0) break; have_dupfd_cloexec = -1; } } else - result = fcntl (fd, F_DUPFD, target); + result = rpl_fcntl (fd, F_DUPFD, target); if (0 <= result && have_dupfd_cloexec == -1) { int flags = fcntl (result, F_GETFD); @@ -85,10 +115,6 @@ result = -1; } } -#if REPLACE_FCHDIR - if (0 <= result) - result = _gl_register_dup (fd, result); -#endif break; } /* F_DUPFD_CLOEXEC */
--- a/m4/fcntl.m4 +++ b/m4/fcntl.m4 @@ -1,13 +1,12 @@ -# fcntl.m4 serial 1 +# fcntl.m4 serial 2 dnl Copyright (C) 2009 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. # For now, this module ensures that fcntl() +# - supports F_DUPFD correctly # - supports or emulates F_DUPFD_CLOEXEC -# Still to be ported to various platforms: -# - supports F_DUPFD correctly # Still to be ported to mingw: # - F_GETFD, F_SETFD, F_DUPFD # - F_DUPFD_CLOEXEC @@ -19,10 +18,33 @@ dnl Persuade glibc to expose F_DUPFD_CLOEXEC. AC_REQUIRE([gl_USE_SYSTEM_EXTENSIONS]) AC_REQUIRE([gl_FCNTL_H_DEFAULTS]) + AC_REQUIRE([AC_CANONICAL_HOST]) AC_CHECK_FUNCS_ONCE([fcntl]) if test $ac_cv_func_fcntl = no; then HAVE_FCNTL=0 else + dnl cygwin 1.5.x F_DUPFD has wrong errno, and allows negative target + AC_CACHE_CHECK([whether fcntl handles F_DUPFD correctly], + [gl_cv_func_fcntl_f_dupfd_works], + [AC_RUN_IFELSE([AC_LANG_PROGRAM([[ +#include <fcntl.h> +]], [[return fcntl (0, F_DUPFD, -1) != -1; + ]])], + [gl_cv_func_fcntl_f_dupfd_works=yes], + [gl_cv_func_fcntl_f_dupfd_works=no], + [# Guess that it works on glibc systems + case $host_os in #(( + *-gnu*) gl_cv_func_fcntl_f_dupfd_works="guessing yes";; + *) gl_cv_func_fcntl_f_dupfd_works="guessing no";; + esac])]) + case $gl_cv_func_fcntl_f_dupfd_works in + *yes) ;; + *) gl_REPLACE_FCNTL + AC_DEFINE([FCNTL_DUPFD_BUGGY], [1], [Define this to 1 if F_DUPFD + behavior does not match POSIX]) ;; + esac + + dnl Many systems lack F_DUPFD_CLOEXEC AC_CACHE_CHECK([whether fcntl understands F_DUPFD_CLOEXEC], [gl_cv_func_fcntl_f_dupfd_cloexec], [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ @@ -42,8 +64,18 @@ [gl_cv_func_fcntl_f_dupfd_cloexec="needs runtime check"])], [gl_cv_func_fcntl_f_dupfd_cloexec=no])]) if test "$gl_cv_func_fcntl_f_dupfd_cloexec" != yes; then - REPLACE_FCNTL=1 - AC_LIBOBJ([fcntl]) + gl_REPLACE_FCNTL + dnl No witness macro needed for this bug. fi fi ]) + +AC_DEFUN([gl_REPLACE_FCNTL], +[ + AC_REQUIRE([gl_FCNTL_H_DEFAULTS]) + AC_CHECK_FUNCS_ONCE([fcntl]) + if test $ac_cv_func_fcntl = yes; then + REPLACE_FCNTL=1 + AC_LIBOBJ([fcntl]) + fi +])