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