Mercurial > hg > octave-nkf > gnulib-hg
changeset 11936:a126d5b22410
dirent-safer: new module
* modules/dirent-safer: New file.
* lib/dirent--.h: Likewise.
* lib/dirent-safer.h: Likewise.
* lib/opendir-safer.c: Likewise.
* m4/dirent-safer.m4: Likewise.
* MODULES.html.sh (Enhancements for POSIX:2008): Mention it.
* modules/dirent-safer-tests: New test.
* tests/test-dirent-safer.c: New file.
* lib/fdopendir.c (includes): Ensure fdopendir is also safe.
Signed-off-by: Eric Blake <ebb9@byu.net>
author | Eric Blake <ebb9@byu.net> |
---|---|
date | Tue, 01 Sep 2009 07:41:28 -0600 |
parents | d233b3d8efbf |
children | ded3ad24a7f4 |
files | ChangeLog MODULES.html.sh lib/dirent--.h lib/dirent-safer.h lib/fdopendir.c lib/opendir-safer.c m4/dirent-safer.m4 modules/dirent-safer modules/dirent-safer-tests tests/test-dirent-safer.c |
diffstat | 10 files changed, 285 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,16 @@ 2009-09-02 Eric Blake <ebb9@byu.net> + dirent-safer: new module + * modules/dirent-safer: New file. + * lib/dirent--.h: Likewise. + * lib/dirent-safer.h: Likewise. + * lib/opendir-safer.c: Likewise. + * m4/dirent-safer.m4: Likewise. + * MODULES.html.sh (Enhancements for POSIX:2008): Mention it. + * modules/dirent-safer-tests: New test. + * tests/test-dirent-safer.c: New file. + * lib/fdopendir.c (includes): Ensure fdopendir is also safe. + fdopendir: optimize on mingw * lib/unistd.in.h (_gl_directory_name): New prototype. * lib/fchdir.c (_gl_directory_name): Implement it.
--- a/MODULES.html.sh +++ b/MODULES.html.sh @@ -2394,6 +2394,7 @@ func_begin_table func_module chdir-long + func_module dirent-safer func_module dirname func_module getopt func_module iconv_open-utf
new file mode 100644 --- /dev/null +++ b/lib/dirent--.h @@ -0,0 +1,23 @@ +/* Like dirent.h, but redefine some names to avoid glitches. + + 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. */ + +#include "dirent-safer.h" + +#undef opendir +#define opendir opendir_safer
new file mode 100644 --- /dev/null +++ b/lib/dirent-safer.h @@ -0,0 +1,22 @@ +/* Invoke dirent-like functions, but avoid some glitches. + + 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. */ + +#include <dirent.h> + +DIR *opendir_safer (const char *name);
--- a/lib/fdopendir.c +++ b/lib/fdopendir.c @@ -27,6 +27,10 @@ #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> First, try to simulate it via opendir ("/proc/self/fd/FD"). Failing
new file mode 100644 --- /dev/null +++ b/lib/opendir-safer.c @@ -0,0 +1,68 @@ +/* Invoke opendir, but avoid some glitches. + + 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. */ + +#include <config.h> + +#include "dirent-safer.h" + +#include <errno.h> +#include <unistd.h> +#include "unistd-safer.h" + +/* Like opendir, but do not clobber stdin, stdout, or stderr. */ + +DIR * +opendir_safer (char const *name) +{ + DIR *dp = opendir (name); + + if (dp) + { + int fd = dirfd (dp); + + if (0 <= fd && fd <= STDERR_FILENO) + { + /* If fdopendir is native (as on Linux), then it is safe to + assume dirfd(fdopendir(n))==n. If we are using the + gnulib module fdopendir, then this guarantee is not met, + but fdopendir recursively calls opendir_safer up to 3 + times to at least get a safe fd. If fdopendir is not + present but dirfd is accurate (as on cygwin 1.5.x), then + we recurse up to 3 times ourselves. Finally, if dirfd + always fails (as on mingw), then we are already safe. */ + DIR *newdp; + int e; +#if HAVE_FDOPENDIR || GNULIB_FDOPENDIR + int f = dup_safer (fd); + newdp = fdopendir (f); + e = errno; + if (! newdp) + close (f); +#else /* !FDOPENDIR */ + newdp = opendir_safer (name); + e = errno; +#endif + closedir (dp); + errno = e; + dp = newdp; + } + } + + return dp; +}
new file mode 100644 --- /dev/null +++ b/m4/dirent-safer.m4 @@ -0,0 +1,11 @@ +#serial 1 +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. + +AC_DEFUN([gl_DIRENT_SAFER], +[ + AC_CHECK_FUNCS_ONCE([fdopendir]) + AC_LIBOBJ([opendir-safer]) +])
new file mode 100644 --- /dev/null +++ b/modules/dirent-safer @@ -0,0 +1,28 @@ +Description: +Directory functions that avoid clobbering STD{IN,OUT,ERR}_FILENO. + +Files: +lib/dirent--.h +lib/dirent-safer.h +lib/opendir-safer.c +m4/dirent-safer.m4 + +Depends-on: +dirent +dirfd +unistd-safer + +configure.ac: +gl_DIRENT_SAFER +gl_MODULE_INDICATOR([dirent-safer]) + +Makefile.am: + +Include: +"dirent-safer.h" + +License: +GPL + +Maintainer: +Eric Blake
new file mode 100644 --- /dev/null +++ b/modules/dirent-safer-tests @@ -0,0 +1,11 @@ +Files: +tests/test-dirent-safer.c + +Depends-on: +dup2 + +configure.ac: + +Makefile.am: +TESTS += test-dirent-safer +check_PROGRAMS += test-dirent-safer
new file mode 100644 --- /dev/null +++ b/tests/test-dirent-safer.c @@ -0,0 +1,106 @@ +/* Test that directory streams leave standard fds alone. + 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> + +#include "unistd-safer.h" + +/* This test intentionally closes stderr. So, we arrange to have fd 10 + (outside the range of interesting fd's during the test) set up to + duplicate the original stderr. */ + +#define BACKUP_STDERR_FILENO 10 +static FILE *myerr; + +#define ASSERT(expr) \ + do \ + { \ + if (!(expr)) \ + { \ + fprintf (myerr, "%s:%d: assertion failed\n", __FILE__, __LINE__); \ + fflush (myerr); \ + abort (); \ + } \ + } \ + while (0) + +int +main () +{ + int i; + DIR *dp; + /* The dirent-safer module works without the use of fdopendir (which + would also pull in fchdir and openat); but if those modules were + also used, we ensure that they are safe. In particular, the + gnulib version of fdopendir is unable to guarantee that + dirfd(fdopendir(fd))==fd, but we can at least guarantee that if + they are not equal, the fd returned by dirfd is safe. */ +#if HAVE_FDOPENDIR || GNULIB_FDOPENDIR + int dfd; +#endif + + /* We close fd 2 later, so save it in fd 10. */ + if (dup2 (STDERR_FILENO, BACKUP_STDERR_FILENO) != BACKUP_STDERR_FILENO + || (myerr = fdopen (BACKUP_STDERR_FILENO, "w")) == NULL) + return 2; + +#if HAVE_FDOPENDIR || GNULIB_FDOPENDIR + dfd = open (".", O_RDONLY); + ASSERT (STDERR_FILENO < dfd); +#endif + + /* Four iterations, with progressively more standard descriptors + closed. */ + for (i = -1; i <= STDERR_FILENO; i++) + { + if (0 <= i) + ASSERT (close (i) == 0); + dp = opendir ("."); + ASSERT (dp); + ASSERT (dirfd (dp) == -1 || STDERR_FILENO < dirfd (dp)); + ASSERT (closedir (dp) == 0); + +#if HAVE_FDOPENDIR || GNULIB_FDOPENDIR + { + int fd = dup_safer (dfd); + ASSERT (STDERR_FILENO < fd); + dp = fdopendir (fd); + ASSERT (dp); + ASSERT (dirfd (dp) == -1 || STDERR_FILENO < dirfd (dp)); + ASSERT (closedir (dp) == 0); + errno = 0; + ASSERT (close (fd) == -1); + ASSERT (errno == EBADF); + } +#endif + } + +#if HAVE_FDOPENDIR || GNULIB_FDOPENDIR + ASSERT (close (dfd) == 0); +#endif + + return 0; +}