xref: /netbsd-src/tests/lib/libc/stdio/t_fmemopen.c (revision ba65fde2d7fefa7d39838fa5fa855e62bd606b5e)
1 /* $NetBSD: t_fmemopen.c,v 1.3 2011/08/22 00:33:16 dholland 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 
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 len, i;
467 	const char **p;
468 	char buf[BUFSIZ];
469 	FILE *fp;
470 
471 	for (t = &testcases[0]; t->s != NULL; ++t) {
472 		len = (off_t)strnlen(t->s, t->n);
473 		for (p = &mode_rw[0]; *p != NULL; ++p) {
474 
475 			memcpy(&buf[0], t->s, t->n);
476 			fp = fmemopen(&buf[0], t->n, *p);
477 			ATF_CHECK(fp != NULL);
478 
479 /*
480  * test fmemopen_seek(SEEK_CUR)
481  */
482 			ATF_CHECK(ftello(fp) == (off_t)0);
483 
484 			/* zero */
485 			ATF_CHECK(fseeko(fp, (off_t)0, SEEK_CUR) == 0);
486 			ATF_CHECK(ftello(fp) == (off_t)0);
487 
488 			/* negative & OOB */
489 			ATF_CHECK(fseeko(fp, (off_t)-1, SEEK_CUR) == -1);
490 			ATF_CHECK(ftello(fp) == (off_t)0);
491 
492 			/* positive */
493 			for (i = 0; i < (off_t)t->n; ++i) {
494 				ATF_CHECK(fseeko(fp, (off_t)1, SEEK_CUR) == 0);
495 				ATF_CHECK(ftello(fp) == i + 1);
496 			}
497 
498 			/* positive & OOB */
499 			ATF_CHECK(fseeko(fp, (off_t)1, SEEK_CUR) == -1);
500 			ATF_CHECK(ftello(fp) == (off_t)t->n);
501 
502 			ATF_CHECK(fclose(fp) == 0);
503 		}
504 	}
505 }
506 
507 ATF_TC(test11);
508 ATF_TC_HEAD(test11, tc)
509 {
510 	atf_tc_set_md_var(tc, "descr", "test11");
511 }
512 ATF_TC_BODY(test11, tc)
513 {
514 	struct testcase *t;
515 	off_t len, rest, i;
516 	const char **p;
517 	char buf[BUFSIZ];
518 	FILE *fp;
519 
520 	/* test fmemopen_seek(SEEK_CUR) */
521 	for (t = &testcases[0]; t->s != NULL; ++t) {
522 		len = (off_t)strnlen(t->s, t->n);
523 		rest = (off_t)t->n - len;
524 		for (p = &mode_a[0]; *p != NULL; ++p) {
525 
526 			memcpy(&buf[0], t->s, t->n);
527 			fp = fmemopen(&buf[0], t->n, *p);
528 			ATF_CHECK(fp != NULL);
529 /*
530  * test fmemopen_seek(SEEK_CUR)
531  */
532 #if defined(__GLIBC__)
533 			if (i < (off_t)t->n) {
534 #endif
535 			/* zero */
536 			ATF_CHECK(fseeko(fp, (off_t)0, SEEK_CUR) == 0);
537 			ATF_CHECK(ftello(fp) == len);
538 
539 			/* posive */
540 			for (i = (off_t)1; i <= rest; ++i) {
541 				ATF_CHECK(fseeko(fp, (off_t)1, SEEK_CUR) == 0);
542 				ATF_CHECK(ftello(fp) == len + i);
543 			}
544 
545 			/* positive + OOB */
546 			ATF_CHECK(fseeko(fp, (off_t)1, SEEK_CUR) == -1);
547 			ATF_CHECK(ftello(fp) == (off_t)t->n);
548 
549 			/* negative */
550 			for (i = (off_t)1; i <= (off_t)t->n; ++i) {
551 				ATF_CHECK(fseeko(fp, (off_t)-1, SEEK_CUR) == 0);
552 				ATF_CHECK(ftello(fp) == (off_t)t->n - i);
553 			}
554 
555 			/* negative + OOB */
556 			ATF_CHECK(fseeko(fp, (off_t)-1, SEEK_CUR) == -1);
557 			ATF_CHECK(ftello(fp) == (off_t)0);
558 
559 #if defined(__GLIBC__)
560 			}
561 #endif
562 			ATF_CHECK(fclose(fp) == 0);
563 		}
564 	}
565 }
566 
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 
625 ATF_TC(test13);
626 ATF_TC_HEAD(test13, tc)
627 {
628 	atf_tc_set_md_var(tc, "descr", "test13");
629 }
630 ATF_TC_BODY(test13, tc)
631 {
632 	struct testcase *t;
633 	off_t len, rest, i;
634 	const char **p;
635 	char buf[BUFSIZ];
636 	FILE *fp;
637 
638 	/* test fmemopen_seek(SEEK_END) */
639 	for (t = &testcases[0]; t->s != NULL; ++t) {
640 		len = (off_t)strnlen(t->s, t->n);
641 		rest = t->n - len;
642 		for (p = &mode_w[0]; *p != NULL; ++p) {
643 
644 			memcpy(buf, t->s, t->n);
645 			fp = fmemopen(&buf[0], t->n, *p);
646 			ATF_CHECK(fp != NULL);
647 /*
648  * test fmemopen_seek(SEEK_END)
649  */
650 #if !defined(__GLIBC__)
651 			ATF_CHECK(ftello(fp) == (off_t)0);
652 			ATF_CHECK(buf[0] == '\0');
653 
654 			/* zero */
655 			ATF_CHECK(fseeko(fp, (off_t)0, SEEK_END) == 0);
656 			ATF_CHECK(ftello(fp) == (off_t)0);
657 
658 			/* positive + OOB */
659 			ATF_CHECK(fseeko(fp, (off_t)t->n + 1, SEEK_END) == -1);
660 			ATF_CHECK(ftello(fp) == (off_t)0);
661 
662 			/* negative + OOB */
663 			ATF_CHECK(fseeko(fp, -1, SEEK_END) == -1);
664 			ATF_CHECK(ftello(fp) == (off_t)0);
665 
666 			/* positive */
667 			for (i = 1; i <= t->n; ++i) {
668 				ATF_CHECK(fseeko(fp, i, SEEK_END) == 0);
669 				ATF_CHECK(ftello(fp) == i);
670 			}
671 #endif
672 			ATF_CHECK(fclose(fp) == 0);
673 		}
674 	}
675 }
676 
677 ATF_TC(test14);
678 ATF_TC_HEAD(test14, tc)
679 {
680 	atf_tc_set_md_var(tc, "descr", "test14");
681 }
682 ATF_TC_BODY(test14, tc)
683 {
684 	struct testcase *t;
685 	off_t len, rest, i;
686 	const char **p;
687 	char buf[BUFSIZ];
688 	FILE *fp;
689 
690 	/* test fmemopen_seek(SEEK_END) */
691 	for (t = &testcases[0]; t->s != NULL; ++t) {
692 		len = (off_t)strnlen(t->s, t->n);
693 		rest = (off_t)t->n - len;
694 		for (p = &mode_a[0]; *p != NULL; ++p) {
695 
696 			memcpy(buf, t->s, t->n);
697 			fp = fmemopen(&buf[0], t->n, *p);
698 			ATF_CHECK(fp != NULL);
699 /*
700  * test fmemopen_seek(SEEK_END)
701  */
702 #if !defined(__GLIBC__)
703 			ATF_CHECK(ftello(fp) == len);
704 
705 			/* zero */
706 			ATF_CHECK(fseeko(fp, 0, SEEK_END) == 0);
707 			ATF_CHECK(ftello(fp) == len);
708 
709 			/* positive + OOB */
710 			ATF_CHECK(fseeko(fp, rest + 1, SEEK_END) == -1);
711 			ATF_CHECK(ftello(fp) == len);
712 
713 			/* negative + OOB */
714 			ATF_CHECK(fseeko(fp, -(len + 1), SEEK_END) == -1);
715 			ATF_CHECK(ftello(fp) == len);
716 
717 			/* positive */
718 			for (i = 1; i <= rest; ++i) {
719 				ATF_CHECK(fseeko(fp, i, SEEK_END) == 0);
720 				ATF_CHECK(ftello(fp) == len + i);
721 			}
722 
723 			/* negative */
724 			for (i = 1; i < len; ++i) {
725 				ATF_CHECK(fseeko(fp, -i, SEEK_END) == 0);
726 				ATF_CHECK(ftello(fp) == len - i);
727 			}
728 #endif
729 			ATF_CHECK(fclose(fp) == 0);
730 		}
731 	}
732 }
733 
734 const char *mode_rw1[] = {
735     "r", "rb", "r+", "rb+", "r+b",
736     "w+", "wb+",
737     NULL
738 };
739 
740 /* test15 - 18:
741  * When a stream open for writing is flushed or closed, a null byte is written
742  * at the current position or at the end of the buffer, depending on the size
743  * of the contents.
744  */
745 
746 ATF_TC(test15);
747 ATF_TC_HEAD(test15, tc)
748 {
749 	atf_tc_set_md_var(tc, "descr", "test15");
750 }
751 ATF_TC_BODY(test15, tc)
752 {
753 	struct testcase *t;
754 	const char **p;
755 	char buf0[BUFSIZ];
756 	FILE *fp;
757 	int i;
758 
759 	for (t = &testcases[0]; t->s != NULL; ++t) {
760 		for (p = &mode_rw1[0]; *p != NULL; ++p) {
761 
762 			memcpy(&buf0[0], t->s, t->n);
763 			fp = fmemopen(&buf0[0], t->n, *p);
764 			ATF_CHECK(fp != NULL);
765 /*
766  * test fmemopen_read + fgetc(3)
767  */
768 			for (i = 0; i < t->n; ++i) {
769 				ATF_CHECK(ftello(fp) == (off_t)i);
770 				ATF_CHECK(fgetc(fp) == buf0[i]);
771 				ATF_CHECK(feof(fp) == 0);
772 				ATF_CHECK(ftello(fp) == (off_t)i + 1);
773 			}
774 			ATF_CHECK(fgetc(fp) == EOF);
775 			ATF_CHECK(feof(fp) != 0);
776 			ATF_CHECK(ftello(fp) == (off_t)t->n);
777 			ATF_CHECK(fclose(fp) == 0);
778 		}
779 	}
780 }
781 
782 ATF_TC(test16);
783 ATF_TC_HEAD(test16, tc)
784 {
785 	atf_tc_set_md_var(tc, "descr", "test16");
786 }
787 ATF_TC_BODY(test16, tc)
788 {
789 	struct testcase *t;
790 	const char **p;
791 	char buf0[BUFSIZ], buf1[BUFSIZ];
792 	FILE *fp;
793 
794 	for (t = &testcases[0]; t->s != NULL; ++t) {
795 		for (p = &mode_rw1[0]; *p != NULL; ++p) {
796 
797 			memcpy(&buf0[0], t->s, t->n);
798 			buf1[t->n] = 0x1;
799 			fp = fmemopen(&buf0[0], t->n, *p);
800 			ATF_CHECK(fp != NULL);
801 /*
802  * test fmemopen_read + fread(4)
803  */
804 			ATF_CHECK(ftello(fp) == (off_t)0);
805 			ATF_CHECK(fread(&buf1[0], 1, sizeof(buf1), fp) == (size_t)t->n);
806 			ATF_CHECK(feof(fp) != 0);
807 			ATF_CHECK(memcmp(&buf0[0], &buf1[0], t->n) == 0);
808 			ATF_CHECK((unsigned char)buf1[t->n] == 0x1);
809 
810 			ATF_CHECK(fclose(fp) == 0);
811 		}
812 	}
813 }
814 
815 const char *mode_a1[] = { "a+", "ab+", NULL };
816 
817 ATF_TC(test17);
818 ATF_TC_HEAD(test17, tc)
819 {
820 	atf_tc_set_md_var(tc, "descr", "test17");
821 }
822 ATF_TC_BODY(test17, tc)
823 {
824 	struct testcase *t;
825 	size_t len;
826 	int i;
827 	const char **p;
828 	char buf[BUFSIZ];
829 	FILE *fp;
830 
831 	for (t = &testcases[0]; t->s != NULL; ++t) {
832 		len = strnlen(t->s, t->n);
833 		for (p = &mode_a1[0]; *p != NULL; ++p) {
834 
835 			memcpy(&buf[0], t->s, t->n);
836 			fp = fmemopen(&buf[0], t->n, *p);
837 			ATF_CHECK(fp != NULL);
838 /*
839  * test fmemopen_read + fgetc(3)
840  */
841 #if defined(__GLIBC__)
842 			if (i < t->n) {
843 #endif
844 			for (i = len; i < t->n; ++i) {
845 				ATF_CHECK(ftello(fp) == (off_t)i);
846 				ATF_CHECK(fgetc(fp) == buf[i]);
847 				ATF_CHECK(feof(fp) == 0);
848 				ATF_CHECK(ftello(fp) == (off_t)i + 1);
849 			}
850 			ATF_CHECK(fgetc(fp) == EOF);
851 			ATF_CHECK(feof(fp) != 0);
852 			ATF_CHECK(ftello(fp) == (off_t)t->n);
853 			rewind(fp);
854 			for (i = 0; i < t->n; ++i) {
855 				ATF_CHECK(ftello(fp) == (off_t)i);
856 				ATF_CHECK(fgetc(fp) == buf[i]);
857 				ATF_CHECK(feof(fp) == 0);
858 				ATF_CHECK(ftello(fp) == (off_t)i + 1);
859 			}
860 			ATF_CHECK(fgetc(fp) == EOF);
861 			ATF_CHECK(feof(fp) != 0);
862 			ATF_CHECK(ftello(fp) == (off_t)t->n);
863 #if defined(__GLIBC__)
864 			}
865 #endif
866 			ATF_CHECK(fclose(fp) == 0);
867 		}
868 	}
869 }
870 
871 ATF_TC(test18);
872 ATF_TC_HEAD(test18, tc)
873 {
874 	atf_tc_set_md_var(tc, "descr", "test18");
875 }
876 ATF_TC_BODY(test18, tc)
877 {
878 	struct testcase *t;
879 	size_t len;
880 	const char **p;
881 	char buf0[BUFSIZ], buf1[BUFSIZ];
882 	FILE *fp;
883 
884 	for (t = &testcases[0]; t->s != NULL; ++t) {
885 		len = strnlen(t->s, t->n);
886 		for (p = &mode_a1[0]; *p != NULL; ++p) {
887 
888 			memcpy(&buf0[0], t->s, t->n);
889 			buf1[t->n - len] = 0x1;
890 			fp = fmemopen(&buf0[0], t->n, *p);
891 			ATF_CHECK(fp != NULL);
892 /*
893  * test fmemopen_read + fread(3)
894  */
895 #if defined(__GLIBC__)
896 			if (i < t->n) {
897 #endif
898 			ATF_CHECK(ftello(fp) == (off_t)len);
899 			ATF_CHECK(fread(&buf1[0], 1, sizeof(buf1), fp)
900 			    == t->n - len);
901 			ATF_CHECK(feof(fp) != 0);
902 			ATF_CHECK(!memcmp(&buf0[len], &buf1[0], t->n - len));
903 			ATF_CHECK((unsigned char)buf1[t->n - len] == 0x1);
904 			rewind(fp);
905 			buf1[t->n] = 0x1;
906 			ATF_CHECK(ftello(fp) == (off_t)0);
907 			ATF_CHECK(fread(&buf1[0], 1, sizeof(buf1), fp)
908 			    == (size_t)t->n);
909 			ATF_CHECK(feof(fp) != 0);
910 			ATF_CHECK(!memcmp(&buf0[0], &buf1[0], t->n));
911 			ATF_CHECK((unsigned char)buf1[t->n] == 0x1);
912 #if defined(__GLIBC__)
913 			}
914 #endif
915 			ATF_CHECK(fclose(fp) == 0);
916 		}
917 	}
918 }
919 
920 /*
921  * test19 - test22:
922  * If a stream open for update is flushed or closed and the last write has
923  * advanced the current buffer size, a null byte is written at the end of the
924  * buffer if it fits.
925  */
926 
927 const char *mode_rw2[] = {
928     "r+", "rb+", "r+b",
929     "w", "wb", "w+", "wb+", "w+b",
930     NULL
931 };
932 
933 ATF_TC(test19);
934 ATF_TC_HEAD(test19, tc)
935 {
936 	atf_tc_set_md_var(tc, "descr", "test19");
937 }
938 ATF_TC_BODY(test19, tc)
939 {
940 	struct testcase *t;
941 	size_t len;
942 	int i;
943 	const char **p;
944 	char buf[BUFSIZ];
945 	FILE *fp;
946 
947 	for (t = &testcases[0]; t->s != NULL; ++t) {
948 		len = strnlen(t->s, t->n);
949 		for (p = &mode_rw2[0]; *p != NULL; ++p) {
950 
951 			memcpy(&buf[0], t->s, t->n);
952 			buf[t->n] = 0x1;
953 			fp = fmemopen(&buf[0], t->n + 1, *p);
954 			ATF_CHECK(fp != NULL);
955 			setbuf(fp, NULL);
956 /*
957  * test fmemopen_write + fputc(3)
958  */
959 			for (i = 0; i < t->n; ++i) {
960 				ATF_CHECK(ftello(fp) == (off_t)i);
961 				ATF_CHECK(fputc(t->s[i], fp) == t->s[i]);
962 				ATF_CHECK(buf[i] == t->s[i]);
963 				ATF_CHECK(ftello(fp) == (off_t)i + 1);
964 				ATF_CHECK(buf[i] == t->s[i]);
965 #if !defined(__GLIBC__)
966 				ATF_CHECK(buf[i + 1] == '\0');
967 #endif
968 			}
969 
970 /* don't accept non nul character at end of buffer */
971 			ATF_CHECK(fputc(0x1, fp) == EOF);
972 			ATF_CHECK(ftello(fp) == (off_t)t->n);
973 			ATF_CHECK(feof(fp) == 0);
974 
975 /* accept nul character at end of buffer */
976 			ATF_CHECK(fputc('\0', fp) == '\0');
977 			ATF_CHECK(ftello(fp) == (off_t)t->n + 1);
978 			ATF_CHECK(feof(fp) == 0);
979 
980 /* reach EOF */
981 			ATF_CHECK(fputc('\0', fp) == EOF);
982 			ATF_CHECK(ftello(fp) == (off_t)t->n + 1);
983 
984 			/* compare */
985 			ATF_CHECK(memcmp(&buf[0], t->s, t->n) == 0);
986 			ATF_CHECK(buf[t->n] == '\0');
987 
988 			ATF_CHECK(fclose(fp) == 0);
989 		}
990 	}
991 }
992 
993 ATF_TC(test20);
994 ATF_TC_HEAD(test20, tc)
995 {
996 	atf_tc_set_md_var(tc, "descr", "test20");
997 }
998 ATF_TC_BODY(test20, tc)
999 {
1000 	struct testcase *t;
1001 	size_t len;
1002 	const char **p;
1003 	char buf[BUFSIZ];
1004 	FILE *fp;
1005 
1006 	for (t = &testcases[0]; t->s != NULL; ++t) {
1007 		len = strnlen(t->s, t->n);
1008 		for (p = &mode_rw2[0]; *p != NULL; ++p) {
1009 
1010 			memcpy(&buf[0], t->s, t->n);
1011 			buf[t->n] = 0x1;
1012 			fp = fmemopen(&buf[0], t->n + 1, *p);
1013 			ATF_CHECK(fp != NULL);
1014 			setbuf(fp, NULL);
1015 			ATF_CHECK(fwrite(t->s, 1, t->n, fp) == (size_t)t->n);
1016 /*
1017  * test fmemopen_write + fwrite(3)
1018  */
1019 #if !defined(__GLIBC__)
1020 			ATF_CHECK(buf[t->n] == '\0');
1021 
1022 /* don't accept non nul character at end of buffer */
1023 			ATF_CHECK(fwrite("\x1", 1, 1, fp) == 0);
1024 			ATF_CHECK(ftello(fp) == (off_t)t->n);
1025 			ATF_CHECK(feof(fp) == 0);
1026 #endif
1027 
1028 /* accept nul character at end of buffer */
1029 			ATF_CHECK(fwrite("\x0", 1, 1, fp) == 1);
1030 			ATF_CHECK(ftello(fp) == (off_t)t->n + 1);
1031 			ATF_CHECK(feof(fp) == 0);
1032 
1033 /* reach EOF */
1034 			ATF_CHECK(fputc('\0', fp) == EOF);
1035 			ATF_CHECK(ftello(fp) == (off_t)t->n + 1);
1036 
1037 /* compare */
1038 			ATF_CHECK(memcmp(&buf[0], t->s, t->n) == 0);
1039 			ATF_CHECK(buf[t->n] == '\0');
1040 
1041 			ATF_CHECK(fclose(fp) == 0);
1042 		}
1043 	}
1044 }
1045 
1046 ATF_TC(test21);
1047 ATF_TC_HEAD(test21, tc)
1048 {
1049 	atf_tc_set_md_var(tc, "descr", "test21");
1050 }
1051 ATF_TC_BODY(test21, tc)
1052 {
1053 	struct testcase *t;
1054 	int len, i;
1055 	const char **p;
1056 	char buf[BUFSIZ];
1057 	FILE *fp;
1058 
1059 	for (t = &testcases[0]; t->s != NULL; ++t) {
1060 		len = strnlen(t->s, t->n);
1061 		for (p = &mode_a[0]; *p != NULL; ++p) {
1062 			memcpy(&buf[0], t->s, t->n);
1063 			fp = fmemopen(&buf[0], t->n, *p);
1064 			ATF_CHECK(fp != NULL);
1065 			setbuf(fp, NULL);
1066 /*
1067  * test fmemopen_write + fputc(3)
1068  */
1069 			if (len < t->n) {
1070 				for (i = len; i < t->n - 1; ++i) {
1071 					ATF_CHECK(ftello(fp) == (off_t)i);
1072 					ATF_CHECK(fputc(t->s[i - len], fp)
1073 					    == t->s[i - len]);
1074 					ATF_CHECK(buf[i] == t->s[i - len]);
1075 					ATF_CHECK(ftello(fp) == (off_t)i + 1);
1076 #if !defined(__GLIBC__)
1077 					ATF_CHECK(buf[i + 1] == '\0');
1078 #endif
1079 				}
1080 
1081 /* don't accept non nul character at end of buffer */
1082 				ATF_CHECK(ftello(fp) == (off_t)t->n - 1);
1083 				ATF_CHECK(fputc(0x1, fp) == EOF);
1084 				ATF_CHECK(ftello(fp) == (off_t)t->n - 1);
1085 
1086 /* accept nul character at end of buffer */
1087 				ATF_CHECK(ftello(fp) == (off_t)t->n - 1);
1088 				ATF_CHECK(fputc('\0', fp) == '\0');
1089 				ATF_CHECK(ftello(fp) == (off_t)t->n);
1090 			}
1091 
1092 /* reach EOF */
1093 			ATF_CHECK(ftello(fp) == (off_t)t->n);
1094 			ATF_CHECK(fputc('\0', fp) == EOF);
1095 			ATF_CHECK(ftello(fp) == (off_t)t->n);
1096 
1097 			ATF_CHECK(fclose(fp) == 0);
1098 		}
1099 	}
1100 }
1101 
1102 ATF_TC(test22);
1103 ATF_TC_HEAD(test22, tc)
1104 {
1105 	atf_tc_set_md_var(tc, "descr", "test22");
1106 }
1107 ATF_TC_BODY(test22, tc)
1108 {
1109 	struct testcase *t0, *t1;
1110 	size_t len0, len1, nleft;
1111 	const char **p;
1112 	char buf[BUFSIZ];
1113 	FILE *fp;
1114 
1115 	for (t0 = &testcases[0]; t0->s != NULL; ++t0) {
1116 		len0 = strnlen(t0->s, t0->n);
1117 		for (t1 = &testcases[0]; t1->s != NULL; ++t1) {
1118 			len1 = strnlen(t1->s, t1->n);
1119 			for (p = &mode_a[0]; *p != NULL; ++p) {
1120 
1121 				memcpy(&buf[0], t0->s, t0->n);
1122 				fp = fmemopen(&buf[0], t0->n, *p);
1123 				ATF_CHECK(fp != NULL);
1124 				setbuf(fp, NULL);
1125 /*
1126  * test fmemopen_write + fwrite(3)
1127  */
1128 				nleft = t0->n - len0;
1129 #if !defined(__GLIBC__)
1130 				if (nleft == 0 || len1 == nleft - 1) {
1131 					ATF_CHECK(fwrite(t1->s, 1, t1->n, fp)
1132 					    == nleft);
1133 					ATF_CHECK(ftell(fp) == t1->n);
1134 				} else {
1135 					ATF_CHECK(fwrite(t1->s, 1, t1->n, fp)
1136 					    == nleft - 1);
1137 					ATF_CHECK(ftell(fp) == t1->n - 1);
1138 				}
1139 #endif
1140 				ATF_CHECK(fclose(fp) == 0);
1141 			}
1142 		}
1143 	}
1144 }
1145 
1146 ATF_TP_ADD_TCS(tp)
1147 {
1148 	ATF_TP_ADD_TC(tp, test00);
1149 	ATF_TP_ADD_TC(tp, test01);
1150 	ATF_TP_ADD_TC(tp, test02);
1151 	ATF_TP_ADD_TC(tp, test03);
1152 	ATF_TP_ADD_TC(tp, test04);
1153 	ATF_TP_ADD_TC(tp, test05);
1154 	ATF_TP_ADD_TC(tp, test06);
1155 	ATF_TP_ADD_TC(tp, test07);
1156 	ATF_TP_ADD_TC(tp, test08);
1157 	ATF_TP_ADD_TC(tp, test09);
1158 	ATF_TP_ADD_TC(tp, test10);
1159 	ATF_TP_ADD_TC(tp, test11);
1160 	ATF_TP_ADD_TC(tp, test12);
1161 	ATF_TP_ADD_TC(tp, test13);
1162 	ATF_TP_ADD_TC(tp, test14);
1163 	ATF_TP_ADD_TC(tp, test15);
1164 	ATF_TP_ADD_TC(tp, test16);
1165 	ATF_TP_ADD_TC(tp, test17);
1166 	ATF_TP_ADD_TC(tp, test18);
1167 	ATF_TP_ADD_TC(tp, test19);
1168 	ATF_TP_ADD_TC(tp, test20);
1169 	ATF_TP_ADD_TC(tp, test21);
1170 	ATF_TP_ADD_TC(tp, test22);
1171 
1172 	return atf_no_error();
1173 }
1174