(root)/
glibc-2.38/
wcsmbs/
tst-fgetwc-after-eof.c
       1  /* Bug 1190: EOF conditions are supposed to be sticky.
       2     Copyright (C) 2018 Free Software Foundation.
       3     Copying and distribution of this file, with or without modification,
       4     are permitted in any medium without royalty provided the copyright
       5     notice and this notice are preserved. This file is offered as-is,
       6     without any warranty.  */
       7  
       8  /* ISO C1999 specification of fgetwc:
       9  
      10         #include <stdio.h>
      11         #include <wchar.h>
      12         wint_t fgetwc (FILE *stream);
      13  
      14     Description
      15  
      16       If the end-of-file indicator for the input stream pointed to by
      17       stream is not set and a next wide character is present, the
      18       fgetwc function obtains that wide character as a wchar_t
      19       converted to a wint_t and advances the associated file position
      20       indicator for the stream (if defined).
      21  
      22    Returns
      23  
      24       If the end-of-file indicator for the stream is set, or if the
      25       stream is at end-of-file, the end- of-file indicator for the
      26       stream is set and the fgetwc function returns WEOF. Otherwise,
      27       the fgetwc function returns the next wide character from the
      28       input stream pointed to by stream. If a read error occurs, the
      29       error indicator for the stream is set and the fgetwc function
      30       returns WEOF. If an encoding error occurs (including too few
      31       bytes), the value of the macro EILSEQ is stored in errno and the
      32       fgetwc function returns WEOF.
      33  
      34     The requirement to return WEOF "if the end-of-file indicator for the
      35     stream is set" was new in C99; the language in the 1995 edition of
      36     the standard was ambiguous.  Historically, BSD-derived Unix always
      37     had the C99 behavior, whereas in System V fgetwc would attempt to
      38     call read() again before returning EOF again.  Prior to version 2.28,
      39     glibc followed the System V behavior even though this does not
      40     comply with C99.
      41  
      42     See
      43     <https://sourceware.org/bugzilla/show_bug.cgi?id=1190>,
      44     <https://sourceware.org/bugzilla/show_bug.cgi?id=19476>,
      45     and the thread at
      46     <https://sourceware.org/ml/libc-alpha/2012-09/msg00343.html>
      47     for more detail.  */
      48  
      49  #include <support/tty.h>
      50  #include <support/check.h>
      51  
      52  #include <fcntl.h>
      53  #include <stdio.h>
      54  #include <stdlib.h>
      55  #include <string.h>
      56  #include <unistd.h>
      57  #include <wchar.h>
      58  
      59  #define XWRITE(fd, s, msg) do {                         \
      60      if (write (fd, s, sizeof s - 1) != sizeof s - 1)    \
      61        {                                                 \
      62          perror ("write " msg);                          \
      63          return 1;                                       \
      64        }                                                 \
      65    } while (0)
      66  
      67  int
      68  do_test (void)
      69  {
      70    /* The easiest way to set up the conditions under which you can
      71       notice whether the end-of-file indicator is sticky, is with a
      72       pseudo-tty.  This is also the case which applications are most
      73       likely to care about.  And it avoids any question of whether and
      74       how it is legitimate to access the same physical file with two
      75       independent FILE objects.  */
      76    int outer_fd, inner_fd;
      77    FILE *fp;
      78  
      79    support_openpty (&outer_fd, &inner_fd, 0, 0, 0);
      80    fp = fdopen (inner_fd, "r+");
      81    if (!fp)
      82      {
      83        perror ("fdopen");
      84        return 1;
      85      }
      86  
      87    XWRITE (outer_fd, "abc\n\004", "first line + EOF");
      88    TEST_COMPARE (fgetwc (fp), L'a');
      89    TEST_COMPARE (fgetwc (fp), L'b');
      90    TEST_COMPARE (fgetwc (fp), L'c');
      91    TEST_COMPARE (fgetwc (fp), L'\n');
      92    TEST_COMPARE (fgetwc (fp), WEOF);
      93  
      94    TEST_VERIFY_EXIT (feof (fp));
      95    TEST_VERIFY_EXIT (!ferror (fp));
      96  
      97    XWRITE (outer_fd, "d\n", "second line");
      98  
      99    /* At this point, there is a new full line of input waiting in the
     100       kernelside input buffer, but we should still observe EOF from
     101       stdio, because the end-of-file indicator has not been cleared.  */
     102    TEST_COMPARE (fgetwc (fp), WEOF);
     103  
     104    /* Clearing EOF should reveal the next line of input.  */
     105    clearerr (fp);
     106    TEST_COMPARE (fgetwc (fp), L'd');
     107    TEST_COMPARE (fgetwc (fp), L'\n');
     108  
     109    fclose (fp);
     110    close (outer_fd);
     111    return 0;
     112  }
     113  
     114  #include <support/test-driver.c>