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