t_fmemopen.c revision 272345
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(__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
566ATF_TC(test12);
567ATF_TC_HEAD(test12, tc)
568{
569	atf_tc_set_md_var(tc, "descr", "test12");
570}
571ATF_TC_BODY(test12, tc)
572{
573	struct testcase *t;
574	off_t len, rest, i;
575	const char **p;
576	char buf[BUFSIZ];
577	FILE *fp;
578
579	/* test fmemopen_seek(SEEK_END) */
580	for (t = &testcases[0]; t->s != NULL; ++t) {
581		len = (off_t)strnlen(t->s, t->n);
582		rest = t->n - len;
583		for (p = &mode_r[0]; *p != NULL; ++p) {
584
585			memcpy(buf, t->s, t->n);
586			fp = fmemopen(&buf[0], t->n, *p);
587			ATF_CHECK(fp != NULL);
588
589/*
590 * test fmemopen_seek(SEEK_END)
591 */
592#if !defined(__GLIBC__)
593			ATF_CHECK(ftello(fp) == (off_t)0);
594
595			/* zero */
596			ATF_CHECK(fseeko(fp, (off_t)0, SEEK_END) == 0);
597			ATF_CHECK(ftello(fp) == len);
598
599			/* positive + OOB */
600			ATF_CHECK(fseeko(fp, rest + 1, SEEK_END) == -1);
601			ATF_CHECK(ftello(fp) == len);
602
603			/* negative + OOB */
604			ATF_CHECK(fseeko(fp, -(len + 1), SEEK_END) == -1);
605			ATF_CHECK(ftello(fp) == len);
606
607			/* positive */
608			for (i = 1; i <= rest; ++i) {
609				ATF_CHECK(fseeko(fp, i, SEEK_END) == 0);
610				ATF_CHECK(ftello(fp) == len + i);
611			}
612
613			/* negative */
614			for (i = 1; i < len; ++i) {
615				ATF_CHECK(fseeko(fp, -i, SEEK_END) == 0);
616				ATF_CHECK(ftello(fp) == len - i);
617			}
618#endif
619			ATF_CHECK(fclose(fp) == 0);
620		}
621	}
622}
623
624ATF_TC(test13);
625ATF_TC_HEAD(test13, tc)
626{
627	atf_tc_set_md_var(tc, "descr", "test13");
628}
629ATF_TC_BODY(test13, tc)
630{
631	struct testcase *t;
632	off_t i;
633	const char **p;
634	char buf[BUFSIZ];
635	FILE *fp;
636
637	/* test fmemopen_seek(SEEK_END) */
638	for (t = &testcases[0]; t->s != NULL; ++t) {
639		for (p = &mode_w[0]; *p != NULL; ++p) {
640
641			memcpy(buf, t->s, t->n);
642			fp = fmemopen(&buf[0], t->n, *p);
643			ATF_CHECK(fp != NULL);
644/*
645 * test fmemopen_seek(SEEK_END)
646 */
647#if !defined(__GLIBC__)
648			ATF_CHECK(ftello(fp) == (off_t)0);
649			ATF_CHECK(buf[0] == '\0');
650
651			/* zero */
652			ATF_CHECK(fseeko(fp, (off_t)0, SEEK_END) == 0);
653			ATF_CHECK(ftello(fp) == (off_t)0);
654
655			/* positive + OOB */
656			ATF_CHECK(fseeko(fp, (off_t)t->n + 1, SEEK_END) == -1);
657			ATF_CHECK(ftello(fp) == (off_t)0);
658
659			/* negative + OOB */
660			ATF_CHECK(fseeko(fp, -1, SEEK_END) == -1);
661			ATF_CHECK(ftello(fp) == (off_t)0);
662
663			/* positive */
664			for (i = 1; i <= t->n; ++i) {
665				ATF_CHECK(fseeko(fp, i, SEEK_END) == 0);
666				ATF_CHECK(ftello(fp) == i);
667			}
668#endif
669			ATF_CHECK(fclose(fp) == 0);
670		}
671	}
672}
673
674ATF_TC(test14);
675ATF_TC_HEAD(test14, tc)
676{
677	atf_tc_set_md_var(tc, "descr", "test14");
678}
679ATF_TC_BODY(test14, tc)
680{
681	struct testcase *t;
682	off_t len, rest, i;
683	const char **p;
684	char buf[BUFSIZ];
685	FILE *fp;
686
687	/* test fmemopen_seek(SEEK_END) */
688	for (t = &testcases[0]; t->s != NULL; ++t) {
689		len = (off_t)strnlen(t->s, t->n);
690		rest = (off_t)t->n - len;
691		for (p = &mode_a[0]; *p != NULL; ++p) {
692
693			memcpy(buf, t->s, t->n);
694			fp = fmemopen(&buf[0], t->n, *p);
695			ATF_CHECK(fp != NULL);
696/*
697 * test fmemopen_seek(SEEK_END)
698 */
699#if !defined(__GLIBC__)
700			ATF_CHECK(ftello(fp) == len);
701
702			/* zero */
703			ATF_CHECK(fseeko(fp, 0, SEEK_END) == 0);
704			ATF_CHECK(ftello(fp) == len);
705
706			/* positive + OOB */
707			ATF_CHECK(fseeko(fp, rest + 1, SEEK_END) == -1);
708			ATF_CHECK(ftello(fp) == len);
709
710			/* negative + OOB */
711			ATF_CHECK(fseeko(fp, -(len + 1), SEEK_END) == -1);
712			ATF_CHECK(ftello(fp) == len);
713
714			/* positive */
715			for (i = 1; i <= rest; ++i) {
716				ATF_CHECK(fseeko(fp, i, SEEK_END) == 0);
717				ATF_CHECK(ftello(fp) == len + i);
718			}
719
720			/* negative */
721			for (i = 1; i < len; ++i) {
722				ATF_CHECK(fseeko(fp, -i, SEEK_END) == 0);
723				ATF_CHECK(ftello(fp) == len - i);
724			}
725#endif
726			ATF_CHECK(fclose(fp) == 0);
727		}
728	}
729}
730
731const char *mode_rw1[] = {
732    "r", "rb", "r+", "rb+", "r+b",
733    "w+", "wb+",
734    NULL
735};
736
737/* test15 - 18:
738 * When a stream open for writing is flushed or closed, a null byte is written
739 * at the current position or at the end of the buffer, depending on the size
740 * of the contents.
741 */
742
743ATF_TC(test15);
744ATF_TC_HEAD(test15, tc)
745{
746	atf_tc_set_md_var(tc, "descr", "test15");
747}
748ATF_TC_BODY(test15, tc)
749{
750	struct testcase *t;
751	const char **p;
752	char buf0[BUFSIZ];
753	FILE *fp;
754	int i;
755
756	for (t = &testcases[0]; t->s != NULL; ++t) {
757		for (p = &mode_rw1[0]; *p != NULL; ++p) {
758
759			memcpy(&buf0[0], t->s, t->n);
760			fp = fmemopen(&buf0[0], t->n, *p);
761			ATF_CHECK(fp != NULL);
762/*
763 * test fmemopen_read + fgetc(3)
764 */
765			for (i = 0; i < t->n; ++i) {
766				ATF_CHECK(ftello(fp) == (off_t)i);
767				ATF_CHECK(fgetc(fp) == buf0[i]);
768				ATF_CHECK(feof(fp) == 0);
769				ATF_CHECK(ftello(fp) == (off_t)i + 1);
770			}
771			ATF_CHECK(fgetc(fp) == EOF);
772			ATF_CHECK(feof(fp) != 0);
773			ATF_CHECK(ftello(fp) == (off_t)t->n);
774			ATF_CHECK(fclose(fp) == 0);
775		}
776	}
777}
778
779ATF_TC(test16);
780ATF_TC_HEAD(test16, tc)
781{
782	atf_tc_set_md_var(tc, "descr", "test16");
783}
784ATF_TC_BODY(test16, tc)
785{
786	struct testcase *t;
787	const char **p;
788	char buf0[BUFSIZ], buf1[BUFSIZ];
789	FILE *fp;
790
791	for (t = &testcases[0]; t->s != NULL; ++t) {
792		for (p = &mode_rw1[0]; *p != NULL; ++p) {
793
794			memcpy(&buf0[0], t->s, t->n);
795			buf1[t->n] = 0x1;
796			fp = fmemopen(&buf0[0], t->n, *p);
797			ATF_CHECK(fp != NULL);
798/*
799 * test fmemopen_read + fread(4)
800 */
801			ATF_CHECK(ftello(fp) == (off_t)0);
802			ATF_CHECK(fread(&buf1[0], 1, sizeof(buf1), fp) == (size_t)t->n);
803			ATF_CHECK(feof(fp) != 0);
804			ATF_CHECK(memcmp(&buf0[0], &buf1[0], t->n) == 0);
805			ATF_CHECK((unsigned char)buf1[t->n] == 0x1);
806
807			ATF_CHECK(fclose(fp) == 0);
808		}
809	}
810}
811
812const char *mode_a1[] = { "a+", "ab+", NULL };
813
814ATF_TC(test17);
815ATF_TC_HEAD(test17, tc)
816{
817	atf_tc_set_md_var(tc, "descr", "test17");
818}
819ATF_TC_BODY(test17, tc)
820{
821	struct testcase *t;
822	size_t len;
823	int i;
824	const char **p;
825	char buf[BUFSIZ];
826	FILE *fp;
827
828	for (t = &testcases[0]; t->s != NULL; ++t) {
829		len = strnlen(t->s, t->n);
830		for (p = &mode_a1[0]; *p != NULL; ++p) {
831
832			memcpy(&buf[0], t->s, t->n);
833			fp = fmemopen(&buf[0], t->n, *p);
834			ATF_CHECK(fp != NULL);
835/*
836 * test fmemopen_read + fgetc(3)
837 */
838#if defined(__GLIBC__)
839			if (i < t->n) {
840#endif
841			for (i = len; i < t->n; ++i) {
842				ATF_CHECK(ftello(fp) == (off_t)i);
843				ATF_CHECK(fgetc(fp) == buf[i]);
844				ATF_CHECK(feof(fp) == 0);
845				ATF_CHECK(ftello(fp) == (off_t)i + 1);
846			}
847			ATF_CHECK(fgetc(fp) == EOF);
848			ATF_CHECK(feof(fp) != 0);
849			ATF_CHECK(ftello(fp) == (off_t)t->n);
850			rewind(fp);
851			for (i = 0; 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#if defined(__GLIBC__)
861			}
862#endif
863			ATF_CHECK(fclose(fp) == 0);
864		}
865	}
866}
867
868ATF_TC(test18);
869ATF_TC_HEAD(test18, tc)
870{
871	atf_tc_set_md_var(tc, "descr", "test18");
872}
873ATF_TC_BODY(test18, tc)
874{
875	struct testcase *t;
876	size_t len;
877	const char **p;
878	char buf0[BUFSIZ], buf1[BUFSIZ];
879	FILE *fp;
880
881	for (t = &testcases[0]; t->s != NULL; ++t) {
882		len = strnlen(t->s, t->n);
883		for (p = &mode_a1[0]; *p != NULL; ++p) {
884
885			memcpy(&buf0[0], t->s, t->n);
886			buf1[t->n - len] = 0x1;
887			fp = fmemopen(&buf0[0], t->n, *p);
888			ATF_CHECK(fp != NULL);
889/*
890 * test fmemopen_read + fread(3)
891 */
892#if defined(__GLIBC__)
893			if (i < t->n) {
894#endif
895			ATF_CHECK(ftello(fp) == (off_t)len);
896			ATF_CHECK(fread(&buf1[0], 1, sizeof(buf1), fp)
897			    == t->n - len);
898			ATF_CHECK(feof(fp) != 0);
899			ATF_CHECK(!memcmp(&buf0[len], &buf1[0], t->n - len));
900			ATF_CHECK((unsigned char)buf1[t->n - len] == 0x1);
901			rewind(fp);
902			buf1[t->n] = 0x1;
903			ATF_CHECK(ftello(fp) == (off_t)0);
904			ATF_CHECK(fread(&buf1[0], 1, sizeof(buf1), fp)
905			    == (size_t)t->n);
906			ATF_CHECK(feof(fp) != 0);
907			ATF_CHECK(!memcmp(&buf0[0], &buf1[0], t->n));
908			ATF_CHECK((unsigned char)buf1[t->n] == 0x1);
909#if defined(__GLIBC__)
910			}
911#endif
912			ATF_CHECK(fclose(fp) == 0);
913		}
914	}
915}
916
917/*
918 * test19 - test22:
919 * If a stream open for update is flushed or closed and the last write has
920 * advanced the current buffer size, a null byte is written at the end of the
921 * buffer if it fits.
922 */
923
924const char *mode_rw2[] = {
925    "r+", "rb+", "r+b",
926    "w", "wb", "w+", "wb+", "w+b",
927    NULL
928};
929
930ATF_TC(test19);
931ATF_TC_HEAD(test19, tc)
932{
933	atf_tc_set_md_var(tc, "descr", "test19");
934}
935ATF_TC_BODY(test19, tc)
936{
937	struct testcase *t;
938	int i;
939	const char **p;
940	char buf[BUFSIZ];
941	FILE *fp;
942
943	for (t = &testcases[0]; t->s != NULL; ++t) {
944		for (p = &mode_rw2[0]; *p != NULL; ++p) {
945
946			memcpy(&buf[0], t->s, t->n);
947			buf[t->n] = 0x1;
948			fp = fmemopen(&buf[0], t->n + 1, *p);
949			ATF_CHECK(fp != NULL);
950			setbuf(fp, NULL);
951/*
952 * test fmemopen_write + fputc(3)
953 */
954			for (i = 0; i < t->n; ++i) {
955				ATF_CHECK(ftello(fp) == (off_t)i);
956				ATF_CHECK(fputc(t->s[i], fp) == t->s[i]);
957				ATF_CHECK(buf[i] == t->s[i]);
958				ATF_CHECK(ftello(fp) == (off_t)i + 1);
959				ATF_CHECK(buf[i] == t->s[i]);
960#if !defined(__GLIBC__)
961				ATF_CHECK(buf[i + 1] == '\0');
962#endif
963			}
964
965/* don't accept non nul character at end of buffer */
966			ATF_CHECK(fputc(0x1, fp) == EOF);
967			ATF_CHECK(ftello(fp) == (off_t)t->n);
968			ATF_CHECK(feof(fp) == 0);
969
970/* accept nul character at end of buffer */
971			ATF_CHECK(fputc('\0', fp) == '\0');
972			ATF_CHECK(ftello(fp) == (off_t)t->n + 1);
973			ATF_CHECK(feof(fp) == 0);
974
975/* reach EOF */
976			ATF_CHECK(fputc('\0', fp) == EOF);
977			ATF_CHECK(ftello(fp) == (off_t)t->n + 1);
978
979			/* compare */
980			ATF_CHECK(memcmp(&buf[0], t->s, t->n) == 0);
981			ATF_CHECK(buf[t->n] == '\0');
982
983			ATF_CHECK(fclose(fp) == 0);
984		}
985	}
986}
987
988ATF_TC(test20);
989ATF_TC_HEAD(test20, tc)
990{
991	atf_tc_set_md_var(tc, "descr", "test20");
992}
993ATF_TC_BODY(test20, tc)
994{
995	struct testcase *t;
996	const char **p;
997	char buf[BUFSIZ];
998	FILE *fp;
999
1000	for (t = &testcases[0]; t->s != NULL; ++t) {
1001		for (p = &mode_rw2[0]; *p != NULL; ++p) {
1002
1003			memcpy(&buf[0], t->s, t->n);
1004			buf[t->n] = 0x1;
1005			fp = fmemopen(&buf[0], t->n + 1, *p);
1006			ATF_CHECK(fp != NULL);
1007			setbuf(fp, NULL);
1008			ATF_CHECK(fwrite(t->s, 1, t->n, fp) == (size_t)t->n);
1009/*
1010 * test fmemopen_write + fwrite(3)
1011 */
1012#if !defined(__GLIBC__)
1013			ATF_CHECK(buf[t->n] == '\0');
1014
1015/* don't accept non nul character at end of buffer */
1016			ATF_CHECK(fwrite("\x1", 1, 1, fp) == 0);
1017			ATF_CHECK(ftello(fp) == (off_t)t->n);
1018			ATF_CHECK(feof(fp) == 0);
1019#endif
1020
1021/* accept nul character at end of buffer */
1022			ATF_CHECK(fwrite("\x0", 1, 1, fp) == 1);
1023			ATF_CHECK(ftello(fp) == (off_t)t->n + 1);
1024			ATF_CHECK(feof(fp) == 0);
1025
1026/* reach EOF */
1027			ATF_CHECK(fputc('\0', fp) == EOF);
1028			ATF_CHECK(ftello(fp) == (off_t)t->n + 1);
1029
1030/* compare */
1031			ATF_CHECK(memcmp(&buf[0], t->s, t->n) == 0);
1032			ATF_CHECK(buf[t->n] == '\0');
1033
1034			ATF_CHECK(fclose(fp) == 0);
1035		}
1036	}
1037}
1038
1039ATF_TC(test21);
1040ATF_TC_HEAD(test21, tc)
1041{
1042	atf_tc_set_md_var(tc, "descr", "test21");
1043}
1044ATF_TC_BODY(test21, tc)
1045{
1046	struct testcase *t;
1047	int len, i;
1048	const char **p;
1049	char buf[BUFSIZ];
1050	FILE *fp;
1051
1052	for (t = &testcases[0]; t->s != NULL; ++t) {
1053		len = strnlen(t->s, t->n);
1054		for (p = &mode_a[0]; *p != NULL; ++p) {
1055			memcpy(&buf[0], t->s, t->n);
1056			fp = fmemopen(&buf[0], t->n, *p);
1057			ATF_CHECK(fp != NULL);
1058			setbuf(fp, NULL);
1059/*
1060 * test fmemopen_write + fputc(3)
1061 */
1062			if (len < t->n) {
1063				for (i = len; i < t->n - 1; ++i) {
1064					ATF_CHECK(ftello(fp) == (off_t)i);
1065					ATF_CHECK(fputc(t->s[i - len], fp)
1066					    == t->s[i - len]);
1067					ATF_CHECK(buf[i] == t->s[i - len]);
1068					ATF_CHECK(ftello(fp) == (off_t)i + 1);
1069#if !defined(__GLIBC__)
1070					ATF_CHECK(buf[i + 1] == '\0');
1071#endif
1072				}
1073
1074/* don't accept non nul character at end of buffer */
1075				ATF_CHECK(ftello(fp) == (off_t)t->n - 1);
1076				ATF_CHECK(fputc(0x1, fp) == EOF);
1077				ATF_CHECK(ftello(fp) == (off_t)t->n - 1);
1078
1079/* accept nul character at end of buffer */
1080				ATF_CHECK(ftello(fp) == (off_t)t->n - 1);
1081				ATF_CHECK(fputc('\0', fp) == '\0');
1082				ATF_CHECK(ftello(fp) == (off_t)t->n);
1083			}
1084
1085/* reach EOF */
1086			ATF_CHECK(ftello(fp) == (off_t)t->n);
1087			ATF_CHECK(fputc('\0', fp) == EOF);
1088			ATF_CHECK(ftello(fp) == (off_t)t->n);
1089
1090			ATF_CHECK(fclose(fp) == 0);
1091		}
1092	}
1093}
1094
1095ATF_TC(test22);
1096ATF_TC_HEAD(test22, tc)
1097{
1098	atf_tc_set_md_var(tc, "descr", "test22");
1099}
1100ATF_TC_BODY(test22, tc)
1101{
1102	struct testcase *t0, *t1;
1103	size_t len0, len1, nleft;
1104	const char **p;
1105	char buf[BUFSIZ];
1106	FILE *fp;
1107
1108	for (t0 = &testcases[0]; t0->s != NULL; ++t0) {
1109		len0 = strnlen(t0->s, t0->n);
1110		for (t1 = &testcases[0]; t1->s != NULL; ++t1) {
1111			len1 = strnlen(t1->s, t1->n);
1112			for (p = &mode_a[0]; *p != NULL; ++p) {
1113
1114				memcpy(&buf[0], t0->s, t0->n);
1115				fp = fmemopen(&buf[0], t0->n, *p);
1116				ATF_CHECK(fp != NULL);
1117				setbuf(fp, NULL);
1118/*
1119 * test fmemopen_write + fwrite(3)
1120 */
1121				nleft = t0->n - len0;
1122#if !defined(__GLIBC__)
1123				if (nleft == 0 || len1 == nleft - 1) {
1124					ATF_CHECK(fwrite(t1->s, 1, t1->n, fp)
1125					    == nleft);
1126					ATF_CHECK(ftell(fp) == t1->n);
1127				} else {
1128					ATF_CHECK(fwrite(t1->s, 1, t1->n, fp)
1129					    == nleft - 1);
1130					ATF_CHECK(ftell(fp) == t1->n - 1);
1131				}
1132#endif
1133				ATF_CHECK(fclose(fp) == 0);
1134			}
1135		}
1136	}
1137}
1138
1139ATF_TP_ADD_TCS(tp)
1140{
1141	ATF_TP_ADD_TC(tp, test00);
1142	ATF_TP_ADD_TC(tp, test01);
1143	ATF_TP_ADD_TC(tp, test02);
1144	ATF_TP_ADD_TC(tp, test03);
1145	ATF_TP_ADD_TC(tp, test04);
1146	ATF_TP_ADD_TC(tp, test05);
1147	ATF_TP_ADD_TC(tp, test06);
1148	ATF_TP_ADD_TC(tp, test07);
1149	ATF_TP_ADD_TC(tp, test08);
1150	ATF_TP_ADD_TC(tp, test09);
1151	ATF_TP_ADD_TC(tp, test10);
1152	ATF_TP_ADD_TC(tp, test11);
1153	ATF_TP_ADD_TC(tp, test12);
1154	ATF_TP_ADD_TC(tp, test13);
1155	ATF_TP_ADD_TC(tp, test14);
1156	ATF_TP_ADD_TC(tp, test15);
1157	ATF_TP_ADD_TC(tp, test16);
1158	ATF_TP_ADD_TC(tp, test17);
1159	ATF_TP_ADD_TC(tp, test18);
1160	ATF_TP_ADD_TC(tp, test19);
1161	ATF_TP_ADD_TC(tp, test20);
1162	ATF_TP_ADD_TC(tp, test21);
1163	ATF_TP_ADD_TC(tp, test22);
1164
1165	return atf_no_error();
1166}
1167