root/maint/gnulib/tests/test-link.h

/* [previous][next][first][last][top][bottom][index][help] */

INCLUDED FROM


DEFINITIONS

This source file includes following definitions.
  1. test_link

   1 /* Test of link() function.
   2    Copyright (C) 2009-2021 Free Software Foundation, Inc.
   3 
   4    This program is free software: you can redistribute it and/or modify
   5    it under the terms of the GNU General Public License as published by
   6    the Free Software Foundation; either version 3 of the License, or
   7    (at your option) any later version.
   8 
   9    This program is distributed in the hope that it will be useful,
  10    but WITHOUT ANY WARRANTY; without even the implied warranty of
  11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12    GNU General Public License for more details.
  13 
  14    You should have received a copy of the GNU General Public License
  15    along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
  16 
  17 /* This file is designed to test both link(a,b) and
  18    linkat(AT_FDCWD,a,AT_FDCWD,b,0).  FUNC is the function to test.
  19    Assumes that BASE and ASSERT are already defined, and that
  20    appropriate headers are already included.  If PRINT, warn before
  21    skipping tests with status 77.  This test does not try to create
  22    hard links to symlinks, but does test other aspects of symlink.  */
  23 
  24 static int
  25 test_link (int (*func) (char const *, char const *), bool print)
     /* [previous][next][first][last][top][bottom][index][help] */
  26 {
  27   int fd;
  28   int ret;
  29 
  30   /* Create first file.  */
  31   fd = open (BASE "a", O_CREAT | O_EXCL | O_WRONLY, 0600);
  32   ASSERT (0 <= fd);
  33   ASSERT (write (fd, "hello", 5) == 5);
  34   ASSERT (close (fd) == 0);
  35 
  36   /* Not all file systems support link.  Mingw doesn't have reliable
  37      st_nlink on hard links, but our implementation does fail with
  38      EPERM on poor file systems, and we can detect the inferior stat()
  39      via st_ino.  Cygwin 1.5.x copies rather than links files on those
  40      file systems, but there, st_nlink and st_ino are reliable.  */
  41   ret = func (BASE "a", BASE "b");
  42   if (!ret)
  43   {
  44     struct stat st;
  45     ASSERT (stat (BASE "b", &st) == 0);
  46     if (st.st_ino && st.st_nlink != 2)
  47       {
  48         ASSERT (unlink (BASE "b") == 0);
  49         errno = EPERM;
  50         ret = -1;
  51       }
  52   }
  53   if (ret == -1)
  54     {
  55       /* If the device does not support hard links, errno is
  56          EPERM on Linux, EOPNOTSUPP on FreeBSD.  */
  57       switch (errno)
  58         {
  59         case EPERM:
  60         case EOPNOTSUPP:
  61           if (print)
  62             fputs ("skipping test: "
  63                    "hard links not supported on this file system\n",
  64                    stderr);
  65           ASSERT (unlink (BASE "a") == 0);
  66           return 77;
  67         default:
  68           perror ("link");
  69           return 1;
  70         }
  71     }
  72   ASSERT (ret == 0);
  73 
  74   /* Now, for some behavior tests.  Modify the contents of 'b', and
  75      ensure that 'a' can see it, both while 'b' exists and after.  */
  76   fd = open (BASE "b", O_APPEND | O_WRONLY);
  77   ASSERT (0 <= fd);
  78   ASSERT (write (fd, "world", 5) == 5);
  79   ASSERT (close (fd) == 0);
  80   {
  81     char buf[11] = { 0 };
  82     fd = open (BASE "a", O_RDONLY);
  83     ASSERT (0 <= fd);
  84     ASSERT (read (fd, buf, 10) == 10);
  85     ASSERT (strcmp (buf, "helloworld") == 0);
  86     ASSERT (close (fd) == 0);
  87     ASSERT (unlink (BASE "b") == 0);
  88     fd = open (BASE "a", O_RDONLY);
  89     ASSERT (0 <= fd);
  90     ASSERT (read (fd, buf, 10) == 10);
  91     ASSERT (strcmp (buf, "helloworld") == 0);
  92     ASSERT (close (fd) == 0);
  93   }
  94 
  95   /* Test for various error conditions.  */
  96   ASSERT (mkdir (BASE "d", 0700) == 0);
  97   errno = 0;
  98   ASSERT (func (BASE "a", ".") == -1);
  99   ASSERT (errno == EEXIST || errno == EINVAL);
 100   errno = 0;
 101   ASSERT (func (BASE "a", BASE "a") == -1);
 102   ASSERT (errno == EEXIST);
 103   ASSERT (func (BASE "a", BASE "b") == 0);
 104   errno = 0;
 105   ASSERT (func (BASE "a", BASE "b") == -1);
 106   ASSERT (errno == EEXIST);
 107   errno = 0;
 108   ASSERT (func (BASE "a", BASE "d") == -1);
 109   ASSERT (errno == EEXIST);
 110   errno = 0;
 111   ASSERT (func (BASE "c", BASE "e") == -1);
 112   ASSERT (errno == ENOENT);
 113   errno = 0;
 114   ASSERT (func (BASE "a", BASE "c/.") == -1);
 115   ASSERT (errno == ENOENT);
 116   errno = 0;
 117   ASSERT (func (BASE "a/", BASE "c") == -1);
 118   ASSERT (errno == ENOTDIR || errno == EINVAL);
 119   errno = 0;
 120   ASSERT (func (BASE "a", BASE "c/") == -1);
 121   ASSERT (errno == ENOTDIR || errno == ENOENT || errno == EINVAL);
 122 
 123   /* Most platforms reject hard links to directories, and even on
 124      those that do permit it, most users can't create them.  We assume
 125      that if this test is run as root and we managed to create a hard
 126      link, then unlink better be able to clean it up.  */
 127   {
 128     int result;
 129     errno = 0;
 130     result = func (BASE "d", BASE "c");
 131     if (result == 0)
 132       {
 133         /* Probably root on Solaris.  */
 134         ASSERT (unlink (BASE "c") == 0);
 135       }
 136     else
 137       {
 138         /* Most everyone else.  */
 139         ASSERT (errno == EPERM || errno == EACCES || errno == EISDIR);
 140         errno = 0;
 141         ASSERT (func (BASE "d/.", BASE "c") == -1);
 142         ASSERT (errno == EPERM || errno == EACCES || errno == EISDIR
 143                 || errno == EINVAL);
 144         errno = 0;
 145         ASSERT (func (BASE "d/.//", BASE "c") == -1);
 146         ASSERT (errno == EPERM || errno == EACCES || errno == EISDIR
 147                 || errno == EINVAL);
 148       }
 149   }
 150   ASSERT (unlink (BASE "a") == 0);
 151   errno = 0;
 152   ASSERT (unlink (BASE "c") == -1);
 153   ASSERT (errno == ENOENT);
 154   ASSERT (rmdir (BASE "d") == 0);
 155 
 156   /* Test invalid use of symlink.  */
 157   if (symlink (BASE "a", BASE "link") != 0)
 158     {
 159       ASSERT (unlink (BASE "b") == 0);
 160       if (print)
 161         fputs ("skipping test: symlinks not supported on this file system\n",
 162                stderr);
 163       return 77;
 164     }
 165   errno = 0;
 166   ASSERT (func (BASE "b", BASE "link/") == -1);
 167   ASSERT (errno == ENOTDIR || errno == ENOENT || errno == EEXIST
 168           || errno == EINVAL);
 169   errno = 0;
 170   ASSERT (func (BASE "b", BASE "link") == -1);
 171   ASSERT (errno == EEXIST);
 172   ASSERT (rename (BASE "b", BASE "a") == 0);
 173   errno = 0;
 174   ASSERT (func (BASE "link/", BASE "b") == -1);
 175   ASSERT (errno == ENOTDIR || errno == EEXIST || errno == EINVAL);
 176 
 177   /* Clean up.  */
 178   ASSERT (unlink (BASE "a") == 0);
 179   ASSERT (unlink (BASE "link") == 0);
 180 
 181   return 0;
 182 }

/* [previous][next][first][last][top][bottom][index][help] */