Blame gnulib/tests/test-open.h

Packit 06dd63
/* Test of opening a file descriptor.
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
/* Make test_open always inline if we're using Fortify, which defines
Packit 06dd63
   __always_inline to do that.  Do nothing otherwise.  This works
Packit 06dd63
   around a glibc bug whereby 'open' cannot be used as a function
Packit 06dd63
   pointer when _FORTIFY_SOURCE is positive.  */
Packit 06dd63
Packit 06dd63
#if __GLIBC__ && defined __always_inline
Packit 06dd63
# define ALWAYS_INLINE __always_inline
Packit 06dd63
#else
Packit 06dd63
# define ALWAYS_INLINE
Packit 06dd63
#endif
Packit 06dd63
Packit 06dd63
/* This file is designed to test both open(n,buf[,mode]) and
Packit 06dd63
   openat(AT_FDCWD,n,buf[,mode]).  FUNC is the function to test.
Packit 06dd63
   Assumes that BASE and ASSERT are already defined, and that
Packit 06dd63
   appropriate headers are already included.  If PRINT, warn before
Packit 06dd63
   skipping symlink tests with status 77.  */
Packit 06dd63
Packit 06dd63
static ALWAYS_INLINE int
Packit 06dd63
test_open (int (*func) (char const *, int, ...), bool print)
Packit 06dd63
{
Packit 06dd63
  int fd;
Packit 06dd63
  /* Remove anything from prior partial run.  */
Packit 06dd63
  unlink (BASE "file");
Packit 06dd63
Packit 06dd63
  /* Cannot create directory.  */
Packit 06dd63
  errno = 0;
Packit 06dd63
  ASSERT (func ("nonexist.ent/", O_CREAT | O_RDONLY, 0600) == -1);
Packit 06dd63
  ASSERT (errno == ENOTDIR || errno == EISDIR || errno == ENOENT
Packit 06dd63
          || errno == EINVAL);
Packit 06dd63
Packit 06dd63
  /* Create a regular file.  */
Packit 06dd63
  fd = func (BASE "file", O_CREAT | O_RDONLY, 0600);
Packit 06dd63
  ASSERT (0 <= fd);
Packit 06dd63
  ASSERT (close (fd) == 0);
Packit 06dd63
Packit 06dd63
  /* Trailing slash handling.  */
Packit 06dd63
  errno = 0;
Packit 06dd63
  ASSERT (func (BASE "file/", O_RDONLY) == -1);
Packit 06dd63
  ASSERT (errno == ENOTDIR || errno == EISDIR || errno == EINVAL);
Packit 06dd63
Packit 06dd63
  /* Directories cannot be opened for writing.  */
Packit 06dd63
  errno = 0;
Packit 06dd63
  ASSERT (func (".", O_WRONLY) == -1);
Packit 06dd63
  ASSERT (errno == EISDIR || errno == EACCES);
Packit 06dd63
Packit 06dd63
  /* /dev/null must exist, and be writable.  */
Packit 06dd63
  fd = func ("/dev/null", O_RDONLY);
Packit 06dd63
  ASSERT (0 <= fd);
Packit 06dd63
  {
Packit 06dd63
    char c;
Packit 06dd63
    ASSERT (read (fd, &c, 1) == 0);
Packit 06dd63
  }
Packit 06dd63
  ASSERT (close (fd) == 0);
Packit 06dd63
  fd = func ("/dev/null", O_WRONLY);
Packit 06dd63
  ASSERT (0 <= fd);
Packit 06dd63
  ASSERT (write (fd, "c", 1) == 1);
Packit 06dd63
  ASSERT (close (fd) == 0);
Packit 06dd63
Packit 06dd63
  /* Although O_NONBLOCK on regular files can be ignored, it must not
Packit 06dd63
     cause a failure.  */
Packit 06dd63
  fd = func (BASE "file", O_NONBLOCK | O_RDONLY);
Packit 06dd63
  ASSERT (0 <= fd);
Packit 06dd63
  ASSERT (close (fd) == 0);
Packit 06dd63
Packit 06dd63
  /* Symlink handling, where supported.  */
Packit 06dd63
  if (symlink (BASE "file", BASE "link") != 0)
Packit 06dd63
    {
Packit 06dd63
      ASSERT (unlink (BASE "file") == 0);
Packit 06dd63
      if (print)
Packit 06dd63
        fputs ("skipping test: symlinks not supported on this file system\n",
Packit 06dd63
               stderr);
Packit 06dd63
      return 77;
Packit 06dd63
    }
Packit 06dd63
  errno = 0;
Packit 06dd63
  ASSERT (func (BASE "link/", O_RDONLY) == -1);
Packit 06dd63
  ASSERT (errno == ENOTDIR);
Packit 06dd63
  fd = func (BASE "link", O_RDONLY);
Packit 06dd63
  ASSERT (0 <= fd);
Packit 06dd63
  ASSERT (close (fd) == 0);
Packit 06dd63
Packit 06dd63
  /* Cleanup.  */
Packit 06dd63
  ASSERT (unlink (BASE "file") == 0);
Packit 06dd63
  ASSERT (unlink (BASE "link") == 0);
Packit 06dd63
Packit 06dd63
  return 0;
Packit 06dd63
}