From a70e916dd49b2764af8cbd3c4fb41a4ef10de7d0 Mon Sep 17 00:00:00 2001 From: Sumit Bose Date: Wed, 8 Oct 2014 16:12:52 +0200 Subject: [PATCH 07/10] sysdb: add sysdb_attrs_add_val_safe() and sysdb_attrs_add_string_safe() sysdb_attrs_add_val_safe() works like sysdb_attrs_add_val() but checks if the attribute value to add already exists. In this case the value list is not changed. This is useful if values are added from different sources at different times to avoid LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS errors from ldb_modify() later on. sysdb_attrs_add_string_safe() does the same for string arguments --- src/db/sysdb.c | 40 ++++++++++++++++++- src/db/sysdb.h | 4 ++ src/tests/sysdb-tests.c | 103 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 145 insertions(+), 2 deletions(-) diff --git a/src/db/sysdb.c b/src/db/sysdb.c index 88cff24..8d6f00b 100644 --- a/src/db/sysdb.c +++ b/src/db/sysdb.c @@ -508,18 +508,31 @@ int sysdb_attrs_get_string_array(struct sysdb_attrs *attrs, const char *name, return EOK; } -int sysdb_attrs_add_val(struct sysdb_attrs *attrs, - const char *name, const struct ldb_val *val) + +static int sysdb_attrs_add_val_int(struct sysdb_attrs *attrs, + const char *name, bool check_values, + const struct ldb_val *val) { struct ldb_message_element *el = NULL; struct ldb_val *vals; int ret; + size_t c; ret = sysdb_attrs_get_el(attrs, name, &el); if (ret != EOK) { return ret; } + if (check_values) { + for (c = 0; c < el->num_values; c++) { + if (val->length == el->values[c].length + && memcmp(val->data, el->values[c].data, + val->length) == 0) { + return EOK; + } + } + } + vals = talloc_realloc(attrs->a, el->values, struct ldb_val, el->num_values+1); if (!vals) return ENOMEM; @@ -535,6 +548,29 @@ int sysdb_attrs_add_val(struct sysdb_attrs *attrs, return EOK; } +int sysdb_attrs_add_val(struct sysdb_attrs *attrs, + const char *name, const struct ldb_val *val) +{ + return sysdb_attrs_add_val_int(attrs, name, false, val); +} + +/* Check if the same value already exists. */ +int sysdb_attrs_add_val_safe(struct sysdb_attrs *attrs, + const char *name, const struct ldb_val *val) +{ + return sysdb_attrs_add_val_int(attrs, name, true, val); +} + +int sysdb_attrs_add_string_safe(struct sysdb_attrs *attrs, + const char *name, const char *str) +{ + struct ldb_val v; + + v.data = (uint8_t *)discard_const(str); + v.length = strlen(str); + + return sysdb_attrs_add_val_safe(attrs, name, &v); +} int sysdb_attrs_add_string(struct sysdb_attrs *attrs, const char *name, const char *str) diff --git a/src/db/sysdb.h b/src/db/sysdb.h index b039a67..602db2c 100644 --- a/src/db/sysdb.h +++ b/src/db/sysdb.h @@ -287,6 +287,10 @@ struct range_info { /* values are copied in the structure, allocated on "attrs" */ int sysdb_attrs_add_val(struct sysdb_attrs *attrs, const char *name, const struct ldb_val *val); +int sysdb_attrs_add_val_safe(struct sysdb_attrs *attrs, + const char *name, const struct ldb_val *val); +int sysdb_attrs_add_string_safe(struct sysdb_attrs *attrs, + const char *name, const char *str); int sysdb_attrs_add_string(struct sysdb_attrs *attrs, const char *name, const char *str); int sysdb_attrs_add_lower_case_string(struct sysdb_attrs *attrs, diff --git a/src/tests/sysdb-tests.c b/src/tests/sysdb-tests.c index c251156..e01ddf4 100644 --- a/src/tests/sysdb-tests.c +++ b/src/tests/sysdb-tests.c @@ -4630,6 +4630,106 @@ START_TEST(test_sysdb_attrs_get_string_array) } END_TEST +START_TEST(test_sysdb_attrs_add_val) +{ + int ret; + struct sysdb_attrs *attrs; + TALLOC_CTX *tmp_ctx; + struct ldb_val val = {discard_const(TEST_ATTR_VALUE), + sizeof(TEST_ATTR_VALUE) - 1}; + + tmp_ctx = talloc_new(NULL); + fail_unless(tmp_ctx != NULL, "talloc_new failed"); + + attrs = sysdb_new_attrs(NULL); + fail_unless(attrs != NULL, "sysdb_new_attrs failed"); + + ret = sysdb_attrs_add_val(attrs, TEST_ATTR_NAME, &val); + fail_unless(ret == EOK, "sysdb_attrs_add_val failed."); + + ret = sysdb_attrs_add_val(attrs, TEST_ATTR_NAME, &val); + fail_unless(ret == EOK, "sysdb_attrs_add_val failed."); + + fail_unless(attrs->num == 1, "Unexpected number of attributes."); + fail_unless(strcmp(attrs->a[0].name, TEST_ATTR_NAME) == 0, + "Unexpected attribute name."); + fail_unless(attrs->a[0].num_values == 2, + "Unexpected number of attribute values."); + fail_unless(ldb_val_string_cmp(&attrs->a[0].values[0], + TEST_ATTR_VALUE) == 0, + "Unexpected attribute value."); + fail_unless(ldb_val_string_cmp(&attrs->a[0].values[1], + TEST_ATTR_VALUE) == 0, + "Unexpected attribute value."); + + talloc_free(tmp_ctx); +} +END_TEST + +START_TEST(test_sysdb_attrs_add_val_safe) +{ + int ret; + struct sysdb_attrs *attrs; + TALLOC_CTX *tmp_ctx; + struct ldb_val val = {discard_const(TEST_ATTR_VALUE), + sizeof(TEST_ATTR_VALUE) - 1}; + + tmp_ctx = talloc_new(NULL); + fail_unless(tmp_ctx != NULL, "talloc_new failed"); + + attrs = sysdb_new_attrs(NULL); + fail_unless(attrs != NULL, "sysdb_new_attrs failed"); + + ret = sysdb_attrs_add_val(attrs, TEST_ATTR_NAME, &val); + fail_unless(ret == EOK, "sysdb_attrs_add_val failed."); + + ret = sysdb_attrs_add_val_safe(attrs, TEST_ATTR_NAME, &val); + fail_unless(ret == EOK, "sysdb_attrs_add_val failed."); + + fail_unless(attrs->num == 1, "Unexpected number of attributes."); + fail_unless(strcmp(attrs->a[0].name, TEST_ATTR_NAME) == 0, + "Unexpected attribute name."); + fail_unless(attrs->a[0].num_values == 1, + "Unexpected number of attribute values."); + fail_unless(ldb_val_string_cmp(&attrs->a[0].values[0], + TEST_ATTR_VALUE) == 0, + "Unexpected attribute value."); + + talloc_free(tmp_ctx); +} +END_TEST + +START_TEST(test_sysdb_attrs_add_string_safe) +{ + int ret; + struct sysdb_attrs *attrs; + TALLOC_CTX *tmp_ctx; + + tmp_ctx = talloc_new(NULL); + fail_unless(tmp_ctx != NULL, "talloc_new failed"); + + attrs = sysdb_new_attrs(NULL); + fail_unless(attrs != NULL, "sysdb_new_attrs failed"); + + ret = sysdb_attrs_add_string(attrs, TEST_ATTR_NAME, TEST_ATTR_VALUE); + fail_unless(ret == EOK, "sysdb_attrs_add_val failed."); + + ret = sysdb_attrs_add_string_safe(attrs, TEST_ATTR_NAME, TEST_ATTR_VALUE); + fail_unless(ret == EOK, "sysdb_attrs_add_val failed."); + + fail_unless(attrs->num == 1, "Unexpected number of attributes."); + fail_unless(strcmp(attrs->a[0].name, TEST_ATTR_NAME) == 0, + "Unexpected attribute name."); + fail_unless(attrs->a[0].num_values == 1, + "Unexpected number of attribute values."); + fail_unless(ldb_val_string_cmp(&attrs->a[0].values[0], + TEST_ATTR_VALUE) == 0, + "Unexpected attribute value."); + + talloc_free(tmp_ctx); +} +END_TEST + START_TEST (test_sysdb_search_return_ENOENT) { struct sysdb_test_ctx *test_ctx; @@ -6033,6 +6133,9 @@ Suite *create_sysdb_suite(void) /* ===== UTIL TESTS ===== */ tcase_add_test(tc_sysdb, test_sysdb_attrs_get_string_array); + tcase_add_test(tc_sysdb, test_sysdb_attrs_add_val); + tcase_add_test(tc_sysdb, test_sysdb_attrs_add_val_safe); + tcase_add_test(tc_sysdb, test_sysdb_attrs_add_string_safe); /* ===== Test search return empty result ===== */ tcase_add_test(tc_sysdb, test_sysdb_search_return_ENOENT); -- 1.8.3.1