Mercurial > hg > octave-nkf > gnulib-hg
changeset 11934:80567a8f98f8
fdopendir: split into its own module
* lib/openat.c (fdopendir): Move...
* lib/fdopendir.c: ...into new file.
* modules/fdopendir: New module.
* m4/fdopendir.m4 (gl_FUNC_FDOPENDIR): New file.
* modules/openat (Depends-on): Add fdopendir.
* m4/openat.m4 (gl_FUNC_OPENAT): No longer need to check for
fdopendir here.
* modules/savedir (Depends-on): Only need fdopendir, not full
openat.
* lib/savedir.c (include): Use <dirent.h>, not "openat.h".
* lib/openat.h (fdopendir): Drop prototype.
* lib/dirent.in.h (fdopendir): Provide prototype.
* m4/dirent_h.m4 (gl_DIRENT_H_DEFAULTS): Add replacements.
* modules/dirent (Makefile.am): Substitute them.
* MODULES.html.sh (File system functions): Mention it.
* doc/posix-functions/fdopendir.texi (fdopendir): Likewise.
* modules/fdopendir-tests: New file.
* tests/test-fdopendir.c: Likewise.
Signed-off-by: Eric Blake <ebb9@byu.net>
author | Eric Blake <ebb9@byu.net> |
---|---|
date | Mon, 31 Aug 2009 20:37:59 -0600 |
parents | 1ffad224c413 |
children | d233b3d8efbf |
files | ChangeLog MODULES.html.sh doc/posix-functions/fdopendir.texi lib/dirent.in.h lib/fdopendir.c lib/openat.c lib/openat.h lib/savedir.c m4/dirent_h.m4 m4/fdopendir.m4 m4/openat.m4 modules/dirent modules/fdopendir modules/fdopendir-tests modules/openat modules/savedir tests/test-fdopendir.c |
diffstat | 17 files changed, 291 insertions(+), 84 deletions(-) [+] |
line wrap: on
line diff
--- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,25 @@ 2009-09-02 Eric Blake <ebb9@byu.net> + fdopendir: split into its own module + * lib/openat.c (fdopendir): Move... + * lib/fdopendir.c: ...into new file. + * modules/fdopendir: New module. + * m4/fdopendir.m4 (gl_FUNC_FDOPENDIR): New file. + * modules/openat (Depends-on): Add fdopendir. + * m4/openat.m4 (gl_FUNC_OPENAT): No longer need to check for + fdopendir here. + * modules/savedir (Depends-on): Only need fdopendir, not full + openat. + * lib/savedir.c (include): Use <dirent.h>, not "openat.h". + * lib/openat.h (fdopendir): Drop prototype. + * lib/dirent.in.h (fdopendir): Provide prototype. + * m4/dirent_h.m4 (gl_DIRENT_H_DEFAULTS): Add replacements. + * modules/dirent (Makefile.am): Substitute them. + * MODULES.html.sh (File system functions): Mention it. + * doc/posix-functions/fdopendir.texi (fdopendir): Likewise. + * modules/fdopendir-tests: New file. + * tests/test-fdopendir.c: Likewise. + fchdir: use more consistent macro convention * lib/fcntl.in.h (_gl_register_fd): Move declaration to unistd. * lib/sys_stat.in.h (rpl_fstat): Declare via make-time
--- a/MODULES.html.sh +++ b/MODULES.html.sh @@ -2451,6 +2451,7 @@ func_module dirfd func_module double-slash-root func_module euidaccess + func_module fdopendir func_module file-type func_module fileblocks func_module filemode
--- a/doc/posix-functions/fdopendir.texi +++ b/doc/posix-functions/fdopendir.texi @@ -4,7 +4,7 @@ POSIX specification: @url{http://www.opengroup.org/onlinepubs/9699919799/functions/fdopendir.html} -Gnulib module: openat +Gnulib module: fdopendir Portability problems fixed by Gnulib: @itemize @@ -12,7 +12,10 @@ This function is missing on some platforms: glibc 2.3.6, MacOS X 10.3, FreeBSD 6.0, NetBSD 3.0, OpenBSD 3.8, AIX 5.1, HP-UX 11, IRIX 6.5, OSF/1 5.1, Cygwin 1.5.x, mingw, Interix 3.5, BeOS. -But the replacement function is not safe to be used in libraries and is not multithread-safe. +But the replacement function is not safe to be used in libraries and +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). @end itemize Portability problems not fixed by Gnulib:
--- a/lib/dirent.in.h +++ b/lib/dirent.in.h @@ -58,6 +58,23 @@ dirfd (d)) #endif +#if @GNULIB_FDOPENDIR@ +# if !@HAVE_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 + implicitly closed either by this function or by a subsequent + closedir). */ +extern DIR *fdopendir (int fd); +# endif +#elif defined GNULIB_POSIXCHECK +# undef fdopendir +# define fdopendir(f) \ + (GL_LINK_WARNING ("fdopendir is unportable - " \ + "use gnulib module fdopendir for portability"), \ + fdopendir (f)) +#endif + #if @GNULIB_SCANDIR@ /* Scan the directory DIR, calling FILTER on each directory entry. Entries for which FILTER returns nonzero are individually malloc'd,
new file mode 100644 --- /dev/null +++ b/lib/fdopendir.c @@ -0,0 +1,95 @@ +/* provide a replacement fdopendir function + Copyright (C) 2004-2009 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +/* written by Jim Meyering */ + +#include <config.h> + +#include <dirent.h> + +#include <stdlib.h> +#include <unistd.h> + +#include "openat.h" +#include "openat-priv.h" +#include "save-cwd.h" + +/* Replacement for Solaris' function by the same name. + <http://www.google.com/search?q=fdopendir+site:docs.sun.com> + First, try to simulate it via opendir ("/proc/self/fd/FD"). Failing + that, simulate it by doing save_cwd/fchdir/opendir(".")/restore_cwd. + If either the save_cwd or the restore_cwd fails (relatively unlikely), + then give a diagnostic and exit nonzero. + Otherwise, this function works just like Solaris' fdopendir. + + W A R N I N G: + Unlike other fd-related functions, this one effectively consumes + its FD parameter. The caller should not close or otherwise + manipulate FD if this function returns successfully. Also, this + implementation does not guarantee that dirfd(fdopendir(n))==n; + the open directory stream may use a clone of FD, or have no + associated fd at all. */ +DIR * +fdopendir (int fd) +{ + struct saved_cwd saved_cwd; + int saved_errno; + DIR *dir; + + char buf[OPENAT_BUFFER_SIZE]; + char *proc_file = openat_proc_name (buf, fd, "."); + if (proc_file) + { + dir = opendir (proc_file); + saved_errno = errno; + } + else + { + dir = NULL; + saved_errno = EOPNOTSUPP; + } + + /* If the syscall fails with an expected errno value, resort to + save_cwd/restore_cwd. */ + if (! dir && EXPECTED_ERRNO (saved_errno)) + { + if (save_cwd (&saved_cwd) != 0) + openat_save_fail (errno); + + if (fchdir (fd) != 0) + { + dir = NULL; + saved_errno = errno; + } + else + { + dir = opendir ("."); + saved_errno = errno; + + if (restore_cwd (&saved_cwd) != 0) + openat_restore_fail (errno); + } + + free_cwd (&saved_cwd); + } + + if (dir) + close (fd); + if (proc_file != buf) + free (proc_file); + errno = saved_errno; + return dir; +}
--- a/lib/openat.c +++ b/lib/openat.c @@ -152,74 +152,6 @@ return needs_fchdir; } -#if !HAVE_FDOPENDIR - -/* Replacement for Solaris' function by the same name. - <http://www.google.com/search?q=fdopendir+site:docs.sun.com> - First, try to simulate it via opendir ("/proc/self/fd/FD"). Failing - that, simulate it by doing save_cwd/fchdir/opendir(".")/restore_cwd. - If either the save_cwd or the restore_cwd fails (relatively unlikely), - then give a diagnostic and exit nonzero. - Otherwise, this function works just like Solaris' fdopendir. - - W A R N I N G: - Unlike the other fd-related functions here, this one - effectively consumes its FD parameter. The caller should not - close or otherwise manipulate FD if this function returns successfully. */ -DIR * -fdopendir (int fd) -{ - struct saved_cwd saved_cwd; - int saved_errno; - DIR *dir; - - char buf[OPENAT_BUFFER_SIZE]; - char *proc_file = openat_proc_name (buf, fd, "."); - if (proc_file) - { - dir = opendir (proc_file); - saved_errno = errno; - } - else - { - dir = NULL; - saved_errno = EOPNOTSUPP; - } - - /* If the syscall fails with an expected errno value, resort to - save_cwd/restore_cwd. */ - if (! dir && EXPECTED_ERRNO (saved_errno)) - { - if (save_cwd (&saved_cwd) != 0) - openat_save_fail (errno); - - if (fchdir (fd) != 0) - { - dir = NULL; - saved_errno = errno; - } - else - { - dir = opendir ("."); - saved_errno = errno; - - if (restore_cwd (&saved_cwd) != 0) - openat_restore_fail (errno); - } - - free_cwd (&saved_cwd); - } - - if (dir) - close (fd); - if (proc_file != buf) - free (proc_file); - errno = saved_errno; - return dir; -} - -#endif - /* Replacement for Solaris' function by the same name. <http://www.google.com/search?q=fstatat+site:docs.sun.com> First, try to simulate it via l?stat ("/proc/self/fd/FD/FILE").
--- a/lib/openat.h +++ b/lib/openat.h @@ -1,5 +1,5 @@ /* provide a replacement openat function - Copyright (C) 2004, 2005, 2006, 2008 Free Software Foundation, Inc. + Copyright (C) 2004-2006, 2008-2009 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -66,10 +66,6 @@ int openat (int fd, char const *file, int flags, /* mode_t mode */ ...); int openat_permissive (int fd, char const *file, int flags, mode_t mode, int *cwd_errno); -# if ! HAVE_FDOPENDIR -# define fdopendir __OPENAT_ID (fdopendir) -# endif -DIR *fdopendir (int fd); # define fstatat __OPENAT_ID (fstatat) int fstatat (int fd, char const *file, struct stat *st, int flag); # define unlinkat __OPENAT_ID (unlinkat)
--- a/lib/savedir.c +++ b/lib/savedir.c @@ -1,7 +1,7 @@ /* savedir.c -- save the list of files in a directory in a string Copyright (C) 1990, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, - 2006 Free Software Foundation, Inc. + 2006, 2009 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -35,7 +35,6 @@ #include <stdlib.h> #include <string.h> -#include "openat.h" #include "xalloc.h" #ifndef NAME_SIZE_DEFAULT
--- a/m4/dirent_h.m4 +++ b/m4/dirent_h.m4 @@ -33,11 +33,13 @@ [ 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]) dnl Assume proper GNU behavior unless another module says otherwise. - HAVE_DECL_DIRFD=1; AC_SUBST([HAVE_DECL_DIRFD]) - HAVE_SCANDIR=1; AC_SUBST([HAVE_SCANDIR]) - HAVE_ALPHASORT=1; AC_SUBST([HAVE_ALPHASORT]) - 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]) + DIRENT_H=''; AC_SUBST([DIRENT_H]) ])
new file mode 100644 --- /dev/null +++ b/m4/fdopendir.m4 @@ -0,0 +1,21 @@ +# serial 1 +# See if we need to provide fdopendir. + +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. + +# Written by Eric Blake. + +AC_DEFUN([gl_FUNC_FDOPENDIR], +[ + AC_REQUIRE([gl_USE_SYSTEM_EXTENSIONS]) + AC_CHECK_FUNCS_ONCE([fdopendir]) + if test $ac_cv_func_fdopendir = no; then + AC_LIBOBJ([openat-proc]) + AC_LIBOBJ([fdopendir]) + gl_REPLACE_DIRENT_H + HAVE_FDOPENDIR=0 + fi +])
--- a/m4/openat.m4 +++ b/m4/openat.m4 @@ -1,4 +1,4 @@ -# serial 18 +# serial 19 # See if we need to use our replacement for Solaris' openat et al functions. dnl Copyright (C) 2004-2009 Free Software Foundation, Inc. @@ -13,7 +13,6 @@ AC_LIBOBJ([openat-proc]) AC_REQUIRE([gl_USE_SYSTEM_EXTENSIONS]) AC_CHECK_FUNCS_ONCE([lchmod]) - AC_CHECK_FUNCS_ONCE([fdopendir]) AC_REPLACE_FUNCS([fchmodat mkdirat openat]) AC_REQUIRE([AC_FUNC_LSTAT_FOLLOWS_SLASHED_SYMLINK]) case $ac_cv_func_openat+$ac_cv_func_lstat_dereferences_slashed_symlink in
--- a/modules/dirent +++ b/modules/dirent @@ -25,9 +25,11 @@ -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ -e 's|@''NEXT_DIRENT_H''@|$(NEXT_DIRENT_H)|g' \ -e 's|@''GNULIB_DIRFD''@|$(GNULIB_DIRFD)|g' \ + -e 's|@''GNULIB_FDOPENDIR''@|$(GNULIB_FDOPENDIR)|g' \ -e 's|@''GNULIB_SCANDIR''@|$(GNULIB_SCANDIR)|g' \ -e 's|@''GNULIB_ALPHASORT''@|$(GNULIB_ALPHASORT)|g' \ -e 's|@''HAVE_DECL_DIRFD''@|$(HAVE_DECL_DIRFD)|g' \ + -e 's|@''HAVE_FDOPENDIR''@|$(HAVE_FDOPENDIR)|g' \ -e 's|@''HAVE_SCANDIR''@|$(HAVE_SCANDIR)|g' \ -e 's|@''HAVE_ALPHASORT''@|$(HAVE_ALPHASORT)|g' \ -e 's|@''REPLACE_FCHDIR''@|$(REPLACE_FCHDIR)|g' \
new file mode 100644 --- /dev/null +++ b/modules/fdopendir @@ -0,0 +1,30 @@ +Description: +Open a directory stream from a file descriptor. + +Files: +lib/fdopendir.c +lib/openat-priv.h +lib/openat-proc.c +m4/fdopendir.m4 + +Depends-on: +extensions +dirent +fchdir +openat-die +save-cwd + +configure.ac: +gl_FUNC_FDOPENDIR +gl_DIRENT_MODULE_INDICATOR([fdopendir]) + +Makefile.am: + +Include: +<dirent.h> + +License: +GPL + +Maintainer: +Jim Meyering, Eric Blake
new file mode 100644 --- /dev/null +++ b/modules/fdopendir-tests @@ -0,0 +1,13 @@ +Files: +tests/test-fdopendir.c + +Depends-on: +open +progname + +configure.ac: + +Makefile.am: +TESTS += test-fdopendir +check_PROGRAMS += test-fdopendir +test_fdopendir_LDADD = $(LDADD) @LIBINTL@
--- a/modules/openat +++ b/modules/openat @@ -18,6 +18,7 @@ dirname extensions fchdir +fdopendir gettext-h intprops lchown
--- a/modules/savedir +++ b/modules/savedir @@ -7,7 +7,7 @@ m4/savedir.m4 Depends-on: -openat +fdopendir xalloc configure.ac:
new file mode 100644 --- /dev/null +++ b/tests/test-fdopendir.c @@ -0,0 +1,76 @@ +/* Test opening a directory stream from a file descriptor. + Copyright (C) 2009 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +/* Written by Eric Blake <ebb9@byu.net>, 2009. */ + +#include <config.h> + +#include <dirent.h> + +#include <errno.h> +#include <fcntl.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> + +#define ASSERT(expr) \ + do \ + { \ + if (!(expr)) \ + { \ + fprintf (stderr, "%s:%d: assertion failed\n", __FILE__, __LINE__); \ + fflush (stderr); \ + abort (); \ + } \ + } \ + while (0) + +int +main () +{ + DIR *d; + int fd; + + /* A non-directory cannot be turned into a directory stream. */ + fd = open ("/dev/null", O_RDONLY); + ASSERT (0 <= fd); + errno = 0; + ASSERT (fdopendir (fd) == NULL); + ASSERT (errno == ENOTDIR); + ASSERT (close (fd) == 0); + + /* A bad fd cannot be turned into a stream. */ + errno = 0; + ASSERT (fdopendir (-1) == NULL); + ASSERT (errno == EBADF); + + /* This should work. */ + fd = open (".", O_RDONLY); + ASSERT (0 <= fd); + d = fdopendir (fd); + /* We know that fd is now out of our reach, but it is not specified + whether it is closed now or at the closedir. We also can't + guarantee whether dirfd returns fd, some other descriptor, or + -1. */ + ASSERT (d); + ASSERT (closedir (d) == 0); + /* Now we can guarantee that fd must be closed. */ + errno = 0; + ASSERT (dup2 (fd, fd) == -1); + ASSERT (errno == EBADF); + + return 0; +}