xref: /netbsd/tests/lib/libc/stdio/t_fmemopen.c (revision 6550d01e)
1 /* $NetBSD: t_fmemopen.c,v 1.2 2010/11/03 16:10:22 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 <stdio.h>
54 #include <limits.h>
55 #include <stdlib.h>
56 #include <string.h>
57 
58 const char *mode_rwa[] = {
59     "r", "rb", "r+", "rb+", "r+b",
60     "w", "wb", "w+", "wb+", "w+b",
61     "a", "ab", "a+", "ab+", "a+b",
62     NULL
63 };
64 
65 const char *mode_r[] = { "r", "rb", "r+", "rb+", "r+b", NULL };
66 const char *mode_w[] = { "w", "wb", "w+", "wb+", "w+b", NULL };
67 const char *mode_a[] = { "a", "ab", "a+", "ab+", "a+b", NULL };
68 
69 struct testcase {
70 	const char *s;
71 	off_t n;
72 } testcases[] = {
73 #define TESTSTR(s)	{ s, sizeof(s)-1 }
74 	TESTSTR("\0he quick brown fox jumps over the lazy dog"),
75 	TESTSTR("T\0e quick brown fox jumps over the lazy dog"),
76 	TESTSTR("Th\0 quick brown fox jumps over the lazy dog"),
77 	TESTSTR("The\0quick brown fox jumps over the lazy dog"),
78 	TESTSTR("The \0uick brown fox jumps over the lazy dog"),
79 	TESTSTR("The q\0ick brown fox jumps over the lazy dog"),
80 	TESTSTR("The qu\0ck brown fox jumps over the lazy dog"),
81 	TESTSTR("The qui\0k brown fox jumps over the lazy dog"),
82 	TESTSTR("The quic\0 brown fox jumps over the lazy dog"),
83 	TESTSTR("The quick\0brown fox jumps over the lazy dog"),
84 	TESTSTR("The quick \0rown fox jumps over the lazy dog"),
85 	TESTSTR("The quick b\0own fox jumps over the lazy dog"),
86 	TESTSTR("The quick br\0wn fox jumps over the lazy dog"),
87 	TESTSTR("The quick bro\0n fox jumps over the lazy dog"),
88 	TESTSTR("The quick brow\0 fox jumps over the lazy dog"),
89 	TESTSTR("The quick brown\0fox jumps over the lazy dog"),
90 	TESTSTR("The quick brown \0ox jumps over the lazy dog"),
91 	TESTSTR("The quick brown f\0x jumps over the lazy dog"),
92 	TESTSTR("The quick brown fo\0 jumps over the lazy dog"),
93 	TESTSTR("The quick brown fox\0jumps over the lazy dog"),
94 	TESTSTR("The quick brown fox \0umps over the lazy dog"),
95 	TESTSTR("The quick brown fox j\0mps over the lazy dog"),
96 	TESTSTR("The quick brown fox ju\0ps over the lazy dog"),
97 	TESTSTR("The quick brown fox jum\0s over the lazy dog"),
98 	TESTSTR("The quick brown fox jump\0 over the lazy dog"),
99 	TESTSTR("The quick brown fox jumps\0over the lazy dog"),
100 	TESTSTR("The quick brown fox jumps \0ver the lazy dog"),
101 	TESTSTR("The quick brown fox jumps o\0er the lazy dog"),
102 	TESTSTR("The quick brown fox jumps ov\0r the lazy dog"),
103 	TESTSTR("The quick brown fox jumps ove\0 the lazy dog"),
104 	TESTSTR("The quick brown fox jumps over\0the lazy dog"),
105 	TESTSTR("The quick brown fox jumps over \0he lazy dog"),
106 	TESTSTR("The quick brown fox jumps over t\0e lazy dog"),
107 	TESTSTR("The quick brown fox jumps over th\0 lazy dog"),
108 	TESTSTR("The quick brown fox jumps over the\0lazy dog"),
109 	TESTSTR("The quick brown fox jumps over the \0azy dog"),
110 	TESTSTR("The quick brown fox jumps over the l\0zy dog"),
111 	TESTSTR("The quick brown fox jumps over the la\0y dog"),
112 	TESTSTR("The quick brown fox jumps over the laz\0 dog"),
113 	TESTSTR("The quick brown fox jumps over the lazy\0dog"),
114 	TESTSTR("The quick brown fox jumps over the lazy \0og"),
115 	TESTSTR("The quick brown fox jumps over the lazy d\0g"),
116 	TESTSTR("The quick brown fox jumps over the lazy do\0"),
117 	TESTSTR("The quick brown fox jumps over the lazy dog"),
118 	{ NULL, 0 },
119 };
120 
121 ATF_TC(test00);
122 ATF_TC_HEAD(test00, tc)
123 {
124 	atf_tc_set_md_var(tc, "descr", "test00");
125 }
126 ATF_TC_BODY(test00, tc)
127 {
128 	const char **p;
129 	char buf[BUFSIZ];
130 	FILE *fp;
131 
132 	for (p = &mode_rwa[0]; *p != NULL; ++p) {
133 		fp = fmemopen(&buf[0], sizeof(buf), *p);
134 /*
135  * Upon successful completion, fmemopen() shall return a pointer to the
136  * object controlling the stream.
137  */
138 		ATF_CHECK(fp != NULL);
139 
140 		ATF_CHECK(fclose(fp) == 0);
141 	}
142 }
143 
144 ATF_TC(test01);
145 ATF_TC_HEAD(test01, tc)
146 {
147 	atf_tc_set_md_var(tc, "descr", "test01");
148 }
149 ATF_TC_BODY(test01, tc)
150 {
151 	const char **p;
152 	const char *mode[] = {
153 	    "r+", "rb+", "r+b",
154 	    "w+", "wb+", "w+b",
155 	    "a+", "ab+", "a+b",
156 	    NULL
157 	};
158 	FILE *fp;
159 
160 	for (p = &mode[0]; *p != NULL; ++p) {
161 /*
162  * If a null pointer is specified as the buf argument, fmemopen() shall
163  * allocate size bytes of memory as if by a call to malloc().
164  */
165 		fp = fmemopen(NULL, BUFSIZ, *p);
166 		ATF_CHECK(fp != NULL);
167 
168 /*
169  * If buf is a null pointer, the initial position shall always be set
170  * to the beginning of the buffer.
171  */
172 		ATF_CHECK(ftello(fp) == (off_t)0);
173 
174 		ATF_CHECK(fclose(fp) == 0);
175 	}
176 }
177 
178 ATF_TC(test02);
179 ATF_TC_HEAD(test02, tc)
180 {
181         atf_tc_set_md_var(tc, "descr", "test02");
182 }
183 ATF_TC_BODY(test02, tc)
184 {
185 	const char **p;
186 	char buf[BUFSIZ];
187 	FILE *fp;
188 
189 	for (p = &mode_r[0]; *p != NULL; ++p) {
190 
191 		memset(&buf[0], 0x1, sizeof(buf));
192 		fp = fmemopen(&buf[0], sizeof(buf), *p);
193 		ATF_CHECK(fp != NULL);
194 
195 /*
196  * This position is initially set to either the beginning of the buffer
197  * (for r and w modes)
198  */
199 		ATF_CHECK((unsigned char)buf[0] == 0x1);
200 		ATF_CHECK(ftello(fp) == (off_t)0);
201 
202 /*
203  * The stream also maintains the size of the current buffer contents.
204  * For modes r and r+ the size is set to the value given by the size argument.
205  */
206 #if !defined(__GLIBC__)
207 		ATF_CHECK(fseeko(fp, (off_t)0, SEEK_END) == 0);
208 		ATF_CHECK(ftello(fp) == (off_t)sizeof(buf));
209 #endif
210 		ATF_CHECK(fclose(fp) == 0);
211 	}
212 }
213 
214 ATF_TC(test03);
215 ATF_TC_HEAD(test03, tc)
216 {
217         atf_tc_set_md_var(tc, "descr", "test03");
218 }
219 ATF_TC_BODY(test03, tc)
220 {
221 	const char **p;
222 	char buf[BUFSIZ];
223 	FILE *fp;
224 
225 	for (p = &mode_w[0]; *p != NULL; ++p) {
226 
227 		memset(&buf[0], 0x1, sizeof(buf));
228 		fp = fmemopen(&buf[0], sizeof(buf), *p);
229 		ATF_CHECK(fp != NULL);
230 
231 /*
232  * This position is initially set to either the beginning of the buffer
233  * (for r and w modes)
234  */
235 		ATF_CHECK(buf[0] == '\0');
236 		ATF_CHECK(ftello(fp) == (off_t)0);
237 
238 /*
239  * For modes w and w+ the initial size is zero
240  */
241 		ATF_CHECK(fseeko(fp, (off_t)0, SEEK_END) == 0);
242 		ATF_CHECK(ftello(fp) == (off_t)0);
243 
244 		ATF_CHECK(fclose(fp) == 0);
245 	}
246 }
247 
248 ATF_TC(test04);
249 ATF_TC_HEAD(test04, tc)
250 {
251 	atf_tc_set_md_var(tc, "descr", "test04");
252 }
253 ATF_TC_BODY(test04, tc)
254 {
255 	const char **p;
256 	char buf[BUFSIZ];
257 	FILE *fp;
258 
259 /*
260  * or to the first null byte in the buffer (for a modes)
261  */
262 	for (p = &mode_a[0]; *p != NULL; ++p) {
263 
264 		memset(&buf[0], 0x1, sizeof(buf));
265 		fp = fmemopen(&buf[0], sizeof(buf), *p);
266 		ATF_CHECK(fp != NULL);
267 
268 		ATF_CHECK((unsigned char)buf[0] == 0x1);
269 
270 /* If no null byte is found in append mode,
271  * the initial position is set to one byte after the end of the buffer.
272  */
273 #if !defined(__GLIBC__)
274 		ATF_CHECK(ftello(fp) == (off_t)sizeof(buf));
275 #endif
276 
277 /*
278  * and for modes a and a+ the initial size is either the position of the
279  * first null byte in the buffer or the value of the size argument
280  * if no null byte is found.
281  */
282 #if !defined(__GLIBC__)
283 		ATF_CHECK(fseeko(fp, (off_t)0, SEEK_END) == 0);
284 		ATF_CHECK(ftello(fp) == (off_t)sizeof(buf));
285 #endif
286 
287 		ATF_CHECK(fclose(fp) == 0);
288 	}
289 }
290 
291 ATF_TC(test05);
292 ATF_TC_HEAD(test05, tc)
293 {
294 	atf_tc_set_md_var(tc, "descr", "test05");
295 }
296 ATF_TC_BODY(test05, tc)
297 {
298 	const char **p;
299 	FILE *fp;
300 	char buf[BUFSIZ];
301 
302 	for (p = &mode_rwa[0]; *p != NULL; ++p) {
303 /*
304  * Otherwise, a null pointer shall be returned, and errno shall be set
305  * to indicate the error.
306  */
307 		errno = 0;
308 		fp = fmemopen(NULL, (size_t)0, *p);
309 		ATF_CHECK(fp == NULL);
310 		ATF_CHECK(errno == EINVAL);
311 
312 		errno = 0;
313 		fp = fmemopen((void *)&buf[0], 0, *p);
314 		ATF_CHECK(fp == NULL);
315 		ATF_CHECK(errno == EINVAL);
316 	}
317 }
318 
319 ATF_TC(test06);
320 ATF_TC_HEAD(test06, tc)
321 {
322 	atf_tc_set_md_var(tc, "descr", "test06");
323 }
324 ATF_TC_BODY(test06, tc)
325 {
326 	const char **p;
327 	const char *mode[] = { "", " ", "???", NULL };
328 	FILE *fp;
329 
330 	for (p = &mode[0]; *p != NULL; ++p) {
331 /*
332  * The value of the mode argument is not valid.
333  */
334 		fp = fmemopen(NULL, 1, *p);
335 		ATF_CHECK(fp == NULL);
336 		ATF_CHECK(errno == EINVAL);
337 	}
338 }
339 
340 ATF_TC(test07);
341 ATF_TC_HEAD(test07, tc)
342 {
343 	atf_tc_set_md_var(tc, "descr", "test07");
344 }
345 ATF_TC_BODY(test07, tc)
346 {
347 #if !defined(__GLIBC__)
348 	const char **p;
349 	const char *mode[] = {
350 	    "r", "rb",
351 	    "w", "wb",
352 	    "a", "ab",
353 	    NULL
354 	};
355 	FILE *fp;
356 
357 	for (p = &mode[0]; *p != NULL; ++p) {
358 /*
359  * Because this feature is only useful when the stream is opened for updating
360  * (because there is no way to get a pointer to the buffer) the fmemopen()
361  * call may fail if the mode argument does not include a '+' .
362  */
363 		errno = 0;
364 		fp = fmemopen(NULL, 1, *p);
365 		ATF_CHECK(fp == NULL);
366 		ATF_CHECK(errno == EINVAL);
367 	}
368 #endif
369 }
370 
371 ATF_TC(test08);
372 ATF_TC_HEAD(test08, tc)
373 {
374 	atf_tc_set_md_var(tc, "descr", "test08");
375 }
376 ATF_TC_BODY(test08, tc)
377 {
378 #if !defined(__GLIBC__)
379 	const char **p;
380 	const char *mode[] = {
381 	    "r+", "rb+", "r+b",
382 	    "w+", "wb+", "w+b",
383 	    "a+", "ab+", "a+b",
384 	    NULL
385 	};
386 	FILE *fp;
387 
388 	for (p = &mode[0]; *p != NULL; ++p) {
389 /*
390  * The buf argument is a null pointer and the allocation of a buffer of
391  * length size has failed.
392  */
393 		fp = fmemopen(NULL, SIZE_MAX, *p);
394 		ATF_CHECK(fp == NULL);
395 		ATF_CHECK(errno == ENOMEM);
396 	}
397 #endif
398 }
399 
400 /*
401  * test09 - test14:
402  * An attempt to seek a memory buffer stream to a negative position or to a
403  * position larger than the buffer size given in the size argument shall fail.
404  */
405 
406 ATF_TC(test09);
407 ATF_TC_HEAD(test09, tc)
408 {
409 	atf_tc_set_md_var(tc, "descr", "test09");
410 }
411 ATF_TC_BODY(test09, tc)
412 {
413 	struct testcase *t;
414 	const char **p;
415 	char buf[BUFSIZ];
416 	FILE *fp;
417 	off_t i;
418 
419 	for (t = &testcases[0]; t->s != NULL; ++t) {
420 		for (p = &mode_rwa[0]; *p != NULL; ++p) {
421 
422 			memcpy(&buf[0], t->s, t->n);
423 			fp = fmemopen(&buf[0], t->n, *p);
424 			ATF_CHECK(fp != NULL);
425 
426 /*
427  * test fmemopen_seek(SEEK_SET)
428  */
429 			/* zero */
430 			ATF_CHECK(fseeko(fp, (off_t)0, SEEK_SET) == 0);
431 			ATF_CHECK(ftello(fp) == (off_t)0);
432 
433 			/* positive */
434 			for (i = (off_t)1; i <= (off_t)t->n; ++i) {
435 				ATF_CHECK(fseeko(fp, i, SEEK_SET) == 0);
436 				ATF_CHECK(ftello(fp) == i);
437 			}
438 			/* positive + OOB */
439 			ATF_CHECK(fseeko(fp, t->n + 1, SEEK_SET) == -1);
440 			ATF_CHECK(ftello(fp) == t->n);
441 
442 			/* negative + OOB */
443 			ATF_CHECK(fseeko(fp, (off_t)-1, SEEK_SET) == -1);
444 			ATF_CHECK(ftello(fp) == t->n);
445 
446 			ATF_CHECK(fclose(fp) == 0);
447 		}
448 	}
449 }
450 
451 const char *mode_rw[] = {
452     "r", "rb", "r+", "rb+", "r+b",
453     "w", "wb", "w+", "wb+", "w+b",
454     NULL
455 };
456 
457 ATF_TC(test10);
458 ATF_TC_HEAD(test10, tc)
459 {
460 	atf_tc_set_md_var(tc, "descr", "test10");
461 }
462 ATF_TC_BODY(test10, tc)
463 {
464 	struct testcase *t;
465 	off_t len, i;
466 	const char **p;
467 	char buf[BUFSIZ];
468 	FILE *fp;
469 
470 	for (t = &testcases[0]; t->s != NULL; ++t) {
471 		len = (off_t)strnlen(t->s, t->n);
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 ATF_TC(test12);
567 ATF_TC_HEAD(test12, tc)
568 {
569 	atf_tc_set_md_var(tc, "descr", "test12");
570 }
571 ATF_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 
624 ATF_TC(test13);
625 ATF_TC_HEAD(test13, tc)
626 {
627 	atf_tc_set_md_var(tc, "descr", "test13");
628 }
629 ATF_TC_BODY(test13, tc)
630 {
631 	struct testcase *t;
632 	off_t len, rest, 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 		len = (off_t)strnlen(t->s, t->n);
640 		rest = t->n - len;
641 		for (p = &mode_w[0]; *p != NULL; ++p) {
642 
643 			memcpy(buf, t->s, t->n);
644 			fp = fmemopen(&buf[0], t->n, *p);
645 			ATF_CHECK(fp != NULL);
646 /*
647  * test fmemopen_seek(SEEK_END)
648  */
649 #if !defined(__GLIBC__)
650 			ATF_CHECK(ftello(fp) == (off_t)0);
651 			ATF_CHECK(buf[0] == '\0');
652 
653 			/* zero */
654 			ATF_CHECK(fseeko(fp, (off_t)0, SEEK_END) == 0);
655 			ATF_CHECK(ftello(fp) == (off_t)0);
656 
657 			/* positive + OOB */
658 			ATF_CHECK(fseeko(fp, (off_t)t->n + 1, SEEK_END) == -1);
659 			ATF_CHECK(ftello(fp) == (off_t)0);
660 
661 			/* negative + OOB */
662 			ATF_CHECK(fseeko(fp, -1, SEEK_END) == -1);
663 			ATF_CHECK(ftello(fp) == (off_t)0);
664 
665 			/* positive */
666 			for (i = 1; i <= t->n; ++i) {
667 				ATF_CHECK(fseeko(fp, i, SEEK_END) == 0);
668 				ATF_CHECK(ftello(fp) == i);
669 			}
670 #endif
671 			ATF_CHECK(fclose(fp) == 0);
672 		}
673 	}
674 }
675 
676 ATF_TC(test14);
677 ATF_TC_HEAD(test14, tc)
678 {
679 	atf_tc_set_md_var(tc, "descr", "test14");
680 }
681 ATF_TC_BODY(test14, tc)
682 {
683 	struct testcase *t;
684 	off_t len, rest, i;
685 	const char **p;
686 	char buf[BUFSIZ];
687 	FILE *fp;
688 
689 	/* test fmemopen_seek(SEEK_END) */
690 	for (t = &testcases[0]; t->s != NULL; ++t) {
691 		len = (off_t)strnlen(t->s, t->n);
692 		rest = (off_t)t->n - len;
693 		for (p = &mode_a[0]; *p != NULL; ++p) {
694 
695 			memcpy(buf, t->s, t->n);
696 			fp = fmemopen(&buf[0], t->n, *p);
697 			ATF_CHECK(fp != NULL);
698 /*
699  * test fmemopen_seek(SEEK_END)
700  */
701 #if !defined(__GLIBC__)
702 			ATF_CHECK(ftello(fp) == len);
703 
704 			/* zero */
705 			ATF_CHECK(fseeko(fp, 0, SEEK_END) == 0);
706 			ATF_CHECK(ftello(fp) == len);
707 
708 			/* positive + OOB */
709 			ATF_CHECK(fseeko(fp, rest + 1, SEEK_END) == -1);
710 			ATF_CHECK(ftello(fp) == len);
711 
712 			/* negative + OOB */
713 			ATF_CHECK(fseeko(fp, -(len + 1), SEEK_END) == -1);
714 			ATF_CHECK(ftello(fp) == len);
715 
716 			/* positive */
717 			for (i = 1; i <= rest; ++i) {
718 				ATF_CHECK(fseeko(fp, i, SEEK_END) == 0);
719 				ATF_CHECK(ftello(fp) == len + i);
720 			}
721 
722 			/* negative */
723 			for (i = 1; i < len; ++i) {
724 				ATF_CHECK(fseeko(fp, -i, SEEK_END) == 0);
725 				ATF_CHECK(ftello(fp) == len - i);
726 			}
727 #endif
728 			ATF_CHECK(fclose(fp) == 0);
729 		}
730 	}
731 }
732 
733 const char *mode_rw1[] = {
734     "r", "rb", "r+", "rb+", "r+b",
735     "w+", "wb+",
736     NULL
737 };
738 
739 /* test15 - 18:
740  * When a stream open for writing is flushed or closed, a null byte is written
741  * at the current position or at the end of the buffer, depending on the size
742  * of the contents.
743  */
744 
745 ATF_TC(test15);
746 ATF_TC_HEAD(test15, tc)
747 {
748 	atf_tc_set_md_var(tc, "descr", "test15");
749 }
750 ATF_TC_BODY(test15, tc)
751 {
752 	struct testcase *t;
753 	const char **p;
754 	char buf0[BUFSIZ];
755 	FILE *fp;
756 	int i;
757 
758 	for (t = &testcases[0]; t->s != NULL; ++t) {
759 		for (p = &mode_rw1[0]; *p != NULL; ++p) {
760 
761 			memcpy(&buf0[0], t->s, t->n);
762 			fp = fmemopen(&buf0[0], t->n, *p);
763 			ATF_CHECK(fp != NULL);
764 /*
765  * test fmemopen_read + fgetc(3)
766  */
767 			for (i = 0; i < t->n; ++i) {
768 				ATF_CHECK(ftello(fp) == (off_t)i);
769 				ATF_CHECK(fgetc(fp) == buf0[i]);
770 				ATF_CHECK(feof(fp) == 0);
771 				ATF_CHECK(ftello(fp) == (off_t)i + 1);
772 			}
773 			ATF_CHECK(fgetc(fp) == EOF);
774 			ATF_CHECK(feof(fp) != 0);
775 			ATF_CHECK(ftello(fp) == (off_t)t->n);
776 			ATF_CHECK(fclose(fp) == 0);
777 		}
778 	}
779 }
780 
781 ATF_TC(test16);
782 ATF_TC_HEAD(test16, tc)
783 {
784 	atf_tc_set_md_var(tc, "descr", "test16");
785 }
786 ATF_TC_BODY(test16, tc)
787 {
788 	struct testcase *t;
789 	const char **p;
790 	char buf0[BUFSIZ], buf1[BUFSIZ];
791 	FILE *fp;
792 
793 	for (t = &testcases[0]; t->s != NULL; ++t) {
794 		for (p = &mode_rw1[0]; *p != NULL; ++p) {
795 
796 			memcpy(&buf0[0], t->s, t->n);
797 			buf1[t->n] = 0x1;
798 			fp = fmemopen(&buf0[0], t->n, *p);
799 			ATF_CHECK(fp != NULL);
800 /*
801  * test fmemopen_read + fread(4)
802  */
803 			ATF_CHECK(ftello(fp) == (off_t)0);
804 			ATF_CHECK(fread(&buf1[0], 1, sizeof(buf1), fp) == (size_t)t->n);
805 			ATF_CHECK(feof(fp) != 0);
806 			ATF_CHECK(memcmp(&buf0[0], &buf1[0], t->n) == 0);
807 			ATF_CHECK((unsigned char)buf1[t->n] == 0x1);
808 
809 			ATF_CHECK(fclose(fp) == 0);
810 		}
811 	}
812 }
813 
814 const char *mode_a1[] = { "a+", "ab+", NULL };
815 
816 ATF_TC(test17);
817 ATF_TC_HEAD(test17, tc)
818 {
819 	atf_tc_set_md_var(tc, "descr", "test17");
820 }
821 ATF_TC_BODY(test17, tc)
822 {
823 	struct testcase *t;
824 	size_t len;
825 	int i;
826 	const char **p;
827 	char buf[BUFSIZ];
828 	FILE *fp;
829 
830 	for (t = &testcases[0]; t->s != NULL; ++t) {
831 		len = strnlen(t->s, t->n);
832 		for (p = &mode_a1[0]; *p != NULL; ++p) {
833 
834 			memcpy(&buf[0], t->s, t->n);
835 			fp = fmemopen(&buf[0], t->n, *p);
836 			ATF_CHECK(fp != NULL);
837 /*
838  * test fmemopen_read + fgetc(3)
839  */
840 #if defined(__GLIBC__)
841 			if (i < t->n) {
842 #endif
843 			for (i = len; i < t->n; ++i) {
844 				ATF_CHECK(ftello(fp) == (off_t)i);
845 				ATF_CHECK(fgetc(fp) == buf[i]);
846 				ATF_CHECK(feof(fp) == 0);
847 				ATF_CHECK(ftello(fp) == (off_t)i + 1);
848 			}
849 			ATF_CHECK(fgetc(fp) == EOF);
850 			ATF_CHECK(feof(fp) != 0);
851 			ATF_CHECK(ftello(fp) == (off_t)t->n);
852 			rewind(fp);
853 			for (i = 0; i < t->n; ++i) {
854 				ATF_CHECK(ftello(fp) == (off_t)i);
855 				ATF_CHECK(fgetc(fp) == buf[i]);
856 				ATF_CHECK(feof(fp) == 0);
857 				ATF_CHECK(ftello(fp) == (off_t)i + 1);
858 			}
859 			ATF_CHECK(fgetc(fp) == EOF);
860 			ATF_CHECK(feof(fp) != 0);
861 			ATF_CHECK(ftello(fp) == (off_t)t->n);
862 #if defined(__GLIBC__)
863 			}
864 #endif
865 			ATF_CHECK(fclose(fp) == 0);
866 		}
867 	}
868 }
869 
870 ATF_TC(test18);
871 ATF_TC_HEAD(test18, tc)
872 {
873 	atf_tc_set_md_var(tc, "descr", "test18");
874 }
875 ATF_TC_BODY(test18, tc)
876 {
877 	struct testcase *t;
878 	size_t len;
879 	const char **p;
880 	char buf0[BUFSIZ], buf1[BUFSIZ];
881 	FILE *fp;
882 
883 	for (t = &testcases[0]; t->s != NULL; ++t) {
884 		len = strnlen(t->s, t->n);
885 		for (p = &mode_a1[0]; *p != NULL; ++p) {
886 
887 			memcpy(&buf0[0], t->s, t->n);
888 			buf1[t->n - len] = 0x1;
889 			fp = fmemopen(&buf0[0], t->n, *p);
890 			ATF_CHECK(fp != NULL);
891 /*
892  * test fmemopen_read + fread(3)
893  */
894 #if defined(__GLIBC__)
895 			if (i < t->n) {
896 #endif
897 			ATF_CHECK(ftello(fp) == (off_t)len);
898 			ATF_CHECK(fread(&buf1[0], 1, sizeof(buf1), fp)
899 			    == t->n - len);
900 			ATF_CHECK(feof(fp) != 0);
901 			ATF_CHECK(!memcmp(&buf0[len], &buf1[0], t->n - len));
902 			ATF_CHECK((unsigned char)buf1[t->n - len] == 0x1);
903 			rewind(fp);
904 			buf1[t->n] = 0x1;
905 			ATF_CHECK(ftello(fp) == (off_t)0);
906 			ATF_CHECK(fread(&buf1[0], 1, sizeof(buf1), fp)
907 			    == (size_t)t->n);
908 			ATF_CHECK(feof(fp) != 0);
909 			ATF_CHECK(!memcmp(&buf0[0], &buf1[0], t->n));
910 			ATF_CHECK((unsigned char)buf1[t->n] == 0x1);
911 #if defined(__GLIBC__)
912 			}
913 #endif
914 			ATF_CHECK(fclose(fp) == 0);
915 		}
916 	}
917 }
918 
919 /*
920  * test19 - test22:
921  * If a stream open for update is flushed or closed and the last write has
922  * advanced the current buffer size, a null byte is written at the end of the
923  * buffer if it fits.
924  */
925 
926 const char *mode_rw2[] = {
927     "r+", "rb+", "r+b",
928     "w", "wb", "w+", "wb+", "w+b",
929     NULL
930 };
931 
932 ATF_TC(test19);
933 ATF_TC_HEAD(test19, tc)
934 {
935 	atf_tc_set_md_var(tc, "descr", "test19");
936 }
937 ATF_TC_BODY(test19, tc)
938 {
939 	struct testcase *t;
940 	size_t len;
941 	int i;
942 	const char **p;
943 	char buf[BUFSIZ];
944 	FILE *fp;
945 
946 	for (t = &testcases[0]; t->s != NULL; ++t) {
947 		len = strnlen(t->s, t->n);
948 		for (p = &mode_rw2[0]; *p != NULL; ++p) {
949 
950 			memcpy(&buf[0], t->s, t->n);
951 			buf[t->n] = 0x1;
952 			fp = fmemopen(&buf[0], t->n + 1, *p);
953 			ATF_CHECK(fp != NULL);
954 			setbuf(fp, NULL);
955 /*
956  * test fmemopen_write + fputc(3)
957  */
958 			for (i = 0; i < t->n; ++i) {
959 				ATF_CHECK(ftello(fp) == (off_t)i);
960 				ATF_CHECK(fputc(t->s[i], fp) == t->s[i]);
961 				ATF_CHECK(buf[i] == t->s[i]);
962 				ATF_CHECK(ftello(fp) == (off_t)i + 1);
963 				ATF_CHECK(buf[i] == t->s[i]);
964 #if !defined(__GLIBC__)
965 				ATF_CHECK(buf[i + 1] == '\0');
966 #endif
967 			}
968 
969 /* don't accept non nul character at end of buffer */
970 			ATF_CHECK(fputc(0x1, fp) == EOF);
971 			ATF_CHECK(ftello(fp) == (off_t)t->n);
972 			ATF_CHECK(feof(fp) == 0);
973 
974 /* accept nul character at end of buffer */
975 			ATF_CHECK(fputc('\0', fp) == '\0');
976 			ATF_CHECK(ftello(fp) == (off_t)t->n + 1);
977 			ATF_CHECK(feof(fp) == 0);
978 
979 /* reach EOF */
980 			ATF_CHECK(fputc('\0', fp) == EOF);
981 			ATF_CHECK(ftello(fp) == (off_t)t->n + 1);
982 
983 			/* compare */
984 			ATF_CHECK(memcmp(&buf[0], t->s, t->n) == 0);
985 			ATF_CHECK(buf[t->n] == '\0');
986 
987 			ATF_CHECK(fclose(fp) == 0);
988 		}
989 	}
990 }
991 
992 ATF_TC(test20);
993 ATF_TC_HEAD(test20, tc)
994 {
995 	atf_tc_set_md_var(tc, "descr", "test20");
996 }
997 ATF_TC_BODY(test20, tc)
998 {
999 	struct testcase *t;
1000 	size_t len;
1001 	const char **p;
1002 	char buf[BUFSIZ];
1003 	FILE *fp;
1004 
1005 	for (t = &testcases[0]; t->s != NULL; ++t) {
1006 		len = strnlen(t->s, t->n);
1007 		for (p = &mode_rw2[0]; *p != NULL; ++p) {
1008 
1009 			memcpy(&buf[0], t->s, t->n);
1010 			buf[t->n] = 0x1;
1011 			fp = fmemopen(&buf[0], t->n + 1, *p);
1012 			ATF_CHECK(fp != NULL);
1013 			setbuf(fp, NULL);
1014 			ATF_CHECK(fwrite(t->s, 1, t->n, fp) == (size_t)t->n);
1015 /*
1016  * test fmemopen_write + fwrite(3)
1017  */
1018 #if !defined(__GLIBC__)
1019 			ATF_CHECK(buf[t->n] == '\0');
1020 
1021 /* don't accept non nul character at end of buffer */
1022 			ATF_CHECK(fwrite("\x1", 1, 1, fp) == 0);
1023 			ATF_CHECK(ftello(fp) == (off_t)t->n);
1024 			ATF_CHECK(feof(fp) == 0);
1025 #endif
1026 
1027 /* accept nul character at end of buffer */
1028 			ATF_CHECK(fwrite("\x0", 1, 1, fp) == 1);
1029 			ATF_CHECK(ftello(fp) == (off_t)t->n + 1);
1030 			ATF_CHECK(feof(fp) == 0);
1031 
1032 /* reach EOF */
1033 			ATF_CHECK(fputc('\0', fp) == EOF);
1034 			ATF_CHECK(ftello(fp) == (off_t)t->n + 1);
1035 
1036 /* compare */
1037 			ATF_CHECK(memcmp(&buf[0], t->s, t->n) == 0);
1038 			ATF_CHECK(buf[t->n] == '\0');
1039 
1040 			ATF_CHECK(fclose(fp) == 0);
1041 		}
1042 	}
1043 }
1044 
1045 ATF_TC(test21);
1046 ATF_TC_HEAD(test21, tc)
1047 {
1048 	atf_tc_set_md_var(tc, "descr", "test21");
1049 }
1050 ATF_TC_BODY(test21, tc)
1051 {
1052 	struct testcase *t;
1053 	int len, i;
1054 	const char **p;
1055 	char buf[BUFSIZ];
1056 	FILE *fp;
1057 
1058 	for (t = &testcases[0]; t->s != NULL; ++t) {
1059 		len = strnlen(t->s, t->n);
1060 		for (p = &mode_a[0]; *p != NULL; ++p) {
1061 			memcpy(&buf[0], t->s, t->n);
1062 			fp = fmemopen(&buf[0], t->n, *p);
1063 			ATF_CHECK(fp != NULL);
1064 			setbuf(fp, NULL);
1065 /*
1066  * test fmemopen_write + fputc(3)
1067  */
1068 			if (len < t->n) {
1069 				for (i = len; i < t->n - 1; ++i) {
1070 					ATF_CHECK(ftello(fp) == (off_t)i);
1071 					ATF_CHECK(fputc(t->s[i - len], fp)
1072 					    == t->s[i - len]);
1073 					ATF_CHECK(buf[i] == t->s[i - len]);
1074 					ATF_CHECK(ftello(fp) == (off_t)i + 1);
1075 #if !defined(__GLIBC__)
1076 					ATF_CHECK(buf[i + 1] == '\0');
1077 #endif
1078 				}
1079 
1080 /* don't accept non nul character at end of buffer */
1081 				ATF_CHECK(ftello(fp) == (off_t)t->n - 1);
1082 				ATF_CHECK(fputc(0x1, fp) == EOF);
1083 				ATF_CHECK(ftello(fp) == (off_t)t->n - 1);
1084 
1085 /* accept nul character at end of buffer */
1086 				ATF_CHECK(ftello(fp) == (off_t)t->n - 1);
1087 				ATF_CHECK(fputc('\0', fp) == '\0');
1088 				ATF_CHECK(ftello(fp) == (off_t)t->n);
1089 			}
1090 
1091 /* reach EOF */
1092 			ATF_CHECK(ftello(fp) == (off_t)t->n);
1093 			ATF_CHECK(fputc('\0', fp) == EOF);
1094 			ATF_CHECK(ftello(fp) == (off_t)t->n);
1095 
1096 			ATF_CHECK(fclose(fp) == 0);
1097 		}
1098 	}
1099 }
1100 
1101 ATF_TC(test22);
1102 ATF_TC_HEAD(test22, tc)
1103 {
1104 	atf_tc_set_md_var(tc, "descr", "test22");
1105 }
1106 ATF_TC_BODY(test22, tc)
1107 {
1108 	struct testcase *t0, *t1;
1109 	size_t len0, len1, nleft;
1110 	const char **p;
1111 	char buf[BUFSIZ];
1112 	FILE *fp;
1113 
1114 	for (t0 = &testcases[0]; t0->s != NULL; ++t0) {
1115 		len0 = strnlen(t0->s, t0->n);
1116 		for (t1 = &testcases[0]; t1->s != NULL; ++t1) {
1117 			len1 = strnlen(t1->s, t1->n);
1118 			for (p = &mode_a[0]; *p != NULL; ++p) {
1119 
1120 				memcpy(&buf[0], t0->s, t0->n);
1121 				fp = fmemopen(&buf[0], t0->n, *p);
1122 				ATF_CHECK(fp != NULL);
1123 				setbuf(fp, NULL);
1124 /*
1125  * test fmemopen_write + fwrite(3)
1126  */
1127 				nleft = t0->n - len0;
1128 #if !defined(__GLIBC__)
1129 				if (nleft == 0 || len1 == nleft - 1) {
1130 					ATF_CHECK(fwrite(t1->s, 1, t1->n, fp)
1131 					    == nleft);
1132 					ATF_CHECK(ftell(fp) == t1->n);
1133 				} else {
1134 					ATF_CHECK(fwrite(t1->s, 1, t1->n, fp)
1135 					    == nleft - 1);
1136 					ATF_CHECK(ftell(fp) == t1->n - 1);
1137 				}
1138 #endif
1139 				ATF_CHECK(fclose(fp) == 0);
1140 			}
1141 		}
1142 	}
1143 }
1144 
1145 ATF_TP_ADD_TCS(tp)
1146 {
1147 	ATF_TP_ADD_TC(tp, test00);
1148 	ATF_TP_ADD_TC(tp, test01);
1149 	ATF_TP_ADD_TC(tp, test02);
1150 	ATF_TP_ADD_TC(tp, test03);
1151 	ATF_TP_ADD_TC(tp, test04);
1152 	ATF_TP_ADD_TC(tp, test05);
1153 	ATF_TP_ADD_TC(tp, test06);
1154 	ATF_TP_ADD_TC(tp, test07);
1155 	ATF_TP_ADD_TC(tp, test08);
1156 	ATF_TP_ADD_TC(tp, test09);
1157 	ATF_TP_ADD_TC(tp, test10);
1158 	ATF_TP_ADD_TC(tp, test11);
1159 	ATF_TP_ADD_TC(tp, test12);
1160 	ATF_TP_ADD_TC(tp, test13);
1161 	ATF_TP_ADD_TC(tp, test14);
1162 	ATF_TP_ADD_TC(tp, test15);
1163 	ATF_TP_ADD_TC(tp, test16);
1164 	ATF_TP_ADD_TC(tp, test17);
1165 	ATF_TP_ADD_TC(tp, test18);
1166 	ATF_TP_ADD_TC(tp, test19);
1167 	ATF_TP_ADD_TC(tp, test20);
1168 	ATF_TP_ADD_TC(tp, test21);
1169 	ATF_TP_ADD_TC(tp, test22);
1170 
1171 	return atf_no_error();
1172 }
1173