|
|
905b4d |
From a624616892da3dc0ee39659e24cbd5a40ae98e9e Mon Sep 17 00:00:00 2001
|
|
|
905b4d |
From: Sumit Bose <sbose@redhat.com>
|
|
|
905b4d |
Date: Mon, 27 Oct 2014 16:53:44 +0100
|
|
|
905b4d |
Subject: [PATCH 55/64] Add add_strings_lists() utility function
|
|
|
905b4d |
|
|
|
905b4d |
Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
|
|
|
905b4d |
---
|
|
|
905b4d |
src/tests/cmocka/test_utils.c | 111 ++++++++++++++++++++++++++++++++++++++++++
|
|
|
905b4d |
src/util/util.c | 65 +++++++++++++++++++++++++
|
|
|
905b4d |
src/util/util.h | 18 +++++++
|
|
|
905b4d |
3 files changed, 194 insertions(+)
|
|
|
905b4d |
|
|
|
905b4d |
diff --git a/src/tests/cmocka/test_utils.c b/src/tests/cmocka/test_utils.c
|
|
|
905b4d |
index 9d6cbf35f7c2e33c57b3a539b409848c22cf263e..d9781377be70a0d58b0fd1fff2145483dbeb199c 100644
|
|
|
905b4d |
--- a/src/tests/cmocka/test_utils.c
|
|
|
905b4d |
+++ b/src/tests/cmocka/test_utils.c
|
|
|
905b4d |
@@ -875,6 +875,114 @@ void test_expand_homedir_template(void **state)
|
|
|
905b4d |
talloc_free(tmp_ctx);
|
|
|
905b4d |
}
|
|
|
905b4d |
|
|
|
905b4d |
+void setup_add_strings_lists(void **state)
|
|
|
905b4d |
+{
|
|
|
905b4d |
+ assert_true(leak_check_setup());
|
|
|
905b4d |
+
|
|
|
905b4d |
+ check_leaks_push(global_talloc_context);
|
|
|
905b4d |
+}
|
|
|
905b4d |
+
|
|
|
905b4d |
+void teardown_add_strings_lists(void **state)
|
|
|
905b4d |
+{
|
|
|
905b4d |
+ assert_true(check_leaks_pop(global_talloc_context) == true);
|
|
|
905b4d |
+ assert_true(leak_check_teardown());
|
|
|
905b4d |
+}
|
|
|
905b4d |
+
|
|
|
905b4d |
+void test_add_strings_lists(void **state)
|
|
|
905b4d |
+{
|
|
|
905b4d |
+ const char *l1[] = {"a", "b", "c", NULL};
|
|
|
905b4d |
+ const char *l2[] = {"1", "2", "3", NULL};
|
|
|
905b4d |
+ char **res;
|
|
|
905b4d |
+ int ret;
|
|
|
905b4d |
+ size_t c;
|
|
|
905b4d |
+ size_t d;
|
|
|
905b4d |
+
|
|
|
905b4d |
+ ret = add_strings_lists(global_talloc_context, NULL, NULL, true, &res;;
|
|
|
905b4d |
+ assert_int_equal(ret, EOK);
|
|
|
905b4d |
+ assert_non_null(res);
|
|
|
905b4d |
+ assert_null(res[0]);
|
|
|
905b4d |
+ talloc_free(res);
|
|
|
905b4d |
+
|
|
|
905b4d |
+ ret = add_strings_lists(global_talloc_context, NULL, NULL, false, &res;;
|
|
|
905b4d |
+ assert_int_equal(ret, EOK);
|
|
|
905b4d |
+ assert_non_null(res);
|
|
|
905b4d |
+ assert_null(res[0]);
|
|
|
905b4d |
+ talloc_free(res);
|
|
|
905b4d |
+
|
|
|
905b4d |
+ ret = add_strings_lists(global_talloc_context, l1, NULL, false, &res;;
|
|
|
905b4d |
+ assert_int_equal(ret, EOK);
|
|
|
905b4d |
+ assert_non_null(res);
|
|
|
905b4d |
+ for (c = 0; l1[c] != NULL; c++) {
|
|
|
905b4d |
+ /* 'copy_strings' is 'false', pointers must be equal */
|
|
|
905b4d |
+ assert_int_equal(memcmp(&l1[c], &res[c], sizeof(char *)), 0);
|
|
|
905b4d |
+ }
|
|
|
905b4d |
+ assert_null(res[c]);
|
|
|
905b4d |
+ talloc_free(res);
|
|
|
905b4d |
+
|
|
|
905b4d |
+ ret = add_strings_lists(global_talloc_context, l1, NULL, true, &res;;
|
|
|
905b4d |
+ assert_int_equal(ret, EOK);
|
|
|
905b4d |
+ assert_non_null(res);
|
|
|
905b4d |
+ for (c = 0; l1[c] != NULL; c++) {
|
|
|
905b4d |
+ /* 'copy_strings' is 'true', pointers must be different, but strings
|
|
|
905b4d |
+ * must be equal */
|
|
|
905b4d |
+ assert_int_not_equal(memcmp(&l1[c], &res[c], sizeof(char *)), 0);
|
|
|
905b4d |
+ assert_string_equal(l1[c], res[c]);
|
|
|
905b4d |
+ }
|
|
|
905b4d |
+ assert_null(res[c]);
|
|
|
905b4d |
+ talloc_free(res);
|
|
|
905b4d |
+
|
|
|
905b4d |
+ ret = add_strings_lists(global_talloc_context, NULL, l1, false, &res;;
|
|
|
905b4d |
+ assert_int_equal(ret, EOK);
|
|
|
905b4d |
+ assert_non_null(res);
|
|
|
905b4d |
+ for (c = 0; l1[c] != NULL; c++) {
|
|
|
905b4d |
+ /* 'copy_strings' is 'false', pointers must be equal */
|
|
|
905b4d |
+ assert_int_equal(memcmp(&l1[c], &res[c], sizeof(char *)), 0);
|
|
|
905b4d |
+ }
|
|
|
905b4d |
+ assert_null(res[c]);
|
|
|
905b4d |
+ talloc_free(res);
|
|
|
905b4d |
+
|
|
|
905b4d |
+ ret = add_strings_lists(global_talloc_context, NULL, l1, true, &res;;
|
|
|
905b4d |
+ assert_int_equal(ret, EOK);
|
|
|
905b4d |
+ assert_non_null(res);
|
|
|
905b4d |
+ for (c = 0; l1[c] != NULL; c++) {
|
|
|
905b4d |
+ /* 'copy_strings' is 'true', pointers must be different, but strings
|
|
|
905b4d |
+ * must be equal */
|
|
|
905b4d |
+ assert_int_not_equal(memcmp(&l1[c], &res[c], sizeof(char *)), 0);
|
|
|
905b4d |
+ assert_string_equal(l1[c], res[c]);
|
|
|
905b4d |
+ }
|
|
|
905b4d |
+ assert_null(res[c]);
|
|
|
905b4d |
+ talloc_free(res);
|
|
|
905b4d |
+
|
|
|
905b4d |
+ ret = add_strings_lists(global_talloc_context, l1, l2, false, &res;;
|
|
|
905b4d |
+ assert_int_equal(ret, EOK);
|
|
|
905b4d |
+ assert_non_null(res);
|
|
|
905b4d |
+ for (c = 0; l1[c] != NULL; c++) {
|
|
|
905b4d |
+ /* 'copy_strings' is 'false', pointers must be equal */
|
|
|
905b4d |
+ assert_int_equal(memcmp(&l1[c], &res[c], sizeof(char *)), 0);
|
|
|
905b4d |
+ }
|
|
|
905b4d |
+ for (d = 0; l2[d] != NULL; d++) {
|
|
|
905b4d |
+ assert_int_equal(memcmp(&l2[d], &res[c+d], sizeof(char *)), 0);
|
|
|
905b4d |
+ }
|
|
|
905b4d |
+ assert_null(res[c+d]);
|
|
|
905b4d |
+ talloc_free(res);
|
|
|
905b4d |
+
|
|
|
905b4d |
+ ret = add_strings_lists(global_talloc_context, l1, l2, true, &res;;
|
|
|
905b4d |
+ assert_int_equal(ret, EOK);
|
|
|
905b4d |
+ assert_non_null(res);
|
|
|
905b4d |
+ for (c = 0; l1[c] != NULL; c++) {
|
|
|
905b4d |
+ /* 'copy_strings' is 'true', pointers must be different, but strings
|
|
|
905b4d |
+ * must be equal */
|
|
|
905b4d |
+ assert_int_not_equal(memcmp(&l1[c], &res[c], sizeof(char *)), 0);
|
|
|
905b4d |
+ assert_string_equal(l1[c], res[c]);
|
|
|
905b4d |
+ }
|
|
|
905b4d |
+ for (d = 0; l2[d] != NULL; d++) {
|
|
|
905b4d |
+ assert_int_not_equal(memcmp(&l2[d], &res[c+d], sizeof(char *)), 0);
|
|
|
905b4d |
+ assert_string_equal(l2[d], res[c+d]);
|
|
|
905b4d |
+ }
|
|
|
905b4d |
+ assert_null(res[c+d]);
|
|
|
905b4d |
+ talloc_free(res);
|
|
|
905b4d |
+}
|
|
|
905b4d |
+
|
|
|
905b4d |
int main(int argc, const char *argv[])
|
|
|
905b4d |
{
|
|
|
905b4d |
poptContext pc;
|
|
|
905b4d |
@@ -919,6 +1027,9 @@ int main(int argc, const char *argv[])
|
|
|
905b4d |
unit_test(test_textual_public_key),
|
|
|
905b4d |
unit_test(test_replace_whitespaces),
|
|
|
905b4d |
unit_test(test_reverse_replace_whitespaces),
|
|
|
905b4d |
+ unit_test_setup_teardown(test_add_strings_lists,
|
|
|
905b4d |
+ setup_add_strings_lists,
|
|
|
905b4d |
+ teardown_add_strings_lists),
|
|
|
905b4d |
};
|
|
|
905b4d |
|
|
|
905b4d |
/* Set debug level to invalid value so we can deside if -d 0 was used. */
|
|
|
905b4d |
diff --git a/src/util/util.c b/src/util/util.c
|
|
|
905b4d |
index d78d37d975e6591bca6ac3f2fa36b5b9f4659a29..2acb8604ac0c2bc7b83ee578c7bbead9a7fd44b3 100644
|
|
|
905b4d |
--- a/src/util/util.c
|
|
|
905b4d |
+++ b/src/util/util.c
|
|
|
905b4d |
@@ -815,3 +815,68 @@ const char * const * get_known_services(void)
|
|
|
905b4d |
|
|
|
905b4d |
return svc;
|
|
|
905b4d |
}
|
|
|
905b4d |
+
|
|
|
905b4d |
+errno_t add_strings_lists(TALLOC_CTX *mem_ctx, const char **l1, const char **l2,
|
|
|
905b4d |
+ bool copy_strings, char ***_new_list)
|
|
|
905b4d |
+{
|
|
|
905b4d |
+ size_t c;
|
|
|
905b4d |
+ size_t l1_count = 0;
|
|
|
905b4d |
+ size_t l2_count = 0;
|
|
|
905b4d |
+ size_t new_count = 0;
|
|
|
905b4d |
+ char **new;
|
|
|
905b4d |
+ int ret;
|
|
|
905b4d |
+
|
|
|
905b4d |
+ if (l1 != NULL) {
|
|
|
905b4d |
+ for (l1_count = 0; l1[l1_count] != NULL; l1_count++);
|
|
|
905b4d |
+ }
|
|
|
905b4d |
+
|
|
|
905b4d |
+ if (l2 != NULL) {
|
|
|
905b4d |
+ for (l2_count = 0; l2[l2_count] != NULL; l2_count++);
|
|
|
905b4d |
+ }
|
|
|
905b4d |
+
|
|
|
905b4d |
+ new_count = l1_count + l2_count;
|
|
|
905b4d |
+
|
|
|
905b4d |
+ new = talloc_array(mem_ctx, char *, new_count + 1);
|
|
|
905b4d |
+ if (new == NULL) {
|
|
|
905b4d |
+ DEBUG(SSSDBG_OP_FAILURE, "talloc_array failed.\n");
|
|
|
905b4d |
+ return ENOMEM;
|
|
|
905b4d |
+ }
|
|
|
905b4d |
+ new [new_count] = NULL;
|
|
|
905b4d |
+
|
|
|
905b4d |
+ if (copy_strings) {
|
|
|
905b4d |
+ for(c = 0; c < l1_count; c++) {
|
|
|
905b4d |
+ new[c] = talloc_strdup(new, l1[c]);
|
|
|
905b4d |
+ if (new[c] == NULL) {
|
|
|
905b4d |
+ DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n");
|
|
|
905b4d |
+ ret = ENOMEM;
|
|
|
905b4d |
+ goto done;
|
|
|
905b4d |
+ }
|
|
|
905b4d |
+ }
|
|
|
905b4d |
+ for(c = 0; c < l2_count; c++) {
|
|
|
905b4d |
+ new[l1_count + c] = talloc_strdup(new, l2[c]);
|
|
|
905b4d |
+ if (new[l1_count + c] == NULL) {
|
|
|
905b4d |
+ DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n");
|
|
|
905b4d |
+ ret = ENOMEM;
|
|
|
905b4d |
+ goto done;
|
|
|
905b4d |
+ }
|
|
|
905b4d |
+ }
|
|
|
905b4d |
+ } else {
|
|
|
905b4d |
+ if (l1 != NULL) {
|
|
|
905b4d |
+ memcpy(new, l1, sizeof(char *) * l1_count);
|
|
|
905b4d |
+ }
|
|
|
905b4d |
+
|
|
|
905b4d |
+ if (l2 != NULL) {
|
|
|
905b4d |
+ memcpy(&new[l1_count], l2, sizeof(char *) * l2_count);
|
|
|
905b4d |
+ }
|
|
|
905b4d |
+ }
|
|
|
905b4d |
+
|
|
|
905b4d |
+ *_new_list = new;
|
|
|
905b4d |
+ ret = EOK;
|
|
|
905b4d |
+
|
|
|
905b4d |
+done:
|
|
|
905b4d |
+ if (ret != EOK) {
|
|
|
905b4d |
+ talloc_free(new);
|
|
|
905b4d |
+ }
|
|
|
905b4d |
+
|
|
|
905b4d |
+ return ret;
|
|
|
905b4d |
+}
|
|
|
905b4d |
diff --git a/src/util/util.h b/src/util/util.h
|
|
|
905b4d |
index 69074c93c1640a1e4a7e590b7f9feb6cc04804a4..ffc8a87eafa4c4b8271d195c7d27fd10f5aa3568 100644
|
|
|
905b4d |
--- a/src/util/util.h
|
|
|
905b4d |
+++ b/src/util/util.h
|
|
|
905b4d |
@@ -426,6 +426,24 @@ errno_t sss_hash_create_ex(TALLOC_CTX *mem_ctx,
|
|
|
905b4d |
hash_delete_callback *delete_callback,
|
|
|
905b4d |
void *delete_private_data);
|
|
|
905b4d |
|
|
|
905b4d |
+/**
|
|
|
905b4d |
+ * @brief Add two list of strings
|
|
|
905b4d |
+ *
|
|
|
905b4d |
+ * Create a new NULL-termintated list of strings by adding two lists together.
|
|
|
905b4d |
+ *
|
|
|
905b4d |
+ * @param[in] mem_ctx Talloc memory context for the new list.
|
|
|
905b4d |
+ * @param[in] l1 First NULL-termintated list of strings.
|
|
|
905b4d |
+ * @param[in] l2 Second NULL-termintated list of strings.
|
|
|
905b4d |
+ * @param[in] copy_strings If set to 'true' the list items will be copied
|
|
|
905b4d |
+ * otherwise only the pointers to the items are
|
|
|
905b4d |
+ * copied.
|
|
|
905b4d |
+ * @param[out] new_list New NULL-terminated list of strings. Must be freed
|
|
|
905b4d |
+ * with talloc_free() by the caller. If copy_strings
|
|
|
905b4d |
+ * is 'true' the new elements will be freed as well.
|
|
|
905b4d |
+ */
|
|
|
905b4d |
+errno_t add_strings_lists(TALLOC_CTX *mem_ctx, const char **l1, const char **l2,
|
|
|
905b4d |
+ bool copy_strings, char ***_new_list);
|
|
|
905b4d |
+
|
|
|
905b4d |
/* Copy a NULL-terminated string list
|
|
|
905b4d |
* Returns NULL on out of memory error or invalid input
|
|
|
905b4d |
*/
|
|
|
905b4d |
--
|
|
|
905b4d |
1.9.3
|
|
|
905b4d |
|