freebsd-ports/sysutils/mcelog/files/memstream.c
Ryan Steinmetz 6e9151ca05 New port: sysutils/mcelog
mcelog processes machine checks (in particular memory and CPU
hardware errors) on modern x86-based unix systems and
produces human-readable output.

FreeBSD conversion patches were originally written by John
Baldwin <jhb@freebsd.org> and later incorporated into this
port.

WWW: http://mcelog.org/

PR:		ports/161395
Submitted by:	Jeremy Chadwick <freebsd@jdc.parodius.com>
2011-10-15 02:53:31 +00:00

133 lines
2.3 KiB
C

/* 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);
}