/* $OpenLDAP$ */
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
*
- * Copyright 2000-2013 The OpenLDAP Foundation.
+ * Copyright 2000-2014 The OpenLDAP Foundation.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
*/
mdb_entry_return( op, matched );
rs->sr_text = NULL;
+ rs->sr_err = 0;
}
}
/* If this is a OneLevel search, we're done; oldsubs only had one
mdb_search( Operation *op, SlapReply *rs )
{
struct mdb_info *mdb = (struct mdb_info *) op->o_bd->be_private;
- ID id, cursor, nsubs, ncand;
+ ID id, cursor, nsubs, ncand, cscope;
ID lastid = NOID;
ID candidates[MDB_IDL_UM_SIZE];
+ ID iscopes[MDB_IDL_DB_SIZE];
ID2 *scopes;
Entry *e = NULL, *base = NULL;
Entry *matched = NULL;
isc.mt = ltid;
isc.mc = mcd;
isc.scopes = scopes;
+ isc.oscope = op->ors_scope;
if ( op->ors_deref & LDAP_DEREF_FINDING ) {
MDB_IDL_ZERO(candidates);
/* select candidates */
if ( op->oq_search.rs_scope == LDAP_SCOPE_BASE ) {
rs->sr_err = base_candidate( op->o_bd, base, candidates );
+ scopes[0].mid = 0;
ncand = 1;
} else {
if ( op->ors_scope == LDAP_SCOPE_ONELEVEL ) {
if ( nsubs < ncand ) {
int rc;
/* Do scope-based search */
+
+ /* if any alias scopes were set, save them */
+ if (scopes[0].mid > 1) {
+ cursor = 1;
+ for (cscope = 1; cscope <= scopes[0].mid; cscope++) {
+ /* Ignore the original base */
+ if (scopes[cscope].mid == base->e_id)
+ continue;
+ iscopes[cursor++] = scopes[cscope].mid;
+ }
+ iscopes[0] = scopes[0].mid - 1;
+ } else {
+ iscopes[0] = 0;
+ }
+
isc.id = base->e_id;
isc.numrdns = 0;
rc = mdb_dn2id_walk( op, &isc );
id = NOID;
else
id = isc.id;
+ cscope = 0;
} else {
id = mdb_idl_first( candidates, &cursor );
}
int i;
/* child of base, just append RDNs to base->e_name */
- if ( nsubs < ncand || isc.nscope == 1 ) {
+ if ( nsubs < ncand || isc.scopes[isc.nscope].mid == base->e_id ) {
pdn = base->e_name;
pndn = base->e_nname;
} else {
break;
default: /* entry not sent */
break;
+ case LDAP_BUSY:
+ send_ldap_result( op, rs );
+ goto done;
case LDAP_UNAVAILABLE:
case LDAP_SIZELIMIT_EXCEEDED:
if ( rs->sr_err == LDAP_SIZELIMIT_EXCEEDED ) {
if ( nsubs < ncand ) {
int rc = mdb_dn2id_walk( op, &isc );
- if (rc)
+ if (rc) {
id = NOID;
- else
+ /* We got to the end of a subtree. If there are any
+ * alias scopes left, search them too.
+ */
+ while (iscopes[0] && cscope < iscopes[0]) {
+ cscope++;
+ isc.id = iscopes[cscope];
+ if ( base )
+ mdb_entry_return( op, base );
+ rs->sr_err = mdb_id2entry(op, mci, isc.id, &base);
+ if ( !rs->sr_err ) {
+ mdb_id2name( op, ltid, &isc.mc, isc.id, &base->e_name, &base->e_nname );
+ isc.numrdns = 0;
+ if (isc.oscope == LDAP_SCOPE_ONELEVEL)
+ isc.oscope = LDAP_SCOPE_BASE;
+ rc = mdb_dn2id_walk( op, &isc );
+ if ( !rc ) {
+ id = isc.id;
+ break;
+ }
+ }
+ }
+ } else
id = isc.id;
} else {
id = mdb_idl_next( candidates, &cursor );
if ( moi == &opinfo ) {
mdb_txn_reset( moi->moi_txn );
LDAP_SLIST_REMOVE( &op->o_extra, &moi->moi_oe, OpExtra, oe_next );
+ } else {
+ moi->moi_ref--;
}
if( rs->sr_v2ref ) {
ber_bvarray_free( rs->sr_v2ref );