Blame gnulib/tests/test-canonicalize-lgpl.c

Packit 06dd63
/* Test of execution of program termination handlers.
Packit 06dd63
   Copyright (C) 2007-2019 Free Software Foundation, Inc.
Packit 06dd63
Packit 06dd63
   This program is free software: you can redistribute it and/or modify
Packit 06dd63
   it under the terms of the GNU General Public License as published by
Packit 06dd63
   the Free Software Foundation; either version 3 of the License, or
Packit 06dd63
   (at your option) any later version.
Packit 06dd63
Packit 06dd63
   This program is distributed in the hope that it will be useful,
Packit 06dd63
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 06dd63
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit 06dd63
   GNU General Public License for more details.
Packit 06dd63
Packit 06dd63
   You should have received a copy of the GNU General Public License
Packit 06dd63
   along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
Packit 06dd63
Packit 06dd63
/* Written by Bruno Haible <bruno@clisp.org>, 2007.  */
Packit 06dd63
Packit 06dd63
#include <config.h>
Packit 06dd63
Packit 06dd63
#include <stdlib.h>
Packit 06dd63
Packit 06dd63
#include "signature.h"
Packit 06dd63
SIGNATURE_CHECK (realpath, char *, (const char *, char *));
Packit 06dd63
SIGNATURE_CHECK (canonicalize_file_name, char *, (const char *));
Packit 06dd63
Packit 06dd63
#include <errno.h>
Packit 06dd63
#include <fcntl.h>
Packit 06dd63
#include <stdio.h>
Packit 06dd63
#include <string.h>
Packit 06dd63
#include <sys/stat.h>
Packit 06dd63
#include <unistd.h>
Packit 06dd63
Packit 06dd63
#include "same-inode.h"
Packit 06dd63
#include "ignore-value.h"
Packit 06dd63
Packit 06dd63
#include "null-ptr.h"
Packit 06dd63
#include "macros.h"
Packit 06dd63
Packit 06dd63
#define BASE "t-can-lgpl.tmp"
Packit 06dd63
Packit 06dd63
int
Packit 06dd63
main (void)
Packit 06dd63
{
Packit 06dd63
#if GNULIB_TEST_CANONICALIZE
Packit 06dd63
  /* No need to test canonicalize-lgpl module if canonicalize is also
Packit 06dd63
     in use.  */
Packit 06dd63
  return 0;
Packit 06dd63
#endif
Packit 06dd63
Packit 06dd63
  /* Setup some hierarchy to be used by this test.  Start by removing
Packit 06dd63
     any leftovers from a previous partial run.  */
Packit 06dd63
  {
Packit 06dd63
    int fd;
Packit 06dd63
    ignore_value (system ("rm -rf " BASE " ise"));
Packit 06dd63
    ASSERT (mkdir (BASE, 0700) == 0);
Packit 06dd63
    fd = creat (BASE "/tra", 0600);
Packit 06dd63
    ASSERT (0 <= fd);
Packit 06dd63
    ASSERT (close (fd) == 0);
Packit 06dd63
  }
Packit 06dd63
Packit 06dd63
  /* Check for ., .., intermediate // handling, and for error cases.  */
Packit 06dd63
  {
Packit 06dd63
    char *result = canonicalize_file_name (BASE "//./..//" BASE "/tra");
Packit 06dd63
    ASSERT (result != NULL);
Packit 06dd63
    ASSERT (strstr (result, "/" BASE "/tra")
Packit 06dd63
            == result + strlen (result) - strlen ("/" BASE "/tra"));
Packit 06dd63
    free (result);
Packit 06dd63
    errno = 0;
Packit 06dd63
    result = canonicalize_file_name ("");
Packit 06dd63
    ASSERT (result == NULL);
Packit 06dd63
    ASSERT (errno == ENOENT);
Packit 06dd63
    errno = 0;
Packit 06dd63
    result = canonicalize_file_name (null_ptr ());
Packit 06dd63
    ASSERT (result == NULL);
Packit 06dd63
    ASSERT (errno == EINVAL);
Packit 06dd63
  }
Packit 06dd63
Packit 06dd63
  /* Check that a non-directory with trailing slash yields NULL.  */
Packit 06dd63
  {
Packit 06dd63
    char *result;
Packit 06dd63
    errno = 0;
Packit 06dd63
    result = canonicalize_file_name (BASE "/tra/");
Packit 06dd63
    ASSERT (result == NULL);
Packit 06dd63
    ASSERT (errno == ENOTDIR);
Packit 06dd63
  }
Packit 06dd63
Packit 06dd63
  /* Check that a missing directory yields NULL.  */
Packit 06dd63
  {
Packit 06dd63
    char *result;
Packit 06dd63
    errno = 0;
Packit 06dd63
    result = canonicalize_file_name (BASE "/zzz/..");
Packit 06dd63
    ASSERT (result == NULL);
Packit 06dd63
    ASSERT (errno == ENOENT);
Packit 06dd63
  }
Packit 06dd63
Packit 06dd63
  /* From here on out, tests involve symlinks.  */
Packit 06dd63
  if (symlink (BASE "/ket", "ise") != 0)
Packit 06dd63
    {
Packit 06dd63
      ASSERT (remove (BASE "/tra") == 0);
Packit 06dd63
      ASSERT (rmdir (BASE) == 0);
Packit 06dd63
      fputs ("skipping test: symlinks not supported on this file system\n",
Packit 06dd63
             stderr);
Packit 06dd63
      return 77;
Packit 06dd63
    }
Packit 06dd63
  ASSERT (symlink ("bef", BASE "/plo") == 0);
Packit 06dd63
  ASSERT (symlink ("tra", BASE "/huk") == 0);
Packit 06dd63
  ASSERT (symlink ("lum", BASE "/bef") == 0);
Packit 06dd63
  ASSERT (symlink ("wum", BASE "/ouk") == 0);
Packit 06dd63
  ASSERT (symlink ("../ise", BASE "/ket") == 0);
Packit 06dd63
  ASSERT (mkdir (BASE "/lum", 0700) == 0);
Packit 06dd63
  ASSERT (symlink ("//.//../..", BASE "/droot") == 0);
Packit 06dd63
Packit 06dd63
  /* Check that the symbolic link to a file can be resolved.  */
Packit 06dd63
  {
Packit 06dd63
    char *result1 = canonicalize_file_name (BASE "/huk");
Packit 06dd63
    char *result2 = canonicalize_file_name (BASE "/tra");
Packit 06dd63
    ASSERT (result1 != NULL);
Packit 06dd63
    ASSERT (result2 != NULL);
Packit 06dd63
    ASSERT (strcmp (result1, result2) == 0);
Packit 06dd63
    ASSERT (strcmp (result1 + strlen (result1) - strlen ("/" BASE "/tra"),
Packit 06dd63
                    "/" BASE "/tra") == 0);
Packit 06dd63
    free (result1);
Packit 06dd63
    free (result2);
Packit 06dd63
  }
Packit 06dd63
Packit 06dd63
  /* Check that the symbolic link to a directory can be resolved.  */
Packit 06dd63
  {
Packit 06dd63
    char *result1 = canonicalize_file_name (BASE "/plo");
Packit 06dd63
    char *result2 = canonicalize_file_name (BASE "/bef");
Packit 06dd63
    char *result3 = canonicalize_file_name (BASE "/lum");
Packit 06dd63
    ASSERT (result1 != NULL);
Packit 06dd63
    ASSERT (result2 != NULL);
Packit 06dd63
    ASSERT (result3 != NULL);
Packit 06dd63
    ASSERT (strcmp (result1, result2) == 0);
Packit 06dd63
    ASSERT (strcmp (result2, result3) == 0);
Packit 06dd63
    ASSERT (strcmp (result1 + strlen (result1) - strlen ("/" BASE "/lum"),
Packit 06dd63
                    "/" BASE "/lum") == 0);
Packit 06dd63
    free (result1);
Packit 06dd63
    free (result2);
Packit 06dd63
    free (result3);
Packit 06dd63
  }
Packit 06dd63
Packit 06dd63
  /* Check that a symbolic link to a nonexistent file yields NULL.  */
Packit 06dd63
  {
Packit 06dd63
    char *result;
Packit 06dd63
    errno = 0;
Packit 06dd63
    result = canonicalize_file_name (BASE "/ouk");
Packit 06dd63
    ASSERT (result == NULL);
Packit 06dd63
    ASSERT (errno == ENOENT);
Packit 06dd63
  }
Packit 06dd63
Packit 06dd63
  /* Check that a non-directory symlink with trailing slash yields NULL.  */
Packit 06dd63
  {
Packit 06dd63
    char *result;
Packit 06dd63
    errno = 0;
Packit 06dd63
    result = canonicalize_file_name (BASE "/huk/");
Packit 06dd63
    ASSERT (result == NULL);
Packit 06dd63
    ASSERT (errno == ENOTDIR);
Packit 06dd63
  }
Packit 06dd63
Packit 06dd63
  /* Check that a missing directory via symlink yields NULL.  */
Packit 06dd63
  {
Packit 06dd63
    char *result;
Packit 06dd63
    errno = 0;
Packit 06dd63
    result = canonicalize_file_name (BASE "/ouk/..");
Packit 06dd63
    ASSERT (result == NULL);
Packit 06dd63
    ASSERT (errno == ENOENT);
Packit 06dd63
  }
Packit 06dd63
Packit 06dd63
  /* Check that a loop of symbolic links is detected.  */
Packit 06dd63
  {
Packit 06dd63
    char *result;
Packit 06dd63
    errno = 0;
Packit 06dd63
    result = canonicalize_file_name ("ise");
Packit 06dd63
    ASSERT (result == NULL);
Packit 06dd63
    ASSERT (errno == ELOOP);
Packit 06dd63
  }
Packit 06dd63
Packit 06dd63
  /* Check that leading // is honored correctly.  */
Packit 06dd63
  {
Packit 06dd63
    struct stat st1;
Packit 06dd63
    struct stat st2;
Packit 06dd63
    char *result1 = canonicalize_file_name ("//.");
Packit 06dd63
    char *result2 = canonicalize_file_name (BASE "/droot");
Packit 06dd63
    ASSERT (result1);
Packit 06dd63
    ASSERT (result2);
Packit 06dd63
    ASSERT (stat ("/", &st1) == 0);
Packit 06dd63
    ASSERT (stat ("//", &st2) == 0);
Packit 06dd63
    /* On IBM z/OS, "/" and "//" are distinct, yet they both have
Packit 06dd63
       st_dev == st_ino == 1.  */
Packit 06dd63
#ifndef __MVS__
Packit 06dd63
    if (SAME_INODE (st1, st2))
Packit 06dd63
      {
Packit 06dd63
        ASSERT (strcmp (result1, "/") == 0);
Packit 06dd63
        ASSERT (strcmp (result2, "/") == 0);
Packit 06dd63
      }
Packit 06dd63
    else
Packit 06dd63
#endif
Packit 06dd63
      {
Packit 06dd63
        ASSERT (strcmp (result1, "//") == 0);
Packit 06dd63
        ASSERT (strcmp (result2, "//") == 0);
Packit 06dd63
      }
Packit 06dd63
    free (result1);
Packit 06dd63
    free (result2);
Packit 06dd63
  }
Packit 06dd63
Packit 06dd63
Packit 06dd63
  /* Cleanup.  */
Packit 06dd63
  ASSERT (remove (BASE "/droot") == 0);
Packit 06dd63
  ASSERT (remove (BASE "/plo") == 0);
Packit 06dd63
  ASSERT (remove (BASE "/huk") == 0);
Packit 06dd63
  ASSERT (remove (BASE "/bef") == 0);
Packit 06dd63
  ASSERT (remove (BASE "/ouk") == 0);
Packit 06dd63
  ASSERT (remove (BASE "/ket") == 0);
Packit 06dd63
  ASSERT (remove (BASE "/lum") == 0);
Packit 06dd63
  ASSERT (remove (BASE "/tra") == 0);
Packit 06dd63
  ASSERT (remove (BASE) == 0);
Packit 06dd63
  ASSERT (remove ("ise") == 0);
Packit 06dd63
Packit 06dd63
  return 0;
Packit 06dd63
}