| /* Test program for synchronization of stdio state with file after EOF.  */ | 
 |  | 
 | #include <stdio.h> | 
 | #include <error.h> | 
 | #include <errno.h> | 
 | #include <string.h> | 
 | #include <unistd.h> | 
 |  | 
 | static void do_prepare (void); | 
 | #define PREPARE(argc, argv) do_prepare () | 
 | static int do_test (void); | 
 | #define TEST_FUNCTION do_test () | 
 | #include <test-skeleton.c> | 
 |  | 
 | static char *temp_file; | 
 | static int temp_fd; | 
 |  | 
 | static char *pages; | 
 |  | 
 | static void | 
 | do_prepare (void) | 
 | { | 
 |   pages = malloc (getpagesize () * 2); | 
 |   memset (pages, 'a', getpagesize ()); | 
 |   memset (pages + getpagesize (), 'b', getpagesize ()); | 
 |  | 
 |   temp_fd = create_temp_file ("tst-mmap2-eofsync.", &temp_file); | 
 |   if (temp_fd == -1) | 
 |     error (1, errno, "cannot create temporary file"); | 
 |   else | 
 |     { | 
 |       ssize_t cc = write (temp_fd, pages, getpagesize ()); | 
 |       if (cc != getpagesize ()) | 
 | 	error (1, errno, "cannot write to temporary file"); | 
 |     } | 
 | } | 
 |  | 
 | static int | 
 | do_test (void) | 
 | { | 
 |   const size_t pagesize = getpagesize (); | 
 |   FILE *f; | 
 |   char buf[pagesize]; | 
 |   int result = 0; | 
 |   int c; | 
 |  | 
 |   f = fopen (temp_file, "rm"); | 
 |   if (f == NULL) | 
 |     { | 
 |       perror (temp_file); | 
 |       return 1; | 
 |     } | 
 |  | 
 |   if (fread (buf, pagesize, 1, f) != 1) | 
 |     { | 
 |       perror ("fread"); | 
 |       return 1; | 
 |     } | 
 |  | 
 |   if (memcmp (buf, pages, pagesize)) | 
 |     { | 
 |       puts ("data mismatch in page 1"); | 
 |       result = 1; | 
 |     } | 
 |  | 
 |   printf ("feof = %d, ferror = %d immediately after fread\n", | 
 | 	  feof (f), ferror (f)); | 
 |  | 
 |   c = fgetc (f); | 
 |   if (c == EOF) | 
 |     printf ("fgetc -> EOF (feof = %d, ferror = %d)\n", | 
 | 	    feof (f), ferror (f)); | 
 |   else | 
 |     { | 
 |       printf ("fgetc returned %o (feof = %d, ferror = %d)\n", | 
 | 	      c, feof (f), ferror (f)); | 
 |       result = 1; | 
 |     } | 
 |  | 
 |   c = write (temp_fd, pages + pagesize, pagesize); | 
 |   if (c == (ssize_t) pagesize) | 
 |     printf ("wrote more to file\n"); | 
 |   else | 
 |     { | 
 |       printf ("wrote %d != %zd (%m)\n", c, pagesize); | 
 |       result = 1; | 
 |     } | 
 |  | 
 |   if (fread (buf, pagesize, 1, f) != 1) | 
 |     { | 
 |       printf ("second fread fails: feof = %d, ferror = %d (%m)\n", | 
 | 	      feof (f), ferror (f)); | 
 |       clearerr (f); | 
 |       if (fread (buf, pagesize, 1, f) != 1) | 
 | 	{ | 
 | 	  printf ("retry fread fails: feof = %d, ferror = %d (%m)\n", | 
 | 		  feof (f), ferror (f)); | 
 | 	  result = 1; | 
 | 	} | 
 |     } | 
 |   if (result == 0 && memcmp (buf, pages + pagesize, pagesize)) | 
 |     { | 
 |       puts ("data mismatch in page 2"); | 
 |       result = 1; | 
 |     } | 
 |  | 
 |   fseek (f, pagesize - 1, SEEK_SET); | 
 |   c = fgetc (f); | 
 |   if (c != 'a') | 
 |     { | 
 |       printf ("fgetc at end of page 1 read '%c' (%m)\n", c); | 
 |       result = 1; | 
 |     } | 
 |  | 
 |   if (ftruncate (temp_fd, pagesize) < 0) | 
 |     { | 
 |       printf ("ftruncate failed: %m\n"); | 
 |       result = 1; | 
 |     } | 
 |  | 
 |   fflush (f); | 
 |  | 
 |   c = fgetc (f); | 
 |   if (c == EOF) | 
 |     printf ("after truncate fgetc -> EOF (feof = %d, ferror = %d)\n", | 
 | 	    feof (f), ferror (f)); | 
 |   else | 
 |     { | 
 |       printf ("after truncate fgetc returned '%c' (feof = %d, ferror = %d)\n", | 
 | 	      c, feof (f), ferror (f)); | 
 |       result = 1; | 
 |     } | 
 |  | 
 |   fclose (f); | 
 |  | 
 |   return result; | 
 | } |