<pre style='margin:0'>
Christopher Nielsen (mascguy) pushed a commit to branch master
in repository macports-legacy-support.
</pre>
<p><a href="https://github.com/macports/macports-legacy-support/commit/0b67cf1c08831cc54340b7be7c6ec0ad774b91cf">https://github.com/macports/macports-legacy-support/commit/0b67cf1c08831cc54340b7be7c6ec0ad774b91cf</a></p>
<pre style="white-space: pre; background: #F8F8F8">The following commit(s) were added to refs/heads/master by this push:
<span style='display:block; white-space:pre;color:#404040;'> new 0b67cf1 stdio.h: add fmemopen (OS X < 10.13) - Credit: FreeBSD Project - License: BSD See: https://trac.macports.org/ticket/63785
</span>0b67cf1 is described below
<span style='display:block; white-space:pre;color:#808000;'>commit 0b67cf1c08831cc54340b7be7c6ec0ad774b91cf
</span>Author: Christopher Nielsen <mascguy@github.com>
AuthorDate: Tue Jul 4 14:23:55 2023 -0400
<span style='display:block; white-space:pre;color:#404040;'> stdio.h: add fmemopen (OS X < 10.13)
</span><span style='display:block; white-space:pre;color:#404040;'> - Credit: FreeBSD Project
</span><span style='display:block; white-space:pre;color:#404040;'> - License: BSD
</span><span style='display:block; white-space:pre;color:#404040;'> See: https://trac.macports.org/ticket/63785
</span>---
README.md | 2 +-
include/MacportsLegacySupport.h | 3 +
include/stdio.h | 9 ++
src/fmemopen.c | 260 +++++++++++++++++++++++++++++++++++
test/test_fmemopen.c | 298 ++++++++++++++++++++++++++++++++++++++++
5 files changed, 571 insertions(+), 1 deletion(-)
<span style='display:block; white-space:pre;color:#808080;'>diff --git a/README.md b/README.md
</span><span style='display:block; white-space:pre;color:#808080;'>index c271050..d7dce54 100644
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>--- a/README.md
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>+++ b/README.md
</span><span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -71,7 +71,7 @@ Wrapped headers and replaced functions are:
</span> <tr>
<td><code>stdio.h</code></td>
<td>Adds <code>dprintf</code>, <code>getline</code>, <code>getdelim</code>,
<span style='display:block; white-space:pre;background:#ffe0e0;'>- and <code>open_memstream</code> functions</td>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ <code>open_memstream</code>, and <code>fmemopen</code> functions</td>
</span> <td>OSX10.6, OSX10.12 (open_memstream)</td>
</tr>
<tr>
<span style='display:block; white-space:pre;color:#808080;'>diff --git a/include/MacportsLegacySupport.h b/include/MacportsLegacySupport.h
</span><span style='display:block; white-space:pre;color:#808080;'>index 98c58ea..ede0f6f 100644
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>--- a/include/MacportsLegacySupport.h
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>+++ b/include/MacportsLegacySupport.h
</span><span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -154,6 +154,9 @@
</span> /* open_memstream */
#define __MP_LEGACY_SUPPORT_OPEN_MEMSTREAM__ (__APPLE__ && __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 101300)
<span style='display:block; white-space:pre;background:#e0ffe0;'>+/* fmemopen */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#define __MP_LEGACY_SUPPORT_FMEMOPEN__ (__APPLE__ && __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 101300)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span> /* pthread_setname_np */
#define __MP_LEGACY_SUPPORT_PTHREAD_SETNAME_NP__ (__APPLE__ && __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 1060)
<span style='display:block; white-space:pre;color:#808080;'>diff --git a/include/stdio.h b/include/stdio.h
</span><span style='display:block; white-space:pre;color:#808080;'>index e3e3897..3ddd718 100644
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>--- a/include/stdio.h
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>+++ b/include/stdio.h
</span><span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -67,6 +67,15 @@ __MP__END_DECLS
</span>
#endif /* __MP_LEGACY_SUPPORT_OPEN_MEMSTREAM__ */
<span style='display:block; white-space:pre;background:#e0ffe0;'>+/* fmemopen */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#if __MP_LEGACY_SUPPORT_FMEMOPEN__
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+__MP__BEGIN_DECLS
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+FILE *fmemopen(void *buf, size_t size, const char *mode);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+__MP__END_DECLS
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#endif /* __MP_LEGACY_SUPPORT_FMEMOPEN__ */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span> /* renameat */
#if __MP_LEGACY_SUPPORT_ATCALLS__
<span style='display:block; white-space:pre;color:#808080;'>diff --git a/src/fmemopen.c b/src/fmemopen.c
</span>new file mode 100644
<span style='display:block; white-space:pre;color:#808080;'>index 0000000..b040693
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>--- /dev/null
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>+++ b/src/fmemopen.c
</span><span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -0,0 +1,260 @@
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+/*-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * Copyright (C) 2013 Pietro Cerutti <gahr@FreeBSD.org>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ *
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * Redistribution and use in source and binary forms, with or without
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * modification, are permitted provided that the following conditions
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * are met:
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * 1. Redistributions of source code must retain the above copyright
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * notice, this list of conditions and the following disclaimer.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * 2. Redistributions in binary form must reproduce the above copyright
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * notice, this list of conditions and the following disclaimer in the
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * documentation and/or other materials provided with the distribution.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ *
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * SUCH DAMAGE.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#include <sys/cdefs.h>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#include <fcntl.h>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#include <stdbool.h>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#include <stdio.h>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#include <stdlib.h>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#include <string.h>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#include <errno.h>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+struct fmemopen_cookie
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+{
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ char *buf; /* pointer to the memory region */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ bool own; /* did we allocate the buffer ourselves? */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ char bin; /* is this a binary buffer? */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ size_t size; /* buffer length in bytes */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ size_t len; /* data length in bytes */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ size_t off; /* current offset into the buffer */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+};
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+static int fmemopen_read(void *cookie, char *buf, int nbytes);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+static int fmemopen_write(void *cookie, const char *buf, int nbytes);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+static fpos_t fmemopen_seek(void *cookie, fpos_t offset, int whence);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+static int fmemopen_close(void *cookie);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+FILE *
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+fmemopen(void * __restrict buf, size_t size, const char * __restrict mode)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+{
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ struct fmemopen_cookie *ck;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ FILE *f;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ int flags, rc;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ /*
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * POSIX says we shall return EINVAL if size is 0.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ if (size == 0) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ errno = EINVAL;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ return (NULL);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ /*
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * Retrieve the flags as used by open(2) from the mode argument, and
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * validate them.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ rc = __sflags(mode, &flags);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ if (rc == 0) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ errno = EINVAL;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ return (NULL);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ /*
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * There's no point in requiring an automatically allocated buffer
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * in write-only mode.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ if (!(flags & O_RDWR) && buf == NULL) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ errno = EINVAL;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ return (NULL);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ ck = malloc(sizeof(struct fmemopen_cookie));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ if (ck == NULL) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ return (NULL);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ ck->off = 0;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ ck->size = size;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ /* Check whether we have to allocate the buffer ourselves. */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ ck->own = ((ck->buf = buf) == NULL);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ if (ck->own) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ ck->buf = malloc(size);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ if (ck->buf == NULL) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ free(ck);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ return (NULL);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ /*
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * POSIX distinguishes between w+ and r+, in that w+ is supposed to
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * truncate the buffer.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ if (ck->own || mode[0] == 'w') {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ ck->buf[0] = '\0';
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ /* Check for binary mode. */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ ck->bin = strchr(mode, 'b') != NULL;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ /*
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * The size of the current buffer contents is set depending on the
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * mode:
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ *
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * for append (text-mode), the position of the first NULL byte, or the
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * size of the buffer if none is found
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ *
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * for append (binary-mode), the size of the buffer
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ *
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * for read, the size of the buffer
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ *
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * for write, 0
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ switch (mode[0]) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ case 'a':
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ ck->off = ck->len = strnlen(ck->buf, ck->size);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ break;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ case 'r':
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ ck->len = size;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ break;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ case 'w':
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ ck->len = 0;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ break;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ f = funopen(ck,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ flags & O_WRONLY ? NULL : fmemopen_read,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ flags & O_RDONLY ? NULL : fmemopen_write,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ fmemopen_seek, fmemopen_close);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ if (f == NULL) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ if (ck->own)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ free(ck->buf);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ free(ck);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ return (NULL);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ if (mode[0] == 'a')
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ f->_flags |= __SAPP;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ /*
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * Turn off buffering, so a write past the end of the buffer
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * correctly returns a short object count.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ setvbuf(f, NULL, _IONBF, 0);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ return (f);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+static int
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+fmemopen_read(void *cookie, char *buf, int nbytes)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+{
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ struct fmemopen_cookie *ck = cookie;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ if (nbytes > ck->len - ck->off)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ nbytes = ck->len - ck->off;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ if (nbytes == 0)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ return (0);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ memcpy(buf, ck->buf + ck->off, nbytes);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ ck->off += nbytes;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ return (nbytes);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+static int
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+fmemopen_write(void *cookie, const char *buf, int nbytes)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+{
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ struct fmemopen_cookie *ck = cookie;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ if (nbytes > ck->size - ck->off)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ nbytes = ck->size - ck->off;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ if (nbytes == 0)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ return (0);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ memcpy(ck->buf + ck->off, buf, nbytes);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ ck->off += nbytes;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ if (ck->off > ck->len)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ ck->len = ck->off;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ /*
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * We append a NULL byte if all these conditions are met:
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * - the buffer is not binary
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * - the buffer is not full
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * - the data just written doesn't already end with a NULL byte
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ if (!ck->bin && ck->off < ck->size && ck->buf[ck->off - 1] != '\0')
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ ck->buf[ck->off] = '\0';
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ return (nbytes);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+static fpos_t
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+fmemopen_seek(void *cookie, fpos_t offset, int whence)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+{
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ struct fmemopen_cookie *ck = cookie;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ switch (whence) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ case SEEK_SET:
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ if (offset > ck->size) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ errno = EINVAL;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ return (-1);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ ck->off = offset;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ break;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ case SEEK_CUR:
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ if (ck->off + offset > ck->size) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ errno = EINVAL;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ return (-1);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ ck->off += offset;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ break;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ case SEEK_END:
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ if (offset > 0 || -offset > ck->len) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ errno = EINVAL;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ return (-1);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ ck->off = ck->len + offset;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ break;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ default:
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ errno = EINVAL;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ return (-1);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ return (ck->off);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+static int
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+fmemopen_close(void *cookie)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+{
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ struct fmemopen_cookie *ck = cookie;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ if (ck->own)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ free(ck->buf);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ free(ck);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ return (0);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+}
</span><span style='display:block; white-space:pre;color:#808080;'>diff --git a/test/test_fmemopen.c b/test/test_fmemopen.c
</span>new file mode 100644
<span style='display:block; white-space:pre;color:#808080;'>index 0000000..f7be90a
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>--- /dev/null
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>+++ b/test/test_fmemopen.c
</span><span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -0,0 +1,298 @@
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+/*-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+Copyright (C) 2013 Pietro Cerutti <gahr@FreeBSD.org>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+Redistribution and use in source and binary forms, with or without
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+modification, are permitted provided that the following conditions
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+are met:
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+1. Redistributions of source code must retain the above copyright
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ notice, this list of conditions and the following disclaimer.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+2. Redistributions in binary form must reproduce the above copyright
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ notice, this list of conditions and the following disclaimer in the
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ documentation and/or other materials provided with the distribution.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+SUCH DAMAGE.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+*/
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+/*
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * Test basic FILE * functions (fread, fwrite, fseek, fclose) against
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * a FILE * retrieved using fmemopen()
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#include <sys/cdefs.h>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#include <assert.h>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#include <errno.h>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#include <stdio.h>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#include <string.h>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#include <strings.h>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+void
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+test_preexisting()
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+{
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ /*
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * Use a pre-existing buffer.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ char buf[512];
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ char buf2[512];
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ char str[] = "Test writing some stuff";
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ char str2[] = "AAAAAAAAA";
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ char str3[] = "AAAA writing some stuff";
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ FILE *fp;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ size_t nofw, nofr;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ int rc;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ /* Open a FILE * using fmemopen. */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ fp = fmemopen(buf, sizeof(buf), "w");
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ assert(fp != NULL);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ /* Write to the buffer. */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ nofw = fwrite(str, 1, sizeof(str), fp);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ assert(nofw == sizeof(str));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ /* Close the FILE *. */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ rc = fclose(fp);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ assert(rc == 0);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ /* Re-open the FILE * to read back the data. */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ fp = fmemopen(buf, sizeof(buf), "r");
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ assert(fp != NULL);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ /* Read from the buffer. */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ bzero(buf2, sizeof(buf2));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ nofr = fread(buf2, 1, sizeof(buf2), fp);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ assert(nofr == sizeof(buf2));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ /*
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * Since a write on a FILE * retrieved by fmemopen
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * will add a '\0' (if there's space), we can check
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * the strings for equality.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ assert(strcmp(str, buf2) == 0);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ /* Close the FILE *. */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ rc = fclose(fp);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ assert(rc == 0);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ /* Now open a FILE * on the first 4 bytes of the string. */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ fp = fmemopen(str, 4, "w");
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ assert(fp != NULL);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ /*
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * Try to write more bytes than we shoud, we'll get a short count (4).
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ nofw = fwrite(str2, 1, sizeof(str2), fp);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ assert(nofw == 4);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ /* Close the FILE *. */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ rc = fclose(fp);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ /* Check that the string was not modified after the first 4 bytes. */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ assert(strcmp(str, str3) == 0);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+void
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+test_autoalloc()
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+{
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ /*
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * Let fmemopen allocate the buffer.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ char str[] = "A quick test";
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ FILE *fp;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ long pos;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ size_t nofw, nofr, i;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ int rc;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ /* Open a FILE * using fmemopen. */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ fp = fmemopen(NULL, 512, "w+");
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ assert(fp != NULL);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ /* fill the buffer */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ for (i = 0; i < 512; i++) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ nofw = fwrite("a", 1, 1, fp);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ assert(nofw == 1);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ /* Get the current position into the stream. */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ pos = ftell(fp);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ assert(pos == 512);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ /*
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * Try to write past the end, we should get a short object count (0)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ nofw = fwrite("a", 1, 1, fp);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ assert(nofw == 0);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ /* Close the FILE *. */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ rc = fclose(fp);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ assert(rc == 0);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ /* Open a FILE * using a wrong mode */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ fp = fmemopen(NULL, 512, "r");
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ assert(fp == NULL);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ fp = fmemopen(NULL, 512, "w");
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ assert(fp == NULL);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+void
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+test_data_length()
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+{
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ /*
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * Here we test that a read operation doesn't go past the end of the
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * data actually written, and that a SEEK_END seeks from the end of the
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * data, not of the whole buffer.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ FILE *fp;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ char buf[512] = {'\0'};
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ char str[] = "Test data length. ";
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ char str2[] = "Do we have two sentences?";
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ char str3[sizeof(str) + sizeof(str2) -1];
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ long pos;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ size_t nofw, nofr;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ int rc;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ /* Open a FILE * for updating our buffer. */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ fp = fmemopen(buf, sizeof(buf), "w+");
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ assert(fp != NULL);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ /* Write our string into the buffer. */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ nofw = fwrite(str, 1, sizeof(str), fp);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ assert(nofw == sizeof(str));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ /*
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * Now seek to the end and check that ftell
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * gives us sizeof(str).
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ rc = fseek(fp, 0, SEEK_END);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ assert(rc == 0);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ pos = ftell(fp);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ assert(pos == sizeof(str));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ /* Close the FILE *. */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ rc = fclose(fp);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ assert(rc == 0);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ /* Reopen the buffer for appending. */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ fp = fmemopen(buf, sizeof(buf), "a+");
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ assert(fp != NULL);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ /* We should now be writing after the first string. */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ nofw = fwrite(str2, 1, sizeof(str2), fp);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ assert(nofw == sizeof(str2));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ /* Rewind the FILE *. */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ rc = fseek(fp, 0, SEEK_SET);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ assert(rc == 0);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ /* Make sure we're at the beginning. */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ pos = ftell(fp);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ assert(pos == 0);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ /* Read the whole buffer. */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ nofr = fread(str3, 1, sizeof(buf), fp);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ assert(nofr == sizeof(str3));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ /* Make sure the two strings are there. */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ assert(strncmp(str3, str, sizeof(str) - 1) == 0);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ assert(strncmp(str3 + sizeof(str) - 1, str2, sizeof(str2)) == 0);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ /* Close the FILE *. */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ rc = fclose(fp);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ assert(rc == 0);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+void
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+test_binary()
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+{
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ /*
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * Make sure that NULL bytes are never appended when opening a buffer
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * in binary mode.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ FILE *fp;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ char buf[20];
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ char str[] = "Test";
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ size_t nofw;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ int rc, i;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ /* Pre-fill the buffer. */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ memset(buf, 'A', sizeof(buf));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ /* Open a FILE * in binary mode. */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ fp = fmemopen(buf, sizeof(buf), "w+b");
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ assert(fp != NULL);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ /* Write some data into it. */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ nofw = fwrite(str, 1, strlen(str), fp);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ assert(nofw == strlen(str));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ /* Make sure that the buffer doesn't contain any NULL bytes. */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ for (i = 0; i < sizeof(buf); i++)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ assert(buf[i] != '\0');
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ /* Close the FILE *. */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ rc = fclose(fp);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ assert(rc == 0);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+void
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+test_append_binary_pos()
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+{
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ /*
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * For compatibility with other implementations (glibc), we set the
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * position to 0 when opening an automatically allocated binary stream
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * for appending.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ FILE *fp;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ fp = fmemopen(NULL, 16, "ab+");
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ assert(ftell(fp) == 0L);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ fclose(fp);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ /*
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * Make sure that a pre-allocated buffer behaves correctly.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ char buf[] = "Hello";
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ fp = fmemopen(buf, sizeof(buf), "ab+");
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ assert(ftell(fp) == strlen(buf));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ fclose(fp);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+void
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+test_size_0()
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+{
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ /*
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * POSIX mandates that we return EINVAL if size is 0.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ FILE *fp;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ fp = fmemopen(NULL, 0, "r+");
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ assert(fp == NULL);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ assert(errno == EINVAL);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+int
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+main(void)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+{
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ test_autoalloc();
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ test_preexisting();
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ test_data_length();
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ test_binary();
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ test_append_binary_pos();
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ test_size_0();
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ return (0);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+}
</span></pre><pre style='margin:0'>
</pre>