summaryrefslogtreecommitdiff
path: root/lib/fdopendir.c
diff options
context:
space:
mode:
authorEric Blake <ebb9@byu.net>2009-10-06 06:58:08 -0600
committerEric Blake <ebb9@byu.net>2009-10-06 22:06:49 -0600
commitdfbec8be94ca116ce40c04f88302329505dbb745 (patch)
treee25ce6c31551b711f784d927aa215860370c4d04 /lib/fdopendir.c
parent48b0feac54dce2caf46cc53dd160e699737ff52a (diff)
downloadgnulib-dfbec8be94ca116ce40c04f88302329505dbb745.tar.gz
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>
Diffstat (limited to 'lib/fdopendir.c')
-rw-r--r--lib/fdopendir.c45
1 files changed, 36 insertions, 9 deletions
diff --git a/lib/fdopendir.c b/lib/fdopendir.c
index 14dc111c81..c364306630 100644
--- 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 @@ fdopendir (int fd)
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 @@ fdopendir (int fd)
}
free_cwd (&saved_cwd);
-#endif /* !REPLACE_FCHDIR */
+# endif /* !REPLACE_FCHDIR */
}
if (dir)
@@ -105,3 +107,28 @@ fdopendir (int fd)
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 */