From b7363b496caf60600eefa0a5f2d37f77a5dee606 Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Mon, 24 Jul 2017 23:12:59 -0700 Subject: [PATCH] fts-tests: new module * modules/fts-tests, tests/test-fts.c: New files. --- ChangeLog | 5 ++ modules/fts-tests | 13 +++++ tests/test-fts.c | 142 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 160 insertions(+) create mode 100644 modules/fts-tests create mode 100644 tests/test-fts.c diff --git a/ChangeLog b/ChangeLog index 43401d2ada..05ac15d934 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2017-07-24 Paul Eggert + + fts-tests: new module + * modules/fts-tests, tests/test-fts.c: New files. + 2017-07-23 Bruno Haible Rename module 'strftime' to 'nstrftime'. diff --git a/modules/fts-tests b/modules/fts-tests new file mode 100644 index 0000000000..115bf669af --- /dev/null +++ b/modules/fts-tests @@ -0,0 +1,13 @@ +Files: +tests/test-fts.c + +Depends-on: +errno +remove +unlinkat + +configure.ac: + +Makefile.am: +TESTS += test-fts +check_PROGRAMS += test-fts diff --git a/tests/test-fts.c b/tests/test-fts.c new file mode 100644 index 0000000000..2ce72c96ab --- /dev/null +++ b/tests/test-fts.c @@ -0,0 +1,142 @@ +/* Test the fts function. + Copyright 2017 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +#define BASE "t-fts.tmp" +static char *const argv[2] = { BASE, 0 }; + +static void +perror_exit (char const *message, int status) +{ + perror (message); + exit (status); +} + +/* Remove BASE and all files under it. */ +static void +remove_tree (void) +{ + FTSENT *e; + FTS *ftsp = fts_open (argv, FTS_NOSTAT | FTS_PHYSICAL | FTS_CWDFD, 0); + if (ftsp) + { + while ((e = fts_read (ftsp))) + { + int status = 0; + switch (e->fts_info) + { + case FTS_DP: + status = unlinkat (ftsp->fts_cwd_fd, e->fts_accpath, + AT_REMOVEDIR); + break; + + case FTS_F: case FTS_NSOK: + status = unlinkat (ftsp->fts_cwd_fd, e->fts_accpath, 0); + break; + } + if (status != 0) + perror_exit (e->fts_path, 1); + } + if (fts_close (ftsp) != 0) + perror_exit ("fts_close", 2); + } + else if (errno != ENOENT) + perror_exit (BASE, 3); +} + +int +main (void) +{ + FTS *ftsp; + FTSENT *e; + char buf[sizeof BASE + 100]; + int i; + enum { needles = 4 }; + int needles_seen = 0; + struct stat st; + + remove_tree (); + + /* Create directories BASE, BASE/d, BASE/d/1, BASE/d/2, ..., BASE/d/65536, + to stress-test fts. Stop if directory creation fails due to + EMFILE problems, or if BASE/d's link count no longer matches the + Unix tradition. See: + https://bugzilla.kernel.org/show_bug.cgi?id=196405 + for more info. */ + if (mkdir (BASE, 0777) != 0) + perror_exit (BASE, 4); + if (mkdir (BASE "/d", 0777) != 0) + perror_exit (BASE "/d", 5); + for (i = 1; i <= 65536; i++) + { + sprintf (buf, "%s/d/%i", BASE, i); + if (mkdir (buf, 0777) != 0) + { + if (errno != EMFILE || i <= needles) + perror_exit (buf, 77); + break; + } + if (needles < i && stat (BASE "/d", &st) == 0 && st.st_nlink != i + 2) + break; + } + + /* Create empty files BASE/d/1/needle etc. */ + for (i = 1; i <= needles; i++) + { + int fd; + sprintf (buf, "%s/d/%d/needle", BASE, i); + fd = open (buf, O_WRONLY | O_CREAT, 0666); + if (fd < 0 || close (fd) != 0) + perror_exit (buf, 77); + } + + /* Use fts to look for the needles. */ + ftsp = fts_open (argv, FTS_SEEDOT | FTS_NOSTAT | FTS_PHYSICAL | FTS_CWDFD, 0); + if (!ftsp) + perror_exit (BASE, 6); + while ((e = fts_read (ftsp))) + needles_seen += strcmp (e->fts_name, "needle") == 0; + fflush (stdout); + if (errno) + perror_exit ("fts_read", 7); + + /* Report an error if we did not find the needles. */ + if (needles_seen != needles) + { + fprintf (stderr, "%d needles found (should be %d)\n", + needles_seen, needles); + return 1; + } + + remove_tree (); + if (stat (BASE, &st) == 0) + { + fprintf (stderr, "fts could not remove directory\n"); + return 1; + } + return 0; +} -- 2.39.5