(root)/
glibc-2.38/
io/
tst-fcntl.c
       1  /* Tests for fcntl.
       2     Copyright (C) 2000-2023 Free Software Foundation, Inc.
       3     This file is part of the GNU C Library.
       4  
       5     The GNU C Library is free software; you can redistribute it and/or
       6     modify it under the terms of the GNU Lesser General Public
       7     License as published by the Free Software Foundation; either
       8     version 2.1 of the License, or (at your option) any later version.
       9  
      10     The GNU C Library is distributed in the hope that it will be useful,
      11     but WITHOUT ANY WARRANTY; without even the implied warranty of
      12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      13     Lesser General Public License for more details.
      14  
      15     You should have received a copy of the GNU Lesser General Public
      16     License along with the GNU C Library; if not, see
      17     <https://www.gnu.org/licenses/>.  */
      18  
      19  #include <errno.h>
      20  #include <fcntl.h>
      21  #include <paths.h>
      22  #include <string.h>
      23  #include <unistd.h>
      24  #include <sys/stat.h>
      25  
      26  
      27  /* Prototype for our test function.  */
      28  extern void do_prepare (int argc, char *argv[]);
      29  extern int do_test (int argc, char *argv[]);
      30  
      31  /* We have a preparation function.  */
      32  #define PREPARE do_prepare
      33  
      34  #include "../test-skeleton.c"
      35  
      36  
      37  /* Name of the temporary files.  */
      38  static char *name;
      39  
      40  /* File descriptor to temporary file.  */
      41  static int fd;
      42  
      43  void
      44  do_prepare (int argc, char *argv[])
      45  {
      46     size_t name_len;
      47  
      48     name_len = strlen (test_dir);
      49     name = xmalloc (name_len + sizeof ("/fcntlXXXXXX"));
      50     mempcpy (mempcpy (name, test_dir, name_len),
      51  	    "/fcntlXXXXXX", sizeof ("/fcntlXXXXXX"));
      52    /* Create the temporary file.  */
      53    fd = mkstemp (name);
      54    if (fd == -1)
      55      {
      56        printf ("cannot open temporary file: %m\n");
      57        exit (1);
      58      }
      59     add_temp_file (name);
      60  }
      61  
      62  
      63  int
      64  do_test (int argc, char *argv[])
      65  {
      66    int fd2;
      67    int fd3;
      68    struct stat64 st;
      69    int val;
      70    int result = 0;
      71  
      72    if (fstat64 (fd, &st) != 0)
      73      {
      74        printf ("cannot stat test file: %m\n");
      75        return 1;
      76      }
      77    if (! S_ISREG (st.st_mode) || st.st_size != 0)
      78      {
      79        puts ("file not created correctly");
      80        return 1;
      81      }
      82  
      83    /* Get the flags with fcntl().  */
      84    val = fcntl (fd, F_GETFL);
      85    if (val == -1)
      86      {
      87        printf ("fcntl(fd, F_GETFL) failed: %m\n");
      88        result = 1;
      89      }
      90    else if ((val & O_ACCMODE) != O_RDWR)
      91      {
      92        puts ("temporary file not opened for read and write");
      93        result = 1;
      94      }
      95  
      96    /* Set the flags to something else.  */
      97    if (fcntl (fd, F_SETFL, O_RDONLY) == -1)
      98      {
      99        printf ("fcntl(fd, F_SETFL, O_RDONLY) failed: %m\n");
     100        result = 1;
     101      }
     102  
     103    val = fcntl (fd, F_GETFL);
     104    if (val == -1)
     105      {
     106        printf ("fcntl(fd, F_GETFL) after F_SETFL failed: %m\n");
     107        result = 1;
     108      }
     109    else if ((val & O_ACCMODE) != O_RDWR)
     110      {
     111        puts ("temporary file access mode changed");
     112        result = 1;
     113      }
     114  
     115    /* Set the flags to something else.  */
     116    if (fcntl (fd, F_SETFL, O_APPEND) == -1)
     117      {
     118        printf ("fcntl(fd, F_SETFL, O_APPEND) failed: %m\n");
     119        result = 1;
     120      }
     121  
     122    val = fcntl (fd, F_GETFL);
     123    if (val == -1)
     124      {
     125        printf ("fcntl(fd, F_GETFL) after second F_SETFL failed: %m\n");
     126        result = 1;
     127      }
     128    else if ((val & O_APPEND) == 0)
     129      {
     130        puts ("O_APPEND not set");
     131        result = 1;
     132      }
     133  
     134    val = fcntl (fd, F_GETFD);
     135    if (val == -1)
     136      {
     137        printf ("fcntl(fd, F_GETFD) failed: %m\n");
     138        result = 1;
     139      }
     140    else if (fcntl (fd, F_SETFD, val | FD_CLOEXEC) == -1)
     141      {
     142        printf ("fcntl(fd, F_SETFD, FD_CLOEXEC) failed: %m\n");
     143        result = 1;
     144      }
     145    else
     146      {
     147        val = fcntl (fd, F_GETFD);
     148        if (val == -1)
     149  	{
     150  	  printf ("fcntl(fd, F_GETFD) after F_SETFD failed: %m\n");
     151  	  result = 1;
     152  	}
     153        else if ((val & FD_CLOEXEC) == 0)
     154  	{
     155  	  puts ("FD_CLOEXEC not set");
     156  	  result = 1;
     157  	}
     158      }
     159  
     160    /* Get a number of a free descriptor.  If /dev/null is not available
     161       don't continue testing.  */
     162    fd2 = open (_PATH_DEVNULL, O_RDWR);
     163    if (fd2 == -1)
     164      return result;
     165    close (fd2);
     166  
     167    fd3 = fcntl (fd, F_DUPFD, fd2 + 1);
     168    if (fd3 == -1)
     169      {
     170        printf ("fcntl(fd, F_DUPFD, %d) failed: %m\n", fd2 + 1);
     171        result = 1;
     172      }
     173    else if (fd3 <= fd2)
     174      {
     175        printf ("F_DUPFD returned %d which is not larger than %d\n", fd3, fd2);
     176        result = 1;
     177      }
     178  
     179    if (fd3 != -1)
     180      {
     181        val = fcntl (fd3, F_GETFD);
     182        if (val == -1)
     183  	{
     184  	  printf ("fcntl(fd3, F_GETFD) after F_DUPFD failed: %m\n");
     185  	  result = 1;
     186  	}
     187        else if ((val & FD_CLOEXEC) != 0)
     188  	{
     189  	  puts ("FD_CLOEXEC still set");
     190  	  result = 1;
     191  	}
     192  
     193        close (fd3);
     194      }
     195  
     196    return result;
     197  }