summaryrefslogtreecommitdiffstats
path: root/lib/libc/stdio/fmemopen.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/fmemopen.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/fmemopen.c')
-rw-r--r--lib/libc/stdio/fmemopen.c39
1 files changed, 18 insertions, 21 deletions
diff --git a/lib/libc/stdio/fmemopen.c b/lib/libc/stdio/fmemopen.c
index fd76f625b23..8cda0476340 100644
--- a/lib/libc/stdio/fmemopen.c
+++ b/lib/libc/stdio/fmemopen.c
@@ -1,4 +1,5 @@
-/* $OpenBSD: fmemopen.c,v 1.1 2013/01/01 17:41:13 mpi Exp $ */
+/* $OpenBSD: fmemopen.c,v 1.2 2013/03/27 15:06:25 mpi Exp $ */
+
/*
* Copyright (c) 2011 Martin Pieuchot <mpi@openbsd.org>
* Copyright (c) 2009 Ted Unangst
@@ -20,6 +21,7 @@
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
#include "local.h"
struct state {
@@ -27,6 +29,7 @@ struct state {
size_t pos; /* current position */
size_t size; /* allocated size */
size_t len; /* length of the data */
+ int update; /* open for update */
};
static int
@@ -55,44 +58,40 @@ fmemopen_write(void *v, const char *b, int l)
if (st->pos >= st->len) {
st->len = st->pos;
- if (st->len == st->size)
- st->string[st->len - 1] = '\0';
- else
+ if (st->len < st->size)
st->string[st->len] = '\0';
+ else if (!st->update)
+ st->string[st->size - 1] = '\0';
}
return (i);
}
static fpos_t
-fmemopen_seek(void *v, fpos_t pos, int whence)
+fmemopen_seek(void *v, fpos_t off, int whence)
{
struct state *st = v;
+ ssize_t base = 0;
switch (whence) {
case SEEK_SET:
break;
case SEEK_CUR:
- pos += st->pos;
+ base = st->pos;
break;
case SEEK_END:
- /*
- * XXX The standard is not clear about where to seek
- * from the end of the data or the end of the buffer.
- */
- pos += st->len;
+ base = st->len;
break;
- default:
- errno = EINVAL;
- return (-1);
}
- if (pos < 0 || pos > st->size)
+ if (off > st->size - base || off < -base) {
+ errno = EOVERFLOW;
return (-1);
+ }
- st->pos = pos;
+ st->pos = base + off;
- return (pos);
+ return (st->pos);
}
static int
@@ -145,8 +144,9 @@ fmemopen(void *buf, size_t size, const char *mode)
}
st->pos = 0;
- st->len = 0;
+ st->len = (oflags & O_WRONLY) ? 0 : size;
st->size = size;
+ st->update = oflags & O_RDWR;
if (buf == NULL) {
if ((st->string = malloc(size)) == NULL) {
@@ -158,9 +158,6 @@ fmemopen(void *buf, size_t size, const char *mode)
} else {
st->string = (char *)buf;
- if ((oflags & O_WRONLY) == 0)
- st->len = size;
-
if (oflags & O_TRUNC)
*st->string = '\0';