4 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2006-2007
5 Copyright (C) Stefan Metzmacher <metze@samba.org> 2007
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
24 * Component: ldb subtree rename module
26 * Description: Rename a subtree in LDB
28 * Author: Andrew Bartlett
31 #include "ldb_includes.h"
33 struct subren_msg_store
{
34 struct subren_msg_store
*next
;
39 struct subtree_rename_context
{
40 struct ldb_module
*module
;
41 struct ldb_request
*req
;
43 struct subren_msg_store
*list
;
44 struct subren_msg_store
*current
;
47 static struct subtree_rename_context
*subren_ctx_init(struct ldb_module
*module
,
48 struct ldb_request
*req
)
50 struct subtree_rename_context
*ac
;
52 ac
= talloc_zero(req
, struct subtree_rename_context
);
64 static int subtree_rename_next_request(struct subtree_rename_context
*ac
);
66 static int subtree_rename_callback(struct ldb_request
*req
,
67 struct ldb_reply
*ares
)
69 struct subtree_rename_context
*ac
;
72 ac
= talloc_get_type(req
->context
, struct subtree_rename_context
);
75 return ldb_module_done(ac
->req
, NULL
, NULL
,
76 LDB_ERR_OPERATIONS_ERROR
);
79 if (ares
->error
!= LDB_SUCCESS
) {
80 return ldb_module_done(ac
->req
, ares
->controls
,
81 ares
->response
, ares
->error
);
84 if (ares
->type
!= LDB_REPLY_DONE
) {
85 ldb_set_errstring(ac
->module
->ldb
, "Invalid reply type!\n");
86 return ldb_module_done(ac
->req
, NULL
, NULL
,
87 LDB_ERR_OPERATIONS_ERROR
);
90 if (ac
->current
== NULL
) {
91 /* this was the last one */
92 return ldb_module_done(ac
->req
, ares
->controls
,
93 ares
->response
, LDB_SUCCESS
);
96 ret
= subtree_rename_next_request(ac
);
97 if (ret
!= LDB_SUCCESS
) {
98 return ldb_module_done(ac
->req
, NULL
, NULL
, ret
);
105 static int subtree_rename_next_request(struct subtree_rename_context
*ac
)
107 struct ldb_request
*req
;
110 if (ac
->current
== NULL
) {
111 return LDB_ERR_OPERATIONS_ERROR
;
114 ret
= ldb_build_rename_req(&req
, ac
->module
->ldb
, ac
->current
,
118 ac
, subtree_rename_callback
,
120 if (ret
!= LDB_SUCCESS
) {
124 ac
->current
= ac
->current
->next
;
126 return ldb_next_request(ac
->module
, req
);
129 static int subtree_rename_search_callback(struct ldb_request
*req
,
130 struct ldb_reply
*ares
)
132 struct subren_msg_store
*store
;
133 struct subtree_rename_context
*ac
;
136 ac
= talloc_get_type(req
->context
, struct subtree_rename_context
);
138 if (!ares
|| !ac
->current
) {
139 return ldb_module_done(ac
->req
, NULL
, NULL
,
140 LDB_ERR_OPERATIONS_ERROR
);
142 if (ares
->error
!= LDB_SUCCESS
) {
143 return ldb_module_done(ac
->req
, ares
->controls
,
144 ares
->response
, ares
->error
);
147 switch (ares
->type
) {
148 case LDB_REPLY_ENTRY
:
150 if (ldb_dn_compare(ares
->message
->dn
, ac
->list
->olddn
) == 0) {
151 /* this was already stored by the
152 * subtree_rename_search() */
157 store
= talloc_zero(ac
, struct subren_msg_store
);
159 return ldb_module_done(ac
->req
, NULL
, NULL
,
160 LDB_ERR_OPERATIONS_ERROR
);
162 ac
->current
->next
= store
;
165 /* the first list element contains the base for the rename */
166 store
->olddn
= talloc_steal(store
, ares
->message
->dn
);
167 store
->newdn
= ldb_dn_copy(store
, store
->olddn
);
169 if ( ! ldb_dn_remove_base_components(store
->newdn
,
170 ldb_dn_get_comp_num(ac
->list
->olddn
))) {
171 return ldb_module_done(ac
->req
, NULL
, NULL
,
172 LDB_ERR_OPERATIONS_ERROR
);
175 if ( ! ldb_dn_add_base(store
->newdn
, ac
->list
->newdn
)) {
176 return ldb_module_done(ac
->req
, NULL
, NULL
,
177 LDB_ERR_OPERATIONS_ERROR
);
182 case LDB_REPLY_REFERRAL
:
188 /* rewind ac->current */
189 ac
->current
= ac
->list
;
191 /* All dns set up, start with the first one */
192 ret
= subtree_rename_next_request(ac
);
194 if (ret
!= LDB_SUCCESS
) {
195 return ldb_module_done(ac
->req
, NULL
, NULL
, ret
);
205 static int subtree_rename(struct ldb_module
*module
, struct ldb_request
*req
)
207 static const char *attrs
[2] = { "distinguishedName", NULL
};
208 struct ldb_request
*search_req
;
209 struct subtree_rename_context
*ac
;
211 if (ldb_dn_is_special(req
->op
.rename
.olddn
)) { /* do not manipulate our control entries */
212 return ldb_next_request(module
, req
);
215 /* This gets complex: We need to:
216 - Do a search for all entires under this entry
217 - Wait for these results to appear
218 - In the callback for each result, issue a modify request
219 - That will include this rename, we hope
220 - Wait for each modify result
224 ac
= subren_ctx_init(module
, req
);
226 return LDB_ERR_OPERATIONS_ERROR
;
229 /* add this entry as the first to do */
230 ac
->current
= talloc_zero(ac
, struct subren_msg_store
);
231 if (ac
->current
== NULL
) {
232 return LDB_ERR_OPERATIONS_ERROR
;
234 ac
->current
->olddn
= req
->op
.rename
.olddn
;
235 ac
->current
->newdn
= req
->op
.rename
.newdn
;
236 ac
->list
= ac
->current
;
238 ret
= ldb_build_search_req(&search_req
, module
->ldb
, ac
,
239 req
->op
.rename
.olddn
,
245 subtree_rename_search_callback
,
247 if (ret
!= LDB_SUCCESS
) {
251 return ldb_next_request(module
, search_req
);
254 const struct ldb_module_ops ldb_subtree_rename_module_ops
= {
255 .name
= "subtree_rename",
256 .rename
= subtree_rename
,