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
->error
!= LDB_SUCCESS
) {
85 return ldb_module_done(ac
->req
, ares
->controls
,
86 ares
->response
, ares
->error
);
89 if (ares
->type
!= LDB_REPLY_DONE
) {
90 ldb_set_errstring(ldb
, "Invalid reply type!\n");
91 return ldb_module_done(ac
->req
, NULL
, NULL
,
92 LDB_ERR_OPERATIONS_ERROR
);
95 if (ac
->current
== NULL
) {
96 /* this was the last one */
97 return ldb_module_done(ac
->req
, ares
->controls
,
98 ares
->response
, LDB_SUCCESS
);
101 ret
= subtree_rename_next_request(ac
);
102 if (ret
!= LDB_SUCCESS
) {
103 return ldb_module_done(ac
->req
, NULL
, NULL
, ret
);
110 static int subtree_rename_next_request(struct subtree_rename_context
*ac
)
112 struct ldb_context
*ldb
;
113 struct ldb_request
*req
;
116 ldb
= ldb_module_get_ctx(ac
->module
);
118 if (ac
->current
== NULL
) {
119 return LDB_ERR_OPERATIONS_ERROR
;
122 ret
= ldb_build_rename_req(&req
, ldb
, ac
->current
,
126 ac
, subtree_rename_callback
,
128 if (ret
!= LDB_SUCCESS
) {
132 ac
->current
= ac
->current
->next
;
134 return ldb_next_request(ac
->module
, req
);
137 static int subtree_rename_search_callback(struct ldb_request
*req
,
138 struct ldb_reply
*ares
)
140 struct subren_msg_store
*store
;
141 struct subtree_rename_context
*ac
;
144 ac
= talloc_get_type(req
->context
, struct subtree_rename_context
);
146 if (!ares
|| !ac
->current
) {
147 return ldb_module_done(ac
->req
, NULL
, NULL
,
148 LDB_ERR_OPERATIONS_ERROR
);
150 if (ares
->error
!= LDB_SUCCESS
) {
151 return ldb_module_done(ac
->req
, ares
->controls
,
152 ares
->response
, ares
->error
);
155 switch (ares
->type
) {
156 case LDB_REPLY_ENTRY
:
158 if (ldb_dn_compare(ares
->message
->dn
, ac
->list
->olddn
) == 0) {
159 /* this was already stored by the
160 * subtree_rename_search() */
165 store
= talloc_zero(ac
, struct subren_msg_store
);
167 return ldb_module_done(ac
->req
, NULL
, NULL
,
168 LDB_ERR_OPERATIONS_ERROR
);
170 ac
->current
->next
= store
;
173 /* the first list element contains the base for the rename */
174 store
->olddn
= talloc_steal(store
, ares
->message
->dn
);
175 store
->newdn
= ldb_dn_copy(store
, store
->olddn
);
177 if ( ! ldb_dn_remove_base_components(store
->newdn
,
178 ldb_dn_get_comp_num(ac
->list
->olddn
))) {
179 return ldb_module_done(ac
->req
, NULL
, NULL
,
180 LDB_ERR_OPERATIONS_ERROR
);
183 if ( ! ldb_dn_add_base(store
->newdn
, ac
->list
->newdn
)) {
184 return ldb_module_done(ac
->req
, NULL
, NULL
,
185 LDB_ERR_OPERATIONS_ERROR
);
190 case LDB_REPLY_REFERRAL
:
196 /* rewind ac->current */
197 ac
->current
= ac
->list
;
199 /* All dns set up, start with the first one */
200 ret
= subtree_rename_next_request(ac
);
202 if (ret
!= LDB_SUCCESS
) {
203 return ldb_module_done(ac
->req
, NULL
, NULL
, ret
);
213 static int subtree_rename(struct ldb_module
*module
, struct ldb_request
*req
)
215 struct ldb_context
*ldb
;
216 static const char *attrs
[2] = { "distinguishedName", NULL
};
217 struct ldb_request
*search_req
;
218 struct subtree_rename_context
*ac
;
220 if (ldb_dn_is_special(req
->op
.rename
.olddn
)) { /* do not manipulate our control entries */
221 return ldb_next_request(module
, req
);
224 ldb
= ldb_module_get_ctx(module
);
226 /* This gets complex: We need to:
227 - Do a search for all entires under this entry
228 - Wait for these results to appear
229 - In the callback for each result, issue a modify request
230 - That will include this rename, we hope
231 - Wait for each modify result
235 ac
= subren_ctx_init(module
, req
);
237 return LDB_ERR_OPERATIONS_ERROR
;
240 /* add this entry as the first to do */
241 ac
->current
= talloc_zero(ac
, struct subren_msg_store
);
242 if (ac
->current
== NULL
) {
243 return LDB_ERR_OPERATIONS_ERROR
;
245 ac
->current
->olddn
= req
->op
.rename
.olddn
;
246 ac
->current
->newdn
= req
->op
.rename
.newdn
;
247 ac
->list
= ac
->current
;
249 ret
= ldb_build_search_req(&search_req
, ldb
, ac
,
250 req
->op
.rename
.olddn
,
256 subtree_rename_search_callback
,
258 if (ret
!= LDB_SUCCESS
) {
262 return ldb_next_request(module
, search_req
);
265 const struct ldb_module_ops ldb_subtree_rename_module_ops
= {
266 .name
= "subtree_rename",
267 .rename
= subtree_rename
,