4 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2006-2007
5 Copyright (C) Stefan Metzmacher <metze@samba.org> 2007
7 ** NOTE! The following LGPL license applies to the ldb
8 ** library. This does NOT imply that all of Samba is released
11 This library is free software; you can redistribute it and/or
12 modify it under the terms of the GNU Lesser General Public
13 License as published by the Free Software Foundation; either
14 version 3 of the License, or (at your option) any later version.
16 This library is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 Lesser General Public License for more details.
21 You should have received a copy of the GNU Lesser General Public
22 License along with this library; if not, see <http://www.gnu.org/licenses/>.
28 * Component: ldb subtree rename module
30 * Description: Rename a subtree in LDB
32 * Author: Andrew Bartlett
35 #include "ldb_includes.h"
37 struct subtree_rename_context {
38 struct ldb_module *module;
39 struct ldb_handle *handle;
40 struct ldb_request *orig_req;
42 struct ldb_request **down_req;
44 int finished_requests;
47 struct subtree_rename_search_context {
48 struct ldb_module *module;
49 struct ldb_request *orig_req;
50 struct ldb_handle *handle;
52 struct ldb_request **down_req;
54 int finished_requests;
57 static struct subtree_rename_context *subtree_rename_init_handle(struct ldb_request *req,
58 struct ldb_module *module)
60 struct subtree_rename_context *ac;
63 h = talloc_zero(req, struct ldb_handle);
65 ldb_set_errstring(module->ldb, "Out of Memory");
71 ac = talloc_zero(h, struct subtree_rename_context);
73 ldb_set_errstring(module->ldb, "Out of Memory");
90 static int subtree_rename_search_callback(struct ldb_context *ldb, void *context, struct ldb_reply *ares)
92 /* OK, we have one of *many* search results here:
94 We should also get the entry we tried to rename. This
95 callback handles this and everything below it.
98 if (ares->type == LDB_REPLY_ENTRY) {
99 /* And it is an actual entry: now create a rename from it */
100 struct subtree_rename_context *ac = talloc_get_type(context, struct subtree_rename_context);
101 struct ldb_request *req;
104 TALLOC_CTX *mem_ctx = talloc_new(ac);
106 struct ldb_dn *newdn = ldb_dn_copy(mem_ctx, ares->message->dn);
108 ldb_oom(ac->module->ldb);
109 return LDB_ERR_OPERATIONS_ERROR;
112 ldb_dn_remove_base_components(newdn, ldb_dn_get_comp_num(ac->orig_req->op.rename.olddn));
114 if (!ldb_dn_add_base(newdn, ac->orig_req->op.rename.newdn)) {
115 ldb_oom(ac->module->ldb);
116 return LDB_ERR_OPERATIONS_ERROR;
119 ret = ldb_build_rename_req(&req, ldb, mem_ctx,
126 if (ret != LDB_SUCCESS) return ret;
128 talloc_steal(req, newdn);
130 req->handle = ac->handle;
132 ac->down_req = talloc_realloc(ac, ac->down_req,
133 struct ldb_request *, ac->num_requests + 1);
135 ldb_oom(ac->module->ldb);
136 return LDB_ERR_OPERATIONS_ERROR;
138 ac->down_req[ac->num_requests] = req;
140 return ldb_next_request(ac->module, req);
151 static int subtree_rename(struct ldb_module *module, struct ldb_request *req)
153 const char *attrs[] = { NULL };
154 struct ldb_request *new_req;
155 struct subtree_rename_context *ac;
157 struct ldb_search_options_control *search_options;
158 if (ldb_dn_is_special(req->op.mod.message->dn)) { /* do not manipulate our control entries */
159 return ldb_next_request(module, req);
162 /* This gets complex: We need to:
163 - Do a search for all entires under this entry
164 - Wait for these results to appear
165 - In the callback for each result, issue a modify request
166 - That will include this rename, we hope
167 - Wait for each modify result
171 ac = subtree_rename_init_handle(req, module);
173 return LDB_ERR_OPERATIONS_ERROR;
176 ret = ldb_build_search_req(&new_req, module->ldb, req,
177 req->op.rename.olddn,
183 subtree_rename_search_callback);
185 /* We want to find any partitions under this entry. That way,
186 * if we try and rename a whole partition, the partitions
187 * module should cause us to fail the lot */
188 search_options = talloc(ac, struct ldb_search_options_control);
189 if (!search_options) {
190 ldb_oom(ac->module->ldb);
191 return LDB_ERR_OPERATIONS_ERROR;
193 search_options->search_options = LDB_SEARCH_OPTION_PHANTOM_ROOT;
195 ret = ldb_request_add_control(new_req, LDB_CONTROL_SEARCH_OPTIONS_OID, false, search_options);
196 if (ret != LDB_SUCCESS) {
200 new_req->handle = req->handle;
202 ac->down_req = talloc_realloc(ac, ac->down_req,
203 struct ldb_request *, ac->num_requests + 1);
205 ldb_oom(ac->module->ldb);
206 return LDB_ERR_OPERATIONS_ERROR;
208 ac->down_req[ac->num_requests] = new_req;
210 ldb_oom(ac->module->ldb);
211 return LDB_ERR_OPERATIONS_ERROR;
214 return ldb_next_request(module, req);
217 static int subtree_rename_wait_none(struct ldb_handle *handle) {
218 struct subtree_rename_context *ac;
220 if (!handle || !handle->private_data) {
221 return LDB_ERR_OPERATIONS_ERROR;
224 if (handle->state == LDB_ASYNC_DONE) {
225 return handle->status;
228 handle->state = LDB_ASYNC_PENDING;
229 handle->status = LDB_SUCCESS;
231 ac = talloc_get_type(handle->private_data, struct subtree_rename_context);
233 for (i=0; i < ac->num_requests; i++) {
234 ret = ldb_wait(ac->down_req[i]->handle, LDB_WAIT_NONE);
236 if (ret != LDB_SUCCESS) {
237 handle->status = ret;
240 if (ac->down_req[i]->handle->status != LDB_SUCCESS) {
241 handle->status = ac->down_req[i]->handle->status;
245 if (ac->down_req[i]->handle->state != LDB_ASYNC_DONE) {
253 handle->state = LDB_ASYNC_DONE;
258 static int subtree_rename_wait_all(struct ldb_handle *handle) {
262 while (handle->state != LDB_ASYNC_DONE) {
263 ret = subtree_rename_wait_none(handle);
264 if (ret != LDB_SUCCESS) {
269 return handle->status;
272 static int subtree_rename_wait(struct ldb_handle *handle, enum ldb_wait_type type)
274 if (type == LDB_WAIT_ALL) {
275 return subtree_rename_wait_all(handle);
277 return subtree_rename_wait_none(handle);
281 static const struct ldb_module_ops subtree_rename_ops = {
282 .name = "subtree_rename",
283 .rename = subtree_rename,
284 .wait = subtree_rename_wait,
287 int ldb_subtree_rename_init(void)
289 return ldb_register_module(&subtree_rename_ops);