summaryrefslogtreecommitdiff
path: root/sysutils/mcelog/files/memstream.c
diff options
context:
space:
mode:
Diffstat (limited to 'sysutils/mcelog/files/memstream.c')
-rw-r--r--sysutils/mcelog/files/memstream.c133
1 files changed, 133 insertions, 0 deletions
diff --git a/sysutils/mcelog/files/memstream.c b/sysutils/mcelog/files/memstream.c
new file mode 100644
index 000000000000..20cbf29b472c
--- /dev/null
+++ b/sysutils/mcelog/files/memstream.c
@@ -0,0 +1,133 @@
+/* Use funopen(3) to provide open_memstream(3) like functionality. */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+struct memstream {
+ char **cp;
+ size_t *lenp;
+ size_t offset;
+};
+
+FILE *
+open_memstream(char **cp, size_t *lenp);
+
+static void
+memstream_grow(struct memstream *ms, size_t newsize)
+{
+ char *buf;
+
+ if (newsize > *ms->lenp) {
+ buf = realloc(*ms->cp, newsize + 1);
+ if (buf != NULL) {
+#ifdef DEBUG
+ fprintf(stderr, "MS: %p growing from %zd to %zd\n",
+ ms, *ms->lenp, newsize);
+#endif
+ memset(buf + *ms->lenp + 1, 0, newsize - *ms->lenp);
+ *ms->cp = buf;
+ *ms->lenp = newsize;
+ }
+ }
+}
+
+static int
+memstream_read(void *cookie, char *buf, int len)
+{
+ struct memstream *ms;
+ int tocopy;
+
+ ms = cookie;
+ memstream_grow(ms, ms->offset + len);
+ tocopy = *ms->lenp - ms->offset;
+ if (len < tocopy)
+ tocopy = len;
+ memcpy(buf, *ms->cp + ms->offset, tocopy);
+ ms->offset += tocopy;
+#ifdef DEBUG
+ fprintf(stderr, "MS: read(%p, %d) = %d\n", ms, len, tocopy);
+#endif
+ return (tocopy);
+}
+
+static int
+memstream_write(void *cookie, const char *buf, int len)
+{
+ struct memstream *ms;
+ int tocopy;
+
+ ms = cookie;
+ memstream_grow(ms, ms->offset + len);
+ tocopy = *ms->lenp - ms->offset;
+ if (len < tocopy)
+ tocopy = len;
+ memcpy(*ms->cp + ms->offset, buf, tocopy);
+ ms->offset += tocopy;
+#ifdef DEBUG
+ fprintf(stderr, "MS: write(%p, %d) = %d\n", ms, len, tocopy);
+#endif
+ return (tocopy);
+}
+
+static fpos_t
+memstream_seek(void *cookie, fpos_t pos, int whence)
+{
+ struct memstream *ms;
+#ifdef DEBUG
+ size_t old;
+#endif
+
+ ms = cookie;
+#ifdef DEBUG
+ old = ms->offset;
+#endif
+ switch (whence) {
+ case SEEK_SET:
+ ms->offset = pos;
+ break;
+ case SEEK_CUR:
+ ms->offset += pos;
+ break;
+ case SEEK_END:
+ ms->offset = *ms->lenp + pos;
+ break;
+ }
+#ifdef DEBUG
+ fprintf(stderr, "MS: seek(%p, %zd, %d) %zd -> %zd\n", ms, pos, whence,
+ old, ms->offset);
+#endif
+ return (ms->offset);
+}
+
+static int
+memstream_close(void *cookie)
+{
+
+ free(cookie);
+ return (0);
+}
+
+FILE *
+open_memstream(char **cp, size_t *lenp)
+{
+ struct memstream *ms;
+ int save_errno;
+ FILE *fp;
+
+ *cp = NULL;
+ *lenp = 0;
+ ms = malloc(sizeof(*ms));
+ ms->cp = cp;
+ ms->lenp = lenp;
+ ms->offset = 0;
+ fp = funopen(ms, memstream_read, memstream_write, memstream_seek,
+ memstream_close);
+ if (fp == NULL) {
+ save_errno = errno;
+ free(ms);
+ errno = save_errno;
+ }
+ return (fp);
+}