From: Volker Lendecke Date: Tue, 4 May 2021 10:30:02 +0000 (+0200) Subject: lib: Add str_list_add_printf() X-Git-Tag: tevent-0.11.0~897 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=ecf9ba381e7bd2691d0c8a674f519516c63600ff;p=thirdparty%2Fsamba.git lib: Add str_list_add_printf() Build up execv argument lists Signed-off-by: Volker Lendecke Reviewed-by: Jeremy Allison --- diff --git a/lib/util/tests/strlist.c b/lib/util/tests/strlist.c index 17184990d2c..a9306b82f53 100644 --- a/lib/util/tests/strlist.c +++ b/lib/util/tests/strlist.c @@ -493,10 +493,32 @@ static bool test_list_append_const(struct torture_context *tctx) return true; } +static bool test_list_add_printf_NULL(struct torture_context *tctx) +{ + char **list = NULL; + str_list_add_printf(&list, "x=%d", 1); + torture_assert(tctx, list==NULL, "str_list_add_printf must keep NULL"); + return true; +} + +static bool test_list_add_printf(struct torture_context *tctx) +{ + const char *list2[] = { "foo", "bar=baz", NULL }; + char **list = str_list_make_empty(tctx); + str_list_add_printf(&list, "foo"); + str_list_add_printf(&list, "bar=%s", "baz"); + torture_assert( + tctx, + str_list_equal((const char * const *)list, list2), + "str_list_add_printf failed"); + TALLOC_FREE(list); + return true; +} + struct torture_suite *torture_local_util_strlist(TALLOC_CTX *mem_ctx) { struct torture_suite *suite = torture_suite_create(mem_ctx, "strlist"); - int i; + size_t i; for (i = 0; i < ARRAY_SIZE(test_lists_shell_strings); i++) { char *name; @@ -528,6 +550,9 @@ struct torture_suite *torture_local_util_strlist(TALLOC_CTX *mem_ctx) torture_suite_add_simple_test(suite, "list_unique_2", test_list_unique_2); torture_suite_add_simple_test(suite, "list_append", test_list_append); torture_suite_add_simple_test(suite, "list_append_const", test_list_append_const); - + torture_suite_add_simple_test( + suite, "list_add_printf_NULL", test_list_add_printf_NULL); + torture_suite_add_simple_test( + suite, "list_add_printf", test_list_add_printf); return suite; } diff --git a/lib/util/util_strlist.c b/lib/util/util_strlist.c index 131f602bfff..b56e17379cb 100644 --- a/lib/util/util_strlist.c +++ b/lib/util/util_strlist.c @@ -299,6 +299,57 @@ _PUBLIC_ const char **str_list_add(const char **list, const char *s) return ret; } +/** + * @brief Extend a talloc'ed string list with a printf'ed string + * + * str_list_add_printf() does nothing if *plist is NULL and it sets + * *plist to NULL on failure. It is designed to avoid intermediate + * NULL checks: + * + * argv = str_list_make_empty(ctx); + * str_list_add_printf(&argv, "smbstatus"); + * str_list_add_printf(&argv, "--configfile=%s", config); + * if (argv == NULL) { + * goto nomem; + * } + * + * @param[in,out] plist The talloc'ed list to extend + * @param[in] fmt The format string + */ +void str_list_add_printf(char ***plist, const char *fmt, ...) +{ + char **list = *plist; + size_t len; + char **tmp = NULL; + va_list ap; + + if (list == NULL) { + return; + } + len = str_list_length((const char * const *)list); + + tmp = talloc_realloc(NULL, list, char *, len+2); + if (tmp == NULL) { + goto fail; + } + list = tmp; + list[len+1] = NULL; + + va_start(ap, fmt); + list[len] = talloc_vasprintf(list, fmt, ap); + va_end(ap); + + if (list[len] == NULL) { + goto fail; + } + *plist = list; + + return; +fail: + TALLOC_FREE(list); + *plist = NULL; +} + /** remove an entry from a string list */ diff --git a/lib/util/util_strlist.h b/lib/util/util_strlist.h index 116303424c2..5c3a7ee1f37 100644 --- a/lib/util/util_strlist.h +++ b/lib/util/util_strlist.h @@ -87,6 +87,12 @@ bool str_list_equal(const char * const *list1, */ const char **str_list_add(const char **list, const char *s); +/* + * Extend a list with a printf'ed string + */ +void str_list_add_printf(char ***plist, const char *fmt, ...) + PRINTF_ATTRIBUTE(2,3); + /** remove an entry from a string list */