Blame gnulib-tests/test-readlink.h

Packit 33f14e
/* Tests of readlink.
Packit 33f14e
   Copyright (C) 2009-2017 Free Software Foundation, Inc.
Packit 33f14e
Packit 33f14e
   This program is free software: you can redistribute it and/or modify
Packit 33f14e
   it under the terms of the GNU General Public License as published by
Packit 33f14e
   the Free Software Foundation; either version 3 of the License, or
Packit 33f14e
   (at your option) any later version.
Packit 33f14e
Packit 33f14e
   This program is distributed in the hope that it will be useful,
Packit 33f14e
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 33f14e
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit 33f14e
   GNU General Public License for more details.
Packit 33f14e
Packit 33f14e
   You should have received a copy of the GNU General Public License
Packit 33f14e
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
Packit 33f14e
Packit 33f14e
/* Written by Eric Blake <ebb9@byu.net>, 2009.  */
Packit 33f14e
Packit 33f14e
/* This file is designed to test both readlink(a,b,c) and
Packit 33f14e
   readlinkat(AT_FDCWD,a,b,c).  FUNC is the function to test.  Assumes
Packit 33f14e
   that BASE and ASSERT are already defined, and that appropriate
Packit 33f14e
   headers are already included.  If PRINT, warn before skipping
Packit 33f14e
   symlink tests with status 77.  */
Packit 33f14e
Packit 33f14e
static int
Packit 33f14e
test_readlink (ssize_t (*func) (char const *, char *, size_t), bool print)
Packit 33f14e
{
Packit 33f14e
  char buf[80];
Packit 33f14e
Packit 33f14e
  /* Sanity checks of failures.  Mingw lacks symlink, but readlink can
Packit 33f14e
     still distinguish between various errors.  */
Packit 33f14e
  memset (buf, 0xff, sizeof buf);
Packit 33f14e
  errno = 0;
Packit 33f14e
  ASSERT (func ("no_such", buf, sizeof buf) == -1);
Packit 33f14e
  ASSERT (errno == ENOENT);
Packit 33f14e
  errno = 0;
Packit 33f14e
  ASSERT (func ("no_such/", buf, sizeof buf) == -1);
Packit 33f14e
  ASSERT (errno == ENOENT);
Packit 33f14e
  errno = 0;
Packit 33f14e
  ASSERT (func ("", buf, sizeof buf) == -1);
Packit 33f14e
  ASSERT (errno == ENOENT || errno == EINVAL);
Packit 33f14e
  errno = 0;
Packit 33f14e
  ASSERT (func (".", buf, sizeof buf) == -1);
Packit 33f14e
  ASSERT (errno == EINVAL);
Packit 33f14e
  errno = 0;
Packit 33f14e
  ASSERT (func ("./", buf, sizeof buf) == -1);
Packit 33f14e
  ASSERT (errno == EINVAL);
Packit 33f14e
  ASSERT (close (creat (BASE "file", 0600)) == 0);
Packit 33f14e
  errno = 0;
Packit 33f14e
  ASSERT (func (BASE "file", buf, sizeof buf) == -1);
Packit 33f14e
  ASSERT (errno == EINVAL);
Packit 33f14e
  errno = 0;
Packit 33f14e
  ASSERT (func (BASE "file/", buf, sizeof buf) == -1);
Packit 33f14e
  ASSERT (errno == ENOTDIR || errno == EINVAL); /* AIX yields EINVAL */
Packit 33f14e
Packit 33f14e
  /* Now test actual symlinks.  */
Packit 33f14e
  if (symlink (BASE "dir", BASE "link"))
Packit 33f14e
    {
Packit 33f14e
      ASSERT (unlink (BASE "file") == 0);
Packit 33f14e
      if (print)
Packit 33f14e
        fputs ("skipping test: symlinks not supported on this file system\n",
Packit 33f14e
               stderr);
Packit 33f14e
      return 77;
Packit 33f14e
    }
Packit 33f14e
  ASSERT (mkdir (BASE "dir", 0700) == 0);
Packit 33f14e
  errno = 0;
Packit 33f14e
  ASSERT (func (BASE "link/", buf, sizeof buf) == -1);
Packit 33f14e
  ASSERT (errno == EINVAL);
Packit 33f14e
  ASSERT (symlink (BASE "link", BASE "link2") == 0);
Packit 33f14e
  errno = 0;
Packit 33f14e
  ASSERT (func (BASE "link2/", buf, sizeof buf) == -1);
Packit 33f14e
  ASSERT (errno == EINVAL);
Packit 33f14e
  ASSERT (unlink (BASE "link2") == 0);
Packit 33f14e
  ASSERT (symlink (BASE "file", BASE "link2") == 0);
Packit 33f14e
  errno = 0;
Packit 33f14e
  ASSERT (func (BASE "link2/", buf, sizeof buf) == -1);
Packit 33f14e
  ASSERT (errno == ENOTDIR || errno == EINVAL); /* AIX yields EINVAL */
Packit 33f14e
  ASSERT (unlink (BASE "file") == 0);
Packit 33f14e
  ASSERT (unlink (BASE "link2") == 0);
Packit 33f14e
  {
Packit 33f14e
    /* Up till now, no readlink has been successful, so buf should be
Packit 33f14e
       unchanged.  */
Packit 33f14e
    int i;
Packit 33f14e
    for (i = 0; i < sizeof buf; i++)
Packit 33f14e
      ASSERT (buf[i] == (char) 0xff);
Packit 33f14e
  }
Packit 33f14e
  {
Packit 33f14e
    size_t len = strlen (BASE "dir");
Packit 33f14e
    /* When passing too small of a buffer, expect the truncated
Packit 33f14e
       length, or an ERANGE failure.  However, a size of 0 is not
Packit 33f14e
       portable enough to test.  */
Packit 33f14e
    ssize_t result;
Packit 33f14e
    errno = 0;
Packit 33f14e
    result = readlink (BASE "link", buf, 1);
Packit 33f14e
    if (result == -1)
Packit 33f14e
      {
Packit 33f14e
        ASSERT (errno == ERANGE);
Packit 33f14e
        ASSERT (buf[0] == (char) 0xff);
Packit 33f14e
      }
Packit 33f14e
    else
Packit 33f14e
      {
Packit 33f14e
        ASSERT (result == 1);
Packit 33f14e
        ASSERT (buf[0] == BASE[0]);
Packit 33f14e
      }
Packit 33f14e
    ASSERT (buf[1] == (char) 0xff);
Packit 33f14e
    ASSERT (func (BASE "link", buf, len) == len);
Packit 33f14e
    ASSERT (strncmp (buf, BASE "dir", len) == 0);
Packit 33f14e
    ASSERT (buf[len] == (char) 0xff);
Packit 33f14e
    ASSERT (func (BASE "link", buf, sizeof buf) == len);
Packit 33f14e
    ASSERT (strncmp (buf, BASE "dir", len) == 0);
Packit 33f14e
    /* POSIX says rest of buf is unspecified; but in practice, it is
Packit 33f14e
       either left alone, or NUL-terminated.  */
Packit 33f14e
    ASSERT (buf[len] == '\0' || buf[len] == (char) 0xff);
Packit 33f14e
  }
Packit 33f14e
  ASSERT (rmdir (BASE "dir") == 0);
Packit 33f14e
  ASSERT (unlink (BASE "link") == 0);
Packit 33f14e
Packit 33f14e
  return 0;
Packit 33f14e
}