fchdir on mingw
On mingw still, I'm seeing these errors: test-fchdir.c:24: error: `fchdir' undeclared here (not in a function) make[4]: *** [test-fchdir.o] Error 1 and in C++ mode: ../gllib/unistd.h:698: error: `fchdir' was not declared in this scope The reason is a regression from 2010-03-08: I was confused by the macro REPLACE_FCHDIR, when the common idiom is to use !...@have_fchdir@ instead. This fixes it: 2010-04-03 Bruno Haible br...@clisp.org fchdir: Fix regression introduced on 2010-03-08. * lib/unistd.in.h (fchdir): Fix declaration. * m4/fchdir.m4 (gl_FUNC_FCHDIR): Set HAVE_FCHDIR, not REPLACE_FCHDIR. * m4/unistd_h.m4 (gl_UNISTD_H_DEFAULTS): Initialize HAVE_FCHDIR, not REPLACE_FCHDIR. * modules/unistd (Makefile.am): Substitute HAVE_FCHDIR, not REPLACE_FCHDIR. --- lib/unistd.in.h.origSat Apr 3 15:53:45 2010 +++ lib/unistd.in.h Sat Apr 3 15:51:28 2010 @@ -415,9 +415,8 @@ Return 0 if successful, otherwise -1 and errno set. See the POSIX:2001 specification http://www.opengroup.org/susv3xsh/fchdir.html. */ -# if @REPLACE_FCHDIR@ -_GL_FUNCDECL_RPL (fchdir, int, (int /*fd*/)); -_GL_CXXALIAS_RPL (fchdir, int, (int /*fd*/)); +# if ! @HAVE_FCHDIR@ +_GL_FUNCDECL_SYS (fchdir, int, (int /*fd*/)); /* Gnulib internal hooks needed to maintain the fchdir metadata. */ _GL_EXTERN_C int _gl_register_fd (int fd, const char *filename) @@ -426,9 +425,8 @@ _GL_EXTERN_C int _gl_register_dup (int oldfd, int newfd); _GL_EXTERN_C const char *_gl_directory_name (int fd); -# else -_GL_CXXALIAS_SYS (fchdir, int, (int /*fd*/)); # endif +_GL_CXXALIAS_SYS (fchdir, int, (int /*fd*/)); _GL_CXXALIASWARN (fchdir); #elif defined GNULIB_POSIXCHECK # undef fchdir --- m4/fchdir.m4.orig Sat Apr 3 15:53:45 2010 +++ m4/fchdir.m4Sat Apr 3 15:49:56 2010 @@ -1,4 +1,4 @@ -# fchdir.m4 serial 13 +# fchdir.m4 serial 14 dnl Copyright (C) 2006-2010 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -11,7 +11,7 @@ AC_REQUIRE([gl_SYS_STAT_H_DEFAULTS]) AC_CHECK_FUNCS_ONCE([fchdir]) if test $ac_cv_func_fchdir = no; then -REPLACE_FCHDIR=1 +HAVE_FCHDIR=0 AC_LIBOBJ([fchdir]) gl_PREREQ_FCHDIR AC_DEFINE([REPLACE_FCHDIR], [1], --- m4/unistd_h.m4.orig Sat Apr 3 15:53:45 2010 +++ m4/unistd_h.m4 Sat Apr 3 15:51:58 2010 @@ -1,4 +1,4 @@ -# unistd_h.m4 serial 44 +# unistd_h.m4 serial 45 dnl Copyright (C) 2006-2010 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -98,6 +98,7 @@ HAVE_DUP3=1;AC_SUBST([HAVE_DUP3]) HAVE_EUIDACCESS=1; AC_SUBST([HAVE_EUIDACCESS]) HAVE_FACCESSAT=1; AC_SUBST([HAVE_FACCESSAT]) + HAVE_FCHDIR=1; AC_SUBST([HAVE_FCHDIR]) HAVE_FCHOWNAT=1;AC_SUBST([HAVE_FCHOWNAT]) HAVE_FSYNC=1; AC_SUBST([HAVE_FSYNC]) HAVE_FTRUNCATE=1; AC_SUBST([HAVE_FTRUNCATE]) @@ -130,7 +131,6 @@ REPLACE_CLOSE=0;AC_SUBST([REPLACE_CLOSE]) REPLACE_DUP=0; AC_SUBST([REPLACE_DUP]) REPLACE_DUP2=0; AC_SUBST([REPLACE_DUP2]) - REPLACE_FCHDIR=0; AC_SUBST([REPLACE_FCHDIR]) REPLACE_FCHOWNAT=0; AC_SUBST([REPLACE_FCHOWNAT]) REPLACE_GETCWD=0; AC_SUBST([REPLACE_GETCWD]) REPLACE_GETGROUPS=0;AC_SUBST([REPLACE_GETGROUPS]) --- modules/unistd.orig Sat Apr 3 15:53:45 2010 +++ modules/unistd Sat Apr 3 15:52:24 2010 @@ -72,6 +72,7 @@ -e 's|@''HAVE_DUP3''@|$(HAVE_DUP3)|g' \ -e 's|@''HAVE_EUIDACCESS''@|$(HAVE_EUIDACCESS)|g' \ -e 's|@''HAVE_FACCESSAT''@|$(HAVE_FACCESSAT)|g' \ + -e 's|@''HAVE_FCHDIR''@|$(HAVE_FCHDIR)|g' \ -e 's|@''HAVE_FCHOWNAT''@|$(HAVE_FCHOWNAT)|g' \ -e 's|@''HAVE_FSYNC''@|$(HAVE_FSYNC)|g' \ -e 's|@''HAVE_FTRUNCATE''@|$(HAVE_FTRUNCATE)|g' \ @@ -104,7 +105,6 @@ -e 's|@''REPLACE_CLOSE''@|$(REPLACE_CLOSE)|g' \ -e 's|@''REPLACE_DUP''@|$(REPLACE_DUP)|g' \ -e 's|@''REPLACE_DUP2''@|$(REPLACE_DUP2)|g' \ - -e 's|@''REPLACE_FCHDIR''@|$(REPLACE_FCHDIR)|g' \ -e 's|@''REPLACE_FCHOWNAT''@|$(REPLACE_FCHOWNAT)|g' \ -e 's|@''REPLACE_GETCWD''@|$(REPLACE_GETCWD)|g' \ -e 's|@''REPLACE_GETGROUPS''@|$(REPLACE_GETGROUPS)|g' \
Re: fchdir on mingw
Eric Blake ebb9 at byu.net writes: Date: Tue, 15 Sep 2009 15:54:43 -0600 Subject: [PATCH] fchdir: improve use of replacement functions * m4/fchdir.m4 (gl_FUNC_FCHDIR): Set appropriate witnesses. * m4/sys_stat_h.m4 (gl_SYS_STAT_H_DEFAULTS): Add REPLACE_FSTAT. This patch broke fstat on non-directories on mingw, due to infinite recursion on the rpl_fstat definition (and it took me a month, and the addition of the utimens test, before I noticed it). Fixing as follows: From: Eric Blake e...@byu.net Date: Tue, 13 Oct 2009 09:25:30 -0600 Subject: [PATCH] fchdir: avoid infinite recursion in mingw * lib/fchdir.c (rpl_fstat): Call system fstat, rather than recursing. Signed-off-by: Eric Blake e...@byu.net --- ChangeLog|4 lib/fchdir.c |1 + 2 files changed, 5 insertions(+), 0 deletions(-) diff --git a/ChangeLog b/ChangeLog index 4bac820..6069410 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,9 @@ 2009-10-13 Eric Blake e...@byu.net + fchdir: avoid infinite recursion in mingw + * lib/fchdir.c (rpl_fstat): Call system fstat, rather than + recursing. + test-stat-time: port to mingw * tests/test-stat-time.c (force_unlink): Return a value. (test_ctime) [W32]: Fix compilation error. diff --git a/lib/fchdir.c b/lib/fchdir.c index 19f02c3..16b17b4 100644 --- a/lib/fchdir.c +++ b/lib/fchdir.c @@ -217,6 +217,7 @@ _gl_directory_name (int fd) rpl_open() used a dummy file to work around an open() that can't normally visit directories. */ #if REPLACE_OPEN_DIRECTORY +# undef fstat int rpl_fstat (int fd, struct stat *statbuf) { -- 1.6.4.2
Re: fchdir on mingw
-BEGIN PGP SIGNED MESSAGE- Hash: SHA1 According to Eric Blake on 9/1/2009 10:55 AM: Eric Blake (5): fchdir: fix off-by-one bug in previous patch fchdir: simplify error handling, and support dup3 fchdir: use more consistent macro convention This particular patch wasn't quite consistent with other replacement macros. I'm pushing this followup: - -- Don't work too hard, make some time for fun as well! Eric Blake e...@byu.net -BEGIN PGP SIGNATURE- Version: GnuPG v1.4.9 (Cygwin) Comment: Public key at home.comcast.net/~ericblake/eblake.gpg Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/ iEYEARECAAYFAkqwYJsACgkQ84KuGfSFAYAOJgCeN3uOMkcSL183t6YteqTe5u0K 9nEAoNkHZTfaxabjuCryKU/HG7hEsb0U =eKlF -END PGP SIGNATURE- From c9dd0005fe00602d13c3d54f0834655b1e769520 Mon Sep 17 00:00:00 2001 From: Eric Blake e...@byu.net Date: Tue, 15 Sep 2009 15:54:43 -0600 Subject: [PATCH] fchdir: improve use of replacement functions * m4/fchdir.m4 (gl_FUNC_FCHDIR): Set appropriate witnesses. * m4/sys_stat_h.m4 (gl_SYS_STAT_H_DEFAULTS): Add REPLACE_FSTAT. * m4/dirent_h.m4 (gl_DIRENT_H_DEFAULTS): Add REPLACE_OPENDIR, REPLACE_CLOSEDIR. * m4/unistd_h.m4 (gl_UNISTD_H_DEFAULTS): Add REPLACE_DUP. * modules/sys_stat (Makefile.am): Substitute correct witness. * modules/dirent (Makefile.am): Likewise. * modules/unistd (Makefile.am): Likewise. * lib/dirent.in.h (opendir, closedir): Use better witnesses. * lib/unistd.in.h (dup): Likewise. * lib/sys_stat.in.h (fstat): Likewise. Signed-off-by: Eric Blake e...@byu.net --- ChangeLog | 13 + lib/dirent.in.h | 11 ++- lib/sys_stat.in.h |2 +- lib/unistd.in.h |8 m4/dirent_h.m4|4 +++- m4/fchdir.m4 |8 +++- m4/sys_stat_h.m4 |3 ++- m4/unistd_h.m4|3 ++- modules/dirent|3 ++- modules/sys_stat |2 +- modules/unistd|1 + 11 files changed, 42 insertions(+), 16 deletions(-) diff --git a/ChangeLog b/ChangeLog index 322aca5..e58b782 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,18 @@ 2009-09-15 Eric Blake e...@byu.net + fchdir: improve use of replacement functions + * m4/fchdir.m4 (gl_FUNC_FCHDIR): Set appropriate witnesses. + * m4/sys_stat_h.m4 (gl_SYS_STAT_H_DEFAULTS): Add REPLACE_FSTAT. + * m4/dirent_h.m4 (gl_DIRENT_H_DEFAULTS): Add REPLACE_OPENDIR, + REPLACE_CLOSEDIR. + * m4/unistd_h.m4 (gl_UNISTD_H_DEFAULTS): Add REPLACE_DUP. + * modules/sys_stat (Makefile.am): Substitute correct witness. + * modules/dirent (Makefile.am): Likewise. + * modules/unistd (Makefile.am): Likewise. + * lib/dirent.in.h (opendir, closedir): Use better witnesses. + * lib/unistd.in.h (dup): Likewise. + * lib/sys_stat.in.h (fstat): Likewise. + maint: ignore gnulib-tool temp files * .gitignore: Ignore files created during gnulib-tool --test. diff --git a/lib/dirent.in.h b/lib/dirent.in.h index 8930765..6da77d9 100644 --- a/lib/dirent.in.h +++ b/lib/dirent.in.h @@ -35,15 +35,11 @@ extern C { /* Declare overridden functions. */ -#if @REPLACE_FCHDIR@ -# define opendir rpl_opendir -extern DIR * opendir (const char *); +#if @REPLACE_CLOSEDIR@ # define closedir rpl_closedir extern int closedir (DIR *); #endif -/* Declare other POSIX functions. */ - #if @GNULIB_DIRFD@ # if !...@have_decl_dirfd@ !defined dirfd /* Return the file descriptor associated with the given directory stream, @@ -75,6 +71,11 @@ extern DIR *fdopendir (int fd); fdopendir (f)) #endif +#if @REPLACE_OPENDIR@ +# define opendir rpl_opendir +extern DIR * opendir (const char *); +#endif + #if @GNULIB_SCANDIR@ /* Scan the directory DIR, calling FILTER on each directory entry. Entries for which FILTER returns nonzero are individually malloc'd, diff --git a/lib/sys_stat.in.h b/lib/sys_stat.in.h index b0ea92d..869cb0f 100644 --- a/lib/sys_stat.in.h +++ b/lib/sys_stat.in.h @@ -369,7 +369,7 @@ int mknodat (int fd, char const *file, mode_t mode, dev_t dev); mknodat (f, n, m, d)) #endif -#if @REPLACE_FCHDIR@ +#if @REPLACE_FSTAT@ # define fstat rpl_fstat extern int fstat (int fd, struct stat *buf); #endif diff --git a/lib/unistd.in.h b/lib/unistd.in.h index f191412..553fb06 100644 --- a/lib/unistd.in.h +++ b/lib/unistd.in.h @@ -231,6 +231,10 @@ extern int close (int); close (f)) #endif +#if @REPLACE_DUP@ +# define dup rpl_dup +extern int dup (int); +#endif #if @GNULIB_DUP2@ # if @REPLACE_DUP2@ @@ -312,7 +316,6 @@ extern int euidaccess (const char *filename, int mode); #if @GNULIB_FCHDIR@ # if @REPLACE_FCHDIR@ - /* Change the process' current working directory to the directory on which the given file descriptor is open. Return 0 if successful, otherwise -1 and errno set. @@ -320,9 +323,6 @@ extern int euidaccess (const char *filename, int mode); http://www.opengroup.org/susv3xsh/fchdir.html. */ extern int fchdir (int /*fd*/); -# define
Re: fchdir on mingw
Eric Blake ebb9 at byu.net writes: +/* Return stat information about FD in STATBUF. Needed when + rpl_open() used a dummy file to work around an open() that can't + normally visit directories. */ +#if REPLACE_OPEN_DIRECTORY +int +rpl_fstat (int fd, struct stat *statbuf) +{ + if (0 = fd fd = dirs_allocated dirs[fd].name != NULL) +return stat (dirs[fd].name, statbuf); Ouch. Off-by-one error, which can lead to segfault on mingw when fd == dirs_allocated. Here's the correction, along with the rest of my rebased pending patches. Any comments before I apply? Stay tuned for dirent-safer built on top of this. Eric Blake (5): fchdir: fix off-by-one bug in previous patch fchdir: simplify error handling, and support dup3 fchdir: use more consistent macro convention fdopendir: split into its own module fdopendir: optimize on mingw From 2fc6c30f4fdda7b373a16dd849cfebcc4cc7669f Mon Sep 17 00:00:00 2001 From: Eric Blake e...@byu.net Date: Tue, 1 Sep 2009 10:06:44 -0600 Subject: [PATCH 1/5] fchdir: fix off-by-one bug in previous patch * lib/fchdir.c (rpl_fstat): Use correct bounds. (_gl_unregister_fd): Delete useless if. Signed-off-by: Eric Blake e...@byu.net --- ChangeLog|6 ++ lib/fchdir.c |5 ++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index d53ed5d..7b67cf4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2009-09-01 Eric Blake e...@byu.net + + fchdir: fix off-by-one bug in previous patch + * lib/fchdir.c (rpl_fstat): Use correct bounds. + (_gl_unregister_fd): Delete useless if. + 2009-09-01 Simon Josefsson si...@josefsson.org * modules/arpa_inet: Use $(MKDIR_P) instead of @mkdi...@. diff --git a/lib/fchdir.c b/lib/fchdir.c index cedbcde..170505f 100644 --- a/lib/fchdir.c +++ b/lib/fchdir.c @@ -93,8 +93,7 @@ _gl_unregister_fd (int fd) { if (fd = 0 fd dirs_allocated) { - if (dirs[fd].name != NULL) - free (dirs[fd].name); + free (dirs[fd].name); dirs[fd].name = NULL; dirs[fd].saved_errno = ENOTDIR; } @@ -126,7 +125,7 @@ _gl_register_fd (int fd, const char *filename) int rpl_fstat (int fd, struct stat *statbuf) { - if (0 = fd fd = dirs_allocated dirs[fd].name != NULL) + if (0 = fd fd dirs_allocated dirs[fd].name != NULL) return stat (dirs[fd].name, statbuf); return fstat (fd, statbuf); } -- 1.6.3.2 From 21fc064f72d5acb6c326022b4b77818703b1c897 Mon Sep 17 00:00:00 2001 From: Eric Blake e...@byu.net Date: Mon, 31 Aug 2009 14:20:03 -0600 Subject: [PATCH 2/5] fchdir: simplify error handling, and support dup3 * modules/fchdir (Depends-on): Use strdup-posix, not strdup. Add stdbool, malloc-posix, realloc-posix. * lib/fchdir.c (struct dir_info_t): Delete saved_errno. (ensure_dirs_slot): Return false on allocation failure. (rpl_dup2): Delete. (_gl_register_dup): New function. (_gl_unregister_fd, rpl_opendir, rpl_dup): Update callers. (_gl_register_fd): Close fd on allocation failure. * lib/fcntl.in.h (_gl_register_fd): Update signature. * lib/unistd.in.h (_gl_register_dup) [FCHDIR_REPLACEMENT]: New prototype. (rpl_dup2_fchdir): Delete prototype. * lib/open.c (open): Update caller. * lib/dup2.c (dup2): Track fchdir metadata. * lib/dup3.c (dup3): Likewise. * m4/dup2.m4 (gl_REPLACE_DUP2): New macro. * m4/fchdir.m4 (gl_FUNC_FCHDIR): Use it. Signed-off-by: Eric Blake e...@byu.net --- ChangeLog | 19 ++ lib/dup2.c | 16 - lib/dup3.c | 11 lib/fchdir.c| 177 --- lib/fcntl.in.h |2 +- lib/open.c |4 +- lib/unistd.in.h |8 +-- m4/dup2.m4 | 12 +++- m4/fchdir.m4|4 +- modules/fchdir |5 +- 10 files changed, 141 insertions(+), 117 deletions(-) diff --git a/ChangeLog b/ChangeLog index 7b67cf4..6a0b18e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,24 @@ 2009-09-01 Eric Blake e...@byu.net + fchdir: simplify error handling, and support dup3 + * modules/fchdir (Depends-on): Use strdup-posix, not strdup. Add + stdbool, malloc-posix, realloc-posix. + * lib/fchdir.c (struct dir_info_t): Delete saved_errno. + (ensure_dirs_slot): Return false on allocation failure. + (rpl_dup2): Delete. + (_gl_register_dup): New function. + (_gl_unregister_fd, rpl_opendir, rpl_dup): Update callers. + (_gl_register_fd): Close fd on allocation failure. + * lib/fcntl.in.h (_gl_register_fd): Update signature. + * lib/unistd.in.h (_gl_register_dup) [FCHDIR_REPLACEMENT]: New + prototype. + (rpl_dup2_fchdir): Delete prototype. + * lib/open.c (open): Update caller. + * lib/dup2.c (dup2): Track fchdir metadata. + * lib/dup3.c (dup3): Likewise. + * m4/dup2.m4 (gl_REPLACE_DUP2): New macro. + * m4/fchdir.m4 (gl_FUNC_FCHDIR): Use it. + fchdir: fix off-by-one bug in previous patch *
fchdir on mingw
One of the main reasons the fchdir module was added was so that the openat module (and friends) would compile on mingw. Well, it turns out that mingw has the (documented) limitation that open(dir,O_RDONLY) fails with EACCES, so rpl_open was never registering an fd visiting a directory in the first place, and the fchdir replacement (and thus openat and fts) failed to run on mingw. The first patch improves things by adding a fchdir unit test, and teaches rpl_open how to fake out opening a directory (the end result of using /dev/null under the hood means that read() on the fd gives the same EOF results as on Linux; and replacing fstat() means we can hide the fact that we used a dummy). Techincally, I probably could have spent more time trying to figure out how to open a directory HANDLE using CreateFile with FILE_FLAG_BACKUP_SEMANTICS, but I couldn't quickly get that working. I also wonder how _open_osfhandle would react to a directory HANDLE. At any rate, since the method in the patch below passed the unit test, I'm not going to worry about the CreateFile approach. The second patch fixes the fact that dup3 needs to play nicely with fchdir, and changes dup2 so that it is only overridden once, not twice, in gnulib sources. It also simplifies the logic in fchdir by not maintaining a saved_errno for every known fd, but instead aborting any attempt to open a directory up front with ENOMEM if we could not enlarge the map or strdup the directory name. It is still possible to use fcntl(F_DUPFD{,_CLOEXEC}) to go behind fchdir's back at the moment, but until I finish an fcntl replacement module, that isn't too much to worry about. I'm also working on a patch to split fdopendir into its own module (rather than being intimately tied to openat), as a prerequisite for implementing opendir_safer and dirent--.h. One improvement possible for fdopendir is that if fchdir is being emulated by gnulib, we can do a query into the fchdir metadata table to retrieve the directory name associated with an fd, rather than having to go through save_cwd/fchdir/opendir/restore_cwd (although the latter finally does work now on mingw, with just my first patch in place). Also, it might still be possible to make dirfd work on mingw (right now, it always returns -1). One way would be by adding a struct rpl_DIR which tracks an fd associated with a DIR, another way would be by adding a DIR* field to the fchdir metadata then doing a linear search for DIR pointer equality to find which fd is tied to a given DIR. Since the maximum fd is not all that big, the O(n) cost of a reverse lookup is not too bad, and seems easier than an O(1) lookup by overriding struct DIR. But with either approach, it would mean that fdopendir would need to change to keep the fd open as long as the DIR is open (rather than the current fdopendir policy of closing the user's fd up front), closedir would have to be responsible for closing the fd tied to a DIR, and we would have to decide whether it was better to always open an fd up front in opendir or just delay until the first dirfd (if any) for tying an fd to a DIR created by opendir. So, here's the two patches I plan to apply soon... From: Eric Blake e...@byu.net Date: Mon, 31 Aug 2009 06:09:08 -0600 Subject: [PATCH 1/2] fchdir: port to mingw * m4/fchdir.m4 (gl_FUNC_FCHDIR): Check for mingw bug. * lib/open.c (open) [FCHDIR_REPLACEMENT]: If directories can't be opened, then use a substitute. * lib/sys_stat.in.h (fstat) [REPLACE_OPEN_DIRECTORY]: Declare replacement. * lib/fchdir.c (fstat) [REPLACE_OPEN_DIRECTORY]: Implement it. (_gl_register_fd): No need to check stat if open already filters all directories. (fchdir): Fix error condition to match POSIX. * modules/fchdir (Depends-on): Add sys_stat. * doc/posix-functions/open.texi (open): Document the limitation. * modules/fchdir-tests: New file. * tests/test-fchdir.c: Likewise. Signed-off-by: Eric Blake e...@byu.net --- ChangeLog | 15 +++ doc/posix-functions/open.texi | 11 - lib/fchdir.c | 63 ++-- lib/open.c| 29 +- lib/sys_stat.in.h |4 ++ m4/fchdir.m4 | 13 +- modules/fchdir|1 + modules/fchdir-tests | 11 + tests/test-fchdir.c | 91 + 9 files changed, 211 insertions(+), 27 deletions(-) create mode 100644 modules/fchdir-tests create mode 100644 tests/test-fchdir.c diff --git a/ChangeLog b/ChangeLog index 6e39cef..749215d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,20 @@ 2009-08-31 Eric Blake e...@byu.net + fchdir: port to mingw + * m4/fchdir.m4 (gl_FUNC_FCHDIR): Check for mingw bug. + * lib/open.c (open) [FCHDIR_REPLACEMENT]: If directories can't be + opened, then use a substitute. + * lib/sys_stat.in.h (fstat) [REPLACE_OPEN_DIRECTORY
Re: fchdir on mingw
Eric Blake ebb9 at byu.net writes: One improvement possible for fdopendir is that if fchdir is being emulated by gnulib, we can do a query into the fchdir metadata table to retrieve the directory name associated with an fd, rather than having to go through save_cwd/fchdir/opendir/restore_cwd. Here's two patches for that, to be applied on top of fchdir. From: Eric Blake e...@byu.net Date: Sun, 30 Aug 2009 18:48:20 -0600 Subject: [PATCH 1/2] 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 e...@byu.net --- ChangeLog | 20 MODULES.html.sh|1 + doc/posix-functions/fdopendir.texi |2 +- lib/dirent.in.h| 17 ++ lib/fdopendir.c| 96 lib/openat.c | 68 - lib/openat.h |6 +-- lib/savedir.c |3 +- m4/dirent_h.m4 | 10 ++-- m4/fdopendir.m4| 21 m4/openat.m4 |3 +- modules/dirent |2 + modules/fdopendir | 30 +++ modules/fdopendir-tests| 13 + modules/openat |1 + modules/savedir|2 +- tests/test-fdopendir.c | 76 17 files changed, 288 insertions(+), 83 deletions(-) create mode 100644 lib/fdopendir.c create mode 100644 m4/fdopendir.m4 create mode 100644 modules/fdopendir create mode 100644 modules/fdopendir-tests create mode 100644 tests/test-fdopendir.c diff --git a/ChangeLog b/ChangeLog index 869567e..b9b3041 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,25 @@ 2009-08-31 Eric Blake e...@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: simplify error handling, and support dup3 * modules/fchdir (Depends-on): Use strdup-posix, not strdup. Add stdbool, malloc-posix, realloc-posix. diff --git a/MODULES.html.sh b/MODULES.html.sh index 3c54cec..027a0bc 100755 --- a/MODULES.html.sh +++ b/MODULES.html.sh @@ -2451,6 +2451,7 @@ func_all_modules () func_module dirfd func_module double-slash-root func_module euidaccess + func_module fdopendir func_module file-type func_module fileblocks func_module filemode diff --git a/doc/posix-functions/fdopendir.texi b/doc/posix- functions/fdopendir.texi index 1d9827c..81b6991 100644 --- a/doc/posix-functions/fdopendir.texi +++ b/doc/posix-functions/fdopendir.texi @@ -4,7 +4,7 @@ fdopendir POSIX specification: @url {http://www.opengroup.org/onlinepubs/9699919799/functions/fdopendir.html} -Gnulib module: openat +Gnulib module: fdopendir Portability problems fixed by Gnulib: @itemize diff --git a/lib/dirent.in.h b/lib/dirent.in.h index 15f0245..8930765 100644 --- a/lib/dirent.in.h +++ b/lib/dirent.in.h @@ -58,6 +58,23 @@ extern int dirfd (DIR const *dir); 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
Re: fchdir on mingw
-BEGIN PGP SIGNED MESSAGE- Hash: SHA1 According to Eric Blake on 8/31/2009 5:38 PM: Notice that this changes the status of fdopendir - whereas it was previously non-multithread safe and could call _exit, the mingw version of fdopendir is now threadsafe and avoids _exit. Well, not entirely threadsafe. There is a window between when rpl_open() does a stat() to learn that name is a directory, and when fchdir/fdopendir (via chdir()/opendir()) uses that name later on. It's not as pronounced on mingw, where you can't rename an in-use directory (and we could even open up a directory HANDLE to prevent users from changing it behind our backs), but it probably is asking for problems on Unix if another process is actively changing the same hierarchy as what we just tied to the fchdir metadata table. So on second thought, for systems with fchdir and which can open() directories without help, I'd rather stick with save_cwd/fchdir/opendir/restore_cwd rather than risk an optimized fdopendir that exposes the user to a multi-process data race. At least with the fchdir approach to fdopendir, you have limited your problems only to a race between threads in a single process, rather than something exploitable by other processes. - -- Don't work too hard, make some time for fun as well! Eric Blake e...@byu.net -BEGIN PGP SIGNATURE- Version: GnuPG v1.4.9 (Cygwin) Comment: Public key at home.comcast.net/~ericblake/eblake.gpg Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/ iEYEARECAAYFAkqceEYACgkQ84KuGfSFAYCkQACeJsHocH5U2USkxI9aP/HG2B8f kVoAoIPtnTxbHHFgX7RnX8VQuoEC+7sE =TAb9 -END PGP SIGNATURE-
Re: fchdir on mingw
-BEGIN PGP SIGNED MESSAGE- Hash: SHA1 According to Eric Blake on 8/31/2009 3:35 PM: One of the main reasons the fchdir module was added was so that the openat module (and friends) would compile on mingw. Well, it turns out that mingw has the (documented) limitation that open(dir,O_RDONLY) fails with EACCES, so rpl_open was never registering an fd visiting a directory in the first place, and the fchdir replacement (and thus openat and fts) failed to run on mingw. The first patch improves things by adding a fchdir unit test, and teaches rpl_open how to fake out opening a directory (the end result of using /dev/null under the hood means that read() on the fd gives the same EOF results as on Linux; and replacing fstat() means we can hide the fact that we used a dummy). Pushed the first one; I'll wait a bit longer for any more review before pushing the second (since it changes the implementation of fchdir) or the subsequent fdopendir patches. Subject: [PATCH 1/2] fchdir: port to mingw * m4/fchdir.m4 (gl_FUNC_FCHDIR): Check for mingw bug. * lib/open.c (open) [FCHDIR_REPLACEMENT]: If directories can't be opened, then use a substitute. * lib/sys_stat.in.h (fstat) [REPLACE_OPEN_DIRECTORY]: Declare replacement. * lib/fchdir.c (fstat) [REPLACE_OPEN_DIRECTORY]: Implement it. (_gl_register_fd): No need to check stat if open already filters all directories. (fchdir): Fix error condition to match POSIX. * modules/fchdir (Depends-on): Add sys_stat. * doc/posix-functions/open.texi (open): Document the limitation. * modules/fchdir-tests: New file. * tests/test-fchdir.c: Likewise. - -- Don't work too hard, make some time for fun as well! Eric Blake e...@byu.net -BEGIN PGP SIGNATURE- Version: GnuPG v1.4.9 (Cygwin) Comment: Public key at home.comcast.net/~ericblake/eblake.gpg Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/ iEYEARECAAYFAkqcolwACgkQ84KuGfSFAYBCWwCcCkOO6YkzMbTphFCsHIqbs474 PEAAoJN4VaMMuLSQg4cLTUUftfzSTWK0 =rJu1 -END PGP SIGNATURE-