(root)/
grep-3.11/
gnulib-tests/
test-fchdir.c
       1  /* Test changing to a directory named by a file descriptor.
       2     Copyright (C) 2009-2023 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  /* Written by Eric Blake <ebb9@byu.net>, 2009.  */
      18  
      19  #include <config.h>
      20  
      21  #include <unistd.h>
      22  
      23  #include "signature.h"
      24  SIGNATURE_CHECK (fchdir, int, (int));
      25  
      26  #include <errno.h>
      27  #include <fcntl.h>
      28  #include <stdlib.h>
      29  #include <string.h>
      30  
      31  #include "cloexec.h"
      32  #include "macros.h"
      33  
      34  int
      35  main (void)
      36  {
      37    char *cwd;
      38    int fd;
      39    int i;
      40  
      41    cwd = getcwd (NULL, 0);
      42    ASSERT (cwd);
      43  
      44    fd = open (".", O_RDONLY);
      45    ASSERT (0 <= fd);
      46  
      47    /* Test behaviour for invalid file descriptors.  */
      48    {
      49      errno = 0;
      50      ASSERT (fchdir (-1) == -1);
      51      ASSERT (errno == EBADF);
      52    }
      53    {
      54      close (99);
      55      errno = 0;
      56      ASSERT (fchdir (99) == -1);
      57      ASSERT (errno == EBADF);
      58    }
      59  
      60    /* Check for other failure cases.  */
      61    {
      62      int bad_fd = open ("/dev/null", O_RDONLY);
      63      ASSERT (0 <= bad_fd);
      64      errno = 0;
      65      ASSERT (fchdir (bad_fd) == -1);
      66      ASSERT (errno == ENOTDIR);
      67      ASSERT (close (bad_fd) == 0);
      68    }
      69  
      70    /* Repeat test twice, once in '.' and once in '..'.  */
      71    for (i = 0; i < 2; i++)
      72      {
      73        ASSERT (chdir (&".."[1 - i]) == 0);
      74        ASSERT (fchdir (fd) == 0);
      75        {
      76          size_t len = strlen (cwd) + 1;
      77          char *new_dir = malloc (len);
      78          ASSERT (new_dir);
      79          ASSERT (getcwd (new_dir, len) == new_dir);
      80          ASSERT (strcmp (cwd, new_dir) == 0);
      81          free (new_dir);
      82        }
      83  
      84        /* For second iteration, use a cloned fd, to ensure that dup
      85           remembers whether an fd was associated with a directory.  */
      86        if (!i)
      87          {
      88            int new_fd = dup (fd);
      89            ASSERT (0 <= new_fd);
      90            ASSERT (close (fd) == 0);
      91            ASSERT (dup2 (new_fd, fd) == fd);
      92            ASSERT (close (new_fd) == 0);
      93            ASSERT (dup_cloexec (fd) == new_fd);
      94            ASSERT (dup2 (new_fd, fd) == fd);
      95            ASSERT (close (new_fd) == 0);
      96            ASSERT (fcntl (fd, F_DUPFD_CLOEXEC, new_fd) == new_fd);
      97            ASSERT (close (fd) == 0);
      98            ASSERT (fcntl (new_fd, F_DUPFD, fd) == fd);
      99            ASSERT (close (new_fd) == 0);
     100  #if GNULIB_TEST_DUP3
     101            ASSERT (dup3 (fd, new_fd, 0) == new_fd);
     102            ASSERT (dup3 (new_fd, fd, 0) == fd);
     103            ASSERT (close (new_fd) == 0);
     104  #endif
     105          }
     106      }
     107  
     108    free (cwd);
     109    return 0;
     110  }