1 /* Test program for ungetc/fseekpos interaction.
2    Copyright (C) 2004-2022 Free Software Foundation, Inc.
3    This file is part of the GNU C Library.
4 
5    The GNU C Library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Lesser General Public
7    License as published by the Free Software Foundation; either
8    version 2.1 of the License, or (at your option) any later version.
9 
10    The GNU C Library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Lesser General Public License for more details.
14 
15    You should have received a copy of the GNU Lesser General Public
16    License along with the GNU C Library; if not, see
17    <https://www.gnu.org/licenses/>.  */
18 
19 #include <stdio.h>
20 
21 static void do_prepare (void);
22 #define PREPARE(argc, argv) do_prepare ()
23 static int do_test (void);
24 #define TEST_FUNCTION do_test ()
25 #include "../test-skeleton.c"
26 
27 static const char pattern[] = "abcdefghijklmnopqrstuvwxyz";
28 static char *temp_file;
29 
30 static void
do_prepare(void)31 do_prepare (void)
32 {
33   int fd = create_temp_file ("bug-ungetc.", &temp_file);
34   if (fd == -1)
35     {
36       printf ("cannot create temporary file: %m\n");
37       exit (1);
38     }
39   write (fd, pattern, sizeof (pattern) - 1);
40   close (fd);
41 }
42 
43 #define TEST_POS 5
44 
45 static int
do_one_test(int mode)46 do_one_test (int mode)
47 {
48   FILE *f = fopen (temp_file, "r");
49   if (f == NULL)
50     {
51       printf ("%d: could not open temporary file: %m\n", mode);
52       return 1;
53     }
54 
55   int i;
56   for (i = 0; i < TEST_POS; ++i)
57     getc (f);
58 
59   fpos_t p;
60   if (fgetpos (f, &p) != 0)
61     {
62       printf ("%d: fgetpos failed: %m\n", mode);
63       return 1;
64     }
65 
66   if (mode)
67     {
68       if (fseek (f, 0, SEEK_SET) != 0)
69         {
70           printf ("%d: fseek failed: %m\n", mode);
71           return 1;
72         }
73 
74       for (i = 0; i < TEST_POS - (mode >= 2); ++i)
75         getc (f);
76     }
77 
78   if (mode != 2 && ungetc ('X', f) != 'X')
79     {
80       printf ("%d: ungetc failed\n", mode);
81       return 1;
82     }
83 
84   if (mode == 3 && getc (f) != 'X')
85     {
86       printf ("%d: getc after ungetc did not return X\n", mode);
87       return 1;
88     }
89 
90   if (fsetpos (f, &p) != 0)
91     {
92       printf ("%d: fsetpos failed: %m\n", mode);
93       return 1;
94     }
95 
96   if (getc (f) != pattern[TEST_POS])
97     {
98       printf ("%d: getc did not return %c\n", mode, pattern[TEST_POS]);
99       return 1;
100     }
101 
102   fclose (f);
103 
104   return 0;
105 }
106 
107 static int
do_test(void)108 do_test (void)
109 {
110   int mode, ret = 0;
111   for (mode = 0; mode <= 4; mode++)
112     ret |= do_one_test (mode);
113   return ret;
114 }
115