rename, renameat: Avoid test failures at NFS mounted locations.
authorBruno Haible <bruno@clisp.org>
Sat, 13 Nov 2010 23:57:14 +0000 (00:57 +0100)
committerBruno Haible <bruno@clisp.org>
Sat, 13 Nov 2010 23:57:14 +0000 (00:57 +0100)
* tests/test-rename.h (dentry_exists, assert_nonexistent): New
functions.
(test_rename): Use assert_nonexistent.
* tests/test-rename.c: Include <dirent.h>.
* tests/test-renameat.c: Likewise.
Reported by Gary V. Vaughan <gary@gnu.org>.

ChangeLog
tests/test-rename.c
tests/test-rename.h
tests/test-renameat.c

index 5ea657c5435223b888d5236cf7465e2a64544a42..aaa02eff17ffc9e934a644652d31f3b2d9cd11a3 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,13 @@
 2010-11-13  Bruno Haible  <bruno@clisp.org>
 
+       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 <dirent.h>.
+       * tests/test-renameat.c: Likewise.
+       Reported by Gary V. Vaughan <gary@gnu.org>.
+
        rename, renameat: Document Linux bug with NFS
        <http://lists.gnu.org/archive/html/bug-gnulib/2010-11/msg00154.html>.
        * doc/posix-functions/rename.texi: Mention the NFS bug on Linux.
index c5c6c439195f70c576c955ef65fed8e44e1f2d41..0bc27b6c0685f41c82e6c192881bc00501defb4c 100644 (file)
@@ -21,6 +21,7 @@
 #include "signature.h"
 SIGNATURE_CHECK (rename, int, (char const *, char const *));
 
+#include <dirent.h>
 #include <errno.h>
 #include <fcntl.h>
 #include <stdbool.h>
index 97530524ad270c07f8de661a122a837c0d4232d7..b8ff4fed16be86450699ba0f751f214de2ec5056 100644 (file)
    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:
index 6292ba08a24bed7a30edbeeda5723dd306577d47..f9a561106bfe8c49b44ff78b566037865674e10d 100644 (file)
@@ -23,6 +23,7 @@
 #include "signature.h"
 SIGNATURE_CHECK (renameat, int, (int, char const *, int, char const *));
 
+#include <dirent.h>
 #include <fcntl.h>
 #include <errno.h>
 #include <stdbool.h>