xref: /freebsd/contrib/netbsd-tests/lib/libc/stdio/t_fmemopen.c (revision e0c4386e7e71d93b0edc0c8fa156263fc4a8b0b6)
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 
59 const 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 
66 const char *mode_r[] = { "r", "rb", "r+", "rb+", "r+b", NULL };
67 const char *mode_w[] = { "w", "wb", "w+", "wb+", "w+b", NULL };
68 const char *mode_a[] = { "a", "ab", "a+", "ab+", "a+b", NULL };
69 
70 struct 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 
122 ATF_TC(test00);
123 ATF_TC_HEAD(test00, tc)
124 {
125 	atf_tc_set_md_var(tc, "descr", "test00");
126 }
127 ATF_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 
145 ATF_TC(test01);
146 ATF_TC_HEAD(test01, tc)
147 {
148 	atf_tc_set_md_var(tc, "descr", "test01");
149 }
150 ATF_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 
179 ATF_TC(test02);
180 ATF_TC_HEAD(test02, tc)
181 {
182         atf_tc_set_md_var(tc, "descr", "test02");
183 }
184 ATF_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 
215 ATF_TC(test03);
216 ATF_TC_HEAD(test03, tc)
217 {
218         atf_tc_set_md_var(tc, "descr", "test03");
219 }
220 ATF_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 
249 ATF_TC(test04);
250 ATF_TC_HEAD(test04, tc)
251 {
252 	atf_tc_set_md_var(tc, "descr", "test04");
253 }
254 ATF_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 
292 ATF_TC(test05);
293 ATF_TC_HEAD(test05, tc)
294 {
295 	atf_tc_set_md_var(tc, "descr", "test05");
296 }
297 ATF_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 
320 ATF_TC(test06);
321 ATF_TC_HEAD(test06, tc)
322 {
323 	atf_tc_set_md_var(tc, "descr", "test06");
324 }
325 ATF_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 
341 ATF_TC(test07);
342 ATF_TC_HEAD(test07, tc)
343 {
344 	atf_tc_set_md_var(tc, "descr", "test07");
345 }
346 ATF_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 
372 ATF_TC(test08);
373 ATF_TC_HEAD(test08, tc)
374 {
375 	atf_tc_set_md_var(tc, "descr", "test08");
376 }
377 ATF_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 
407 ATF_TC(test09);
408 ATF_TC_HEAD(test09, tc)
409 {
410 	atf_tc_set_md_var(tc, "descr", "test09");
411 }
412 ATF_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 
452 const char *mode_rw[] = {
453     "r", "rb", "r+", "rb+", "r+b",
454     "w", "wb", "w+", "wb+", "w+b",
455     NULL
456 };
457 
458 ATF_TC(test10);
459 ATF_TC_HEAD(test10, tc)
460 {
461 	atf_tc_set_md_var(tc, "descr", "test10");
462 }
463 ATF_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 
506 ATF_TC(test11);
507 ATF_TC_HEAD(test11, tc)
508 {
509 	atf_tc_set_md_var(tc, "descr", "test11");
510 }
511 ATF_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__
567 ATF_TC(test12);
568 ATF_TC_HEAD(test12, tc)
569 {
570 	atf_tc_set_md_var(tc, "descr", "test12");
571 }
572 ATF_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 
626 ATF_TC(test13);
627 ATF_TC_HEAD(test13, tc)
628 {
629 	atf_tc_set_md_var(tc, "descr", "test13");
630 }
631 ATF_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 
680 ATF_TC(test14);
681 ATF_TC_HEAD(test14, tc)
682 {
683 	atf_tc_set_md_var(tc, "descr", "test14");
684 }
685 ATF_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 
739 const 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 
753 ATF_TC(test15);
754 ATF_TC_HEAD(test15, tc)
755 {
756 	atf_tc_set_md_var(tc, "descr", "test15");
757 }
758 ATF_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 
789 ATF_TC(test16);
790 ATF_TC_HEAD(test16, tc)
791 {
792 	atf_tc_set_md_var(tc, "descr", "test16");
793 }
794 ATF_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 
822 const char *mode_a1[] = { "a+", "ab+", NULL };
823 
824 ATF_TC(test17);
825 ATF_TC_HEAD(test17, tc)
826 {
827 	atf_tc_set_md_var(tc, "descr", "test17");
828 }
829 ATF_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 
878 ATF_TC(test18);
879 ATF_TC_HEAD(test18, tc)
880 {
881 	atf_tc_set_md_var(tc, "descr", "test18");
882 }
883 ATF_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 
934 const char *mode_rw2[] = {
935     "r+", "rb+", "r+b",
936     "w", "wb", "w+", "wb+", "w+b",
937     NULL
938 };
939 
940 ATF_TC(test19);
941 ATF_TC_HEAD(test19, tc)
942 {
943 	atf_tc_set_md_var(tc, "descr", "test19");
944 }
945 ATF_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 
998 ATF_TC(test20);
999 ATF_TC_HEAD(test20, tc)
1000 {
1001 	atf_tc_set_md_var(tc, "descr", "test20");
1002 }
1003 ATF_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 
1049 ATF_TC(test21);
1050 ATF_TC_HEAD(test21, tc)
1051 {
1052 	atf_tc_set_md_var(tc, "descr", "test21");
1053 }
1054 ATF_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 
1105 ATF_TC(test22);
1106 ATF_TC_HEAD(test22, tc)
1107 {
1108 	atf_tc_set_md_var(tc, "descr", "test22");
1109 }
1110 ATF_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 
1150 ATF_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