| lh | 9ed821d | 2023-04-07 01:36:19 -0700 | [diff] [blame] | 1 | /* Test program for synchronization of stdio state with file after EOF.  */ | 
 | 2 |  | 
 | 3 | #include <stdio.h> | 
 | 4 | #include <error.h> | 
 | 5 | #include <errno.h> | 
 | 6 | #include <string.h> | 
 | 7 | #include <unistd.h> | 
 | 8 |  | 
 | 9 | static void do_prepare (void); | 
 | 10 | #define PREPARE(argc, argv) do_prepare () | 
 | 11 | static int do_test (void); | 
 | 12 | #define TEST_FUNCTION do_test () | 
 | 13 | #include <test-skeleton.c> | 
 | 14 |  | 
 | 15 | static char *temp_file; | 
 | 16 | static int temp_fd; | 
 | 17 |  | 
 | 18 | static char *pages; | 
 | 19 |  | 
 | 20 | static void | 
 | 21 | do_prepare (void) | 
 | 22 | { | 
 | 23 |   pages = malloc (getpagesize () * 2); | 
 | 24 |   memset (pages, 'a', getpagesize ()); | 
 | 25 |   memset (pages + getpagesize (), 'b', getpagesize ()); | 
 | 26 |  | 
 | 27 |   temp_fd = create_temp_file ("tst-mmap2-eofsync.", &temp_file); | 
 | 28 |   if (temp_fd == -1) | 
 | 29 |     error (1, errno, "cannot create temporary file"); | 
 | 30 |   else | 
 | 31 |     { | 
 | 32 |       ssize_t cc = write (temp_fd, pages, getpagesize ()); | 
 | 33 |       if (cc != getpagesize ()) | 
 | 34 | 	error (1, errno, "cannot write to temporary file"); | 
 | 35 |     } | 
 | 36 | } | 
 | 37 |  | 
 | 38 | static int | 
 | 39 | do_test (void) | 
 | 40 | { | 
 | 41 |   const size_t pagesize = getpagesize (); | 
 | 42 |   FILE *f; | 
 | 43 |   char buf[pagesize]; | 
 | 44 |   int result = 0; | 
 | 45 |   int c; | 
 | 46 |  | 
 | 47 |   f = fopen (temp_file, "rm"); | 
 | 48 |   if (f == NULL) | 
 | 49 |     { | 
 | 50 |       perror (temp_file); | 
 | 51 |       return 1; | 
 | 52 |     } | 
 | 53 |  | 
 | 54 |   if (fread (buf, pagesize, 1, f) != 1) | 
 | 55 |     { | 
 | 56 |       perror ("fread"); | 
 | 57 |       return 1; | 
 | 58 |     } | 
 | 59 |  | 
 | 60 |   if (memcmp (buf, pages, pagesize)) | 
 | 61 |     { | 
 | 62 |       puts ("data mismatch in page 1"); | 
 | 63 |       result = 1; | 
 | 64 |     } | 
 | 65 |  | 
 | 66 |   printf ("feof = %d, ferror = %d immediately after fread\n", | 
 | 67 | 	  feof (f), ferror (f)); | 
 | 68 |  | 
 | 69 |   c = fgetc (f); | 
 | 70 |   if (c == EOF) | 
 | 71 |     printf ("fgetc -> EOF (feof = %d, ferror = %d)\n", | 
 | 72 | 	    feof (f), ferror (f)); | 
 | 73 |   else | 
 | 74 |     { | 
 | 75 |       printf ("fgetc returned %o (feof = %d, ferror = %d)\n", | 
 | 76 | 	      c, feof (f), ferror (f)); | 
 | 77 |       result = 1; | 
 | 78 |     } | 
 | 79 |  | 
 | 80 |   c = write (temp_fd, pages + pagesize, pagesize); | 
 | 81 |   if (c == (ssize_t) pagesize) | 
 | 82 |     printf ("wrote more to file\n"); | 
 | 83 |   else | 
 | 84 |     { | 
 | 85 |       printf ("wrote %d != %zd (%m)\n", c, pagesize); | 
 | 86 |       result = 1; | 
 | 87 |     } | 
 | 88 |  | 
 | 89 |   if (fread (buf, pagesize, 1, f) != 1) | 
 | 90 |     { | 
 | 91 |       printf ("second fread fails: feof = %d, ferror = %d (%m)\n", | 
 | 92 | 	      feof (f), ferror (f)); | 
 | 93 |       clearerr (f); | 
 | 94 |       if (fread (buf, pagesize, 1, f) != 1) | 
 | 95 | 	{ | 
 | 96 | 	  printf ("retry fread fails: feof = %d, ferror = %d (%m)\n", | 
 | 97 | 		  feof (f), ferror (f)); | 
 | 98 | 	  result = 1; | 
 | 99 | 	} | 
 | 100 |     } | 
 | 101 |   if (result == 0 && memcmp (buf, pages + pagesize, pagesize)) | 
 | 102 |     { | 
 | 103 |       puts ("data mismatch in page 2"); | 
 | 104 |       result = 1; | 
 | 105 |     } | 
 | 106 |  | 
 | 107 |   fseek (f, pagesize - 1, SEEK_SET); | 
 | 108 |   c = fgetc (f); | 
 | 109 |   if (c != 'a') | 
 | 110 |     { | 
 | 111 |       printf ("fgetc at end of page 1 read '%c' (%m)\n", c); | 
 | 112 |       result = 1; | 
 | 113 |     } | 
 | 114 |  | 
 | 115 |   if (ftruncate (temp_fd, pagesize) < 0) | 
 | 116 |     { | 
 | 117 |       printf ("ftruncate failed: %m\n"); | 
 | 118 |       result = 1; | 
 | 119 |     } | 
 | 120 |  | 
 | 121 |   fflush (f); | 
 | 122 |  | 
 | 123 |   c = fgetc (f); | 
 | 124 |   if (c == EOF) | 
 | 125 |     printf ("after truncate fgetc -> EOF (feof = %d, ferror = %d)\n", | 
 | 126 | 	    feof (f), ferror (f)); | 
 | 127 |   else | 
 | 128 |     { | 
 | 129 |       printf ("after truncate fgetc returned '%c' (feof = %d, ferror = %d)\n", | 
 | 130 | 	      c, feof (f), ferror (f)); | 
 | 131 |       result = 1; | 
 | 132 |     } | 
 | 133 |  | 
 | 134 |   fclose (f); | 
 | 135 |  | 
 | 136 |   return result; | 
 | 137 | } |