xref: /minix/tests/lib/libc/stdio/t_fmemopen.c (revision 84d9c625)
1 /* $NetBSD: t_fmemopen.c,v 1.4 2013/10/19 17:45:00 christos Exp $ */
2 
3 /*-
4  * Copyright (c)2010 Takehiko NOZAKI,
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  *
28  */
29 
30 #if defined(__NetBSD__)
31 #include <atf-c.h>
32 #else
33 #if defined(__linux__)
34 #define _GNU_SOURCE
35 #include <features.h>
36 #endif
37 #include <assert.h>
38 #include <stdio.h>
39 #define ATF_TC(arg0)		static void arg0##_head(void)
40 #define ATF_TC_HEAD(arg0, arg1)	static void arg0##_head()
41 #define atf_tc_set_md_var(arg0, arg1, ...) do {	\
42 	printf(__VA_ARGS__);			\
43 	puts("");				\
44 } while (/*CONSTCOND*/0)
45 #define ATF_TC_BODY(arg0, arg1)	static void arg0##_body()
46 #define ATF_CHECK(arg0)		assert(arg0)
47 #define ATF_TP_ADD_TCS(arg0)	int main(void)
48 #define ATF_TP_ADD_TC(arg0, arg1) arg1##_head(); arg1##_body()
49 #define atf_no_error()		0
50 #endif
51 
52 #include <errno.h>
53 #include <stdint.h>
54 #include <stdio.h>
55 #include <limits.h>
56 #include <stdlib.h>
57 #include <string.h>
58 
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);
ATF_TC_HEAD(test00,tc)123 ATF_TC_HEAD(test00, tc)
124 {
125 	atf_tc_set_md_var(tc, "descr", "test00");
126 }
ATF_TC_BODY(test00,tc)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);
ATF_TC_HEAD(test01,tc)146 ATF_TC_HEAD(test01, tc)
147 {
148 	atf_tc_set_md_var(tc, "descr", "test01");
149 }
ATF_TC_BODY(test01,tc)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);
ATF_TC_HEAD(test02,tc)180 ATF_TC_HEAD(test02, tc)
181 {
182         atf_tc_set_md_var(tc, "descr", "test02");
183 }
ATF_TC_BODY(test02,tc)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);
ATF_TC_HEAD(test03,tc)216 ATF_TC_HEAD(test03, tc)
217 {
218         atf_tc_set_md_var(tc, "descr", "test03");
219 }
ATF_TC_BODY(test03,tc)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);
ATF_TC_HEAD(test04,tc)250 ATF_TC_HEAD(test04, tc)
251 {
252 	atf_tc_set_md_var(tc, "descr", "test04");
253 }
ATF_TC_BODY(test04,tc)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);
ATF_TC_HEAD(test05,tc)293 ATF_TC_HEAD(test05, tc)
294 {
295 	atf_tc_set_md_var(tc, "descr", "test05");
296 }
ATF_TC_BODY(test05,tc)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);
ATF_TC_HEAD(test06,tc)321 ATF_TC_HEAD(test06, tc)
322 {
323 	atf_tc_set_md_var(tc, "descr", "test06");
324 }
ATF_TC_BODY(test06,tc)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);
ATF_TC_HEAD(test07,tc)342 ATF_TC_HEAD(test07, tc)
343 {
344 	atf_tc_set_md_var(tc, "descr", "test07");
345 }
ATF_TC_BODY(test07,tc)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);
ATF_TC_HEAD(test08,tc)373 ATF_TC_HEAD(test08, tc)
374 {
375 	atf_tc_set_md_var(tc, "descr", "test08");
376 }
ATF_TC_BODY(test08,tc)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);
ATF_TC_HEAD(test09,tc)408 ATF_TC_HEAD(test09, tc)
409 {
410 	atf_tc_set_md_var(tc, "descr", "test09");
411 }
ATF_TC_BODY(test09,tc)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);
ATF_TC_HEAD(test10,tc)459 ATF_TC_HEAD(test10, tc)
460 {
461 	atf_tc_set_md_var(tc, "descr", "test10");
462 }
ATF_TC_BODY(test10,tc)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);
ATF_TC_HEAD(test11,tc)507 ATF_TC_HEAD(test11, tc)
508 {
509 	atf_tc_set_md_var(tc, "descr", "test11");
510 }
ATF_TC_BODY(test11,tc)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);
ATF_TC_HEAD(test12,tc)567 ATF_TC_HEAD(test12, tc)
568 {
569 	atf_tc_set_md_var(tc, "descr", "test12");
570 }
ATF_TC_BODY(test12,tc)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);
ATF_TC_HEAD(test13,tc)625 ATF_TC_HEAD(test13, tc)
626 {
627 	atf_tc_set_md_var(tc, "descr", "test13");
628 }
ATF_TC_BODY(test13,tc)629 ATF_TC_BODY(test13, tc)
630 {
631 	struct testcase *t;
632 	off_t i;
633 	const char **p;
634 	char buf[BUFSIZ];
635 	FILE *fp;
636 
637 	/* test fmemopen_seek(SEEK_END) */
638 	for (t = &testcases[0]; t->s != NULL; ++t) {
639 		for (p = &mode_w[0]; *p != NULL; ++p) {
640 
641 			memcpy(buf, t->s, t->n);
642 			fp = fmemopen(&buf[0], t->n, *p);
643 			ATF_CHECK(fp != NULL);
644 /*
645  * test fmemopen_seek(SEEK_END)
646  */
647 #if !defined(__GLIBC__)
648 			ATF_CHECK(ftello(fp) == (off_t)0);
649 			ATF_CHECK(buf[0] == '\0');
650 
651 			/* zero */
652 			ATF_CHECK(fseeko(fp, (off_t)0, SEEK_END) == 0);
653 			ATF_CHECK(ftello(fp) == (off_t)0);
654 
655 			/* positive + OOB */
656 			ATF_CHECK(fseeko(fp, (off_t)t->n + 1, SEEK_END) == -1);
657 			ATF_CHECK(ftello(fp) == (off_t)0);
658 
659 			/* negative + OOB */
660 			ATF_CHECK(fseeko(fp, -1, SEEK_END) == -1);
661 			ATF_CHECK(ftello(fp) == (off_t)0);
662 
663 			/* positive */
664 			for (i = 1; i <= t->n; ++i) {
665 				ATF_CHECK(fseeko(fp, i, SEEK_END) == 0);
666 				ATF_CHECK(ftello(fp) == i);
667 			}
668 #endif
669 			ATF_CHECK(fclose(fp) == 0);
670 		}
671 	}
672 }
673 
674 ATF_TC(test14);
ATF_TC_HEAD(test14,tc)675 ATF_TC_HEAD(test14, tc)
676 {
677 	atf_tc_set_md_var(tc, "descr", "test14");
678 }
ATF_TC_BODY(test14,tc)679 ATF_TC_BODY(test14, tc)
680 {
681 	struct testcase *t;
682 	off_t len, rest, i;
683 	const char **p;
684 	char buf[BUFSIZ];
685 	FILE *fp;
686 
687 	/* test fmemopen_seek(SEEK_END) */
688 	for (t = &testcases[0]; t->s != NULL; ++t) {
689 		len = (off_t)strnlen(t->s, t->n);
690 		rest = (off_t)t->n - len;
691 		for (p = &mode_a[0]; *p != NULL; ++p) {
692 
693 			memcpy(buf, t->s, t->n);
694 			fp = fmemopen(&buf[0], t->n, *p);
695 			ATF_CHECK(fp != NULL);
696 /*
697  * test fmemopen_seek(SEEK_END)
698  */
699 #if !defined(__GLIBC__)
700 			ATF_CHECK(ftello(fp) == len);
701 
702 			/* zero */
703 			ATF_CHECK(fseeko(fp, 0, SEEK_END) == 0);
704 			ATF_CHECK(ftello(fp) == len);
705 
706 			/* positive + OOB */
707 			ATF_CHECK(fseeko(fp, rest + 1, SEEK_END) == -1);
708 			ATF_CHECK(ftello(fp) == len);
709 
710 			/* negative + OOB */
711 			ATF_CHECK(fseeko(fp, -(len + 1), SEEK_END) == -1);
712 			ATF_CHECK(ftello(fp) == len);
713 
714 			/* positive */
715 			for (i = 1; i <= rest; ++i) {
716 				ATF_CHECK(fseeko(fp, i, SEEK_END) == 0);
717 				ATF_CHECK(ftello(fp) == len + i);
718 			}
719 
720 			/* negative */
721 			for (i = 1; i < len; ++i) {
722 				ATF_CHECK(fseeko(fp, -i, SEEK_END) == 0);
723 				ATF_CHECK(ftello(fp) == len - i);
724 			}
725 #endif
726 			ATF_CHECK(fclose(fp) == 0);
727 		}
728 	}
729 }
730 
731 const char *mode_rw1[] = {
732     "r", "rb", "r+", "rb+", "r+b",
733     "w+", "wb+",
734     NULL
735 };
736 
737 /* test15 - 18:
738  * When a stream open for writing is flushed or closed, a null byte is written
739  * at the current position or at the end of the buffer, depending on the size
740  * of the contents.
741  */
742 
743 ATF_TC(test15);
ATF_TC_HEAD(test15,tc)744 ATF_TC_HEAD(test15, tc)
745 {
746 	atf_tc_set_md_var(tc, "descr", "test15");
747 }
ATF_TC_BODY(test15,tc)748 ATF_TC_BODY(test15, tc)
749 {
750 	struct testcase *t;
751 	const char **p;
752 	char buf0[BUFSIZ];
753 	FILE *fp;
754 	int i;
755 
756 	for (t = &testcases[0]; t->s != NULL; ++t) {
757 		for (p = &mode_rw1[0]; *p != NULL; ++p) {
758 
759 			memcpy(&buf0[0], t->s, t->n);
760 			fp = fmemopen(&buf0[0], t->n, *p);
761 			ATF_CHECK(fp != NULL);
762 /*
763  * test fmemopen_read + fgetc(3)
764  */
765 			for (i = 0; i < t->n; ++i) {
766 				ATF_CHECK(ftello(fp) == (off_t)i);
767 				ATF_CHECK(fgetc(fp) == buf0[i]);
768 				ATF_CHECK(feof(fp) == 0);
769 				ATF_CHECK(ftello(fp) == (off_t)i + 1);
770 			}
771 			ATF_CHECK(fgetc(fp) == EOF);
772 			ATF_CHECK(feof(fp) != 0);
773 			ATF_CHECK(ftello(fp) == (off_t)t->n);
774 			ATF_CHECK(fclose(fp) == 0);
775 		}
776 	}
777 }
778 
779 ATF_TC(test16);
ATF_TC_HEAD(test16,tc)780 ATF_TC_HEAD(test16, tc)
781 {
782 	atf_tc_set_md_var(tc, "descr", "test16");
783 }
ATF_TC_BODY(test16,tc)784 ATF_TC_BODY(test16, tc)
785 {
786 	struct testcase *t;
787 	const char **p;
788 	char buf0[BUFSIZ], buf1[BUFSIZ];
789 	FILE *fp;
790 
791 	for (t = &testcases[0]; t->s != NULL; ++t) {
792 		for (p = &mode_rw1[0]; *p != NULL; ++p) {
793 
794 			memcpy(&buf0[0], t->s, t->n);
795 			buf1[t->n] = 0x1;
796 			fp = fmemopen(&buf0[0], t->n, *p);
797 			ATF_CHECK(fp != NULL);
798 /*
799  * test fmemopen_read + fread(4)
800  */
801 			ATF_CHECK(ftello(fp) == (off_t)0);
802 			ATF_CHECK(fread(&buf1[0], 1, sizeof(buf1), fp) == (size_t)t->n);
803 			ATF_CHECK(feof(fp) != 0);
804 			ATF_CHECK(memcmp(&buf0[0], &buf1[0], t->n) == 0);
805 			ATF_CHECK((unsigned char)buf1[t->n] == 0x1);
806 
807 			ATF_CHECK(fclose(fp) == 0);
808 		}
809 	}
810 }
811 
812 const char *mode_a1[] = { "a+", "ab+", NULL };
813 
814 ATF_TC(test17);
ATF_TC_HEAD(test17,tc)815 ATF_TC_HEAD(test17, tc)
816 {
817 	atf_tc_set_md_var(tc, "descr", "test17");
818 }
ATF_TC_BODY(test17,tc)819 ATF_TC_BODY(test17, tc)
820 {
821 	struct testcase *t;
822 	size_t len;
823 	int i;
824 	const char **p;
825 	char buf[BUFSIZ];
826 	FILE *fp;
827 
828 	for (t = &testcases[0]; t->s != NULL; ++t) {
829 		len = strnlen(t->s, t->n);
830 		for (p = &mode_a1[0]; *p != NULL; ++p) {
831 
832 			memcpy(&buf[0], t->s, t->n);
833 			fp = fmemopen(&buf[0], t->n, *p);
834 			ATF_CHECK(fp != NULL);
835 /*
836  * test fmemopen_read + fgetc(3)
837  */
838 #if defined(__GLIBC__)
839 			if (i < t->n) {
840 #endif
841 			for (i = len; i < t->n; ++i) {
842 				ATF_CHECK(ftello(fp) == (off_t)i);
843 				ATF_CHECK(fgetc(fp) == buf[i]);
844 				ATF_CHECK(feof(fp) == 0);
845 				ATF_CHECK(ftello(fp) == (off_t)i + 1);
846 			}
847 			ATF_CHECK(fgetc(fp) == EOF);
848 			ATF_CHECK(feof(fp) != 0);
849 			ATF_CHECK(ftello(fp) == (off_t)t->n);
850 			rewind(fp);
851 			for (i = 0; i < t->n; ++i) {
852 				ATF_CHECK(ftello(fp) == (off_t)i);
853 				ATF_CHECK(fgetc(fp) == buf[i]);
854 				ATF_CHECK(feof(fp) == 0);
855 				ATF_CHECK(ftello(fp) == (off_t)i + 1);
856 			}
857 			ATF_CHECK(fgetc(fp) == EOF);
858 			ATF_CHECK(feof(fp) != 0);
859 			ATF_CHECK(ftello(fp) == (off_t)t->n);
860 #if defined(__GLIBC__)
861 			}
862 #endif
863 			ATF_CHECK(fclose(fp) == 0);
864 		}
865 	}
866 }
867 
868 ATF_TC(test18);
ATF_TC_HEAD(test18,tc)869 ATF_TC_HEAD(test18, tc)
870 {
871 	atf_tc_set_md_var(tc, "descr", "test18");
872 }
ATF_TC_BODY(test18,tc)873 ATF_TC_BODY(test18, tc)
874 {
875 	struct testcase *t;
876 	size_t len;
877 	const char **p;
878 	char buf0[BUFSIZ], buf1[BUFSIZ];
879 	FILE *fp;
880 
881 	for (t = &testcases[0]; t->s != NULL; ++t) {
882 		len = strnlen(t->s, t->n);
883 		for (p = &mode_a1[0]; *p != NULL; ++p) {
884 
885 			memcpy(&buf0[0], t->s, t->n);
886 			buf1[t->n - len] = 0x1;
887 			fp = fmemopen(&buf0[0], t->n, *p);
888 			ATF_CHECK(fp != NULL);
889 /*
890  * test fmemopen_read + fread(3)
891  */
892 #if defined(__GLIBC__)
893 			if (i < t->n) {
894 #endif
895 			ATF_CHECK(ftello(fp) == (off_t)len);
896 			ATF_CHECK(fread(&buf1[0], 1, sizeof(buf1), fp)
897 			    == t->n - len);
898 			ATF_CHECK(feof(fp) != 0);
899 			ATF_CHECK(!memcmp(&buf0[len], &buf1[0], t->n - len));
900 			ATF_CHECK((unsigned char)buf1[t->n - len] == 0x1);
901 			rewind(fp);
902 			buf1[t->n] = 0x1;
903 			ATF_CHECK(ftello(fp) == (off_t)0);
904 			ATF_CHECK(fread(&buf1[0], 1, sizeof(buf1), fp)
905 			    == (size_t)t->n);
906 			ATF_CHECK(feof(fp) != 0);
907 			ATF_CHECK(!memcmp(&buf0[0], &buf1[0], t->n));
908 			ATF_CHECK((unsigned char)buf1[t->n] == 0x1);
909 #if defined(__GLIBC__)
910 			}
911 #endif
912 			ATF_CHECK(fclose(fp) == 0);
913 		}
914 	}
915 }
916 
917 /*
918  * test19 - test22:
919  * If a stream open for update is flushed or closed and the last write has
920  * advanced the current buffer size, a null byte is written at the end of the
921  * buffer if it fits.
922  */
923 
924 const char *mode_rw2[] = {
925     "r+", "rb+", "r+b",
926     "w", "wb", "w+", "wb+", "w+b",
927     NULL
928 };
929 
930 ATF_TC(test19);
ATF_TC_HEAD(test19,tc)931 ATF_TC_HEAD(test19, tc)
932 {
933 	atf_tc_set_md_var(tc, "descr", "test19");
934 }
ATF_TC_BODY(test19,tc)935 ATF_TC_BODY(test19, tc)
936 {
937 	struct testcase *t;
938 	int i;
939 	const char **p;
940 	char buf[BUFSIZ];
941 	FILE *fp;
942 
943 	for (t = &testcases[0]; t->s != NULL; ++t) {
944 		for (p = &mode_rw2[0]; *p != NULL; ++p) {
945 
946 			memcpy(&buf[0], t->s, t->n);
947 			buf[t->n] = 0x1;
948 			fp = fmemopen(&buf[0], t->n + 1, *p);
949 			ATF_CHECK(fp != NULL);
950 			setbuf(fp, NULL);
951 /*
952  * test fmemopen_write + fputc(3)
953  */
954 			for (i = 0; i < t->n; ++i) {
955 				ATF_CHECK(ftello(fp) == (off_t)i);
956 				ATF_CHECK(fputc(t->s[i], fp) == t->s[i]);
957 				ATF_CHECK(buf[i] == t->s[i]);
958 				ATF_CHECK(ftello(fp) == (off_t)i + 1);
959 				ATF_CHECK(buf[i] == t->s[i]);
960 #if !defined(__GLIBC__)
961 				ATF_CHECK(buf[i + 1] == '\0');
962 #endif
963 			}
964 
965 /* don't accept non nul character at end of buffer */
966 			ATF_CHECK(fputc(0x1, fp) == EOF);
967 			ATF_CHECK(ftello(fp) == (off_t)t->n);
968 			ATF_CHECK(feof(fp) == 0);
969 
970 /* accept nul character at end of buffer */
971 			ATF_CHECK(fputc('\0', fp) == '\0');
972 			ATF_CHECK(ftello(fp) == (off_t)t->n + 1);
973 			ATF_CHECK(feof(fp) == 0);
974 
975 /* reach EOF */
976 			ATF_CHECK(fputc('\0', fp) == EOF);
977 			ATF_CHECK(ftello(fp) == (off_t)t->n + 1);
978 
979 			/* compare */
980 			ATF_CHECK(memcmp(&buf[0], t->s, t->n) == 0);
981 			ATF_CHECK(buf[t->n] == '\0');
982 
983 			ATF_CHECK(fclose(fp) == 0);
984 		}
985 	}
986 }
987 
988 ATF_TC(test20);
ATF_TC_HEAD(test20,tc)989 ATF_TC_HEAD(test20, tc)
990 {
991 	atf_tc_set_md_var(tc, "descr", "test20");
992 }
ATF_TC_BODY(test20,tc)993 ATF_TC_BODY(test20, tc)
994 {
995 	struct testcase *t;
996 	const char **p;
997 	char buf[BUFSIZ];
998 	FILE *fp;
999 
1000 	for (t = &testcases[0]; t->s != NULL; ++t) {
1001 		for (p = &mode_rw2[0]; *p != NULL; ++p) {
1002 
1003 			memcpy(&buf[0], t->s, t->n);
1004 			buf[t->n] = 0x1;
1005 			fp = fmemopen(&buf[0], t->n + 1, *p);
1006 			ATF_CHECK(fp != NULL);
1007 			setbuf(fp, NULL);
1008 			ATF_CHECK(fwrite(t->s, 1, t->n, fp) == (size_t)t->n);
1009 /*
1010  * test fmemopen_write + fwrite(3)
1011  */
1012 #if !defined(__GLIBC__)
1013 			ATF_CHECK(buf[t->n] == '\0');
1014 
1015 /* don't accept non nul character at end of buffer */
1016 			ATF_CHECK(fwrite("\x1", 1, 1, fp) == 0);
1017 			ATF_CHECK(ftello(fp) == (off_t)t->n);
1018 			ATF_CHECK(feof(fp) == 0);
1019 #endif
1020 
1021 /* accept nul character at end of buffer */
1022 			ATF_CHECK(fwrite("\x0", 1, 1, fp) == 1);
1023 			ATF_CHECK(ftello(fp) == (off_t)t->n + 1);
1024 			ATF_CHECK(feof(fp) == 0);
1025 
1026 /* reach EOF */
1027 			ATF_CHECK(fputc('\0', fp) == EOF);
1028 			ATF_CHECK(ftello(fp) == (off_t)t->n + 1);
1029 
1030 /* compare */
1031 			ATF_CHECK(memcmp(&buf[0], t->s, t->n) == 0);
1032 			ATF_CHECK(buf[t->n] == '\0');
1033 
1034 			ATF_CHECK(fclose(fp) == 0);
1035 		}
1036 	}
1037 }
1038 
1039 ATF_TC(test21);
ATF_TC_HEAD(test21,tc)1040 ATF_TC_HEAD(test21, tc)
1041 {
1042 	atf_tc_set_md_var(tc, "descr", "test21");
1043 }
ATF_TC_BODY(test21,tc)1044 ATF_TC_BODY(test21, tc)
1045 {
1046 	struct testcase *t;
1047 	int len, i;
1048 	const char **p;
1049 	char buf[BUFSIZ];
1050 	FILE *fp;
1051 
1052 	for (t = &testcases[0]; t->s != NULL; ++t) {
1053 		len = strnlen(t->s, t->n);
1054 		for (p = &mode_a[0]; *p != NULL; ++p) {
1055 			memcpy(&buf[0], t->s, t->n);
1056 			fp = fmemopen(&buf[0], t->n, *p);
1057 			ATF_CHECK(fp != NULL);
1058 			setbuf(fp, NULL);
1059 /*
1060  * test fmemopen_write + fputc(3)
1061  */
1062 			if (len < t->n) {
1063 				for (i = len; i < t->n - 1; ++i) {
1064 					ATF_CHECK(ftello(fp) == (off_t)i);
1065 					ATF_CHECK(fputc(t->s[i - len], fp)
1066 					    == t->s[i - len]);
1067 					ATF_CHECK(buf[i] == t->s[i - len]);
1068 					ATF_CHECK(ftello(fp) == (off_t)i + 1);
1069 #if !defined(__GLIBC__)
1070 					ATF_CHECK(buf[i + 1] == '\0');
1071 #endif
1072 				}
1073 
1074 /* don't accept non nul character at end of buffer */
1075 				ATF_CHECK(ftello(fp) == (off_t)t->n - 1);
1076 				ATF_CHECK(fputc(0x1, fp) == EOF);
1077 				ATF_CHECK(ftello(fp) == (off_t)t->n - 1);
1078 
1079 /* accept nul character at end of buffer */
1080 				ATF_CHECK(ftello(fp) == (off_t)t->n - 1);
1081 				ATF_CHECK(fputc('\0', fp) == '\0');
1082 				ATF_CHECK(ftello(fp) == (off_t)t->n);
1083 			}
1084 
1085 /* reach EOF */
1086 			ATF_CHECK(ftello(fp) == (off_t)t->n);
1087 			ATF_CHECK(fputc('\0', fp) == EOF);
1088 			ATF_CHECK(ftello(fp) == (off_t)t->n);
1089 
1090 			ATF_CHECK(fclose(fp) == 0);
1091 		}
1092 	}
1093 }
1094 
1095 ATF_TC(test22);
ATF_TC_HEAD(test22,tc)1096 ATF_TC_HEAD(test22, tc)
1097 {
1098 	atf_tc_set_md_var(tc, "descr", "test22");
1099 }
ATF_TC_BODY(test22,tc)1100 ATF_TC_BODY(test22, tc)
1101 {
1102 	struct testcase *t0, *t1;
1103 	size_t len0, len1, nleft;
1104 	const char **p;
1105 	char buf[BUFSIZ];
1106 	FILE *fp;
1107 
1108 	for (t0 = &testcases[0]; t0->s != NULL; ++t0) {
1109 		len0 = strnlen(t0->s, t0->n);
1110 		for (t1 = &testcases[0]; t1->s != NULL; ++t1) {
1111 			len1 = strnlen(t1->s, t1->n);
1112 			for (p = &mode_a[0]; *p != NULL; ++p) {
1113 
1114 				memcpy(&buf[0], t0->s, t0->n);
1115 				fp = fmemopen(&buf[0], t0->n, *p);
1116 				ATF_CHECK(fp != NULL);
1117 				setbuf(fp, NULL);
1118 /*
1119  * test fmemopen_write + fwrite(3)
1120  */
1121 				nleft = t0->n - len0;
1122 #if !defined(__GLIBC__)
1123 				if (nleft == 0 || len1 == nleft - 1) {
1124 					ATF_CHECK(fwrite(t1->s, 1, t1->n, fp)
1125 					    == nleft);
1126 					ATF_CHECK(ftell(fp) == t1->n);
1127 				} else {
1128 					ATF_CHECK(fwrite(t1->s, 1, t1->n, fp)
1129 					    == nleft - 1);
1130 					ATF_CHECK(ftell(fp) == t1->n - 1);
1131 				}
1132 #endif
1133 				ATF_CHECK(fclose(fp) == 0);
1134 			}
1135 		}
1136 	}
1137 }
1138 
ATF_TP_ADD_TCS(tp)1139 ATF_TP_ADD_TCS(tp)
1140 {
1141 	ATF_TP_ADD_TC(tp, test00);
1142 	ATF_TP_ADD_TC(tp, test01);
1143 	ATF_TP_ADD_TC(tp, test02);
1144 	ATF_TP_ADD_TC(tp, test03);
1145 	ATF_TP_ADD_TC(tp, test04);
1146 	ATF_TP_ADD_TC(tp, test05);
1147 	ATF_TP_ADD_TC(tp, test06);
1148 	ATF_TP_ADD_TC(tp, test07);
1149 	ATF_TP_ADD_TC(tp, test08);
1150 	ATF_TP_ADD_TC(tp, test09);
1151 	ATF_TP_ADD_TC(tp, test10);
1152 	ATF_TP_ADD_TC(tp, test11);
1153 	ATF_TP_ADD_TC(tp, test12);
1154 	ATF_TP_ADD_TC(tp, test13);
1155 	ATF_TP_ADD_TC(tp, test14);
1156 	ATF_TP_ADD_TC(tp, test15);
1157 	ATF_TP_ADD_TC(tp, test16);
1158 	ATF_TP_ADD_TC(tp, test17);
1159 	ATF_TP_ADD_TC(tp, test18);
1160 	ATF_TP_ADD_TC(tp, test19);
1161 	ATF_TP_ADD_TC(tp, test20);
1162 	ATF_TP_ADD_TC(tp, test21);
1163 	ATF_TP_ADD_TC(tp, test22);
1164 
1165 	return atf_no_error();
1166 }
1167