diff options
author | Ulrich Drepper <drepper@redhat.com> | 2006-02-05 21:19:53 +0000 |
---|---|---|
committer | Ulrich Drepper <drepper@redhat.com> | 2006-02-05 21:19:53 +0000 |
commit | becac6c5b1104415cd76ea02ec01a4c55fb15e55 (patch) | |
tree | 7508f37731bd781111b8e5fcf9dfc42a7b05e176 /io | |
parent | df6871cb7e345e88b9e571962020354a2363d796 (diff) | |
download | glibc-becac6c5b1104415cd76ea02ec01a4c55fb15e55.tar.gz glibc-becac6c5b1104415cd76ea02ec01a4c55fb15e55.tar.xz glibc-becac6c5b1104415cd76ea02ec01a4c55fb15e55.zip |
* io/ftw.c (ftw_startup): Use fchdir to return to original
directory for FTW_CHDIR.
Diffstat (limited to 'io')
-rw-r--r-- | io/ftw.c | 51 |
1 files changed, 30 insertions, 21 deletions
diff --git a/io/ftw.c b/io/ftw.c index 7610851047..5cd0faf54d 100644 --- a/io/ftw.c +++ b/io/ftw.c @@ -1,5 +1,5 @@ /* File tree walker functions. - Copyright (C) 1996-2003, 2004 Free Software Foundation, Inc. + Copyright (C) 1996-2003, 2004, 2006 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996. @@ -36,7 +36,7 @@ char *alloca (); # endif #endif -#if defined _LIBC +#ifdef _LIBC # include <dirent.h> # define NAMLEN(dirent) _D_EXACT_NAMLEN (dirent) #else @@ -59,6 +59,7 @@ char *alloca (); #endif #include <errno.h> +#include <fcntl.h> #include <ftw.h> #include <limits.h> #include <search.h> @@ -585,7 +586,7 @@ ftw_startup (const char *dir, int is_nftw, void *func, int descriptors, struct STAT st; int result = 0; int save_err; - char *cwd = NULL; + int cwdfd = -1; char *cp; /* First make sure the parameters are reasonable. */ @@ -639,24 +640,33 @@ ftw_startup (const char *dir, int is_nftw, void *func, int descriptors, /* Now go to the directory containing the initial file/directory. */ if (flags & FTW_CHDIR) { - /* GNU extension ahead. */ - cwd = __getcwd (NULL, 0); - if (cwd == NULL) + /* We have to be able to go back to the current working + directory. The best way to do this is to use a file + descriptor. */ + cwdfd = __open (".", O_RDONLY | O_DIRECTORY); + if (cwdfd == -1) result = -1; - else if (data.ftw.base > 0) + else { - /* Change to the directory the file is in. In data.dirbuf - we have a writable copy of the file name. Just NUL - terminate it for now and change the directory. */ - if (data.ftw.base == 1) - /* I.e., the file is in the root directory. */ - result = __chdir ("/"); - else + if (data.maxdir > 1) + /* Account for the file descriptor we use here. */ + --data.maxdir; + + if (data.ftw.base > 0) { - char ch = data.dirbuf[data.ftw.base - 1]; - data.dirbuf[data.ftw.base - 1] = '\0'; - result = __chdir (data.dirbuf); - data.dirbuf[data.ftw.base - 1] = ch; + /* Change to the directory the file is in. In data.dirbuf + we have a writable copy of the file name. Just NUL + terminate it for now and change the directory. */ + if (data.ftw.base == 1) + /* I.e., the file is in the root directory. */ + result = __chdir ("/"); + else + { + char ch = data.dirbuf[data.ftw.base - 1]; + data.dirbuf[data.ftw.base - 1] = '\0'; + result = __chdir (data.dirbuf); + data.dirbuf[data.ftw.base - 1] = ch; + } } } } @@ -713,11 +723,10 @@ ftw_startup (const char *dir, int is_nftw, void *func, int descriptors, } /* Return to the start directory (if necessary). */ - if (cwd != NULL) + if (cwdfd != -1) { int save_err = errno; - __chdir (cwd); - free (cwd); + __fchdir (cwdfd); __set_errno (save_err); } |