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