From e883d16914dea7abb79a653376b7d919e01707f8 Mon Sep 17 00:00:00 2001
From: Stephen Gallagher <sgallagh@redhat.com>
Date: Wed, 8 Dec 2010 14:35:35 -0500
Subject: [PATCH 1/2] Add sysdb_has_enumerated and sysdb_set_enumerated helper functions

Includes a unit test
---
 src/db/sysdb.c          |  142 +++++++++++++++++++++++++++++++++++++++++++++++
 src/db/sysdb.h          |   10 +++
 src/tests/sysdb-tests.c |   40 +++++++++++++
 3 files changed, 192 insertions(+), 0 deletions(-)

diff --git a/src/db/sysdb.c b/src/db/sysdb.c
index ace31a46c8c715aacb7148a9ee265d2fdb363e11..8806fe05ffcfd92190bf8ab1af18b50407c4345b 100644
--- a/src/db/sysdb.c
+++ b/src/db/sysdb.c
@@ -1863,3 +1863,145 @@ errno_t sysdb_attrs_to_list(TALLOC_CTX *memctx,
     *_list = list;
     return EOK;
 }
+
+errno_t sysdb_has_enumerated(struct sysdb_ctx *ctx,
+                             struct sss_domain_info *dom,
+                             bool *has_enumerated)
+{
+    errno_t ret;
+    int lret;
+    struct ldb_dn *base_dn;
+    struct ldb_result *res;
+    const char *attributes[2] = {SYSDB_HAS_ENUMERATED,
+                                 NULL};
+    TALLOC_CTX *tmpctx;
+
+
+    tmpctx = talloc_new(NULL);
+    if (!tmpctx) {
+        ret = ENOMEM;
+        goto done;
+    }
+
+    base_dn = ldb_dn_new_fmt(tmpctx, ctx->ldb,
+                             SYSDB_DOM_BASE,
+                             dom->name);
+    if (!base_dn) {
+        ret = ENOMEM;
+        goto done;
+    }
+
+    lret = ldb_search(ctx->ldb, tmpctx, &res, base_dn,
+                      LDB_SCOPE_BASE, attributes, NULL);
+    if (lret != LDB_SUCCESS) {
+        ret = sysdb_error_to_errno(lret);
+        goto done;
+    }
+
+    if (res->count == 0) {
+        /* This entry has not been populated in LDB
+         * This is a common case, as unlike LDAP,
+         * LDB does not need to have all of its parent
+         * objects actually exist.
+         * This object in the sysdb exists mostly just
+         * to contain this attribute.
+         */
+        *has_enumerated = false;
+        ret = EOK;
+        goto done;
+    } else if (res->count != 1) {
+        DEBUG(0, ("Corrupted database. "
+                  "More than one entry for base search.\n"));
+        ret = EIO;
+        goto done;
+    }
+
+    /* Object existed. Return the stored value */
+    *has_enumerated = ldb_msg_find_attr_as_bool(res->msgs[0],
+                                                SYSDB_HAS_ENUMERATED,
+                                                false);
+
+    ret = EOK;
+
+done:
+    talloc_free(tmpctx);
+    return ret;
+}
+
+errno_t sysdb_set_enumerated(struct sysdb_ctx *ctx,
+                             struct sss_domain_info *dom,
+                             bool enumerated)
+{
+    errno_t ret;
+    int lret;
+    TALLOC_CTX *tmp_ctx;
+    struct ldb_message *msg;
+    struct ldb_result *res;
+    struct ldb_dn *dn;
+
+    tmp_ctx = talloc_new(NULL);
+    if (!tmp_ctx) {
+        ret = ENOMEM;
+        goto done;
+    }
+
+    dn = ldb_dn_new_fmt(tmp_ctx, ctx->ldb,
+                        SYSDB_DOM_BASE,
+                        dom->name);
+    if (!dn) {
+        ret = ENOMEM;
+        goto done;
+    }
+
+    lret = ldb_search(ctx->ldb, tmp_ctx, &res,
+                      dn, LDB_SCOPE_BASE,
+                      NULL, NULL);
+    if (lret != LDB_SUCCESS) {
+        ret = EIO;
+        goto done;
+    }
+
+    msg = ldb_msg_new(tmp_ctx);
+    if (!msg) {
+        ret = ENOMEM;
+        goto done;
+    }
+    msg->dn = dn;
+
+    if (res->count == 0) {
+        lret = ldb_msg_add_string(msg, "cn", dom->name);
+        if (lret != LDB_SUCCESS) {
+            ret = sysdb_error_to_errno(lret);
+            goto done;
+        }
+    } else if (res->count != 1) {
+        DEBUG(0, ("Got more than one reply for base search!\n"));
+        ret = EIO;
+        goto done;
+    } else {
+        lret = ldb_msg_add_empty(msg, SYSDB_HAS_ENUMERATED,
+                                 LDB_FLAG_MOD_REPLACE, NULL);
+        if (lret != LDB_SUCCESS) {
+            ret = sysdb_error_to_errno(lret);
+            goto done;
+        }
+    }
+    lret = ldb_msg_add_fmt(msg, SYSDB_HAS_ENUMERATED, "%s",
+                           enumerated?"TRUE":"FALSE");
+    if (lret != LDB_SUCCESS) {
+        ret = sysdb_error_to_errno(lret);
+        goto done;
+    }
+
+    if (res->count) {
+        lret = ldb_modify(ctx->ldb, msg);
+    } else {
+        lret = ldb_add(ctx->ldb, msg);
+    }
+
+    ret = sysdb_error_to_errno(lret);
+
+done:
+    talloc_free(tmp_ctx);
+    return ret;
+}
diff --git a/src/db/sysdb.h b/src/db/sysdb.h
index ed100b69967f19543b6c70f8d349ac239f24a6a1..b5eed49b4ae83b195eed80a8b35df4c2906330bf 100644
--- a/src/db/sysdb.h
+++ b/src/db/sysdb.h
@@ -122,6 +122,8 @@
 #define SYSDB_NETGR_FILTER "(&("SYSDB_NC")("SYSDB_NAME"=%s))"
 #define SYSDB_NETGR_TRIPLES_FILTER "(|("SYSDB_NAME"=%s)("SYSDB_MEMBEROF"=%s))"
 
+#define SYSDB_HAS_ENUMERATED "has_enumerated"
+
 #define SYSDB_DEFAULT_ATTRS SYSDB_LAST_UPDATE, \
                             SYSDB_CACHE_EXPIRE, \
                             SYSDB_INITGR_EXPIRE, \
@@ -700,4 +702,12 @@ errno_t sysdb_netgr_to_entries(TALLOC_CTX *mem_ctx,
 errno_t sysdb_dn_sanitize(void *mem_ctx, const char *input,
                           char **sanitized);
 
+errno_t sysdb_has_enumerated(struct sysdb_ctx *ctx,
+                             struct sss_domain_info *dom,
+                             bool *has_enumerated);
+
+errno_t sysdb_set_enumerated(struct sysdb_ctx *ctx,
+                             struct sss_domain_info *dom,
+                             bool enumerated);
+
 #endif /* __SYS_DB_H__ */
diff --git a/src/tests/sysdb-tests.c b/src/tests/sysdb-tests.c
index 797b18d63f482ba3cf9dcf0e8d0d6cb676b37312..4d21395a09771f7b7027d2a68d785881b9effa9f 100644
--- a/src/tests/sysdb-tests.c
+++ b/src/tests/sysdb-tests.c
@@ -2857,6 +2857,43 @@ START_TEST(test_odd_characters)
 }
 END_TEST
 
+START_TEST(test_sysdb_has_enumerated)
+{
+    errno_t ret;
+    struct sysdb_test_ctx *test_ctx;
+    bool enumerated;
+
+    /* Setup */
+    ret = setup_sysdb_tests(&test_ctx);
+    fail_if(ret != EOK, "Could not set up the test");
+
+    ret = sysdb_has_enumerated(test_ctx->sysdb,
+                               test_ctx->domain,
+                               &enumerated);
+    fail_if(ret != EOK, "Error [%d][%s] checking enumeration",
+                        ret, strerror(ret));
+
+    fail_if(enumerated, "Enumeration should default to false");
+
+    ret = sysdb_set_enumerated(test_ctx->sysdb,
+                               test_ctx->domain,
+                               true);
+    fail_if(ret != EOK, "Error [%d][%s] setting enumeration",
+                        ret, strerror(ret));
+
+    /* Recheck enumeration status */
+    ret = sysdb_has_enumerated(test_ctx->sysdb,
+                               test_ctx->domain,
+                               &enumerated);
+    fail_if(ret != EOK, "Error [%d][%s] checking enumeration",
+                        ret, strerror(ret));
+
+    fail_unless(enumerated, "Enumeration should have been set to true");
+
+    talloc_free(test_ctx);
+}
+END_TEST
+
 Suite *create_sysdb_suite(void)
 {
     Suite *s = suite_create("sysdb");
@@ -2981,6 +3018,9 @@ Suite *create_sysdb_suite(void)
     /* Test unusual characters */
     tcase_add_test(tc_sysdb, test_odd_characters);
 
+    /* Test sysdb enumerated flag */
+    tcase_add_test(tc_sysdb, test_sysdb_has_enumerated);
+
 /* ===== NETGROUP TESTS ===== */
 
     /* Create a new netgroup */
-- 
1.7.3.2

