fchdir on mingw

2010-04-03 Thread Bruno Haible
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

2009-10-13 Thread Eric Blake
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

2009-09-15 Thread Eric Blake
-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

2009-09-01 Thread Eric Blake
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

2009-08-31 Thread Eric Blake
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

2009-08-31 Thread Eric Blake
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

2009-08-31 Thread Eric Blake
-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

2009-08-31 Thread Eric Blake
-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-