[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