Module Name: src Committed By: tnozaki Date: Fri Sep 24 09:21:53 UTC 2010
Modified Files: src/include: stdio.h src/lib/libc: shlib_version src/lib/libc/stdio: Makefile.inc Added Files: src/lib/libc/stdio: fmemopen.c src/tests/lib/libc/stdio: Makefile t_fmemopen.c Log Message: add fmemopen(3) derrived from POSIX:2008. libc minor bump. To generate a diff of this commit: cvs rdiff -u -r1.77 -r1.78 src/include/stdio.h cvs rdiff -u -r1.218 -r1.219 src/lib/libc/shlib_version cvs rdiff -u -r1.37 -r1.38 src/lib/libc/stdio/Makefile.inc cvs rdiff -u -r0 -r1.1 src/lib/libc/stdio/fmemopen.c cvs rdiff -u -r0 -r1.1 src/tests/lib/libc/stdio/Makefile \ src/tests/lib/libc/stdio/t_fmemopen.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/include/stdio.h diff -u src/include/stdio.h:1.77 src/include/stdio.h:1.78 --- src/include/stdio.h:1.77 Mon Sep 6 14:52:26 2010 +++ src/include/stdio.h Fri Sep 24 09:21:53 2010 @@ -1,4 +1,4 @@ -/* $NetBSD: stdio.h,v 1.77 2010/09/06 14:52:26 christos Exp $ */ +/* $NetBSD: stdio.h,v 1.78 2010/09/24 09:21:53 tnozaki Exp $ */ /*- * Copyright (c) 1990, 1993 @@ -508,6 +508,11 @@ #define putchar_unlocked(x) putc_unlocked(x, stdout) #endif /* _POSIX_C_SOURCE >= 199506 || _XOPEN_SOURCE >= 500 || _REENTRANT... */ +#if (_POSIX_C_SOURCE - 0) >= 200809L || (_XOPEN_SOURCE - 0) >= 700 || \ + defined(_NETBSD_SOURCE) +FILE *fmemopen(void * __restrict, size_t, const char * __restrict); +#endif + #if _FORTIFY_SOURCE > 0 #include <ssp/stdio.h> #endif Index: src/lib/libc/shlib_version diff -u src/lib/libc/shlib_version:1.218 src/lib/libc/shlib_version:1.219 --- src/lib/libc/shlib_version:1.218 Mon Jun 7 13:52:29 2010 +++ src/lib/libc/shlib_version Fri Sep 24 09:21:53 2010 @@ -1,4 +1,4 @@ -# $NetBSD: shlib_version,v 1.218 2010/06/07 13:52:29 tnozaki Exp $ +# $NetBSD: shlib_version,v 1.219 2010/09/24 09:21:53 tnozaki Exp $ # Remember to update distrib/sets/lists/base/shl.* when changing # # things we wish to do on next major version bump: @@ -31,4 +31,4 @@ # it's insufficient bitwidth to implement all ctype class. # see isblank's comment in ctype.h. major=12 -minor=173 +minor=174 Index: src/lib/libc/stdio/Makefile.inc diff -u src/lib/libc/stdio/Makefile.inc:1.37 src/lib/libc/stdio/Makefile.inc:1.38 --- src/lib/libc/stdio/Makefile.inc:1.37 Mon Sep 6 14:52:55 2010 +++ src/lib/libc/stdio/Makefile.inc Fri Sep 24 09:21:53 2010 @@ -1,5 +1,5 @@ # from: @(#)Makefile.inc 5.7 (Berkeley) 6/27/91 -# $NetBSD: Makefile.inc,v 1.37 2010/09/06 14:52:55 christos Exp $ +# $NetBSD: Makefile.inc,v 1.38 2010/09/24 09:21:53 tnozaki Exp $ # stdio sources .PATH: ${.CURDIR}/stdio @@ -20,6 +20,7 @@ vasprintf.c vdprintf.c vfprintf.c vfscanf.c vfwprintf.c vfwscanf.c \ vprintf.c vscanf.c vsnprintf.c vsnprintf_ss.c vsscanf.c vswprintf.c \ vswscanf.c vwprintf.c vwscanf.c wbuf.c wprintf.c wscanf.c wsetup.c +SRCS+= fmemopen.c .if !defined(AUDIT) SRCS+= gets.c sprintf.c vsprintf.c tempnam.c tmpnam.c mktemp.c Added files: Index: src/lib/libc/stdio/fmemopen.c diff -u /dev/null src/lib/libc/stdio/fmemopen.c:1.1 --- /dev/null Fri Sep 24 09:21:53 2010 +++ src/lib/libc/stdio/fmemopen.c Fri Sep 24 09:21:53 2010 @@ -0,0 +1,216 @@ +/* $NetBSD: fmemopen.c,v 1.1 2010/09/24 09:21:53 tnozaki Exp $ */ + +/*- + * Copyright (c)2007, 2010 Takehiko NOZAKI, + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#include <sys/cdefs.h> +#if defined(LIBC_SCCS) && !defined(lint) +__RCSID("$NetBSD: fmemopen.c,v 1.1 2010/09/24 09:21:53 tnozaki Exp $"); +#endif /* LIBC_SCCS and not lint */ + +#include <assert.h> +#include <errno.h> +#include <fcntl.h> +#include <stdio.h> +#include <stdlib.h> + +#include "reentrant.h" +#include "local.h" + +struct fmemopen_cookie { + char *head, *tail, *cur, *eob; +}; + +static int +fmemopen_read(void *cookie, char *buf, int nbytes) +{ + struct fmemopen_cookie *p; + char *s; + + _DIAGASSERT(cookie != NULL); + _DIAGASSERT(buf != NULL && nbytes > 0); + + p = (struct fmemopen_cookie *)cookie; + s = p->cur; + do { + if (p->cur == p->tail) + break; + *buf++ = *p->cur++; + } while (--nbytes > 0); + + return (int)(p->cur - s); +} + +static int +fmemopen_write(void *cookie, const char *buf, int nbytes) +{ + struct fmemopen_cookie *p; + char *s, *t; + + _DIAGASSERT(cookie != NULL); + _DIAGASSERT(buf != NULL && nbytes > 0); + + p = (struct fmemopen_cookie *)cookie; + if (p->cur >= p->tail) + return 0; + s = p->cur; + t = p->tail - 1; + do { + if (p->cur == t) { + if (*buf == '\0') + *p->cur++ = *buf++; + break; + } + *p->cur++ = *buf++; + } while (--nbytes > 0); + *p->cur = '\0'; + if (p->cur > p->eob) + p->eob = p->cur; + + return (int)(p->cur - s); +} + +static fpos_t +fmemopen_seek(void *cookie, fpos_t offset, int whence) +{ + struct fmemopen_cookie *p; + + _DIAGASSERT(cookie != NULL); + + p = (struct fmemopen_cookie *)cookie; + switch (whence) { + case SEEK_SET: + break; + case SEEK_CUR: + offset += p->cur - p->head; + break; + case SEEK_END: + offset += p->eob - p->head; + break; + default: + errno = EINVAL; + goto error; + } + if (offset >= (fpos_t)0 && offset <= p->tail - p->head) { + p->cur = p->head + offset; + return (fpos_t)(p->cur - p->head); + } +error: + return (fpos_t)-1; +} + +static int +fmemopen_close0(void *cookie) +{ + _DIAGASSERT(cookie != NULL); + + free(cookie); + + return 0; +} + +static int +fmemopen_close1(void *cookie) +{ + struct fmemopen_cookie *p; + + _DIAGASSERT(cookie != NULL); + + p = (struct fmemopen_cookie *)cookie; + free(p->head); + free(p); + + return 0; +} + + +FILE * +fmemopen(void * __restrict buf, size_t size, const char * __restrict mode) +{ + int oflags; + FILE *fp; + struct fmemopen_cookie *cookie; + + if (size < (size_t)1) { + errno = EINVAL; + return NULL; + } + + fp = __sfp(); + if (fp == NULL) + return NULL; + fp->_file = -1; + + fp->_flags = __sflags(mode, &oflags); + if (fp->_flags == 0) + return NULL; + + if ((oflags & O_RDWR) == 0 && buf == NULL) { + errno = EINVAL; + goto release; + } + + cookie = malloc(sizeof(*cookie)); + if (cookie == NULL) + goto release; + + if (buf == NULL) { + cookie->head = malloc(size); + if (cookie->head == NULL) { + free(cookie); + goto release; + } + *cookie->head = '\0'; + fp->_close = &fmemopen_close1; + } else { + cookie->head = (char *)buf; + if (oflags & O_TRUNC) + *cookie->head = '\0'; + fp->_close = &fmemopen_close0; + } + + cookie->tail = cookie->head + size; + cookie->eob = cookie->head; + do { + if (*cookie->eob == '\0') + break; + ++cookie->eob; + } while (--size > 0); + + cookie->cur = (oflags & O_APPEND) ? cookie->eob : cookie->head; + + fp->_write = (fp->_flags & __SRD) ? NULL : &fmemopen_write; + fp->_read = (fp->_flags & __SWR) ? NULL : &fmemopen_read; + fp->_seek = &fmemopen_seek; + fp->_cookie = (void *)cookie; + + return fp; + +release: + fp->_flags = 0; + return NULL; +} Index: src/tests/lib/libc/stdio/Makefile diff -u /dev/null src/tests/lib/libc/stdio/Makefile:1.1 --- /dev/null Fri Sep 24 09:21:53 2010 +++ src/tests/lib/libc/stdio/Makefile Fri Sep 24 09:21:53 2010 @@ -0,0 +1,9 @@ +# $NetBSD: Makefile,v 1.1 2010/09/24 09:21:53 tnozaki Exp $ + +.include <bsd.own.mk> + +TESTSDIR= ${TESTSBASE}/lib/libc/stdio + +TESTS_C+= t_fmemopen + +.include <bsd.test.mk> Index: src/tests/lib/libc/stdio/t_fmemopen.c diff -u /dev/null src/tests/lib/libc/stdio/t_fmemopen.c:1.1 --- /dev/null Fri Sep 24 09:21:53 2010 +++ src/tests/lib/libc/stdio/t_fmemopen.c Fri Sep 24 09:21:53 2010 @@ -0,0 +1,1170 @@ +/* $NetBSD: t_fmemopen.c,v 1.1 2010/09/24 09:21:53 tnozaki Exp $ */ + +/*- + * Copyright (c)2010 Takehiko NOZAKI, + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#if defined(__NetBSD__) +#include <atf-c.h> +#else +#if defined(__linux__) +#define _GNU_SOURCE +#include <features.h> +#endif +#include <assert.h> +#include <stdio.h> +#define ATF_TC(arg0) static void arg0##_head(void) +#define ATF_TC_HEAD(arg0, arg1) static void arg0##_head() +#define atf_tc_set_md_var(arg0, arg1, ...) do { \ + printf(__VA_ARGS__); \ + puts(""); \ +} while (/*CONSTCOND*/0) +#define ATF_TC_BODY(arg0, arg1) static void arg0##_body() +#define ATF_CHECK(arg0) assert(arg0) +#define ATF_TP_ADD_TCS(arg0) int main(void) +#define ATF_TP_ADD_TC(arg0, arg1) arg1##_head(); arg1##_body() +#define atf_no_error() 0 +#endif + +#include <errno.h> +#include <stdio.h> +#include <limits.h> +#include <stdlib.h> +#include <string.h> + +const char *mode_rwa[] = { + "r", "rb", "r+", "rb+", "r+b", + "w", "wb", "w+", "wb+", "w+b", + "a", "ab", "a+", "ab+", "a+b", + NULL +}; + +const char *mode_r[] = { "r", "rb", "r+", "rb+", "r+b", NULL }; +const char *mode_w[] = { "w", "wb", "w+", "wb+", "w+b", NULL }; +const char *mode_a[] = { "a", "ab", "a+", "ab+", "a+b", NULL }; + +struct testcase { + const char *s; + size_t n; +} testcases[] = { +#define TESTSTR(s) { s, sizeof(s)-1 } + TESTSTR("\0he quick brown fox jumps over the lazy dog"), + TESTSTR("T\0e quick brown fox jumps over the lazy dog"), + TESTSTR("Th\0 quick brown fox jumps over the lazy dog"), + TESTSTR("The\0quick brown fox jumps over the lazy dog"), + TESTSTR("The \0uick brown fox jumps over the lazy dog"), + TESTSTR("The q\0ick brown fox jumps over the lazy dog"), + TESTSTR("The qu\0ck brown fox jumps over the lazy dog"), + TESTSTR("The qui\0k brown fox jumps over the lazy dog"), + TESTSTR("The quic\0 brown fox jumps over the lazy dog"), + TESTSTR("The quick\0brown fox jumps over the lazy dog"), + TESTSTR("The quick \0rown fox jumps over the lazy dog"), + TESTSTR("The quick b\0own fox jumps over the lazy dog"), + TESTSTR("The quick br\0wn fox jumps over the lazy dog"), + TESTSTR("The quick bro\0n fox jumps over the lazy dog"), + TESTSTR("The quick brow\0 fox jumps over the lazy dog"), + TESTSTR("The quick brown\0fox jumps over the lazy dog"), + TESTSTR("The quick brown \0ox jumps over the lazy dog"), + TESTSTR("The quick brown f\0x jumps over the lazy dog"), + TESTSTR("The quick brown fo\0 jumps over the lazy dog"), + TESTSTR("The quick brown fox\0jumps over the lazy dog"), + TESTSTR("The quick brown fox \0umps over the lazy dog"), + TESTSTR("The quick brown fox j\0mps over the lazy dog"), + TESTSTR("The quick brown fox ju\0ps over the lazy dog"), + TESTSTR("The quick brown fox jum\0s over the lazy dog"), + TESTSTR("The quick brown fox jump\0 over the lazy dog"), + TESTSTR("The quick brown fox jumps\0over the lazy dog"), + TESTSTR("The quick brown fox jumps \0ver the lazy dog"), + TESTSTR("The quick brown fox jumps o\0er the lazy dog"), + TESTSTR("The quick brown fox jumps ov\0r the lazy dog"), + TESTSTR("The quick brown fox jumps ove\0 the lazy dog"), + TESTSTR("The quick brown fox jumps over\0the lazy dog"), + TESTSTR("The quick brown fox jumps over \0he lazy dog"), + TESTSTR("The quick brown fox jumps over t\0e lazy dog"), + TESTSTR("The quick brown fox jumps over th\0 lazy dog"), + TESTSTR("The quick brown fox jumps over the\0lazy dog"), + TESTSTR("The quick brown fox jumps over the \0azy dog"), + TESTSTR("The quick brown fox jumps over the l\0zy dog"), + TESTSTR("The quick brown fox jumps over the la\0y dog"), + TESTSTR("The quick brown fox jumps over the laz\0 dog"), + TESTSTR("The quick brown fox jumps over the lazy\0dog"), + TESTSTR("The quick brown fox jumps over the lazy \0og"), + TESTSTR("The quick brown fox jumps over the lazy d\0g"), + TESTSTR("The quick brown fox jumps over the lazy do\0"), + TESTSTR("The quick brown fox jumps over the lazy dog"), + { NULL, 0 }, +}; + +ATF_TC(test00); +ATF_TC_HEAD(test00, tc) +{ + atf_tc_set_md_var(tc, "descr", "test00"); +} +ATF_TC_BODY(test00, tc) +{ + const char **p; + char buf[BUFSIZ]; + FILE *fp; + + for (p = &mode_rwa[0]; *p != NULL; ++p) { + fp = fmemopen(&buf[0], sizeof(buf), *p); +/* + * Upon successful completion, fmemopen() shall return a pointer to the + * object controlling the stream. + */ + ATF_CHECK(fp != NULL); + + ATF_CHECK(fclose(fp) == 0); + } +} + +ATF_TC(test01); +ATF_TC_HEAD(test01, tc) +{ + atf_tc_set_md_var(tc, "descr", "test01"); +} +ATF_TC_BODY(test01, tc) +{ + const char **p; + const char *mode[] = { + "r+", "rb+", "r+b", + "w+", "wb+", "w+b", + "a+", "ab+", "a+b", + NULL + }; + FILE *fp; + + for (p = &mode[0]; *p != NULL; ++p) { +/* + * If a null pointer is specified as the buf argument, fmemopen() shall + * allocate size bytes of memory as if by a call to malloc(). + */ + fp = fmemopen(NULL, BUFSIZ, *p); + ATF_CHECK(fp != NULL); + +/* + * If buf is a null pointer, the initial position shall always be set + * to the beginning of the buffer. + */ + ATF_CHECK(ftello(fp) == (off_t)0); + + ATF_CHECK(fclose(fp) == 0); + } +} + +ATF_TC(test02); +ATF_TC_HEAD(test02, tc) +{ + atf_tc_set_md_var(tc, "descr", "test02"); +} +ATF_TC_BODY(test02, tc) +{ + const char **p; + char buf[BUFSIZ]; + FILE *fp; + + for (p = &mode_r[0]; *p != NULL; ++p) { + + memset(&buf[0], 0x1, sizeof(buf)); + fp = fmemopen(&buf[0], sizeof(buf), *p); + ATF_CHECK(fp != NULL); + +/* + * This position is initially set to either the beginning of the buffer + * (for r and w modes) + */ + ATF_CHECK((unsigned char)buf[0] == 0x1); + ATF_CHECK(ftello(fp) == (off_t)0); + +/* + * The stream also maintains the size of the current buffer contents. + * For modes r and r+ the size is set to the value given by the size argument. + */ +#if !defined(__GLIBC__) + ATF_CHECK(fseeko(fp, (off_t)0, SEEK_END) == 0); + ATF_CHECK(ftello(fp) == (off_t)sizeof(buf)); +#endif + ATF_CHECK(fclose(fp) == 0); + } +} + +ATF_TC(test03); +ATF_TC_HEAD(test03, tc) +{ + atf_tc_set_md_var(tc, "descr", "test03"); +} +ATF_TC_BODY(test03, tc) +{ + const char **p; + char buf[BUFSIZ]; + FILE *fp; + + for (p = &mode_w[0]; *p != NULL; ++p) { + + memset(&buf[0], 0x1, sizeof(buf)); + fp = fmemopen(&buf[0], sizeof(buf), *p); + ATF_CHECK(fp != NULL); + +/* + * This position is initially set to either the beginning of the buffer + * (for r and w modes) + */ + ATF_CHECK(buf[0] == '\0'); + ATF_CHECK(ftello(fp) == (off_t)0); + +/* + * For modes w and w+ the initial size is zero + */ + ATF_CHECK(fseeko(fp, (off_t)0, SEEK_END) == 0); + ATF_CHECK(ftello(fp) == (off_t)0); + + ATF_CHECK(fclose(fp) == 0); + } +} + +ATF_TC(test04); +ATF_TC_HEAD(test04, tc) +{ + atf_tc_set_md_var(tc, "descr", "test04"); +} +ATF_TC_BODY(test04, tc) +{ + const char **p; + char buf[BUFSIZ]; + FILE *fp; + +/* + * or to the first null byte in the buffer (for a modes) + */ + for (p = &mode_a[0]; *p != NULL; ++p) { + + memset(&buf[0], 0x1, sizeof(buf)); + fp = fmemopen(&buf[0], sizeof(buf), *p); + ATF_CHECK(fp != NULL); + + ATF_CHECK((unsigned char)buf[0] == 0x1); + +/* If no null byte is found in append mode, + * the initial position is set to one byte after the end of the buffer. + */ +#if !defined(__GLIBC__) + ATF_CHECK(ftello(fp) == (off_t)sizeof(buf)); +#endif + +/* + * and for modes a and a+ the initial size is either the position of the + * first null byte in the buffer or the value of the size argument + * if no null byte is found. + */ +#if !defined(__GLIBC__) + ATF_CHECK(fseeko(fp, (off_t)0, SEEK_END) == 0); + ATF_CHECK(ftello(fp) == (off_t)sizeof(buf)); +#endif + + ATF_CHECK(fclose(fp) == 0); + } +} + +ATF_TC(test05); +ATF_TC_HEAD(test05, tc) +{ + atf_tc_set_md_var(tc, "descr", "test05"); +} +ATF_TC_BODY(test05, tc) +{ + const char **p; + FILE *fp; + char buf[BUFSIZ]; + + for (p = &mode_rwa[0]; *p != NULL; ++p) { +/* + * Otherwise, a null pointer shall be returned, and errno shall be set + * to indicate the error. + */ + errno = 0; + fp = fmemopen(NULL, (size_t)0, *p); + ATF_CHECK(fp == NULL); + ATF_CHECK(errno == EINVAL); + + errno = 0; + fp = fmemopen((void *)&buf[0], 0, *p); + ATF_CHECK(fp == NULL); + ATF_CHECK(errno == EINVAL); + } +} + +ATF_TC(test06); +ATF_TC_HEAD(test06, tc) +{ + atf_tc_set_md_var(tc, "descr", "test06"); +} +ATF_TC_BODY(test06, tc) +{ + const char **p; + const char *mode[] = { "", " ", "???", NULL }; + FILE *fp; + + for (p = &mode[0]; *p != NULL; ++p) { +/* + * The value of the mode argument is not valid. + */ + fp = fmemopen(NULL, 1, *p); + ATF_CHECK(fp == NULL); + ATF_CHECK(errno == EINVAL); + } +} + +ATF_TC(test07); +ATF_TC_HEAD(test07, tc) +{ + atf_tc_set_md_var(tc, "descr", "test07"); +} +ATF_TC_BODY(test07, tc) +{ +#if !defined(__GLIBC__) + const char **p; + const char *mode[] = { + "r", "rb", + "w", "wb", + "a", "ab", + NULL + }; + FILE *fp; + + for (p = &mode[0]; *p != NULL; ++p) { +/* + * Because this feature is only useful when the stream is opened for updating + * (because there is no way to get a pointer to the buffer) the fmemopen() + * call may fail if the mode argument does not include a '+' . + */ + errno = 0; + fp = fmemopen(NULL, 1, *p); + ATF_CHECK(fp == NULL); + ATF_CHECK(errno == EINVAL); + } +#endif +} + +ATF_TC(test08); +ATF_TC_HEAD(test08, tc) +{ + atf_tc_set_md_var(tc, "descr", "test08"); +} +ATF_TC_BODY(test08, tc) +{ +#if !defined(__GLIBC__) + const char **p; + const char *mode[] = { + "r+", "rb+", "r+b", + "w+", "wb+", "w+b", + "a+", "ab+", "a+b", + NULL + }; + FILE *fp; + + for (p = &mode[0]; *p != NULL; ++p) { +/* + * The buf argument is a null pointer and the allocation of a buffer of + * length size has failed. + */ + fp = fmemopen(NULL, SIZE_MAX, *p); + ATF_CHECK(fp == NULL); + ATF_CHECK(errno == ENOMEM); + } +#endif +} + +/* + * test09 - test14: + * An attempt to seek a memory buffer stream to a negative position or to a + * position larger than the buffer size given in the size argument shall fail. + */ + +ATF_TC(test09); +ATF_TC_HEAD(test09, tc) +{ + atf_tc_set_md_var(tc, "descr", "test09"); +} +ATF_TC_BODY(test09, tc) +{ + struct testcase *t; + const char **p; + char buf[BUFSIZ]; + FILE *fp; + off_t i; + + for (t = &testcases[0]; t->s != NULL; ++t) { + for (p = &mode_rwa[0]; *p != NULL; ++p) { + + memcpy(&buf[0], t->s, t->n); + fp = fmemopen(&buf[0], t->n, *p); + ATF_CHECK(fp != NULL); + +/* + * test fmemopen_seek(SEEK_SET) + */ + /* zero */ + ATF_CHECK(fseeko(fp, (off_t)0, SEEK_SET) == 0); + ATF_CHECK(ftello(fp) == (off_t)0); + + /* positive */ + for (i = (off_t)1; i <= (off_t)t->n; ++i) { + ATF_CHECK(fseeko(fp, i, SEEK_SET) == 0); + ATF_CHECK(ftello(fp) == i); + } + /* positive + OOB */ + ATF_CHECK(fseeko(fp, t->n + 1, SEEK_SET) == -1); + ATF_CHECK(ftello(fp) == t->n); + + /* negative + OOB */ + ATF_CHECK(fseeko(fp, (off_t)-1, SEEK_SET) == -1); + ATF_CHECK(ftello(fp) == t->n); + + ATF_CHECK(fclose(fp) == 0); + } + } +} + +const char *mode_rw[] = { + "r", "rb", "r+", "rb+", "r+b", + "w", "wb", "w+", "wb+", "w+b", + NULL +}; + +ATF_TC(test10); +ATF_TC_HEAD(test10, tc) +{ + atf_tc_set_md_var(tc, "descr", "test10"); +} +ATF_TC_BODY(test10, tc) +{ + struct testcase *t; + off_t len, i; + const char **p; + char buf[BUFSIZ]; + FILE *fp; + + for (t = &testcases[0]; t->s != NULL; ++t) { + len = (off_t)strnlen(t->s, t->n); + for (p = &mode_rw[0]; *p != NULL; ++p) { + + memcpy(&buf[0], t->s, t->n); + fp = fmemopen(&buf[0], t->n, *p); + ATF_CHECK(fp != NULL); + +/* + * test fmemopen_seek(SEEK_CUR) + */ + ATF_CHECK(ftello(fp) == (off_t)0); + + /* zero */ + ATF_CHECK(fseeko(fp, (off_t)0, SEEK_CUR) == 0); + ATF_CHECK(ftello(fp) == (off_t)0); + + /* negative & OOB */ + ATF_CHECK(fseeko(fp, (off_t)-1, SEEK_CUR) == -1); + ATF_CHECK(ftello(fp) == (off_t)0); + + /* positive */ + for (i = 0; i < (off_t)t->n; ++i) { + ATF_CHECK(fseeko(fp, (off_t)1, SEEK_CUR) == 0); + ATF_CHECK(ftello(fp) == i + 1); + } + + /* positive & OOB */ + ATF_CHECK(fseeko(fp, (off_t)1, SEEK_CUR) == -1); + ATF_CHECK(ftello(fp) == (off_t)t->n); + + ATF_CHECK(fclose(fp) == 0); + } + } +} + +ATF_TC(test11); +ATF_TC_HEAD(test11, tc) +{ + atf_tc_set_md_var(tc, "descr", "test11"); +} +ATF_TC_BODY(test11, tc) +{ + struct testcase *t; + off_t len, rest, i; + const char **p; + char buf[BUFSIZ]; + FILE *fp; + + /* test fmemopen_seek(SEEK_CUR) */ + for (t = &testcases[0]; t->s != NULL; ++t) { + len = (off_t)strnlen(t->s, t->n); + rest = (off_t)t->n - len; + for (p = &mode_a[0]; *p != NULL; ++p) { + + memcpy(&buf[0], t->s, t->n); + fp = fmemopen(&buf[0], t->n, *p); + ATF_CHECK(fp != NULL); +/* + * test fmemopen_seek(SEEK_CUR) + */ +#if defined(__GLIBC__) + if (i < (off_t)t->n) { +#endif + /* zero */ + ATF_CHECK(fseeko(fp, (off_t)0, SEEK_CUR) == 0); + ATF_CHECK(ftello(fp) == len); + + /* posive */ + for (i = (off_t)1; i <= rest; ++i) { + ATF_CHECK(fseeko(fp, (off_t)1, SEEK_CUR) == 0); + ATF_CHECK(ftello(fp) == len + i); + } + + /* positive + OOB */ + ATF_CHECK(fseeko(fp, (off_t)1, SEEK_CUR) == -1); + ATF_CHECK(ftello(fp) == (off_t)t->n); + + /* negative */ + for (i = (off_t)1; i <= (off_t)t->n; ++i) { + ATF_CHECK(fseeko(fp, (off_t)-1, SEEK_CUR) == 0); + ATF_CHECK(ftello(fp) == (off_t)t->n - i); + } + + /* negative + OOB */ + ATF_CHECK(fseeko(fp, (off_t)-1, SEEK_CUR) == -1); + ATF_CHECK(ftello(fp) == (off_t)0); + +#if defined(__GLIBC__) + } +#endif + ATF_CHECK(fclose(fp) == 0); + } + } +} + +ATF_TC(test12); +ATF_TC_HEAD(test12, tc) +{ + atf_tc_set_md_var(tc, "descr", "test12"); +} +ATF_TC_BODY(test12, tc) +{ + struct testcase *t; + off_t len, rest, i; + const char **p; + char buf[BUFSIZ]; + FILE *fp; + + /* test fmemopen_seek(SEEK_END) */ + for (t = &testcases[0]; t->s != NULL; ++t) { + len = (off_t)strnlen(t->s, t->n); + rest = t->n - len; + for (p = &mode_r[0]; *p != NULL; ++p) { + + memcpy(buf, t->s, t->n); + fp = fmemopen(&buf[0], t->n, *p); + ATF_CHECK(fp != NULL); + +/* + * test fmemopen_seek(SEEK_END) + */ +#if !defined(__GLIBC__) + ATF_CHECK(ftello(fp) == (off_t)0); + + /* zero */ + ATF_CHECK(fseeko(fp, (off_t)0, SEEK_END) == 0); + ATF_CHECK(ftello(fp) == len); + + /* positive + OOB */ + ATF_CHECK(fseeko(fp, rest + 1, SEEK_END) == -1); + ATF_CHECK(ftello(fp) == len); + + /* negative + OOB */ + ATF_CHECK(fseeko(fp, -(len + 1), SEEK_END) == -1); + ATF_CHECK(ftello(fp) == len); + + /* positive */ + for (i = 1; i <= rest; ++i) { + ATF_CHECK(fseeko(fp, i, SEEK_END) == 0); + ATF_CHECK(ftello(fp) == len + i); + } + + /* negative */ + for (i = 1; i < len; ++i) { + ATF_CHECK(fseeko(fp, -i, SEEK_END) == 0); + ATF_CHECK(ftello(fp) == len - i); + } +#endif + ATF_CHECK(fclose(fp) == 0); + } + } +} + +ATF_TC(test13); +ATF_TC_HEAD(test13, tc) +{ + atf_tc_set_md_var(tc, "descr", "test13"); +} +ATF_TC_BODY(test13, tc) +{ + struct testcase *t; + off_t len, rest, i; + const char **p; + char buf[BUFSIZ]; + FILE *fp; + + /* test fmemopen_seek(SEEK_END) */ + for (t = &testcases[0]; t->s != NULL; ++t) { + len = (off_t)strnlen(t->s, t->n); + rest = t->n - len; + for (p = &mode_w[0]; *p != NULL; ++p) { + + memcpy(buf, t->s, t->n); + fp = fmemopen(&buf[0], t->n, *p); + ATF_CHECK(fp != NULL); +/* + * test fmemopen_seek(SEEK_END) + */ +#if !defined(__GLIBC__) + ATF_CHECK(ftello(fp) == (off_t)0); + ATF_CHECK(buf[0] == '\0'); + + /* zero */ + ATF_CHECK(fseeko(fp, (off_t)0, SEEK_END) == 0); + ATF_CHECK(ftello(fp) == (off_t)0); + + /* positive + OOB */ + ATF_CHECK(fseeko(fp, (off_t)t->n + 1, SEEK_END) == -1); + ATF_CHECK(ftello(fp) == (off_t)0); + + /* negative + OOB */ + ATF_CHECK(fseeko(fp, -1, SEEK_END) == -1); + ATF_CHECK(ftello(fp) == (off_t)0); + + /* positive */ + for (i = 1; i <= t->n; ++i) { + ATF_CHECK(fseeko(fp, i, SEEK_END) == 0); + ATF_CHECK(ftello(fp) == i); + } +#endif + ATF_CHECK(fclose(fp) == 0); + } + } +} + +ATF_TC(test14); +ATF_TC_HEAD(test14, tc) +{ + atf_tc_set_md_var(tc, "descr", "test14"); +} +ATF_TC_BODY(test14, tc) +{ + struct testcase *t; + off_t len, rest, i; + const char **p; + char buf[BUFSIZ]; + FILE *fp; + + /* test fmemopen_seek(SEEK_END) */ + for (t = &testcases[0]; t->s != NULL; ++t) { + len = (off_t)strnlen(t->s, t->n); + rest = (off_t)t->n - len; + for (p = &mode_a[0]; *p != NULL; ++p) { + + memcpy(buf, t->s, t->n); + fp = fmemopen(&buf[0], t->n, *p); + ATF_CHECK(fp != NULL); +/* + * test fmemopen_seek(SEEK_END) + */ +#if !defined(__GLIBC__) + ATF_CHECK(ftello(fp) == len); + + /* zero */ + ATF_CHECK(fseeko(fp, 0, SEEK_END) == 0); + ATF_CHECK(ftello(fp) == len); + + /* positive + OOB */ + ATF_CHECK(fseeko(fp, rest + 1, SEEK_END) == -1); + ATF_CHECK(ftello(fp) == len); + + /* negative + OOB */ + ATF_CHECK(fseeko(fp, -(len + 1), SEEK_END) == -1); + ATF_CHECK(ftello(fp) == len); + + /* positive */ + for (i = 1; i <= rest; ++i) { + ATF_CHECK(fseeko(fp, i, SEEK_END) == 0); + ATF_CHECK(ftello(fp) == len + i); + } + + /* negative */ + for (i = 1; i < len; ++i) { + ATF_CHECK(fseeko(fp, -i, SEEK_END) == 0); + ATF_CHECK(ftello(fp) == len - i); + } +#endif + ATF_CHECK(fclose(fp) == 0); + } + } +} + +const char *mode_rw1[] = { + "r", "rb", "r+", "rb+", "r+b", + "w+", "wb+", + NULL +}; + +/* test15 - 18: + * When a stream open for writing is flushed or closed, a null byte is written + * at the current position or at the end of the buffer, depending on the size + * of the contents. + */ + +ATF_TC(test15); +ATF_TC_HEAD(test15, tc) +{ + atf_tc_set_md_var(tc, "descr", "test15"); +} +ATF_TC_BODY(test15, tc) +{ + struct testcase *t; + const char **p; + char buf0[BUFSIZ], buf1[BUFSIZ]; + FILE *fp; + size_t i; + + for (t = &testcases[0]; t->s != NULL; ++t) { + for (p = &mode_rw1[0]; *p != NULL; ++p) { + + memcpy(&buf0[0], t->s, t->n); + fp = fmemopen(&buf0[0], t->n, *p); + ATF_CHECK(fp != NULL); +/* + * test fmemopen_read + fgetc(3) + */ + for (i = (size_t)0; i < t->n; ++i) { + ATF_CHECK(ftello(fp) == (off_t)i); + ATF_CHECK(fgetc(fp) == buf0[i]); + ATF_CHECK(feof(fp) == 0); + ATF_CHECK(ftello(fp) == (off_t)i + 1); + } + ATF_CHECK(fgetc(fp) == EOF); + ATF_CHECK(feof(fp) != 0); + ATF_CHECK(ftello(fp) == (off_t)t->n); + ATF_CHECK(fclose(fp) == 0); + } + } +} + +ATF_TC(test16); +ATF_TC_HEAD(test16, tc) +{ + atf_tc_set_md_var(tc, "descr", "test16"); +} +ATF_TC_BODY(test16, tc) +{ + struct testcase *t; + const char **p; + char buf0[BUFSIZ], buf1[BUFSIZ]; + FILE *fp; + + for (t = &testcases[0]; t->s != NULL; ++t) { + for (p = &mode_rw1[0]; *p != NULL; ++p) { + + memcpy(&buf0[0], t->s, t->n); + buf1[t->n] = 0x1; + fp = fmemopen(&buf0[0], t->n, *p); + ATF_CHECK(fp != NULL); +/* + * test fmemopen_read + fread(4) + */ + ATF_CHECK(ftello(fp) == (off_t)0); + ATF_CHECK(fread(&buf1[0], 1, sizeof(buf1), fp) == t->n); + ATF_CHECK(feof(fp) != 0); + ATF_CHECK(memcmp(&buf0[0], &buf1[0], t->n) == 0); + ATF_CHECK((unsigned char)buf1[t->n] == 0x1); + + ATF_CHECK(fclose(fp) == 0); + } + } +} + +const char *mode_a1[] = { "a+", "ab+", NULL }; + +ATF_TC(test17); +ATF_TC_HEAD(test17, tc) +{ + atf_tc_set_md_var(tc, "descr", "test17"); +} +ATF_TC_BODY(test17, tc) +{ + struct testcase *t; + size_t len, i; + const char **p; + char buf[BUFSIZ]; + FILE *fp; + + for (t = &testcases[0]; t->s != NULL; ++t) { + len = strnlen(t->s, t->n); + for (p = &mode_a1[0]; *p != NULL; ++p) { + + memcpy(&buf[0], t->s, t->n); + fp = fmemopen(&buf[0], t->n, *p); + ATF_CHECK(fp != NULL); +/* + * test fmemopen_read + fgetc(3) + */ +#if defined(__GLIBC__) + if (i < t->n) { +#endif + for (i = len; i < t->n; ++i) { + ATF_CHECK(ftello(fp) == (off_t)i); + ATF_CHECK(fgetc(fp) == buf[i]); + ATF_CHECK(feof(fp) == 0); + ATF_CHECK(ftello(fp) == (off_t)i + 1); + } + ATF_CHECK(fgetc(fp) == EOF); + ATF_CHECK(feof(fp) != 0); + ATF_CHECK(ftello(fp) == (off_t)t->n); + rewind(fp); + for (i = (size_t)0; i < t->n; ++i) { + ATF_CHECK(ftello(fp) == (off_t)i); + ATF_CHECK(fgetc(fp) == buf[i]); + ATF_CHECK(feof(fp) == 0); + ATF_CHECK(ftello(fp) == (off_t)i + 1); + } + ATF_CHECK(fgetc(fp) == EOF); + ATF_CHECK(feof(fp) != 0); + ATF_CHECK(ftello(fp) == (off_t)t->n); +#if defined(__GLIBC__) + } +#endif + ATF_CHECK(fclose(fp) == 0); + } + } +} + +ATF_TC(test18); +ATF_TC_HEAD(test18, tc) +{ + atf_tc_set_md_var(tc, "descr", "test18"); +} +ATF_TC_BODY(test18, tc) +{ + struct testcase *t; + size_t len, i; + const char **p; + char buf0[BUFSIZ], buf1[BUFSIZ]; + FILE *fp; + + for (t = &testcases[0]; t->s != NULL; ++t) { + len = strnlen(t->s, t->n); + for (p = &mode_a1[0]; *p != NULL; ++p) { + + memcpy(&buf0[0], t->s, t->n); + buf1[t->n - len] = 0x1; + fp = fmemopen(&buf0[0], t->n, *p); + ATF_CHECK(fp != NULL); +/* + * test fmemopen_read + fread(3) + */ +#if defined(__GLIBC__) + if (i < t->n) { +#endif + ATF_CHECK(ftello(fp) == (off_t)len); + ATF_CHECK(fread(&buf1[0], 1, sizeof(buf1), fp) + == t->n - len); + ATF_CHECK(feof(fp) != 0); + ATF_CHECK(!memcmp(&buf0[len], &buf1[0], t->n - len)); + ATF_CHECK((unsigned char)buf1[t->n - len] == 0x1); + rewind(fp); + buf1[t->n] = 0x1; + ATF_CHECK(ftello(fp) == (off_t)0); + ATF_CHECK(fread(&buf1[0], 1, sizeof(buf1), fp) + == t->n); + ATF_CHECK(feof(fp) != 0); + ATF_CHECK(!memcmp(&buf0[0], &buf1[0], t->n)); + ATF_CHECK((unsigned char)buf1[t->n] == 0x1); +#if defined(__GLIBC__) + } +#endif + ATF_CHECK(fclose(fp) == 0); + } + } +} + +/* + * test19 - test22: + * If a stream open for update is flushed or closed and the last write has + * advanced the current buffer size, a null byte is written at the end of the + * buffer if it fits. + */ + +const char *mode_rw2[] = { + "r+", "rb+", "r+b", + "w", "wb", "w+", "wb+", "w+b", + NULL +}; + +ATF_TC(test19); +ATF_TC_HEAD(test19, tc) +{ + atf_tc_set_md_var(tc, "descr", "test19"); +} +ATF_TC_BODY(test19, tc) +{ + struct testcase *t; + size_t len, i; + const char **p; + char buf[BUFSIZ]; + FILE *fp; + + for (t = &testcases[0]; t->s != NULL; ++t) { + len = strnlen(t->s, t->n); + for (p = &mode_rw2[0]; *p != NULL; ++p) { + + memcpy(&buf[0], t->s, t->n); + buf[t->n] = 0x1; + fp = fmemopen(&buf[0], t->n + 1, *p); + ATF_CHECK(fp != NULL); + setbuf(fp, NULL); +/* + * test fmemopen_write + fputc(3) + */ + for (i = (size_t)0; i < t->n; ++i) { + ATF_CHECK(ftello(fp) == (off_t)i); + ATF_CHECK(fputc(t->s[i], fp) == t->s[i]); + ATF_CHECK(buf[i] == t->s[i]); + ATF_CHECK(ftello(fp) == (off_t)i + 1); + ATF_CHECK(buf[i] == t->s[i]); +#if !defined(__GLIBC__) + ATF_CHECK(buf[i + 1] == '\0'); +#endif + } + +/* don't accept non nul character at end of buffer */ + ATF_CHECK(fputc(0x1, fp) == EOF); + ATF_CHECK(ftello(fp) == (off_t)t->n); + ATF_CHECK(feof(fp) == 0); + +/* accept nul character at end of buffer */ + ATF_CHECK(fputc('\0', fp) == '\0'); + ATF_CHECK(ftello(fp) == (off_t)t->n + 1); + ATF_CHECK(feof(fp) == 0); + +/* reach EOF */ + ATF_CHECK(fputc('\0', fp) == EOF); + ATF_CHECK(ftello(fp) == (off_t)t->n + 1); + + /* compare */ + ATF_CHECK(memcmp(&buf[0], t->s, t->n) == 0); + ATF_CHECK(buf[t->n] == '\0'); + + ATF_CHECK(fclose(fp) == 0); + } + } +} + +ATF_TC(test20); +ATF_TC_HEAD(test20, tc) +{ + atf_tc_set_md_var(tc, "descr", "test20"); +} +ATF_TC_BODY(test20, tc) +{ + struct testcase *t; + size_t len, i; + const char **p; + char buf[BUFSIZ]; + FILE *fp; + + for (t = &testcases[0]; t->s != NULL; ++t) { + len = strnlen(t->s, t->n); + for (p = &mode_rw2[0]; *p != NULL; ++p) { + + memcpy(&buf[0], t->s, t->n); + buf[t->n] = 0x1; + fp = fmemopen(&buf[0], t->n + 1, *p); + ATF_CHECK(fp != NULL); + setbuf(fp, NULL); + ATF_CHECK(fwrite(t->s, 1, t->n, fp) == t->n); +/* + * test fmemopen_write + fwrite(3) + */ +#if !defined(__GLIBC__) + ATF_CHECK(buf[t->n] == '\0'); + +/* don't accept non nul character at end of buffer */ + ATF_CHECK(fwrite("\x1", 1, 1, fp) == 0); + ATF_CHECK(ftello(fp) == (off_t)t->n); + ATF_CHECK(feof(fp) == 0); +#endif + +/* accept nul character at end of buffer */ + ATF_CHECK(fwrite("\x0", 1, 1, fp) == 1); + ATF_CHECK(ftello(fp) == (off_t)t->n + 1); + ATF_CHECK(feof(fp) == 0); + +/* reach EOF */ + ATF_CHECK(fputc('\0', fp) == EOF); + ATF_CHECK(ftello(fp) == (off_t)t->n + 1); + +/* compare */ + ATF_CHECK(memcmp(&buf[0], t->s, t->n) == 0); + ATF_CHECK(buf[t->n] == '\0'); + + ATF_CHECK(fclose(fp) == 0); + } + } +} + +ATF_TC(test21); +ATF_TC_HEAD(test21, tc) +{ + atf_tc_set_md_var(tc, "descr", "test21"); +} +ATF_TC_BODY(test21, tc) +{ + struct testcase *t; + size_t len, i; + const char **p; + char buf[BUFSIZ]; + FILE *fp; + + for (t = &testcases[0]; t->s != NULL; ++t) { + len = strnlen(t->s, t->n); + for (p = &mode_a[0]; *p != NULL; ++p) { + memcpy(&buf[0], t->s, t->n); + fp = fmemopen(&buf[0], t->n, *p); + ATF_CHECK(fp != NULL); + setbuf(fp, NULL); +/* + * test fmemopen_write + fputc(3) + */ + if (len < t->n) { + for (i = len; i < t->n - 1; ++i) { + ATF_CHECK(ftello(fp) == (off_t)i); + ATF_CHECK(fputc(t->s[i - len], fp) + == t->s[i - len]); + ATF_CHECK(buf[i] == t->s[i - len]); + ATF_CHECK(ftello(fp) == (off_t)i + 1); +#if !defined(__GLIBC__) + ATF_CHECK(buf[i + 1] == '\0'); +#endif + } + +/* don't accept non nul character at end of buffer */ + ATF_CHECK(ftello(fp) == (off_t)t->n - 1); + ATF_CHECK(fputc(0x1, fp) == EOF); + ATF_CHECK(ftello(fp) == (off_t)t->n - 1); + +/* accept nul character at end of buffer */ + ATF_CHECK(ftello(fp) == (off_t)t->n - 1); + ATF_CHECK(fputc('\0', fp) == '\0'); + ATF_CHECK(ftello(fp) == (off_t)t->n); + } + +/* reach EOF */ + ATF_CHECK(ftello(fp) == (off_t)t->n); + ATF_CHECK(fputc('\0', fp) == EOF); + ATF_CHECK(ftello(fp) == (off_t)t->n); + + ATF_CHECK(fclose(fp) == 0); + } + } +} + +ATF_TC(test22); +ATF_TC_HEAD(test22, tc) +{ + atf_tc_set_md_var(tc, "descr", "test22"); +} +ATF_TC_BODY(test22, tc) +{ + struct testcase *t0, *t1; + size_t len0, len1, i, nleft; + const char **p; + char buf[BUFSIZ]; + FILE *fp; + + for (t0 = &testcases[0]; t0->s != NULL; ++t0) { + len0 = strnlen(t0->s, t0->n); + for (t1 = &testcases[0]; t1->s != NULL; ++t1) { + len1 = strnlen(t1->s, t1->n); + for (p = &mode_a[0]; *p != NULL; ++p) { + + memcpy(&buf[0], t0->s, t0->n); + fp = fmemopen(&buf[0], t0->n, *p); + ATF_CHECK(fp != NULL); + setbuf(fp, NULL); +/* + * test fmemopen_write + fwrite(3) + */ + nleft = t0->n - len0; +#if !defined(__GLIBC__) + if (nleft == 0 || len1 == nleft - 1) { + ATF_CHECK(fwrite(t1->s, 1, t1->n, fp) + == nleft); + ATF_CHECK(ftell(fp) == t1->n); + } else { + ATF_CHECK(fwrite(t1->s, 1, t1->n, fp) + == nleft - 1); + ATF_CHECK(ftell(fp) == t1->n - 1); + } +#endif + ATF_CHECK(fclose(fp) == 0); + } + } + } +} + +ATF_TP_ADD_TCS(tp) +{ + ATF_TP_ADD_TC(tp, test00); + ATF_TP_ADD_TC(tp, test01); + ATF_TP_ADD_TC(tp, test02); + ATF_TP_ADD_TC(tp, test03); + ATF_TP_ADD_TC(tp, test04); + ATF_TP_ADD_TC(tp, test05); + ATF_TP_ADD_TC(tp, test06); + ATF_TP_ADD_TC(tp, test07); + ATF_TP_ADD_TC(tp, test08); + ATF_TP_ADD_TC(tp, test09); + ATF_TP_ADD_TC(tp, test10); + ATF_TP_ADD_TC(tp, test11); + ATF_TP_ADD_TC(tp, test12); + ATF_TP_ADD_TC(tp, test13); + ATF_TP_ADD_TC(tp, test14); + ATF_TP_ADD_TC(tp, test15); + ATF_TP_ADD_TC(tp, test16); + ATF_TP_ADD_TC(tp, test17); + ATF_TP_ADD_TC(tp, test18); + ATF_TP_ADD_TC(tp, test19); + ATF_TP_ADD_TC(tp, test20); + ATF_TP_ADD_TC(tp, test21); + ATF_TP_ADD_TC(tp, test22); + + return atf_no_error(); +}