diff options
author | Ulrich Drepper <drepper@redhat.com> | 2003-11-07 23:00:00 +0000 |
---|---|---|
committer | Ulrich Drepper <drepper@redhat.com> | 2003-11-07 23:00:00 +0000 |
commit | ca10f33858adef0c20f8bcbf65b49f920e3274e9 (patch) | |
tree | dff8ac42acd1b9e8e289058bc3a0cab2f907ae3b /io/ftw.c | |
parent | c685b2b0b4e86f488ead098816292684362e55f7 (diff) | |
download | glibc-ca10f33858adef0c20f8bcbf65b49f920e3274e9.zip glibc-ca10f33858adef0c20f8bcbf65b49f920e3274e9.tar.gz glibc-ca10f33858adef0c20f8bcbf65b49f920e3274e9.tar.bz2 |
Update.
2003-11-07 Jakub Jelinek <jakub@redhat.com>
* io/ftw.c (NFTW_OLD_NAME, NFTW_NEW_NAME): Define.
(ftw_dir, ftw_startup): Add __attribute ((noinline)).
(NFTW_OLD_NAME, NFTW_NEW_NAME): New functions.
(NFTW_NAME): Only define if !_LIBC, add versioned_symbol
and compat_symbol.
* io/ftw64.c (NFTW_OLD_NAME, NFTW_NEW_NAME): Define.
* io/Versions (libc): Export nftw@@GLIBC_2.3.3
and nftw64@@GLIBC_2.3.3.
* io/ftw.h (FTW_ACTIONRETVAL): New flag.
(FTW_CONTINUE, FTW_STOP, FTW_SKIP_SUBTREE, FTW_SKIP_SIBLINGS): New.
* io/ftw.c (ftw_dir): Add old_dir argument.
Clear result if it was FTW_SKIP_SIBLINGS after processing all
dir entries. Change cwd back if old_dir != NULL.
(process_entry): Adjust caller. Don't change cwd back here.
Change FTW_SKIP_SUBTREE result to 0.
(ftw_startup): Adjust ftw_dir caller.
Clear result if it was FTW_SKIP_SUBTREE or FTW_SKIP_SIBLINGS.
* io/ftwtest.c (skip_subtree, skip_siblings): New variables.
(options, main): Add --skip-subtree and --skip-siblings options.
(cb): Use return FTW_CONTINUE instead of return 0.
Handle --skip-subtree and --skip-siblings.
* io/ftwtest-sh: Add tests for FTW_ACTIONRETVAL.
* manual/filesys.texi: Document FTW_ACTIONRETVAL.
Diffstat (limited to 'io/ftw.c')
-rw-r--r-- | io/ftw.c | 112 |
1 files changed, 85 insertions, 27 deletions
@@ -135,6 +135,8 @@ int rpl_lstat (const char *, struct stat *); #ifndef FTW_NAME # define FTW_NAME ftw # define NFTW_NAME nftw +# define NFTW_OLD_NAME __old_nftw +# define NFTW_NEW_NAME __new_nftw # define INO_T ino_t # define STAT stat # ifdef _LIBC @@ -217,7 +219,8 @@ static const int ftw_arr[] = /* Forward declarations of local functions. */ -static int ftw_dir (struct ftw_data *data, struct STAT *st) internal_function; +static int ftw_dir (struct ftw_data *data, struct STAT *st, + struct dir_data *old_dir) internal_function; static int @@ -415,43 +418,24 @@ process_entry (struct ftw_data *data, struct dir_data *dir, const char *name, || (!find_object (data, &st) /* Remember the object. */ && (result = add_object (data, &st)) == 0)) - { - result = ftw_dir (data, &st); - - if (result == 0 && (data->flags & FTW_CHDIR)) - { - /* Change back to the parent directory. */ - int done = 0; - if (dir->stream != NULL) - if (__fchdir (dirfd (dir->stream)) == 0) - done = 1; - - if (!done) - { - if (data->ftw.base == 1) - { - if (__chdir ("/") < 0) - result = -1; - } - else - if (__chdir ("..") < 0) - result = -1; - } - } - } + result = ftw_dir (data, &st, dir); } else result = (*data->func) (data->dirbuf, &st, data->cvt_arr[flag], &data->ftw); } + if ((data->flags & FTW_ACTIONRETVAL) && result == FTW_SKIP_SUBTREE) + result = 0; + return result; } static int +__attribute ((noinline)) internal_function -ftw_dir (struct ftw_data *data, struct STAT *st) +ftw_dir (struct ftw_data *data, struct STAT *st, struct dir_data *old_dir) { struct dir_data dir; struct dirent64 *d; @@ -550,6 +534,9 @@ fail: __set_errno (save_err); } + if ((data->flags & FTW_ACTIONRETVAL) && result == FTW_SKIP_SIBLINGS) + result = 0; + /* Prepare the return, revert the `struct FTW' information. */ data->dirbuf[data->ftw.base - 1] = '\0'; --data->ftw.level; @@ -559,11 +546,37 @@ fail: if (result == 0 && (data->flags & FTW_DEPTH)) result = (*data->func) (data->dirbuf, st, FTW_DP, &data->ftw); + if (old_dir + && (data->flags & FTW_CHDIR) + && (result == 0 + || ((data->flags & FTW_ACTIONRETVAL) + && (result != -1 && result != FTW_STOP)))) + { + /* Change back to the parent directory. */ + int done = 0; + if (old_dir->stream != NULL) + if (__fchdir (dirfd (old_dir->stream)) == 0) + done = 1; + + if (!done) + { + if (data->ftw.base == 1) + { + if (__chdir ("/") < 0) + result = -1; + } + else + if (__chdir ("..") < 0) + result = -1; + } + } + return result; } static int +__attribute ((noinline)) internal_function ftw_startup (const char *dir, int is_nftw, void *func, int descriptors, int flags) @@ -683,7 +696,7 @@ ftw_startup (const char *dir, int is_nftw, void *func, int descriptors, result = add_object (&data, &st); if (result == 0) - result = ftw_dir (&data, &st); + result = ftw_dir (&data, &st, NULL); } else { @@ -693,6 +706,10 @@ ftw_startup (const char *dir, int is_nftw, void *func, int descriptors, &data.ftw); } } + + if ((flags & FTW_ACTIONRETVAL) + && (result == FTW_SKIP_SUBTREE || result == FTW_SKIP_SIBLINGS)) + result = 0; } /* Return to the start directory (if necessary). */ @@ -726,6 +743,7 @@ FTW_NAME (path, func, descriptors) return ftw_startup (path, 0, func, descriptors, 0); } +#ifndef _LIBC int NFTW_NAME (path, func, descriptors, flags) const char *path; @@ -735,3 +753,43 @@ NFTW_NAME (path, func, descriptors, flags) { return ftw_startup (path, 1, func, descriptors, flags); } +#else + +#include <shlib-compat.h> + +int +NFTW_NEW_NAME (path, func, descriptors, flags) + const char *path; + NFTW_FUNC_T func; + int descriptors; + int flags; +{ + if (flags + & ~(FTW_PHYS | FTW_MOUNT | FTW_CHDIR | FTW_DEPTH | FTW_ACTIONRETVAL)) + { + __set_errno (EINVAL); + return -1; + } + return ftw_startup (path, 1, func, descriptors, flags); +} + +versioned_symbol (libc, NFTW_NEW_NAME, NFTW_NAME, GLIBC_2_3_3); + +#if SHLIB_COMPAT(libc, GLIBC_2_1, GLIBC_2_3_3) + +/* Older nftw* version just ignored all unknown flags. */ + +int +NFTW_OLD_NAME (path, func, descriptors, flags) + const char *path; + NFTW_FUNC_T func; + int descriptors; + int flags; +{ + flags &= (FTW_PHYS | FTW_MOUNT | FTW_CHDIR | FTW_DEPTH); + return ftw_startup (path, 1, func, descriptors, flags); +} + +compat_symbol (libc, NFTW_OLD_NAME, NFTW_NAME, GLIBC_2_1); +#endif +#endif |