From 78c896b3b3127515478090c19447e27dc406427e Mon Sep 17 00:00:00 2001 From: Jianfeng Tan Date: Mon, 18 Nov 2019 06:59:50 +0000 Subject: TLDKv2 Signed-off-by: Jianfeng Tan Signed-off-by: Jielong Zhou Signed-off-by: Jian Zhang Signed-off-by: Chen Zhao Change-Id: I55c39de4c6cd30f991f35631eb507f770230f08e --- test/packetdrill/open_memstream.c | 142 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 142 insertions(+) create mode 100644 test/packetdrill/open_memstream.c (limited to 'test/packetdrill/open_memstream.c') diff --git a/test/packetdrill/open_memstream.c b/test/packetdrill/open_memstream.c new file mode 100644 index 0000000..9114091 --- /dev/null +++ b/test/packetdrill/open_memstream.c @@ -0,0 +1,142 @@ +/* + * Copyright 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ +/* + * Author: ncardwell@google.com (Neal Cardwell) + * + * FreeBSD does not have open_memstream(), so we roll our own minimalist + * implementation here. + */ + +#include "types.h" + +#ifndef HAVE_OPEN_MEMSTREAM + +#include "assert.h" +#include "open_memstream.h" +#include +#include +#include +#include + +/* Our internal state for the memstream. */ +struct mem_stream { + char **buf; /* pointer to the output buffer pointer */ + size_t *sizeloc; /* pointer to the output final buffer size */ + + size_t buf_size; /* currently allocated size of buffer */ + size_t offset; /* current write offset */ +}; + +#define INITIAL_BUF_SIZE 1024 + +/* Grow buffer, if needed, to write "write_bytes" bytes at the current + * offset. We also have to take into account the extra '\0' that we + * maintain just past the end. Returns 0 on success, or -1 on failure. + */ +static int mem_stream_grow(struct mem_stream *stream, int write_bytes) +{ + char *new_buf = NULL; + size_t new_size = 0; + size_t needed_bytes = 0; + + needed_bytes = stream->offset + write_bytes + 1; + if (needed_bytes <= stream->buf_size) + return 0; + + if (stream->buf_size == 0) + new_size = INITIAL_BUF_SIZE; + else + new_size = 2 * stream->buf_size; + + if (new_size < needed_bytes) + new_size = needed_bytes; + + new_buf = (char *) realloc(*stream->buf, new_size); + if (new_buf == NULL) + return -1; + + *stream->buf = new_buf; + stream->buf_size = new_size; + + return 0; +} + +/* Write the give data to our memstream, expanding our buffer if we + * need to. Per the specification in the Linux man pages, "A null byte + * is maintained at the end of the buffer. This byte is not included + * in the size value stored at sizeloc." + */ +static int write_memstream(void *cookie, const char *buf, int write_bytes) +{ + struct mem_stream *stream = (struct mem_stream *) cookie; + + if (mem_stream_grow(stream, write_bytes) < 0) + return -1; + + memcpy(*stream->buf + stream->offset, buf, write_bytes); + stream->offset += write_bytes; + + *(*stream->buf + stream->offset) = '\0'; + + *stream->sizeloc = stream->offset; /* size does not include '\0' */ + + return write_bytes; +} + +/* Clean up */ +static int close_memstream(void *cookie) +{ + struct mem_stream *stream = (struct mem_stream *) cookie; + + free(stream); + + return 0; +} + +/* Create a memstream. */ +FILE *open_memstream(char **ptr, size_t *sizeloc) +{ + FILE *f; + struct mem_stream *stream; + + if (ptr == NULL || sizeloc == NULL) { + errno = EINVAL; + return NULL; + } + + stream = (struct mem_stream *) calloc(1, sizeof(struct mem_stream)); + if (stream == NULL) + return NULL; + + f = funopen(stream, NULL, write_memstream, NULL, close_memstream); + if (f == NULL) { + free(stream); + return NULL; + } + + *ptr = NULL; + *sizeloc = 0; + + stream->buf = ptr; + stream->sizeloc = sizeloc; + + return f; +} + +#endif /* HAVE_OPEN_MEMSTREAM */ -- cgit 1.2.3-korg