summaryrefslogtreecommitdiff
path: root/source4/lib/ldb/modules/rdn_name.c
diff options
context:
space:
mode:
Diffstat (limited to 'source4/lib/ldb/modules/rdn_name.c')
-rw-r--r--source4/lib/ldb/modules/rdn_name.c179
1 files changed, 174 insertions, 5 deletions
diff --git a/source4/lib/ldb/modules/rdn_name.c b/source4/lib/ldb/modules/rdn_name.c
index 59930046ce..24e3430254 100644
--- a/source4/lib/ldb/modules/rdn_name.c
+++ b/source4/lib/ldb/modules/rdn_name.c
@@ -1,7 +1,8 @@
/*
ldb database library
- Copyright (C) Simo Sorce 2004
+ Copyright (C) Andrew Bartlet 2005
+ Copyright (C) Simo Sorce 2006
** NOTE! The following LGPL license applies to the ldb
** library. This does NOT imply that all of Samba is released
@@ -23,13 +24,17 @@
*/
/*
- * Name: ldb
+ * Name: rdb_name
*
- * Component: ldb objectguid module
+ * Component: ldb rdn name module
*
- * Description: add a unique objectGUID onto every new record
+ * Description: keep a consistent name attribute on objects manpulations
*
- * Author: Simo Sorce
+ * Author: Andrew Bartlet
+ *
+ * Modifications:
+ * - made the module async
+ * Simo Sorce Mar 2006
*/
#include "includes.h"
@@ -188,6 +193,165 @@ static int rdn_name_modify(struct ldb_module *module, struct ldb_request *req)
return ret;
}
+static int rdn_name_add_async(struct ldb_module *module, struct ldb_request *req)
+{
+ struct ldb_request *down_req;
+ struct ldb_message *msg;
+ struct ldb_message_element *attribute;
+ struct ldb_dn_component *rdn;
+ int i, ret;
+
+ ldb_debug(module->ldb, LDB_DEBUG_TRACE, "rdn_name_add_record\n");
+
+ /* do not manipulate our control entries */
+ if (ldb_dn_is_special(req->op.add.message->dn)) {
+ return ldb_next_request(module, req);
+ }
+
+ down_req = talloc(module, struct ldb_request);
+ if (down_req == NULL) {
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
+ msg = ldb_msg_copy_shallow(down_req, req->op.add.message);
+ if (msg == NULL) {
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
+ rdn = ldb_dn_get_rdn(msg, msg->dn);
+ if (rdn == NULL) {
+ talloc_free(down_req);
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
+ /* Perhaps someone above us tried to set this? */
+ if ((attribute = rdn_name_find_attribute(msg, "name")) != NULL ) {
+ attribute->num_values = 0;
+ }
+
+ if (ldb_msg_add_value(msg, "name", &rdn->value) != 0) {
+ talloc_free(down_req);
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
+ attribute = rdn_name_find_attribute(msg, rdn->name);
+
+ if (!attribute) {
+ if (ldb_msg_add_value(msg, rdn->name, &rdn->value) != 0) {
+ talloc_free(down_req);
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+ } else {
+ const struct ldb_attrib_handler *handler = ldb_attrib_handler(module->ldb, rdn->name);
+
+ for (i = 0; i < attribute->num_values; i++) {
+ if (handler->comparison_fn(module->ldb, msg, &rdn->value, &attribute->values[i]) == 0) {
+ /* overwrite so it matches in case */
+ attribute->values[i] = rdn->value;
+ break;
+ }
+ }
+ if (i == attribute->num_values) {
+ ldb_debug_set(module->ldb, LDB_DEBUG_FATAL,
+ "RDN mismatch on %s: %s",
+ ldb_dn_linearize(msg, msg->dn), rdn->name);
+ talloc_free(down_req);
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+ }
+
+ down_req->op.add.message = msg;
+
+ down_req->controls = req->controls;
+ down_req->creds = req->creds;
+
+ down_req->async.context = req->async.context;
+ down_req->async.callback = req->async.callback;
+ down_req->async.timeout = req->async.timeout;
+
+ /* go on with the call chain */
+ ret = ldb_next_request(module, down_req);
+
+ /* do not free down_req as the call results may be linked to it,
+ * it will be freed when the upper level request get freed */
+ if (ret == LDB_SUCCESS) {
+ req->async.handle = down_req->async.handle;
+ }
+
+ return ret;
+}
+
+static int rdn_name_modify_async(struct ldb_module *module, struct ldb_request *req)
+{
+ struct ldb_request *down_req;
+ struct ldb_message *msg;
+ struct ldb_message_element *attribute;
+ struct ldb_dn_component *rdn;
+ int ret;
+
+ ldb_debug(module->ldb, LDB_DEBUG_TRACE, "rdn_name_modify_record\n");
+
+ /* do not manipulate our control entries */
+ if (ldb_dn_is_special(req->op.mod.message->dn)) {
+ return ldb_next_request(module, req);
+ }
+
+ /* Perhaps someone above us knows better */
+ if ((attribute = rdn_name_find_attribute(req->op.mod.message, "name")) != NULL ) {
+ return ldb_next_request(module, req);
+ }
+
+ /* FIXME: are we sure we wont to change "name" on each and every modify operation ?? */
+ down_req = talloc(module, struct ldb_request);
+ if (down_req == NULL) {
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
+ msg = ldb_msg_copy_shallow(down_req, req->op.add.message);
+ if (msg == NULL) {
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
+ rdn = ldb_dn_get_rdn(msg, msg->dn);
+ if (rdn == NULL) {
+ talloc_free(down_req);
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
+ if (ldb_msg_add_value(msg, "name", &rdn->value) != 0) {
+ talloc_free(down_req);
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
+ attribute = rdn_name_find_attribute(msg, "name");
+ if (!attribute) {
+ talloc_free(down_req);
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
+ attribute->flags = LDB_FLAG_MOD_REPLACE;
+
+ down_req->op.add.message = msg;
+
+ down_req->controls = req->controls;
+ down_req->creds = req->creds;
+
+ down_req->async.context = req->async.context;
+ down_req->async.callback = req->async.callback;
+ down_req->async.timeout = req->async.timeout;
+
+ /* go on with the call chain */
+ ret = ldb_next_request(module, down_req);
+
+ /* do not free down_req as the call results may be linked to it,
+ * it will be freed when the upper level request get freed */
+ if (ret == LDB_SUCCESS) {
+ req->async.handle = down_req->async.handle;
+ }
+
+ return ret;
+}
+
static int rdn_name_request(struct ldb_module *module, struct ldb_request *req)
{
switch (req->operation) {
@@ -198,6 +362,11 @@ static int rdn_name_request(struct ldb_module *module, struct ldb_request *req)
case LDB_REQ_MODIFY:
return rdn_name_modify(module, req);
+ case LDB_ASYNC_ADD:
+ return rdn_name_add_async(module, req);
+
+ case LDB_ASYNC_MODIFY:
+ return rdn_name_modify_async(module, req);
default:
return ldb_next_request(module, req);