4 Copyright (C) Andrew Bartlet 2005
5 Copyright (C) Simo Sorce 2006
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 rdn name module
30 * Description: keep a consistent name attribute on objects manpulations
32 * Author: Andrew Bartlet
35 * - made the module async
40 #include "ldb/include/includes.h"
42 static struct ldb_message_element
*rdn_name_find_attribute(const struct ldb_message
*msg
, const char *name
)
46 for (i
= 0; i
< msg
->num_elements
; i
++) {
47 if (ldb_attr_cmp(name
, msg
->elements
[i
].name
) == 0) {
48 return &msg
->elements
[i
];
55 static int rdn_name_add(struct ldb_module
*module
, struct ldb_request
*req
)
57 struct ldb_request
*down_req
;
58 struct ldb_message
*msg
;
59 struct ldb_message_element
*attribute
;
61 struct ldb_val rdn_val
;
64 ldb_debug(module
->ldb
, LDB_DEBUG_TRACE
, "rdn_name_add_record\n");
66 /* do not manipulate our control entries */
67 if (ldb_dn_is_special(req
->op
.add
.message
->dn
)) {
68 return ldb_next_request(module
, req
);
71 down_req
= talloc(req
, struct ldb_request
);
72 if (down_req
== NULL
) {
73 return LDB_ERR_OPERATIONS_ERROR
;
78 down_req
->op
.add
.message
= msg
= ldb_msg_copy_shallow(down_req
, req
->op
.add
.message
);
80 return LDB_ERR_OPERATIONS_ERROR
;
83 rdn_name
= ldb_dn_get_rdn_name(msg
->dn
);
84 if (rdn_name
== NULL
) {
85 talloc_free(down_req
);
86 return LDB_ERR_OPERATIONS_ERROR
;
89 rdn_val
= ldb_val_dup(msg
, ldb_dn_get_rdn_val(msg
->dn
));
91 /* Perhaps someone above us tried to set this? */
92 if ((attribute
= rdn_name_find_attribute(msg
, "name")) != NULL
) {
93 attribute
->num_values
= 0;
96 if (ldb_msg_add_value(msg
, "name", &rdn_val
, NULL
) != 0) {
97 talloc_free(down_req
);
98 return LDB_ERR_OPERATIONS_ERROR
;
101 attribute
= rdn_name_find_attribute(msg
, rdn_name
);
104 if (ldb_msg_add_value(msg
, rdn_name
, &rdn_val
, NULL
) != 0) {
105 talloc_free(down_req
);
106 return LDB_ERR_OPERATIONS_ERROR
;
109 const struct ldb_attrib_handler
*handler
= ldb_attrib_handler(module
->ldb
, rdn_name
);
111 for (i
= 0; i
< attribute
->num_values
; i
++) {
112 if (handler
->comparison_fn(module
->ldb
, msg
, &rdn_val
, &attribute
->values
[i
]) == 0) {
113 /* overwrite so it matches in case */
114 attribute
->values
[i
] = rdn_val
;
118 if (i
== attribute
->num_values
) {
119 ldb_debug_set(module
->ldb
, LDB_DEBUG_FATAL
,
120 "RDN mismatch on %s: %s (%s)",
121 ldb_dn_linearize(msg
, msg
->dn
), rdn_name
, rdn_val
.data
);
122 talloc_free(down_req
);
123 return LDB_ERR_OPERATIONS_ERROR
;
127 /* go on with the call chain */
128 ret
= ldb_next_request(module
, down_req
);
130 /* do not free down_req as the call results may be linked to it,
131 * it will be freed when the upper level request get freed */
132 if (ret
== LDB_SUCCESS
) {
133 req
->handle
= down_req
->handle
;
139 struct rename_context
{
141 enum {RENAME_RENAME
, RENAME_MODIFY
} step
;
142 struct ldb_request
*orig_req
;
143 struct ldb_request
*down_req
;
144 struct ldb_request
*mod_req
;
147 static int rdn_name_rename(struct ldb_module
*module
, struct ldb_request
*req
)
149 struct ldb_handle
*h
;
150 struct rename_context
*ac
;
152 ldb_debug(module
->ldb
, LDB_DEBUG_TRACE
, "rdn_name_rename\n");
154 /* do not manipulate our control entries */
155 if (ldb_dn_is_special(req
->op
.rename
.newdn
)) {
156 return ldb_next_request(module
, req
);
159 h
= talloc_zero(req
, struct ldb_handle
);
161 return LDB_ERR_OPERATIONS_ERROR
;
166 ac
= talloc_zero(h
, struct rename_context
);
168 return LDB_ERR_OPERATIONS_ERROR
;
171 h
->private_data
= (void *)ac
;
173 h
->state
= LDB_ASYNC_INIT
;
174 h
->status
= LDB_SUCCESS
;
177 ac
->down_req
= talloc(req
, struct ldb_request
);
178 if (ac
->down_req
== NULL
) {
179 return LDB_ERR_OPERATIONS_ERROR
;
182 *(ac
->down_req
) = *req
;
184 ac
->step
= RENAME_RENAME
;
188 /* rename first, modify "name" if rename is ok */
189 return ldb_next_request(module
, ac
->down_req
);
192 static int rdn_name_rename_do_mod(struct ldb_handle
*h
) {
194 struct rename_context
*ac
;
195 const char *rdn_name
;
196 struct ldb_val rdn_val
;
197 struct ldb_message
*msg
;
199 ac
= talloc_get_type(h
->private_data
, struct rename_context
);
201 ac
->mod_req
= talloc_zero(ac
, struct ldb_request
);
203 ac
->mod_req
->operation
= LDB_MODIFY
;
204 ac
->mod_req
->op
.mod
.message
= msg
= ldb_msg_new(ac
->mod_req
);
206 return LDB_ERR_OPERATIONS_ERROR
;
209 msg
->dn
= ldb_dn_copy(msg
, ac
->orig_req
->op
.rename
.newdn
);
210 if (msg
->dn
== NULL
) {
211 return LDB_ERR_OPERATIONS_ERROR
;
214 rdn_name
= ldb_dn_get_rdn_name(ac
->orig_req
->op
.rename
.newdn
);
215 if (rdn_name
== NULL
) {
216 return LDB_ERR_OPERATIONS_ERROR
;
219 rdn_val
= ldb_val_dup(msg
, ldb_dn_get_rdn_val(ac
->orig_req
->op
.rename
.newdn
));
221 if (ldb_msg_add_empty(msg
, rdn_name
, LDB_FLAG_MOD_REPLACE
, NULL
) != 0) {
222 return LDB_ERR_OPERATIONS_ERROR
;
224 if (ldb_msg_add_value(msg
, rdn_name
, &rdn_val
, NULL
) != 0) {
225 return LDB_ERR_OPERATIONS_ERROR
;
227 if (ldb_msg_add_empty(msg
, "name", LDB_FLAG_MOD_REPLACE
, NULL
) != 0) {
228 return LDB_ERR_OPERATIONS_ERROR
;
230 if (ldb_msg_add_value(msg
, "name", &rdn_val
, NULL
) != 0) {
231 return LDB_ERR_OPERATIONS_ERROR
;
234 ldb_set_timeout_from_prev_req(h
->module
->ldb
, ac
->orig_req
, ac
->mod_req
);
236 ac
->step
= RENAME_MODIFY
;
238 /* do the mod call */
239 return ldb_request(h
->module
->ldb
, ac
->mod_req
);
242 static int rename_wait(struct ldb_handle
*handle
)
244 struct rename_context
*ac
;
247 if (!handle
|| !handle
->private_data
) {
248 return LDB_ERR_OPERATIONS_ERROR
;
251 if (handle
->state
== LDB_ASYNC_DONE
) {
252 return handle
->status
;
255 handle
->state
= LDB_ASYNC_PENDING
;
256 handle
->status
= LDB_SUCCESS
;
258 ac
= talloc_get_type(handle
->private_data
, struct rename_context
);
262 ret
= ldb_wait(ac
->down_req
->handle
, LDB_WAIT_NONE
);
263 if (ret
!= LDB_SUCCESS
) {
264 handle
->status
= ret
;
267 if (ac
->down_req
->handle
->status
!= LDB_SUCCESS
) {
268 handle
->status
= ac
->down_req
->handle
->status
;
272 if (ac
->down_req
->handle
->state
!= LDB_ASYNC_DONE
) {
276 /* rename operation done */
277 return rdn_name_rename_do_mod(handle
);
280 ret
= ldb_wait(ac
->mod_req
->handle
, LDB_WAIT_NONE
);
281 if (ret
!= LDB_SUCCESS
) {
282 handle
->status
= ret
;
285 if (ac
->mod_req
->handle
->status
!= LDB_SUCCESS
) {
286 handle
->status
= ac
->mod_req
->handle
->status
;
290 if (ac
->mod_req
->handle
->state
!= LDB_ASYNC_DONE
) {
297 ret
= LDB_ERR_OPERATIONS_ERROR
;
304 handle
->state
= LDB_ASYNC_DONE
;
308 static int rename_wait_all(struct ldb_handle
*handle
) {
312 while (handle
->state
!= LDB_ASYNC_DONE
) {
313 ret
= rename_wait(handle
);
314 if (ret
!= LDB_SUCCESS
) {
319 return handle
->status
;
322 static int rdn_name_wait(struct ldb_handle
*handle
, enum ldb_wait_type type
)
324 if (type
== LDB_WAIT_ALL
) {
325 return rename_wait_all(handle
);
327 return rename_wait(handle
);
331 static const struct ldb_module_ops rdn_name_ops
= {
334 .rename
= rdn_name_rename
,
335 .wait
= rdn_name_wait
339 int ldb_rdn_name_init(void)
341 return ldb_register_module(&rdn_name_ops
);