Mercurial > hg > octave-nkf > gnulib-hg
changeset 11935:d233b3d8efbf
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 <ebb9@byu.net>
author | Eric Blake <ebb9@byu.net> |
---|---|
date | Tue, 01 Sep 2009 10:05:44 -0600 |
parents | 80567a8f98f8 |
children | a126d5b22410 |
files | ChangeLog lib/fchdir.c lib/fdopendir.c lib/unistd.in.h |
diffstat | 4 files changed, 39 insertions(+), 14 deletions(-) [+] |
line wrap: on
line diff
--- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,12 @@ 2009-09-02 Eric Blake <ebb9@byu.net> + 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.
--- a/lib/fchdir.c +++ b/lib/fchdir.c @@ -154,6 +154,25 @@ 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 @@ 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; }
--- a/lib/fdopendir.c +++ b/lib/fdopendir.c @@ -30,7 +30,8 @@ /* Replacement for Solaris' function by the same name. <http://www.google.com/search?q=fdopendir+site:docs.sun.com> 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 @@ 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 @@ } free_cwd (&saved_cwd); +#endif /* !REPLACE_FCHDIR */ } if (dir)
--- a/lib/unistd.in.h +++ b/lib/unistd.in.h @@ -252,6 +252,7 @@ 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