From 657fb89d3276465fcf756392f10aa268ca451136 Mon Sep 17 00:00:00 2001 From: Eric Blake Date: Wed, 23 Sep 2009 20:33:40 -0600 Subject: [PATCH] fchdir: another mingw fix 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 --- ChangeLog | 7 +++++++ lib/fchdir.c | 42 +++++++++++++++++++++++++++++++++++++++++- modules/fchdir | 1 - 3 files changed, 48 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index bed42c53f..ee180ac44 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,12 @@ 2009-09-23 Eric Blake + 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 diff --git a/lib/fchdir.c b/lib/fchdir.c index 677d4422e..54bbc623d 100644 --- a/lib/fchdir.c +++ b/lib/fchdir.c @@ -33,6 +33,14 @@ # 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); diff --git a/modules/fchdir b/modules/fchdir index 69ac3c308..5bae7d611 100644 --- a/modules/fchdir +++ b/modules/fchdir @@ -6,7 +6,6 @@ lib/fchdir.c m4/fchdir.m4 Depends-on: -canonicalize-lgpl close dirent dirfd -- 2.11.0