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_module.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 ldb_context
*ldb
;
51 struct subtree_rename_context
*ac
;
53 ldb
= ldb_module_get_ctx(module
);
55 ac
= talloc_zero(req
, struct subtree_rename_context
);
67 static int subtree_rename_next_request(struct subtree_rename_context
*ac
);
69 static int subtree_rename_callback(struct ldb_request
*req
,
70 struct ldb_reply
*ares
)
72 struct ldb_context
*ldb
;
73 struct subtree_rename_context
*ac
;
76 ac
= talloc_get_type(req
->context
, struct subtree_rename_context
);
77 ldb
= ldb_module_get_ctx(ac
->module
);
80 return ldb_module_done(ac
->req
, NULL
, NULL
,
81 LDB_ERR_OPERATIONS_ERROR
);
84 if (ares
->type
== LDB_REPLY_REFERRAL
) {
85 return ldb_module_send_referral(ac
->req
, ares
->referral
);
88 if (ares
->error
!= LDB_SUCCESS
) {
89 return ldb_module_done(ac
->req
, ares
->controls
,
90 ares
->response
, ares
->error
);
93 if (ares
->type
!= LDB_REPLY_DONE
) {
94 ldb_set_errstring(ldb
, "Invalid reply type!\n");
95 return ldb_module_done(ac
->req
, NULL
, NULL
,
96 LDB_ERR_OPERATIONS_ERROR
);
99 if (ac
->current
== NULL
) {
100 /* this was the last one */
101 return ldb_module_done(ac
->req
, ares
->controls
,
102 ares
->response
, LDB_SUCCESS
);
105 ret
= subtree_rename_next_request(ac
);
106 if (ret
!= LDB_SUCCESS
) {
107 return ldb_module_done(ac
->req
, NULL
, NULL
, ret
);
114 static int subtree_rename_next_request(struct subtree_rename_context
*ac
)
116 struct ldb_context
*ldb
;
117 struct ldb_request
*req
;
120 ldb
= ldb_module_get_ctx(ac
->module
);
122 if (ac
->current
== NULL
) {
123 return LDB_ERR_OPERATIONS_ERROR
;
126 ret
= ldb_build_rename_req(&req
, ldb
, ac
->current
,
130 ac
, subtree_rename_callback
,
132 if (ret
!= LDB_SUCCESS
) {
136 ac
->current
= ac
->current
->next
;
138 return ldb_next_request(ac
->module
, req
);
141 static int subtree_rename_search_callback(struct ldb_request
*req
,
142 struct ldb_reply
*ares
)
144 struct subren_msg_store
*store
;
145 struct subtree_rename_context
*ac
;
148 ac
= talloc_get_type(req
->context
, struct subtree_rename_context
);
150 if (!ares
|| !ac
->current
) {
151 return ldb_module_done(ac
->req
, NULL
, NULL
,
152 LDB_ERR_OPERATIONS_ERROR
);
154 if (ares
->error
!= LDB_SUCCESS
) {
155 return ldb_module_done(ac
->req
, ares
->controls
,
156 ares
->response
, ares
->error
);
159 switch (ares
->type
) {
160 case LDB_REPLY_ENTRY
:
162 if (ldb_dn_compare(ares
->message
->dn
, ac
->list
->olddn
) == 0) {
163 /* this was already stored by the
164 * subtree_rename_search() */
169 store
= talloc_zero(ac
, struct subren_msg_store
);
171 return ldb_module_done(ac
->req
, NULL
, NULL
,
172 LDB_ERR_OPERATIONS_ERROR
);
174 ac
->current
->next
= store
;
177 /* the first list element contains the base for the rename */
178 store
->olddn
= talloc_steal(store
, ares
->message
->dn
);
179 store
->newdn
= ldb_dn_copy(store
, store
->olddn
);
181 if ( ! ldb_dn_remove_base_components(store
->newdn
,
182 ldb_dn_get_comp_num(ac
->list
->olddn
))) {
183 return ldb_module_done(ac
->req
, NULL
, NULL
,
184 LDB_ERR_OPERATIONS_ERROR
);
187 if ( ! ldb_dn_add_base(store
->newdn
, ac
->list
->newdn
)) {
188 return ldb_module_done(ac
->req
, NULL
, NULL
,
189 LDB_ERR_OPERATIONS_ERROR
);
194 case LDB_REPLY_REFERRAL
:
200 /* rewind ac->current */
201 ac
->current
= ac
->list
;
203 /* All dns set up, start with the first one */
204 ret
= subtree_rename_next_request(ac
);
206 if (ret
!= LDB_SUCCESS
) {
207 return ldb_module_done(ac
->req
, NULL
, NULL
, ret
);
217 static int subtree_rename(struct ldb_module
*module
, struct ldb_request
*req
)
219 struct ldb_context
*ldb
;
220 static const char *attrs
[2] = { "distinguishedName", NULL
};
221 struct ldb_request
*search_req
;
222 struct subtree_rename_context
*ac
;
224 if (ldb_dn_is_special(req
->op
.rename
.olddn
)) { /* do not manipulate our control entries */
225 return ldb_next_request(module
, req
);
228 ldb
= ldb_module_get_ctx(module
);
230 /* This gets complex: We need to:
231 - Do a search for all entires under this entry
232 - Wait for these results to appear
233 - In the callback for each result, issue a modify request
234 - That will include this rename, we hope
235 - Wait for each modify result
239 ac
= subren_ctx_init(module
, req
);
241 return LDB_ERR_OPERATIONS_ERROR
;
244 /* add this entry as the first to do */
245 ac
->current
= talloc_zero(ac
, struct subren_msg_store
);
246 if (ac
->current
== NULL
) {
247 return LDB_ERR_OPERATIONS_ERROR
;
249 ac
->current
->olddn
= req
->op
.rename
.olddn
;
250 ac
->current
->newdn
= req
->op
.rename
.newdn
;
251 ac
->list
= ac
->current
;
253 ret
= ldb_build_search_req(&search_req
, ldb
, ac
,
254 req
->op
.rename
.olddn
,
260 subtree_rename_search_callback
,
262 if (ret
!= LDB_SUCCESS
) {
266 return ldb_next_request(module
, search_req
);
269 const struct ldb_module_ops ldb_subtree_rename_module_ops
= {
270 .name
= "subtree_rename",
271 .rename
= subtree_rename
,