(root)/
glibc-2.38/
libio/
tst-freopen.c
       1  /* Test freopen with mmap stdio.
       2     Copyright (C) 2002-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 <stdio.h>
      20  #include <stdlib.h>
      21  #include <string.h>
      22  #include <unistd.h>
      23  
      24  #include <support/check.h>
      25  #include <support/temp_file.h>
      26  
      27  static int fd;
      28  static char *name;
      29  
      30  static void
      31  do_prepare (int argc, char *argv[])
      32  {
      33    fd = create_temp_file ("tst-freopen.", &name);
      34    TEST_VERIFY_EXIT (fd != -1);
      35  }
      36  
      37  #define PREPARE do_prepare
      38  
      39  /* Basic tests for freopen.  */
      40  static void
      41  do_test_basic (void)
      42  {
      43    const char * const test = "Let's test freopen.\n";
      44    char temp[strlen (test) + 1];
      45  
      46    FILE *f = fdopen (fd, "w");
      47    if (f == NULL)
      48      FAIL_EXIT1 ("fdopen: %m");
      49  
      50    fputs (test, f);
      51    fclose (f);
      52  
      53    f = fopen (name, "r");
      54    if (f == NULL)
      55      FAIL_EXIT1 ("fopen: %m");
      56  
      57    if (fread (temp, 1, strlen (test), f) != strlen (test))
      58      FAIL_EXIT1 ("fread: %m");
      59    temp [strlen (test)] = '\0';
      60  
      61    if (strcmp (test, temp))
      62      FAIL_EXIT1 ("read different string than was written: (%s, %s)",
      63  	        test, temp);
      64  
      65    f = freopen (name, "r+", f);
      66    if (f == NULL)
      67      FAIL_EXIT1 ("freopen: %m");
      68  
      69    if (fseek (f, 0, SEEK_SET) != 0)
      70      FAIL_EXIT1 ("fseek: %m");
      71  
      72    if (fread (temp, 1, strlen (test), f) != strlen (test))
      73      FAIL_EXIT1 ("fread: %m");
      74    temp [strlen (test)] = '\0';
      75  
      76    if (strcmp (test, temp))
      77      FAIL_EXIT1 ("read different string than was written: (%s, %s)",
      78  	        test, temp);
      79  
      80    fclose (f);
      81  }
      82  
      83  #if defined __GNUC__ && __GNUC__ >= 11
      84  /* Force an error to detect incorrectly making freopen a deallocator
      85     for its last argument via attribute malloc.  The function closes
      86     the stream without deallocating it so either the argument or
      87     the pointer returned from the function (but not both) can be passed
      88     to fclose.  */
      89  #pragma GCC diagnostic push
      90  #pragma GCC diagnostic error "-Wmismatched-dealloc"
      91  #endif
      92  
      93  /* Verify that freopen returns stream.  */
      94  static void
      95  do_test_return_stream (void)
      96  {
      97    FILE *f1 = fopen (name, "r");
      98    if (f1 == NULL)
      99      FAIL_EXIT1 ("fopen: %m");
     100  
     101    FILE *f2 = freopen (name, "r+", f1);
     102    if (f2 == NULL)
     103      FAIL_EXIT1 ("freopen: %m");
     104  
     105    /* Verify that freopen isn't declared with the no-argument attribute
     106       malloc (which could let GCC fold the inequality to false).  */
     107    if (f1 != f2)
     108      FAIL_EXIT1 ("freopen returned a different stream");
     109  
     110    /* This shouldn't trigger -Wmismatched-dealloc.  */
     111    fclose (f1);
     112  }
     113  
     114  #if defined __GNUC__ && __GNUC__ >= 11
     115  /* Pop -Wmismatched-dealloc set to error above.  */
     116  # pragma GCC diagnostic pop
     117  #endif
     118  
     119  /* Test for BZ#21398, where it tries to freopen stdio after the close
     120     of its file descriptor.  */
     121  static void
     122  do_test_bz21398 (void)
     123  {
     124    (void) close (STDIN_FILENO);
     125  
     126    FILE *f = freopen (name, "r", stdin);
     127    if (f == NULL)
     128      FAIL_EXIT1 ("freopen: %m");
     129  
     130    TEST_VERIFY_EXIT (ferror (f) == 0);
     131  
     132    char buf[128];
     133    char *ret = fgets (buf, sizeof (buf), stdin);
     134    TEST_VERIFY_EXIT (ret != NULL);
     135    TEST_VERIFY_EXIT (ferror (f) == 0);
     136  }
     137  
     138  static int
     139  do_test (void)
     140  {
     141    do_test_basic ();
     142    do_test_bz21398 ();
     143    do_test_return_stream ();
     144  
     145    return 0;
     146  }
     147  
     148  #include <support/test-driver.c>