doc: use ASCII in .texi files where UTF-8 isn't needed
[gnulib.git] / tests / test-rename.h
index 63ec8ca..2bc610f 100644 (file)
@@ -1,9 +1,9 @@
 /* Test of rename() function.
-   Copyright (C) 2009 Free Software Foundation, Inc.
+   Copyright (C) 2009-2014 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 2 of the License, or
+   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,
    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));
+      /* Remove the old directory name, so that subsequent mkdir calls
+         succeed.  */
+      (void) rmdir (filename);
+    }
+}
+
 static int
 test_rename (int (*func) (char const *, char const *), bool print)
 {
@@ -31,168 +79,400 @@ test_rename (int (*func) (char const *, char const *), bool print)
   ASSERT (close (fd) == 0);
   ASSERT (mkdir (BASE "dir", 0700) == 0);
 
+  /* Files present here:
+       {BASE}file
+       {BASE}dir/
+   */
+
   /* Obvious errors.  */
 
-  errno = 0; /* Missing source.  */
-  ASSERT (func (BASE "missing", BASE "missing") == -1);
-  ASSERT (errno == ENOENT);
-  errno = 0;
-  ASSERT (func (BASE "missing/", BASE "missing") == -1);
-  ASSERT (errno == ENOENT);
-  errno = 0;
-  ASSERT (func (BASE "missing", BASE "missing/") == -1);
-  ASSERT (errno == ENOENT);
-  errno = 0; /* Empty operand.  */
-  ASSERT (func ("", BASE "missing") == -1);
-  ASSERT (errno == ENOENT);
-  errno = 0;
-  ASSERT (func (BASE "file", "") == -1);
-  ASSERT (errno == ENOENT);
-  errno = 0;
-  ASSERT (func (BASE "", "") == -1);
-  ASSERT (errno == ENOENT);
+  { /* Missing source.  */
+    {
+      errno = 0;
+      ASSERT (func (BASE "missing", BASE "missing") == -1);
+      ASSERT (errno == ENOENT);
+    }
+    {
+      errno = 0;
+      ASSERT (func (BASE "missing/", BASE "missing") == -1);
+      ASSERT (errno == ENOENT);
+    }
+    {
+      errno = 0;
+      ASSERT (func (BASE "missing", BASE "missing/") == -1);
+      ASSERT (errno == ENOENT);
+    }
+  }
+  { /* Empty operand.  */
+    {
+      errno = 0;
+      ASSERT (func ("", BASE "missing") == -1);
+      ASSERT (errno == ENOENT);
+    }
+    {
+      errno = 0;
+      ASSERT (func (BASE "file", "") == -1);
+      ASSERT (errno == ENOENT);
+    }
+    {
+      errno = 0;
+      ASSERT (func (BASE "", "") == -1);
+      ASSERT (errno == ENOENT);
+    }
+  }
 
   /* Files.  */
-  errno = 0; /* Trailing slash.  */
-  ASSERT (func (BASE "file", BASE "file2/") == -1);
-  ASSERT (errno == ENOENT || errno == ENOTDIR);
-  errno = 0;
-  ASSERT (func (BASE "file/", BASE "file2") == -1);
-  ASSERT (errno == ENOTDIR);
-  errno = 0;
-  ASSERT (stat (BASE "file2", &st) == -1);
-  ASSERT (errno == ENOENT);
-  ASSERT (func (BASE "file", BASE "file2") == 0); /* Simple rename.  */
-  errno = 0;
-  ASSERT (stat (BASE "file", &st) == -1);
-  ASSERT (errno == ENOENT);
-  memset (&st, 0, sizeof st);
-  ASSERT (stat (BASE "file2", &st) == 0);
-  ASSERT (st.st_size == 2);
-  ASSERT (close (creat (BASE "file", 0600)) == 0); /* Overwrite.  */
-  errno = 0;
-  ASSERT (func (BASE "file2", BASE "file/") == -1);
-  ASSERT (errno == ENOTDIR);
-  ASSERT (func (BASE "file2", BASE "file") == 0);
-  memset (&st, 0, sizeof st);
-  ASSERT (stat (BASE "file", &st) == 0);
-  ASSERT (st.st_size == 2);
-  errno = 0;
-  ASSERT (stat (BASE "file2", &st) == -1);
-  ASSERT (errno == ENOENT);
+
+  { /* Trailing slash.  */
+    {
+      errno = 0;
+      ASSERT (func (BASE "file", BASE "file2/") == -1);
+      ASSERT (errno == ENOENT || errno == ENOTDIR);
+    }
+    {
+      errno = 0;
+      ASSERT (func (BASE "file/", BASE "file2") == -1);
+      ASSERT (errno == ENOTDIR);
+    }
+    {
+      errno = 0;
+      ASSERT (stat (BASE "file2", &st) == -1);
+      ASSERT (errno == ENOENT);
+    }
+  }
+  { /* Simple rename.  */
+    ASSERT (func (BASE "file", BASE "file2") == 0);
+    errno = 0;
+    ASSERT (stat (BASE "file", &st) == -1);
+    ASSERT (errno == ENOENT);
+    memset (&st, 0, sizeof st);
+    ASSERT (stat (BASE "file2", &st) == 0);
+    ASSERT (st.st_size == 2);
+  }
+  /* Files present here:
+       {BASE}file2
+       {BASE}dir/
+   */
+  { /* Overwrite.  */
+    ASSERT (close (creat (BASE "file", 0600)) == 0);
+    errno = 0;
+    ASSERT (func (BASE "file2", BASE "file/") == -1);
+    ASSERT (errno == ENOTDIR);
+    ASSERT (func (BASE "file2", BASE "file") == 0);
+    memset (&st, 0, sizeof st);
+    ASSERT (stat (BASE "file", &st) == 0);
+    ASSERT (st.st_size == 2);
+    errno = 0;
+    ASSERT (stat (BASE "file2", &st) == -1);
+    ASSERT (errno == ENOENT);
+  }
+  /* Files present here:
+       {BASE}file
+       {BASE}dir/
+   */
 
   /* Directories.  */
-  ASSERT (func (BASE "dir", BASE "dir2/") == 0); /* Simple rename.  */
-  errno = 0;
-  ASSERT (stat (BASE "dir", &st) == -1);
-  ASSERT (errno == ENOENT);
-  ASSERT (stat (BASE "dir2", &st) == 0);
-  ASSERT (func (BASE "dir2/", BASE "dir") == 0);
-  ASSERT (stat (BASE "dir", &st) == 0);
-  errno = 0;
-  ASSERT (stat (BASE "dir2", &st) == -1);
-  ASSERT (errno == ENOENT);
-  ASSERT (func (BASE "dir", BASE "dir2") == 0);
-  errno = 0;
-  ASSERT (stat (BASE "dir", &st) == -1);
-  ASSERT (errno == ENOENT);
-  ASSERT (stat (BASE "dir2", &st) == 0);
-  ASSERT (mkdir (BASE "dir", 0700) == 0); /* Empty onto empty.  */
-  ASSERT (func (BASE "dir2", BASE "dir") == 0);
-  ASSERT (mkdir (BASE "dir2", 0700) == 0);
-  ASSERT (func (BASE "dir2", BASE "dir/") == 0);
-  ASSERT (mkdir (BASE "dir2", 0700) == 0);
-  ASSERT (func (BASE "dir2/", BASE "dir") == 0);
-  ASSERT (mkdir (BASE "dir2", 0700) == 0);
-  ASSERT (close (creat (BASE "dir/file", 0600)) == 0); /* Empty onto full.  */
-  errno = 0;
-  ASSERT (func (BASE "dir2", BASE "dir") == -1);
-  ASSERT (errno == EEXIST || errno == ENOTEMPTY);
-  errno = 0;
-  ASSERT (func (BASE "dir2/", BASE "dir") == -1);
-  ASSERT (errno == EEXIST || errno == ENOTEMPTY);
-  errno = 0;
-  ASSERT (func (BASE "dir2", BASE "dir/") == -1);
-  ASSERT (errno == EEXIST || errno == ENOTEMPTY);
-  ASSERT (func (BASE "dir", BASE "dir2") == 0); /* Full onto empty.  */
-  errno = 0;
-  ASSERT (stat (BASE "dir", &st) == -1);
-  ASSERT (errno == ENOENT);
-  ASSERT (stat (BASE "dir2/file", &st) == 0);
-  ASSERT (mkdir (BASE "dir", 0700) == 0);
-  ASSERT (func (BASE "dir2/", BASE "dir") == 0);
-  ASSERT (stat (BASE "dir/file", &st) == 0);
-  errno = 0;
-  ASSERT (stat (BASE "dir2", &st) == -1);
-  ASSERT (errno == ENOENT);
-  ASSERT (mkdir (BASE "dir2", 0700) == 0);
-  ASSERT (func (BASE "dir", BASE "dir2/") == 0);
-  errno = 0;
-  ASSERT (stat (BASE "dir", &st) == -1);
-  ASSERT (errno == ENOENT);
-  ASSERT (stat (BASE "dir2/file", &st) == 0);
-  ASSERT (unlink (BASE "dir2/file") == 0);
-  errno = 0; /* Reject trailing dot.  */
-  ASSERT (func (BASE "dir2", BASE "dir/.") == -1);
-  ASSERT (errno == EINVAL || errno == ENOENT);
-  ASSERT (mkdir (BASE "dir", 0700) == 0);
-  errno = 0;
-  ASSERT (func (BASE "dir2", BASE "dir/.") == -1);
-  ASSERT (errno == EINVAL || errno == EBUSY || errno == EISDIR
-          || errno == ENOTEMPTY);
-  errno = 0;
-  ASSERT (func (BASE "dir2/.", BASE "dir") == -1);
-  ASSERT (errno == EINVAL || errno == EBUSY);
-  ASSERT (rmdir (BASE "dir") == 0);
-  errno = 0;
-  ASSERT (func (BASE "dir2", BASE "dir/.//") == -1);
-  ASSERT (errno == EINVAL || errno == ENOENT);
-  ASSERT (mkdir (BASE "dir", 0700) == 0);
-  errno = 0;
-  ASSERT (func (BASE "dir2", BASE "dir/.//") == -1);
-  ASSERT (errno == EINVAL || errno == EBUSY || errno == EISDIR
-          || errno == ENOTEMPTY);
-  errno = 0;
-  ASSERT (func (BASE "dir2/.//", BASE "dir") == -1);
-  ASSERT (errno == EINVAL || errno == EBUSY);
-  ASSERT (rmdir (BASE "dir2") == 0);
-  errno = 0; /* Move into subdir.  */
-  ASSERT (func (BASE "dir", BASE "dir/sub") == -1);
-  ASSERT (errno == EINVAL || errno == EACCES);
-  errno = 0;
-  ASSERT (stat (BASE "dir/sub", &st) == -1);
-  ASSERT (errno == ENOENT);
-  ASSERT (mkdir (BASE "dir/sub", 0700) == 0);
-  errno = 0;
-  ASSERT (func (BASE "dir", BASE "dir/sub") == -1);
-  ASSERT (errno == EINVAL);
-  ASSERT (stat (BASE "dir/sub", &st) == 0);
-  ASSERT (rmdir (BASE "dir/sub") == 0);
+
+  { /* Simple rename.  */
+    {
+      ASSERT (func (BASE "dir", BASE "dir2/") == 0);
+      errno = 0;
+      ASSERT (stat (BASE "dir", &st) == -1);
+      ASSERT (errno == ENOENT);
+      ASSERT (stat (BASE "dir2", &st) == 0);
+    }
+    /* Files present here:
+         {BASE}file
+         {BASE}dir2/
+     */
+    {
+      ASSERT (func (BASE "dir2/", BASE "dir") == 0);
+      ASSERT (stat (BASE "dir", &st) == 0);
+      errno = 0;
+      ASSERT (stat (BASE "dir2", &st) == -1);
+      ASSERT (errno == ENOENT);
+    }
+    /* Files present here:
+         {BASE}file
+         {BASE}dir/
+     */
+    {
+      ASSERT (func (BASE "dir", BASE "dir2") == 0);
+      errno = 0;
+      ASSERT (stat (BASE "dir", &st) == -1);
+      ASSERT (errno == ENOENT);
+      ASSERT (stat (BASE "dir2", &st) == 0);
+    }
+    /* Files present here:
+         {BASE}file
+         {BASE}dir2/
+     */
+    { /* Empty onto empty.  */
+      ASSERT (mkdir (BASE "dir", 0700) == 0);
+      /* Files present here:
+           {BASE}file
+           {BASE}dir/
+           {BASE}dir2/
+       */
+      ASSERT (func (BASE "dir2", BASE "dir") == 0);
+      /* Files present here:
+           {BASE}file
+           {BASE}dir/
+       */
+      ASSERT (mkdir (BASE "dir2", 0700) == 0);
+      /* Files present here:
+           {BASE}file
+           {BASE}dir/
+           {BASE}dir2/
+       */
+      ASSERT (func (BASE "dir2", BASE "dir/") == 0);
+      /* Files present here:
+           {BASE}file
+           {BASE}dir/
+       */
+      ASSERT (mkdir (BASE "dir2", 0700) == 0);
+      /* Files present here:
+           {BASE}file
+           {BASE}dir/
+           {BASE}dir2/
+       */
+      ASSERT (func (BASE "dir2/", BASE "dir") == 0);
+      /* Files present here:
+           {BASE}file
+           {BASE}dir/
+       */
+      ASSERT (mkdir (BASE "dir2", 0700) == 0);
+    }
+    /* Files present here:
+         {BASE}file
+         {BASE}dir/
+         {BASE}dir2/
+     */
+    { /* Empty onto full.  */
+      ASSERT (close (creat (BASE "dir/file", 0600)) == 0);
+      /* Files present here:
+           {BASE}file
+           {BASE}dir/
+           {BASE}dir/file
+           {BASE}dir2/
+       */
+      {
+        errno = 0;
+        ASSERT (func (BASE "dir2", BASE "dir") == -1);
+        ASSERT (errno == EEXIST || errno == ENOTEMPTY);
+      }
+      {
+        errno = 0;
+        ASSERT (func (BASE "dir2/", BASE "dir") == -1);
+        ASSERT (errno == EEXIST || errno == ENOTEMPTY);
+      }
+      {
+        errno = 0;
+        ASSERT (func (BASE "dir2", BASE "dir/") == -1);
+        ASSERT (errno == EEXIST || errno == ENOTEMPTY);
+      }
+    }
+    { /* Full onto empty.  */
+      ASSERT (func (BASE "dir", BASE "dir2") == 0);
+      assert_nonexistent (BASE "dir");
+      ASSERT (stat (BASE "dir2/file", &st) == 0);
+      /* Files present here:
+           {BASE}file
+           {BASE}dir2/
+           {BASE}dir2/file
+       */
+      ASSERT (mkdir (BASE "dir", 0700) == 0);
+      /* Files present here:
+           {BASE}file
+           {BASE}dir/
+           {BASE}dir2/
+           {BASE}dir2/file
+       */
+      {
+        ASSERT (func (BASE "dir2/", BASE "dir") == 0);
+        ASSERT (stat (BASE "dir/file", &st) == 0);
+        errno = 0;
+        ASSERT (stat (BASE "dir2", &st) == -1);
+        ASSERT (errno == ENOENT);
+      }
+      /* Files present here:
+           {BASE}file
+           {BASE}dir/
+           {BASE}dir/file
+       */
+      ASSERT (mkdir (BASE "dir2", 0700) == 0);
+      /* Files present here:
+           {BASE}file
+           {BASE}dir/
+           {BASE}dir/file
+           {BASE}dir2/
+       */
+      {
+        ASSERT (func (BASE "dir", BASE "dir2/") == 0);
+        assert_nonexistent (BASE "dir");
+        ASSERT (stat (BASE "dir2/file", &st) == 0);
+      }
+      /* Files present here:
+           {BASE}file
+           {BASE}dir2/
+           {BASE}dir2/file
+       */
+      ASSERT (unlink (BASE "dir2/file") == 0);
+    }
+    /* Files present here:
+         {BASE}file
+         {BASE}dir2/
+     */
+    { /* Reject trailing dot.  */
+      {
+        errno = 0;
+        ASSERT (func (BASE "dir2", BASE "dir/.") == -1);
+        ASSERT (errno == EINVAL || errno == ENOENT);
+      }
+      ASSERT (mkdir (BASE "dir", 0700) == 0);
+      /* Files present here:
+           {BASE}file
+           {BASE}dir/
+           {BASE}dir2/
+       */
+      {
+        errno = 0;
+        ASSERT (func (BASE "dir2", BASE "dir/.") == -1);
+        ASSERT (errno == EINVAL || errno == EBUSY || errno == EISDIR
+                || errno == ENOTEMPTY || errno == EEXIST);
+      }
+      {
+        errno = 0;
+        ASSERT (func (BASE "dir2/.", BASE "dir") == -1);
+        ASSERT (errno == EINVAL || errno == EBUSY || errno == EEXIST);
+      }
+      ASSERT (rmdir (BASE "dir") == 0);
+      /* Files present here:
+           {BASE}file
+           {BASE}dir2/
+       */
+      {
+        errno = 0;
+        ASSERT (func (BASE "dir2", BASE "dir/.//") == -1);
+        ASSERT (errno == EINVAL || errno == ENOENT);
+      }
+      ASSERT (mkdir (BASE "dir", 0700) == 0);
+      /* Files present here:
+           {BASE}file
+           {BASE}dir/
+           {BASE}dir2/
+       */
+      {
+        errno = 0;
+        ASSERT (func (BASE "dir2", BASE "dir/.//") == -1);
+        ASSERT (errno == EINVAL || errno == EBUSY || errno == EISDIR
+                || errno == ENOTEMPTY || errno == EEXIST);
+      }
+      {
+        errno = 0;
+        ASSERT (func (BASE "dir2/.//", BASE "dir") == -1);
+        ASSERT (errno == EINVAL || errno == EBUSY || errno == EEXIST);
+      }
+      ASSERT (rmdir (BASE "dir2") == 0);
+      /* Files present here:
+           {BASE}file
+           {BASE}dir/
+       */
+    }
+    { /* Move into subdir.  */
+      {
+        errno = 0;
+        ASSERT (func (BASE "dir", BASE "dir/sub") == -1);
+        ASSERT (errno == EINVAL || errno == EACCES);
+      }
+      {
+        errno = 0;
+        ASSERT (stat (BASE "dir/sub", &st) == -1);
+        ASSERT (errno == ENOENT);
+      }
+      ASSERT (mkdir (BASE "dir/sub", 0700) == 0);
+      /* Files present here:
+           {BASE}file
+           {BASE}dir/
+           {BASE}dir/sub/
+       */
+      {
+        errno = 0;
+        ASSERT (func (BASE "dir", BASE "dir/sub") == -1);
+        ASSERT (errno == EINVAL);
+        ASSERT (stat (BASE "dir/sub", &st) == 0);
+      }
+      ASSERT (rmdir (BASE "dir/sub") == 0);
+    }
+  }
+  /* Files present here:
+       {BASE}file
+       {BASE}dir/
+   */
 
   /* Mixing file and directory.  */
-  errno = 0; /* File onto dir.  */
-  ASSERT (func (BASE "file", BASE "dir") == -1);
-  ASSERT (errno == EISDIR || errno == ENOTDIR);
-  errno = 0;
-  ASSERT (func (BASE "file", BASE "dir/") == -1);
-  ASSERT (errno == EISDIR || errno == ENOTDIR);
-  errno = 0; /* Dir onto file.  */
-  ASSERT (func (BASE "dir", BASE "file") == -1);
-  ASSERT (errno == ENOTDIR);
-  errno = 0;
-  ASSERT (func (BASE "dir/", BASE "file") == -1);
-  ASSERT (errno == ENOTDIR);
+
+  {
+    { /* File onto dir.  */
+      {
+        errno = 0;
+        ASSERT (func (BASE "file", BASE "dir") == -1);
+        ASSERT (errno == EISDIR || errno == ENOTDIR);
+      }
+      {
+        errno = 0;
+        ASSERT (func (BASE "file", BASE "dir/") == -1);
+        ASSERT (errno == EISDIR || errno == ENOTDIR);
+      }
+    }
+    { /* Dir onto file.  */
+      {
+        errno = 0;
+        ASSERT (func (BASE "dir", BASE "file") == -1);
+        ASSERT (errno == ENOTDIR);
+      }
+      {
+        errno = 0;
+        ASSERT (func (BASE "dir/", BASE "file") == -1);
+        ASSERT (errno == ENOTDIR);
+      }
+    }
+  }
 
   /* Hard links.  */
-  ASSERT (func (BASE "file", BASE "file") == 0); /* File onto self.  */
-  memset (&st, 0, sizeof st);
-  ASSERT (stat (BASE "file", &st) == 0);
-  ASSERT (st.st_size == 2);
-  ASSERT (func (BASE "dir", BASE "dir") == 0); /* Empty dir onto self.  */
-  ASSERT (stat (BASE "dir", &st) == 0);
+
+  { /* File onto self.  */
+    ASSERT (func (BASE "file", BASE "file") == 0);
+    memset (&st, 0, sizeof st);
+    ASSERT (stat (BASE "file", &st) == 0);
+    ASSERT (st.st_size == 2);
+  }
+  /* Files present here:
+       {BASE}file
+       {BASE}dir/
+   */
+  { /* Empty dir onto self.  */
+    ASSERT (func (BASE "dir", BASE "dir") == 0);
+    ASSERT (stat (BASE "dir", &st) == 0);
+  }
+  /* Files present here:
+       {BASE}file
+       {BASE}dir/
+   */
   ASSERT (close (creat (BASE "dir/file", 0600)) == 0);
-  ASSERT (func (BASE "dir", BASE "dir") == 0); /* Full dir onto self.  */
+  /* Files present here:
+       {BASE}file
+       {BASE}dir/
+       {BASE}dir/file
+   */
+  { /* Full dir onto self.  */
+    ASSERT (func (BASE "dir", BASE "dir") == 0);
+  }
   ASSERT (unlink (BASE "dir/file") == 0);
+  /* Files present here:
+       {BASE}file
+       {BASE}dir/
+   */
   {
     /*  Not all file systems support link.  Mingw doesn't have
         reliable st_nlink on hard links, but our implementation does
@@ -234,16 +514,33 @@ test_rename (int (*func) (char const *, char const *), bool print)
       }
     ASSERT (ret == 0);
   }
-  ASSERT (func (BASE "file", BASE "file2") == 0); /* File onto hard link.  */
-  memset (&st, 0, sizeof st);
-  ASSERT (stat (BASE "file", &st) == 0);
-  ASSERT (st.st_size == 2);
-  memset (&st, 0, sizeof st);
-  ASSERT (stat (BASE "file2", &st) == 0);
-  ASSERT (st.st_size == 2);
+  /* Files present here:
+       {BASE}file
+       {BASE}file2       (hard link to file)
+       {BASE}dir/
+   */
+  { /* File onto hard link.  */
+    ASSERT (func (BASE "file", BASE "file2") == 0);
+    memset (&st, 0, sizeof st);
+    ASSERT (stat (BASE "file", &st) == 0);
+    ASSERT (st.st_size == 2);
+    memset (&st, 0, sizeof st);
+    ASSERT (stat (BASE "file2", &st) == 0);
+    ASSERT (st.st_size == 2);
+  }
+  /* Files present here:
+       {BASE}file
+       {BASE}file2
+       {BASE}dir/
+   */
   ASSERT (unlink (BASE "file2") == 0);
+  /* Files present here:
+       {BASE}file
+       {BASE}dir/
+   */
 
   /* Symlinks.  */
+
   if (symlink (BASE "file", BASE "link1"))
     {
       if (print)
@@ -253,118 +550,298 @@ test_rename (int (*func) (char const *, char const *), bool print)
       ASSERT (rmdir (BASE "dir") == 0);
       return 77;
     }
-  ASSERT (func (BASE "link1", BASE "link2") == 0); /* Simple rename.  */
-  ASSERT (stat (BASE "file", &st) == 0);
-  errno = 0;
-  ASSERT (lstat (BASE "link1", &st) == -1);
-  ASSERT (errno == ENOENT);
-  memset (&st, 0, sizeof st);
-  ASSERT (lstat (BASE "link2", &st) == 0);
-  ASSERT (S_ISLNK (st.st_mode));
-  ASSERT (symlink (BASE "nowhere", BASE "link1") == 0); /* Overwrite.  */
-  ASSERT (func (BASE "link2", BASE "link1") == 0);
-  memset (&st, 0, sizeof st);
-  ASSERT (stat (BASE "link1", &st) == 0);
-  ASSERT (st.st_size == 2);
-  errno = 0;
-  ASSERT (lstat (BASE "link2", &st) == -1);
-  ASSERT (errno == ENOENT);
-  ASSERT (symlink (BASE "link2", BASE "link2") == 0); /* Symlink loop.  */
-  ASSERT (func (BASE "link2", BASE "link2") == 0);
-  errno = 0;
-  ASSERT (func (BASE "link2/", BASE "link2") == -1);
-  ASSERT (errno == ELOOP || errno == ENOTDIR);
-  ASSERT (func (BASE "link2", BASE "link3") == 0);
-  ASSERT (unlink (BASE "link3") == 0);
-  ASSERT (symlink (BASE "nowhere", BASE "link2") == 0); /* Dangling link.  */
-  ASSERT (func (BASE "link2", BASE "link3") == 0);
-  errno = 0;
-  ASSERT (lstat (BASE "link2", &st) == -1);
-  ASSERT (errno == ENOENT);
-  memset (&st, 0, sizeof st);
-  ASSERT (lstat (BASE "link3", &st) == 0);
-  errno = 0; /* Trailing slash on dangling.  */
-  ASSERT (func (BASE "link3/", BASE "link2") == -1);
-  ASSERT (errno == ENOENT || errno == ENOTDIR);
-  errno = 0;
-  ASSERT (func (BASE "link3", BASE "link2/") == -1);
-  ASSERT (errno == ENOENT || errno == ENOTDIR);
-  errno = 0;
-  ASSERT (lstat (BASE "link2", &st) == -1);
-  ASSERT (errno == ENOENT);
-  memset (&st, 0, sizeof st);
-  ASSERT (lstat (BASE "link3", &st) == 0);
-  errno = 0; /* Trailing slash on link to file.  */
-  ASSERT (func (BASE "link1/", BASE "link2") == -1);
-  ASSERT (errno == ENOTDIR);
-  errno = 0;
-  ASSERT (func (BASE "link1", BASE "link3/") == -1);
-  ASSERT (errno == ENOENT || errno == ENOTDIR);
+  /* Files present here:
+       {BASE}file
+       {BASE}link1 -> {BASE}file
+       {BASE}dir/
+   */
+  { /* Simple rename.  */
+    ASSERT (func (BASE "link1", BASE "link2") == 0);
+    ASSERT (stat (BASE "file", &st) == 0);
+    errno = 0;
+    ASSERT (lstat (BASE "link1", &st) == -1);
+    ASSERT (errno == ENOENT);
+    memset (&st, 0, sizeof st);
+    ASSERT (lstat (BASE "link2", &st) == 0);
+    ASSERT (S_ISLNK (st.st_mode));
+  }
+  /* Files present here:
+       {BASE}file
+       {BASE}link2 -> {BASE}file
+       {BASE}dir/
+   */
+  { /* Overwrite.  */
+    ASSERT (symlink (BASE "nowhere", BASE "link1") == 0);
+    /* Files present here:
+         {BASE}file
+         {BASE}link1 -> {BASE}nowhere
+         {BASE}link2 -> {BASE}file
+         {BASE}dir/
+     */
+    {
+      ASSERT (func (BASE "link2", BASE "link1") == 0);
+      memset (&st, 0, sizeof st);
+      ASSERT (stat (BASE "link1", &st) == 0);
+      ASSERT (st.st_size == 2);
+      errno = 0;
+      ASSERT (lstat (BASE "link2", &st) == -1);
+      ASSERT (errno == ENOENT);
+    }
+  }
+  /* Files present here:
+       {BASE}file
+       {BASE}link1 -> {BASE}file
+       {BASE}dir/
+   */
+  { /* Symlink loop.  */
+    ASSERT (symlink (BASE "link2", BASE "link2") == 0);
+    /* Files present here:
+         {BASE}file
+         {BASE}link1 -> {BASE}file
+         {BASE}link2 -> {BASE}link2
+         {BASE}dir/
+     */
+    {
+      ASSERT (func (BASE "link2", BASE "link2") == 0);
+    }
+    {
+      errno = 0;
+      ASSERT (func (BASE "link2/", BASE "link2") == -1);
+      ASSERT (errno == ELOOP || errno == ENOTDIR);
+    }
+    ASSERT (func (BASE "link2", BASE "link3") == 0);
+    /* Files present here:
+         {BASE}file
+         {BASE}link1 -> {BASE}file
+         {BASE}link3 -> {BASE}link2
+         {BASE}dir/
+     */
+    ASSERT (unlink (BASE "link3") == 0);
+  }
+  /* Files present here:
+       {BASE}file
+       {BASE}link1 -> {BASE}file
+       {BASE}dir/
+   */
+  { /* Dangling link.  */
+    ASSERT (symlink (BASE "nowhere", BASE "link2") == 0);
+    /* Files present here:
+         {BASE}file
+         {BASE}link1 -> {BASE}file
+         {BASE}link2 -> {BASE}nowhere
+         {BASE}dir/
+     */
+    {
+      ASSERT (func (BASE "link2", BASE "link3") == 0);
+      errno = 0;
+      ASSERT (lstat (BASE "link2", &st) == -1);
+      ASSERT (errno == ENOENT);
+      memset (&st, 0, sizeof st);
+      ASSERT (lstat (BASE "link3", &st) == 0);
+    }
+  }
+  /* Files present here:
+       {BASE}file
+       {BASE}link1 -> {BASE}file
+       {BASE}link3 -> {BASE}nowhere
+       {BASE}dir/
+   */
+  { /* Trailing slash on dangling.  */
+    {
+      errno = 0;
+      ASSERT (func (BASE "link3/", BASE "link2") == -1);
+      ASSERT (errno == ENOENT || errno == ENOTDIR);
+    }
+    {
+      errno = 0;
+      ASSERT (func (BASE "link3", BASE "link2/") == -1);
+      ASSERT (errno == ENOENT || errno == ENOTDIR);
+    }
+    {
+      errno = 0;
+      ASSERT (lstat (BASE "link2", &st) == -1);
+      ASSERT (errno == ENOENT);
+    }
+    memset (&st, 0, sizeof st);
+    ASSERT (lstat (BASE "link3", &st) == 0);
+  }
+  /* Files present here:
+       {BASE}file
+       {BASE}link1 -> {BASE}file
+       {BASE}link3 -> {BASE}nowhere
+       {BASE}dir/
+   */
+  { /* Trailing slash on link to file.  */
+    {
+      errno = 0;
+      ASSERT (func (BASE "link1/", BASE "link2") == -1);
+      ASSERT (errno == ENOTDIR);
+    }
+    {
+      errno = 0;
+      ASSERT (func (BASE "link1", BASE "link3/") == -1);
+      ASSERT (errno == ENOENT || errno == ENOTDIR);
+    }
+  }
+  /* Files present here:
+       {BASE}file
+       {BASE}link1 -> {BASE}file
+       {BASE}link3 -> {BASE}nowhere
+       {BASE}dir/
+   */
 
   /* Mixing symlink and file.  */
-  ASSERT (close (creat (BASE "file2", 0600)) == 0); /* File onto link.  */
-  ASSERT (func (BASE "file2", BASE "link3") == 0);
-  errno = 0;
-  ASSERT (stat (BASE "file2", &st) == -1);
-  ASSERT (errno == ENOENT);
-  memset (&st, 0, sizeof st);
-  ASSERT (lstat (BASE "link3", &st) == 0);
-  ASSERT (S_ISREG (st.st_mode));
-  ASSERT (unlink (BASE "link3") == 0);
-  ASSERT (symlink (BASE "nowhere", BASE "link2") == 0); /* Link onto file.  */
-  ASSERT (close (creat (BASE "file2", 0600)) == 0);
-  ASSERT (func (BASE "link2", BASE "file2") == 0);
-  errno = 0;
-  ASSERT (lstat (BASE "link2", &st) == -1);
-  ASSERT (errno == ENOENT);
-  memset (&st, 0, sizeof st);
-  ASSERT (lstat (BASE "file2", &st) == 0);
-  ASSERT (S_ISLNK (st.st_mode));
-  ASSERT (unlink (BASE "file2") == 0);
-  errno = 0; /* Trailing slash.  */
-  ASSERT (func (BASE "file/", BASE "link1") == -1);
-  ASSERT (errno == ENOTDIR);
-  errno = 0;
-  ASSERT (func (BASE "file", BASE "link1/") == -1);
-  ASSERT (errno == ENOTDIR || errno == ENOENT);
-  errno = 0;
-  ASSERT (func (BASE "link1/", BASE "file") == -1);
-  ASSERT (errno == ENOTDIR);
-  errno = 0;
-  ASSERT (func (BASE "link1", BASE "file/") == -1);
-  ASSERT (errno == ENOTDIR || errno == ENOENT);
-  memset (&st, 0, sizeof st);
-  ASSERT (lstat (BASE "file", &st) == 0);
-  ASSERT (S_ISREG (st.st_mode));
-  memset (&st, 0, sizeof st);
-  ASSERT (lstat (BASE "link1", &st) == 0);
-  ASSERT (S_ISLNK (st.st_mode));
+
+  { /* File onto link.  */
+    ASSERT (close (creat (BASE "file2", 0600)) == 0);
+    /* Files present here:
+         {BASE}file
+         {BASE}file2
+         {BASE}link1 -> {BASE}file
+         {BASE}link3 -> {BASE}nowhere
+         {BASE}dir/
+     */
+    {
+      ASSERT (func (BASE "file2", BASE "link3") == 0);
+      errno = 0;
+      ASSERT (stat (BASE "file2", &st) == -1);
+      ASSERT (errno == ENOENT);
+      memset (&st, 0, sizeof st);
+      ASSERT (lstat (BASE "link3", &st) == 0);
+      ASSERT (S_ISREG (st.st_mode));
+    }
+    /* Files present here:
+         {BASE}file
+         {BASE}link1 -> {BASE}file
+         {BASE}link3
+         {BASE}dir/
+     */
+    ASSERT (unlink (BASE "link3") == 0);
+  }
+  /* Files present here:
+       {BASE}file
+       {BASE}link1 -> {BASE}file
+       {BASE}dir/
+   */
+  { /* Link onto file.  */
+    ASSERT (symlink (BASE "nowhere", BASE "link2") == 0);
+    /* Files present here:
+         {BASE}file
+         {BASE}link1 -> {BASE}file
+         {BASE}link2 -> {BASE}nowhere
+         {BASE}dir/
+     */
+    ASSERT (close (creat (BASE "file2", 0600)) == 0);
+    /* Files present here:
+         {BASE}file
+         {BASE}file2
+         {BASE}link1 -> {BASE}file
+         {BASE}link2 -> {BASE}nowhere
+         {BASE}dir/
+     */
+    {
+      ASSERT (func (BASE "link2", BASE "file2") == 0);
+      errno = 0;
+      ASSERT (lstat (BASE "link2", &st) == -1);
+      ASSERT (errno == ENOENT);
+      memset (&st, 0, sizeof st);
+      ASSERT (lstat (BASE "file2", &st) == 0);
+      ASSERT (S_ISLNK (st.st_mode));
+    }
+    /* Files present here:
+         {BASE}file
+         {BASE}file2 -> {BASE}nowhere
+         {BASE}link1 -> {BASE}file
+         {BASE}dir/
+     */
+    ASSERT (unlink (BASE "file2") == 0);
+  }
+  /* Files present here:
+       {BASE}file
+       {BASE}link1 -> {BASE}file
+       {BASE}dir/
+   */
+  { /* Trailing slash.  */
+    {
+      errno = 0;
+      ASSERT (func (BASE "file/", BASE "link1") == -1);
+      ASSERT (errno == ENOTDIR);
+    }
+    {
+      errno = 0;
+      ASSERT (func (BASE "file", BASE "link1/") == -1);
+      ASSERT (errno == ENOTDIR || errno == ENOENT);
+    }
+    {
+      errno = 0;
+      ASSERT (func (BASE "link1/", BASE "file") == -1);
+      ASSERT (errno == ENOTDIR);
+    }
+    {
+      errno = 0;
+      ASSERT (func (BASE "link1", BASE "file/") == -1);
+      ASSERT (errno == ENOTDIR || errno == ENOENT);
+      memset (&st, 0, sizeof st);
+      ASSERT (lstat (BASE "file", &st) == 0);
+      ASSERT (S_ISREG (st.st_mode));
+      memset (&st, 0, sizeof st);
+      ASSERT (lstat (BASE "link1", &st) == 0);
+      ASSERT (S_ISLNK (st.st_mode));
+    }
+  }
+  /* Files present here:
+       {BASE}file
+       {BASE}link1 -> {BASE}file
+       {BASE}dir/
+   */
 
   /* Mixing symlink and directory.  */
-  errno = 0; /* Directory onto link.  */
-  ASSERT (func (BASE "dir", BASE "link1") == -1);
-  ASSERT (errno == ENOTDIR);
-  errno = 0;
-  ASSERT (func (BASE "dir/", BASE "link1") == -1);
-  ASSERT (errno == ENOTDIR);
-  errno = 0;
-  ASSERT (func (BASE "dir", BASE "link1/") == -1);
-  ASSERT (errno == ENOTDIR);
-  errno = 0; /* Link onto directory.  */
-  ASSERT (func (BASE "link1", BASE "dir") == -1);
-  ASSERT (errno == EISDIR || errno == ENOTDIR);
-  errno = 0;
-  ASSERT (func (BASE "link1", BASE "dir/") == -1);
-  ASSERT (errno == EISDIR || errno == ENOTDIR);
-  errno = 0;
-  ASSERT (func (BASE "link1/", BASE "dir") == -1);
-  ASSERT (errno == ENOTDIR);
-  memset (&st, 0, sizeof st);
-  ASSERT (lstat (BASE "link1", &st) == 0);
-  ASSERT (S_ISLNK (st.st_mode));
-  memset (&st, 0, sizeof st);
-  ASSERT (lstat (BASE "dir", &st) == 0);
-  ASSERT (S_ISDIR (st.st_mode));
+
+  { /* Directory onto link.  */
+    {
+      errno = 0;
+      ASSERT (func (BASE "dir", BASE "link1") == -1);
+      ASSERT (errno == ENOTDIR);
+    }
+    {
+      errno = 0;
+      ASSERT (func (BASE "dir/", BASE "link1") == -1);
+      ASSERT (errno == ENOTDIR);
+    }
+    {
+      errno = 0;
+      ASSERT (func (BASE "dir", BASE "link1/") == -1);
+      ASSERT (errno == ENOTDIR);
+    }
+  }
+  { /* Link onto directory.  */
+    {
+      errno = 0;
+      ASSERT (func (BASE "link1", BASE "dir") == -1);
+      ASSERT (errno == EISDIR || errno == ENOTDIR);
+    }
+    {
+      errno = 0;
+      ASSERT (func (BASE "link1", BASE "dir/") == -1);
+      ASSERT (errno == EISDIR || errno == ENOTDIR);
+    }
+    {
+      errno = 0;
+      ASSERT (func (BASE "link1/", BASE "dir") == -1);
+      ASSERT (errno == ENOTDIR);
+      memset (&st, 0, sizeof st);
+      ASSERT (lstat (BASE "link1", &st) == 0);
+      ASSERT (S_ISLNK (st.st_mode));
+      memset (&st, 0, sizeof st);
+      ASSERT (lstat (BASE "dir", &st) == 0);
+      ASSERT (S_ISDIR (st.st_mode));
+    }
+  }
+  /* Files present here:
+       {BASE}file
+       {BASE}link1 -> {BASE}file
+       {BASE}dir/
+   */
 
   /* POSIX requires rename("link-to-dir/","other") to rename "dir" and
      leave "link-to-dir" dangling, but GNU rejects this.  POSIX
@@ -376,6 +853,12 @@ test_rename (int (*func) (char const *, char const *), bool print)
   {
     int result;
     ASSERT (symlink (BASE "dir2", BASE "link2") == 0);
+    /* Files present here:
+         {BASE}file
+         {BASE}link1 -> {BASE}file
+         {BASE}link2 -> {BASE}dir2
+         {BASE}dir/
+     */
     errno = 0;
     result = func (BASE "dir", BASE "link2/");
     if (result == 0)
@@ -390,16 +873,24 @@ test_rename (int (*func) (char const *, char const *), bool print)
         memset (&st, 0, sizeof st);
         ASSERT (lstat (BASE "link2", &st) == 0);
         ASSERT (S_ISLNK (st.st_mode));
-        ASSERT (func (BASE "link2/", BASE "dir") == 0);
-        memset (&st, 0, sizeof st);
-        ASSERT (lstat (BASE "dir", &st) == 0);
-        ASSERT (S_ISDIR (st.st_mode));
-        errno = 0;
-        ASSERT (lstat (BASE "dir2", &st) == -1);
-        ASSERT (errno == ENOENT);
-        memset (&st, 0, sizeof st);
-        ASSERT (lstat (BASE "link2", &st) == 0);
-        ASSERT (S_ISLNK (st.st_mode));
+        /* Files present here:
+             {BASE}file
+             {BASE}link1 -> {BASE}file
+             {BASE}link2 -> {BASE}dir2
+             {BASE}dir2/
+         */
+        {
+          ASSERT (func (BASE "link2/", BASE "dir") == 0);
+          memset (&st, 0, sizeof st);
+          ASSERT (lstat (BASE "dir", &st) == 0);
+          ASSERT (S_ISDIR (st.st_mode));
+          errno = 0;
+          ASSERT (lstat (BASE "dir2", &st) == -1);
+          ASSERT (errno == ENOENT);
+          memset (&st, 0, sizeof st);
+          ASSERT (lstat (BASE "link2", &st) == 0);
+          ASSERT (S_ISLNK (st.st_mode));
+        }
       }
     else
       {
@@ -417,12 +908,18 @@ test_rename (int (*func) (char const *, char const *), bool print)
         ASSERT (S_ISLNK (st.st_mode));
         ASSERT (unlink (BASE "link2") == 0);
         ASSERT (symlink (BASE "dir", BASE "link2") == 0);
+        /* Files present here:
+             {BASE}file
+             {BASE}link1 -> {BASE}file
+             {BASE}link2 -> {BASE}dir
+             {BASE}dir/
+         */
         errno = 0; /* OpenBSD notices that link2/ and dir are the same.  */
         result = func (BASE "link2/", BASE "dir");
         if (result) /* GNU/Linux rejects attempts to use link2/.  */
           {
             ASSERT (result == -1);
-            ASSERT (errno == ENOTDIR);
+            ASSERT (errno == ENOTDIR || errno == EISDIR);
           }
         memset (&st, 0, sizeof st);
         ASSERT (lstat (BASE "dir", &st) == 0);
@@ -435,6 +932,12 @@ test_rename (int (*func) (char const *, char const *), bool print)
         ASSERT (S_ISLNK (st.st_mode));
       }
   }
+  /* Files present here:
+       {BASE}file
+       {BASE}link1 -> {BASE}file
+       {BASE}link2 -> {BASE}dir or {BASE}dir2
+       {BASE}dir/
+   */
 
   /* Clean up.  */
   ASSERT (unlink (BASE "file") == 0);