diff options
Diffstat (limited to 'source4/dsdb')
-rw-r--r-- | source4/dsdb/samdb/ldb_modules/subtree_delete.c | 137 |
1 files changed, 20 insertions, 117 deletions
diff --git a/source4/dsdb/samdb/ldb_modules/subtree_delete.c b/source4/dsdb/samdb/ldb_modules/subtree_delete.c index e1ce9c1fa8..34f5ccae83 100644 --- a/source4/dsdb/samdb/ldb_modules/subtree_delete.c +++ b/source4/dsdb/samdb/ldb_modules/subtree_delete.c @@ -2,6 +2,7 @@ ldb database library Copyright (C) Andrew Bartlett <abartlet@samba.org> 2006-2007 + Copyright (C) Andrew Tridgell <tridge@samba.org> 2009 Copyright (C) Stefan Metzmacher <metze@samba.org> 2007 Copyright (C) Simo Sorce <idra@samba.org> 2008 @@ -30,137 +31,39 @@ */ #include "ldb_module.h" +#include "dsdb/samdb/ldb_modules/util.h" -struct subtree_delete_context { - struct ldb_module *module; - struct ldb_request *req; - - int num_children; -}; - -static struct subtree_delete_context *subdel_ctx_init(struct ldb_module *module, - struct ldb_request *req) -{ - struct ldb_context *ldb; - struct subtree_delete_context *ac; - - ldb = ldb_module_get_ctx(module); - - ac = talloc_zero(req, struct subtree_delete_context); - if (ac == NULL) { - ldb_oom(ldb); - return NULL; - } - - ac->module = module; - ac->req = req; - - ac->num_children = 0; - - return ac; -} - -static int subtree_delete_search_callback(struct ldb_request *req, - struct ldb_reply *ares) -{ - struct ldb_context *ldb; - struct subtree_delete_context *ac; - int ret; - - ac = talloc_get_type(req->context, struct subtree_delete_context); - ldb = ldb_module_get_ctx(ac->module); - - if (!ares) { - ret = LDB_ERR_OPERATIONS_ERROR; - goto done; - } - if (ares->error != LDB_SUCCESS) { - return ldb_module_done(ac->req, ares->controls, - ares->response, ares->error); - } - - switch (ares->type) { - case LDB_REPLY_ENTRY: - /* count entry */ - ++(ac->num_children); - - talloc_free(ares); - ret = LDB_SUCCESS; - break; - - case LDB_REPLY_REFERRAL: - /* ignore */ - talloc_free(ares); - ret = LDB_SUCCESS; - break; - - case LDB_REPLY_DONE: - talloc_free(ares); - - if (ac->num_children > 0) { - ldb_asprintf_errstring(ldb, - "Cannot delete %s, not a leaf node " - "(has %d children)\n", - ldb_dn_get_linearized(ac->req->op.del.dn), - ac->num_children); - return ldb_module_done(ac->req, NULL, NULL, - LDB_ERR_NOT_ALLOWED_ON_NON_LEAF); - } - - /* ok no children, let the original request through */ - ret = ldb_next_request(ac->module, ac->req); - break; - } - -done: - if (ret != LDB_SUCCESS) { - return ldb_module_done(ac->req, NULL, NULL, ret); - } - - return LDB_SUCCESS; -} static int subtree_delete(struct ldb_module *module, struct ldb_request *req) { - struct ldb_context *ldb; - static const char * const attrs[2] = { "distinguishedName", NULL }; - struct ldb_request *search_req; - struct subtree_delete_context *ac; + static const char * const attrs[] = { NULL }; int ret; + struct ldb_result *res = NULL; - if (ldb_dn_is_special(req->op.rename.olddn)) { + if (ldb_dn_is_special(req->op.del.dn)) { /* do not manipulate our control entries */ return ldb_next_request(module, req); } - ldb = ldb_module_get_ctx(module); - - /* This gets complex: We need to: - - Do a search for all entires under this entry - - Wait for these results to appear - - In the callback for each result, count the children (if any) - - return an error if there are any - */ - - ac = subdel_ctx_init(module, req); - if (!ac) { - return LDB_ERR_OPERATIONS_ERROR; - } - - /* we do not really need to find all descendents, - * if there is even one single direct child, that's - * enough to bail out */ - ret = ldb_build_search_req(&search_req, ldb, ac, - req->op.del.dn, LDB_SCOPE_ONELEVEL, - "(objectClass=*)", attrs, - req->controls, - ac, subtree_delete_search_callback, - req); + /* see if we have any children */ + ret = dsdb_module_search(module, req, &res, req->op.del.dn, LDB_SCOPE_ONELEVEL, attrs, + DSDB_SEARCH_SHOW_DELETED, NULL); if (ret != LDB_SUCCESS) { + talloc_free(res); return ret; } + if (res->count > 0) { + ldb_asprintf_errstring(ldb_module_get_ctx(module), + "Cannot delete %s, not a leaf node " + "(has %d children)\n", + ldb_dn_get_linearized(req->op.del.dn), + res->count); + talloc_free(res); + return LDB_ERR_NOT_ALLOWED_ON_NON_LEAF; + } + talloc_free(res); - return ldb_next_request(module, search_req); + return ldb_next_request(module, req); } const struct ldb_module_ops ldb_subtree_delete_module_ops = { |