1 /* Test for some *_unlocked stdio interfaces.
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 <stdlib.h>
20 #include <stdio.h>
21 #include <string.h>
22 #include <libc-diag.h>
23 
24 int fd;
25 static void do_prepare (void);
26 static int do_test (void);
27 #define PREPARE(argc, argv) do_prepare ()
28 #define TEST_FUNCTION do_test ()
29 #include "../test-skeleton.c"
30 
31 static int
do_test(void)32 do_test (void)
33 {
34   const char blah[] = "BLAH";
35   char buf[strlen (blah) + 1];
36   FILE *fp, *f;
37   const char *cp;
38   char *wp;
39 
40   if ((fp = fdopen (fd, "w+")) == NULL)
41     exit (1);
42 
43   flockfile (fp);
44 
45   f = fp;
46   cp = blah;
47   /* These tests deliberately use fwrite_unlocked with the size
48      argument specified as 0, which results in "division by zero"
49      warnings from the expansion of that macro (in code that is not
50      evaluated for a size of 0).  This applies to the tests of
51      fread_unlocked below as well.  */
52   DIAG_PUSH_NEEDS_COMMENT;
53   DIAG_IGNORE_NEEDS_COMMENT (4.9, "-Wdiv-by-zero");
54   if (ftello (fp) != 0
55       || fwrite_unlocked (blah, blah - blah, strlen (blah), f++) != 0
56       || f != fp + 1
57       || fwrite_unlocked ("", 5.0, 0, --f) != 0
58       || f != fp
59       || fwrite_unlocked (cp++, 16, 0.25, fp) != 0
60       || cp != blah + 1
61       || fwrite_unlocked (--cp, 0.25, 16, fp) != 0
62       || cp != blah
63       || fwrite_unlocked (blah, 0, -0.0, fp) != 0
64       || ftello (fp) != 0)
65     {
66       puts ("One of fwrite_unlocked tests failed");
67       exit (1);
68     }
69   DIAG_POP_NEEDS_COMMENT;
70 
71   if (fwrite_unlocked (blah, 1, strlen (blah) - 2, fp) != strlen (blah) - 2)
72     {
73       puts ("Could not write string into file");
74       exit (1);
75     }
76 
77   if (putc_unlocked ('A' + 0x1000000, fp) != 'A')
78     {
79       puts ("putc_unlocked failed");
80       exit (1);
81     }
82 
83   f = fp;
84   cp = blah + strlen (blah) - 1;
85   if (putc_unlocked (*cp++, f++) != 'H'
86       || f != fp + 1
87       || cp != strchr (blah, '\0'))
88     {
89       puts ("fputc_unlocked failed");
90       exit (1);
91     }
92 
93   if (ftello (fp) != (off_t) strlen (blah))
94     {
95       printf ("Failed to write %zd bytes to temporary file", strlen (blah));
96       exit (1);
97     }
98 
99   rewind (fp);
100 
101   f = fp;
102   wp = buf;
103   memset (buf, ' ', sizeof (buf));
104   /* See explanation above.  */
105   DIAG_PUSH_NEEDS_COMMENT;
106   DIAG_IGNORE_NEEDS_COMMENT (4.9, "-Wdiv-by-zero");
107   if (ftello (fp) != 0
108       || fread_unlocked (buf, buf - buf, strlen (blah), f++) != 0
109       || f != fp + 1
110       || fread_unlocked (buf, 5.0, 0, --f) != 0
111       || f != fp
112       || fread_unlocked (wp++, 16, 0.25, fp) != 0
113       || wp != buf + 1
114       || fread_unlocked (--wp, 0.25, 16, fp) != 0
115       || wp != buf
116       || fread_unlocked (buf, 0, -0.0, fp) != 0
117       || ftello (fp) != 0
118       || memcmp (buf, "     ", sizeof (buf)) != 0)
119     {
120       puts ("One of fread_unlocked tests failed");
121       exit (1);
122     }
123   DIAG_POP_NEEDS_COMMENT;
124 
125   if (fread_unlocked (buf, 1, strlen (blah) - 2, fp) != strlen (blah) - 2)
126     {
127       puts ("Could not read string from file");
128       exit (1);
129     }
130 
131   if (getc_unlocked (fp) != 'A')
132     {
133       puts ("getc_unlocked failed");
134       exit (1);
135     }
136 
137   f = fp;
138   if (fgetc_unlocked (f++) != 'H'
139       || f != fp + 1
140       || fgetc_unlocked (--f) != EOF
141       || f != fp)
142     {
143       puts ("fgetc_unlocked failed");
144       exit (1);
145     }
146 
147   if (ftello (fp) != (off_t) strlen (blah))
148     {
149       printf ("Failed to read %zd bytes from temporary file", strlen (blah));
150       exit (1);
151     }
152 
153   funlockfile (fp);
154   fclose (fp);
155 
156   return 0;
157 }
158 
159 static void
do_prepare(void)160 do_prepare (void)
161 {
162   fd = create_temp_file ("tst-unlockedio.", NULL);
163   if (fd == -1)
164     {
165       printf ("cannot create temporary file: %m\n");
166       exit (1);
167     }
168 }
169