From eeb36a484013c26402222f677f53a20e3f8488e2 Mon Sep 17 00:00:00 2001 From: Eric Blake Date: Tue, 1 Sep 2009 10:05:44 -0600 Subject: [PATCH] fdopendir: optimize on mingw * lib/unistd.in.h (_gl_directory_name): New prototype. * lib/fchdir.c (_gl_directory_name): Implement it. (fchdir): Use it to simplify implementation. * lib/fdopendir.c (fdopendir) [REPLACE_FCHDIR]: Use metadata from fchdir, when available, to avoid calling [f]chdir(). Signed-off-by: Eric Blake --- ChangeLog | 7 +++++++ lib/fchdir.c | 33 +++++++++++++++++++++------------ lib/fdopendir.c | 12 ++++++++++-- lib/unistd.in.h | 1 + 4 files changed, 39 insertions(+), 14 deletions(-) diff --git a/ChangeLog b/ChangeLog index 0cd6e20963..cf8b1155a1 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,12 @@ 2009-09-02 Eric Blake + fdopendir: optimize on mingw + * lib/unistd.in.h (_gl_directory_name): New prototype. + * lib/fchdir.c (_gl_directory_name): Implement it. + (fchdir): Use it to simplify implementation. + * lib/fdopendir.c (fdopendir) [REPLACE_FCHDIR]: Use metadata from + fchdir, when available, to avoid calling [f]chdir(). + fdopendir: split into its own module * lib/openat.c (fdopendir): Move... * lib/fdopendir.c: ...into new file. diff --git a/lib/fchdir.c b/lib/fchdir.c index 9b64e0294b..f35562911a 100644 --- a/lib/fchdir.c +++ b/lib/fchdir.c @@ -154,6 +154,25 @@ _gl_register_dup (int oldfd, int newfd) return newfd; } +/* If FD is currently visiting a directory, then return the name of + that directory. Otherwise, return NULL and set errno. */ +const char * +_gl_directory_name (int fd) +{ + if (0 <= fd && fd < dirs_allocated && dirs[fd].name != NULL) + return dirs[fd].name; + /* At this point, fd is either invalid, or open but not a directory. + If dup2 fails, errno is correctly EBADF. */ + if (0 <= fd) + { + if (dup2 (fd, fd) == fd) + errno = ENOTDIR; + } + else + errno = EBADF; + return NULL; +} + /* 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. */ @@ -222,16 +241,6 @@ rpl_dup (int oldfd) int fchdir (int fd) { - if (fd >= 0 && fd < dirs_allocated && dirs[fd].name != NULL) - return chdir (dirs[fd].name); - /* At this point, fd is either invalid, or open but not a directory. - If dup2 fails, errno is correctly EBADF. */ - if (0 <= fd) - { - if (dup2 (fd, fd) == fd) - errno = ENOTDIR; - } - else - errno = EBADF; - return -1; + const char *name = _gl_directory_name (fd); + return name ? chdir (name) : -1; } diff --git a/lib/fdopendir.c b/lib/fdopendir.c index 70951562f4..3bc13acf41 100644 --- a/lib/fdopendir.c +++ b/lib/fdopendir.c @@ -30,7 +30,8 @@ /* Replacement for Solaris' function by the same name. First, try to simulate it via opendir ("/proc/self/fd/FD"). Failing - that, simulate it by doing save_cwd/fchdir/opendir(".")/restore_cwd. + that, simulate it by using fchdir metadata, or by doing + save_cwd/fchdir/opendir(".")/restore_cwd. If either the save_cwd or the restore_cwd fails (relatively unlikely), then give a diagnostic and exit nonzero. Otherwise, this function works just like Solaris' fdopendir. @@ -45,7 +46,6 @@ DIR * fdopendir (int fd) { - struct saved_cwd saved_cwd; int saved_errno; DIR *dir; @@ -66,6 +66,13 @@ fdopendir (int fd) save_cwd/restore_cwd. */ if (! dir && EXPECTED_ERRNO (saved_errno)) { +#if REPLACE_FCHDIR + const char *name = _gl_directory_name (fd); + if (name) + dir = opendir (name); + saved_errno = errno; +#else /* !REPLACE_FCHDIR */ + struct saved_cwd saved_cwd; if (save_cwd (&saved_cwd) != 0) openat_save_fail (errno); @@ -84,6 +91,7 @@ fdopendir (int fd) } free_cwd (&saved_cwd); +#endif /* !REPLACE_FCHDIR */ } if (dir) diff --git a/lib/unistd.in.h b/lib/unistd.in.h index 3a748a6728..fe645b79c6 100644 --- a/lib/unistd.in.h +++ b/lib/unistd.in.h @@ -252,6 +252,7 @@ extern int dup (int); extern int _gl_register_fd (int fd, const char *filename); extern void _gl_unregister_fd (int fd); extern int _gl_register_dup (int oldfd, int newfd); +extern const char *_gl_directory_name (int fd); # endif #elif defined GNULIB_POSIXCHECK -- 2.30.2