diff options
Diffstat (limited to 'source4/lib/ldb/modules/rdn_name.c')
-rw-r--r-- | source4/lib/ldb/modules/rdn_name.c | 205 |
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 }; |