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 <daniel.verkamp@intel.com>
This commit is contained in:
Daniel Verkamp 2015-10-02 11:13:11 -07:00
parent 5fc71d7e40
commit 92da744700
4 changed files with 136 additions and 9 deletions

View File

@ -46,6 +46,7 @@
#include "spdk/nvme.h" #include "spdk/nvme.h"
#include "spdk/pci.h" #include "spdk/pci.h"
#include "spdk/string.h"
struct ctrlr_entry { struct ctrlr_entry {
struct nvme_controller *ctrlr; struct nvme_controller *ctrlr;
@ -528,7 +529,7 @@ unregister_controllers(void)
} }
} }
static const char *ealargs[] = { static char *ealargs[] = {
"perf", "perf",
"-c 0x1", /* This must be the second parameter. It is overwritten by index in main(). */ "-c 0x1", /* This must be the second parameter. It is overwritten by index in main(). */
"-n 4", "-n 4",
@ -537,7 +538,6 @@ static const char *ealargs[] = {
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
int rc; int rc;
char core_mask_arg[128];
struct worker_thread *worker; struct worker_thread *worker;
rc = parse_args(argc, argv); rc = parse_args(argc, argv);
@ -545,13 +545,12 @@ int main(int argc, char **argv)
return rc; return rc;
} }
if (g_core_mask != NULL) { ealargs[1] = sprintf_alloc("-c %s", g_core_mask ? g_core_mask : "0x1");
snprintf(core_mask_arg, sizeof(core_mask_arg), "-c %s", g_core_mask);
ealargs[1] = strdup(core_mask_arg); 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) { if (rc < 0) {
fprintf(stderr, "could not initialize dpdk\n"); fprintf(stderr, "could not initialize dpdk\n");
return 1; return 1;

46
include/spdk/string.h Normal file
View File

@ -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

View File

@ -35,7 +35,7 @@ include $(SPDK_ROOT_DIR)/mk/spdk.common.mk
CFLAGS += $(DPDK_INC) CFLAGS += $(DPDK_INC)
C_SRCS = pci.c C_SRCS = string.c pci.c
C_OBJS := $(patsubst %.c,%.o,$(C_SRCS)) C_OBJS := $(patsubst %.c,%.o,$(C_SRCS))

82
lib/util/string.c Normal file
View File

@ -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 <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#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;
}