fchdir: another mingw fix
authorEric Blake <ebb9@byu.net>
Thu, 24 Sep 2009 02:33:40 +0000 (20:33 -0600)
committerEric Blake <ebb9@byu.net>
Thu, 24 Sep 2009 03:02:22 +0000 (21:02 -0600)
canonicalize_file_name does not understand drive letters or
backslash.  The only reason openat required it was to make
fchdir get the canonical name of a directory.  But we can do
the same trick with chdir and getcwd.  With this fix,
fchdir(open("..",O_RDONLY)) finally does the right thing on mingw.

* modules/fchdir (Depends-on): Drop canonicalize-lgpl.
* lib/fchdir.c (get_name): New helper method; skips canonicalize
on mingw (where it has not yet been ported), and make it optional
elsewhere.
(_gl_register_fd): Use it.

Signed-off-by: Eric Blake <ebb9@byu.net>
ChangeLog
lib/fchdir.c
modules/fchdir

index bed42c53ff905ac96a38235cdb4564fdab48fd4e..ee180ac44eeace41e5d58559013902ff93780c6a 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,12 @@
 2009-09-23  Eric Blake  <ebb9@byu.net>
 
+       fchdir: another mingw fix
+       * modules/fchdir (Depends-on): Drop canonicalize-lgpl.
+       * lib/fchdir.c (get_name): New helper method; skips canonicalize
+       on mingw (where it has not yet been ported), and make it optional
+       elsewhere.
+       (_gl_register_fd): Use it.
+
        same-inode: make SAME_INODE tri-state, to port to mingw
        * NEWS: Mention this change.
        * lib/same-inode.h (same-inode.h): Recognize mingw limitation of
index 677d4422e8f0f767df4f816b21373d3447394331..54bbc623dbc18e8fdfd7b0362c14823d056661b7 100644 (file)
 # define REPLACE_OPEN_DIRECTORY 0
 #endif
 
+#ifndef HAVE_CANONICALIZE_FILE_NAME
+# if GNULIB_CANONICALIZE || GNULIB_CANONICALIZE_LGPL
+#  define HAVE_CANONICALIZE_FILE_NAME 1
+# else
+#  define HAVE_CANONICALIZE_FILE_NAME 0
+# endif
+#endif
+
 /* This replacement assumes that a directory is not renamed while opened
    through a file descriptor.
 
@@ -78,6 +86,38 @@ ensure_dirs_slot (size_t fd)
   return true;
 }
 
+/* Return the canonical name of DIR in malloc'd storage.  */
+static char *
+get_name (char const *dir)
+{
+  char *result;
+  if (REPLACE_OPEN_DIRECTORY || !HAVE_CANONICALIZE_FILE_NAME)
+    {
+      /* The function canonicalize_file_name has not yet been ported
+        to mingw, with all its drive letter and backslash quirks.
+        Fortunately, getcwd is reliable in this case, but we ensure
+        we can get back to where we started before using it.  Treat
+        "." as a special case, as it is frequently encountered.  */
+      char *cwd = getcwd (NULL, 0);
+      int saved_errno;
+      if (dir[0] == '.' && dir[1] == '\0')
+       return cwd;
+      if (chdir (cwd))
+       return NULL;
+      result = chdir (dir) ? NULL : getcwd (NULL, 0);
+      saved_errno = errno;
+      chdir (cwd);
+      free (cwd);
+      errno = saved_errno;
+    }
+  else
+    {
+      /* Avoid changing the directory.  */
+      result = canonicalize_file_name (dir);
+    }
+  return result;
+}
+
 /* Hook into the gnulib replacements for open() and close() to keep track
    of the open file descriptors.  */
 
@@ -108,7 +148,7 @@ _gl_register_fd (int fd, const char *filename)
       || (fstat (fd, &statbuf) == 0 && S_ISDIR (statbuf.st_mode)))
     {
       if (!ensure_dirs_slot (fd)
-          || (dirs[fd].name = canonicalize_file_name (filename)) == NULL)
+          || (dirs[fd].name = get_name (filename)) == NULL)
         {
           int saved_errno = errno;
           close (fd);
index 69ac3c308ad3d433f6e4d5d591472cacbdac5dc3..5bae7d611c69782844cacf7e0783359d2b58aabc 100644 (file)
@@ -6,7 +6,6 @@ lib/fchdir.c
 m4/fchdir.m4
 
 Depends-on:
-canonicalize-lgpl
 close
 dirent
 dirfd