From nobody Sun Feb 8 12:32:47 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of redhat.com designates 209.132.183.39 as permitted sender) client-ip=209.132.183.39; envelope-from=libvir-list-bounces@redhat.com; helo=mx6-phx2.redhat.com; Authentication-Results: mx.zoho.com; spf=pass (zoho.com: domain of redhat.com designates 209.132.183.39 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; Return-Path: Received: from mx6-phx2.redhat.com (mx6-phx2.redhat.com [209.132.183.39]) by mx.zohomail.com with SMTPS id 1487863819734415.07235927905003; Thu, 23 Feb 2017 07:30:19 -0800 (PST) Received: from lists01.pubmisc.prod.ext.phx2.redhat.com (lists01.pubmisc.prod.ext.phx2.redhat.com [10.5.19.33]) by mx6-phx2.redhat.com (8.14.4/8.14.4) with ESMTP id v1NFR6TU019719; Thu, 23 Feb 2017 10:27:06 -0500 Received: from int-mx13.intmail.prod.int.phx2.redhat.com (int-mx13.intmail.prod.int.phx2.redhat.com [10.5.11.26]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id v1NFR3dd000767 for ; Thu, 23 Feb 2017 10:27:03 -0500 Received: from antique-work.brq.redhat.com (dhcp129-175.brq.redhat.com [10.34.129.175]) by int-mx13.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id v1NFR1We018328 for ; Thu, 23 Feb 2017 10:27:03 -0500 From: Pavel Hrdina To: libvir-list@redhat.com Date: Thu, 23 Feb 2017 16:26:56 +0100 Message-Id: In-Reply-To: References: In-Reply-To: References: X-Scanned-By: MIMEDefang 2.68 on 10.5.11.26 X-loop: libvir-list@redhat.com Subject: [libvirt] [PATCH 1/5] util: virstring: introduce virStrcat and VIR_STRCAT X-BeenThere: libvir-list@redhat.com X-Mailman-Version: 2.1.12 Precedence: junk List-Id: Development discussions about the libvirt library & tools List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Sender: libvir-list-bounces@redhat.com Errors-To: libvir-list-bounces@redhat.com X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Type: text/plain; charset="utf-8" Signed-off-by: Pavel Hrdina --- cfg.mk | 2 +- src/libvirt_private.syms | 2 ++ src/util/virstring.c | 70 ++++++++++++++++++++++++++++++++++++++++++++= ++++ src/util/virstring.h | 27 +++++++++++++++++++ tests/virstringtest.c | 49 +++++++++++++++++++++++++++++++++ 5 files changed, 149 insertions(+), 1 deletion(-) diff --git a/cfg.mk b/cfg.mk index aaba61f1dc..22c655eac6 100644 --- a/cfg.mk +++ b/cfg.mk @@ -1147,7 +1147,7 @@ exclude_file_name_regexp--sc_prohibit_fork_wrappers = =3D \ exclude_file_name_regexp--sc_prohibit_gethostname =3D ^src/util/virutil\.c= $$ =20 exclude_file_name_regexp--sc_prohibit_internal_functions =3D \ - ^src/(util/(viralloc|virutil|virfile)\.[hc]|esx/esx_vi\.c)$$ + ^src/(util/(viralloc|virutil|virfile|virstring)\.[hc]|esx/esx_vi\.c)$$ =20 exclude_file_name_regexp--sc_prohibit_newline_at_end_of_diagnostic =3D \ ^src/rpc/gendispatch\.pl$$ diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 07a35333b1..e9c4d73779 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -2502,6 +2502,8 @@ virAsprintfInternal; virSkipSpaces; virSkipSpacesAndBackslash; virSkipSpacesBackwards; +virStrcat; +virStrcatInplace; virStrcpy; virStrdup; virStringBufferIsPrintable; diff --git a/src/util/virstring.c b/src/util/virstring.c index 69abc267bf..bc15ce7e9e 100644 --- a/src/util/virstring.c +++ b/src/util/virstring.c @@ -837,6 +837,76 @@ virStrndup(char **dest, } =20 =20 +/** + * virStrcat + * @dest: where to store concatenated string + * @src: the source string to append to @dest + * @inPlace: false if we should expand the allocated memory before moving, + * true if we should assume someone else has already done that. + * @report: whether to report OOM error, if there is one + * @domcode: error domain code + * @filename: caller's filename + * @funcname: caller's funcname + * @linenr: caller's line number + * + * Wrapper over strcat, which reports OOM error if told so, + * in which case callers wants to pass @domcode, @filename, + * @funcname and @linenr which should represent location in + * caller's body where virStrcat is called from. Consider + * using VIR_STRCAT which sets these automatically. + * + * Returns: 0 for NULL src, 1 on successful concatenate, -1 otherwise. + */ +int +virStrcat(char **dest, + const char *src, + bool report, + int domcode, + const char *filename, + const char *funcname, + size_t linenr) +{ + size_t dest_len =3D 0; + size_t src_len =3D 0; + + if (!src) + return 0; + + if (*dest) + dest_len =3D strlen(*dest); + src_len =3D strlen(src); + + if (virReallocN(dest, sizeof(*dest), dest_len + src_len + 1, + report, domcode, filename, funcname, linenr) < 0) + return -1; + + strcat(*dest, src); + + return 1; +} + + +/** + * virStrcat + * @dest: where to store concatenated string + * @src: the source string to append to @dest + * + * Wrapper over strcat, which properly handles if @src is NULL. + * + * Returns: 0 for NULL src, 1 on successful concatenate. + */ +int +virStrcatInplace(char *dest, const char *src) +{ + if (!src) + return 0; + + strcat(dest, src); + + return 1; +} + + size_t virStringListLength(const char * const *strings) { size_t i =3D 0; diff --git a/src/util/virstring.h b/src/util/virstring.h index a5550e30d2..79d2f23c80 100644 --- a/src/util/virstring.h +++ b/src/util/virstring.h @@ -131,6 +131,13 @@ int virStrdup(char **dest, const char *src, bool repor= t, int domcode, int virStrndup(char **dest, const char *src, ssize_t n, bool report, int d= omcode, const char *filename, const char *funcname, size_t linenr) ATTRIBUTE_RETURN_CHECK ATTRIBUTE_NONNULL(1); + +int virStrcat(char **dest, const char *src, bool report, int domcode, + const char *filename, const char *funcname, size_t linenr) + ATTRIBUTE_RETURN_CHECK ATTRIBUTE_NONNULL(1); +int virStrcatInplace(char *dest, const char *src) + ATTRIBUTE_NONNULL(1); + int virAsprintfInternal(bool report, int domcode, const char *filename, const char *funcname, size_t linenr, char **strp, const char *fmt, ...) @@ -209,6 +216,26 @@ int virVasprintfInternal(bool report, int domcode, con= st char *filename, # define VIR_STRNDUP_QUIET(dst, src, n) virStrndup(&(dst), src, n, false, \ 0, NULL, NULL, 0) =20 +/** + * VIR_STRCAT: + * @dst: variable to hold result (char*, not char**) + * @src: string to concatenate to @dst + * + * Concatenate @src string into @dst string, @dst may be NULL. + * + * This macro is safe to use on arguments with side effects. + * + * VIR_STRCAT_INPLACE expect the @dst to be already allocated to hold + * the result. + * + * Returns -1 on failure, 0 if @src was NULL, 1 if @src was concatenated. + */ +# define VIR_STRCAT(dst, src) virStrcat(&(dst), src, true, VIR_FROM_THIS, \ + __FILE__, __FUNCTION__, __LINE__) +# define VIR_STRCAT_QUIET(dst, src) virStrcat(&(dst), src, false, 0, \ + NULL, NULL, 0) +# define VIR_STRCAT_INPLACE(dst, src) virStrcatInplace(dst, src) + size_t virStringListLength(const char * const *strings); =20 /** diff --git a/tests/virstringtest.c b/tests/virstringtest.c index db1731f96a..d2d6138326 100644 --- a/tests/virstringtest.c +++ b/tests/virstringtest.c @@ -693,6 +693,37 @@ static int testStripControlChars(const void *args) return ret; } =20 + +struct testStrcatData { + const char *dest; + const char *src; + const char *res; +}; + +static int +testStrcat(const void *args) +{ + const struct testStrcatData *data =3D args; + char *str =3D NULL; + int ret =3D -1; + + if (VIR_STRDUP(str, data->dest) < 0) + goto cleanup; + + if (VIR_STRCAT(str, data->src) < 0) + goto cleanup; + + if (!STREQ_NULLABLE(str, data->res)) + goto cleanup; + + ret =3D 0; + + cleanup: + VIR_FREE(str); + return ret; +} + + static int mymain(void) { @@ -958,6 +989,24 @@ mymain(void) TEST_STRIP_CONTROL_CHARS("\x01H\x02" "E\x03L\x04L\x05O", "HELLO"); TEST_STRIP_CONTROL_CHARS("\x01\x02\x03\x04HELL\x05O", "HELLO"); TEST_STRIP_CONTROL_CHARS("\nhello \x01\x07hello\t", "\nhello hello\t"); + +#define TEST_STRCAT(dests, srcs, ress) = \ + do { = \ + struct testStrcatData strcatData =3D { = \ + .dest =3D dests, = \ + .src =3D srcs, = \ + .res =3D ress, = \ + }; = \ + if (virTestRun("Concatenate '" #dests "' with '" #srcs "'", = \ + testStrcat, &strcatData) < 0) = \ + ret =3D -1; = \ + } while (0) + + TEST_STRCAT(NULL, NULL, NULL); + TEST_STRCAT(NULL, "world", "world"); + TEST_STRCAT("hello", NULL, "hello"); + TEST_STRCAT("hello", "world", "helloworld"); + return ret =3D=3D 0 ? EXIT_SUCCESS : EXIT_FAILURE; } =20 --=20 2.11.1 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list