From cf3b6a11724d87837830e3e5390a6cacf6af1cd4 Mon Sep 17 00:00:00 2001 From: Bruno Haible Date: Sun, 14 Nov 2010 00:57:14 +0100 Subject: [PATCH] rename, renameat: Avoid test failures at NFS mounted locations. * tests/test-rename.h (dentry_exists, assert_nonexistent): New functions. (test_rename): Use assert_nonexistent. * tests/test-rename.c: Include . * tests/test-renameat.c: Likewise. Reported by Gary V. Vaughan . --- ChangeLog | 8 ++++++++ tests/test-rename.c | 1 + tests/test-rename.h | 51 +++++++++++++++++++++++++++++++++++++++++++++------ tests/test-renameat.c | 1 + 4 files changed, 55 insertions(+), 6 deletions(-) diff --git a/ChangeLog b/ChangeLog index 5ea657c54..aaa02eff1 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,13 @@ 2010-11-13 Bruno Haible + rename, renameat: Avoid test failures at NFS mounted locations. + * tests/test-rename.h (dentry_exists, assert_nonexistent): New + functions. + (test_rename): Use assert_nonexistent. + * tests/test-rename.c: Include . + * tests/test-renameat.c: Likewise. + Reported by Gary V. Vaughan . + rename, renameat: Document Linux bug with NFS . * doc/posix-functions/rename.texi: Mention the NFS bug on Linux. diff --git a/tests/test-rename.c b/tests/test-rename.c index c5c6c4391..0bc27b6c0 100644 --- a/tests/test-rename.c +++ b/tests/test-rename.c @@ -21,6 +21,7 @@ #include "signature.h" SIGNATURE_CHECK (rename, int, (char const *, char const *)); +#include #include #include #include diff --git a/tests/test-rename.h b/tests/test-rename.h index 97530524a..b8ff4fed1 100644 --- a/tests/test-rename.h +++ b/tests/test-rename.h @@ -20,6 +20,49 @@ appropriate headers are already included. If PRINT, warn before skipping symlink tests with status 77. */ +/* Tests whether a file, given by a file name without slashes, exists in + the current directory, by scanning the directory entries. */ +static bool +dentry_exists (const char *filename) +{ + bool exists = false; + DIR *dir = opendir ("."); + + ASSERT (dir != NULL); + for (;;) + { + struct dirent *d = readdir (dir); + if (d == NULL) + break; + if (strcmp (d->d_name, filename) == 0) + { + exists = true; + break; + } + } + ASSERT (closedir (dir) == 0); + return exists; +} + +/* Asserts that a specific file, given by a file name without slashes, does + not exist in the current directory. */ +static void +assert_nonexistent (const char *filename) +{ + struct stat st; + + /* The usual way to test the presence of a file is via stat() or lstat(). */ + errno = 0; + if (stat (filename, &st) == -1) + ASSERT (errno == ENOENT); + else + /* But after renaming a directory over an empty directory on an NFS-mounted + file system, on Linux 2.6.18, for a period of 30 seconds the old + directory name is "present" according to stat() but "nonexistent" + according to dentry_exists(). */ + ASSERT (!dentry_exists (filename)); +} + static int test_rename (int (*func) (char const *, char const *), bool print) { @@ -226,9 +269,7 @@ test_rename (int (*func) (char const *, char const *), bool print) } { /* Full onto empty. */ ASSERT (func (BASE "dir", BASE "dir2") == 0); - errno = 0; - ASSERT (stat (BASE "dir", &st) == -1); - ASSERT (errno == ENOENT); + assert_nonexistent (BASE "dir"); ASSERT (stat (BASE "dir2/file", &st) == 0); /* Files present here: {BASE}file @@ -263,9 +304,7 @@ test_rename (int (*func) (char const *, char const *), bool print) */ { ASSERT (func (BASE "dir", BASE "dir2/") == 0); - errno = 0; - ASSERT (stat (BASE "dir", &st) == -1); - ASSERT (errno == ENOENT); + assert_nonexistent (BASE "dir"); ASSERT (stat (BASE "dir2/file", &st) == 0); } /* Files present here: diff --git a/tests/test-renameat.c b/tests/test-renameat.c index 6292ba08a..f9a561106 100644 --- a/tests/test-renameat.c +++ b/tests/test-renameat.c @@ -23,6 +23,7 @@ #include "signature.h" SIGNATURE_CHECK (renameat, int, (int, char const *, int, char const *)); +#include #include #include #include -- 2.11.0