Mercurial > hg > octave-lyh > gnulib-hg
changeset 12127:bda9467a9d66
fdopendir: fix GNU/Hurd bug
fdopendir(open("file",O_RDONLY)) mistakenly succeeded, with
subsequent readdir() failing with ENOTDIR.
* m4/fdopendir.m4 (gl_FUNC_FDOPENDIR): Check for Hurd bug in
allowing non-directory fds.
* lib/fdopendir.c (rpl_fdopendir): Work around it.
* m4/dirent_h.m4 (gl_DIRENT_H_DEFAULTS): New witness.
* modules/dirent (Makefile.am): Substitute it.
* lib/dirent.in.h (fdopendir): Declare replacement.
* doc/posix-functions/fdopendir.texi (fdopendir): Document this.
* tests/test-fdopendir.c (main): Test something other than
/dev/null, since on Hurd that behaves like a directory.
Signed-off-by: Eric Blake <ebb9@byu.net>
author | Eric Blake <ebb9@byu.net> |
---|---|
date | Tue, 06 Oct 2009 06:58:08 -0600 |
parents | 6489be573ae5 |
children | a92e67f6c6f1 |
files | ChangeLog doc/posix-functions/fdopendir.texi lib/dirent.in.h lib/fdopendir.c m4/dirent_h.m4 m4/fdopendir.m4 modules/dirent tests/test-fdopendir.c |
diffstat | 8 files changed, 90 insertions(+), 24 deletions(-) [+] |
line wrap: on
line diff
--- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,16 @@ 2009-10-06 Eric Blake <ebb9@byu.net> + fdopendir: fix GNU/Hurd bug + * m4/fdopendir.m4 (gl_FUNC_FDOPENDIR): Check for Hurd bug in + allowing non-directory fds. + * lib/fdopendir.c (rpl_fdopendir): Work around it. + * m4/dirent_h.m4 (gl_DIRENT_H_DEFAULTS): New witness. + * modules/dirent (Makefile.am): Substitute it. + * lib/dirent.in.h (fdopendir): Declare replacement. + * doc/posix-functions/fdopendir.texi (fdopendir): Document this. + * tests/test-fdopendir.c (main): Test something other than + /dev/null, since on Hurd that behaves like a directory. + test-symlink: port to GNU/Hurd * tests/test-symlink.h (test_symlink): Relax expected errno.
--- a/doc/posix-functions/fdopendir.texi +++ b/doc/posix-functions/fdopendir.texi @@ -16,6 +16,10 @@ is not multithread-safe. Also, the replacement does not guarantee that @samp{dirfd(fdopendir(n))==n} (dirfd might fail, or return a different file descriptor than n). +@item +This function does not reject non-directory file descriptors on some +platforms: +GNU/Hurd. @end itemize Portability problems not fixed by Gnulib:
--- a/lib/dirent.in.h +++ b/lib/dirent.in.h @@ -55,7 +55,11 @@ #endif #if @GNULIB_FDOPENDIR@ -# if !@HAVE_FDOPENDIR@ +# if @REPLACE_FDOPENDIR@ +# undef fdopendir +# define fdopendir rpl_fdopendir +# endif +# if !@HAVE_FDOPENDIR@ || @REPLACE_FDOPENDIR@ /* Open a directory stream visiting the given directory file descriptor. Return NULL and set errno if fd is not visiting a directory. On success, this function consumes fd (it will be
--- a/lib/fdopendir.c +++ b/lib/fdopendir.c @@ -23,13 +23,15 @@ #include <stdlib.h> #include <unistd.h> -#include "openat.h" -#include "openat-priv.h" -#include "save-cwd.h" +#if !HAVE_FDOPENDIR -#if GNULIB_DIRENT_SAFER -# include "dirent--.h" -#endif +# include "openat.h" +# include "openat-priv.h" +# include "save-cwd.h" + +# if GNULIB_DIRENT_SAFER +# include "dirent--.h" +# endif /* Replacement for Solaris' function by the same name. <http://www.google.com/search?q=fdopendir+site:docs.sun.com> @@ -70,12 +72,12 @@ save_cwd/restore_cwd. */ if (! dir && EXPECTED_ERRNO (saved_errno)) { -#if REPLACE_FCHDIR +# if REPLACE_FCHDIR const char *name = _gl_directory_name (fd); if (name) dir = opendir (name); saved_errno = errno; -#else /* !REPLACE_FCHDIR */ +# else /* !REPLACE_FCHDIR */ struct saved_cwd saved_cwd; if (save_cwd (&saved_cwd) != 0) openat_save_fail (errno); @@ -95,7 +97,7 @@ } free_cwd (&saved_cwd); -#endif /* !REPLACE_FCHDIR */ +# endif /* !REPLACE_FCHDIR */ } if (dir) @@ -105,3 +107,28 @@ errno = saved_errno; return dir; } + +#else /* HAVE_FDOPENDIR */ + +# include <errno.h> +# include <sys/stat.h> + +# undef fdopendir + +/* Like fdopendir, but work around GNU/Hurd bug by validating FD. */ + +DIR * +rpl_fdopendir (int fd) +{ + struct stat st; + if (fstat (fd, &st)) + return NULL; + if (!S_ISDIR (st.st_mode)) + { + errno = ENOTDIR; + return NULL; + } + return fdopendir (fd); +} + +#endif /* HAVE_FDOPENDIR */
--- a/m4/dirent_h.m4 +++ b/m4/dirent_h.m4 @@ -1,4 +1,4 @@ -# dirent_h.m4 serial 5 +# dirent_h.m4 serial 6 dnl Copyright (C) 2008-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, @@ -32,16 +32,17 @@ AC_DEFUN([gl_DIRENT_H_DEFAULTS], [ AC_REQUIRE([gl_UNISTD_H_DEFAULTS]) dnl for REPLACE_FCHDIR - GNULIB_DIRFD=0; AC_SUBST([GNULIB_DIRFD]) - GNULIB_FDOPENDIR=0; AC_SUBST([GNULIB_FDOPENDIR]) - GNULIB_SCANDIR=0; AC_SUBST([GNULIB_SCANDIR]) - GNULIB_ALPHASORT=0; AC_SUBST([GNULIB_ALPHASORT]) + GNULIB_DIRFD=0; AC_SUBST([GNULIB_DIRFD]) + GNULIB_FDOPENDIR=0; AC_SUBST([GNULIB_FDOPENDIR]) + GNULIB_SCANDIR=0; AC_SUBST([GNULIB_SCANDIR]) + GNULIB_ALPHASORT=0; AC_SUBST([GNULIB_ALPHASORT]) dnl Assume proper GNU behavior unless another module says otherwise. - HAVE_DECL_DIRFD=1; AC_SUBST([HAVE_DECL_DIRFD]) - HAVE_FDOPENDIR=1; AC_SUBST([HAVE_FDOPENDIR]) - HAVE_SCANDIR=1; AC_SUBST([HAVE_SCANDIR]) - HAVE_ALPHASORT=1; AC_SUBST([HAVE_ALPHASORT]) - REPLACE_CLOSEDIR=0; AC_SUBST([REPLACE_CLOSEDIR]) - REPLACE_OPENDIR=0; AC_SUBST([REPLACE_OPENDIR]) - DIRENT_H=''; AC_SUBST([DIRENT_H]) + HAVE_DECL_DIRFD=1; AC_SUBST([HAVE_DECL_DIRFD]) + HAVE_FDOPENDIR=1; AC_SUBST([HAVE_FDOPENDIR]) + HAVE_SCANDIR=1; AC_SUBST([HAVE_SCANDIR]) + HAVE_ALPHASORT=1; AC_SUBST([HAVE_ALPHASORT]) + REPLACE_CLOSEDIR=0; AC_SUBST([REPLACE_CLOSEDIR]) + REPLACE_FDOPENDIR=0; AC_SUBST([REPLACE_FDOPENDIR]) + REPLACE_OPENDIR=0; AC_SUBST([REPLACE_OPENDIR]) + DIRENT_H=''; AC_SUBST([DIRENT_H]) ])
--- a/m4/fdopendir.m4 +++ b/m4/fdopendir.m4 @@ -1,4 +1,4 @@ -# serial 1 +# serial 2 # See if we need to provide fdopendir. dnl Copyright (C) 2009 Free Software Foundation, Inc. @@ -17,5 +17,22 @@ AC_LIBOBJ([fdopendir]) gl_REPLACE_DIRENT_H HAVE_FDOPENDIR=0 + else + AC_CACHE_CHECK([whether fdopendir works], + [gl_cv_func_fdopendir_works], + [AC_RUN_IFELSE([AC_LANG_PROGRAM([[ +#include <dirent.h> +#include <fcntl.h> +]], [int fd = open ("conftest.h", O_RDONLY); + if (fd < 0) return 2; + return !!fdopendir (fd);])], + [gl_cv_func_fdopendir_works=yes], + [gl_cv_func_fdopendir_works=no], + [gl_cv_func_fdopendir_works="guessing no"])]) + if test "$gl_cv_func_fdopendir_works" != yes; then + REPLACE_FDOPENDIR=1 + gl_REPLACE_DIRENT_H + AC_LIBOBJ([fdopendir]) + fi fi ])
--- a/modules/dirent +++ b/modules/dirent @@ -33,6 +33,7 @@ -e 's|@''HAVE_SCANDIR''@|$(HAVE_SCANDIR)|g' \ -e 's|@''HAVE_ALPHASORT''@|$(HAVE_ALPHASORT)|g' \ -e 's|@''REPLACE_CLOSEDIR''@|$(REPLACE_CLOSEDIR)|g' \ + -e 's|@''REPLACE_FDOPENDIR''@|$(REPLACE_FDOPENDIR)|g' \ -e 's|@''REPLACE_OPENDIR''@|$(REPLACE_OPENDIR)|g' \ -e '/definition of GL_LINK_WARNING/r $(LINK_WARNING_H)' \ < $(srcdir)/dirent.in.h; \
--- a/tests/test-fdopendir.c +++ b/tests/test-fdopendir.c @@ -45,12 +45,13 @@ int fd; /* A non-directory cannot be turned into a directory stream. */ - fd = open ("/dev/null", O_RDONLY); + fd = open ("test-fdopendir.tmp", O_RDONLY | O_CREAT, 0600); ASSERT (0 <= fd); errno = 0; ASSERT (fdopendir (fd) == NULL); ASSERT (errno == ENOTDIR); ASSERT (close (fd) == 0); + ASSERT (unlink ("test-fdopendir.tmp") == 0); /* A bad fd cannot be turned into a stream. */ errno = 0;