summaryrefslogtreecommitdiff
path: root/source4/lib/ldb/modules
diff options
context:
space:
mode:
authorJelmer Vernooij <jelmer@samba.org>2008-10-21 14:51:13 +0200
committerJelmer Vernooij <jelmer@samba.org>2008-10-21 14:51:13 +0200
commit5209a846a9157e649fcdcb561f7eaf19c8c0e465 (patch)
treeb0a7e52b5646c8eec182dbc391e7934b6804488c /source4/lib/ldb/modules
parent625359b2e266105022309df8985720108ecd6f67 (diff)
parent2ee8d29d22bcb1c350ab59d71b0aee548489bc9c (diff)
downloadsamba-5209a846a9157e649fcdcb561f7eaf19c8c0e465.tar.gz
samba-5209a846a9157e649fcdcb561f7eaf19c8c0e465.tar.bz2
samba-5209a846a9157e649fcdcb561f7eaf19c8c0e465.zip
Merge branch 'master' of ssh://git.samba.org/data/git/samba into regsrv
Conflicts: source4/lib/registry/ldb.c source4/rpc_server/winreg/rpc_winreg.c
Diffstat (limited to 'source4/lib/ldb/modules')
-rw-r--r--source4/lib/ldb/modules/asq.c419
-rw-r--r--source4/lib/ldb/modules/operational.c102
-rw-r--r--source4/lib/ldb/modules/paged_results.c493
-rw-r--r--source4/lib/ldb/modules/paged_searches.c359
-rw-r--r--source4/lib/ldb/modules/rdn_name.c300
-rw-r--r--source4/lib/ldb/modules/sort.c369
6 files changed, 791 insertions, 1251 deletions
diff --git a/source4/lib/ldb/modules/asq.c b/source4/lib/ldb/modules/asq.c
index eb27263b16..835715e7dc 100644
--- a/source4/lib/ldb/modules/asq.c
+++ b/source4/lib/ldb/modules/asq.c
@@ -1,7 +1,7 @@
/*
ldb database library
- Copyright (C) Simo Sorce 2005
+ Copyright (C) Simo Sorce 2005-2008
** NOTE! The following LGPL license applies to the ldb
** library. This does NOT imply that all of Samba is released
@@ -36,10 +36,10 @@
struct asq_context {
- enum {ASQ_INIT, ASQ_SEARCH_BASE, ASQ_SEARCH_MULTI} step;
+ enum {ASQ_SEARCH_BASE, ASQ_SEARCH_MULTI} step;
struct ldb_module *module;
- struct ldb_request *orig_req;
+ struct ldb_request *req;
struct ldb_asq_control *asq_ctrl;
@@ -52,7 +52,6 @@ struct asq_context {
ASQ_CTRL_AFFECTS_MULTIPLE_DSA = 71
} asq_ret;
- struct ldb_request *base_req;
struct ldb_reply *base_res;
struct ldb_request **reqs;
@@ -62,192 +61,200 @@ struct asq_context {
struct ldb_control **controls;
};
-static struct ldb_handle *init_handle(struct ldb_request *req, struct ldb_module *module)
+static struct asq_context *asq_context_init(struct ldb_module *module, struct ldb_request *req)
{
struct asq_context *ac;
- struct ldb_handle *h;
-
- h = talloc_zero(req, struct ldb_handle);
- if (h == NULL) {
- ldb_set_errstring(module->ldb, "Out of Memory");
- return NULL;
- }
- h->module = module;
-
- ac = talloc_zero(h, struct asq_context);
+ ac = talloc_zero(req, struct asq_context);
if (ac == NULL) {
- ldb_set_errstring(module->ldb, "Out of Memory");
- talloc_free(h);
+ ldb_oom(module->ldb);
return NULL;
}
- h->private_data = (void *)ac;
-
- h->state = LDB_ASYNC_INIT;
- h->status = LDB_SUCCESS;
-
- ac->step = ASQ_INIT;
ac->module = module;
- ac->orig_req = req;
+ ac->req = req;
- return h;
+ return ac;
}
-static int asq_terminate(struct ldb_handle *handle)
+static int asq_search_continue(struct asq_context *ac);
+
+static int asq_search_terminate(struct asq_context *ac)
{
- struct asq_context *ac;
- struct ldb_reply *ares;
struct ldb_asq_control *asq;
int i;
- ac = talloc_get_type(handle->private_data, struct asq_context);
- if (ac == NULL) {
- return LDB_ERR_OPERATIONS_ERROR;
- }
-
- handle->status = LDB_SUCCESS;
- handle->state = LDB_ASYNC_DONE;
-
- ares = talloc_zero(ac, struct ldb_reply);
- if (ares == NULL)
- return LDB_ERR_OPERATIONS_ERROR;
-
- ares->type = LDB_REPLY_DONE;
-
if (ac->controls) {
- for (i = 0; ac->controls[i]; i++);
- ares->controls = talloc_move(ares, &ac->controls);
+ for (i = 0; ac->controls[i]; i++) /* count em */ ;
} else {
i = 0;
}
- ares->controls = talloc_realloc(ares, ares->controls, struct ldb_control *, i + 2);
-
- if (ares->controls == NULL)
+ ac->controls = talloc_realloc(ac, ac->controls, struct ldb_control *, i + 2);
+
+ if (ac->controls == NULL) {
return LDB_ERR_OPERATIONS_ERROR;
+ }
- ares->controls[i] = talloc(ares->controls, struct ldb_control);
- if (ares->controls[i] == NULL)
+ ac->controls[i] = talloc(ac->controls, struct ldb_control);
+ if (ac->controls[i] == NULL) {
return LDB_ERR_OPERATIONS_ERROR;
+ }
- ares->controls[i]->oid = LDB_CONTROL_ASQ_OID;
- ares->controls[i]->critical = 0;
+ ac->controls[i]->oid = LDB_CONTROL_ASQ_OID;
+ ac->controls[i]->critical = 0;
- asq = talloc_zero(ares->controls[i], struct ldb_asq_control);
+ asq = talloc_zero(ac->controls[i], struct ldb_asq_control);
if (asq == NULL)
return LDB_ERR_OPERATIONS_ERROR;
asq->result = ac->asq_ret;
-
- ares->controls[i]->data = asq;
- ares->controls[i + 1] = NULL;
+ ac->controls[i]->data = asq;
- ac->orig_req->callback(ac->module->ldb, ac->orig_req->context, ares);
+ ac->controls[i + 1] = NULL;
- return LDB_SUCCESS;
+ return ldb_module_done(ac->req, ac->controls, NULL, LDB_SUCCESS);
}
-static int asq_base_callback(struct ldb_context *ldb, void *context, struct ldb_reply *ares)
+static int asq_base_callback(struct ldb_request *req, struct ldb_reply *ares)
{
struct asq_context *ac;
+ int ret;
- if (!context || !ares) {
- ldb_set_errstring(ldb, "NULL Context or Result in callback");
- goto error;
- }
+ ac = talloc_get_type(req->context, struct asq_context);
- ac = talloc_get_type(context, struct asq_context);
- if (ac == NULL) {
- goto error;
+ if (!ares) {
+ return ldb_module_done(ac->req, NULL, NULL,
+ LDB_ERR_OPERATIONS_ERROR);
+ }
+ if (ares->error != LDB_SUCCESS) {
+ return ldb_module_done(ac->req, ares->controls,
+ ares->response, ares->error);
}
- /* we are interested only in the single reply (base search) we receive here */
- if (ares->type == LDB_REPLY_ENTRY) {
+ switch (ares->type) {
+ case LDB_REPLY_ENTRY:
ac->base_res = talloc_move(ac, &ares);
- } else {
+ break;
+
+ case LDB_REPLY_REFERRAL:
+ /* ignore referrals */
talloc_free(ares);
- }
+ break;
+ case LDB_REPLY_DONE:
+
+ talloc_free(ares);
+
+ /* next step */
+ ret = asq_search_continue(ac);
+ if (ret != LDB_SUCCESS) {
+ return ldb_module_done(ac->req, NULL, NULL, ret);
+ }
+ break;
+
+ }
return LDB_SUCCESS;
-error:
- talloc_free(ares);
- return LDB_ERR_OPERATIONS_ERROR;
}
-static int asq_reqs_callback(struct ldb_context *ldb, void *context, struct ldb_reply *ares)
+static int asq_reqs_callback(struct ldb_request *req, struct ldb_reply *ares)
{
struct asq_context *ac;
+ int ret;
- if (!context || !ares) {
- ldb_set_errstring(ldb, "NULL Context or Result in callback");
- goto error;
- }
+ ac = talloc_get_type(req->context, struct asq_context);
- ac = talloc_get_type(context, struct asq_context);
- if (ac == NULL) {
- goto error;
+ if (!ares) {
+ return ldb_module_done(ac->req, NULL, NULL,
+ LDB_ERR_OPERATIONS_ERROR);
+ }
+ if (ares->error != LDB_SUCCESS) {
+ return ldb_module_done(ac->req, ares->controls,
+ ares->response, ares->error);
}
- /* we are interested only in the single reply (base search) we receive here */
- if (ares->type == LDB_REPLY_ENTRY) {
-
+ switch (ares->type) {
+ case LDB_REPLY_ENTRY:
/* pass the message up to the original callback as we
* do not have to elaborate on it any further */
- return ac->orig_req->callback(ac->module->ldb, ac->orig_req->context, ares);
-
- } else { /* ignore any REFERRAL or DONE reply */
+ ret = ldb_module_send_entry(ac->req, ares->message);
+ if (ret != LDB_SUCCESS) {
+ return ldb_module_done(ac->req, NULL, NULL, ret);
+ }
+ talloc_free(ares);
+ break;
+
+ case LDB_REPLY_REFERRAL:
+ /* ignore referrals */
+ talloc_free(ares);
+ break;
+
+ case LDB_REPLY_DONE:
+
talloc_free(ares);
+
+ ret = asq_search_continue(ac);
+ if (ret != LDB_SUCCESS) {
+ return ldb_module_done(ac->req, NULL, NULL, ret);
+ }
+ break;
}
return LDB_SUCCESS;
-error:
- talloc_free(ares);
- return LDB_ERR_OPERATIONS_ERROR;
}
-static int asq_build_first_request(struct asq_context *ac)
+static int asq_build_first_request(struct asq_context *ac, struct ldb_request **base_req)
{
- char **base_attrs;
+ const char **base_attrs;
+ int ret;
- ac->base_req = talloc_zero(ac, struct ldb_request);
- if (ac->base_req == NULL) return LDB_ERR_OPERATIONS_ERROR;
+ ac->req_attrs = ac->req->op.search.attrs;
+ ac->req_attribute = talloc_strdup(ac, ac->asq_ctrl->source_attribute);
+ if (ac->req_attribute == NULL)
+ return LDB_ERR_OPERATIONS_ERROR;
- ac->base_req->operation = ac->orig_req->operation;
- ac->base_req->op.search.base = ac->orig_req->op.search.base;
- ac->base_req->op.search.scope = LDB_SCOPE_BASE;
- ac->base_req->op.search.tree = ac->orig_req->op.search.tree;
- base_attrs = talloc_array(ac->base_req, char *, 2);
+ base_attrs = talloc_array(ac, const char *, 2);
if (base_attrs == NULL) return LDB_ERR_OPERATIONS_ERROR;
base_attrs[0] = talloc_strdup(base_attrs, ac->asq_ctrl->source_attribute);
if (base_attrs[0] == NULL) return LDB_ERR_OPERATIONS_ERROR;
base_attrs[1] = NULL;
- ac->base_req->op.search.attrs = (const char * const *)base_attrs;
- ac->base_req->context = ac;
- ac->base_req->callback = asq_base_callback;
- ldb_set_timeout_from_prev_req(ac->module->ldb, ac->orig_req, ac->base_req);
+ ret = ldb_build_search_req(base_req, ac->module->ldb, ac,
+ ac->req->op.search.base,
+ LDB_SCOPE_BASE,
+ NULL,
+ (const char * const *)base_attrs,
+ NULL,
+ ac, asq_base_callback,
+ ac->req);
+ if (ret != LDB_SUCCESS) {
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
return LDB_SUCCESS;
}
-static int asq_build_multiple_requests(struct asq_context *ac, struct ldb_handle *handle)
+static int asq_build_multiple_requests(struct asq_context *ac, bool *terminated)
{
+ struct ldb_control **saved_controls;
+ struct ldb_control *control;
+ struct ldb_dn *dn;
struct ldb_message_element *el;
- int i;
+ int ret, i;
- /* look up the DNs */
if (ac->base_res == NULL) {
return LDB_ERR_NO_SUCH_OBJECT;
}
+
el = ldb_msg_find_element(ac->base_res->message, ac->req_attribute);
/* no values found */
if (el == NULL) {
ac->asq_ret = ASQ_CTRL_SUCCESS;
- return asq_terminate(handle);
+ *terminated = true;
+ return asq_search_terminate(ac);
}
ac->num_reqs = el->num_values;
@@ -259,144 +266,75 @@ static int asq_build_multiple_requests(struct asq_context *ac, struct ldb_handle
for (i = 0; i < el->num_values; i++) {
- ac->reqs[i] = talloc_zero(ac->reqs, struct ldb_request);
- if (ac->reqs[i] == NULL)
- return LDB_ERR_OPERATIONS_ERROR;
- ac->reqs[i]->operation = LDB_SEARCH;
- ac->reqs[i]->op.search.base = ldb_dn_new(ac->reqs[i], ac->module->ldb, (const char *)el->values[i].data);
- if ( ! ldb_dn_validate(ac->reqs[i]->op.search.base)) {
+ dn = ldb_dn_new(ac, ac->module->ldb,
+ (const char *)el->values[i].data);
+ if ( ! ldb_dn_validate(dn)) {
ac->asq_ret = ASQ_CTRL_INVALID_ATTRIBUTE_SYNTAX;
- return asq_terminate(handle);
+ *terminated = true;
+ return asq_search_terminate(ac);
+ }
+
+ ret = ldb_build_search_req_ex(&ac->reqs[i],
+ ac->module->ldb, ac,
+ dn, LDB_SCOPE_BASE,
+ ac->req->op.search.tree,
+ ac->req_attrs,
+ ac->req->controls,
+ ac, asq_reqs_callback,
+ ac->req);
+ if (ret != LDB_SUCCESS) {
+ return LDB_ERR_OPERATIONS_ERROR;
}
- ac->reqs[i]->op.search.scope = LDB_SCOPE_BASE;
- ac->reqs[i]->op.search.tree = ac->base_req->op.search.tree;
- ac->reqs[i]->op.search.attrs = ac->req_attrs;
- ac->reqs[i]->context = ac;
- ac->reqs[i]->callback = asq_reqs_callback;
- ldb_set_timeout_from_prev_req(ac->module->ldb, ac->base_req, ac->reqs[i]);
+ /* remove the ASQ control itself */
+ control = ldb_request_get_control(ac->req, LDB_CONTROL_ASQ_OID);
+ if (!save_controls(control, ac->reqs[i], &saved_controls)) {
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
}
return LDB_SUCCESS;
}
-static int asq_search_continue(struct ldb_handle *handle)
+static int asq_search_continue(struct asq_context *ac)
{
- struct asq_context *ac;
+ bool terminated = false;
int ret;
-
- if (!handle || !handle->private_data) {
- return LDB_ERR_OPERATIONS_ERROR;
- }
-
- if (handle->state == LDB_ASYNC_DONE) {
- return handle->status;
- }
-
- ac = talloc_get_type(handle->private_data, struct asq_context);
- if (ac == NULL) {
- return LDB_ERR_OPERATIONS_ERROR;
- }
switch (ac->step) {
- case ASQ_INIT:
- /* check the search is well formed */
- if (ac->orig_req->op.search.scope != LDB_SCOPE_BASE) {
- ac->asq_ret = ASQ_CTRL_UNWILLING_TO_PERFORM;
- return asq_terminate(handle);
- }
-
- ac->req_attrs = ac->orig_req->op.search.attrs;
- ac->req_attribute = talloc_strdup(ac, ac->asq_ctrl->source_attribute);
- if (ac->req_attribute == NULL)
- return LDB_ERR_OPERATIONS_ERROR;
-
- /* get the object to retrieve the DNs to search */
- ret = asq_build_first_request(ac);
- if (ret != LDB_SUCCESS) {
- return ret;
- }
-
- ac->step = ASQ_SEARCH_BASE;
-
- handle->state = LDB_ASYNC_PENDING;
- handle->status = LDB_SUCCESS;
-
- return ldb_request(ac->module->ldb, ac->base_req);
-
case ASQ_SEARCH_BASE:
- ret = ldb_wait(ac->base_req->handle, LDB_WAIT_NONE);
-
- if (ret != LDB_SUCCESS) {
- handle->status = ret;
- goto done;
- }
-
- if (ac->base_req->handle->status != LDB_SUCCESS) {
- handle->status = ac->base_req->handle->status;
- goto done;
+ /* build up the requests call chain */
+ ret = asq_build_multiple_requests(ac, &terminated);
+ if (ret != LDB_SUCCESS || terminated) {
+ return ret;
}
- if (ac->base_req->handle->state == LDB_ASYNC_DONE) {
+ ac->step = ASQ_SEARCH_MULTI;
- /* build up the requests call chain */
- ret = asq_build_multiple_requests(ac, handle);
- if (ret != LDB_SUCCESS) {
- return ret;
- }
- if (handle->state == LDB_ASYNC_DONE) {
- return LDB_SUCCESS;
- }
-
- ac->step = ASQ_SEARCH_MULTI;
-
- return ldb_request(ac->module->ldb, ac->reqs[ac->cur_req]);
- }
-
- /* request still pending, return to cycle again */
- return LDB_SUCCESS;
+ return ldb_request(ac->module->ldb, ac->reqs[ac->cur_req]);
case ASQ_SEARCH_MULTI:
- ret = ldb_wait(ac->reqs[ac->cur_req]->handle, LDB_WAIT_NONE);
-
- if (ret != LDB_SUCCESS) {
- handle->status = ret;
- goto done;
- }
- if (ac->reqs[ac->cur_req]->handle->status != LDB_SUCCESS) {
- handle->status = ac->reqs[ac->cur_req]->handle->status;
- }
-
- if (ac->reqs[ac->cur_req]->handle->state == LDB_ASYNC_DONE) {
- ac->cur_req++;
+ ac->cur_req++;
- if (ac->cur_req < ac->num_reqs) {
- return ldb_request(ac->module->ldb, ac->reqs[ac->cur_req]);
- }
-
- return asq_terminate(handle);
+ if (ac->cur_req == ac->num_reqs) {
+ /* done */
+ return asq_search_terminate(ac);
}
- /* request still pending, return to cycle again */
- return LDB_SUCCESS;
-
- default:
- ret = LDB_ERR_OPERATIONS_ERROR;
- break;
+ return ldb_request(ac->module->ldb, ac->reqs[ac->cur_req]);
}
-done:
- handle->state = LDB_ASYNC_DONE;
- return ret;
+ return LDB_ERR_OPERATIONS_ERROR;
}
static int asq_search(struct ldb_module *module, struct ldb_request *req)
{
+ struct ldb_request *base_req;
struct ldb_control *control;
struct asq_context *ac;
- struct ldb_handle *h;
+ int ret;
/* check if there's a paged request control */
control = ldb_request_get_control(req, LDB_CONTROL_ASQ_OID);
@@ -405,67 +343,37 @@ static int asq_search(struct ldb_module *module, struct ldb_request *req)
return ldb_next_request(module, req);
}
- req->handle = NULL;
-
- if (!req->callback || !req->context) {
- ldb_set_errstring(module->ldb,
- "Async interface called with NULL callback function or NULL context");
+ ac = asq_context_init(module, req);
+ if (!ac) {
return LDB_ERR_OPERATIONS_ERROR;
}
- h = init_handle(req, module);
- if (!h) {
- return LDB_ERR_OPERATIONS_ERROR;
+ /* check the search is well formed */
+ if (req->op.search.scope != LDB_SCOPE_BASE) {
+ ac->asq_ret = ASQ_CTRL_UNWILLING_TO_PERFORM;
+ return asq_search_terminate(ac);
}
- ac = talloc_get_type(h->private_data, struct asq_context);
ac->asq_ctrl = talloc_get_type(control->data, struct ldb_asq_control);
if (!ac->asq_ctrl) {
return LDB_ERR_PROTOCOL_ERROR;
}
- req->handle = h;
-
- return asq_search_continue(h);
-}
-
-static int asq_wait(struct ldb_handle *handle, enum ldb_wait_type type)
-{
- int ret;
-
- if (!handle || !handle->private_data) {
- return LDB_ERR_OPERATIONS_ERROR;
+ ret = asq_build_first_request(ac, &base_req);
+ if (ret != LDB_SUCCESS) {
+ return ret;
}
- if (type == LDB_WAIT_ALL) {
- while (handle->state != LDB_ASYNC_DONE) {
- ret = asq_search_continue(handle);
- if (ret != LDB_SUCCESS) {
- return ret;
- }
- }
-
- return handle->status;
- }
+ ac->step = ASQ_SEARCH_BASE;
- return asq_search_continue(handle);
+ return ldb_request(module->ldb, base_req);
}
static int asq_init(struct ldb_module *module)
{
- struct ldb_request *req;
int ret;
- req = talloc_zero(module, struct ldb_request);
- if (req == NULL) {
- ldb_debug(module->ldb, LDB_DEBUG_ERROR, "asq: Out of memory!\n");
- return LDB_ERR_OPERATIONS_ERROR;
- }
-
- req->operation = LDB_REQ_REGISTER_CONTROL;
- req->op.reg_control.oid = LDB_CONTROL_ASQ_OID;
-
- ret = ldb_request(module->ldb, req);
+ ret = ldb_mod_register_control(module, LDB_CONTROL_ASQ_OID);
if (ret != LDB_SUCCESS) {
ldb_debug(module->ldb, LDB_DEBUG_WARNING, "asq: Unable to register control with rootdse!\n");
}
@@ -476,6 +384,5 @@ static int asq_init(struct ldb_module *module)
const struct ldb_module_ops ldb_asq_module_ops = {
.name = "asq",
.search = asq_search,
- .wait = asq_wait,
.init_context = asq_init
};
diff --git a/source4/lib/ldb/modules/operational.c b/source4/lib/ldb/modules/operational.c
index a59e81becd..abb1d4ca1a 100644
--- a/source4/lib/ldb/modules/operational.c
+++ b/source4/lib/ldb/modules/operational.c
@@ -2,7 +2,7 @@
ldb database library
Copyright (C) Andrew Tridgell 2005
- Copyright (C) Simo Sorce 2006
+ Copyright (C) Simo Sorce 2006-2008
** NOTE! The following LGPL license applies to the ldb
** library. This does NOT imply that all of Samba is released
@@ -173,38 +173,53 @@ failed:
*/
struct operational_context {
-
struct ldb_module *module;
- void *up_context;
- int (*up_callback)(struct ldb_context *, void *, struct ldb_reply *);
+ struct ldb_request *req;
const char * const *attrs;
};
-static int operational_callback(struct ldb_context *ldb, void *context, struct ldb_reply *ares)
+static int operational_callback(struct ldb_request *req, struct ldb_reply *ares)
{
struct operational_context *ac;
+ int ret;
- if (!context || !ares) {
- ldb_set_errstring(ldb, "NULL Context or Result in callback");
- goto error;
- }
+ ac = talloc_get_type(req->context, struct operational_context);
- ac = talloc_get_type(context, struct operational_context);
+ if (!ares) {
+ return ldb_module_done(ac->req, NULL, NULL,
+ LDB_ERR_OPERATIONS_ERROR);
+ }
+ if (ares->error != LDB_SUCCESS) {
+ return ldb_module_done(ac->req, ares->controls,
+ ares->response, ares->error);
+ }
- if (ares->type == LDB_REPLY_ENTRY) {
+ switch (ares->type) {
+ case LDB_REPLY_ENTRY:
/* for each record returned post-process to add any derived
attributes that have been asked for */
- if (operational_search_post_process(ac->module, ares->message, ac->attrs) != 0) {
- goto error;
+ ret = operational_search_post_process(ac->module,
+ ares->message,
+ ac->attrs);
+ if (ret != 0) {
+ return ldb_module_done(ac->req, NULL, NULL,
+ LDB_ERR_OPERATIONS_ERROR);
}
- }
+ return ldb_module_send_entry(ac->req, ares->message);
- return ac->up_callback(ldb, ac->up_context, ares);
+ case LDB_REPLY_REFERRAL:
+ /* ignore referrals */
+ break;
+
+ case LDB_REPLY_DONE:
+
+ return ldb_module_done(ac->req, ares->controls,
+ ares->response, LDB_SUCCESS);
+ }
-error:
talloc_free(ares);
- return LDB_ERR_OPERATIONS_ERROR;
+ return LDB_SUCCESS;
}
static int operational_search(struct ldb_module *module, struct ldb_request *req)
@@ -212,9 +227,8 @@ static int operational_search(struct ldb_module *module, struct ldb_request *req
struct operational_context *ac;
struct ldb_request *down_req;
const char **search_attrs = NULL;
- int i, a, ret;
-
- req->handle = NULL;
+ int i, a;
+ int ret;
ac = talloc(req, struct operational_context);
if (ac == NULL) {
@@ -222,21 +236,10 @@ static int operational_search(struct ldb_module *module, struct ldb_request *req
}
ac->module = module;
- ac->up_context = req->context;
- ac->up_callback = req->callback;
+ ac->req = req;
ac->attrs = req->op.search.attrs;
- down_req = talloc_zero(req, struct ldb_request);
- if (down_req == NULL) {
- return LDB_ERR_OPERATIONS_ERROR;
- }
-
- down_req->operation = req->operation;
- down_req->op.search.base = req->op.search.base;
- down_req->op.search.scope = req->op.search.scope;
- down_req->op.search.tree = req->op.search.tree;
-
- /* FIXME: I hink we should copy the tree and keep the original
+ /* FIXME: We must copy the tree and keep the original
* unmodified. SSS */
/* replace any attributes in the parse tree that are
searchable, but are stored using a different name in the
@@ -264,27 +267,26 @@ static int operational_search(struct ldb_module *module, struct ldb_request *req
}
}
}
-
- /* use new set of attrs if any */
- if (search_attrs) down_req->op.search.attrs = search_attrs;
- else down_req->op.search.attrs = req->op.search.attrs;
-
- down_req->controls = req->controls;
-
- down_req->context = ac;
- down_req->callback = operational_callback;
- ldb_set_timeout_from_prev_req(module->ldb, req, down_req);
- /* perform the search */
- ret = ldb_next_request(module, down_req);
+ /* use new set of attrs if any */
+ if (search_attrs == NULL) {
+ search_attrs = req->op.search.attrs;
+ }
- /* 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->handle = down_req->handle;
+ ret = ldb_build_search_req_ex(&down_req, module->ldb, ac,
+ req->op.search.base,
+ req->op.search.scope,
+ req->op.search.tree,
+ (const char * const *)search_attrs,
+ req->controls,
+ ac, operational_callback,
+ req);
+ if (ret != LDB_SUCCESS) {
+ return LDB_ERR_OPERATIONS_ERROR;
}
- return ret;
+ /* perform the search */
+ return ldb_next_request(module, down_req);
}
static int operational_init(struct ldb_module *ctx)
diff --git a/source4/lib/ldb/modules/paged_results.c b/source4/lib/ldb/modules/paged_results.c
index b62b1f92cb..1a242f1be0 100644
--- a/source4/lib/ldb/modules/paged_results.c
+++ b/source4/lib/ldb/modules/paged_results.c
@@ -1,7 +1,7 @@
/*
ldb database library
- Copyright (C) Simo Sorce 2005-2006
+ Copyright (C) Simo Sorce 2005-2008
** NOTE! The following LGPL license applies to the ldb
** library. This does NOT imply that all of Samba is released
@@ -51,9 +51,8 @@ struct results_store {
char *cookie;
time_t timestamp;
- struct results_store *prev;
struct results_store *next;
-
+
struct message_store *first;
struct message_store *last;
int num_entries;
@@ -62,8 +61,6 @@ struct results_store {
struct message_store *last_ref;
struct ldb_control **controls;
-
- struct ldb_request *req;
};
struct private_data {
@@ -73,20 +70,25 @@ struct private_data {
};
-int store_destructor(struct results_store *store)
+static int store_destructor(struct results_store *del)
{
- if (store->prev) {
- store->prev->next = store->next;
- }
- if (store->next) {
- store->next->prev = store->prev;
+ struct private_data *priv = del->priv;
+ struct results_store *loop;
+
+ if (priv->store == del) {
+ priv->store = del->next;
+ return 0;
}
- if (store == store->priv->store) {
- store->priv->store = NULL;
+ for (loop = priv->store; loop; loop = loop->next) {
+ if (loop->next == del) {
+ loop->next = del->next;
+ return 0;
+ }
}
- return 0;
+ /* is not in list ? */
+ return -1;
}
static struct results_store *new_store(struct private_data *priv)
@@ -116,10 +118,7 @@ static struct results_store *new_store(struct private_data *priv)
newr->first_ref = NULL;
newr->controls = NULL;
- /* put this entry as first */
- newr->prev = NULL;
newr->next = priv->store;
- if (priv->store != NULL) priv->store->prev = newr;
priv->store = newr;
talloc_set_destructor(newr, store_destructor);
@@ -129,101 +128,164 @@ static struct results_store *new_store(struct private_data *priv)
struct paged_context {
struct ldb_module *module;
- void *up_context;
- int (*up_callback)(struct ldb_context *, void *, struct ldb_reply *);
-
- int size;
+ struct ldb_request *req;
struct results_store *store;
+ int size;
+ struct ldb_control **controls;
};
-static struct ldb_handle *init_handle(void *mem_ctx, struct ldb_module *module,
- void *context,
- int (*callback)(struct ldb_context *, void *, struct ldb_reply *))
+static int paged_results(struct paged_context *ac)
{
- struct paged_context *ac;
- struct ldb_handle *h;
+ struct ldb_paged_control *paged;
+ struct message_store *msg;
+ int i, num_ctrls, ret;
- h = talloc_zero(mem_ctx, struct ldb_handle);
- if (h == NULL) {
- ldb_set_errstring(module->ldb, "Out of Memory");
- return NULL;
+ if (ac->store == NULL) {
+ return LDB_ERR_OPERATIONS_ERROR;
}
- h->module = module;
+ while (ac->store->num_entries > 0 && ac->size > 0) {
+ msg = ac->store->first;
+ ret = ldb_module_send_entry(ac->req, msg->r->message);
+ if (ret != LDB_SUCCESS) {
+ return ret;
+ }
- ac = talloc_zero(h, struct paged_context);
- if (ac == NULL) {
- ldb_set_errstring(module->ldb, "Out of Memory");
- talloc_free(h);
- return NULL;
+ ac->store->first = msg->next;
+ talloc_free(msg);
+ ac->store->num_entries--;
+ ac->size--;
}
- h->private_data = (void *)ac;
+ while (ac->store->first_ref != NULL) {
+ msg = ac->store->first_ref;
+ ret = ldb_module_send_referral(ac->req, msg->r->referral);
+ if (ret != LDB_SUCCESS) {
+ return ret;
+ }
- h->state = LDB_ASYNC_INIT;
- h->status = LDB_SUCCESS;
+ ac->store->first_ref = msg->next;
+ talloc_free(msg);
+ }
- ac->module = module;
- ac->up_context = context;
- ac->up_callback = callback;
+ /* return result done */
+ num_ctrls = 1;
+ i = 0;
+
+ if (ac->store->controls != NULL) {
+ while (ac->store->controls[i]) i++; /* counting */
+
+ num_ctrls += i;
+ }
+
+ ac->controls = talloc_array(ac, struct ldb_control *, num_ctrls +1);
+ if (ac->controls == NULL) {
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+ ac->controls[num_ctrls] = NULL;
+
+ for (i = 0; i < (num_ctrls -1); i++) {
+ ac->controls[i] = talloc_reference(ac->controls, ac->store->controls[i]);
+ }
+
+ ac->controls[i] = talloc(ac->controls, struct ldb_control);
+ if (ac->controls[i] == NULL) {
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
- return h;
+ ac->controls[i]->oid = talloc_strdup(ac->controls[i],
+ LDB_CONTROL_PAGED_RESULTS_OID);
+ if (ac->controls[i]->oid == NULL) {
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
+ ac->controls[i]->critical = 0;
+
+ paged = talloc(ac->controls[i], struct ldb_paged_control);
+ if (paged == NULL) {
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
+ ac->controls[i]->data = paged;
+
+ if (ac->size > 0) {
+ paged->size = 0;
+ paged->cookie = NULL;
+ paged->cookie_len = 0;
+ } else {
+ paged->size = ac->store->num_entries;
+ paged->cookie = talloc_strdup(paged, ac->store->cookie);
+ paged->cookie_len = strlen(paged->cookie) + 1;
+ }
+
+ return LDB_SUCCESS;
}
-static int paged_search_callback(struct ldb_context *ldb, void *context, struct ldb_reply *ares)
+static int paged_search_callback(struct ldb_request *req, struct ldb_reply *ares)
{
- struct paged_context *ac = NULL;
+ struct paged_context *ac ;
+ struct message_store *msg_store;
+ int ret;
- if (!context || !ares) {
- ldb_set_errstring(ldb, "NULL Context or Result in callback");
- goto error;
+ ac = talloc_get_type(req->context, struct paged_context);
+
+ if (!ares) {
+ return ldb_module_done(ac->req, NULL, NULL,
+ LDB_ERR_OPERATIONS_ERROR);
+ }
+ if (ares->error != LDB_SUCCESS) {
+ return ldb_module_done(ac->req, ares->controls,
+ ares->response, ares->error);
}
- ac = talloc_get_type(context, struct paged_context);
+ switch (ares->type) {
+ case LDB_REPLY_ENTRY:
+ msg_store = talloc(ac->store, struct message_store);
+ if (msg_store == NULL) {
+ return ldb_module_done(ac->req, NULL, NULL,
+ LDB_ERR_OPERATIONS_ERROR);
+ }
+ msg_store->next = NULL;
+ msg_store->r = talloc_steal(msg_store, ares);
- if (ares->type == LDB_REPLY_ENTRY) {
if (ac->store->first == NULL) {
- ac->store->first = ac->store->last = talloc(ac->store, struct message_store);
+ ac->store->first = msg_store;
} else {
- ac->store->last->next = talloc(ac->store, struct message_store);
- ac->store->last = ac->store->last->next;
- }
- if (ac->store->last == NULL) {
- goto error;
+ ac->store->last->next = msg_store;
}
+ ac->store->last = msg_store;
ac->store->num_entries++;
- ac->store->last->r = talloc_steal(ac->store->last, ares);
- ac->store->last->next = NULL;
- }
+ break;
+
+ case LDB_REPLY_REFERRAL:
+ msg_store = talloc(ac->store, struct message_store);
+ if (msg_store == NULL) {
+ return ldb_module_done(ac->req, NULL, NULL,
+ LDB_ERR_OPERATIONS_ERROR);
+ }
+ msg_store->next = NULL;
+ msg_store->r = talloc_steal(msg_store, ares);
- if (ares->type == LDB_REPLY_REFERRAL) {
if (ac->store->first_ref == NULL) {
- ac->store->first_ref = ac->store->last_ref = talloc(ac->store, struct message_store);
+ ac->store->first_ref = msg_store;
} else {
- ac->store->last_ref->next = talloc(ac->store, struct message_store);
- ac->store->last_ref = ac->store->last_ref->next;
- }
- if (ac->store->last_ref == NULL) {
- goto error;
+ ac->store->last_ref->next = msg_store;
}
+ ac->store->last_ref = msg_store;
- ac->store->last_ref->r = talloc_steal(ac->store->last, ares);
- ac->store->last_ref->next = NULL;
- }
+ break;
- if (ares->type == LDB_REPLY_DONE) {
+ case LDB_REPLY_DONE:
ac->store->controls = talloc_move(ac->store, &ares->controls);
- talloc_free(ares);
+ ret = paged_results(ac);
+ return ldb_module_done(ac->req, ac->controls,
+ ares->response, ret);
}
return LDB_SUCCESS;
-
-error:
- talloc_free(ares);
- return LDB_ERR_OPERATIONS_ERROR;
}
static int paged_search(struct ldb_module *module, struct ldb_request *req)
@@ -232,8 +294,8 @@ static int paged_search(struct ldb_module *module, struct ldb_request *req)
struct private_data *private_data;
struct ldb_paged_control *paged_ctrl;
struct ldb_control **saved_controls;
+ struct ldb_request *search_req;
struct paged_context *ac;
- struct ldb_handle *h;
int ret;
/* check if there's a paged request control */
@@ -243,65 +305,57 @@ static int paged_search(struct ldb_module *module, struct ldb_request *req)
return ldb_next_request(module, req);
}
- private_data = talloc_get_type(module->private_data, struct private_data);
-
- req->handle = NULL;
-
- if (!req->callback || !req->context) {
- ldb_set_errstring(module->ldb,
- "Async interface called with NULL callback function or NULL context");
- return LDB_ERR_OPERATIONS_ERROR;
- }
-
paged_ctrl = talloc_get_type(control->data, struct ldb_paged_control);
if (!paged_ctrl) {
return LDB_ERR_PROTOCOL_ERROR;
}
- h = init_handle(req, module, req->context, req->callback);
- if (!h) {
+ private_data = talloc_get_type(module->private_data, struct private_data);
+
+ ac = talloc_zero(req, struct paged_context);
+ if (ac == NULL) {
+ ldb_set_errstring(module->ldb, "Out of Memory");
return LDB_ERR_OPERATIONS_ERROR;
}
- ac = talloc_get_type(h->private_data, struct paged_context);
+ ac->module = module;
+ ac->req = req;
ac->size = paged_ctrl->size;
/* check if it is a continuation search the store */
if (paged_ctrl->cookie_len == 0) {
-
- ac->store = new_store(private_data);
- if (ac->store == NULL) {
- talloc_free(h);
- return LDB_ERR_UNWILLING_TO_PERFORM;
+ if (paged_ctrl->size == 0) {
+ return LDB_ERR_OPERATIONS_ERROR;
}
- ac->store->req = talloc(ac->store, struct ldb_request);
- if (!ac->store->req)
+ ac->store = new_store(private_data);
+ if (ac->store == NULL) {
return LDB_ERR_OPERATIONS_ERROR;
+ }
- ac->store->req->operation = req->operation;
- ac->store->req->op.search.base = req->op.search.base;
- ac->store->req->op.search.scope = req->op.search.scope;
- ac->store->req->op.search.tree = req->op.search.tree;
- ac->store->req->op.search.attrs = req->op.search.attrs;
- ac->store->req->controls = req->controls;
+ ret = ldb_build_search_req_ex(&search_req, module->ldb, ac,
+ req->op.search.base,
+ req->op.search.scope,
+ req->op.search.tree,
+ req->op.search.attrs,
+ req->controls,
+ ac,
+ paged_search_callback,
+ req);
/* save it locally and remove it from the list */
/* we do not need to replace them later as we
* are keeping the original req intact */
- if (!save_controls(control, ac->store->req, &saved_controls)) {
+ if (!save_controls(control, search_req, &saved_controls)) {
return LDB_ERR_OPERATIONS_ERROR;
}
- ac->store->req->context = ac;
- ac->store->req->callback = paged_search_callback;
- ldb_set_timeout_from_prev_req(module->ldb, req, ac->store->req);
-
- ret = ldb_next_request(module, ac->store->req);
+ return ldb_next_request(module, search_req);
} else {
struct results_store *current = NULL;
+ /* TODO: age out old outstanding requests */
for (current = private_data->store; current; current = current->next) {
if (strcmp(current->cookie, paged_ctrl->cookie) == 0) {
current->timestamp = time(NULL);
@@ -309,249 +363,52 @@ static int paged_search(struct ldb_module *module, struct ldb_request *req)
}
}
if (current == NULL) {
- talloc_free(h);
return LDB_ERR_UNWILLING_TO_PERFORM;
}
ac->store = current;
- ret = LDB_SUCCESS;
- }
-
- req->handle = h;
-
- /* check if it is an abandon */
- if (ac->size == 0) {
- talloc_free(ac->store);
- h->status = LDB_SUCCESS;
- h->state = LDB_ASYNC_DONE;
- return LDB_SUCCESS;
- }
-
- /* TODO: age out old outstanding requests */
-
- return ret;
-
-}
-
-static int paged_results(struct ldb_handle *handle)
-{
- struct paged_context *ac;
- struct ldb_paged_control *paged;
- struct ldb_reply *ares;
- struct message_store *msg;
- int i, num_ctrls, ret;
-
- ac = talloc_get_type(handle->private_data, struct paged_context);
-
- if (ac->store == NULL)
- return LDB_ERR_OPERATIONS_ERROR;
- while (ac->store->num_entries > 0 && ac->size > 0) {
- msg = ac->store->first;
- ret = ac->up_callback(ac->module->ldb, ac->up_context, msg->r);
- if (ret != LDB_SUCCESS) {
- handle->status = ret;
- handle->state = LDB_ASYNC_DONE;
- return ret;
+ /* check if it is an abandon */
+ if (ac->size == 0) {
+ return ldb_module_done(req, NULL, NULL,
+ LDB_SUCCESS);
}
- ac->store->first = msg->next;
- talloc_free(msg);
- ac->store->num_entries--;
- ac->size--;
- }
-
- handle->state = LDB_ASYNC_DONE;
-
- while (ac->store->first_ref != NULL) {
- msg = ac->store->first_ref;
- ret = ac->up_callback(ac->module->ldb, ac->up_context, msg->r);
+ ret = paged_results(ac);
if (ret != LDB_SUCCESS) {
- handle->status = ret;
- handle->state = LDB_ASYNC_DONE;
- return ret;
+ return ldb_module_done(req, NULL, NULL, ret);
}
-
- ac->store->first_ref = msg->next;
- talloc_free(msg);
- }
-
- ares = talloc_zero(ac->store, struct ldb_reply);
- if (ares == NULL) {
- handle->status = LDB_ERR_OPERATIONS_ERROR;
- return handle->status;
- }
- num_ctrls = 2;
- i = 0;
-
- if (ac->store->controls != NULL) {
- ares->controls = ac->store->controls;
- while (ares->controls[i]) i++; /* counting */
-
- ares->controls = talloc_move(ares, &ac->store->controls);
- num_ctrls += i;
- }
-
- ares->controls = talloc_realloc(ares, ares->controls, struct ldb_control *, num_ctrls);
- if (ares->controls == NULL) {
- handle->status = LDB_ERR_OPERATIONS_ERROR;
- return handle->status;
+ return ldb_module_done(req, ac->controls, NULL,
+ LDB_SUCCESS);
}
-
- ares->controls[i] = talloc(ares->controls, struct ldb_control);
- if (ares->controls[i] == NULL) {
- handle->status = LDB_ERR_OPERATIONS_ERROR;
- return handle->status;
- }
-
- ares->controls[i]->oid = talloc_strdup(ares->controls[i], LDB_CONTROL_PAGED_RESULTS_OID);
- if (ares->controls[i]->oid == NULL) {
- handle->status = LDB_ERR_OPERATIONS_ERROR;
- return handle->status;
- }
-
- ares->controls[i]->critical = 0;
- ares->controls[i + 1] = NULL;
-
- paged = talloc(ares->controls[i], struct ldb_paged_control);
- if (paged == NULL) {
- handle->status = LDB_ERR_OPERATIONS_ERROR;
- return handle->status;
- }
-
- ares->controls[i]->data = paged;
-
- if (ac->size > 0) {
- paged->size = 0;
- paged->cookie = NULL;
- paged->cookie_len = 0;
- } else {
- paged->size = ac->store->num_entries;
- paged->cookie = talloc_strdup(paged, ac->store->cookie);
- paged->cookie_len = strlen(paged->cookie) + 1;
- }
-
- ares->type = LDB_REPLY_DONE;
-
- ret = ac->up_callback(ac->module->ldb, ac->up_context, ares);
-
- handle->status = ret;
-
- return ret;
-}
-
-static int paged_wait_once(struct ldb_handle *handle) {
- struct paged_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;
-
- ac = talloc_get_type(handle->private_data, struct paged_context);
-
- if (ac->store->req->handle->state == LDB_ASYNC_DONE) {
- /* if lower level is finished we do not need to call it anymore */
- /* return all we have until size == 0 or we empty storage */
- ret = paged_results(handle);
-
- /* we are done, if num_entries is zero free the storage
- * as that mean we delivered the last batch */
- if (ac->store->num_entries == 0) {
- talloc_free(ac->store);
- }
-
- return ret;
- }
-
- ret = ldb_wait(ac->store->req->handle, LDB_WAIT_NONE);
- if (ret != LDB_SUCCESS) {
- handle->state = LDB_ASYNC_DONE;
- handle->status = ret;
- return ret;
- }
-
- handle->status = ret;
-
- if (ac->store->num_entries >= ac->size ||
- ac->store->req->handle->state == LDB_ASYNC_DONE) {
-
- ret = paged_results(handle);
-
- /* we are done, if num_entries is zero free the storage
- * as that mean we delivered the last batch */
- if (ac->store->num_entries == 0) {
- talloc_free(ac->store);
- }
- }
-
- return ret;
-}
-
-static int paged_wait(struct ldb_handle *handle, enum ldb_wait_type type)
-{
- int ret;
-
- if (!handle || !handle->private_data) {
- return LDB_ERR_OPERATIONS_ERROR;
- }
-
- if (type == LDB_WAIT_ALL) {
- while (handle->state != LDB_ASYNC_DONE) {
- ret = paged_wait_once(handle);
- if (ret != LDB_SUCCESS) {
- return ret;
- }
- }
-
- return handle->status;
- }
-
- return paged_wait_once(handle);
}
static int paged_request_init(struct ldb_module *module)
{
struct private_data *data;
- struct ldb_request *req;
int ret;
data = talloc(module, struct private_data);
if (data == NULL) {
return LDB_ERR_OTHER;
}
-
+
data->next_free_id = 1;
data->store = NULL;
module->private_data = data;
- req = talloc(module, struct ldb_request);
- if (req == NULL) {
- return LDB_ERR_OPERATIONS_ERROR;
- }
-
- req->operation = LDB_REQ_REGISTER_CONTROL;
- req->op.reg_control.oid = LDB_CONTROL_PAGED_RESULTS_OID;
- req->controls = NULL;
-
- ret = ldb_request(module->ldb, req);
+ ret = ldb_mod_register_control(module, LDB_CONTROL_PAGED_RESULTS_OID);
if (ret != LDB_SUCCESS) {
- ldb_debug(module->ldb, LDB_DEBUG_WARNING, "paged_request: Unable to register control with rootdse!\n");
+ ldb_debug(module->ldb, LDB_DEBUG_WARNING,
+ "paged_request:"
+ "Unable to register control with rootdse!\n");
}
- talloc_free(req);
return ldb_next_init(module);
}
const struct ldb_module_ops ldb_paged_results_module_ops = {
.name = "paged_results",
.search = paged_search,
- .wait = paged_wait,
.init_context = paged_request_init
};
diff --git a/source4/lib/ldb/modules/paged_searches.c b/source4/lib/ldb/modules/paged_searches.c
index 40e87f70d6..7a728e3bb0 100644
--- a/source4/lib/ldb/modules/paged_searches.c
+++ b/source4/lib/ldb/modules/paged_searches.c
@@ -1,7 +1,7 @@
/*
ldb database library
- Copyright (C) Simo Sorce 2005-2006
+ Copyright (C) Simo Sorce 2005-2008
** NOTE! The following LGPL license applies to the ldb
** library. This does NOT imply that all of Samba is released
@@ -46,12 +46,7 @@ struct private_data {
struct ps_context {
struct ldb_module *module;
- void *up_context;
- int (*up_callback)(struct ldb_context *, void *, struct ldb_reply *);
-
- struct ldb_request *orig_req;
-
- struct ldb_request *new_req;
+ struct ldb_request *req;
bool pending;
@@ -59,51 +54,13 @@ struct ps_context {
int num_referrals;
};
-static struct ldb_handle *init_handle(void *mem_ctx, struct ldb_module *module,
- void *context,
- int (*callback)(struct ldb_context *, void *, struct ldb_reply *))
+static int check_ps_continuation(struct ldb_request *req, struct ldb_reply *ares)
{
struct ps_context *ac;
- struct ldb_handle *h;
-
- h = talloc_zero(mem_ctx, struct ldb_handle);
- if (h == NULL) {
- ldb_set_errstring(module->ldb, "Out of Memory");
- return NULL;
- }
-
- h->module = module;
-
- ac = talloc_zero(h, struct ps_context);
- if (ac == NULL) {
- ldb_set_errstring(module->ldb, "Out of Memory");
- talloc_free(h);
- return NULL;
- }
-
- h->private_data = (void *)ac;
-
- h->state = LDB_ASYNC_INIT;
- h->status = LDB_SUCCESS;
-
- ac->module = module;
- ac->up_context = context;
- ac->up_callback = callback;
-
- ac->pending = false;
-
-
-
- ac->saved_referrals = NULL;
- ac->num_referrals = 0;
-
- return h;
-}
-
-static int check_ps_continuation(struct ldb_reply *ares, struct ps_context *ac)
-{
struct ldb_paged_control *rep_control, *req_control;
+ ac = talloc_get_type(req->context, struct ps_context);
+
/* look up our paged control */
if (!ares->controls || strcmp(LDB_CONTROL_PAGED_RESULTS_OID, ares->controls[0]->oid) != 0) {
/* something wrong here */
@@ -122,12 +79,12 @@ static int check_ps_continuation(struct ldb_reply *ares, struct ps_context *ac)
/* if there's a reply control we must find a request
* control matching it */
- if (strcmp(LDB_CONTROL_PAGED_RESULTS_OID, ac->new_req->controls[0]->oid) != 0) {
+ if (strcmp(LDB_CONTROL_PAGED_RESULTS_OID, req->controls[0]->oid) != 0) {
/* something wrong here */
return LDB_ERR_OPERATIONS_ERROR;
}
- req_control = talloc_get_type(ac->new_req->controls[0]->data, struct ldb_paged_control);
+ req_control = talloc_get_type(req->controls[0]->data, struct ldb_paged_control);
if (req_control->cookie) {
talloc_free(req_control->cookie);
@@ -142,7 +99,7 @@ static int check_ps_continuation(struct ldb_reply *ares, struct ps_context *ac)
return LDB_SUCCESS;
}
-static int store_referral(char *referral, struct ps_context *ac)
+static int store_referral(struct ps_context *ac, char *referral)
{
ac->saved_referrals = talloc_realloc(ac, ac->saved_referrals, char *, ac->num_referrals + 2);
if (!ac->saved_referrals) {
@@ -160,13 +117,14 @@ static int store_referral(char *referral, struct ps_context *ac)
return LDB_SUCCESS;
}
-static int send_referrals(struct ldb_context *ldb, struct ps_context *ac)
+static int send_referrals(struct ps_context *ac)
{
struct ldb_reply *ares;
+ int ret;
int i;
for (i = 0; i < ac->num_referrals; i++) {
- ares = talloc_zero(ac, struct ldb_reply);
+ ares = talloc_zero(ac->req, struct ldb_reply);
if (!ares) {
return LDB_ERR_OPERATIONS_ERROR;
}
@@ -174,69 +132,87 @@ static int send_referrals(struct ldb_context *ldb, struct ps_context *ac)
ares->type = LDB_REPLY_REFERRAL;
ares->referral = ac->saved_referrals[i];
- ac->up_callback(ldb, ac->up_context, ares);
+ ret = ldb_module_send_referral(ac->req, ares->referral);
+ if (ret != LDB_SUCCESS) {
+ return ret;
+ }
}
return LDB_SUCCESS;
}
-static int ps_callback(struct ldb_context *ldb, void *context, struct ldb_reply *ares)
+static int ps_next_request(struct ps_context *ac);
+
+static int ps_callback(struct ldb_request *req, struct ldb_reply *ares)
{
- struct ps_context *ac = NULL;
- int ret = LDB_ERR_OPERATIONS_ERROR;
+ struct ps_context *ac;
+ int ret;
- if (!context || !ares) {
- ldb_set_errstring(ldb, "NULL Context or Result in callback");
- goto error;
- }
+ ac = talloc_get_type(req->context, struct ps_context);
- ac = talloc_get_type(context, struct ps_context);
+ if (!ares) {
+ return ldb_module_done(ac->req, NULL, NULL,
+ LDB_ERR_OPERATIONS_ERROR);
+ }
+ if (ares->error != LDB_SUCCESS) {
+ return ldb_module_done(ac->req, ares->controls,
+ ares->response, ares->error);
+ }
switch (ares->type) {
case LDB_REPLY_ENTRY:
- ac->up_callback(ldb, ac->up_context, ares);
+ ret = ldb_module_send_entry(ac->req, ares->message);
+ if (ret != LDB_SUCCESS) {
+ return ldb_module_done(ac->req, NULL, NULL, ret);
+ }
break;
case LDB_REPLY_REFERRAL:
- ret = store_referral(ares->referral, ac);
+ ret = store_referral(ac, ares->referral);
if (ret != LDB_SUCCESS) {
- goto error;
+ return ldb_module_done(ac->req, NULL, NULL, ret);
}
break;
case LDB_REPLY_DONE:
- ret = check_ps_continuation(ares, ac);
+
+ ret = check_ps_continuation(req, ares);
if (ret != LDB_SUCCESS) {
- goto error;
+ return ldb_module_done(ac->req, NULL, NULL, ret);
}
- if (!ac->pending) {
+
+ if (ac->pending) {
+
+ ret = ps_next_request(ac);
+ if (ret != LDB_SUCCESS) {
+ return ldb_module_done(ac->req,
+ NULL, NULL, ret);
+ }
+
+ } else {
+
/* send referrals */
- ret = send_referrals(ldb, ac);
+ ret = send_referrals(ac);
if (ret != LDB_SUCCESS) {
- goto error;
+ return ldb_module_done(ac->req,
+ NULL, NULL, ret);
}
/* send REPLY_DONE */
- ac->up_callback(ldb, ac->up_context, ares);
+ return ldb_module_done(ac->req, ares->controls,
+ ares->response, LDB_SUCCESS);
}
break;
- default:
- goto error;
}
- return LDB_SUCCESS;
-
-error:
talloc_free(ares);
- return ret;
+ return LDB_SUCCESS;
}
static int ps_search(struct ldb_module *module, struct ldb_request *req)
{
struct private_data *private_data;
- struct ldb_paged_control *control;
struct ps_context *ac;
- struct ldb_handle *h;
private_data = talloc_get_type(module->private_data, struct private_data);
@@ -248,216 +224,151 @@ static int ps_search(struct ldb_module *module, struct ldb_request *req)
return ldb_next_request(module, req);
}
- if (!req->callback || !req->context) {
- ldb_set_errstring(module->ldb,
- "Async interface called with NULL callback function or NULL context");
- return LDB_ERR_OPERATIONS_ERROR;
- }
-
- h = init_handle(req, module, req->context, req->callback);
- if (!h) {
+ ac = talloc_zero(req, struct ps_context);
+ if (ac == NULL) {
+ ldb_oom(module->ldb);
return LDB_ERR_OPERATIONS_ERROR;
}
- ac = talloc_get_type(h->private_data, struct ps_context);
-
- ac->new_req = talloc(ac, struct ldb_request);
- if (!ac->new_req) return LDB_ERR_OPERATIONS_ERROR;
-
- ac->new_req->controls = talloc_array(ac->new_req, struct ldb_control *, 2);
- if (!ac->new_req->controls) return LDB_ERR_OPERATIONS_ERROR;
-
- ac->new_req->controls[0] = talloc(ac->new_req->controls, struct ldb_control);
- if (!ac->new_req->controls[0]) return LDB_ERR_OPERATIONS_ERROR;
-
- control = talloc(ac->new_req->controls[0], struct ldb_paged_control);
- if (!control) return LDB_ERR_OPERATIONS_ERROR;
-
- control->size = PS_DEFAULT_PAGE_SIZE;
- control->cookie = NULL;
- control->cookie_len = 0;
-
- ac->new_req->controls[0]->oid = LDB_CONTROL_PAGED_RESULTS_OID;
- ac->new_req->controls[0]->critical = 1;
- ac->new_req->controls[0]->data = control;
-
- ac->new_req->controls[1] = NULL;
- ac->new_req->operation = req->operation;
- ac->new_req->op.search.base = req->op.search.base;
- ac->new_req->op.search.scope = req->op.search.scope;
- ac->new_req->op.search.tree = req->op.search.tree;
- ac->new_req->op.search.attrs = req->op.search.attrs;
- ac->new_req->context = ac;
- ac->new_req->callback = ps_callback;
- ldb_set_timeout_from_prev_req(module->ldb, req, ac->new_req);
-
- req->handle = h;
+ ac->module = module;
+ ac->req = req;
+ ac->pending = false;
+ ac->saved_referrals = NULL;
+ ac->num_referrals = 0;
- return ldb_next_request(module, ac->new_req);
+ return ps_next_request(ac);
}
-static int ps_continuation(struct ldb_handle *handle)
-{
- struct ps_context *ac;
+static int ps_next_request(struct ps_context *ac) {
- if (!handle || !handle->private_data) {
+ struct ldb_paged_control *control;
+ struct ldb_control **controls;
+ struct ldb_request *new_req;
+ int ret;
+
+ controls = talloc_array(ac, struct ldb_control *, 2);
+ if (!controls) {
return LDB_ERR_OPERATIONS_ERROR;
}
- ac = talloc_get_type(handle->private_data, struct ps_context);
-
- /* reset the requests handle */
- ac->new_req->handle = NULL;
-
- return ldb_next_request(handle->module, ac->new_req);
-}
-
-static int ps_wait_once(struct ldb_handle *handle)
-{
- struct ps_context *ac;
- int ret;
-
- if (!handle || !handle->private_data) {
+ controls[0] = talloc(controls, struct ldb_control);
+ if (!controls[0]) {
return LDB_ERR_OPERATIONS_ERROR;
}
- if (handle->state == LDB_ASYNC_DONE) {
- return handle->status;
+ control = talloc(controls[0], struct ldb_paged_control);
+ if (!control) {
+ return LDB_ERR_OPERATIONS_ERROR;
}
- handle->state = LDB_ASYNC_PENDING;
- handle->status = LDB_SUCCESS;
-
- ac = talloc_get_type(handle->private_data, struct ps_context);
-
- ret = ldb_wait(ac->new_req->handle, LDB_WAIT_NONE);
+ control->size = PS_DEFAULT_PAGE_SIZE;
+ control->cookie = NULL;
+ control->cookie_len = 0;
+ controls[0]->oid = LDB_CONTROL_PAGED_RESULTS_OID;
+ controls[0]->critical = 1;
+ controls[0]->data = control;
+ controls[1] = NULL;
+
+ ret = ldb_build_search_req_ex(&new_req, ac->module->ldb, ac,
+ ac->req->op.search.base,
+ ac->req->op.search.scope,
+ ac->req->op.search.tree,
+ ac->req->op.search.attrs,
+ controls,
+ ac,
+ ps_callback,
+ ac->req);
if (ret != LDB_SUCCESS) {
- handle->status = ret;
- goto done;
- }
-
- if (ac->new_req->handle->status != LDB_SUCCESS) {
- handle->status = ac->new_req->handle->status;
- goto done;
- }
-
- if (ac->new_req->handle->state != LDB_ASYNC_DONE) {
- return LDB_SUCCESS;
- }
-
- /* see if we need to send another request for the next batch */
- if (ac->pending) {
- ret = ps_continuation(handle);
- if (ret != LDB_SUCCESS) {
- handle->status = ret;
- goto done;
- }
-
- /* continue the search with the next request */
- return LDB_SUCCESS;
+ return ret;
}
+ talloc_steal(new_req, controls);
- ret = LDB_SUCCESS;
-
-done:
- handle->state = LDB_ASYNC_DONE;
- return ret;
+ return ldb_next_request(ac->module, new_req);
}
-static int ps_wait(struct ldb_handle *handle, enum ldb_wait_type type)
+static int check_supported_paged(struct ldb_request *req,
+ struct ldb_reply *ares)
{
- int ret;
-
- if (!handle || !handle->private_data) {
- return LDB_ERR_OPERATIONS_ERROR;
- }
+ struct private_data *data;
- if (type == LDB_WAIT_ALL) {
- while (handle->state != LDB_ASYNC_DONE) {
- ret = ps_wait_once(handle);
- if (ret != LDB_SUCCESS) {
- return ret;
- }
- }
+ data = talloc_get_type(req->context, struct private_data);
- return handle->status;
+ if (!ares) {
+ return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR);
+ }
+ if (ares->error != LDB_SUCCESS) {
+ return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR);
}
- return ps_wait_once(handle);
-}
-static int check_supported_paged(struct ldb_context *ldb, void *context,
- struct ldb_reply *ares)
-{
- struct private_data *data;
- data = talloc_get_type(context,
- struct private_data);
- if (ares->type == LDB_REPLY_ENTRY) {
+ switch (ares->type) {
+ case LDB_REPLY_ENTRY:
if (ldb_msg_check_string_attribute(ares->message,
"supportedControl",
LDB_CONTROL_PAGED_RESULTS_OID)) {
data->paged_supported = true;
}
+ break;
+
+ case LDB_REPLY_REFERRAL:
+ /* ignore */
+ break;
+
+ case LDB_REPLY_DONE:
+ return ldb_request_done(req, LDB_SUCCESS);
}
+
+ talloc_free(ares);
return LDB_SUCCESS;
}
-
static int ps_init(struct ldb_module *module)
{
static const char *attrs[] = { "supportedControl", NULL };
struct private_data *data;
+ struct ldb_dn *base;
int ret;
struct ldb_request *req;
data = talloc(module, struct private_data);
if (data == NULL) {
- ldb_set_errstring(module->ldb, "Out of Memory");
- return LDB_ERR_OTHER;
+ ldb_oom(module->ldb);
+ return LDB_ERR_OPERATIONS_ERROR;
}
module->private_data = data;
data->paged_supported = false;
- req = talloc(module, struct ldb_request);
- if (req == NULL) {
- ldb_set_errstring(module->ldb, "Out of Memory");
+ base = ldb_dn_new(module, module->ldb, "");
+ if (base == NULL) {
+ ldb_oom(module->ldb);
return LDB_ERR_OPERATIONS_ERROR;
}
-
- req->operation = LDB_SEARCH;
- req->op.search.base = ldb_dn_new(req, module->ldb, "");
- req->op.search.scope = LDB_SCOPE_BASE;
-
- req->op.search.tree = ldb_parse_tree(req, "objectClass=*");
- if (req->op.search.tree == NULL) {
- ldb_set_errstring(module->ldb, "Unable to parse search expression");
- talloc_free(req);
- return LDB_ERR_OPERATIONS_ERROR;
+ ret = ldb_build_search_req(&req, module->ldb, module,
+ base, LDB_SCOPE_BASE,
+ "(objectClass=*)",
+ attrs, NULL,
+ data, check_supported_paged,
+ NULL);
+ if (ret != LDB_SUCCESS) {
+ return ret;
}
- req->op.search.attrs = attrs;
- req->controls = NULL;
- req->context = data;
- req->callback = check_supported_paged;
- ldb_set_timeout(module->ldb, req, 0); /* use default timeout */
-
ret = ldb_next_request(module, req);
-
if (ret == LDB_SUCCESS) {
ret = ldb_wait(req->handle, LDB_WAIT_ALL);
}
-
- talloc_free(req);
if (ret != LDB_SUCCESS) {
return ret;
}
+ talloc_free(base);
+ talloc_free(req);
+
return ldb_next_init(module);
}
_PUBLIC_ const struct ldb_module_ops ldb_paged_searches_module_ops = {
.name = "paged_searches",
.search = ps_search,
- .wait = ps_wait,
.init_context = ps_init
};
diff --git a/source4/lib/ldb/modules/rdn_name.c b/source4/lib/ldb/modules/rdn_name.c
index 65c044c0f4..62b8ce5112 100644
--- a/source4/lib/ldb/modules/rdn_name.c
+++ b/source4/lib/ldb/modules/rdn_name.c
@@ -2,7 +2,7 @@
ldb database library
Copyright (C) Andrew Bartlet 2005
- Copyright (C) Simo Sorce 2006
+ Copyright (C) Simo Sorce 2006-2008
** NOTE! The following LGPL license applies to the ldb
** library. This does NOT imply that all of Samba is released
@@ -38,6 +38,14 @@
#include "ldb_includes.h"
+struct rename_context {
+
+ struct ldb_module *module;
+ struct ldb_request *req;
+
+ struct ldb_reply *ares;
+};
+
static struct ldb_message_element *rdn_name_find_attribute(const struct ldb_message *msg, const char *name)
{
int i;
@@ -51,11 +59,38 @@ static struct ldb_message_element *rdn_name_find_attribute(const struct ldb_mess
return NULL;
}
+static int rdn_name_add_callback(struct ldb_request *req,
+ struct ldb_reply *ares)
+{
+ struct rename_context *ac;
+
+ ac = talloc_get_type(req->context, struct rename_context);
+
+ if (!ares) {
+ return ldb_module_done(ac->req, NULL, NULL,
+ LDB_ERR_OPERATIONS_ERROR);
+ }
+ if (ares->error != LDB_SUCCESS) {
+ return ldb_module_done(ac->req, ares->controls,
+ ares->response, ares->error);
+ }
+
+ if (ares->type != LDB_REPLY_DONE) {
+ return ldb_module_done(ac->req, NULL, NULL,
+ LDB_ERR_OPERATIONS_ERROR);
+ }
+
+ return ldb_module_done(ac->req, ares->controls,
+ ares->response, LDB_SUCCESS);
+}
+
static int rdn_name_add(struct ldb_module *module, struct ldb_request *req)
{
struct ldb_request *down_req;
+ struct rename_context *ac;
struct ldb_message *msg;
struct ldb_message_element *attribute;
+ const struct ldb_schema_attribute *a;
const char *rdn_name;
struct ldb_val rdn_val;
int i, ret;
@@ -67,21 +102,22 @@ static int rdn_name_add(struct ldb_module *module, struct ldb_request *req)
return ldb_next_request(module, req);
}
- down_req = talloc(req, struct ldb_request);
- if (down_req == NULL) {
+ ac = talloc_zero(req, struct rename_context);
+ if (ac == NULL) {
return LDB_ERR_OPERATIONS_ERROR;
}
- *down_req = *req;
+ ac->module = module;
+ ac->req = req;
- down_req->op.add.message = msg = ldb_msg_copy_shallow(down_req, req->op.add.message);
+ msg = ldb_msg_copy_shallow(req, req->op.add.message);
if (msg == NULL) {
return LDB_ERR_OPERATIONS_ERROR;
}
rdn_name = ldb_dn_get_rdn_name(msg->dn);
if (rdn_name == NULL) {
- talloc_free(down_req);
+ talloc_free(ac);
return LDB_ERR_OPERATIONS_ERROR;
}
@@ -93,7 +129,7 @@ static int rdn_name_add(struct ldb_module *module, struct ldb_request *req)
}
if (ldb_msg_add_value(msg, "name", &rdn_val, NULL) != 0) {
- talloc_free(down_req);
+ talloc_free(ac);
return LDB_ERR_OPERATIONS_ERROR;
}
@@ -101,14 +137,16 @@ static int rdn_name_add(struct ldb_module *module, struct ldb_request *req)
if (!attribute) {
if (ldb_msg_add_value(msg, rdn_name, &rdn_val, NULL) != 0) {
- talloc_free(down_req);
+ talloc_free(ac);
return LDB_ERR_OPERATIONS_ERROR;
}
} else {
- const struct ldb_schema_attribute *a = ldb_schema_attribute_by_name(module->ldb, rdn_name);
+ a = ldb_schema_attribute_by_name(module->ldb, rdn_name);
for (i = 0; i < attribute->num_values; i++) {
- if (a->syntax->comparison_fn(module->ldb, msg, &rdn_val, &attribute->values[i]) == 0) {
+ ret = a->syntax->comparison_fn(module->ldb, msg,
+ &rdn_val, &attribute->values[i]);
+ if (ret == 0) {
/* overwrite so it matches in case */
attribute->values[i] = rdn_val;
break;
@@ -118,218 +156,166 @@ static int rdn_name_add(struct ldb_module *module, struct ldb_request *req)
ldb_debug_set(module->ldb, LDB_DEBUG_FATAL,
"RDN mismatch on %s: %s (%s)",
ldb_dn_get_linearized(msg->dn), rdn_name, rdn_val.data);
- talloc_free(down_req);
+ talloc_free(ac);
/* Match AD's error here */
return LDB_ERR_INVALID_DN_SYNTAX;
}
}
- /* 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->handle = down_req->handle;
+ ret = ldb_build_add_req(&down_req, module->ldb, req,
+ msg,
+ req->controls,
+ ac, rdn_name_add_callback,
+ req);
+ if (ret != LDB_SUCCESS) {
+ return ret;
}
- return ret;
-}
-
-struct rename_context {
+ talloc_steal(down_req, msg);
- enum {RENAME_RENAME, RENAME_MODIFY} step;
- struct ldb_request *orig_req;
- struct ldb_request *down_req;
- struct ldb_request *mod_req;
-};
+ /* go on with the call chain */
+ return ldb_next_request(module, down_req);
+}
-static int rdn_name_rename(struct ldb_module *module, struct ldb_request *req)
+static int rdn_modify_callback(struct ldb_request *req, struct ldb_reply *ares)
{
- struct ldb_handle *h;
struct rename_context *ac;
- ldb_debug(module->ldb, LDB_DEBUG_TRACE, "rdn_name_rename\n");
+ ac = talloc_get_type(req->context, struct rename_context);
- /* do not manipulate our control entries */
- if (ldb_dn_is_special(req->op.rename.newdn)) {
- return ldb_next_request(module, req);
+ if (!ares) {
+ return ldb_module_done(ac->req, NULL, NULL,
+ LDB_ERR_OPERATIONS_ERROR);
}
-
- h = talloc_zero(req, struct ldb_handle);
- if (h == NULL) {
- return LDB_ERR_OPERATIONS_ERROR;
+ if (ares->error != LDB_SUCCESS) {
+ return ldb_module_done(ac->req, ares->controls,
+ ares->response, ares->error);
}
- h->module = module;
-
- ac = talloc_zero(h, struct rename_context);
- if (ac == NULL) {
- return LDB_ERR_OPERATIONS_ERROR;
+ /* the only supported reply right now is a LDB_REPLY_DONE */
+ if (ares->type != LDB_REPLY_DONE) {
+ return ldb_module_done(ac->req, NULL, NULL,
+ 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->handle = h;
-
- /* rename first, modify "name" if rename is ok */
- return ldb_next_request(module, ac->down_req);
+ /* send saved controls eventually */
+ return ldb_module_done(ac->req, ac->ares->controls,
+ ac->ares->response, LDB_SUCCESS);
}
-static int rdn_name_rename_do_mod(struct ldb_handle *h) {
-
+static int rdn_rename_callback(struct ldb_request *req, struct ldb_reply *ares)
+{
struct rename_context *ac;
+ struct ldb_request *mod_req;
const char *rdn_name;
struct ldb_val rdn_val;
struct ldb_message *msg;
+ int ret;
- ac = talloc_get_type(h->private_data, struct rename_context);
+ ac = talloc_get_type(req->context, struct rename_context);
- ac->mod_req = talloc_zero(ac, struct ldb_request);
+ if (!ares) {
+ goto error;
+ }
+ if (ares->error != LDB_SUCCESS) {
+ return ldb_module_done(ac->req, ares->controls,
+ ares->response, ares->error);
+ }
- ac->mod_req->operation = LDB_MODIFY;
- ac->mod_req->op.mod.message = msg = ldb_msg_new(ac->mod_req);
- if (msg == NULL) {
- return LDB_ERR_OPERATIONS_ERROR;
+ /* the only supported reply right now is a LDB_REPLY_DONE */
+ if (ares->type != LDB_REPLY_DONE) {
+ goto error;
}
- msg->dn = ldb_dn_copy(msg, ac->orig_req->op.rename.newdn);
+ /* save reply for caller */
+ ac->ares = talloc_steal(ac, ares);
+
+ msg = ldb_msg_new(ac);
+ if (msg == NULL) {
+ goto error;
+ }
+ msg->dn = ldb_dn_copy(msg, ac->req->op.rename.newdn);
if (msg->dn == NULL) {
- return LDB_ERR_OPERATIONS_ERROR;
+ goto error;
}
-
- rdn_name = ldb_dn_get_rdn_name(ac->orig_req->op.rename.newdn);
+ rdn_name = ldb_dn_get_rdn_name(ac->req->op.rename.newdn);
if (rdn_name == NULL) {
- return LDB_ERR_OPERATIONS_ERROR;
+ goto error;
}
- rdn_val = ldb_val_dup(msg, ldb_dn_get_rdn_val(ac->orig_req->op.rename.newdn));
+ rdn_val = ldb_val_dup(msg, ldb_dn_get_rdn_val(ac->req->op.rename.newdn));
if (ldb_msg_add_empty(msg, rdn_name, LDB_FLAG_MOD_REPLACE, NULL) != 0) {
- return LDB_ERR_OPERATIONS_ERROR;
+ goto error;
}
if (ldb_msg_add_value(msg, rdn_name, &rdn_val, NULL) != 0) {
- return LDB_ERR_OPERATIONS_ERROR;
+ goto error;
}
if (ldb_msg_add_empty(msg, "name", LDB_FLAG_MOD_REPLACE, NULL) != 0) {
- return LDB_ERR_OPERATIONS_ERROR;
+ goto error;
}
if (ldb_msg_add_value(msg, "name", &rdn_val, NULL) != 0) {
- return LDB_ERR_OPERATIONS_ERROR;
+ goto error;
}
- ldb_set_timeout_from_prev_req(h->module->ldb, ac->orig_req, ac->mod_req);
-
- ac->step = RENAME_MODIFY;
+ ret = ldb_build_mod_req(&mod_req, ac->module->ldb,
+ ac, msg, NULL,
+ ac, rdn_modify_callback,
+ req);
+ if (ret != LDB_SUCCESS) {
+ return ldb_module_done(ac->req, NULL, NULL, ret);
+ }
+ talloc_steal(mod_req, msg);
/* do the mod call */
- return ldb_request(h->module->ldb, ac->mod_req);
+ return ldb_request(ac->module->ldb, mod_req);
+
+error:
+ return ldb_module_done(ac->req, NULL, NULL,
+ LDB_ERR_OPERATIONS_ERROR);
}
-static int rdn_name_wait_once(struct ldb_handle *handle)
+static int rdn_name_rename(struct ldb_module *module, struct ldb_request *req)
{
struct rename_context *ac;
+ struct ldb_request *down_req;
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_context);
-
- switch(ac->step) {
- case RENAME_RENAME:
- ret = ldb_wait(ac->down_req->handle, LDB_WAIT_NONE);
- if (ret != LDB_SUCCESS) {
- handle->status = ret;
- goto done;
- }
- if (ac->down_req->handle->status != LDB_SUCCESS) {
- handle->status = ac->down_req->handle->status;
- goto done;
- }
-
- if (ac->down_req->handle->state != LDB_ASYNC_DONE) {
- return LDB_SUCCESS;
- }
-
- /* rename operation done */
- return rdn_name_rename_do_mod(handle);
-
- case RENAME_MODIFY:
- ret = ldb_wait(ac->mod_req->handle, LDB_WAIT_NONE);
- if (ret != LDB_SUCCESS) {
- handle->status = ret;
- goto done;
- }
- if (ac->mod_req->handle->status != LDB_SUCCESS) {
- handle->status = ac->mod_req->handle->status;
- goto done;
- }
-
- if (ac->mod_req->handle->state != LDB_ASYNC_DONE) {
- return LDB_SUCCESS;
- }
-
- break;
+ ldb_debug(module->ldb, LDB_DEBUG_TRACE, "rdn_name_rename\n");
- default:
- ret = LDB_ERR_OPERATIONS_ERROR;
- goto done;
+ /* do not manipulate our control entries */
+ if (ldb_dn_is_special(req->op.rename.newdn)) {
+ return ldb_next_request(module, req);
}
- ret = LDB_SUCCESS;
-
-done:
- handle->state = LDB_ASYNC_DONE;
- return ret;
-}
-
-static int rdn_name_wait(struct ldb_handle *handle, enum ldb_wait_type type)
-{
- int ret;
-
- if (!handle || !handle->private_data) {
+ ac = talloc_zero(req, struct rename_context);
+ if (ac == NULL) {
return LDB_ERR_OPERATIONS_ERROR;
}
- if (type == LDB_WAIT_ALL) {
- while (handle->state != LDB_ASYNC_DONE) {
- ret = rdn_name_wait_once(handle);
- if (ret != LDB_SUCCESS) {
- return ret;
- }
- }
+ ac->module = module;
+ ac->req = req;
- return handle->status;
+ ret = ldb_build_rename_req(&down_req,
+ module->ldb,
+ ac,
+ req->op.rename.olddn,
+ req->op.rename.newdn,
+ req->controls,
+ ac,
+ rdn_rename_callback,
+ req);
+
+ if (ret != LDB_SUCCESS) {
+ return LDB_ERR_OPERATIONS_ERROR;
}
- return rdn_name_wait_once(handle);
+ /* rename first, modify "name" if rename is ok */
+ return ldb_next_request(module, down_req);
}
const struct ldb_module_ops ldb_rdn_name_module_ops = {
.name = "rdn_name",
.add = rdn_name_add,
.rename = rdn_name_rename,
- .wait = rdn_name_wait
};
diff --git a/source4/lib/ldb/modules/sort.c b/source4/lib/ldb/modules/sort.c
index 746befa559..64d60f370c 100644
--- a/source4/lib/ldb/modules/sort.c
+++ b/source4/lib/ldb/modules/sort.c
@@ -1,7 +1,7 @@
/*
ldb database library
- Copyright (C) Simo Sorce 2005
+ Copyright (C) Simo Sorce 2005-2008
** NOTE! The following LGPL license applies to the ldb
** library. This does NOT imply that all of Samba is released
@@ -43,8 +43,6 @@ struct opaque {
struct sort_context {
struct ldb_module *module;
- void *up_context;
- int (*up_callback)(struct ldb_context *, void *, struct ldb_reply *);
char *attributeName;
char *orderingRule;
@@ -53,7 +51,6 @@ struct sort_context {
struct ldb_request *req;
struct ldb_message **msgs;
char **referrals;
- struct ldb_control **controls;
int num_msgs;
int num_refs;
@@ -61,40 +58,6 @@ struct sort_context {
int sort_result;
};
-static struct ldb_handle *init_handle(void *mem_ctx, struct ldb_module *module,
- void *context,
- int (*callback)(struct ldb_context *, void *, struct ldb_reply *))
-{
- struct sort_context *ac;
- struct ldb_handle *h;
-
- h = talloc_zero(mem_ctx, struct ldb_handle);
- if (h == NULL) {
- ldb_set_errstring(module->ldb, "Out of Memory");
- return NULL;
- }
-
- h->module = module;
-
- ac = talloc_zero(h, struct sort_context);
- if (ac == NULL) {
- ldb_set_errstring(module->ldb, "Out of Memory");
- talloc_free(h);
- return NULL;
- }
-
- h->private_data = (void *)ac;
-
- h->state = LDB_ASYNC_INIT;
- h->status = LDB_SUCCESS;
-
- ac->module = module;
- ac->up_context = context;
- ac->up_callback = callback;
-
- return h;
-}
-
static int build_response(void *mem_ctx, struct ldb_control ***ctrls, int result, const char *desc)
{
struct ldb_control **controls;
@@ -142,7 +105,7 @@ static int sort_compare(struct ldb_message **msg1, struct ldb_message **msg2, vo
struct sort_context *ac = talloc_get_type(opaque, struct sort_context);
struct ldb_message_element *el1, *el2;
- if (ac->sort_result != 0) {
+ if (!ac || ac->sort_result != 0) {
/* an error occurred previously,
* let's exit the sorting by returning always 0 */
return 0;
@@ -154,7 +117,7 @@ static int sort_compare(struct ldb_message **msg1, struct ldb_message **msg2, vo
if (!el1 || !el2) {
/* the attribute was not found return and
* set an error */
- ac->sort_result = 53;
+ ac->sort_result = LDB_ERR_UNWILLING_TO_PERFORM;
return 0;
}
@@ -164,51 +127,111 @@ static int sort_compare(struct ldb_message **msg1, struct ldb_message **msg2, vo
return ac->a->syntax->comparison_fn(ac->module->ldb, ac, &el1->values[0], &el2->values[0]);
}
-static int server_sort_search_callback(struct ldb_context *ldb, void *context, struct ldb_reply *ares)
+static int server_sort_results(struct sort_context *ac)
{
- struct sort_context *ac = NULL;
-
- if (!context || !ares) {
- ldb_set_errstring(ldb, "NULL Context or Result in callback");
- goto error;
- }
+ struct ldb_reply *ares;
+ int i, ret;
+
+ ac->a = ldb_schema_attribute_by_name(ac->module->ldb, ac->attributeName);
+ ac->sort_result = 0;
+
+ ldb_qsort(ac->msgs, ac->num_msgs,
+ sizeof(struct ldb_message *),
+ ac, (ldb_qsort_cmp_fn_t)sort_compare);
+
+ if (ac->sort_result != LDB_SUCCESS) {
+ return ac->sort_result;
+ }
+
+ for (i = 0; i < ac->num_msgs; i++) {
+ ares = talloc_zero(ac, struct ldb_reply);
+ if (!ares) {
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
+ ares->type = LDB_REPLY_ENTRY;
+ ares->message = talloc_move(ares, &ac->msgs[i]);
+
+ ret = ldb_module_send_entry(ac->req, ares->message);
+ if (ret != LDB_SUCCESS) {
+ return ret;
+ }
+ }
+
+ for (i = 0; i < ac->num_refs; i++) {
+ ares = talloc_zero(ac, struct ldb_reply);
+ if (!ares) {
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
+ ares->type = LDB_REPLY_REFERRAL;
+ ares->referral = talloc_move(ares, &ac->referrals[i]);
+
+ ret = ldb_module_send_referral(ac->req, ares->referral);
+ if (ret != LDB_SUCCESS) {
+ return ret;
+ }
+ }
+
+ return LDB_SUCCESS;
+}
+
+static int server_sort_search_callback(struct ldb_request *req, struct ldb_reply *ares)
+{
+ struct sort_context *ac;
+ int ret;
- ac = talloc_get_type(context, struct sort_context);
+ ac = talloc_get_type(req->context, struct sort_context);
- if (ares->type == LDB_REPLY_ENTRY) {
+ if (!ares) {
+ return ldb_module_done(ac->req, NULL, NULL,
+ LDB_ERR_OPERATIONS_ERROR);
+ }
+ if (ares->error != LDB_SUCCESS) {
+ return ldb_module_done(ac->req, ares->controls,
+ ares->response, ares->error);
+ }
+
+ switch (ares->type) {
+ case LDB_REPLY_ENTRY:
ac->msgs = talloc_realloc(ac, ac->msgs, struct ldb_message *, ac->num_msgs + 2);
if (! ac->msgs) {
- goto error;
+ talloc_free(ares);
+ ldb_oom(ac->module->ldb);
+ return ldb_module_done(ac->req, NULL, NULL,
+ LDB_ERR_OPERATIONS_ERROR);
}
- ac->msgs[ac->num_msgs + 1] = NULL;
-
- ac->msgs[ac->num_msgs] = talloc_move(ac->msgs, &ares->message);
+ ac->msgs[ac->num_msgs] = talloc_steal(ac->msgs, ares->message);
ac->num_msgs++;
- }
+ ac->msgs[ac->num_msgs] = NULL;
- if (ares->type == LDB_REPLY_REFERRAL) {
+ break;
+
+ case LDB_REPLY_REFERRAL:
ac->referrals = talloc_realloc(ac, ac->referrals, char *, ac->num_refs + 2);
if (! ac->referrals) {
- goto error;
+ talloc_free(ares);
+ ldb_oom(ac->module->ldb);
+ return ldb_module_done(ac->req, NULL, NULL,
+ LDB_ERR_OPERATIONS_ERROR);
}
- ac->referrals[ac->num_refs + 1] = NULL;
- ac->referrals[ac->num_refs] = talloc_move(ac->referrals, &ares->referral);
-
+ ac->referrals[ac->num_refs] = talloc_steal(ac->referrals, ares->referral);
ac->num_refs++;
- }
+ ac->referrals[ac->num_refs] = NULL;
- if (ares->type == LDB_REPLY_DONE) {
- ac->controls = talloc_move(ac, &ares->controls);
+ break;
+
+ case LDB_REPLY_DONE:
+
+ ret = server_sort_results(ac);
+ return ldb_module_done(ac->req, ares->controls,
+ ares->response, ret);
}
talloc_free(ares);
return LDB_SUCCESS;
-
-error:
- talloc_free(ares);
- return LDB_ERR_OPERATIONS_ERROR;
}
static int server_sort_search(struct ldb_module *module, struct ldb_request *req)
@@ -216,8 +239,9 @@ static int server_sort_search(struct ldb_module *module, struct ldb_request *req
struct ldb_control *control;
struct ldb_server_sort_control **sort_ctrls;
struct ldb_control **saved_controls;
+ struct ldb_control **controls;
+ struct ldb_request *down_req;
struct sort_context *ac;
- struct ldb_handle *h;
int ret;
/* check if there's a paged request control */
@@ -227,19 +251,14 @@ static int server_sort_search(struct ldb_module *module, struct ldb_request *req
return ldb_next_request(module, req);
}
- req->handle = NULL;
-
- if (!req->callback || !req->context) {
- ldb_set_errstring(module->ldb,
- "Async interface called with NULL callback function or NULL context");
- return LDB_ERR_OPERATIONS_ERROR;
- }
-
- h = init_handle(req, module, req->context, req->callback);
- if (!h) {
+ ac = talloc_zero(req, struct sort_context);
+ if (ac == NULL) {
+ ldb_oom(module->ldb);
return LDB_ERR_OPERATIONS_ERROR;
}
- ac = talloc_get_type(h->private_data, struct sort_context);
+
+ ac->module = module;
+ ac->req = req;
sort_ctrls = talloc_get_type(control->data, struct ldb_server_sort_control *);
if (!sort_ctrls) {
@@ -251,26 +270,20 @@ static int server_sort_search(struct ldb_module *module, struct ldb_request *req
if (sort_ctrls[1] != NULL) {
if (control->critical) {
- struct ldb_reply *ares;
-
- ares = talloc_zero(req, struct ldb_reply);
- if (!ares)
- return LDB_ERR_OPERATIONS_ERROR;
- /* 53 = unwilling to perform */
- ares->type = LDB_REPLY_DONE;
- if ((ret = build_response(ares, &ares->controls, 53, "sort control is not complete yet")) != LDB_SUCCESS) {
- return ret;
+ /* callback immediately */
+ ret = build_response(req, &controls,
+ LDB_ERR_UNWILLING_TO_PERFORM,
+ "sort control is not complete yet");
+ if (ret != LDB_SUCCESS) {
+ return ldb_module_done(req, NULL, NULL,
+ LDB_ERR_OPERATIONS_ERROR);
}
- h->status = LDB_ERR_UNSUPPORTED_CRITICAL_EXTENSION;
- h->state = LDB_ASYNC_DONE;
- ret = ac->up_callback(module->ldb, ac->up_context, ares);
-
- return ret;
+ return ldb_module_done(req, controls, NULL, ret);
} else {
/* just pass the call down and don't do any sorting */
- ldb_next_request(module, req);
+ return ldb_next_request(module, req);
}
}
@@ -278,181 +291,45 @@ static int server_sort_search(struct ldb_module *module, struct ldb_request *req
ac->orderingRule = sort_ctrls[0]->orderingRule;
ac->reverse = sort_ctrls[0]->reverse;
- ac->req = talloc(req, struct ldb_request);
- if (!ac->req)
+ ret = ldb_build_search_req_ex(&down_req, module->ldb, ac,
+ req->op.search.base,
+ req->op.search.scope,
+ req->op.search.tree,
+ req->op.search.attrs,
+ req->controls,
+ ac,
+ server_sort_search_callback,
+ req);
+ if (ret != LDB_SUCCESS) {
return LDB_ERR_OPERATIONS_ERROR;
-
- ac->req->operation = req->operation;
- ac->req->op.search.base = req->op.search.base;
- ac->req->op.search.scope = req->op.search.scope;
- ac->req->op.search.tree = req->op.search.tree;
- ac->req->op.search.attrs = req->op.search.attrs;
- ac->req->controls = req->controls;
+ }
/* save it locally and remove it from the list */
/* we do not need to replace them later as we
* are keeping the original req intact */
- if (!save_controls(control, ac->req, &saved_controls)) {
+ if (!save_controls(control, down_req, &saved_controls)) {
return LDB_ERR_OPERATIONS_ERROR;
}
- ac->req->context = ac;
- ac->req->callback = server_sort_search_callback;
- ldb_set_timeout_from_prev_req(module->ldb, req, ac->req);
-
- req->handle = h;
-
- return ldb_next_request(module, ac->req);
-}
-
-static int server_sort_results(struct ldb_handle *handle)
-{
- struct sort_context *ac;
- struct ldb_reply *ares;
- int i, ret;
-
- ac = talloc_get_type(handle->private_data, struct sort_context);
-
- ac->a = ldb_schema_attribute_by_name(ac->module->ldb, ac->attributeName);
- ac->sort_result = 0;
-
- ldb_qsort(ac->msgs, ac->num_msgs,
- sizeof(struct ldb_message *),
- ac, (ldb_qsort_cmp_fn_t)sort_compare);
-
- for (i = 0; i < ac->num_msgs; i++) {
- ares = talloc_zero(ac, struct ldb_reply);
- if (!ares) {
- handle->status = LDB_ERR_OPERATIONS_ERROR;
- return handle->status;
- }
-
- ares->type = LDB_REPLY_ENTRY;
- ares->message = talloc_move(ares, &ac->msgs[i]);
-
- handle->status = ac->up_callback(ac->module->ldb, ac->up_context, ares);
- if (handle->status != LDB_SUCCESS) {
- return handle->status;
- }
- }
-
- for (i = 0; i < ac->num_refs; i++) {
- ares = talloc_zero(ac, struct ldb_reply);
- if (!ares) {
- handle->status = LDB_ERR_OPERATIONS_ERROR;
- return handle->status;
- }
-
- ares->type = LDB_REPLY_REFERRAL;
- ares->referral = talloc_move(ares, &ac->referrals[i]);
-
- handle->status = ac->up_callback(ac->module->ldb, ac->up_context, ares);
- if (handle->status != LDB_SUCCESS) {
- return handle->status;
- }
- }
-
- ares = talloc_zero(ac, struct ldb_reply);
- if (!ares) {
- handle->status = LDB_ERR_OPERATIONS_ERROR;
- return handle->status;
- }
-
- ares->type = LDB_REPLY_DONE;
- ares->controls = talloc_move(ares, &ac->controls);
-
- handle->status = ac->up_callback(ac->module->ldb, ac->up_context, ares);
- if (handle->status != LDB_SUCCESS) {
- return handle->status;
- }
-
- if ((ret = build_response(ac, &ac->controls, ac->sort_result, "sort control is not complete yet")) != LDB_SUCCESS) {
- return ret;
- }
-
- return LDB_SUCCESS;
-}
-
-static int server_sort_wait_once(struct ldb_handle *handle)
-{
- struct sort_context *ac;
- int ret;
-
- if (!handle || !handle->private_data) {
- return LDB_ERR_OPERATIONS_ERROR;
- }
-
- ac = talloc_get_type(handle->private_data, struct sort_context);
-
- ret = ldb_wait(ac->req->handle, LDB_WAIT_NONE);
-
- if (ret != LDB_SUCCESS) {
- handle->status = ret;
- return ret;
- }
-
- handle->state = ac->req->handle->state;
- handle->status = ac->req->handle->status;
-
- if (handle->status != LDB_SUCCESS) {
- return handle->status;
- }
-
- if (handle->state == LDB_ASYNC_DONE) {
- ret = server_sort_results(handle);
- }
-
- return ret;
-}
-
-static int server_sort_wait(struct ldb_handle *handle, enum ldb_wait_type type)
-{
- int ret;
-
- if (!handle || !handle->private_data) {
- return LDB_ERR_OPERATIONS_ERROR;
- }
-
- if (type == LDB_WAIT_ALL) {
- while (handle->state != LDB_ASYNC_DONE) {
- ret = server_sort_wait_once(handle);
- if (ret != LDB_SUCCESS) {
- return ret;
- }
- }
-
- return handle->status;
- }
-
- return server_sort_wait_once(handle);
+ return ldb_next_request(module, down_req);
}
static int server_sort_init(struct ldb_module *module)
{
- struct ldb_request *req;
int ret;
- req = talloc(module, struct ldb_request);
- if (req == NULL) {
- return LDB_ERR_OPERATIONS_ERROR;
- }
-
- req->operation = LDB_REQ_REGISTER_CONTROL;
- req->op.reg_control.oid = LDB_CONTROL_SERVER_SORT_OID;
- req->controls = NULL;
-
- ret = ldb_request(module->ldb, req);
+ ret = ldb_mod_register_control(module, LDB_CONTROL_SERVER_SORT_OID);
if (ret != LDB_SUCCESS) {
- ldb_debug(module->ldb, LDB_DEBUG_WARNING, "server_sort: Unable to register control with rootdse!\n");
+ ldb_debug(module->ldb, LDB_DEBUG_WARNING,
+ "server_sort:"
+ "Unable to register control with rootdse!\n");
}
- talloc_free(req);
return ldb_next_init(module);
}
const struct ldb_module_ops ldb_server_sort_module_ops = {
.name = "server_sort",
.search = server_sort_search,
- .wait = server_sort_wait,
.init_context = server_sort_init
};