summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/db/sysdb.c75
-rw-r--r--src/db/sysdb.h6
-rw-r--r--src/tests/sysdb-tests.c31
3 files changed, 112 insertions, 0 deletions
diff --git a/src/db/sysdb.c b/src/db/sysdb.c
index f784e735..00cff372 100644
--- a/src/db/sysdb.c
+++ b/src/db/sysdb.c
@@ -1617,3 +1617,78 @@ int sysdb_attrs_replace_name(struct sysdb_attrs *attrs, const char *oldname,
return EOK;
}
+
+/* Search for all incidences of attr_name in a list of
+ * sysdb_attrs and add their value to a list
+ *
+ * TODO: Currently only works for single-valued
+ * attributes. Multi-valued attributes will return
+ * only the first entry
+ */
+errno_t sysdb_attrs_to_list(TALLOC_CTX *memctx,
+ struct sysdb_attrs **attrs,
+ int attr_count,
+ const char *attr_name,
+ char ***_list)
+{
+ int attr_idx;
+ int i;
+ char **list;
+ char **tmp_list;
+ int list_idx;
+
+ *_list = NULL;
+
+ /* Assume that every attrs entry contains the attr_name
+ * This may waste a little memory if some entries don't
+ * have the attribute, but it will save us the trouble
+ * of continuously resizing the array.
+ */
+ list = talloc_array(memctx, char *, attr_count+1);
+ if (!list) {
+ return ENOMEM;
+ }
+
+ list_idx = 0;
+ /* Loop through all entries in attrs */
+ for (attr_idx = 0; attr_idx < attr_count; attr_idx++) {
+ /* Examine each attribute within the entry */
+ for (i = 0; i < attrs[attr_idx]->num; i++) {
+ if (strcasecmp(attrs[attr_idx]->a->name, attr_name) == 0) {
+ /* Attribute name matches the requested name
+ * Copy it to the output list
+ */
+ list[list_idx] = talloc_strdup(
+ list,
+ (const char *)attrs[attr_idx]->a->values[0].data);
+ if (!list[list_idx]) {
+ talloc_free(list);
+ return ENOMEM;
+ }
+ list_idx++;
+
+ /* We only support single-valued attributes
+ * Break here and go on to the next entry
+ */
+ break;
+ }
+ }
+ }
+
+ list[list_idx] = NULL;
+
+ /* if list_idx < attr_count, do a realloc to
+ * reclaim unused memory
+ */
+ if (list_idx < attr_count) {
+ tmp_list = talloc_realloc(memctx, list, char *, list_idx+1);
+ if (!tmp_list) {
+ talloc_zfree(list);
+ return ENOMEM;
+ }
+ list = tmp_list;
+ }
+
+ *_list = list;
+ return EOK;
+}
diff --git a/src/db/sysdb.h b/src/db/sysdb.h
index 54119457..feda51b4 100644
--- a/src/db/sysdb.h
+++ b/src/db/sysdb.h
@@ -546,4 +546,10 @@ int sysdb_delete_group(TALLOC_CTX *mem_ctx,
struct sss_domain_info *domain,
const char *name, gid_t gid);
+errno_t sysdb_attrs_to_list(TALLOC_CTX *memctx,
+ struct sysdb_attrs **attrs,
+ int attr_count,
+ const char *attr_name,
+ char ***_list);
+
#endif /* __SYS_DB_H__ */
diff --git a/src/tests/sysdb-tests.c b/src/tests/sysdb-tests.c
index 44cb6dc3..ee179503 100644
--- a/src/tests/sysdb-tests.c
+++ b/src/tests/sysdb-tests.c
@@ -2076,6 +2076,35 @@ START_TEST (test_sysdb_memberof_check_memberuid_loop_without_group_5)
}
END_TEST
+START_TEST (test_sysdb_attrs_to_list)
+{
+ struct sysdb_attrs *attrs_list[3];
+ char **list;
+ errno_t ret;
+
+ TALLOC_CTX *test_ctx = talloc_new(NULL);
+
+ attrs_list[0] = sysdb_new_attrs(test_ctx);
+ sysdb_attrs_add_string(attrs_list[0], "test_attr", "attr1");
+ attrs_list[1] = sysdb_new_attrs(test_ctx);
+ sysdb_attrs_add_string(attrs_list[1], "test_attr", "attr2");
+ attrs_list[2] = sysdb_new_attrs(test_ctx);
+ sysdb_attrs_add_string(attrs_list[2], "nottest_attr", "attr3");
+
+ ret = sysdb_attrs_to_list(test_ctx, attrs_list, 3,
+ "test_attr", &list);
+ fail_unless(ret == EOK, "sysdb_attrs_to_list failed with code %d", ret);
+
+ fail_unless(strcmp(list[0],"attr1") == 0, "Expected [attr1], got [%s]",
+ list[0]);
+ fail_unless(strcmp(list[1],"attr2") == 0, "Expected [attr2], got [%s]",
+ list[1]);
+ fail_unless(list[2] == NULL, "List should be NULL-terminated");
+
+ talloc_free(test_ctx);
+}
+END_TEST
+
Suite *create_sysdb_suite(void)
{
Suite *s = suite_create("sysdb");
@@ -2185,6 +2214,8 @@ Suite *create_sysdb_suite(void)
tcase_add_test(tc_sysdb, test_sysdb_attrs_replace_name);
+ tcase_add_test(tc_sysdb, test_sysdb_attrs_to_list);
+
/* Add all test cases to the test suite */
suite_add_tcase(s, tc_sysdb);