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 2 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, write to the Free Software
23 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
29 * Component: ldb rdn name module
31 * Description: keep a consistent name attribute on objects manpulations
33 * Author: Andrew Bartlet
36 * - made the module async
41 #include "ldb/include/includes.h"
43 static struct ldb_message_element
*rdn_name_find_attribute(const struct ldb_message
*msg
, const char *name
)
47 for (i
= 0; i
< msg
->num_elements
; i
++) {
48 if (ldb_attr_cmp(name
, msg
->elements
[i
].name
) == 0) {
49 return &msg
->elements
[i
];
56 static int rdn_name_add(struct ldb_module
*module
, struct ldb_request
*req
)
58 struct ldb_request
*down_req
;
59 struct ldb_message
*msg
;
60 struct ldb_message_element
*attribute
;
62 struct ldb_val rdn_val
;
65 ldb_debug(module
->ldb
, LDB_DEBUG_TRACE
, "rdn_name_add_record\n");
67 /* do not manipulate our control entries */
68 if (ldb_dn_is_special(req
->op
.add
.message
->dn
)) {
69 return ldb_next_request(module
, req
);
72 down_req
= talloc(req
, struct ldb_request
);
73 if (down_req
== NULL
) {
74 return LDB_ERR_OPERATIONS_ERROR
;
79 down_req
->op
.add
.message
= msg
= ldb_msg_copy_shallow(down_req
, req
->op
.add
.message
);
81 return LDB_ERR_OPERATIONS_ERROR
;
84 rdn_name
= ldb_dn_get_rdn_name(msg
->dn
);
85 if (rdn_name
== NULL
) {
86 talloc_free(down_req
);
87 return LDB_ERR_OPERATIONS_ERROR
;
90 rdn_val
= ldb_val_dup(msg
, ldb_dn_get_rdn_val(msg
->dn
));
92 /* Perhaps someone above us tried to set this? */
93 if ((attribute
= rdn_name_find_attribute(msg
, "name")) != NULL
) {
94 attribute
->num_values
= 0;
97 if (ldb_msg_add_value(msg
, "name", &rdn_val
, NULL
) != 0) {
98 talloc_free(down_req
);
99 return LDB_ERR_OPERATIONS_ERROR
;
102 attribute
= rdn_name_find_attribute(msg
, rdn_name
);
105 if (ldb_msg_add_value(msg
, rdn_name
, &rdn_val
, NULL
) != 0) {
106 talloc_free(down_req
);
107 return LDB_ERR_OPERATIONS_ERROR
;
110 const struct ldb_attrib_handler
*handler
= ldb_attrib_handler(module
->ldb
, rdn_name
);
112 for (i
= 0; i
< attribute
->num_values
; i
++) {
113 if (handler
->comparison_fn(module
->ldb
, msg
, &rdn_val
, &attribute
->values
[i
]) == 0) {
114 /* overwrite so it matches in case */
115 attribute
->values
[i
] = rdn_val
;
119 if (i
== attribute
->num_values
) {
120 ldb_debug_set(module
->ldb
, LDB_DEBUG_FATAL
,
121 "RDN mismatch on %s: %s (%s)",
122 ldb_dn_linearize(msg
, msg
->dn
), rdn_name
, rdn_val
.data
);
123 talloc_free(down_req
);
124 return LDB_ERR_OPERATIONS_ERROR
;
128 /* go on with the call chain */
129 ret
= ldb_next_request(module
, down_req
);
131 /* do not free down_req as the call results may be linked to it,
132 * it will be freed when the upper level request get freed */
133 if (ret
== LDB_SUCCESS
) {
134 req
->handle
= down_req
->handle
;
140 struct rename_context
{
142 enum {RENAME_RENAME
, RENAME_MODIFY
} step
;
143 struct ldb_request
*orig_req
;
144 struct ldb_request
*down_req
;
145 struct ldb_request
*mod_req
;
148 static int rdn_name_rename(struct ldb_module
*module
, struct ldb_request
*req
)
150 struct ldb_handle
*h
;
151 struct rename_context
*ac
;
153 ldb_debug(module
->ldb
, LDB_DEBUG_TRACE
, "rdn_name_rename\n");
155 /* do not manipulate our control entries */
156 if (ldb_dn_is_special(req
->op
.rename
.newdn
)) {
157 return ldb_next_request(module
, req
);
160 h
= talloc_zero(req
, struct ldb_handle
);
162 return LDB_ERR_OPERATIONS_ERROR
;
167 ac
= talloc_zero(h
, struct rename_context
);
169 return LDB_ERR_OPERATIONS_ERROR
;
172 h
->private_data
= (void *)ac
;
174 h
->state
= LDB_ASYNC_INIT
;
175 h
->status
= LDB_SUCCESS
;
178 ac
->down_req
= talloc(req
, struct ldb_request
);
179 if (ac
->down_req
== NULL
) {
180 return LDB_ERR_OPERATIONS_ERROR
;
183 *(ac
->down_req
) = *req
;
185 ac
->step
= RENAME_RENAME
;
189 /* rename first, modify "name" if rename is ok */
190 return ldb_next_request(module
, ac
->down_req
);
193 static int rdn_name_rename_do_mod(struct ldb_handle
*h
) {
195 struct rename_context
*ac
;
196 const char *rdn_name
;
197 struct ldb_val rdn_val
;
198 struct ldb_message
*msg
;
200 ac
= talloc_get_type(h
->private_data
, struct rename_context
);
202 ac
->mod_req
= talloc_zero(ac
, struct ldb_request
);
204 ac
->mod_req
->operation
= LDB_MODIFY
;
205 ac
->mod_req
->op
.mod
.message
= msg
= ldb_msg_new(ac
->mod_req
);
207 return LDB_ERR_OPERATIONS_ERROR
;
210 msg
->dn
= ldb_dn_copy(msg
, ac
->orig_req
->op
.rename
.newdn
);
211 if (msg
->dn
== NULL
) {
212 return LDB_ERR_OPERATIONS_ERROR
;
215 rdn_name
= ldb_dn_get_rdn_name(ac
->orig_req
->op
.rename
.newdn
);
216 if (rdn_name
== NULL
) {
217 return LDB_ERR_OPERATIONS_ERROR
;
220 rdn_val
= ldb_val_dup(msg
, ldb_dn_get_rdn_val(ac
->orig_req
->op
.rename
.newdn
));
222 if (ldb_msg_add_empty(msg
, rdn_name
, LDB_FLAG_MOD_REPLACE
, NULL
) != 0) {
223 return LDB_ERR_OPERATIONS_ERROR
;
225 if (ldb_msg_add_value(msg
, rdn_name
, &rdn_val
, NULL
) != 0) {
226 return LDB_ERR_OPERATIONS_ERROR
;
228 if (ldb_msg_add_empty(msg
, "name", LDB_FLAG_MOD_REPLACE
, NULL
) != 0) {
229 return LDB_ERR_OPERATIONS_ERROR
;
231 if (ldb_msg_add_value(msg
, "name", &rdn_val
, NULL
) != 0) {
232 return LDB_ERR_OPERATIONS_ERROR
;
235 ldb_set_timeout_from_prev_req(h
->module
->ldb
, ac
->orig_req
, ac
->mod_req
);
237 ac
->step
= RENAME_MODIFY
;
239 /* do the mod call */
240 return ldb_request(h
->module
->ldb
, ac
->mod_req
);
243 static int rename_wait(struct ldb_handle
*handle
)
245 struct rename_context
*ac
;
248 if (!handle
|| !handle
->private_data
) {
249 return LDB_ERR_OPERATIONS_ERROR
;
252 if (handle
->state
== LDB_ASYNC_DONE
) {
253 return handle
->status
;
256 handle
->state
= LDB_ASYNC_PENDING
;
257 handle
->status
= LDB_SUCCESS
;
259 ac
= talloc_get_type(handle
->private_data
, struct rename_context
);
263 ret
= ldb_wait(ac
->down_req
->handle
, LDB_WAIT_NONE
);
264 if (ret
!= LDB_SUCCESS
) {
265 handle
->status
= ret
;
268 if (ac
->down_req
->handle
->status
!= LDB_SUCCESS
) {
269 handle
->status
= ac
->down_req
->handle
->status
;
273 if (ac
->down_req
->handle
->state
!= LDB_ASYNC_DONE
) {
277 /* rename operation done */
278 return rdn_name_rename_do_mod(handle
);
281 ret
= ldb_wait(ac
->mod_req
->handle
, LDB_WAIT_NONE
);
282 if (ret
!= LDB_SUCCESS
) {
283 handle
->status
= ret
;
286 if (ac
->mod_req
->handle
->status
!= LDB_SUCCESS
) {
287 handle
->status
= ac
->mod_req
->handle
->status
;
291 if (ac
->mod_req
->handle
->state
!= LDB_ASYNC_DONE
) {
298 ret
= LDB_ERR_OPERATIONS_ERROR
;
305 handle
->state
= LDB_ASYNC_DONE
;
309 static int rename_wait_all(struct ldb_handle
*handle
) {
313 while (handle
->state
!= LDB_ASYNC_DONE
) {
314 ret
= rename_wait(handle
);
315 if (ret
!= LDB_SUCCESS
) {
320 return handle
->status
;
323 static int rdn_name_wait(struct ldb_handle
*handle
, enum ldb_wait_type type
)
325 if (type
== LDB_WAIT_ALL
) {
326 return rename_wait_all(handle
);
328 return rename_wait(handle
);
332 static const struct ldb_module_ops rdn_name_ops
= {
335 .rename
= rdn_name_rename
,
336 .wait
= rdn_name_wait
340 int ldb_rdn_name_init(void)
342 return ldb_register_module(&rdn_name_ops
);