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