[CRIU] [PATCH v3 1/6] util: new string helpers introduced
Stanislav Kinsburskiy
skinsbursky at virtuozzo.com
Thu Dec 17 04:29:01 PST 2015
This patch brings add_to_string() and construct_string() helpers.
They allow to create a string with variable amount of parameters in sprintf()
manner, but supporting string allocation (and reallocation if necessary)
v2:
1) Helpers were renamed to xstrcat() and xsprintf() respectively.
2) Added printf attributes to force compiler check
Signed-off-by: Stanislav Kinsburskiy <skinsbursky at virtuozzo.com>
---
include/util.h | 6 +++++
util.c | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 76 insertions(+)
diff --git a/include/util.h b/include/util.h
index df708c8..22a67a9 100644
--- a/include/util.h
+++ b/include/util.h
@@ -275,4 +275,10 @@ void tcp_nodelay(int sk, bool on);
void tcp_cork(int sk, bool on);
const char *ns_to_string(unsigned int ns);
+
+char *xstrcat(char *str, const char *fmt, ...)
+ __attribute__ ((__format__ (__printf__, 2, 3)));
+char *xsprintf(const char *fmt, ...)
+ __attribute__ ((__format__ (__printf__, 1, 2)));
+
#endif /* __CR_UTIL_H__ */
diff --git a/util.c b/util.c
index d56f973..0633500 100644
--- a/util.c
+++ b/util.c
@@ -51,6 +51,76 @@
#define VMA_OPT_LEN 128
+/*
+ * This function reallocates passed str pointer.
+ * It means:
+ * 1) passed pointer can be either NULL, or previously allocated by malloc.
+ * 2) Passed pointer can' be reused. It's either freed in case of error or can
+ * be changed.
+ */
+static char *xvstrcat(char *str, const char *fmt, va_list args)
+{
+ size_t offset = 0, delta;
+ int ret;
+ char *new;
+ va_list tmp;
+
+ if (str)
+ offset = strlen(str);
+ delta = strlen(fmt) * 2;
+
+ do {
+ ret = -ENOMEM;
+ new = xrealloc(str, offset + delta);
+ if (new) {
+ va_copy(tmp, args);
+ ret = vsnprintf(new + offset, delta, fmt, tmp);
+ if (ret >= delta) {
+ /* NOTE: vsnprintf returns the amount of bytes
+ * to allocate. */
+ delta = ret +1;
+ str = new;
+ ret = 0;
+ }
+ }
+ } while (ret == 0);
+
+ if (ret == -ENOMEM) {
+ /* realloc failed. We must release former string */
+ pr_err("Failed to allocate string\n");
+ xfree(str);
+ } else if (ret < 0) {
+ /* vsnprintf failed */
+ pr_err("Failed to print string\n");
+ xfree(new);
+ new = NULL;
+ }
+ return new;
+}
+
+char *xstrcat(char *str, const char *fmt, ...)
+{
+ va_list args;
+
+ va_start(args, fmt);
+ str = xvstrcat(str, fmt, args);
+ va_end(args);
+
+ return str;
+}
+
+char *xsprintf(const char *fmt, ...)
+{
+ va_list args;
+ char *str;
+
+ va_start(args, fmt);
+ str = xvstrcat(NULL, fmt, args);
+ va_end(args);
+
+ return str;
+}
+
static void vma_opt_str(const struct vma_area *v, char *opt)
{
int p = 0;
More information about the CRIU
mailing list