This is the mail archive of the libc-hacker@sources.redhat.com mailing list for the glibc project.
Note that libc-hacker is a closed list. You may look at the archives of this list, but subscription and posting are not open.
| Index Nav: | [Date Index] [Subject Index] [Author Index] [Thread Index] | |
|---|---|---|
| Message Nav: | [Date Prev] [Date Next] | [Thread Prev] [Thread Next] |
Hi!
If the depth level at which {,n}ftw callback decides to return non-zero is
bigger than the descriptors argument passed to {,n}ftw, we trigger an
assertion in ftw_dir and depending on NDEBUG either don't behave correctly
or abort. It is perfectly valid situation though, we just need to free dir
contents and return that value.
This patch fixes this plus adds a testcase for this (which fails unless this
patch is applied).
2000-12-14 Jakub Jelinek <jakub@redhat.com>
* io/ftw.c (ftw_dir): If process_entry returned non-zero result
and dir.stream is NULL, only free dir.content.
* io/ftwtest.c (cb, main): Add --early-exit option to test it.
* io/ftwtest-sh: Test with --early-exit.
--- libc/io/ftw.c.jj Wed May 3 10:19:51 2000
+++ libc/io/ftw.c Thu Dec 14 13:21:16 2000
@@ -426,18 +426,17 @@ ftw_dir (struct ftw_data *data, struct S
int save_err;
char *runp = dir.content;
- assert (result == 0);
+ if (result == 0)
+ while (*runp != '\0')
+ {
+ char *endp = strchr (runp, '\0');
- while (*runp != '\0')
- {
- char *endp = strchr (runp, '\0');
+ result = process_entry (data, &dir, runp, endp - runp);
+ if (result != 0)
+ break;
- result = process_entry (data, &dir, runp, endp - runp);
- if (result != 0)
- break;
-
- runp = endp + 1;
- }
+ runp = endp + 1;
+ }
save_err = errno;
free (dir.content);
--- libc/io/ftwtest.c.jj Fri Sep 19 18:57:36 1997
+++ libc/io/ftwtest.c Thu Dec 14 13:56:26 2000
@@ -10,12 +10,14 @@
int do_depth;
int do_chdir;
int do_phys;
+int do_exit;
struct option options[] =
{
{ "depth", no_argument, &do_depth, 1 },
{ "chdir", no_argument, &do_chdir, 1 },
{ "phys", no_argument, &do_phys, 1 },
+ { "early-exit", no_argument, &do_exit, 1 },
{ NULL, 0, NULL, 0 }
};
@@ -34,6 +36,9 @@ const char *flag2name[] =
int
cb (const char *name, const struct stat *st, int flag, struct FTW *f)
{
+ if (do_exit && strcmp (name + f->base, "file@2"))
+ return 0;
+
printf ("base = \"%.*s\", file = \"%s\", flag = %s",
f->base, name, name + f->base, flag2name[flag]);
if (do_chdir)
@@ -43,7 +48,7 @@ cb (const char *name, const struct stat
free (cwd);
}
printf (", level = %d\n", f->level);
- return 0;
+ return do_exit ? 26 : 0;
}
int
@@ -64,8 +69,13 @@ main (int argc, char *argv[])
if (do_phys)
flag |= FTW_PHYS;
- r = nftw (optind < argc ? argv[optind] : ".", cb, 3, flag);
- if (r)
+ r = nftw (optind < argc ? argv[optind] : ".", cb, do_exit ? 1 : 3, flag);
+ if (r < 0)
perror ("nftw");
+ if (do_exit)
+ {
+ puts (r == 26 ? "succeeded" : "failed");
+ return r == 26 ? 0 : 1;
+ }
return r;
}
--- libc/io/ftwtest-sh.jj Thu Jul 27 15:58:52 2000
+++ libc/io/ftwtest-sh Thu Dec 14 13:58:47 2000
@@ -5,10 +5,12 @@ objpfx=$1
# We expect one parameter which is the test program. This must understand
# a number options:
-# --phys use the FTW_PHYS flag
-# --chdir use the FTW_CHDIR and print the current directory in the
-# callback
-# --depth use the FTW_DEPTH flag
+# --phys use the FTW_PHYS flag
+# --chdir use the FTW_CHDIR and print the current directory
+# in the callback
+# --depth use the FTW_DEPTH flag
+# --early-exit print file@2 item only and return non-zero from the
+# callback when it is seen
testprogram=$2
# We cannot test this as root.
@@ -133,6 +135,15 @@ base = "$tmp/ftwtest.d/foo/lvl1/", file
base = "$tmp/ftwtest.d/foo/lvl1/lvl2/", file = "file@2", flag = FTW_F, cwd = $tmpreal/ftwtest.d/foo/lvl1/lvl2, level = 4
base = "$tmp/ftwtest.d/foo/lvl1/lvl2/", file = "lvl3", flag = FTW_D, cwd = $tmpreal/ftwtest.d/foo/lvl1/lvl2, level = 4
base = "$tmp/ftwtest.d/foo/lvl1/lvl2/lvl3/", file = "file@3", flag = FTW_F, cwd = $tmpreal/ftwtest.d/foo/lvl1/lvl2/lvl3, level = 5
+EOF
+rm $testout
+
+LD_LIBRARY_PATH=$objpfx $ldso $testprogram --early-exit $tmpdir |
+ sort > $testout
+
+cat <<EOF | cmp $testout - || exit 1
+base = "$tmp/ftwtest.d/foo/lvl1/lvl2/", file = "file@2", flag = FTW_F, level = 4
+succeeded
EOF
rm $testout
Jakub
| Index Nav: | [Date Index] [Subject Index] [Author Index] [Thread Index] | |
|---|---|---|
| Message Nav: | [Date Prev] [Date Next] | [Thread Prev] [Thread Next] |