(root)/
gettext-0.22.4/
gettext-tools/
gnulib-tests/
test-perror2.c
       1  /* Test of perror() function.
       2     Copyright (C) 2011-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, or (at your option)
       7     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  #include <config.h>
      18  
      19  #include <stdio.h>
      20  
      21  #include <errno.h>
      22  #include <string.h>
      23  #include <unistd.h>
      24  
      25  /* Tell GCC not to warn about myerr being leaked.  */
      26  #if __GNUC__ >= 13
      27  # pragma GCC diagnostic ignored "-Wanalyzer-fd-leak"
      28  #endif
      29  
      30  /* This test intentionally parses stderr.  So, we arrange to have fd 10
      31     (outside the range of interesting fd's during the test) set up to
      32     duplicate the original stderr.  */
      33  #define BACKUP_STDERR_FILENO 10
      34  #define ASSERT_STREAM myerr
      35  #include "macros.h"
      36  
      37  static FILE *myerr;
      38  
      39  #define BASE "test-perror2"
      40  
      41  int
      42  main (void)
      43  {
      44    /* We change fd 2 later, so save it in fd 10.  */
      45    if (dup2 (STDERR_FILENO, BACKUP_STDERR_FILENO) != BACKUP_STDERR_FILENO
      46        || (myerr = fdopen (BACKUP_STDERR_FILENO, "w")) == NULL)
      47      return 2;
      48  
      49    ASSERT (freopen (BASE ".tmp", "w+", stderr) == stderr);
      50  
      51    /* Test that perror does not clobber strerror buffer.  */
      52    {
      53      const char *msg1;
      54      const char *msg2;
      55      const char *msg3;
      56      const char *msg4;
      57      char *str1;
      58      char *str2;
      59      char *str3;
      60      char *str4;
      61  
      62      msg1 = strerror (ENOENT);
      63      ASSERT (msg1);
      64      str1 = strdup (msg1);
      65      ASSERT (str1);
      66  
      67      msg2 = strerror (ERANGE);
      68      ASSERT (msg2);
      69      str2 = strdup (msg2);
      70      ASSERT (str2);
      71  
      72      msg3 = strerror (-4);
      73      ASSERT (msg3);
      74      str3 = strdup (msg3);
      75      ASSERT (str3);
      76  
      77      msg4 = strerror (1729576);
      78      ASSERT (msg4);
      79      str4 = strdup (msg4);
      80      ASSERT (str4);
      81  
      82      errno = EACCES;
      83      perror ("");
      84      errno = -5;
      85      perror ("");
      86      ASSERT (!ferror (stderr));
      87      ASSERT (STREQ (msg4, str4));
      88  
      89      free (str1);
      90      free (str2);
      91      free (str3);
      92      free (str4);
      93    }
      94  
      95    /* Test that perror uses the same message as strerror.  */
      96    {
      97      int errs[] = { EACCES, 0, -3, };
      98      int i;
      99      for (i = 0; i < SIZEOF (errs); i++)
     100        {
     101          char buf[256];
     102          const char *err = strerror (errs[i]);
     103  
     104          ASSERT (err);
     105          ASSERT (strlen (err) < sizeof buf);
     106          rewind (stderr);
     107          ASSERT (ftruncate (fileno (stderr), 0) == 0);
     108          errno = errs[i];
     109          perror (NULL);
     110          ASSERT (!ferror (stderr));
     111          rewind (stderr);
     112          ASSERT (fgets (buf, sizeof buf, stderr) == buf);
     113          ASSERT (strstr (buf, err));
     114        }
     115    }
     116  
     117    /* Test that perror reports write failure.  */
     118    {
     119      ASSERT (freopen (BASE ".tmp", "r", stderr) == stderr);
     120      ASSERT (setvbuf (stderr, NULL, _IONBF, BUFSIZ) == 0);
     121      errno = -1;
     122      ASSERT (!ferror (stderr));
     123      perror (NULL);
     124  #if 0
     125      /* Commented out until cygwin behaves:
     126         https://sourceware.org/ml/newlib/2011/msg00228.html */
     127      ASSERT (errno > 0);
     128      /* Commented out until glibc behaves:
     129         https://sourceware.org/bugzilla/show_bug.cgi?id=12792 */
     130      ASSERT (ferror (stderr));
     131  #endif
     132    }
     133  
     134    ASSERT (fclose (stderr) == 0);
     135    ASSERT (remove (BASE ".tmp") == 0);
     136  
     137    return 0;
     138  }