openat: don’t close (-1)
[gnulib.git] / tests / test-fwriting.c
blob4ccf428cce335b5f962b28dc47e6ebc02621be5c
1 /* Test of fwriting() function.
2 Copyright (C) 2007-2024 Free Software Foundation, Inc.
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation, either version 3 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <https://www.gnu.org/licenses/>. */
17 /* Written by Bruno Haible <bruno@clisp.org>, 2007. */
19 #include <config.h>
21 /* None of the files accessed by this test are large, so disable the
22 fseek link warning if we are not using the gnulib fseek module. */
23 #define _GL_NO_LARGE_FILES
24 #include "fwriting.h"
26 #include <stdio.h>
28 #include "macros.h"
30 #define TESTFILE "t-fwriting.tmp"
32 int
33 main ()
35 FILE *fp;
37 /* Create a file with some contents. Write-only file is always writing. */
38 fp = fopen (TESTFILE, "w");
39 if (fp == NULL)
40 goto skip;
41 ASSERT (fwriting (fp));
42 if (fwrite ("foobarsh", 1, 8, fp) < 8)
43 goto skip;
44 ASSERT (fwriting (fp));
45 if (fclose (fp))
46 goto skip;
48 /* Open it in read-only mode. Read-only file is never writing. */
49 fp = fopen (TESTFILE, "r");
50 if (fp == NULL)
51 goto skip;
52 ASSERT (!fwriting (fp));
53 if (fgetc (fp) != 'f')
54 goto skip;
55 ASSERT (!fwriting (fp));
56 if (fseek (fp, 2, SEEK_CUR))
57 goto skip;
58 ASSERT (!fwriting (fp));
59 if (fgetc (fp) != 'b')
60 goto skip;
61 ASSERT (!fwriting (fp));
62 fflush (fp);
63 ASSERT (!fwriting (fp));
64 if (fgetc (fp) != 'a')
65 goto skip;
66 ASSERT (!fwriting (fp));
67 if (fseek (fp, 0, SEEK_END))
68 goto skip;
69 ASSERT (!fwriting (fp));
70 if (fclose (fp))
71 goto skip;
73 /* Open it in read-write mode. POSIX requires a reposition (fseek,
74 fsetpos, rewind) or fflush when transitioning from write to read,
75 fwriting is only deterministic after input or output, but this
76 test case should be portable even on open, after reposition, and
77 after fflush. */
78 /* First a scenario with only fgetc, fseek, fputc. */
79 fp = fopen (TESTFILE, "r+");
80 if (fp == NULL)
81 goto skip;
82 ASSERT (!fwriting (fp));
83 if (fgetc (fp) != 'f')
84 goto skip;
85 ASSERT (!fwriting (fp));
86 if (fseek (fp, 2, SEEK_CUR))
87 goto skip;
88 ASSERT (!fwriting (fp));
89 if (fgetc (fp) != 'b')
90 goto skip;
91 ASSERT (!fwriting (fp));
92 /* This fseek call is necessary when switching from reading to writing.
93 See the description of fopen(), ISO C 99 7.19.5.3.(6). */
94 if (fseek (fp, 0, SEEK_CUR) != 0)
95 goto skip;
96 ASSERT (!fwriting (fp));
97 if (fputc ('x', fp) != 'x')
98 goto skip;
99 ASSERT (fwriting (fp));
100 if (fseek (fp, 0, SEEK_END))
101 goto skip;
102 /* freading (fp) is undefined here, because on some implementations (e.g.
103 glibc) fseek causes a buffer to be read.
104 fwriting (fp) is undefined as well. */
105 if (fclose (fp))
106 goto skip;
108 /* Open it in read-write mode. POSIX requires a reposition (fseek,
109 fsetpos, rewind) or fflush when transitioning from write to read,
110 fwriting is only deterministic after input or output, but this
111 test case should be portable even on open, after reposition, and
112 after fflush. */
113 /* Here a scenario that includes fflush. */
114 fp = fopen (TESTFILE, "r+");
115 if (fp == NULL)
116 goto skip;
117 ASSERT (!fwriting (fp));
118 if (fgetc (fp) != 'f')
119 goto skip;
120 ASSERT (!fwriting (fp));
121 if (fseek (fp, 2, SEEK_CUR))
122 goto skip;
123 ASSERT (!fwriting (fp));
124 if (fgetc (fp) != 'b')
125 goto skip;
126 ASSERT (!fwriting (fp));
127 fflush (fp);
128 ASSERT (!fwriting (fp));
129 if (fgetc (fp) != 'x')
130 goto skip;
131 ASSERT (!fwriting (fp));
132 /* This fseek call is necessary when switching from reading to writing.
133 See the description of fopen(), ISO C 99 7.19.5.3.(6). */
134 if (fseek (fp, 0, SEEK_CUR) != 0)
135 goto skip;
136 ASSERT (!fwriting (fp));
137 if (fputc ('z', fp) != 'z')
138 goto skip;
139 ASSERT (fwriting (fp));
140 if (fseek (fp, 0, SEEK_END))
141 goto skip;
142 /* freading (fp) is undefined here, because on some implementations (e.g.
143 glibc) fseek causes a buffer to be read.
144 fwriting (fp) is undefined as well. */
145 if (fclose (fp))
146 goto skip;
148 /* Open it in append mode. */
149 fp = fopen (TESTFILE, "a");
150 if (fp == NULL)
151 goto skip;
152 ASSERT (fwriting (fp));
153 if (fwrite ("bla", 1, 3, fp) < 3)
154 goto skip;
155 ASSERT (fwriting (fp));
156 if (fclose (fp))
157 goto skip;
159 return test_exit_status;
161 skip:
162 if (test_exit_status != EXIT_SUCCESS)
163 return test_exit_status;
164 fprintf (stderr, "Skipping test: file operations failed.\n");
165 return 77;