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.c205
1 files changed, 199 insertions, 6 deletions
diff --git a/source4/lib/ldb/modules/rdn_name.c b/source4/lib/ldb/modules/rdn_name.c
index 18ad625ee2..7ce6c29691 100644
--- a/source4/lib/ldb/modules/rdn_name.c
+++ b/source4/lib/ldb/modules/rdn_name.c
@@ -53,7 +53,7 @@ static struct ldb_message_element *rdn_name_find_attribute(const struct ldb_mess
return NULL;
}
-static int rdn_name_add(struct ldb_module *module, struct ldb_request *req)
+static int rdn_name_add_sync(struct ldb_module *module, struct ldb_request *req)
{
const struct ldb_message *msg = req->op.add.message;
struct ldb_message *msg2;
@@ -132,7 +132,7 @@ static int rdn_name_add(struct ldb_module *module, struct ldb_request *req)
return ret;
}
-static int rdn_name_add_async(struct ldb_module *module, struct ldb_request *req)
+static int rdn_name_add(struct ldb_module *module, struct ldb_request *req)
{
struct ldb_request *down_req;
struct ldb_message *msg;
@@ -147,7 +147,7 @@ static int rdn_name_add_async(struct ldb_module *module, struct ldb_request *req
return ldb_next_request(module, req);
}
- down_req = talloc(module, struct ldb_request);
+ down_req = talloc(req, struct ldb_request);
if (down_req == NULL) {
return LDB_ERR_OPERATIONS_ERROR;
}
@@ -213,15 +213,207 @@ static int rdn_name_add_async(struct ldb_module *module, struct ldb_request *req
return ret;
}
+struct rename_async_context {
+
+ enum {RENAME_RENAME, RENAME_MODIFY} step;
+ struct ldb_request *orig_req;
+ struct ldb_request *down_req;
+ struct ldb_request *mod_req;
+};
+
+static int rdn_name_rename(struct ldb_module *module, struct ldb_request *req)
+{
+ struct ldb_async_handle *h;
+ struct rename_async_context *ac;
+
+ ldb_debug(module->ldb, LDB_DEBUG_TRACE, "rdn_name_rename\n");
+
+ /* do not manipulate our control entries */
+ if (ldb_dn_is_special(req->op.rename.newdn)) {
+ return ldb_next_request(module, req);
+ }
+
+ h = talloc_zero(req, struct ldb_async_handle);
+ if (h == NULL) {
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
+ h->module = module;
+
+ ac = talloc_zero(h, struct rename_async_context);
+ if (ac == NULL) {
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
+ h->private_data = (void *)ac;
+
+ h->state = LDB_ASYNC_INIT;
+ h->status = LDB_SUCCESS;
+
+ ac->orig_req = req;
+ ac->down_req = talloc(req, struct ldb_request);
+ if (ac->down_req == NULL) {
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
+ *(ac->down_req) = *req;
+
+ ac->step = RENAME_RENAME;
+
+ req->async.handle = h;
+
+ /* rename first, modify "name" if rename is ok */
+ return ldb_next_request(module, ac->down_req);
+}
+
+static int rdn_name_rename_do_mod(struct ldb_async_handle *h) {
+
+ struct rename_async_context *ac;
+ struct ldb_dn_component *rdn;
+ struct ldb_message *msg;
+
+ ac = talloc_get_type(h->private_data, struct rename_async_context);
+
+ rdn = ldb_dn_get_rdn(ac, ac->orig_req->op.rename.newdn);
+ if (rdn == NULL) {
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
+ ac->mod_req = talloc_zero(ac, struct ldb_request);
+
+ ac->mod_req->operation = LDB_ASYNC_MODIFY;
+ ac->mod_req->op.mod.message = msg = ldb_msg_new(ac->mod_req);
+ if (msg == NULL) {
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
+ msg->dn = ldb_dn_copy(msg, ac->orig_req->op.rename.newdn);
+ if (msg->dn == NULL) {
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
+ if (ldb_msg_add_empty(msg, rdn->name, LDB_FLAG_MOD_REPLACE) != 0) {
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+ if (ldb_msg_add_value(msg, rdn->name, &rdn->value) != 0) {
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+ if (ldb_msg_add_empty(msg, "name", LDB_FLAG_MOD_REPLACE) != 0) {
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+ if (ldb_msg_add_value(msg, "name", &rdn->value) != 0) {
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
+ ac->mod_req->async.timeout = ac->orig_req->async.timeout;
+
+ ac->step = RENAME_MODIFY;
+
+ /* do the mod call */
+ return ldb_next_request(h->module, ac->mod_req);
+}
+
+static int rename_async_wait(struct ldb_async_handle *handle)
+{
+ struct rename_async_context *ac;
+ int ret;
+
+ if (!handle || !handle->private_data) {
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
+ if (handle->state == LDB_ASYNC_DONE) {
+ return handle->status;
+ }
+
+ handle->state = LDB_ASYNC_PENDING;
+ handle->status = LDB_SUCCESS;
+
+ ac = talloc_get_type(handle->private_data, struct rename_async_context);
+
+ switch(ac->step) {
+ case RENAME_RENAME:
+ ret = ldb_async_wait(ac->down_req->async.handle, LDB_WAIT_NONE);
+ if (ret != LDB_SUCCESS) {
+ handle->status = ret;
+ goto done;
+ }
+ if (ac->down_req->async.handle->status != LDB_SUCCESS) {
+ handle->status = ac->down_req->async.handle->status;
+ goto done;
+ }
+
+ if (ac->down_req->async.handle->state != LDB_ASYNC_DONE) {
+ return LDB_SUCCESS;
+ }
+
+ /* rename operation done */
+ return rdn_name_rename_do_mod(handle);
+
+ case RENAME_MODIFY:
+ ret = ldb_async_wait(ac->mod_req->async.handle, LDB_WAIT_NONE);
+ if (ret != LDB_SUCCESS) {
+ handle->status = ret;
+ goto done;
+ }
+ if (ac->mod_req->async.handle->status != LDB_SUCCESS) {
+ handle->status = ac->mod_req->async.handle->status;
+ goto done;
+ }
+
+ if (ac->mod_req->async.handle->state != LDB_ASYNC_DONE) {
+ return LDB_SUCCESS;
+ }
+
+ break;
+
+ default:
+ ret = LDB_ERR_OPERATIONS_ERROR;
+ goto done;
+ }
+
+ ret = LDB_SUCCESS;
+
+done:
+ handle->state = LDB_ASYNC_DONE;
+ return ret;
+}
+
+static int rename_async_wait_all(struct ldb_async_handle *handle) {
+
+ int ret;
+
+ while (handle->state != LDB_ASYNC_DONE) {
+ ret = rename_async_wait(handle);
+ if (ret != LDB_SUCCESS) {
+ return ret;
+ }
+ }
+
+ return handle->status;
+}
+
+static int rdn_name_async_wait(struct ldb_async_handle *handle, enum ldb_async_wait_type type)
+{
+ if (type == LDB_WAIT_ALL) {
+ return rename_async_wait_all(handle);
+ } else {
+ return rename_async_wait(handle);
+ }
+}
+
static int rdn_name_request(struct ldb_module *module, struct ldb_request *req)
{
switch (req->operation) {
case LDB_REQ_ADD:
- return rdn_name_add(module, req);
+ return rdn_name_add_sync(module, req);
case LDB_ASYNC_ADD:
- return rdn_name_add_async(module, req);
+ return rdn_name_add(module, req);
+
+ case LDB_ASYNC_RENAME:
+ return rdn_name_rename(module, req);
default:
return ldb_next_request(module, req);
@@ -231,7 +423,8 @@ static int rdn_name_request(struct ldb_module *module, struct ldb_request *req)
static const struct ldb_module_ops rdn_name_ops = {
.name = "rdn_name",
- .request = rdn_name_request
+ .request = rdn_name_request,
+ .async_wait = rdn_name_async_wait
};