summaryrefslogtreecommitdiffstats
path: root/lib/libc/stdio/open_memstream.c
diff options
context:
space:
mode:
authormpi <mpi@openbsd.org>2013-03-27 15:06:25 +0000
committermpi <mpi@openbsd.org>2013-03-27 15:06:25 +0000
commit03222a19d59515768073c8f9639997d8c0c4da0b (patch)
treeaebd022e89cf4040dc9c9b13d536d8d856528b3d /lib/libc/stdio/open_memstream.c
parentRewrite the work unit handling code in the RAID 1/4/5/6 interrupt handlers. (diff)
downloadwireguard-openbsd-03222a19d59515768073c8f9639997d8c0c4da0b.tar.xz
wireguard-openbsd-03222a19d59515768073c8f9639997d8c0c4da0b.zip
Add an open_wmemstream(3) implementation and fix various issues for
fmemopen(3) and open_memstream(3). With inputs from millert@, stsp@, guenther@, tedu@ and matthew@
Diffstat (limited to 'lib/libc/stdio/open_memstream.c')
-rw-r--r--lib/libc/stdio/open_memstream.c59
1 files changed, 25 insertions, 34 deletions
diff --git a/lib/libc/stdio/open_memstream.c b/lib/libc/stdio/open_memstream.c
index 48ae2900f6d..bd96874e959 100644
--- a/lib/libc/stdio/open_memstream.c
+++ b/lib/libc/stdio/open_memstream.c
@@ -1,4 +1,5 @@
-/* $OpenBSD: open_memstream.c,v 1.1 2013/01/01 17:41:13 mpi Exp $ */
+/* $OpenBSD: open_memstream.c,v 1.2 2013/03/27 15:06:25 mpi Exp $ */
+
/*
* Copyright (c) 2011 Martin Pieuchot <mpi@openbsd.org>
*
@@ -15,8 +16,11 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include <sys/param.h>
+
#include <errno.h>
#include <fcntl.h>
+#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -27,7 +31,7 @@ struct state {
char **pbuf; /* point to the stream */
size_t *psize; /* point to min(pos, len) */
size_t pos; /* current position */
- size_t size; /* allocated size */
+ size_t size; /* number of allocated char */
size_t len; /* length of the data */
};
@@ -35,15 +39,17 @@ static int
memstream_write(void *v, const char *b, int l)
{
struct state *st = v;
- int i;
char *p;
+ size_t i, end;
- if (st->pos + l >= st->size) {
+ end = (st->pos + l);
+
+ if (end >= st->size) {
/* 1.6 is (very) close to the golden ratio. */
size_t sz = st->size * 8 / 5;
- if (sz < st->pos + l + 1)
- sz = st->pos + l + 1;
+ if (sz < end + 1)
+ sz = end + 1;
p = realloc(st->string, sz);
if (!p)
return (-1);
@@ -54,7 +60,7 @@ memstream_write(void *v, const char *b, int l)
for (i = 0; i < l; i++)
st->string[st->pos + i] = b[i];
- st->pos += i;
+ st->pos += l;
if (st->pos > st->len) {
st->len = st->pos;
@@ -67,52 +73,41 @@ memstream_write(void *v, const char *b, int l)
}
static fpos_t
-memstream_seek(void *v, fpos_t pos, int w)
+memstream_seek(void *v, fpos_t off, int whence)
{
struct state *st = v;
- char *p;
+ ssize_t base = 0;
- switch (w) {
+ switch (whence) {
case SEEK_SET:
break;
case SEEK_CUR:
- pos += st->pos;
+ base = st->pos;
break;
case SEEK_END:
- pos += st->len;
+ base = st->len;
break;
- default:
- errno = EINVAL;
- return (-1);
}
- if (pos < 0)
+ if (off > SIZE_MAX - base || off < -base) {
+ errno = EOVERFLOW;
return (-1);
+ }
- st->pos = pos;
-
- if (st->pos < st->len)
- *st->psize = st->pos;
- else
- *st->psize = st->len;
+ st->pos = base + off;
+ *st->psize = MIN(st->pos, st->len);
- return (pos);
+ return (st->pos);
}
static int
memstream_close(void *v)
{
struct state *st = v;
- char *p;
-#define MIN(x, y) (((x) < (y)) ? (x) : (y))
-
- *st->psize = MIN(st->pos, st->len);
- *st->pbuf = st->string;
free(st);
return (0);
-#undef MIN
}
FILE *
@@ -134,11 +129,7 @@ open_memstream(char **pbuf, size_t *psize)
return (NULL);
}
- if (*psize < 128)
- st->size = 128;
- else
- st->size = *psize;
-
+ st->size = BUFSIZ;
if ((st->string = calloc(1, st->size)) == NULL) {
free(st);
fp->_flags = 0;