From c2a29bea5248554a9112d051a7b5be492aa729b6 Mon Sep 17 00:00:00 2001 From: Sumit Bose Date: Thu, 29 Oct 2009 12:57:57 +0100 Subject: add sysdb_delete_recursive request to sysdb API --- server/db/sysdb.c | 12 ++++ server/db/sysdb.h | 10 +++ server/db/sysdb_ops.c | 153 +++++++++++++++++++++++++++++++++++++++++++++ server/tests/sysdb-tests.c | 111 ++++++++++++++++++++++++++++++-- 4 files changed, 282 insertions(+), 4 deletions(-) diff --git a/server/db/sysdb.c b/server/db/sysdb.c index 5811ddc9..a2ac3b22 100644 --- a/server/db/sysdb.c +++ b/server/db/sysdb.c @@ -1417,3 +1417,15 @@ int sysdb_get_ctx_from_list(struct sysdb_ctx_list *ctx_list, /* definitely not found */ return ENOENT; } + + +int compare_ldb_dn_comp_num(const void *m1, const void *m2) +{ + struct ldb_message *msg1 = talloc_get_type(*(void **) discard_const(m1), + struct ldb_message); + struct ldb_message *msg2 = talloc_get_type(*(void **) discard_const(m2), + struct ldb_message); + + return ldb_dn_get_comp_num(msg2->dn) - ldb_dn_get_comp_num(msg1->dn); +} + diff --git a/server/db/sysdb.h b/server/db/sysdb.h index 00a3378c..72f56dba 100644 --- a/server/db/sysdb.h +++ b/server/db/sysdb.h @@ -190,6 +190,8 @@ struct ldb_dn *sysdb_custom_dn(struct sysdb_ctx *ctx, void *memctx, struct ldb_context *sysdb_ctx_get_ldb(struct sysdb_ctx *ctx); struct ldb_context *sysdb_handle_get_ldb(struct sysdb_handle *handle); +int compare_ldb_dn_comp_num(const void *m1, const void *m2); + /* function to start and finish a transaction * sysdb_transaction_send() will queue a request for a transaction * when it is done it will call the tevent_req callback, which must @@ -311,6 +313,14 @@ struct tevent_req *sysdb_delete_entry_send(TALLOC_CTX *mem_ctx, bool ignore_not_found); int sysdb_delete_entry_recv(struct tevent_req *req); + +struct tevent_req *sysdb_delete_recursive_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct sysdb_handle *handle, + struct ldb_dn *dn, + bool ignore_not_found); +int sysdb_delete_recursive_recv(struct tevent_req *req); + /* Search Entry */ struct tevent_req *sysdb_search_entry_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, diff --git a/server/db/sysdb_ops.c b/server/db/sysdb_ops.c index acff5e51..0dcf2e37 100644 --- a/server/db/sysdb_ops.c +++ b/server/db/sysdb_ops.c @@ -300,6 +300,159 @@ int sysdb_delete_entry_recv(struct tevent_req *req) } +/* =Remove-Subentries-From-Sysdb=============================================== */ + +struct sysdb_delete_recursive_state { + struct tevent_context *ev; + struct sysdb_handle *handle; + + bool ignore_not_found; + + struct ldb_reply *ldbreply; + size_t msgs_count; + struct ldb_message **msgs; + size_t current_item; +}; + +static void sysdb_delete_search_done(struct tevent_req *subreq); +static void sysdb_delete_recursive_prepare_op(struct tevent_req *req); +static void sysdb_delete_recursive_op_done(struct tevent_req *req); + +struct tevent_req *sysdb_delete_recursive_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct sysdb_handle *handle, + struct ldb_dn *dn, + bool ignore_not_found) +{ + struct tevent_req *req, *subreq; + struct sysdb_delete_recursive_state *state; + int ret; + const char *no_attrs[] = { NULL }; + + req = tevent_req_create(mem_ctx, &state, + struct sysdb_delete_recursive_state); + if (!req) return NULL; + + state->ev = ev; + state->handle = handle; + state->ignore_not_found = ignore_not_found; + state->ldbreply = NULL; + state->msgs_count = 0; + state->msgs = NULL; + state->current_item = 0; + + subreq = sysdb_search_entry_send(state, ev, handle, dn, LDB_SCOPE_SUBTREE, + "(distinguishedName=*)", no_attrs); + + if (!subreq) { + ERROR_OUT(ret, ENOMEM, fail); + } + tevent_req_set_callback(subreq, sysdb_delete_search_done, req); + + return req; + +fail: + DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret))); + tevent_req_error(req, ret); + tevent_req_post(req, ev); + return req; +} + +static void sysdb_delete_search_done(struct tevent_req *subreq) +{ + struct tevent_req *req = tevent_req_callback_data(subreq, + struct tevent_req); + struct sysdb_delete_recursive_state *state = tevent_req_data(req, + struct sysdb_delete_recursive_state); + int ret; + + ret = sysdb_search_entry_recv(subreq, state, &state->msgs_count, + &state->msgs); + talloc_zfree(subreq); + if (ret) { + if (state->ignore_not_found && ret == ENOENT) { + tevent_req_done(req); + return; + } + DEBUG(6, ("Search error: %d (%s)\n", ret, strerror(ret))); + tevent_req_error(req, ret); + return; + } + DEBUG(9, ("Found [%d] items to delete.\n", state->msgs_count)); + + qsort(state->msgs, state->msgs_count, sizeof(struct ldb_message *), + compare_ldb_dn_comp_num); + + state->current_item = 0; + sysdb_delete_recursive_prepare_op(req); +} + +static void sysdb_delete_recursive_prepare_op(struct tevent_req *req) +{ + struct sysdb_delete_recursive_state *state = tevent_req_data(req, + struct sysdb_delete_recursive_state); + struct tevent_req *subreq; + int ret; + struct ldb_request *ldbreq; + + if (state->current_item < state->msgs_count) { + DEBUG(9 ,("Trying to delete [%s].\n", + ldb_dn_canonical_string(state, + state->msgs[state->current_item]->dn))); + ret = ldb_build_del_req(&ldbreq, state->handle->ctx->ldb, state, + state->msgs[state->current_item]->dn, NULL, + NULL, NULL, NULL); + if (ret != LDB_SUCCESS) { + DEBUG(1, ("LDB Error: %s(%d)\nError Message: [%s]\n", + ldb_strerror(ret), ret, + ldb_errstring(state->handle->ctx->ldb))); + ret = sysdb_error_to_errno(ret); + goto fail; + } + + subreq = sldb_request_send(state, state->ev, state->handle->ctx->ldb, + ldbreq); + if (!subreq) { + ret = ENOMEM; + goto fail; + } + + state->current_item++; + tevent_req_set_callback(subreq, sysdb_delete_recursive_op_done, req); + return; + } + + tevent_req_done(req); + return; + +fail: + DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret))); + tevent_req_error(req, ret); +} + +static void sysdb_delete_recursive_op_done(struct tevent_req *subreq) +{ + struct tevent_req *req = tevent_req_callback_data(subreq, + struct tevent_req); + int ret; + + ret = sysdb_op_default_recv(subreq); + talloc_zfree(subreq); + if (ret) { + DEBUG(6, ("Delete error: %d (%s)\n", ret, strerror(ret))); + tevent_req_error(req, ret); + return; + } + + sysdb_delete_recursive_prepare_op(req); +} + +int sysdb_delete_recursive_recv(struct tevent_req *req) +{ + return sysdb_op_default_recv(req); +} + + /* =Search-Entry========================================================== */ static void sysdb_search_entry_done(struct tevent_req *subreq); diff --git a/server/tests/sysdb-tests.c b/server/tests/sysdb-tests.c index 9d0c60d4..ed61e279 100644 --- a/server/tests/sysdb-tests.c +++ b/server/tests/sysdb-tests.c @@ -843,6 +843,7 @@ static void test_store_custom(struct tevent_req *subreq) struct test_data *data = tevent_req_callback_data(subreq, struct test_data); int ret; + char *object_name; ret = sysdb_transaction_recv(subreq, data, &data->handle); talloc_zfree(subreq); @@ -850,8 +851,13 @@ static void test_store_custom(struct tevent_req *subreq) return test_return(data, ret); } + object_name = talloc_asprintf(data, "%s_%d", CUSTOM_TEST_OBJECT, data->uid); + if (!object_name) { + return test_return(data, ENOMEM); + } + subreq = sysdb_store_custom_send(data, data->ev, data->handle, - data->ctx->domain, CUSTOM_TEST_OBJECT, + data->ctx->domain, object_name, CUSTOM_TEST_CONTAINER, data->attrs); if (!subreq) { return test_return(data, ENOMEM); @@ -877,6 +883,10 @@ static void test_search_custom_by_name_done(struct tevent_req *subreq) ret = sysdb_search_custom_recv(subreq, data, &data->msg); talloc_zfree(subreq); + if (ret != EOK) { + data->error = ret; + goto done; + } fail_unless(data->msg->num_elements == 1, "Wrong number of results, expected [1] got [%d]", @@ -889,6 +899,7 @@ static void test_search_custom_by_name_done(struct tevent_req *subreq) TEST_ATTR_VALUE, data->msg->elements[0].values[0].length) == 0, "Wrong attribute value"); +done: data->finished = true; return; } @@ -901,6 +912,10 @@ static void test_search_custom_update_done(struct tevent_req *subreq) ret = sysdb_search_custom_recv(subreq, data, &data->msg); talloc_zfree(subreq); + if (ret != EOK) { + data->error = ret; + goto done; + } fail_unless(data->msg->num_elements == 2, "Wrong number of results, expected [1] got [%d]", @@ -922,6 +937,7 @@ static void test_search_custom_update_done(struct tevent_req *subreq) el->values[0].length) == 0, "Wrong attribute value"); +done: data->finished = true; return; } @@ -1010,6 +1026,46 @@ static void test_search_all_users_done(struct tevent_req *subreq) return; } +static void test_delete_recursive_done(struct tevent_req *subreq); + +static void test_delete_recursive(struct tevent_req *subreq) +{ + struct test_data *data = tevent_req_callback_data(subreq, + struct test_data); + int ret; + struct ldb_dn *dn; + + ret = sysdb_transaction_recv(subreq, data, &data->handle); + talloc_zfree(subreq); + if (ret != EOK) { + return test_return(data, ret); + } + + dn = ldb_dn_new_fmt(data, data->handle->ctx->ldb, SYSDB_DOM_BASE, + "LOCAL"); + if (!dn) { + return test_return(data, ENOMEM); + } + + subreq = sysdb_delete_recursive_send(data, data->ev, data->handle, dn, + false); + if (!subreq) { + return test_return(data, ENOMEM); + } + tevent_req_set_callback(subreq, test_delete_recursive_done, data); +} + +static void test_delete_recursive_done(struct tevent_req *subreq) +{ + struct test_data *data = tevent_req_callback_data(subreq, struct test_data); + int ret; + + ret = sysdb_delete_recursive_recv(subreq); + talloc_zfree(subreq); + fail_unless(ret == EOK, "sysdb_delete_recursive_recv returned [%d]", ret); + return test_return(data, ret); +} + START_TEST (test_sysdb_store_user) { struct sysdb_test_ctx *test_ctx; @@ -1826,6 +1882,7 @@ START_TEST (test_sysdb_store_custom) data = talloc_zero(test_ctx, struct test_data); data->ctx = test_ctx; data->ev = test_ctx->ev; + data->uid = _i; data->attrs = sysdb_new_attrs(test_ctx); if (ret != EOK) { fail("Could not create attribute list"); @@ -1862,6 +1919,7 @@ START_TEST (test_sysdb_search_custom_by_name) struct test_data *data; struct tevent_req *subreq; int ret; + char *object_name; /* Setup */ ret = setup_sysdb_tests(&test_ctx); @@ -1879,10 +1937,13 @@ START_TEST (test_sysdb_search_custom_by_name) data->attrlist[0] = TEST_ATTR_NAME; data->attrlist[1] = NULL; + object_name = talloc_asprintf(data, "%s_%d", CUSTOM_TEST_OBJECT, 29010); + fail_unless(object_name != NULL, "talloc_asprintf failed"); + subreq = sysdb_search_custom_by_name_send(data, data->ev, data->ctx->sysdb, NULL, data->ctx->domain, - CUSTOM_TEST_OBJECT, + object_name, CUSTOM_TEST_CONTAINER, data->attrlist); if (!subreq) { @@ -1917,6 +1978,7 @@ START_TEST (test_sysdb_update_custom) data = talloc_zero(test_ctx, struct test_data); data->ctx = test_ctx; data->ev = test_ctx->ev; + data->uid = 29010; data->attrs = sysdb_new_attrs(test_ctx); if (ret != EOK) { fail("Could not create attribute list"); @@ -1961,6 +2023,7 @@ START_TEST (test_sysdb_search_custom_update) struct test_data *data; struct tevent_req *subreq; int ret; + char *object_name; /* Setup */ ret = setup_sysdb_tests(&test_ctx); @@ -1979,10 +2042,13 @@ START_TEST (test_sysdb_search_custom_update) data->attrlist[1] = TEST_ATTR_ADD_NAME; data->attrlist[2] = NULL; + object_name = talloc_asprintf(data, "%s_%d", CUSTOM_TEST_OBJECT, 29010); + fail_unless(object_name != NULL, "talloc_asprintf failed"); + subreq = sysdb_search_custom_by_name_send(data, data->ev, data->ctx->sysdb, NULL, data->ctx->domain, - CUSTOM_TEST_OBJECT, + object_name, CUSTOM_TEST_CONTAINER, data->attrlist); if (!subreq) { @@ -2210,6 +2276,40 @@ START_TEST (test_sysdb_search_all_users) } END_TEST +START_TEST (test_sysdb_delete_recursive) +{ + struct sysdb_test_ctx *test_ctx; + struct test_data *data; + struct tevent_req *subreq; + int ret; + + /* Setup */ + ret = setup_sysdb_tests(&test_ctx); + if (ret != EOK) { + fail("Could not set up the test"); + return; + } + + data = talloc_zero(test_ctx, struct test_data); + data->ctx = test_ctx; + data->ev = test_ctx->ev; + + subreq = sysdb_transaction_send(data, data->ev, test_ctx->sysdb); + if (!subreq) { + ret = ENOMEM; + } + + if (ret == EOK) { + tevent_req_set_callback(subreq, test_delete_recursive, data); + + ret = test_loop(data); + } + + fail_if(ret != EOK, "Recursive delete failed"); + talloc_free(test_ctx); +} +END_TEST + Suite *create_sysdb_suite(void) { Suite *s = suite_create("sysdb"); @@ -2295,12 +2395,15 @@ Suite *create_sysdb_suite(void) tcase_add_test(tc_sysdb, test_sysdb_remove_nonexistent_group); /* test custom operations */ - tcase_add_test(tc_sysdb, test_sysdb_store_custom); + tcase_add_loop_test(tc_sysdb, test_sysdb_store_custom, 29010, 29020); tcase_add_test(tc_sysdb, test_sysdb_search_custom_by_name); tcase_add_test(tc_sysdb, test_sysdb_update_custom); tcase_add_test(tc_sysdb, test_sysdb_search_custom_update); tcase_add_test(tc_sysdb, test_sysdb_delete_custom); + /* test recursive delete */ + tcase_add_test(tc_sysdb, test_sysdb_delete_recursive); + /* Add all test cases to the test suite */ suite_add_tcase(s, tc_sysdb); -- cgit