From 92da744700f31355768b258f985fea02050a1429 Mon Sep 17 00:00:00 2001 From: Daniel Verkamp Date: Fri, 2 Oct 2015 11:13:11 -0700 Subject: [PATCH] util: add sprintf_alloc() function Like sprintf() with automatic buffer allocation. This should help to avoid fixed-size buffers in non-performance-sensitive code that formats strings. Change-Id: I35209ae84014ed5daf41baa5b03af8a5f6b02b8e Signed-off-by: Daniel Verkamp --- examples/nvme/perf/perf.c | 15 ++++--- include/spdk/string.h | 46 ++++++++++++++++++++++ lib/util/Makefile | 2 +- lib/util/string.c | 82 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 136 insertions(+), 9 deletions(-) create mode 100644 include/spdk/string.h create mode 100644 lib/util/string.c diff --git a/examples/nvme/perf/perf.c b/examples/nvme/perf/perf.c index 1884c9b65..23c99da14 100644 --- a/examples/nvme/perf/perf.c +++ b/examples/nvme/perf/perf.c @@ -46,6 +46,7 @@ #include "spdk/nvme.h" #include "spdk/pci.h" +#include "spdk/string.h" struct ctrlr_entry { struct nvme_controller *ctrlr; @@ -528,7 +529,7 @@ unregister_controllers(void) } } -static const char *ealargs[] = { +static char *ealargs[] = { "perf", "-c 0x1", /* This must be the second parameter. It is overwritten by index in main(). */ "-n 4", @@ -537,7 +538,6 @@ static const char *ealargs[] = { int main(int argc, char **argv) { int rc; - char core_mask_arg[128]; struct worker_thread *worker; rc = parse_args(argc, argv); @@ -545,13 +545,12 @@ int main(int argc, char **argv) return rc; } - if (g_core_mask != NULL) { - snprintf(core_mask_arg, sizeof(core_mask_arg), "-c %s", g_core_mask); - ealargs[1] = strdup(core_mask_arg); - } + ealargs[1] = sprintf_alloc("-c %s", g_core_mask ? g_core_mask : "0x1"); + + rc = rte_eal_init(sizeof(ealargs) / sizeof(ealargs[0]), ealargs); + + free(ealargs[1]); - rc = rte_eal_init(sizeof(ealargs) / sizeof(ealargs[0]), - (char **)(void *)(uintptr_t)ealargs); if (rc < 0) { fprintf(stderr, "could not initialize dpdk\n"); return 1; diff --git a/include/spdk/string.h b/include/spdk/string.h new file mode 100644 index 000000000..d72365b2f --- /dev/null +++ b/include/spdk/string.h @@ -0,0 +1,46 @@ +/*- + * BSD LICENSE + * + * Copyright(c) 2015 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef SPDK_STRING_H +#define SPDK_STRING_H + +/** + * sprintf with automatic buffer allocation. + * + * The return value is the formatted string, + * which should be passed to free() when no longer needed, + * or NULL on failure. + */ +char *sprintf_alloc(const char *format, ...) __attribute__((format(printf, 1, 2))); + +#endif diff --git a/lib/util/Makefile b/lib/util/Makefile index dbfa74269..00376fa00 100644 --- a/lib/util/Makefile +++ b/lib/util/Makefile @@ -35,7 +35,7 @@ include $(SPDK_ROOT_DIR)/mk/spdk.common.mk CFLAGS += $(DPDK_INC) -C_SRCS = pci.c +C_SRCS = string.c pci.c C_OBJS := $(patsubst %.c,%.o,$(C_SRCS)) diff --git a/lib/util/string.c b/lib/util/string.c new file mode 100644 index 000000000..4acbab2bb --- /dev/null +++ b/lib/util/string.c @@ -0,0 +1,82 @@ +/*- + * BSD LICENSE + * + * Copyright(c) 2015 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include + +#include "spdk/string.h" + +char * +sprintf_alloc(const char *format, ...) +{ + va_list args; + char *buf; + size_t bufsize; + int rc; + + /* Try with a small buffer first. */ + bufsize = 32; + + /* Limit maximum buffer size to something reasonable so we don't loop forever. */ + while (bufsize <= 1024 * 1024) { + buf = malloc(bufsize); + if (buf == NULL) { + return NULL; + } + + va_start(args, format); + rc = vsnprintf(buf, bufsize, format, args); + va_end(args); + + /* + * If vsnprintf() returned a count within our current buffer size, we are done. + * The count does not include the \0 terminator, so rc == bufsize is not OK. + */ + if (rc >= 0 && rc < bufsize) { + return buf; + } + + /* + * vsnprintf() should return the required space, but some libc versions do not + * implement this correctly, so just double the buffer size and try again. + * + * We don't need the data in buf, so rather than realloc(), use free() and malloc() + * again to avoid a copy. + */ + free(buf); + bufsize *= 2; + } + + return NULL; +}