return MDB_SUCCESS;
}
+/* See if ID is a child of any of the scopes,
+ * return MDB_KEYEXIST if so.
+ */
+int
+mdb_idscopechk(
+ Operation *op,
+ IdScopes *isc )
+{
+ struct mdb_info *mdb = (struct mdb_info *) op->o_bd->be_private;
+ MDB_val key, data;
+ ID id, prev;
+ char *ptr;
+ int rc = 0;
+ unsigned int x;
+
+ key.mv_size = sizeof(ID);
+
+ if ( !isc->mc ) {
+ rc = mdb_cursor_open( isc->mt, mdb->mi_dn2id, &isc->mc );
+ if ( rc ) return rc;
+ }
+
+ id = isc->id;
+
+ while (id) {
+ if ( !rc ) {
+ key.mv_data = &id;
+ rc = mdb_cursor_get( isc->mc, &key, &data, MDB_SET );
+ if ( rc )
+ return rc;
+ }
+
+ ptr = data.mv_data;
+ ptr += data.mv_size - sizeof(ID);
+ prev = id;
+ memcpy( &id, ptr, sizeof(ID) );
+ /* If we didn't advance, some parent is missing */
+ if ( id == prev )
+ return MDB_NOTFOUND;
+
+ x = mdb_id2l_search( isc->scopes, id );
+ if ( x <= isc->scopes[0].mid && isc->scopes[x].mid == id )
+ return MDB_KEYEXIST;
+ }
+ return MDB_SUCCESS;
+}
+
int
mdb_dn2id_walk(
Operation *op,
Operation *op,
SlapReply *rs,
Entry *e,
- MDB_txn *txn,
+ IdScopes *isc,
MDB_cursor *mci,
ID *ids,
- ID2L scopes,
ID *stack );
static int parse_paged_cookie( Operation *op, SlapReply *rs );
Operation *op,
SlapReply *rs,
ID e_id,
- MDB_txn *txn,
+ IdScopes *isc,
MDB_cursor *mci,
- ID2L scopes,
ID *stack )
{
ID *aliases, *curscop, *visited, *newsubs, *oldsubs, *tmp;
/* Find all aliases in database */
MDB_IDL_ZERO( aliases );
- rs->sr_err = mdb_filter_candidates( op, txn, &af, aliases,
+ rs->sr_err = mdb_filter_candidates( op, isc->mt, &af, aliases,
curscop, visited );
if (rs->sr_err != LDAP_SUCCESS || MDB_IDL_IS_ZERO( aliases )) {
return rs->sr_err;
/* Set curscop to only the aliases in the current scope. Start with
* all the aliases, then get the intersection with the scope.
*/
- rs->sr_err = mdb_idscope( op, txn, e_id, aliases, curscop );
+ rs->sr_err = mdb_idscope( op, isc->mt, e_id, aliases, curscop );
/* Dereference all of the aliases in the current scope. */
cursora = 0;
/* Actually dereference the alias */
MDB_IDL_ZERO(tmp);
- a = deref_base( op, rs, a, &matched, txn,
+ a = deref_base( op, rs, a, &matched, isc->mt,
tmp, visited );
if (a) {
/* If the target was not already in our current scopes,
ID2 mid;
mid.mid = a->e_id;
mid.mval.mv_data = NULL;
- if (mdb_id2l_insert(scopes, &mid) == 0) {
+ if (op->ors_scope == LDAP_SCOPE_SUBTREE) {
+ isc->id = a->e_id;
+ /* if ID is a child of any of our current scopes,
+ * ignore it, it's already included.
+ */
+ if (mdb_idscopechk(op, isc))
+ goto skip;
+ }
+ if (mdb_id2l_insert(isc->scopes, &mid) == 0) {
mdb_idl_insert(newsubs, a->e_id);
}
- mdb_entry_return( op, a );
+skip: mdb_entry_return( op, a );
} else if (matched) {
/* Alias could not be dereferenced, or it deref'd to
scopes[1].mid = base->e_id;
scopes[1].mval.mv_data = NULL;
rs->sr_err = search_candidates( op, rs, base,
- ltid, mci, candidates, scopes, stack );
+ &isc, mci, candidates, stack );
ncand = MDB_IDL_N( candidates );
if ( !base->e_id || ncand == NOID ) {
/* grab entry count from id2entry stat
Operation *op,
SlapReply *rs,
Entry *e,
- MDB_txn *txn,
+ IdScopes *isc,
MDB_cursor *mci,
ID *ids,
- ID2L scopes,
ID *stack )
{
struct mdb_info *mdb = (struct mdb_info *) op->o_bd->be_private;
}
if( op->ors_deref & LDAP_DEREF_SEARCHING ) {
- rc = search_aliases( op, rs, e->e_id, txn, mci, scopes, stack );
+ rc = search_aliases( op, rs, e->e_id, isc, mci, stack );
} else {
rc = LDAP_SUCCESS;
}
if ( rc == LDAP_SUCCESS ) {
- rc = mdb_filter_candidates( op, txn, f, ids,
+ rc = mdb_filter_candidates( op, isc->mt, f, ids,
stack, stack+MDB_IDL_UM_SIZE );
}