1 /* $NetBSD: t_fmemopen.c,v 1.7 2021/09/11 18:18:28 rillig 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(__PICOLIBC__)
34 #define _GNU_SOURCE  /* strnlen */
35 #elif defined(__linux__)
36 #define _GNU_SOURCE
37 #include <features.h>
38 #endif
39 #include <assert.h>
40 #include <stdio.h>
41 #define ATF_TC(arg0)		static void arg0##_head(void)
42 #define ATF_TC_HEAD(arg0, arg1)	static void arg0##_head(void)
43 #define atf_tc_set_md_var(arg0, arg1, ...) do {	\
44 	printf(__VA_ARGS__);			\
45 	puts("");				\
46 } while (/*CONSTCOND*/0)
47 #define ATF_TC_BODY(arg0, arg1)	static void arg0##_body(void)
48 #define ATF_CHECK(arg0)		assert(arg0)
49 #define ATF_CHECK_MSG(arg0, fmt, ...) do { \
50 	if (!(arg0)) { \
51 		fprintf(stderr, fmt, __VA_ARGS__); \
52 		exit(1); \
53 	} \
54 } while (/*CONSTCOND*/0)
55 #define ATF_TP_ADD_TCS(arg0)	int main(void)
56 #define ATF_TP_ADD_TC(arg0, arg1) arg1##_head(); arg1##_body()
57 #define atf_no_error()		0
58 #endif
59 
60 #include <errno.h>
61 #include <stdbool.h>
62 #include <stdint.h>
63 #include <stdio.h>
64 #include <limits.h>
65 #include <stdlib.h>
66 #include <string.h>
67 
68 const char *mode_rwa[] = {
69     "r", "rb", "r+", "rb+", "r+b",
70     "w", "wb", "w+", "wb+", "w+b",
71     "a", "ab", "a+", "ab+", "a+b",
72     NULL
73 };
74 
75 const char *mode_r[] = { "r", "rb", "r+", "rb+", "r+b", NULL };
76 const char *mode_w[] = { "w", "wb", "w+", "wb+", "w+b", NULL };
77 const char *mode_a[] = { "a", "ab", "a+", "ab+", "a+b", NULL };
78 
79 struct testcase {
80 	const char *s;
81 	off_t n;
82 } testcases[] = {
83 #define TESTSTR(s)	{ s, sizeof(s)-1 }
84 	TESTSTR("\0he quick brown fox jumps over the lazy dog"),
85 	TESTSTR("T\0e quick brown fox jumps over the lazy dog"),
86 	TESTSTR("Th\0 quick brown fox jumps over the lazy dog"),
87 	TESTSTR("The\0quick brown fox jumps over the lazy dog"),
88 	TESTSTR("The \0uick brown fox jumps over the lazy dog"),
89 	TESTSTR("The q\0ick brown fox jumps over the lazy dog"),
90 	TESTSTR("The qu\0ck brown fox jumps over the lazy dog"),
91 	TESTSTR("The qui\0k brown fox jumps over the lazy dog"),
92 	TESTSTR("The quic\0 brown fox jumps over the lazy dog"),
93 	TESTSTR("The quick\0brown fox jumps over the lazy dog"),
94 	TESTSTR("The quick \0rown fox jumps over the lazy dog"),
95 	TESTSTR("The quick b\0own fox jumps over the lazy dog"),
96 	TESTSTR("The quick br\0wn fox jumps over the lazy dog"),
97 	TESTSTR("The quick bro\0n fox jumps over the lazy dog"),
98 	TESTSTR("The quick brow\0 fox jumps over the lazy dog"),
99 	TESTSTR("The quick brown\0fox jumps over the lazy dog"),
100 	TESTSTR("The quick brown \0ox jumps over the lazy dog"),
101 	TESTSTR("The quick brown f\0x jumps over the lazy dog"),
102 	TESTSTR("The quick brown fo\0 jumps over the lazy dog"),
103 	TESTSTR("The quick brown fox\0jumps over the lazy dog"),
104 	TESTSTR("The quick brown fox \0umps over the lazy dog"),
105 	TESTSTR("The quick brown fox j\0mps over the lazy dog"),
106 	TESTSTR("The quick brown fox ju\0ps over the lazy dog"),
107 	TESTSTR("The quick brown fox jum\0s over the lazy dog"),
108 	TESTSTR("The quick brown fox jump\0 over the lazy dog"),
109 	TESTSTR("The quick brown fox jumps\0over the lazy dog"),
110 	TESTSTR("The quick brown fox jumps \0ver the lazy dog"),
111 	TESTSTR("The quick brown fox jumps o\0er the lazy dog"),
112 	TESTSTR("The quick brown fox jumps ov\0r the lazy dog"),
113 	TESTSTR("The quick brown fox jumps ove\0 the lazy dog"),
114 	TESTSTR("The quick brown fox jumps over\0the lazy dog"),
115 	TESTSTR("The quick brown fox jumps over \0he lazy dog"),
116 	TESTSTR("The quick brown fox jumps over t\0e lazy dog"),
117 	TESTSTR("The quick brown fox jumps over th\0 lazy dog"),
118 	TESTSTR("The quick brown fox jumps over the\0lazy dog"),
119 	TESTSTR("The quick brown fox jumps over the \0azy dog"),
120 	TESTSTR("The quick brown fox jumps over the l\0zy dog"),
121 	TESTSTR("The quick brown fox jumps over the la\0y dog"),
122 	TESTSTR("The quick brown fox jumps over the laz\0 dog"),
123 	TESTSTR("The quick brown fox jumps over the lazy\0dog"),
124 	TESTSTR("The quick brown fox jumps over the lazy \0og"),
125 	TESTSTR("The quick brown fox jumps over the lazy d\0g"),
126 	TESTSTR("The quick brown fox jumps over the lazy do\0"),
127 	TESTSTR("The quick brown fox jumps over the lazy dog"),
128 	{ NULL, 0 },
129 };
130 
131 ATF_TC(test00);
ATF_TC_HEAD(test00,tc)132 ATF_TC_HEAD(test00, tc)
133 {
134 	atf_tc_set_md_var(tc, "descr", "test00");
135 }
ATF_TC_BODY(test00,tc)136 ATF_TC_BODY(test00, tc)
137 {
138 	const char **p;
139 	char buf[BUFSIZ];
140 	FILE *fp;
141 
142 	for (p = &mode_rwa[0]; *p != NULL; ++p) {
143 		fp = fmemopen(&buf[0], sizeof(buf), *p);
144 /*
145  * Upon successful completion, fmemopen() shall return a pointer to the
146  * object controlling the stream.
147  */
148 		ATF_CHECK(fp != NULL);
149 
150 		ATF_CHECK(fclose(fp) == 0);
151 	}
152 }
153 
154 ATF_TC(test01);
ATF_TC_HEAD(test01,tc)155 ATF_TC_HEAD(test01, tc)
156 {
157 	atf_tc_set_md_var(tc, "descr", "test01");
158 }
ATF_TC_BODY(test01,tc)159 ATF_TC_BODY(test01, tc)
160 {
161 	const char **p;
162 	const char *mode[] = {
163 	    "r+", "rb+", "r+b",
164 	    "w+", "wb+", "w+b",
165 	    "a+", "ab+", "a+b",
166 	    NULL
167 	};
168 	FILE *fp;
169 
170 	for (p = &mode[0]; *p != NULL; ++p) {
171 /*
172  * If a null pointer is specified as the buf argument, fmemopen() shall
173  * allocate size bytes of memory as if by a call to malloc().
174  */
175 		fp = fmemopen(NULL, BUFSIZ, *p);
176 		ATF_CHECK(fp != NULL);
177 
178 /*
179  * If buf is a null pointer, the initial position shall always be set
180  * to the beginning of the buffer.
181  */
182 		ATF_CHECK(ftello(fp) == (off_t)0);
183 
184 		ATF_CHECK(fclose(fp) == 0);
185 	}
186 }
187 
188 ATF_TC(test02);
ATF_TC_HEAD(test02,tc)189 ATF_TC_HEAD(test02, tc)
190 {
191 	atf_tc_set_md_var(tc, "descr", "test02");
192 }
ATF_TC_BODY(test02,tc)193 ATF_TC_BODY(test02, tc)
194 {
195 	const char **p;
196 	char buf[BUFSIZ];
197 	FILE *fp;
198 
199 	for (p = &mode_r[0]; *p != NULL; ++p) {
200 
201 		memset(&buf[0], 0x1, sizeof(buf));
202 		fp = fmemopen(&buf[0], sizeof(buf), *p);
203 		ATF_CHECK(fp != NULL);
204 
205 /*
206  * This position is initially set to either the beginning of the buffer
207  * (for r and w modes)
208  */
209 		ATF_CHECK((unsigned char)buf[0] == 0x1);
210 		ATF_CHECK(ftello(fp) == (off_t)0);
211 
212 /*
213  * The stream also maintains the size of the current buffer contents.
214  * For modes r and r+ the size is set to the value given by the size argument.
215  */
216 #if !defined(__GLIBC__)
217 		ATF_CHECK(fseeko(fp, (off_t)0, SEEK_END) == 0);
218 		ATF_CHECK(ftello(fp) == (off_t)sizeof(buf));
219 #endif
220 		ATF_CHECK(fclose(fp) == 0);
221 	}
222 }
223 
224 static bool
fmemopen_truncates_buffer(const char * mode)225 fmemopen_truncates_buffer(const char *mode)
226 {
227     if (mode[0] != 'w')
228 		return false;
229 #if defined(__NetBSD__)
230 	/* The NetBSD implementation truncates for all 'w' open flags */
231 	return true;
232 #elif defined(__GLIBC__)
233 	/* glibc only truncates the file if "+" is the second char. */
234 	return (mode[1] == '+');
235 #else
236 	/* POSIX mandates truncation for w+ and wb+ */
237 	return strchr(mode, '+') != 0;
238 #endif
239 }
240 
241 ATF_TC(test03);
ATF_TC_HEAD(test03,tc)242 ATF_TC_HEAD(test03, tc)
243 {
244 	atf_tc_set_md_var(tc, "descr", "test03");
245 }
ATF_TC_BODY(test03,tc)246 ATF_TC_BODY(test03, tc)
247 {
248 	const char **p;
249 	char buf[BUFSIZ];
250 	FILE *fp;
251 
252 	for (p = &mode_w[0]; *p != NULL; ++p) {
253 
254 		memset(&buf[0], 0x1, sizeof(buf));
255 		fp = fmemopen(&buf[0], sizeof(buf), *p);
256 		ATF_CHECK(fp != NULL);
257 
258 /*
259  * This position is initially set to either the beginning of the buffer
260  * (for r and w modes)
261  */
262 		if (fmemopen_truncates_buffer(*p)) {
263 			ATF_CHECK(buf[0] == '\0');
264 		} else {
265 			ATF_CHECK(buf[0] == 1);
266 		}
267 		ATF_CHECK(ftello(fp) == (off_t)0);
268 
269 /*
270  * For modes w and w+ the initial size is zero
271  */
272 		ATF_CHECK(fseeko(fp, (off_t)0, SEEK_END) == 0);
273 		ATF_CHECK(ftello(fp) == (off_t)0);
274 
275 		ATF_CHECK(fclose(fp) == 0);
276 	}
277 }
278 
279 ATF_TC(test04);
ATF_TC_HEAD(test04,tc)280 ATF_TC_HEAD(test04, tc)
281 {
282 	atf_tc_set_md_var(tc, "descr", "test04");
283 }
ATF_TC_BODY(test04,tc)284 ATF_TC_BODY(test04, tc)
285 {
286 	const char **p;
287 	char buf[BUFSIZ];
288 	FILE *fp;
289 
290 /*
291  * or to the first null byte in the buffer (for a modes)
292  */
293 	for (p = &mode_a[0]; *p != NULL; ++p) {
294 
295 		memset(&buf[0], 0x1, sizeof(buf));
296 		fp = fmemopen(&buf[0], sizeof(buf), *p);
297 		ATF_CHECK(fp != NULL);
298 
299 		ATF_CHECK((unsigned char)buf[0] == 0x1);
300 
301 /* If no null byte is found in append mode,
302  * the initial position is set to one byte after the end of the buffer.
303  */
304 #if !defined(__GLIBC__)
305 		ATF_CHECK(ftello(fp) == (off_t)sizeof(buf));
306 #endif
307 
308 /*
309  * and for modes a and a+ the initial size is either the position of the
310  * first null byte in the buffer or the value of the size argument
311  * if no null byte is found.
312  */
313 #if !defined(__GLIBC__)
314 		ATF_CHECK(fseeko(fp, (off_t)0, SEEK_END) == 0);
315 		ATF_CHECK(ftello(fp) == (off_t)sizeof(buf));
316 #endif
317 
318 		ATF_CHECK(fclose(fp) == 0);
319 	}
320 }
321 
322 ATF_TC(test05);
ATF_TC_HEAD(test05,tc)323 ATF_TC_HEAD(test05, tc)
324 {
325 	atf_tc_set_md_var(tc, "descr", "test05");
326 }
ATF_TC_BODY(test05,tc)327 ATF_TC_BODY(test05, tc)
328 {
329 #if !defined(__GLIBC__)
330 	const char **p;
331 	FILE *fp;
332 	char buf[BUFSIZ];
333 
334 	for (p = &mode_rwa[0]; *p != NULL; ++p) {
335 /*
336  * Otherwise, a null pointer shall be returned, and errno shall be set
337  * to indicate the error.
338  */
339 		errno = 0;
340 		fp = fmemopen(NULL, (size_t)0, *p);
341 		ATF_CHECK(fp == NULL);
342 		ATF_CHECK(errno == EINVAL);
343 
344 		errno = 0;
345 		fp = fmemopen((void *)&buf[0], 0, *p);
346 		ATF_CHECK(fp == NULL);
347 		ATF_CHECK(errno == EINVAL);
348 	}
349 #endif
350 }
351 
352 ATF_TC(test06);
ATF_TC_HEAD(test06,tc)353 ATF_TC_HEAD(test06, tc)
354 {
355 	atf_tc_set_md_var(tc, "descr", "test06");
356 }
ATF_TC_BODY(test06,tc)357 ATF_TC_BODY(test06, tc)
358 {
359 	const char **p;
360 	const char *mode[] = { "", " ", "???", NULL };
361 	FILE *fp;
362 
363 	for (p = &mode[0]; *p != NULL; ++p) {
364 /*
365  * The value of the mode argument is not valid.
366  */
367 		fp = fmemopen(NULL, 1, *p);
368 		ATF_CHECK(fp == NULL);
369 		ATF_CHECK(errno == EINVAL);
370 	}
371 }
372 
373 ATF_TC(test07);
ATF_TC_HEAD(test07,tc)374 ATF_TC_HEAD(test07, tc)
375 {
376 	atf_tc_set_md_var(tc, "descr", "test07");
377 }
ATF_TC_BODY(test07,tc)378 ATF_TC_BODY(test07, tc)
379 {
380 #if !defined(__GLIBC__)
381 	const char **p;
382 	const char *mode[] = {
383 	    "r", "rb",
384 	    "w", "wb",
385 	    "a", "ab",
386 	    NULL
387 	};
388 	FILE *fp;
389 
390 	for (p = &mode[0]; *p != NULL; ++p) {
391 /*
392  * Because this feature is only useful when the stream is opened for updating
393  * (because there is no way to get a pointer to the buffer) the fmemopen()
394  * call may fail if the mode argument does not include a '+'.
395  */
396 		errno = 0;
397 		fp = fmemopen(NULL, 1, *p);
398 		ATF_CHECK(fp == NULL);
399 		ATF_CHECK(errno == EINVAL);
400 	}
401 #endif
402 }
403 
404 ATF_TC(test08);
ATF_TC_HEAD(test08,tc)405 ATF_TC_HEAD(test08, tc)
406 {
407 	atf_tc_set_md_var(tc, "descr", "test08");
408 }
ATF_TC_BODY(test08,tc)409 ATF_TC_BODY(test08, tc)
410 {
411 #if !defined(__GLIBC__)
412 	const char **p;
413 	const char *mode[] = {
414 	    "r+", "rb+", "r+b",
415 	    "w+", "wb+", "w+b",
416 	    "a+", "ab+", "a+b",
417 	    NULL
418 	};
419 	FILE *fp;
420 
421 	for (p = &mode[0]; *p != NULL; ++p) {
422 /*
423  * The buf argument is a null pointer and the allocation of a buffer of
424  * length size has failed.
425  */
426 		fp = fmemopen(NULL, SIZE_MAX, *p);
427 		ATF_CHECK(fp == NULL);
428 		ATF_CHECK(errno == ENOMEM);
429 	}
430 #endif
431 }
432 
433 /*
434  * test09 - test14:
435  * An attempt to seek a memory buffer stream to a negative position or to a
436  * position larger than the buffer size given in the size argument shall fail.
437  */
438 
439 ATF_TC(test09);
ATF_TC_HEAD(test09,tc)440 ATF_TC_HEAD(test09, tc)
441 {
442 	atf_tc_set_md_var(tc, "descr", "test09");
443 }
ATF_TC_BODY(test09,tc)444 ATF_TC_BODY(test09, tc)
445 {
446 	struct testcase *t;
447 	const char **p;
448 	char buf[BUFSIZ];
449 	FILE *fp;
450 	off_t i;
451 
452 	for (t = &testcases[0]; t->s != NULL; ++t) {
453 		for (p = &mode_rwa[0]; *p != NULL; ++p) {
454 
455 			memcpy(&buf[0], t->s, t->n);
456 			fp = fmemopen(&buf[0], t->n, *p);
457 			ATF_CHECK(fp != NULL);
458 
459 /*
460  * test fmemopen_seek(SEEK_SET)
461  */
462 			/* zero */
463 			ATF_CHECK(fseeko(fp, (off_t)0, SEEK_SET) == 0);
464 			ATF_CHECK(ftello(fp) == (off_t)0);
465 
466 			/* positive */
467 			for (i = (off_t)1; i <= (off_t)t->n; ++i) {
468 				ATF_CHECK(fseeko(fp, i, SEEK_SET) == 0);
469 				ATF_CHECK(ftello(fp) == i);
470 			}
471 			/* positive + OOB */
472 			ATF_CHECK(ftello(fp) == t->n);
473 #if defined(__GLIBC__)
474 			/* seeking beyond the end of a buffered w/a file on
475 			 * glibc appears to rewind the buffer. */
476 			if (**p != 'r')
477 				setbuf(fp, NULL);
478 #endif
479 			ATF_CHECK(fseeko(fp, t->n + 1, SEEK_SET) == -1);
480 			ATF_CHECK(ftello(fp) == t->n);
481 
482 			/* negative + OOB */
483 			ATF_CHECK(fseeko(fp, (off_t)-1, SEEK_SET) == -1);
484 			ATF_CHECK(ftello(fp) == t->n);
485 
486 			ATF_CHECK(fclose(fp) == 0);
487 		}
488 	}
489 }
490 
491 const char *mode_rw[] = {
492     "r", "rb", "r+", "rb+", "r+b",
493     "w", "wb", "w+", "wb+", "w+b",
494     NULL
495 };
496 
497 ATF_TC(test10);
ATF_TC_HEAD(test10,tc)498 ATF_TC_HEAD(test10, tc)
499 {
500 	atf_tc_set_md_var(tc, "descr", "test10");
501 }
ATF_TC_BODY(test10,tc)502 ATF_TC_BODY(test10, tc)
503 {
504 	struct testcase *t;
505 	off_t i;
506 	const char **p;
507 	char buf[BUFSIZ];
508 	FILE *fp;
509 
510 	for (t = &testcases[0]; t->s != NULL; ++t) {
511 		for (p = &mode_rw[0]; *p != NULL; ++p) {
512 
513 			memcpy(&buf[0], t->s, t->n);
514 			fp = fmemopen(&buf[0], t->n, *p);
515 			ATF_CHECK(fp != NULL);
516 
517 /*
518  * test fmemopen_seek(SEEK_CUR)
519  */
520 			ATF_CHECK(ftello(fp) == (off_t)0);
521 
522 			/* zero */
523 			ATF_CHECK(fseeko(fp, (off_t)0, SEEK_CUR) == 0);
524 			ATF_CHECK(ftello(fp) == (off_t)0);
525 
526 			/* negative & OOB */
527 			ATF_CHECK(fseeko(fp, (off_t)-1, SEEK_CUR) == -1);
528 			ATF_CHECK(ftello(fp) == (off_t)0);
529 
530 			/* positive */
531 			for (i = 0; i < (off_t)t->n; ++i) {
532 				ATF_CHECK(fseeko(fp, (off_t)1, SEEK_CUR) == 0);
533 				ATF_CHECK(ftello(fp) == i + 1);
534 			}
535 
536 			/* positive & OOB */
537 			ATF_CHECK(fseeko(fp, (off_t)1, SEEK_CUR) == -1);
538 			ATF_CHECK(ftello(fp) == (off_t)t->n);
539 
540 			ATF_CHECK(fclose(fp) == 0);
541 		}
542 	}
543 }
544 
545 ATF_TC(test11);
ATF_TC_HEAD(test11,tc)546 ATF_TC_HEAD(test11, tc)
547 {
548 	atf_tc_set_md_var(tc, "descr", "test11");
549 }
ATF_TC_BODY(test11,tc)550 ATF_TC_BODY(test11, tc)
551 {
552 	struct testcase *t;
553 	off_t len, rest, i;
554 	const char **p;
555 	char buf[BUFSIZ];
556 	FILE *fp;
557 
558 	/* test fmemopen_seek(SEEK_CUR) */
559 	for (t = &testcases[0]; t->s != NULL; ++t) {
560 		len = (off_t)strnlen(t->s, t->n);
561 		rest = (off_t)t->n - len;
562 		for (p = &mode_a[0]; *p != NULL; ++p) {
563 
564 			memcpy(&buf[0], t->s, t->n);
565 			fp = fmemopen(&buf[0], t->n, *p);
566 			ATF_CHECK(fp != NULL);
567 /*
568  * test fmemopen_seek(SEEK_CUR)
569  */
570 #if defined(__GLIBC__)
571 			if (i < (off_t)t->n) {
572 #endif
573 			/* zero */
574 			ATF_CHECK(fseeko(fp, (off_t)0, SEEK_CUR) == 0);
575 			ATF_CHECK(ftello(fp) == len);
576 
577 			/* posive */
578 			for (i = (off_t)1; i <= rest; ++i) {
579 				ATF_CHECK(fseeko(fp, (off_t)1, SEEK_CUR) == 0);
580 				ATF_CHECK(ftello(fp) == len + i);
581 			}
582 
583 			/* positive + OOB */
584 			ATF_CHECK(fseeko(fp, (off_t)1, SEEK_CUR) == -1);
585 			ATF_CHECK(ftello(fp) == (off_t)t->n);
586 
587 			/* negative */
588 			for (i = (off_t)1; i <= (off_t)t->n; ++i) {
589 				ATF_CHECK(fseeko(fp, (off_t)-1, SEEK_CUR) == 0);
590 				ATF_CHECK(ftello(fp) == (off_t)t->n - i);
591 			}
592 
593 			/* negative + OOB */
594 			ATF_CHECK(fseeko(fp, (off_t)-1, SEEK_CUR) == -1);
595 			ATF_CHECK(ftello(fp) == (off_t)0);
596 
597 #if defined(__GLIBC__)
598 			}
599 #endif
600 			ATF_CHECK(fclose(fp) == 0);
601 		}
602 	}
603 }
604 
605 ATF_TC(test12);
ATF_TC_HEAD(test12,tc)606 ATF_TC_HEAD(test12, tc)
607 {
608 	atf_tc_set_md_var(tc, "descr", "test12");
609 }
ATF_TC_BODY(test12,tc)610 ATF_TC_BODY(test12, tc)
611 {
612 	struct testcase *t;
613 	off_t len, rest, i;
614 	const char **p;
615 	char buf[BUFSIZ];
616 	FILE *fp;
617 
618 	/* test fmemopen_seek(SEEK_END) */
619 	for (t = &testcases[0]; t->s != NULL; ++t) {
620 #if !defined(__NetBSD__)
621 		/* Modes starting with 'r' treat the buffer size as length not the
622 		 * first NUL byte offset. */
623 		len = t->n;
624 #else
625 		len = (off_t)strnlen(t->s, t->n);
626 #endif
627 		rest = t->n - len;
628 		for (p = &mode_r[0]; *p != NULL; ++p) {
629 
630 			memcpy(buf, t->s, t->n);
631 			fp = fmemopen(&buf[0], t->n, *p);
632 			ATF_CHECK(fp != NULL);
633 
634 /*
635  * test fmemopen_seek(SEEK_END)
636  */
637 			ATF_CHECK(ftello(fp) == (off_t)0);
638 
639 			/* zero */
640 			ATF_CHECK(fseeko(fp, (off_t)0, SEEK_END) == 0);
641 			ATF_CHECK(ftello(fp) == len);
642 
643 			/* positive + OOB */
644 			ATF_CHECK(fseeko(fp, rest + 1, SEEK_END) == -1);
645 			ATF_CHECK(ftello(fp) == len);
646 
647 			/* negative + OOB */
648 			ATF_CHECK(fseeko(fp, -(len + 1), SEEK_END) == -1);
649 			ATF_CHECK(ftello(fp) == len);
650 
651 			/* positive */
652 			for (i = 1; i <= rest; ++i) {
653 				ATF_CHECK(fseeko(fp, i, SEEK_END) == 0);
654 				ATF_CHECK(ftello(fp) == len + i);
655 			}
656 
657 			/* negative */
658 			for (i = 1; i < len; ++i) {
659 				ATF_CHECK(fseeko(fp, -i, SEEK_END) == 0);
660 				ATF_CHECK(ftello(fp) == len - i);
661 			}
662 			ATF_CHECK(fclose(fp) == 0);
663 		}
664 	}
665 }
666 
667 ATF_TC(test13);
ATF_TC_HEAD(test13,tc)668 ATF_TC_HEAD(test13, tc)
669 {
670 	atf_tc_set_md_var(tc, "descr", "test13");
671 }
ATF_TC_BODY(test13,tc)672 ATF_TC_BODY(test13, tc)
673 {
674 	struct testcase *t;
675 	off_t i;
676 	const char **p;
677 	char buf[BUFSIZ];
678 	FILE *fp;
679 
680 	/* test fmemopen_seek(SEEK_END) */
681 	for (t = &testcases[0]; t->s != NULL; ++t) {
682 		for (p = &mode_w[0]; *p != NULL; ++p) {
683 
684 			memcpy(buf, t->s, t->n);
685 			fp = fmemopen(&buf[0], t->n, *p);
686 			ATF_CHECK(fp != NULL);
687 /*
688  * test fmemopen_seek(SEEK_END)
689  */
690 			ATF_CHECK(ftello(fp) == (off_t)0);
691 			if (fmemopen_truncates_buffer(*p))
692 				ATF_CHECK(buf[0] == '\0');
693 
694 			/* zero */
695 			ATF_CHECK(fseeko(fp, (off_t)0, SEEK_END) == 0);
696 			ATF_CHECK(ftello(fp) == (off_t)0);
697 
698 			/* positive + OOB */
699 			ATF_CHECK(fseeko(fp, (off_t)t->n + 1, SEEK_END) == -1);
700 			ATF_CHECK(ftello(fp) == (off_t)0);
701 
702 			/* negative + OOB */
703 			ATF_CHECK(fseeko(fp, -1, SEEK_END) == -1);
704 			ATF_CHECK(ftello(fp) == (off_t)0);
705 
706 			/* positive */
707 			for (i = 1; i <= t->n; ++i) {
708 				ATF_CHECK(fseeko(fp, i, SEEK_END) == 0);
709 				ATF_CHECK(ftello(fp) == i);
710 			}
711 			ATF_CHECK(fclose(fp) == 0);
712 		}
713 	}
714 }
715 
716 ATF_TC(test14);
ATF_TC_HEAD(test14,tc)717 ATF_TC_HEAD(test14, tc)
718 {
719 	atf_tc_set_md_var(tc, "descr", "test14");
720 }
ATF_TC_BODY(test14,tc)721 ATF_TC_BODY(test14, tc)
722 {
723 	struct testcase *t;
724 	off_t len, rest, i;
725 	const char **p;
726 	char buf[BUFSIZ];
727 	FILE *fp;
728 
729 	/* test fmemopen_seek(SEEK_END) */
730 	for (t = &testcases[0]; t->s != NULL; ++t) {
731 		len = (off_t)strnlen(t->s, t->n);
732 		rest = (off_t)t->n - len;
733 		for (p = &mode_a[0]; *p != NULL; ++p) {
734 
735 			memcpy(buf, t->s, t->n);
736 			fp = fmemopen(&buf[0], t->n, *p);
737 			ATF_CHECK(fp != NULL);
738 /*
739  * test fmemopen_seek(SEEK_END)
740  */
741 			ATF_CHECK(ftello(fp) == len);
742 
743 			/* zero */
744 			ATF_CHECK(fseeko(fp, 0, SEEK_END) == 0);
745 			ATF_CHECK(ftello(fp) == len);
746 
747 			/* positive + OOB */
748 			ATF_CHECK(fseeko(fp, rest + 1, SEEK_END) == -1);
749 			ATF_CHECK(ftello(fp) == len);
750 
751 			/* negative + OOB */
752 			ATF_CHECK(fseeko(fp, -(len + 1), SEEK_END) == -1);
753 			ATF_CHECK(ftello(fp) == len);
754 
755 			/* positive */
756 			for (i = 1; i <= rest; ++i) {
757 				ATF_CHECK(fseeko(fp, i, SEEK_END) == 0);
758 				ATF_CHECK(ftello(fp) == len + i);
759 			}
760 
761 			/* negative */
762 			for (i = 1; i < len; ++i) {
763 				ATF_CHECK(fseeko(fp, -i, SEEK_END) == 0);
764 				ATF_CHECK(ftello(fp) == len - i);
765 			}
766 			ATF_CHECK(fclose(fp) == 0);
767 		}
768 	}
769 }
770 
771 const char *mode_rw1[] = {
772     "r", "rb", "r+", "rb+", "r+b",
773     "w+", "wb+",
774     NULL
775 };
776 
777 /* test15 - 18:
778  * When a stream open for writing is flushed or closed, a null byte is written
779  * at the current position or at the end of the buffer, depending on the size
780  * of the contents.
781  */
782 
783 ATF_TC(test15);
ATF_TC_HEAD(test15,tc)784 ATF_TC_HEAD(test15, tc)
785 {
786 	atf_tc_set_md_var(tc, "descr", "test15");
787 }
ATF_TC_BODY(test15,tc)788 ATF_TC_BODY(test15, tc)
789 {
790 	struct testcase *t;
791 	const char **p;
792 	char buf0[BUFSIZ];
793 	FILE *fp;
794 	off_t i, read_end;
795 
796 	for (t = &testcases[0]; t->s != NULL; ++t) {
797 		for (p = &mode_rw1[0]; *p != NULL; ++p) {
798 			read_end = (off_t)t->n;
799 #ifndef __NetBSD__
800 			/* NetBSD allows reading beyond EOF for 'w' mode. */
801 			if (**p == 'w') {
802 				read_end = 0;
803 			}
804 #endif
805 
806 			memcpy(&buf0[0], t->s, t->n);
807 			fp = fmemopen(&buf0[0], t->n, *p);
808 			ATF_CHECK(fp != NULL);
809 /*
810  * test fmemopen_read + fgetc(3)
811  */
812 			for (i = 0; i < read_end; ++i) {
813 				ATF_CHECK(ftello(fp) == i);
814 				ATF_CHECK(fgetc(fp) == buf0[i]);
815 				ATF_CHECK(feof(fp) == 0);
816 				ATF_CHECK(ftello(fp) == i + 1);
817 			}
818 			ATF_CHECK(fgetc(fp) == EOF);
819 			ATF_CHECK(feof(fp) != 0);
820 			ATF_CHECK(ftello(fp) == read_end);
821 			ATF_CHECK(fclose(fp) == 0);
822 		}
823 	}
824 }
825 
826 ATF_TC(test16);
ATF_TC_HEAD(test16,tc)827 ATF_TC_HEAD(test16, tc)
828 {
829 	atf_tc_set_md_var(tc, "descr", "test16");
830 }
ATF_TC_BODY(test16,tc)831 ATF_TC_BODY(test16, tc)
832 {
833 	struct testcase *t;
834 	const char **p;
835 	char buf0[BUFSIZ], buf1[BUFSIZ];
836 	FILE *fp;
837 	size_t read_end;
838 
839 	for (t = &testcases[0]; t->s != NULL; ++t) {
840 		for (p = &mode_rw1[0]; *p != NULL; ++p) {
841 			read_end = t->n;
842 #ifndef __NetBSD__
843 			/* NetBSD allows reading beyond EOF for 'w' mode. */
844 			if (**p == 'w') {
845 				read_end = 0;
846 			}
847 #endif
848 
849 			memcpy(&buf0[0], t->s, t->n);
850 			buf1[t->n] = 0x1;
851 			fp = fmemopen(&buf0[0], t->n, *p);
852 			ATF_CHECK(fp != NULL);
853 /*
854  * test fmemopen_read + fread(4)
855  */
856 			ATF_CHECK(ftello(fp) == (off_t)0);
857 			ATF_CHECK(fread(&buf1[0], 1, sizeof(buf1), fp) == read_end);
858 			ATF_CHECK(feof(fp) != 0);
859 			ATF_CHECK(memcmp(&buf0[0], &buf1[0], read_end) == 0);
860 			ATF_CHECK((unsigned char)buf1[t->n] == 0x1);
861 
862 			ATF_CHECK(fclose(fp) == 0);
863 		}
864 	}
865 }
866 
867 const char *mode_a1[] = { "a+", "ab+", NULL };
868 
869 ATF_TC(test17);
ATF_TC_HEAD(test17,tc)870 ATF_TC_HEAD(test17, tc)
871 {
872 	atf_tc_set_md_var(tc, "descr", "test17");
873 }
ATF_TC_BODY(test17,tc)874 ATF_TC_BODY(test17, tc)
875 {
876 	struct testcase *t;
877 	size_t len;
878 	size_t i;
879 	const char **p;
880 	char buf[BUFSIZ];
881 	FILE *fp;
882 	size_t read_end;
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(&buf[0], t->s, t->n);
889 			fp = fmemopen(&buf[0], t->n, *p);
890 			ATF_CHECK(fp != NULL);
891 /*
892  * test fmemopen_read + fgetc(3)
893  */
894 #ifdef __NetBSD__
895 			/* NetBSD allows reading beyond EOF for 'a' mode. */
896 			read_end = t->n;
897 #else
898 			read_end = len;
899 #endif
900 			for (i = len; i < read_end; ++i) {
901 				ATF_CHECK(ftello(fp) == (off_t)i);
902 				ATF_CHECK(fgetc(fp) == buf[i]);
903 				ATF_CHECK(feof(fp) == 0);
904 				ATF_CHECK(ftello(fp) == (off_t)i + 1);
905 			}
906 			ATF_CHECK(fgetc(fp) == EOF);
907 			ATF_CHECK(feof(fp) != 0);
908 #ifdef __NetBSD__
909 			ATF_CHECK(ftello(fp) == (off_t)t->n);
910 #else
911 			ATF_CHECK(ftello(fp) == (off_t)len);
912 #endif
913 			rewind(fp);
914 			for (i = 0; i < read_end; ++i) {
915 				ATF_CHECK(ftello(fp) == (off_t)i);
916 				ATF_CHECK(fgetc(fp) == buf[i]);
917 				ATF_CHECK(feof(fp) == 0);
918 				ATF_CHECK(ftello(fp) == (off_t)i + 1);
919 			}
920 			ATF_CHECK(fgetc(fp) == EOF);
921 			ATF_CHECK(feof(fp) != 0);
922 			ATF_CHECK(ftello(fp) == (off_t)read_end);
923 			ATF_CHECK(fclose(fp) == 0);
924 		}
925 	}
926 }
927 
928 ATF_TC(test18);
ATF_TC_HEAD(test18,tc)929 ATF_TC_HEAD(test18, tc)
930 {
931 	atf_tc_set_md_var(tc, "descr", "test18");
932 }
ATF_TC_BODY(test18,tc)933 ATF_TC_BODY(test18, tc)
934 {
935 	struct testcase *t;
936 	size_t len, readlen1, readlen2;
937 	const char **p;
938 	char buf0[BUFSIZ], buf1[BUFSIZ];
939 	FILE *fp;
940 
941 	for (t = &testcases[0]; t->s != NULL; ++t) {
942 		len = strnlen(t->s, t->n);
943 		for (p = &mode_a1[0]; *p != NULL; ++p) {
944 			/* POSIX says reads end at current buffer length. */
945 #if defined(__NetBSD__)
946 			readlen1 = t->n - len;
947 			readlen2 = (size_t)t->n;
948 #else
949 			readlen1 = 0;
950 			readlen2 = len;
951 #endif
952 			memcpy(&buf0[0], t->s, t->n);
953 			buf1[t->n - len] = 0x1;
954 			fp = fmemopen(&buf0[0], t->n, *p);
955 			ATF_CHECK(fp != NULL);
956 /*
957  * test fmemopen_read + fread(3)
958  */
959 			ATF_CHECK(ftello(fp) == (off_t)len);
960 			ATF_CHECK(fread(&buf1[0], 1, sizeof(buf1), fp)
961 			    == readlen1);
962 			ATF_CHECK(feof(fp) != 0);
963 			ATF_CHECK(!memcmp(&buf0[len], &buf1[0], readlen1));
964 			ATF_CHECK((unsigned char)buf1[t->n - len] == 0x1);
965 			rewind(fp);
966 			buf1[t->n] = 0x1;
967 			ATF_CHECK(ftello(fp) == (off_t)0);
968 			ATF_CHECK(fread(&buf1[0], 1, sizeof(buf1), fp)
969 			    == readlen2);
970 			ATF_CHECK(feof(fp) != 0);
971 			ATF_CHECK(!memcmp(&buf0[0], &buf1[0], readlen2));
972 			ATF_CHECK((unsigned char)buf1[t->n] == 0x1);
973 			ATF_CHECK(fclose(fp) == 0);
974 		}
975 	}
976 }
977 
978 /*
979  * test19 - test22:
980  * If a stream open for update is flushed or closed and the last write has
981  * advanced the current buffer size, a null byte is written at the end of the
982  * buffer if it fits.
983  */
984 
985 const char *mode_rw2[] = {
986     "r+", "rb+", "r+b",
987     "w", "wb", "w+", "wb+", "w+b",
988     NULL
989 };
990 
991 ATF_TC(test19);
ATF_TC_HEAD(test19,tc)992 ATF_TC_HEAD(test19, tc)
993 {
994 	atf_tc_set_md_var(tc, "descr", "test19");
995 }
ATF_TC_BODY(test19,tc)996 ATF_TC_BODY(test19, tc)
997 {
998 	struct testcase *t;
999 	int i;
1000 	const char **p;
1001 	char buf[BUFSIZ];
1002 	FILE *fp;
1003 
1004 	for (t = &testcases[0]; t->s != NULL; ++t) {
1005 		for (p = &mode_rw2[0]; *p != NULL; ++p) {
1006 
1007 			memcpy(&buf[0], t->s, t->n);
1008 			buf[t->n] = 0x1;
1009 			fp = fmemopen(&buf[0], t->n + 1, *p);
1010 			ATF_CHECK(fp != NULL);
1011 			setbuf(fp, NULL);
1012 /*
1013  * test fmemopen_write + fputc(3)
1014  */
1015 			for (i = 0; i < t->n; ++i) {
1016 				ATF_CHECK(ftello(fp) == (off_t)i);
1017 				ATF_CHECK(fputc(t->s[i], fp) == t->s[i]);
1018 				ATF_CHECK(buf[i] == t->s[i]);
1019 				ATF_CHECK(ftello(fp) == (off_t)i + 1);
1020 				ATF_CHECK(buf[i] == t->s[i]);
1021 #if !defined(__NetBSD__)
1022 				if (**p == 'w' && t->s[i] != '\0')
1023 #endif
1024 				ATF_CHECK(buf[i + 1] == '\0');
1025 			}
1026 
1027 /* don't accept non nul character at end of buffer (not mandated by POSIX, so
1028  * fails with glibc, etc.) */
1029 #if defined(__NetBSD__)
1030 			ATF_CHECK(fputc(0x1, fp) == EOF);
1031 			ATF_CHECK_MSG(ftello(fp) == (off_t)t->n,
1032 				"%jd != %jd", (intmax_t)ftello(fp),
1033 				(intmax_t)t->n);
1034 			ATF_CHECK(feof(fp) == 0);
1035 #endif
1036 
1037 /* accept nul character at end of buffer */
1038 			ATF_CHECK(fputc('\0', fp) == '\0');
1039 			ATF_CHECK(ftello(fp) == (off_t)t->n + 1);
1040 			ATF_CHECK(feof(fp) == 0);
1041 
1042 /* reach EOF */
1043 			ATF_CHECK(fputc('\0', fp) == EOF);
1044 			ATF_CHECK(ftello(fp) == (off_t)t->n + 1);
1045 
1046 			/* compare */
1047 			ATF_CHECK(memcmp(&buf[0], t->s, t->n) == 0);
1048 			ATF_CHECK(buf[t->n] == '\0');
1049 
1050 			ATF_CHECK(fclose(fp) == 0);
1051 		}
1052 	}
1053 }
1054 
1055 ATF_TC(test20);
ATF_TC_HEAD(test20,tc)1056 ATF_TC_HEAD(test20, tc)
1057 {
1058 	atf_tc_set_md_var(tc, "descr", "test20");
1059 }
ATF_TC_BODY(test20,tc)1060 ATF_TC_BODY(test20, tc)
1061 {
1062 	struct testcase *t;
1063 	const char **p;
1064 	char buf[BUFSIZ];
1065 	FILE *fp;
1066 
1067 	for (t = &testcases[0]; t->s != NULL; ++t) {
1068 		for (p = &mode_rw2[0]; *p != NULL; ++p) {
1069 
1070 			memcpy(&buf[0], t->s, t->n);
1071 			buf[t->n] = 0x1;
1072 			fp = fmemopen(&buf[0], t->n + 1, *p);
1073 			ATF_CHECK(fp != NULL);
1074 			setbuf(fp, NULL);
1075 			ATF_CHECK(fwrite(t->s, 1, t->n, fp) == (size_t)t->n);
1076 /*
1077  * test fmemopen_write + fwrite(3)
1078  */
1079 #if defined(__NetBSD__)
1080 /* NUL termination is not mandated by POSIX, so fails with glibc, etc. */
1081 			ATF_CHECK(buf[t->n] == '\0');
1082 /* don't accept non nul character at end of buffer (not mandated by POSIX, so
1083  * fails with glibc, etc.) */
1084 			ATF_CHECK(fwrite("\x1", 1, 1, fp) == 0);
1085 			ATF_CHECK(ftello(fp) == (off_t)t->n);
1086 			ATF_CHECK(feof(fp) == 0);
1087 #endif
1088 
1089 /* accept nul character at end of buffer */
1090 			ATF_CHECK(fwrite("\x0", 1, 1, fp) == 1);
1091 			ATF_CHECK(ftello(fp) == (off_t)t->n + 1);
1092 			ATF_CHECK(feof(fp) == 0);
1093 
1094 /* reach EOF */
1095 			ATF_CHECK(fputc('\0', fp) == EOF);
1096 			ATF_CHECK(ftello(fp) == (off_t)t->n + 1);
1097 
1098 /* compare */
1099 			ATF_CHECK(memcmp(&buf[0], t->s, t->n) == 0);
1100 			ATF_CHECK(buf[t->n] == '\0');
1101 
1102 			ATF_CHECK(fclose(fp) == 0);
1103 		}
1104 	}
1105 }
1106 
1107 ATF_TC(test21);
ATF_TC_HEAD(test21,tc)1108 ATF_TC_HEAD(test21, tc)
1109 {
1110 	atf_tc_set_md_var(tc, "descr", "test21");
1111 }
ATF_TC_BODY(test21,tc)1112 ATF_TC_BODY(test21, tc)
1113 {
1114 	struct testcase *t;
1115 	int len, i;
1116 	const char **p;
1117 	char buf[BUFSIZ];
1118 	FILE *fp;
1119 
1120 	for (t = &testcases[0]; t->s != NULL; ++t) {
1121 		len = strnlen(t->s, t->n);
1122 		for (p = &mode_a[0]; *p != NULL; ++p) {
1123 			memcpy(&buf[0], t->s, t->n);
1124 			fp = fmemopen(&buf[0], t->n, *p);
1125 			ATF_CHECK(fp != NULL);
1126 			setbuf(fp, NULL);
1127 /*
1128  * test fmemopen_write + fputc(3)
1129  */
1130 			if (len < t->n) {
1131 				for (i = len; i < t->n - 1; ++i) {
1132 					ATF_CHECK(ftello(fp) == (off_t)i);
1133 					ATF_CHECK(fputc(t->s[i - len], fp)
1134 					    == t->s[i - len]);
1135 					ATF_CHECK(buf[i] == t->s[i - len]);
1136 					ATF_CHECK(ftello(fp) == (off_t)i + 1);
1137 #if defined(__NetBSD__)
1138 					ATF_CHECK(buf[i + 1] == '\0');
1139 #endif
1140 				}
1141 
1142 /* don't accept non nul character at end of buffer (not mandated by POSIX, so
1143  * fails with glibc, etc.) */
1144 #if defined(__NetBSD__)
1145 				ATF_CHECK(ftello(fp) == (off_t)t->n - 1);
1146 				ATF_CHECK(fputc(0x1, fp) == EOF);
1147 				ATF_CHECK(ftello(fp) == (off_t)t->n - 1);
1148 #endif
1149 
1150 /* accept nul character at end of buffer */
1151 				ATF_CHECK(ftello(fp) == (off_t)t->n - 1);
1152 				ATF_CHECK(fputc('\0', fp) == '\0');
1153 				ATF_CHECK(ftello(fp) == (off_t)t->n);
1154 			}
1155 
1156 /* reach EOF */
1157 			ATF_CHECK(ftello(fp) == (off_t)t->n);
1158 			ATF_CHECK(fputc('\0', fp) == EOF);
1159 			ATF_CHECK(ftello(fp) == (off_t)t->n);
1160 
1161 			ATF_CHECK(fclose(fp) == 0);
1162 		}
1163 	}
1164 }
1165 
1166 ATF_TC(test22);
ATF_TC_HEAD(test22,tc)1167 ATF_TC_HEAD(test22, tc)
1168 {
1169 	atf_tc_set_md_var(tc, "descr", "test22");
1170 }
ATF_TC_BODY(test22,tc)1171 ATF_TC_BODY(test22, tc)
1172 {
1173 	struct testcase *t0, *t1;
1174 	size_t len0, len1, nleft, written, writelen;
1175 	const char **p;
1176 	char buf[BUFSIZ];
1177 	FILE *fp;
1178 
1179 	for (t0 = &testcases[0]; t0->s != NULL; ++t0) {
1180 		len0 = strnlen(t0->s, t0->n);
1181 		for (t1 = &testcases[0]; t1->s != NULL; ++t1) {
1182 			for (p = &mode_a[0]; *p != NULL; ++p) {
1183 				len1 = strnlen(t1->s, t1->n);
1184 				memcpy(&buf[0], t0->s, t0->n);
1185 				fp = fmemopen(&buf[0], t0->n, *p);
1186 				ATF_CHECK(fp != NULL);
1187 				setbuf(fp, NULL);
1188 				ATF_CHECK(ftello(fp) == (off_t)len0);
1189 /*
1190  * test fmemopen_write + fwrite(3)
1191  */
1192 				nleft = t0->n - len0;
1193 				written = fwrite(t1->s, 1, t1->n, fp);
1194 				if (nleft == 0 || len1 == nleft - 1) {
1195 					writelen = nleft;
1196 				} else {
1197 #if defined(__NetBSD__)
1198 					/* NetBSD ensures NUL-termination */
1199 					writelen = nleft - 1;
1200 #else
1201 					/* POSIX says it's not required. */
1202 					writelen = nleft;
1203 #endif
1204 				}
1205 #if defined(__GLIBC__)
1206 				/* glibc incorrectly checks buf[writelen-1] for
1207 				 * NUL termination instead of clamped index. */
1208 				if (t1->s[t1->n - 1] != '\0' && nleft <= 1)
1209 					writelen = 0;
1210 #endif
1211 				ATF_CHECK(written == writelen);
1212 				ATF_CHECK(ftello(fp) == (off_t)(len0 + writelen));
1213 				ATF_CHECK(fclose(fp) == 0);
1214 			}
1215 		}
1216 	}
1217 }
1218 
ATF_TP_ADD_TCS(tp)1219 ATF_TP_ADD_TCS(tp)
1220 {
1221 	ATF_TP_ADD_TC(tp, test00);
1222 	ATF_TP_ADD_TC(tp, test01);
1223 	ATF_TP_ADD_TC(tp, test02);
1224 	ATF_TP_ADD_TC(tp, test03);
1225 	ATF_TP_ADD_TC(tp, test04);
1226 	ATF_TP_ADD_TC(tp, test05);
1227 	ATF_TP_ADD_TC(tp, test06);
1228 	ATF_TP_ADD_TC(tp, test07);
1229 	ATF_TP_ADD_TC(tp, test08);
1230 	ATF_TP_ADD_TC(tp, test09);
1231 	ATF_TP_ADD_TC(tp, test10);
1232 	ATF_TP_ADD_TC(tp, test11);
1233 	ATF_TP_ADD_TC(tp, test12);
1234 	ATF_TP_ADD_TC(tp, test13);
1235 	ATF_TP_ADD_TC(tp, test14);
1236 	ATF_TP_ADD_TC(tp, test15);
1237 	ATF_TP_ADD_TC(tp, test16);
1238 	ATF_TP_ADD_TC(tp, test17);
1239 	ATF_TP_ADD_TC(tp, test18);
1240 	ATF_TP_ADD_TC(tp, test19);
1241 	ATF_TP_ADD_TC(tp, test20);
1242 	ATF_TP_ADD_TC(tp, test21);
1243 	ATF_TP_ADD_TC(tp, test22);
1244 
1245 	return atf_no_error();
1246 }
1247