Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
Ulrich Drepper committed Nov 7, 2003
1 parent c685b2b commit ca10f33
Show file tree
Hide file tree
Showing 8 changed files with 260 additions and 30 deletions.
27 changes: 27 additions & 0 deletions ChangeLog
@@ -1,3 +1,30 @@
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.

2003-11-04 Jakub Jelinek <jakub@redhat.com>

* io/ftw.c (ftw_dir): Close dir if callback with FTW_D type returns
Expand Down
4 changes: 4 additions & 0 deletions io/Versions
Expand Up @@ -93,6 +93,10 @@ libc {
# l*
lchmod;
}
GLIBC_2.3.3 {
# n*
nftw; nftw64;
}
GLIBC_PRIVATE {
# functions which have an additional interface since they are
# cancelable.
Expand Down
112 changes: 85 additions & 27 deletions io/ftw.c
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -550,6 +534,9 @@ ftw_dir (struct ftw_data *data, struct STAT *st)
__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;
Expand All @@ -559,11 +546,37 @@ ftw_dir (struct ftw_data *data, struct STAT *st)
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)
Expand Down Expand Up @@ -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
{
Expand All @@ -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). */
Expand Down Expand Up @@ -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;
Expand All @@ -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
26 changes: 26 additions & 0 deletions io/ftw.h
Expand Up @@ -74,7 +74,33 @@ enum
# define FTW_CHDIR FTW_CHDIR
FTW_DEPTH = 8 /* Report files in directory before directory itself.*/
# define FTW_DEPTH FTW_DEPTH
# ifdef __USE_GNU
,
FTW_ACTIONRETVAL = 16 /* Assume callback to return FTW_* values instead of
zero to continue and non-zero to terminate. */
# define FTW_ACTIONRETVAL FTW_ACTIONRETVAL
# endif
};

#ifdef __USE_GNU
/* Return values from callback functions. */
enum
{
FTW_CONTINUE = 0, /* Continue with next sibling or for FTW_D with the
first child. */
# define FTW_CONTINUE FTW_CONTINUE
FTW_STOP = 1, /* Return from `ftw' or `nftw' with FTW_STOP as return
value. */
# define FTW_STOP FTW_STOP
FTW_SKIP_SUBTREE = 2, /* Only meaningful for FTW_D: Don't walk through the
subtree, instead just continue with its next
sibling. */
# define FTW_SKIP_SUBTREE FTW_SKIP_SUBTREE
FTW_SKIP_SIBLINGS = 3,/* Continue with FTW_DP callback for current directory
(if FTW_DEPTH) and then its siblings. */
# define FTW_SKIP_SIBLINGS FTW_SKIP_SIBLINGS
};
#endif

/* Structure used for fourth argument to callback function for `nftw'. */
struct FTW
Expand Down
2 changes: 2 additions & 0 deletions io/ftw64.c
Expand Up @@ -20,6 +20,8 @@

#define FTW_NAME ftw64
#define NFTW_NAME nftw64
#define NFTW_OLD_NAME __old_nftw64
#define NFTW_NEW_NAME __new_nftw64
#define INO_T ino64_t
#define STAT stat64
#define LXSTAT __lxstat64
Expand Down
77 changes: 77 additions & 0 deletions io/ftwtest-sh
Expand Up @@ -202,6 +202,83 @@ succeeded
EOF
rm $testout

mkdir $tmpdir/foo/lvl1b
echo > $tmpdir/foo/lvl1b/file@1b
echo > $tmpdir/foo/lvl1b/file2@1b
echo > $tmpdir/foo/lvl1b/file3@1b

LD_LIBRARY_PATH=$objpfx $ldso $testprogram --skip-subtree=lvl1 $tmpdir |
sort > $testout

cat <<EOF | diff -u $testout - || exit 1
base = "/tmp/", file = "ftwtest.d", flag = FTW_D, level = 0
base = "/tmp/ftwtest.d/", file = "bar", flag = FTW_D, level = 1
base = "/tmp/ftwtest.d/", file = "baz", flag = FTW_F, level = 1
base = "/tmp/ftwtest.d/", file = "foo", flag = FTW_D, level = 1
base = "/tmp/ftwtest.d/bar/", file = "xo", flag = FTW_F, level = 2
base = "/tmp/ftwtest.d/foo/", file = "lvl1", flag = FTW_D, level = 2
base = "/tmp/ftwtest.d/foo/", file = "lvl1b", flag = FTW_D, level = 2
base = "/tmp/ftwtest.d/foo/lvl1b/", file = "file2@1b", flag = FTW_F, level = 3
base = "/tmp/ftwtest.d/foo/lvl1b/", file = "file3@1b", flag = FTW_F, level = 3
base = "/tmp/ftwtest.d/foo/lvl1b/", file = "file@1b", flag = FTW_F, level = 3
EOF
rm $testout

LD_LIBRARY_PATH=$objpfx $ldso $testprogram --skip-siblings=lvl1 $tmpdir |
sort > $testout

# The filesystem is not required to put lvl1 before lvl1b.
# If lvl1b comes after lvl1, it shouldn't be printed, while if it
# comes before, it should.
catcmd=cat
[ -n "`ls -U $tmpdir/foo/ | sed -n '/lvl1$/,${/lvl1b$/p}'`" ] \
&& catcmd="grep -v lvl1b"

$catcmd <<EOF | diff -u $testout - || exit 1
base = "/tmp/", file = "ftwtest.d", flag = FTW_D, level = 0
base = "/tmp/ftwtest.d/", file = "bar", flag = FTW_D, level = 1
base = "/tmp/ftwtest.d/", file = "baz", flag = FTW_F, level = 1
base = "/tmp/ftwtest.d/", file = "foo", flag = FTW_D, level = 1
base = "/tmp/ftwtest.d/bar/", file = "xo", flag = FTW_F, level = 2
base = "/tmp/ftwtest.d/foo/", file = "lvl1", flag = FTW_D, level = 2
base = "/tmp/ftwtest.d/foo/", file = "lvl1b", flag = FTW_D, level = 2
base = "/tmp/ftwtest.d/foo/lvl1b/", file = "file2@1b", flag = FTW_F, level = 3
base = "/tmp/ftwtest.d/foo/lvl1b/", file = "file3@1b", flag = FTW_F, level = 3
base = "/tmp/ftwtest.d/foo/lvl1b/", file = "file@1b", flag = FTW_F, level = 3
EOF
rm $testout

LD_LIBRARY_PATH=$objpfx $ldso $testprogram --skip-siblings=file@1b $tmpdir |
sort > $testout

# The filesystem is not required to put file2@1b and file3@1b after file@1b.
# If file[23]@1b come after file@1b, it shouldn't be printed, while if they
# come before, they should.
regexp=`echo $(ls -U /tmp/ftwtest.d/foo/lvl1b \
| sed -n '/file@1b$/,${/file[23]@1b$/p}') | sed 's, ,|,'`
catcmd=cat
[ -n "$regexp" ] && catcmd="egrep -v $regexp"

$catcmd <<EOF | diff -u $testout - || exit 1
base = "/tmp/", file = "ftwtest.d", flag = FTW_D, level = 0
base = "/tmp/ftwtest.d/", file = "bar", flag = FTW_D, level = 1
base = "/tmp/ftwtest.d/", file = "baz", flag = FTW_F, level = 1
base = "/tmp/ftwtest.d/", file = "foo", flag = FTW_D, level = 1
base = "/tmp/ftwtest.d/bar/", file = "xo", flag = FTW_F, level = 2
base = "/tmp/ftwtest.d/foo/", file = "lvl1", flag = FTW_D, level = 2
base = "/tmp/ftwtest.d/foo/", file = "lvl1b", flag = FTW_D, level = 2
base = "/tmp/ftwtest.d/foo/lvl1/", file = "file@1", flag = FTW_F, level = 3
base = "/tmp/ftwtest.d/foo/lvl1/", file = "link@1", flag = FTW_SLN, level = 3
base = "/tmp/ftwtest.d/foo/lvl1/", file = "lvl2", flag = FTW_D, level = 3
base = "/tmp/ftwtest.d/foo/lvl1/lvl2/", file = "file@2", flag = FTW_F, level = 4
base = "/tmp/ftwtest.d/foo/lvl1/lvl2/", file = "lvl3", flag = FTW_D, level = 4
base = "/tmp/ftwtest.d/foo/lvl1/lvl2/lvl3/", file = "file@3", flag = FTW_F, level = 5
base = "/tmp/ftwtest.d/foo/lvl1b/", file = "file2@1b", flag = FTW_F, level = 3
base = "/tmp/ftwtest.d/foo/lvl1b/", file = "file3@1b", flag = FTW_F, level = 3
base = "/tmp/ftwtest.d/foo/lvl1b/", file = "file@1b", flag = FTW_F, level = 3
EOF
rm $testout

rm -fr $tmpdir

exit 0

0 comments on commit ca10f33

Please sign in to comment.