1e1f2d32ngie/* $NetBSD: t_fmemopen.c,v 1.4 2013/10/19 17:45:00 christos Exp $ */
2e1f2d32ngie
3e1f2d32ngie/*-
4e1f2d32ngie * Copyright (c)2010 Takehiko NOZAKI,
5e1f2d32ngie * All rights reserved.
6e1f2d32ngie *
7e1f2d32ngie * Redistribution and use in source and binary forms, with or without
8e1f2d32ngie * modification, are permitted provided that the following conditions
9e1f2d32ngie * are met:
10e1f2d32ngie * 1. Redistributions of source code must retain the above copyright
11e1f2d32ngie *    notice, this list of conditions and the following disclaimer.
12e1f2d32ngie * 2. Redistributions in binary form must reproduce the above copyright
13e1f2d32ngie *    notice, this list of conditions and the following disclaimer in the
14e1f2d32ngie *    documentation and/or other materials provided with the distribution.
15e1f2d32ngie *
16e1f2d32ngie * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17e1f2d32ngie * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18e1f2d32ngie * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19e1f2d32ngie * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20e1f2d32ngie * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21e1f2d32ngie * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22e1f2d32ngie * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23e1f2d32ngie * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24e1f2d32ngie * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25e1f2d32ngie * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26e1f2d32ngie * SUCH DAMAGE.
27e1f2d32ngie *
28e1f2d32ngie */
29e1f2d32ngie
304625d6dngie#if defined(__FreeBSD__) || defined(__NetBSD__)
31e1f2d32ngie#include <atf-c.h>
32e1f2d32ngie#else
33e1f2d32ngie#if defined(__linux__)
34e1f2d32ngie#define _GNU_SOURCE
35e1f2d32ngie#include <features.h>
36e1f2d32ngie#endif
37e1f2d32ngie#include <assert.h>
38e1f2d32ngie#include <stdio.h>
39e1f2d32ngie#define ATF_TC(arg0)		static void arg0##_head(void)
40e1f2d32ngie#define ATF_TC_HEAD(arg0, arg1)	static void arg0##_head()
41e1f2d32ngie#define atf_tc_set_md_var(arg0, arg1, ...) do {	\
42e1f2d32ngie	printf(__VA_ARGS__);			\
43e1f2d32ngie	puts("");				\
44e1f2d32ngie} while (/*CONSTCOND*/0)
45e1f2d32ngie#define ATF_TC_BODY(arg0, arg1)	static void arg0##_body()
46e1f2d32ngie#define ATF_CHECK(arg0)		assert(arg0)
47e1f2d32ngie#define ATF_TP_ADD_TCS(arg0)	int main(void)
48e1f2d32ngie#define ATF_TP_ADD_TC(arg0, arg1) arg1##_head(); arg1##_body()
49e1f2d32ngie#define atf_no_error()		0
50e1f2d32ngie#endif
51e1f2d32ngie
52e1f2d32ngie#include <errno.h>
53e1f2d32ngie#include <stdint.h>
54e1f2d32ngie#include <stdio.h>
55e1f2d32ngie#include <limits.h>
56e1f2d32ngie#include <stdlib.h>
57e1f2d32ngie#include <string.h>
58e1f2d32ngie
59e1f2d32ngieconst char *mode_rwa[] = {
60e1f2d32ngie    "r", "rb", "r+", "rb+", "r+b",
61e1f2d32ngie    "w", "wb", "w+", "wb+", "w+b",
62e1f2d32ngie    "a", "ab", "a+", "ab+", "a+b",
63e1f2d32ngie    NULL
64e1f2d32ngie};
65e1f2d32ngie
66e1f2d32ngieconst char *mode_r[] = { "r", "rb", "r+", "rb+", "r+b", NULL };
67e1f2d32ngieconst char *mode_w[] = { "w", "wb", "w+", "wb+", "w+b", NULL };
68e1f2d32ngieconst char *mode_a[] = { "a", "ab", "a+", "ab+", "a+b", NULL };
69e1f2d32ngie
70e1f2d32ngiestruct testcase {
71e1f2d32ngie	const char *s;
72e1f2d32ngie	off_t n;
73e1f2d32ngie} testcases[] = {
74e1f2d32ngie#define TESTSTR(s)	{ s, sizeof(s)-1 }
75e1f2d32ngie	TESTSTR("\0he quick brown fox jumps over the lazy dog"),
76e1f2d32ngie	TESTSTR("T\0e quick brown fox jumps over the lazy dog"),
77e1f2d32ngie	TESTSTR("Th\0 quick brown fox jumps over the lazy dog"),
78e1f2d32ngie	TESTSTR("The\0quick brown fox jumps over the lazy dog"),
79e1f2d32ngie	TESTSTR("The \0uick brown fox jumps over the lazy dog"),
80e1f2d32ngie	TESTSTR("The q\0ick brown fox jumps over the lazy dog"),
81e1f2d32ngie	TESTSTR("The qu\0ck brown fox jumps over the lazy dog"),
82e1f2d32ngie	TESTSTR("The qui\0k brown fox jumps over the lazy dog"),
83e1f2d32ngie	TESTSTR("The quic\0 brown fox jumps over the lazy dog"),
84e1f2d32ngie	TESTSTR("The quick\0brown fox jumps over the lazy dog"),
85e1f2d32ngie	TESTSTR("The quick \0rown fox jumps over the lazy dog"),
86e1f2d32ngie	TESTSTR("The quick b\0own fox jumps over the lazy dog"),
87e1f2d32ngie	TESTSTR("The quick br\0wn fox jumps over the lazy dog"),
88e1f2d32ngie	TESTSTR("The quick bro\0n fox jumps over the lazy dog"),
89e1f2d32ngie	TESTSTR("The quick brow\0 fox jumps over the lazy dog"),
90e1f2d32ngie	TESTSTR("The quick brown\0fox jumps over the lazy dog"),
91e1f2d32ngie	TESTSTR("The quick brown \0ox jumps over the lazy dog"),
92e1f2d32ngie	TESTSTR("The quick brown f\0x jumps over the lazy dog"),
93e1f2d32ngie	TESTSTR("The quick brown fo\0 jumps over the lazy dog"),
94e1f2d32ngie	TESTSTR("The quick brown fox\0jumps over the lazy dog"),
95e1f2d32ngie	TESTSTR("The quick brown fox \0umps over the lazy dog"),
96e1f2d32ngie	TESTSTR("The quick brown fox j\0mps over the lazy dog"),
97e1f2d32ngie	TESTSTR("The quick brown fox ju\0ps over the lazy dog"),
98e1f2d32ngie	TESTSTR("The quick brown fox jum\0s over the lazy dog"),
99e1f2d32ngie	TESTSTR("The quick brown fox jump\0 over the lazy dog"),
100e1f2d32ngie	TESTSTR("The quick brown fox jumps\0over the lazy dog"),
101e1f2d32ngie	TESTSTR("The quick brown fox jumps \0ver the lazy dog"),
102e1f2d32ngie	TESTSTR("The quick brown fox jumps o\0er the lazy dog"),
103e1f2d32ngie	TESTSTR("The quick brown fox jumps ov\0r the lazy dog"),
104e1f2d32ngie	TESTSTR("The quick brown fox jumps ove\0 the lazy dog"),
105e1f2d32ngie	TESTSTR("The quick brown fox jumps over\0the lazy dog"),
106e1f2d32ngie	TESTSTR("The quick brown fox jumps over \0he lazy dog"),
107e1f2d32ngie	TESTSTR("The quick brown fox jumps over t\0e lazy dog"),
108e1f2d32ngie	TESTSTR("The quick brown fox jumps over th\0 lazy dog"),
109e1f2d32ngie	TESTSTR("The quick brown fox jumps over the\0lazy dog"),
110e1f2d32ngie	TESTSTR("The quick brown fox jumps over the \0azy dog"),
111e1f2d32ngie	TESTSTR("The quick brown fox jumps over the l\0zy dog"),
112e1f2d32ngie	TESTSTR("The quick brown fox jumps over the la\0y dog"),
113e1f2d32ngie	TESTSTR("The quick brown fox jumps over the laz\0 dog"),
114e1f2d32ngie	TESTSTR("The quick brown fox jumps over the lazy\0dog"),
115e1f2d32ngie	TESTSTR("The quick brown fox jumps over the lazy \0og"),
116e1f2d32ngie	TESTSTR("The quick brown fox jumps over the lazy d\0g"),
117e1f2d32ngie	TESTSTR("The quick brown fox jumps over the lazy do\0"),
118e1f2d32ngie	TESTSTR("The quick brown fox jumps over the lazy dog"),
119e1f2d32ngie	{ NULL, 0 },
120e1f2d32ngie};
121e1f2d32ngie
122e1f2d32ngieATF_TC(test00);
123e1f2d32ngieATF_TC_HEAD(test00, tc)
124e1f2d32ngie{
125e1f2d32ngie	atf_tc_set_md_var(tc, "descr", "test00");
126e1f2d32ngie}
127e1f2d32ngieATF_TC_BODY(test00, tc)
128e1f2d32ngie{
129e1f2d32ngie	const char **p;
130e1f2d32ngie	char buf[BUFSIZ];
131e1f2d32ngie	FILE *fp;
132e1f2d32ngie
133e1f2d32ngie	for (p = &mode_rwa[0]; *p != NULL; ++p) {
134e1f2d32ngie		fp = fmemopen(&buf[0], sizeof(buf), *p);
135e1f2d32ngie/*
136e1f2d32ngie * Upon successful completion, fmemopen() shall return a pointer to the
137e1f2d32ngie * object controlling the stream.
138e1f2d32ngie */
139e1f2d32ngie		ATF_CHECK(fp != NULL);
140e1f2d32ngie
141e1f2d32ngie		ATF_CHECK(fclose(fp) == 0);
142e1f2d32ngie	}
143e1f2d32ngie}
144e1f2d32ngie
145e1f2d32ngieATF_TC(test01);
146e1f2d32ngieATF_TC_HEAD(test01, tc)
147e1f2d32ngie{
148e1f2d32ngie	atf_tc_set_md_var(tc, "descr", "test01");
149e1f2d32ngie}
150e1f2d32ngieATF_TC_BODY(test01, tc)
151e1f2d32ngie{
152e1f2d32ngie	const char **p;
153e1f2d32ngie	const char *mode[] = {
154e1f2d32ngie	    "r+", "rb+", "r+b",
155e1f2d32ngie	    "w+", "wb+", "w+b",
156e1f2d32ngie	    "a+", "ab+", "a+b",
157e1f2d32ngie	    NULL
158e1f2d32ngie	};
159e1f2d32ngie	FILE *fp;
160e1f2d32ngie
161e1f2d32ngie	for (p = &mode[0]; *p != NULL; ++p) {
162e1f2d32ngie/*
163e1f2d32ngie * If a null pointer is specified as the buf argument, fmemopen() shall
164e1f2d32ngie * allocate size bytes of memory as if by a call to malloc().
165e1f2d32ngie */
166e1f2d32ngie		fp = fmemopen(NULL, BUFSIZ, *p);
167e1f2d32ngie		ATF_CHECK(fp != NULL);
168e1f2d32ngie
169e1f2d32ngie/*
170e1f2d32ngie * If buf is a null pointer, the initial position shall always be set
171e1f2d32ngie * to the beginning of the buffer.
172e1f2d32ngie */
173e1f2d32ngie		ATF_CHECK(ftello(fp) == (off_t)0);
174e1f2d32ngie
175e1f2d32ngie		ATF_CHECK(fclose(fp) == 0);
176e1f2d32ngie	}
177e1f2d32ngie}
178e1f2d32ngie
179e1f2d32ngieATF_TC(test02);
180e1f2d32ngieATF_TC_HEAD(test02, tc)
181e1f2d32ngie{
182e1f2d32ngie        atf_tc_set_md_var(tc, "descr", "test02");
183e1f2d32ngie}
184e1f2d32ngieATF_TC_BODY(test02, tc)
185e1f2d32ngie{
186e1f2d32ngie	const char **p;
187e1f2d32ngie	char buf[BUFSIZ];
188e1f2d32ngie	FILE *fp;
189e1f2d32ngie
190e1f2d32ngie	for (p = &mode_r[0]; *p != NULL; ++p) {
191e1f2d32ngie
192e1f2d32ngie		memset(&buf[0], 0x1, sizeof(buf));
193e1f2d32ngie		fp = fmemopen(&buf[0], sizeof(buf), *p);
194e1f2d32ngie		ATF_CHECK(fp != NULL);
195e1f2d32ngie
196e1f2d32ngie/*
197e1f2d32ngie * This position is initially set to either the beginning of the buffer
198e1f2d32ngie * (for r and w modes)
199e1f2d32ngie */
200e1f2d32ngie		ATF_CHECK((unsigned char)buf[0] == 0x1);
201e1f2d32ngie		ATF_CHECK(ftello(fp) == (off_t)0);
202e1f2d32ngie
203e1f2d32ngie/*
204e1f2d32ngie * The stream also maintains the size of the current buffer contents.
205e1f2d32ngie * For modes r and r+ the size is set to the value given by the size argument.
206e1f2d32ngie */
207e1f2d32ngie#if !defined(__GLIBC__)
208e1f2d32ngie		ATF_CHECK(fseeko(fp, (off_t)0, SEEK_END) == 0);
209e1f2d32ngie		ATF_CHECK(ftello(fp) == (off_t)sizeof(buf));
210e1f2d32ngie#endif
211e1f2d32ngie		ATF_CHECK(fclose(fp) == 0);
212e1f2d32ngie	}
213e1f2d32ngie}
214e1f2d32ngie
215e1f2d32ngieATF_TC(test03);
216e1f2d32ngieATF_TC_HEAD(test03, tc)
217e1f2d32ngie{
218e1f2d32ngie        atf_tc_set_md_var(tc, "descr", "test03");
219e1f2d32ngie}
220e1f2d32ngieATF_TC_BODY(test03, tc)
221e1f2d32ngie{
222e1f2d32ngie	const char **p;
223e1f2d32ngie	char buf[BUFSIZ];
224e1f2d32ngie	FILE *fp;
225e1f2d32ngie
226e1f2d32ngie	for (p = &mode_w[0]; *p != NULL; ++p) {
227e1f2d32ngie
228e1f2d32ngie		memset(&buf[0], 0x1, sizeof(buf));
229e1f2d32ngie		fp = fmemopen(&buf[0], sizeof(buf), *p);
230e1f2d32ngie		ATF_CHECK(fp != NULL);
231e1f2d32ngie
232e1f2d32ngie/*
233e1f2d32ngie * This position is initially set to either the beginning of the buffer
234e1f2d32ngie * (for r and w modes)
235e1f2d32ngie */
236e1f2d32ngie		ATF_CHECK(buf[0] == '\0');
237e1f2d32ngie		ATF_CHECK(ftello(fp) == (off_t)0);
238e1f2d32ngie
239e1f2d32ngie/*
240e1f2d32ngie * For modes w and w+ the initial size is zero
241e1f2d32ngie */
242e1f2d32ngie		ATF_CHECK(fseeko(fp, (off_t)0, SEEK_END) == 0);
243e1f2d32ngie		ATF_CHECK(ftello(fp) == (off_t)0);
244e1f2d32ngie
245e1f2d32ngie		ATF_CHECK(fclose(fp) == 0);
246e1f2d32ngie	}
247e1f2d32ngie}
248e1f2d32ngie
249e1f2d32ngieATF_TC(test04);
250e1f2d32ngieATF_TC_HEAD(test04, tc)
251e1f2d32ngie{
252e1f2d32ngie	atf_tc_set_md_var(tc, "descr", "test04");
253e1f2d32ngie}
254e1f2d32ngieATF_TC_BODY(test04, tc)
255e1f2d32ngie{
256e1f2d32ngie	const char **p;
257e1f2d32ngie	char buf[BUFSIZ];
258e1f2d32ngie	FILE *fp;
259e1f2d32ngie
260e1f2d32ngie/*
261e1f2d32ngie * or to the first null byte in the buffer (for a modes)
262e1f2d32ngie */
263e1f2d32ngie	for (p = &mode_a[0]; *p != NULL; ++p) {
264e1f2d32ngie
265e1f2d32ngie		memset(&buf[0], 0x1, sizeof(buf));
266e1f2d32ngie		fp = fmemopen(&buf[0], sizeof(buf), *p);
267e1f2d32ngie		ATF_CHECK(fp != NULL);
268e1f2d32ngie
269e1f2d32ngie		ATF_CHECK((unsigned char)buf[0] == 0x1);
270e1f2d32ngie
271e1f2d32ngie/* If no null byte is found in append mode,
272e1f2d32ngie * the initial position is set to one byte after the end of the buffer.
273e1f2d32ngie */
274e1f2d32ngie#if !defined(__GLIBC__)
275e1f2d32ngie		ATF_CHECK(ftello(fp) == (off_t)sizeof(buf));
276e1f2d32ngie#endif
277e1f2d32ngie
278e1f2d32ngie/*
279e1f2d32ngie * and for modes a and a+ the initial size is either the position of the
280e1f2d32ngie * first null byte in the buffer or the value of the size argument
281e1f2d32ngie * if no null byte is found.
282e1f2d32ngie */
283e1f2d32ngie#if !defined(__GLIBC__)
284e1f2d32ngie		ATF_CHECK(fseeko(fp, (off_t)0, SEEK_END) == 0);
285e1f2d32ngie		ATF_CHECK(ftello(fp) == (off_t)sizeof(buf));
286e1f2d32ngie#endif
287e1f2d32ngie
288e1f2d32ngie		ATF_CHECK(fclose(fp) == 0);
289e1f2d32ngie	}
290e1f2d32ngie}
291e1f2d32ngie
292e1f2d32ngieATF_TC(test05);
293e1f2d32ngieATF_TC_HEAD(test05, tc)
294e1f2d32ngie{
295e1f2d32ngie	atf_tc_set_md_var(tc, "descr", "test05");
296e1f2d32ngie}
297e1f2d32ngieATF_TC_BODY(test05, tc)
298e1f2d32ngie{
299e1f2d32ngie	const char **p;
300e1f2d32ngie	FILE *fp;
301e1f2d32ngie	char buf[BUFSIZ];
302e1f2d32ngie
303e1f2d32ngie	for (p = &mode_rwa[0]; *p != NULL; ++p) {
304e1f2d32ngie/*
305e1f2d32ngie * Otherwise, a null pointer shall be returned, and errno shall be set
306e1f2d32ngie * to indicate the error.
307e1f2d32ngie */
308e1f2d32ngie		errno = 0;
309e1f2d32ngie		fp = fmemopen(NULL, (size_t)0, *p);
310e1f2d32ngie		ATF_CHECK(fp == NULL);
311e1f2d32ngie		ATF_CHECK(errno == EINVAL);
312e1f2d32ngie
313e1f2d32ngie		errno = 0;
314e1f2d32ngie		fp = fmemopen((void *)&buf[0], 0, *p);
315e1f2d32ngie		ATF_CHECK(fp == NULL);
316e1f2d32ngie		ATF_CHECK(errno == EINVAL);
317e1f2d32ngie	}
318e1f2d32ngie}
319e1f2d32ngie
320e1f2d32ngieATF_TC(test06);
321e1f2d32ngieATF_TC_HEAD(test06, tc)
322e1f2d32ngie{
323e1f2d32ngie	atf_tc_set_md_var(tc, "descr", "test06");
324e1f2d32ngie}
325e1f2d32ngieATF_TC_BODY(test06, tc)
326e1f2d32ngie{
327e1f2d32ngie	const char **p;
328e1f2d32ngie	const char *mode[] = { "", " ", "???", NULL };
329e1f2d32ngie	FILE *fp;
330e1f2d32ngie
331e1f2d32ngie	for (p = &mode[0]; *p != NULL; ++p) {
332e1f2d32ngie/*
333e1f2d32ngie * The value of the mode argument is not valid.
334e1f2d32ngie */
335e1f2d32ngie		fp = fmemopen(NULL, 1, *p);
336e1f2d32ngie		ATF_CHECK(fp == NULL);
337e1f2d32ngie		ATF_CHECK(errno == EINVAL);
338e1f2d32ngie	}
339e1f2d32ngie}
340e1f2d32ngie
341e1f2d32ngieATF_TC(test07);
342e1f2d32ngieATF_TC_HEAD(test07, tc)
343e1f2d32ngie{
344e1f2d32ngie	atf_tc_set_md_var(tc, "descr", "test07");
345e1f2d32ngie}
346e1f2d32ngieATF_TC_BODY(test07, tc)
347e1f2d32ngie{
348e1f2d32ngie#if !defined(__GLIBC__)
349e1f2d32ngie	const char **p;
350e1f2d32ngie	const char *mode[] = {
351e1f2d32ngie	    "r", "rb",
352e1f2d32ngie	    "w", "wb",
353e1f2d32ngie	    "a", "ab",
354e1f2d32ngie	    NULL
355e1f2d32ngie	};
356e1f2d32ngie	FILE *fp;
357e1f2d32ngie
358e1f2d32ngie	for (p = &mode[0]; *p != NULL; ++p) {
359e1f2d32ngie/*
360e1f2d32ngie * Because this feature is only useful when the stream is opened for updating
361e1f2d32ngie * (because there is no way to get a pointer to the buffer) the fmemopen()
362e1f2d32ngie * call may fail if the mode argument does not include a '+' .
363e1f2d32ngie */
364e1f2d32ngie		errno = 0;
365e1f2d32ngie		fp = fmemopen(NULL, 1, *p);
366e1f2d32ngie		ATF_CHECK(fp == NULL);
367e1f2d32ngie		ATF_CHECK(errno == EINVAL);
368e1f2d32ngie	}
369e1f2d32ngie#endif
370e1f2d32ngie}
371e1f2d32ngie
372e1f2d32ngieATF_TC(test08);
373e1f2d32ngieATF_TC_HEAD(test08, tc)
374e1f2d32ngie{
375e1f2d32ngie	atf_tc_set_md_var(tc, "descr", "test08");
376e1f2d32ngie}
377e1f2d32ngieATF_TC_BODY(test08, tc)
378e1f2d32ngie{
379e1f2d32ngie#if !defined(__GLIBC__)
380e1f2d32ngie	const char **p;
381e1f2d32ngie	const char *mode[] = {
382e1f2d32ngie	    "r+", "rb+", "r+b",
383e1f2d32ngie	    "w+", "wb+", "w+b",
384e1f2d32ngie	    "a+", "ab+", "a+b",
385e1f2d32ngie	    NULL
386e1f2d32ngie	};
387e1f2d32ngie	FILE *fp;
388e1f2d32ngie
389e1f2d32ngie	for (p = &mode[0]; *p != NULL; ++p) {
390e1f2d32ngie/*
391e1f2d32ngie * The buf argument is a null pointer and the allocation of a buffer of
392e1f2d32ngie * length size has failed.
393e1f2d32ngie */
394e1f2d32ngie		fp = fmemopen(NULL, SIZE_MAX, *p);
395e1f2d32ngie		ATF_CHECK(fp == NULL);
396e1f2d32ngie		ATF_CHECK(errno == ENOMEM);
397e1f2d32ngie	}
398e1f2d32ngie#endif
399e1f2d32ngie}
400e1f2d32ngie
401e1f2d32ngie/*
402e1f2d32ngie * test09 - test14:
403e1f2d32ngie * An attempt to seek a memory buffer stream to a negative position or to a
404e1f2d32ngie * position larger than the buffer size given in the size argument shall fail.
405e1f2d32ngie */
406e1f2d32ngie
407e1f2d32ngieATF_TC(test09);
408e1f2d32ngieATF_TC_HEAD(test09, tc)
409e1f2d32ngie{
410e1f2d32ngie	atf_tc_set_md_var(tc, "descr", "test09");
411e1f2d32ngie}
412e1f2d32ngieATF_TC_BODY(test09, tc)
413e1f2d32ngie{
414e1f2d32ngie	struct testcase *t;
415e1f2d32ngie	const char **p;
416e1f2d32ngie	char buf[BUFSIZ];
417e1f2d32ngie	FILE *fp;
418e1f2d32ngie	off_t i;
419e1f2d32ngie
420e1f2d32ngie	for (t = &testcases[0]; t->s != NULL; ++t) {
421e1f2d32ngie		for (p = &mode_rwa[0]; *p != NULL; ++p) {
422e1f2d32ngie
423e1f2d32ngie			memcpy(&buf[0], t->s, t->n);
424e1f2d32ngie			fp = fmemopen(&buf[0], t->n, *p);
425e1f2d32ngie			ATF_CHECK(fp != NULL);
426e1f2d32ngie
427e1f2d32ngie/*
428e1f2d32ngie * test fmemopen_seek(SEEK_SET)
429e1f2d32ngie */
430e1f2d32ngie			/* zero */
431e1f2d32ngie			ATF_CHECK(fseeko(fp, (off_t)0, SEEK_SET) == 0);
432e1f2d32ngie			ATF_CHECK(ftello(fp) == (off_t)0);
433e1f2d32ngie
434e1f2d32ngie			/* positive */
435e1f2d32ngie			for (i = (off_t)1; i <= (off_t)t->n; ++i) {
436e1f2d32ngie				ATF_CHECK(fseeko(fp, i, SEEK_SET) == 0);
437e1f2d32ngie				ATF_CHECK(ftello(fp) == i);
438e1f2d32ngie			}
439e1f2d32ngie			/* positive + OOB */
440e1f2d32ngie			ATF_CHECK(fseeko(fp, t->n + 1, SEEK_SET) == -1);
441e1f2d32ngie			ATF_CHECK(ftello(fp) == t->n);
442e1f2d32ngie
443e1f2d32ngie			/* negative + OOB */
444e1f2d32ngie			ATF_CHECK(fseeko(fp, (off_t)-1, SEEK_SET) == -1);
445e1f2d32ngie			ATF_CHECK(ftello(fp) == t->n);
446e1f2d32ngie
447e1f2d32ngie			ATF_CHECK(fclose(fp) == 0);
448e1f2d32ngie		}
449e1f2d32ngie	}
450e1f2d32ngie}
451e1f2d32ngie
452e1f2d32ngieconst char *mode_rw[] = {
453e1f2d32ngie    "r", "rb", "r+", "rb+", "r+b",
454e1f2d32ngie    "w", "wb", "w+", "wb+", "w+b",
455e1f2d32ngie    NULL
456e1f2d32ngie};
457e1f2d32ngie
458e1f2d32ngieATF_TC(test10);
459e1f2d32ngieATF_TC_HEAD(test10, tc)
460e1f2d32ngie{
461e1f2d32ngie	atf_tc_set_md_var(tc, "descr", "test10");
462e1f2d32ngie}
463e1f2d32ngieATF_TC_BODY(test10, tc)
464e1f2d32ngie{
465e1f2d32ngie	struct testcase *t;
466e1f2d32ngie	off_t i;
467e1f2d32ngie	const char **p;
468e1f2d32ngie	char buf[BUFSIZ];
469e1f2d32ngie	FILE *fp;
470e1f2d32ngie
471e1f2d32ngie	for (t = &testcases[0]; t->s != NULL; ++t) {
472e1f2d32ngie		for (p = &mode_rw[0]; *p != NULL; ++p) {
473e1f2d32ngie
474e1f2d32ngie			memcpy(&buf[0], t->s, t->n);
475e1f2d32ngie			fp = fmemopen(&buf[0], t->n, *p);
476e1f2d32ngie			ATF_CHECK(fp != NULL);
477e1f2d32ngie
478e1f2d32ngie/*
479e1f2d32ngie * test fmemopen_seek(SEEK_CUR)
480e1f2d32ngie */
481e1f2d32ngie			ATF_CHECK(ftello(fp) == (off_t)0);
482e1f2d32ngie
483e1f2d32ngie			/* zero */
484e1f2d32ngie			ATF_CHECK(fseeko(fp, (off_t)0, SEEK_CUR) == 0);
485e1f2d32ngie			ATF_CHECK(ftello(fp) == (off_t)0);
486e1f2d32ngie
487e1f2d32ngie			/* negative & OOB */
488e1f2d32ngie			ATF_CHECK(fseeko(fp, (off_t)-1, SEEK_CUR) == -1);
489e1f2d32ngie			ATF_CHECK(ftello(fp) == (off_t)0);
490e1f2d32ngie
491e1f2d32ngie			/* positive */
492e1f2d32ngie			for (i = 0; i < (off_t)t->n; ++i) {
493e1f2d32ngie				ATF_CHECK(fseeko(fp, (off_t)1, SEEK_CUR) == 0);
494e1f2d32ngie				ATF_CHECK(ftello(fp) == i + 1);
495e1f2d32ngie			}
496e1f2d32ngie
497e1f2d32ngie			/* positive & OOB */
498e1f2d32ngie			ATF_CHECK(fseeko(fp, (off_t)1, SEEK_CUR) == -1);
499e1f2d32ngie			ATF_CHECK(ftello(fp) == (off_t)t->n);
500e1f2d32ngie
501e1f2d32ngie			ATF_CHECK(fclose(fp) == 0);
502e1f2d32ngie		}
503e1f2d32ngie	}
504e1f2d32ngie}
505e1f2d32ngie
506e1f2d32ngieATF_TC(test11);
507e1f2d32ngieATF_TC_HEAD(test11, tc)
508e1f2d32ngie{
509e1f2d32ngie	atf_tc_set_md_var(tc, "descr", "test11");
510e1f2d32ngie}
511e1f2d32ngieATF_TC_BODY(test11, tc)
512e1f2d32ngie{
513e1f2d32ngie	struct testcase *t;
514e1f2d32ngie	off_t len, rest, i;
515e1f2d32ngie	const char **p;
516e1f2d32ngie	char buf[BUFSIZ];
517e1f2d32ngie	FILE *fp;
518e1f2d32ngie
519e1f2d32ngie	/* test fmemopen_seek(SEEK_CUR) */
520e1f2d32ngie	for (t = &testcases[0]; t->s != NULL; ++t) {
521e1f2d32ngie		len = (off_t)strnlen(t->s, t->n);
522e1f2d32ngie		rest = (off_t)t->n - len;
523e1f2d32ngie		for (p = &mode_a[0]; *p != NULL; ++p) {
524e1f2d32ngie
525e1f2d32ngie			memcpy(&buf[0], t->s, t->n);
526e1f2d32ngie			fp = fmemopen(&buf[0], t->n, *p);
527e1f2d32ngie			ATF_CHECK(fp != NULL);
528e1f2d32ngie/*
529e1f2d32ngie * test fmemopen_seek(SEEK_CUR)
530e1f2d32ngie */
531e1f2d32ngie#if defined(__GLIBC__)
532e1f2d32ngie			if (i < (off_t)t->n) {
533e1f2d32ngie#endif
534e1f2d32ngie			/* zero */
535e1f2d32ngie			ATF_CHECK(fseeko(fp, (off_t)0, SEEK_CUR) == 0);
536e1f2d32ngie			ATF_CHECK(ftello(fp) == len);
537e1f2d32ngie
538e1f2d32ngie			/* posive */
539e1f2d32ngie			for (i = (off_t)1; i <= rest; ++i) {
540e1f2d32ngie				ATF_CHECK(fseeko(fp, (off_t)1, SEEK_CUR) == 0);
541e1f2d32ngie				ATF_CHECK(ftello(fp) == len + i);
542e1f2d32ngie			}
543e1f2d32ngie
544e1f2d32ngie			/* positive + OOB */
545e1f2d32ngie			ATF_CHECK(fseeko(fp, (off_t)1, SEEK_CUR) == -1);
546e1f2d32ngie			ATF_CHECK(ftello(fp) == (off_t)t->n);
547e1f2d32ngie
548e1f2d32ngie			/* negative */
549e1f2d32ngie			for (i = (off_t)1; i <= (off_t)t->n; ++i) {
550e1f2d32ngie				ATF_CHECK(fseeko(fp, (off_t)-1, SEEK_CUR) == 0);
551e1f2d32ngie				ATF_CHECK(ftello(fp) == (off_t)t->n - i);
552e1f2d32ngie			}
553e1f2d32ngie
554e1f2d32ngie			/* negative + OOB */
555e1f2d32ngie			ATF_CHECK(fseeko(fp, (off_t)-1, SEEK_CUR) == -1);
556e1f2d32ngie			ATF_CHECK(ftello(fp) == (off_t)0);
557e1f2d32ngie
558e1f2d32ngie#if defined(__GLIBC__)
559e1f2d32ngie			}
560e1f2d32ngie#endif
561e1f2d32ngie			ATF_CHECK(fclose(fp) == 0);
562e1f2d32ngie		}
563e1f2d32ngie	}
564e1f2d32ngie}
565e1f2d32ngie
5664625d6dngie#ifndef __FreeBSD__
567e1f2d32ngieATF_TC(test12);
568e1f2d32ngieATF_TC_HEAD(test12, tc)
569e1f2d32ngie{
570e1f2d32ngie	atf_tc_set_md_var(tc, "descr", "test12");
571e1f2d32ngie}
572e1f2d32ngieATF_TC_BODY(test12, tc)
573e1f2d32ngie{
574e1f2d32ngie	struct testcase *t;
575e1f2d32ngie	off_t len, rest, i;
576e1f2d32ngie	const char **p;
577e1f2d32ngie	char buf[BUFSIZ];
578e1f2d32ngie	FILE *fp;
579e1f2d32ngie
580e1f2d32ngie	/* test fmemopen_seek(SEEK_END) */
581e1f2d32ngie	for (t = &testcases[0]; t->s != NULL; ++t) {
582e1f2d32ngie		len = (off_t)strnlen(t->s, t->n);
583e1f2d32ngie		rest = t->n - len;
584e1f2d32ngie		for (p = &mode_r[0]; *p != NULL; ++p) {
585e1f2d32ngie
586e1f2d32ngie			memcpy(buf, t->s, t->n);
587e1f2d32ngie			fp = fmemopen(&buf[0], t->n, *p);
588e1f2d32ngie			ATF_CHECK(fp != NULL);
589e1f2d32ngie
590e1f2d32ngie/*
591e1f2d32ngie * test fmemopen_seek(SEEK_END)
592e1f2d32ngie */
593e1f2d32ngie#if !defined(__GLIBC__)
594e1f2d32ngie			ATF_CHECK(ftello(fp) == (off_t)0);
595e1f2d32ngie
596e1f2d32ngie			/* zero */
597e1f2d32ngie			ATF_CHECK(fseeko(fp, (off_t)0, SEEK_END) == 0);
598e1f2d32ngie			ATF_CHECK(ftello(fp) == len);
599e1f2d32ngie
600e1f2d32ngie			/* positive + OOB */
601e1f2d32ngie			ATF_CHECK(fseeko(fp, rest + 1, SEEK_END) == -1);
602e1f2d32ngie			ATF_CHECK(ftello(fp) == len);
603e1f2d32ngie
604e1f2d32ngie			/* negative + OOB */
605e1f2d32ngie			ATF_CHECK(fseeko(fp, -(len + 1), SEEK_END) == -1);
606e1f2d32ngie			ATF_CHECK(ftello(fp) == len);
607e1f2d32ngie
608e1f2d32ngie			/* positive */
609e1f2d32ngie			for (i = 1; i <= rest; ++i) {
610e1f2d32ngie				ATF_CHECK(fseeko(fp, i, SEEK_END) == 0);
611e1f2d32ngie				ATF_CHECK(ftello(fp) == len + i);
612e1f2d32ngie			}
613e1f2d32ngie
614e1f2d32ngie			/* negative */
615e1f2d32ngie			for (i = 1; i < len; ++i) {
616e1f2d32ngie				ATF_CHECK(fseeko(fp, -i, SEEK_END) == 0);
617e1f2d32ngie				ATF_CHECK(ftello(fp) == len - i);
618e1f2d32ngie			}
619e1f2d32ngie#endif
620e1f2d32ngie			ATF_CHECK(fclose(fp) == 0);
621e1f2d32ngie		}
622e1f2d32ngie	}
623e1f2d32ngie}
6244625d6dngie#endif
625e1f2d32ngie
626e1f2d32ngieATF_TC(test13);
627e1f2d32ngieATF_TC_HEAD(test13, tc)
628e1f2d32ngie{
629e1f2d32ngie	atf_tc_set_md_var(tc, "descr", "test13");
630e1f2d32ngie}
631e1f2d32ngieATF_TC_BODY(test13, tc)
632e1f2d32ngie{
633e1f2d32ngie	struct testcase *t;
6344625d6dngie#ifndef __FreeBSD__
635e1f2d32ngie	off_t i;
6364625d6dngie#endif
637e1f2d32ngie	const char **p;
638e1f2d32ngie	char buf[BUFSIZ];
639e1f2d32ngie	FILE *fp;
640e1f2d32ngie
641e1f2d32ngie	/* test fmemopen_seek(SEEK_END) */
642e1f2d32ngie	for (t = &testcases[0]; t->s != NULL; ++t) {
643e1f2d32ngie		for (p = &mode_w[0]; *p != NULL; ++p) {
644e1f2d32ngie
645e1f2d32ngie			memcpy(buf, t->s, t->n);
646e1f2d32ngie			fp = fmemopen(&buf[0], t->n, *p);
647e1f2d32ngie			ATF_CHECK(fp != NULL);
648e1f2d32ngie/*
649e1f2d32ngie * test fmemopen_seek(SEEK_END)
650e1f2d32ngie */
651e1f2d32ngie#if !defined(__GLIBC__)
652e1f2d32ngie			ATF_CHECK(ftello(fp) == (off_t)0);
653e1f2d32ngie			ATF_CHECK(buf[0] == '\0');
654e1f2d32ngie
655e1f2d32ngie			/* zero */
656e1f2d32ngie			ATF_CHECK(fseeko(fp, (off_t)0, SEEK_END) == 0);
657e1f2d32ngie			ATF_CHECK(ftello(fp) == (off_t)0);
658e1f2d32ngie
659e1f2d32ngie			/* positive + OOB */
660e1f2d32ngie			ATF_CHECK(fseeko(fp, (off_t)t->n + 1, SEEK_END) == -1);
661e1f2d32ngie			ATF_CHECK(ftello(fp) == (off_t)0);
662e1f2d32ngie
663e1f2d32ngie			/* negative + OOB */
664e1f2d32ngie			ATF_CHECK(fseeko(fp, -1, SEEK_END) == -1);
665e1f2d32ngie			ATF_CHECK(ftello(fp) == (off_t)0);
6664625d6dngie#endif
667e1f2d32ngie
6684625d6dngie#ifndef __FreeBSD__
669e1f2d32ngie			/* positive */
670e1f2d32ngie			for (i = 1; i <= t->n; ++i) {
671e1f2d32ngie				ATF_CHECK(fseeko(fp, i, SEEK_END) == 0);
672e1f2d32ngie				ATF_CHECK(ftello(fp) == i);
673e1f2d32ngie			}
674e1f2d32ngie#endif
675e1f2d32ngie			ATF_CHECK(fclose(fp) == 0);
676e1f2d32ngie		}
677e1f2d32ngie	}
678e1f2d32ngie}
679e1f2d32ngie
680e1f2d32ngieATF_TC(test14);
681e1f2d32ngieATF_TC_HEAD(test14, tc)
682e1f2d32ngie{
683e1f2d32ngie	atf_tc_set_md_var(tc, "descr", "test14");
684e1f2d32ngie}
685e1f2d32ngieATF_TC_BODY(test14, tc)
686e1f2d32ngie{
687e1f2d32ngie	struct testcase *t;
688e1f2d32ngie	off_t len, rest, i;
689e1f2d32ngie	const char **p;
690e1f2d32ngie	char buf[BUFSIZ];
691e1f2d32ngie	FILE *fp;
692e1f2d32ngie
693e1f2d32ngie	/* test fmemopen_seek(SEEK_END) */
694e1f2d32ngie	for (t = &testcases[0]; t->s != NULL; ++t) {
695e1f2d32ngie		len = (off_t)strnlen(t->s, t->n);
696e1f2d32ngie		rest = (off_t)t->n - len;
697e1f2d32ngie		for (p = &mode_a[0]; *p != NULL; ++p) {
698e1f2d32ngie
699e1f2d32ngie			memcpy(buf, t->s, t->n);
700e1f2d32ngie			fp = fmemopen(&buf[0], t->n, *p);
701e1f2d32ngie			ATF_CHECK(fp != NULL);
702e1f2d32ngie/*
703e1f2d32ngie * test fmemopen_seek(SEEK_END)
704e1f2d32ngie */
705e1f2d32ngie#if !defined(__GLIBC__)
706e1f2d32ngie			ATF_CHECK(ftello(fp) == len);
707e1f2d32ngie
708e1f2d32ngie			/* zero */
709e1f2d32ngie			ATF_CHECK(fseeko(fp, 0, SEEK_END) == 0);
710e1f2d32ngie			ATF_CHECK(ftello(fp) == len);
711e1f2d32ngie
712e1f2d32ngie			/* positive + OOB */
713e1f2d32ngie			ATF_CHECK(fseeko(fp, rest + 1, SEEK_END) == -1);
714e1f2d32ngie			ATF_CHECK(ftello(fp) == len);
715e1f2d32ngie
716e1f2d32ngie			/* negative + OOB */
717e1f2d32ngie			ATF_CHECK(fseeko(fp, -(len + 1), SEEK_END) == -1);
718e1f2d32ngie			ATF_CHECK(ftello(fp) == len);
719e1f2d32ngie
7204625d6dngie#ifndef __FreeBSD__
721e1f2d32ngie			/* positive */
722e1f2d32ngie			for (i = 1; i <= rest; ++i) {
723e1f2d32ngie				ATF_CHECK(fseeko(fp, i, SEEK_END) == 0);
724e1f2d32ngie				ATF_CHECK(ftello(fp) == len + i);
725e1f2d32ngie			}
7264625d6dngie#endif
727e1f2d32ngie
728e1f2d32ngie			/* negative */
729e1f2d32ngie			for (i = 1; i < len; ++i) {
730e1f2d32ngie				ATF_CHECK(fseeko(fp, -i, SEEK_END) == 0);
731e1f2d32ngie				ATF_CHECK(ftello(fp) == len - i);
732e1f2d32ngie			}
733e1f2d32ngie#endif
734e1f2d32ngie			ATF_CHECK(fclose(fp) == 0);
735e1f2d32ngie		}
736e1f2d32ngie	}
737e1f2d32ngie}
738e1f2d32ngie
739e1f2d32ngieconst char *mode_rw1[] = {
740e1f2d32ngie    "r", "rb", "r+", "rb+", "r+b",
741e1f2d32ngie    "w+", "wb+",
742e1f2d32ngie    NULL
743e1f2d32ngie};
744e1f2d32ngie
7454625d6dngie#ifndef __FreeBSD__
7464625d6dngie
747e1f2d32ngie/* test15 - 18:
748e1f2d32ngie * When a stream open for writing is flushed or closed, a null byte is written
749e1f2d32ngie * at the current position or at the end of the buffer, depending on the size
750e1f2d32ngie * of the contents.
751e1f2d32ngie */
752e1f2d32ngie
753e1f2d32ngieATF_TC(test15);
754e1f2d32ngieATF_TC_HEAD(test15, tc)
755e1f2d32ngie{
756e1f2d32ngie	atf_tc_set_md_var(tc, "descr", "test15");
757e1f2d32ngie}
758e1f2d32ngieATF_TC_BODY(test15, tc)
759e1f2d32ngie{
760e1f2d32ngie	struct testcase *t;
761e1f2d32ngie	const char **p;
762e1f2d32ngie	char buf0[BUFSIZ];
763e1f2d32ngie	FILE *fp;
764e1f2d32ngie	int i;
765e1f2d32ngie
766e1f2d32ngie	for (t = &testcases[0]; t->s != NULL; ++t) {
767e1f2d32ngie		for (p = &mode_rw1[0]; *p != NULL; ++p) {
768e1f2d32ngie
769e1f2d32ngie			memcpy(&buf0[0], t->s, t->n);
770e1f2d32ngie			fp = fmemopen(&buf0[0], t->n, *p);
771e1f2d32ngie			ATF_CHECK(fp != NULL);
772e1f2d32ngie/*
773e1f2d32ngie * test fmemopen_read + fgetc(3)
774e1f2d32ngie */
775e1f2d32ngie			for (i = 0; i < t->n; ++i) {
776e1f2d32ngie				ATF_CHECK(ftello(fp) == (off_t)i);
777e1f2d32ngie				ATF_CHECK(fgetc(fp) == buf0[i]);
778e1f2d32ngie				ATF_CHECK(feof(fp) == 0);
779e1f2d32ngie				ATF_CHECK(ftello(fp) == (off_t)i + 1);
780e1f2d32ngie			}
781e1f2d32ngie			ATF_CHECK(fgetc(fp) == EOF);
782e1f2d32ngie			ATF_CHECK(feof(fp) != 0);
783e1f2d32ngie			ATF_CHECK(ftello(fp) == (off_t)t->n);
784e1f2d32ngie			ATF_CHECK(fclose(fp) == 0);
785e1f2d32ngie		}
786e1f2d32ngie	}
787e1f2d32ngie}
788e1f2d32ngie
789e1f2d32ngieATF_TC(test16);
790e1f2d32ngieATF_TC_HEAD(test16, tc)
791e1f2d32ngie{
792e1f2d32ngie	atf_tc_set_md_var(tc, "descr", "test16");
793e1f2d32ngie}
794e1f2d32ngieATF_TC_BODY(test16, tc)
795e1f2d32ngie{
796e1f2d32ngie	struct testcase *t;
797e1f2d32ngie	const char **p;
798e1f2d32ngie	char buf0[BUFSIZ], buf1[BUFSIZ];
799e1f2d32ngie	FILE *fp;
800e1f2d32ngie
801e1f2d32ngie	for (t = &testcases[0]; t->s != NULL; ++t) {
802e1f2d32ngie		for (p = &mode_rw1[0]; *p != NULL; ++p) {
803e1f2d32ngie
804e1f2d32ngie			memcpy(&buf0[0], t->s, t->n);
805e1f2d32ngie			buf1[t->n] = 0x1;
806e1f2d32ngie			fp = fmemopen(&buf0[0], t->n, *p);
807e1f2d32ngie			ATF_CHECK(fp != NULL);
808e1f2d32ngie/*
809e1f2d32ngie * test fmemopen_read + fread(4)
810e1f2d32ngie */
811e1f2d32ngie			ATF_CHECK(ftello(fp) == (off_t)0);
812e1f2d32ngie			ATF_CHECK(fread(&buf1[0], 1, sizeof(buf1), fp) == (size_t)t->n);
813e1f2d32ngie			ATF_CHECK(feof(fp) != 0);
814e1f2d32ngie			ATF_CHECK(memcmp(&buf0[0], &buf1[0], t->n) == 0);
815e1f2d32ngie			ATF_CHECK((unsigned char)buf1[t->n] == 0x1);
816e1f2d32ngie
817e1f2d32ngie			ATF_CHECK(fclose(fp) == 0);
818e1f2d32ngie		}
819e1f2d32ngie	}
820e1f2d32ngie}
821e1f2d32ngie
822e1f2d32ngieconst char *mode_a1[] = { "a+", "ab+", NULL };
823e1f2d32ngie
824e1f2d32ngieATF_TC(test17);
825e1f2d32ngieATF_TC_HEAD(test17, tc)
826e1f2d32ngie{
827e1f2d32ngie	atf_tc_set_md_var(tc, "descr", "test17");
828e1f2d32ngie}
829e1f2d32ngieATF_TC_BODY(test17, tc)
830e1f2d32ngie{
831e1f2d32ngie	struct testcase *t;
832e1f2d32ngie	size_t len;
833e1f2d32ngie	int i;
834e1f2d32ngie	const char **p;
835e1f2d32ngie	char buf[BUFSIZ];
836e1f2d32ngie	FILE *fp;
837e1f2d32ngie
838e1f2d32ngie	for (t = &testcases[0]; t->s != NULL; ++t) {
839e1f2d32ngie		len = strnlen(t->s, t->n);
840e1f2d32ngie		for (p = &mode_a1[0]; *p != NULL; ++p) {
841e1f2d32ngie
842e1f2d32ngie			memcpy(&buf[0], t->s, t->n);
843e1f2d32ngie			fp = fmemopen(&buf[0], t->n, *p);
844e1f2d32ngie			ATF_CHECK(fp != NULL);
845e1f2d32ngie/*
846e1f2d32ngie * test fmemopen_read + fgetc(3)
847e1f2d32ngie */
848e1f2d32ngie#if defined(__GLIBC__)
849e1f2d32ngie			if (i < t->n) {
850e1f2d32ngie#endif
851e1f2d32ngie			for (i = len; i < t->n; ++i) {
852e1f2d32ngie				ATF_CHECK(ftello(fp) == (off_t)i);
853e1f2d32ngie				ATF_CHECK(fgetc(fp) == buf[i]);
854e1f2d32ngie				ATF_CHECK(feof(fp) == 0);
855e1f2d32ngie				ATF_CHECK(ftello(fp) == (off_t)i + 1);
856e1f2d32ngie			}
857e1f2d32ngie			ATF_CHECK(fgetc(fp) == EOF);
858e1f2d32ngie			ATF_CHECK(feof(fp) != 0);
859e1f2d32ngie			ATF_CHECK(ftello(fp) == (off_t)t->n);
860e1f2d32ngie			rewind(fp);
861e1f2d32ngie			for (i = 0; i < t->n; ++i) {
862e1f2d32ngie				ATF_CHECK(ftello(fp) == (off_t)i);
863e1f2d32ngie				ATF_CHECK(fgetc(fp) == buf[i]);
864e1f2d32ngie				ATF_CHECK(feof(fp) == 0);
865e1f2d32ngie				ATF_CHECK(ftello(fp) == (off_t)i + 1);
866e1f2d32ngie			}
867e1f2d32ngie			ATF_CHECK(fgetc(fp) == EOF);
868e1f2d32ngie			ATF_CHECK(feof(fp) != 0);
869e1f2d32ngie			ATF_CHECK(ftello(fp) == (off_t)t->n);
870e1f2d32ngie#if defined(__GLIBC__)
871e1f2d32ngie			}
872e1f2d32ngie#endif
873e1f2d32ngie			ATF_CHECK(fclose(fp) == 0);
874e1f2d32ngie		}
875e1f2d32ngie	}
876e1f2d32ngie}
877e1f2d32ngie
878e1f2d32ngieATF_TC(test18);
879e1f2d32ngieATF_TC_HEAD(test18, tc)
880e1f2d32ngie{
881e1f2d32ngie	atf_tc_set_md_var(tc, "descr", "test18");
882e1f2d32ngie}
883e1f2d32ngieATF_TC_BODY(test18, tc)
884e1f2d32ngie{
885e1f2d32ngie	struct testcase *t;
886e1f2d32ngie	size_t len;
887e1f2d32ngie	const char **p;
888e1f2d32ngie	char buf0[BUFSIZ], buf1[BUFSIZ];
889e1f2d32ngie	FILE *fp;
890e1f2d32ngie
891e1f2d32ngie	for (t = &testcases[0]; t->s != NULL; ++t) {
892e1f2d32ngie		len = strnlen(t->s, t->n);
893e1f2d32ngie		for (p = &mode_a1[0]; *p != NULL; ++p) {
894e1f2d32ngie
895e1f2d32ngie			memcpy(&buf0[0], t->s, t->n);
896e1f2d32ngie			buf1[t->n - len] = 0x1;
897e1f2d32ngie			fp = fmemopen(&buf0[0], t->n, *p);
898e1f2d32ngie			ATF_CHECK(fp != NULL);
899e1f2d32ngie/*
900e1f2d32ngie * test fmemopen_read + fread(3)
901e1f2d32ngie */
902e1f2d32ngie#if defined(__GLIBC__)
903e1f2d32ngie			if (i < t->n) {
904e1f2d32ngie#endif
905e1f2d32ngie			ATF_CHECK(ftello(fp) == (off_t)len);
906e1f2d32ngie			ATF_CHECK(fread(&buf1[0], 1, sizeof(buf1), fp)
907e1f2d32ngie			    == t->n - len);
908e1f2d32ngie			ATF_CHECK(feof(fp) != 0);
909e1f2d32ngie			ATF_CHECK(!memcmp(&buf0[len], &buf1[0], t->n - len));
910e1f2d32ngie			ATF_CHECK((unsigned char)buf1[t->n - len] == 0x1);
911e1f2d32ngie			rewind(fp);
912e1f2d32ngie			buf1[t->n] = 0x1;
913e1f2d32ngie			ATF_CHECK(ftello(fp) == (off_t)0);
914e1f2d32ngie			ATF_CHECK(fread(&buf1[0], 1, sizeof(buf1), fp)
915e1f2d32ngie			    == (size_t)t->n);
916e1f2d32ngie			ATF_CHECK(feof(fp) != 0);
917e1f2d32ngie			ATF_CHECK(!memcmp(&buf0[0], &buf1[0], t->n));
918e1f2d32ngie			ATF_CHECK((unsigned char)buf1[t->n] == 0x1);
919e1f2d32ngie#if defined(__GLIBC__)
920e1f2d32ngie			}
921e1f2d32ngie#endif
922e1f2d32ngie			ATF_CHECK(fclose(fp) == 0);
923e1f2d32ngie		}
924e1f2d32ngie	}
925e1f2d32ngie}
926e1f2d32ngie
927e1f2d32ngie/*
928e1f2d32ngie * test19 - test22:
929e1f2d32ngie * If a stream open for update is flushed or closed and the last write has
930e1f2d32ngie * advanced the current buffer size, a null byte is written at the end of the
931e1f2d32ngie * buffer if it fits.
932e1f2d32ngie */
933e1f2d32ngie
934e1f2d32ngieconst char *mode_rw2[] = {
935e1f2d32ngie    "r+", "rb+", "r+b",
936e1f2d32ngie    "w", "wb", "w+", "wb+", "w+b",
937e1f2d32ngie    NULL
938e1f2d32ngie};
939e1f2d32ngie
940e1f2d32ngieATF_TC(test19);
941e1f2d32ngieATF_TC_HEAD(test19, tc)
942e1f2d32ngie{
943e1f2d32ngie	atf_tc_set_md_var(tc, "descr", "test19");
944e1f2d32ngie}
945e1f2d32ngieATF_TC_BODY(test19, tc)
946e1f2d32ngie{
947e1f2d32ngie	struct testcase *t;
948e1f2d32ngie	int i;
949e1f2d32ngie	const char **p;
950e1f2d32ngie	char buf[BUFSIZ];
951e1f2d32ngie	FILE *fp;
952e1f2d32ngie
953e1f2d32ngie	for (t = &testcases[0]; t->s != NULL; ++t) {
954e1f2d32ngie		for (p = &mode_rw2[0]; *p != NULL; ++p) {
955e1f2d32ngie
956e1f2d32ngie			memcpy(&buf[0], t->s, t->n);
957e1f2d32ngie			buf[t->n] = 0x1;
958e1f2d32ngie			fp = fmemopen(&buf[0], t->n + 1, *p);
959e1f2d32ngie			ATF_CHECK(fp != NULL);
960e1f2d32ngie			setbuf(fp, NULL);
961e1f2d32ngie/*
962e1f2d32ngie * test fmemopen_write + fputc(3)
963e1f2d32ngie */
964e1f2d32ngie			for (i = 0; i < t->n; ++i) {
965e1f2d32ngie				ATF_CHECK(ftello(fp) == (off_t)i);
966e1f2d32ngie				ATF_CHECK(fputc(t->s[i], fp) == t->s[i]);
967e1f2d32ngie				ATF_CHECK(buf[i] == t->s[i]);
968e1f2d32ngie				ATF_CHECK(ftello(fp) == (off_t)i + 1);
969e1f2d32ngie				ATF_CHECK(buf[i] == t->s[i]);
970e1f2d32ngie#if !defined(__GLIBC__)
971e1f2d32ngie				ATF_CHECK(buf[i + 1] == '\0');
972e1f2d32ngie#endif
973e1f2d32ngie			}
974e1f2d32ngie
975e1f2d32ngie/* don't accept non nul character at end of buffer */
976e1f2d32ngie			ATF_CHECK(fputc(0x1, fp) == EOF);
977e1f2d32ngie			ATF_CHECK(ftello(fp) == (off_t)t->n);
978e1f2d32ngie			ATF_CHECK(feof(fp) == 0);
979e1f2d32ngie
980e1f2d32ngie/* accept nul character at end of buffer */
981e1f2d32ngie			ATF_CHECK(fputc('\0', fp) == '\0');
982e1f2d32ngie			ATF_CHECK(ftello(fp) == (off_t)t->n + 1);
983e1f2d32ngie			ATF_CHECK(feof(fp) == 0);
984e1f2d32ngie
985e1f2d32ngie/* reach EOF */
986e1f2d32ngie			ATF_CHECK(fputc('\0', fp) == EOF);
987e1f2d32ngie			ATF_CHECK(ftello(fp) == (off_t)t->n + 1);
988e1f2d32ngie
989e1f2d32ngie			/* compare */
990e1f2d32ngie			ATF_CHECK(memcmp(&buf[0], t->s, t->n) == 0);
991e1f2d32ngie			ATF_CHECK(buf[t->n] == '\0');
992e1f2d32ngie
993e1f2d32ngie			ATF_CHECK(fclose(fp) == 0);
994e1f2d32ngie		}
995e1f2d32ngie	}
996e1f2d32ngie}
997e1f2d32ngie
998e1f2d32ngieATF_TC(test20);
999e1f2d32ngieATF_TC_HEAD(test20, tc)
1000e1f2d32ngie{
1001e1f2d32ngie	atf_tc_set_md_var(tc, "descr", "test20");
1002e1f2d32ngie}
1003e1f2d32ngieATF_TC_BODY(test20, tc)
1004e1f2d32ngie{
1005e1f2d32ngie	struct testcase *t;
1006e1f2d32ngie	const char **p;
1007e1f2d32ngie	char buf[BUFSIZ];
1008e1f2d32ngie	FILE *fp;
1009e1f2d32ngie
1010e1f2d32ngie	for (t = &testcases[0]; t->s != NULL; ++t) {
1011e1f2d32ngie		for (p = &mode_rw2[0]; *p != NULL; ++p) {
1012e1f2d32ngie
1013e1f2d32ngie			memcpy(&buf[0], t->s, t->n);
1014e1f2d32ngie			buf[t->n] = 0x1;
1015e1f2d32ngie			fp = fmemopen(&buf[0], t->n + 1, *p);
1016e1f2d32ngie			ATF_CHECK(fp != NULL);
1017e1f2d32ngie			setbuf(fp, NULL);
1018e1f2d32ngie			ATF_CHECK(fwrite(t->s, 1, t->n, fp) == (size_t)t->n);
1019e1f2d32ngie/*
1020e1f2d32ngie * test fmemopen_write + fwrite(3)
1021e1f2d32ngie */
1022e1f2d32ngie#if !defined(__GLIBC__)
1023e1f2d32ngie			ATF_CHECK(buf[t->n] == '\0');
1024e1f2d32ngie
1025e1f2d32ngie/* don't accept non nul character at end of buffer */
1026e1f2d32ngie			ATF_CHECK(fwrite("\x1", 1, 1, fp) == 0);
1027e1f2d32ngie			ATF_CHECK(ftello(fp) == (off_t)t->n);
1028e1f2d32ngie			ATF_CHECK(feof(fp) == 0);
1029e1f2d32ngie#endif
1030e1f2d32ngie
1031e1f2d32ngie/* accept nul character at end of buffer */
1032e1f2d32ngie			ATF_CHECK(fwrite("\x0", 1, 1, fp) == 1);
1033e1f2d32ngie			ATF_CHECK(ftello(fp) == (off_t)t->n + 1);
1034e1f2d32ngie			ATF_CHECK(feof(fp) == 0);
1035e1f2d32ngie
1036e1f2d32ngie/* reach EOF */
1037e1f2d32ngie			ATF_CHECK(fputc('\0', fp) == EOF);
1038e1f2d32ngie			ATF_CHECK(ftello(fp) == (off_t)t->n + 1);
1039e1f2d32ngie
1040e1f2d32ngie/* compare */
1041e1f2d32ngie			ATF_CHECK(memcmp(&buf[0], t->s, t->n) == 0);
1042e1f2d32ngie			ATF_CHECK(buf[t->n] == '\0');
1043e1f2d32ngie
1044e1f2d32ngie			ATF_CHECK(fclose(fp) == 0);
1045e1f2d32ngie		}
1046e1f2d32ngie	}
1047e1f2d32ngie}
1048e1f2d32ngie
1049e1f2d32ngieATF_TC(test21);
1050e1f2d32ngieATF_TC_HEAD(test21, tc)
1051e1f2d32ngie{
1052e1f2d32ngie	atf_tc_set_md_var(tc, "descr", "test21");
1053e1f2d32ngie}
1054e1f2d32ngieATF_TC_BODY(test21, tc)
1055e1f2d32ngie{
1056e1f2d32ngie	struct testcase *t;
1057e1f2d32ngie	int len, i;
1058e1f2d32ngie	const char **p;
1059e1f2d32ngie	char buf[BUFSIZ];
1060e1f2d32ngie	FILE *fp;
1061e1f2d32ngie
1062e1f2d32ngie	for (t = &testcases[0]; t->s != NULL; ++t) {
1063e1f2d32ngie		len = strnlen(t->s, t->n);
1064e1f2d32ngie		for (p = &mode_a[0]; *p != NULL; ++p) {
1065e1f2d32ngie			memcpy(&buf[0], t->s, t->n);
1066e1f2d32ngie			fp = fmemopen(&buf[0], t->n, *p);
1067e1f2d32ngie			ATF_CHECK(fp != NULL);
1068e1f2d32ngie			setbuf(fp, NULL);
1069e1f2d32ngie/*
1070e1f2d32ngie * test fmemopen_write + fputc(3)
1071e1f2d32ngie */
1072e1f2d32ngie			if (len < t->n) {
1073e1f2d32ngie				for (i = len; i < t->n - 1; ++i) {
1074e1f2d32ngie					ATF_CHECK(ftello(fp) == (off_t)i);
1075e1f2d32ngie					ATF_CHECK(fputc(t->s[i - len], fp)
1076e1f2d32ngie					    == t->s[i - len]);
1077e1f2d32ngie					ATF_CHECK(buf[i] == t->s[i - len]);
1078e1f2d32ngie					ATF_CHECK(ftello(fp) == (off_t)i + 1);
1079e1f2d32ngie#if !defined(__GLIBC__)
1080e1f2d32ngie					ATF_CHECK(buf[i + 1] == '\0');
1081e1f2d32ngie#endif
1082e1f2d32ngie				}
1083e1f2d32ngie
1084e1f2d32ngie/* don't accept non nul character at end of buffer */
1085e1f2d32ngie				ATF_CHECK(ftello(fp) == (off_t)t->n - 1);
1086e1f2d32ngie				ATF_CHECK(fputc(0x1, fp) == EOF);
1087e1f2d32ngie				ATF_CHECK(ftello(fp) == (off_t)t->n - 1);
1088e1f2d32ngie
1089e1f2d32ngie/* accept nul character at end of buffer */
1090e1f2d32ngie				ATF_CHECK(ftello(fp) == (off_t)t->n - 1);
1091e1f2d32ngie				ATF_CHECK(fputc('\0', fp) == '\0');
1092e1f2d32ngie				ATF_CHECK(ftello(fp) == (off_t)t->n);
1093e1f2d32ngie			}
1094e1f2d32ngie
1095e1f2d32ngie/* reach EOF */
1096e1f2d32ngie			ATF_CHECK(ftello(fp) == (off_t)t->n);
1097e1f2d32ngie			ATF_CHECK(fputc('\0', fp) == EOF);
1098e1f2d32ngie			ATF_CHECK(ftello(fp) == (off_t)t->n);
1099e1f2d32ngie
1100e1f2d32ngie			ATF_CHECK(fclose(fp) == 0);
1101e1f2d32ngie		}
1102e1f2d32ngie	}
1103e1f2d32ngie}
1104e1f2d32ngie
1105e1f2d32ngieATF_TC(test22);
1106e1f2d32ngieATF_TC_HEAD(test22, tc)
1107e1f2d32ngie{
1108e1f2d32ngie	atf_tc_set_md_var(tc, "descr", "test22");
1109e1f2d32ngie}
1110e1f2d32ngieATF_TC_BODY(test22, tc)
1111e1f2d32ngie{
1112e1f2d32ngie	struct testcase *t0, *t1;
1113e1f2d32ngie	size_t len0, len1, nleft;
1114e1f2d32ngie	const char **p;
1115e1f2d32ngie	char buf[BUFSIZ];
1116e1f2d32ngie	FILE *fp;
1117e1f2d32ngie
1118e1f2d32ngie	for (t0 = &testcases[0]; t0->s != NULL; ++t0) {
1119e1f2d32ngie		len0 = strnlen(t0->s, t0->n);
1120e1f2d32ngie		for (t1 = &testcases[0]; t1->s != NULL; ++t1) {
1121e1f2d32ngie			len1 = strnlen(t1->s, t1->n);
1122e1f2d32ngie			for (p = &mode_a[0]; *p != NULL; ++p) {
1123e1f2d32ngie
1124e1f2d32ngie				memcpy(&buf[0], t0->s, t0->n);
1125e1f2d32ngie				fp = fmemopen(&buf[0], t0->n, *p);
1126e1f2d32ngie				ATF_CHECK(fp != NULL);
1127e1f2d32ngie				setbuf(fp, NULL);
1128e1f2d32ngie/*
1129e1f2d32ngie * test fmemopen_write + fwrite(3)
1130e1f2d32ngie */
1131e1f2d32ngie				nleft = t0->n - len0;
1132e1f2d32ngie#if !defined(__GLIBC__)
1133e1f2d32ngie				if (nleft == 0 || len1 == nleft - 1) {
1134e1f2d32ngie					ATF_CHECK(fwrite(t1->s, 1, t1->n, fp)
1135e1f2d32ngie					    == nleft);
1136e1f2d32ngie					ATF_CHECK(ftell(fp) == t1->n);
1137e1f2d32ngie				} else {
1138e1f2d32ngie					ATF_CHECK(fwrite(t1->s, 1, t1->n, fp)
1139e1f2d32ngie					    == nleft - 1);
1140e1f2d32ngie					ATF_CHECK(ftell(fp) == t1->n - 1);
1141e1f2d32ngie				}
1142e1f2d32ngie#endif
1143e1f2d32ngie				ATF_CHECK(fclose(fp) == 0);
1144e1f2d32ngie			}
1145e1f2d32ngie		}
1146e1f2d32ngie	}
1147e1f2d32ngie}
11484625d6dngie#endif
1149e1f2d32ngie
1150e1f2d32ngieATF_TP_ADD_TCS(tp)
1151e1f2d32ngie{
1152e1f2d32ngie	ATF_TP_ADD_TC(tp, test00);
1153e1f2d32ngie	ATF_TP_ADD_TC(tp, test01);
1154e1f2d32ngie	ATF_TP_ADD_TC(tp, test02);
1155e1f2d32ngie	ATF_TP_ADD_TC(tp, test03);
1156e1f2d32ngie	ATF_TP_ADD_TC(tp, test04);
1157e1f2d32ngie	ATF_TP_ADD_TC(tp, test05);
1158e1f2d32ngie	ATF_TP_ADD_TC(tp, test06);
1159e1f2d32ngie	ATF_TP_ADD_TC(tp, test07);
1160e1f2d32ngie	ATF_TP_ADD_TC(tp, test08);
1161e1f2d32ngie	ATF_TP_ADD_TC(tp, test09);
1162e1f2d32ngie	ATF_TP_ADD_TC(tp, test10);
1163e1f2d32ngie	ATF_TP_ADD_TC(tp, test11);
11644625d6dngie#ifndef __FreeBSD__
1165e1f2d32ngie	ATF_TP_ADD_TC(tp, test12);
11664625d6dngie#endif
1167e1f2d32ngie	ATF_TP_ADD_TC(tp, test13);
1168e1f2d32ngie	ATF_TP_ADD_TC(tp, test14);
11694625d6dngie#ifndef __FreeBSD__
1170e1f2d32ngie	ATF_TP_ADD_TC(tp, test15);
1171e1f2d32ngie	ATF_TP_ADD_TC(tp, test16);
1172e1f2d32ngie	ATF_TP_ADD_TC(tp, test17);
1173e1f2d32ngie	ATF_TP_ADD_TC(tp, test18);
1174e1f2d32ngie	ATF_TP_ADD_TC(tp, test19);
1175e1f2d32ngie	ATF_TP_ADD_TC(tp, test20);
1176e1f2d32ngie	ATF_TP_ADD_TC(tp, test21);
1177e1f2d32ngie	ATF_TP_ADD_TC(tp, test22);
11784625d6dngie#endif
1179e1f2d32ngie
1180e1f2d32ngie	return atf_no_error();
1181e1f2d32ngie}
1182