version-etc: new year
[gnulib.git] / tests / test-link.h
index 9ce1894..d546d56 100644 (file)
@@ -1,9 +1,9 @@
 /* Test of link() function.
-   Copyright (C) 2009 Free Software Foundation, Inc.
+   Copyright (C) 2009-2013 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,
    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
-#include <config.h>
-
 /* This file is designed to test both link(a,b) and
-   linkat(AT_FDCWD,a,AT_FDCWD,b).  FUNC is the function to test.
+   linkat(AT_FDCWD,a,AT_FDCWD,b,0).  FUNC is the function to test.
    Assumes that BASE and ASSERT are already defined, and that
    appropriate headers are already included.  If PRINT, warn before
-   skipping symlink tests with status 77.  */
+   skipping tests with status 77.  This test does not try to create
+   hard links to symlinks, but does test other aspects of symlink.  */
 
 static int
 test_link (int (*func) (char const *, char const *), bool print)
@@ -54,21 +53,21 @@ test_link (int (*func) (char const *, char const *), bool print)
   if (ret == -1)
     {
       /* If the device does not support hard links, errno is
-        EPERM on Linux, EOPNOTSUPP on FreeBSD.  */
+         EPERM on Linux, EOPNOTSUPP on FreeBSD.  */
       switch (errno)
-       {
-       case EPERM:
-       case EOPNOTSUPP:
+        {
+        case EPERM:
+        case EOPNOTSUPP:
           if (print)
             fputs ("skipping test: "
                    "hard links not supported on this file system\n",
                    stderr);
           ASSERT (unlink (BASE "a") == 0);
-         return 77;
-       default:
-         perror ("link");
-         return 1;
-       }
+          return 77;
+        default:
+          perror ("link");
+          return 1;
+        }
     }
   ASSERT (ret == 0);
 
@@ -93,8 +92,7 @@ test_link (int (*func) (char const *, char const *), bool print)
     ASSERT (close (fd) == 0);
   }
 
-  /* Test for various error conditions.  Assumes hard links to
-     directories are not permitted.  */
+  /* Test for various error conditions.  */
   ASSERT (mkdir (BASE "d", 0700) == 0);
   errno = 0;
   ASSERT (func (BASE "a", ".") == -1);
@@ -117,21 +115,68 @@ test_link (int (*func) (char const *, char const *), bool print)
   ASSERT (errno == ENOENT);
   errno = 0;
   ASSERT (func (BASE "a/", BASE "c") == -1);
-  ASSERT (errno == ENOTDIR);
+  ASSERT (errno == ENOTDIR || errno == EINVAL);
   errno = 0;
   ASSERT (func (BASE "a", BASE "c/") == -1);
-  ASSERT (errno == ENOTDIR || errno == ENOENT);
-  errno = 0;
-  ASSERT (func (BASE "d", BASE "c") == -1);
-  ASSERT (errno == EPERM || errno == EACCES);
+  ASSERT (errno == ENOTDIR || errno == ENOENT || errno == EINVAL);
 
-  /* Clean up.  */
+  /* Most platforms reject hard links to directories, and even on
+     those that do permit it, most users can't create them.  We assume
+     that if this test is run as root and we managed to create a hard
+     link, then unlink better be able to clean it up.  */
+  {
+    int result;
+    errno = 0;
+    result = func (BASE "d", BASE "c");
+    if (result == 0)
+      {
+        /* Probably root on Solaris.  */
+        ASSERT (unlink (BASE "c") == 0);
+      }
+    else
+      {
+        /* Most everyone else.  */
+        ASSERT (errno == EPERM || errno == EACCES || errno == EISDIR);
+        errno = 0;
+        ASSERT (func (BASE "d/.", BASE "c") == -1);
+        ASSERT (errno == EPERM || errno == EACCES || errno == EISDIR
+                || errno == EINVAL);
+        errno = 0;
+        ASSERT (func (BASE "d/.//", BASE "c") == -1);
+        ASSERT (errno == EPERM || errno == EACCES || errno == EISDIR
+                || errno == EINVAL);
+      }
+  }
   ASSERT (unlink (BASE "a") == 0);
-  ASSERT (unlink (BASE "b") == 0);
   errno = 0;
   ASSERT (unlink (BASE "c") == -1);
   ASSERT (errno == ENOENT);
   ASSERT (rmdir (BASE "d") == 0);
 
+  /* Test invalid use of symlink.  */
+  if (symlink (BASE "a", BASE "link") != 0)
+    {
+      ASSERT (unlink (BASE "b") == 0);
+      if (print)
+        fputs ("skipping test: symlinks not supported on this file system\n",
+               stderr);
+      return 77;
+    }
+  errno = 0;
+  ASSERT (func (BASE "b", BASE "link/") == -1);
+  ASSERT (errno == ENOTDIR || errno == ENOENT || errno == EEXIST
+          || errno == EINVAL);
+  errno = 0;
+  ASSERT (func (BASE "b", BASE "link") == -1);
+  ASSERT (errno == EEXIST);
+  ASSERT (rename (BASE "b", BASE "a") == 0);
+  errno = 0;
+  ASSERT (func (BASE "link/", BASE "b") == -1);
+  ASSERT (errno == ENOTDIR || errno == EEXIST || errno == EINVAL);
+
+  /* Clean up.  */
+  ASSERT (unlink (BASE "a") == 0);
+  ASSERT (unlink (BASE "link") == 0);
+
   return 0;
 }