X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=servers%2Fslapd%2Fback-mdb%2Fdn2id.c;h=43b82ce076df4a317d8979e9ffcc2f06e99df637;hb=6f5f113612f9175e589d1509005b1af78b2b5f68;hp=af003648af42abf76826590916927d34d9d82dbc;hpb=46d6f994cd77ecd0764c8c616dfec99551664d9d;p=openldap
diff --git a/servers/slapd/back-mdb/dn2id.c b/servers/slapd/back-mdb/dn2id.c
index af003648af..43b82ce076 100644
--- a/servers/slapd/back-mdb/dn2id.c
+++ b/servers/slapd/back-mdb/dn2id.c
@@ -2,7 +2,7 @@
/* $OpenLDAP$ */
/* This work is part of OpenLDAP Software .
*
- * Copyright 2000-2013 The OpenLDAP Foundation.
+ * Copyright 2000-2015 The OpenLDAP Foundation.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -86,6 +86,7 @@ mdb_dn2id_add(
MDB_cursor *mcd,
ID pid,
ID nsubs,
+ int upsub,
Entry *e )
{
struct mdb_info *mdb = (struct mdb_info *) op->o_bd->be_private;
@@ -156,7 +157,7 @@ mdb_dn2id_add(
op->o_tmpfree( d, op->o_tmpmemctx );
/* Add our subtree count to all superiors */
- if ( rc == 0 && nsubs && pid ) {
+ if ( rc == 0 && upsub && pid ) {
ID subs;
nid = pid;
do {
@@ -164,7 +165,7 @@ mdb_dn2id_add(
rc = mdb_cursor_get( mcp, &key, &data, MDB_SET );
if ( !rc ) {
char *p2;
- ptr = data.mv_data + data.mv_size - sizeof( ID );
+ ptr = (char *)data.mv_data + data.mv_size - sizeof( ID );
memcpy( &nid, ptr, sizeof( ID ));
/* Get parent's node under grandparent */
d = data.mv_data;
@@ -177,7 +178,7 @@ mdb_dn2id_add(
op->o_tmpfree( p2, op->o_tmpmemctx );
if ( !rc ) {
/* Get parent's subtree count */
- ptr = data.mv_data + data.mv_size - sizeof( ID );
+ ptr = (char *)data.mv_data + data.mv_size - sizeof( ID );
memcpy( &subs, ptr, sizeof( ID ));
subs += nsubs;
p2 = op->o_tmpalloc( data.mv_size, op->o_tmpmemctx );
@@ -245,7 +246,7 @@ mdb_dn2id_delete(
char *p2;
diskNode *d;
int rlen;
- ptr = data.mv_data + data.mv_size - sizeof( ID );
+ ptr = (char *)data.mv_data + data.mv_size - sizeof( ID );
memcpy( &nid, ptr, sizeof( ID ));
/* Get parent's node under grandparent */
d = data.mv_data;
@@ -258,7 +259,7 @@ mdb_dn2id_delete(
op->o_tmpfree( p2, op->o_tmpmemctx );
if ( !rc ) {
/* Get parent's subtree count */
- ptr = data.mv_data + data.mv_size - sizeof( ID );
+ ptr = (char *)data.mv_data + data.mv_size - sizeof( ID );
memcpy( &subs, ptr, sizeof( ID ));
subs -= nsubs;
p2 = op->o_tmpalloc( data.mv_size, op->o_tmpmemctx );
@@ -345,7 +346,7 @@ mdb_dn2id(
cursor = mc;
} else {
rc = mdb_cursor_open( txn, dbi, &cursor );
- if ( rc ) return rc;
+ if ( rc ) goto done;
}
for (;;) {
@@ -398,7 +399,7 @@ mdb_dn2id(
*id = nid;
/* return subtree count if requested */
if ( !rc && nsubs ) {
- ptr = data.mv_data + data.mv_size - sizeof(ID);
+ ptr = (char *)data.mv_data + data.mv_size - sizeof(ID);
memcpy( nsubs, ptr, sizeof( ID ));
}
if ( !mc )
@@ -469,7 +470,7 @@ mdb_dn2sups(
key.mv_size = sizeof(ID);
rc = mdb_cursor_open( txn, dbi, &cursor );
- if ( rc ) return rc;
+ if ( rc ) goto done;
for (;;) {
key.mv_data = &pid;
@@ -629,9 +630,9 @@ mdb_idscope(
MDB_dbi dbi = mdb->mi_dn2id;
MDB_val key, data;
MDB_cursor *cursor;
- ID ida, id, cid, ci0, idc = 0;
+ ID ida, id, cid = 0, ci0 = 0, idc = 0;
char *ptr;
- int rc;
+ int rc, copy;
key.mv_size = sizeof(ID);
@@ -649,43 +650,47 @@ mdb_idscope(
}
while (ida != NOID) {
+ copy = 1;
id = ida;
while (id) {
key.mv_data = &id;
rc = mdb_cursor_get( cursor, &key, &data, MDB_SET );
if ( rc ) {
- /* not found, move on to next */
- if (idc) {
- if (ci0 != cid)
- ids[ci0] = ids[cid];
- ci0++;
- }
+ /* not found, drop this from ids */
+ copy = 0;
break;
}
ptr = data.mv_data;
ptr += data.mv_size - sizeof(ID);
memcpy( &id, ptr, sizeof(ID) );
if ( id == base ) {
+ if ( res[0] >= MDB_IDL_DB_SIZE-1 ) {
+ /* too many aliases in scope. Fallback to range */
+ MDB_IDL_RANGE( res, MDB_IDL_FIRST( ids ), MDB_IDL_LAST( ids ));
+ goto leave;
+ }
res[0]++;
res[res[0]] = ida;
- if (idc)
- idc--;
+ copy = 0;
break;
- } else {
- if (idc) {
- if (ci0 != cid)
- ids[ci0] = ids[cid];
- ci0++;
- }
}
if ( op->ors_scope == LDAP_SCOPE_ONELEVEL )
break;
}
+ if (idc) {
+ if (copy) {
+ if (ci0 != cid)
+ ids[ci0] = ids[cid];
+ ci0++;
+ } else
+ idc--;
+ }
ida = mdb_idl_next( ids, &cid );
}
if (!MDB_IDL_IS_RANGE( ids ))
ids[0] = idc;
+leave:
mdb_cursor_close( cursor );
return rc;
}
@@ -700,7 +705,7 @@ mdb_idscopes(
struct mdb_info *mdb = (struct mdb_info *) op->o_bd->be_private;
MDB_dbi dbi = mdb->mi_dn2id;
MDB_val key, data;
- ID id;
+ ID id, prev;
ID2 id2;
char *ptr;
int rc = 0;
@@ -716,6 +721,15 @@ mdb_idscopes(
}
id = isc->id;
+
+ /* Catch entries from deref'd aliases */
+ x = mdb_id2l_search( isc->scopes, id );
+ if ( x <= isc->scopes[0].mid && isc->scopes[x].mid == id ) {
+ isc->nscope = x;
+ return MDB_SUCCESS;
+ }
+
+ isc->sctmp[0].mid = 0;
while (id) {
if ( !rc ) {
key.mv_data = &id;
@@ -735,16 +749,32 @@ mdb_idscopes(
isc->numrdns++;
if (!rc && id != isc->id) {
+ /* remember our chain of parents */
id2.mid = id;
id2.mval = data;
- mdb_id2l_insert( isc->scopes, &id2 );
+ mdb_id2l_insert( isc->sctmp, &id2 );
}
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 ) {
if ( !isc->scopes[x].mval.mv_data ) {
+ /* This node is in scope, add parent chain to scope */
+ int i;
+ for ( i = 1; i <= isc->sctmp[0].mid; i++ ) {
+ rc = mdb_id2l_insert( isc->scopes, &isc->sctmp[i] );
+ if ( rc )
+ break;
+ }
+ /* check id again since inserts may have changed its position */
+ if ( isc->scopes[x].mid != id )
+ x = mdb_id2l_search( isc->scopes, id );
isc->nscope = x;
return MDB_SUCCESS;
}
@@ -757,6 +787,53 @@ mdb_idscopes(
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,
@@ -777,18 +854,18 @@ mdb_dn2id_walk(
isc->numrdns++;
isc->nscope = 0;
/* skip base if not a subtree walk */
- if ( op->ors_scope == LDAP_SCOPE_SUBTREE ||
- op->ors_scope == LDAP_SCOPE_BASE )
+ if ( isc->oscope == LDAP_SCOPE_SUBTREE ||
+ isc->oscope == LDAP_SCOPE_BASE )
return rc;
}
- if ( op->ors_scope == LDAP_SCOPE_BASE )
+ if ( isc->oscope == LDAP_SCOPE_BASE )
return MDB_NOTFOUND;
for (;;) {
/* Get next sibling */
rc = mdb_cursor_get( isc->mc, &key, &data, MDB_NEXT_DUP );
if ( !rc ) {
- ptr = data.mv_data + data.mv_size - 2*sizeof(ID);
+ ptr = (char *)data.mv_data + data.mv_size - 2*sizeof(ID);
d = data.mv_data;
memcpy( &isc->id, ptr, sizeof(ID));
@@ -819,7 +896,7 @@ mdb_dn2id_walk(
continue;
} else if ( rc == MDB_NOTFOUND ) {
- if ( !isc->nscope && op->ors_scope != LDAP_SCOPE_ONELEVEL ) {
+ if ( !isc->nscope && isc->oscope != LDAP_SCOPE_ONELEVEL ) {
/* reset to first dup */
mdb_cursor_get( isc->mc, &key, NULL, MDB_GET_CURRENT );
mdb_cursor_get( isc->mc, &key, &data, MDB_SET );
@@ -835,6 +912,7 @@ mdb_dn2id_walk(
key.mv_data = &isc->scopes[n].mid;
key.mv_size = sizeof(ID);
data.mv_data = isc->nrdns[n].bv_val - 2;
+ data.mv_size = 1; /* just needs to be non-zero, mdb_dup_compare doesn't care */
mdb_cursor_get( isc->mc, &key, &data, MDB_GET_BOTH );
continue;
}
@@ -844,3 +922,45 @@ mdb_dn2id_walk(
}
return rc;
}
+
+/* restore the nrdn/rdn pointers after a txn reset */
+void mdb_dn2id_wrestore (
+ Operation *op,
+ IdScopes *isc
+)
+{
+ MDB_val key, data;
+ diskNode *d;
+ int rc, n, nrlen;
+ char *ptr;
+
+ /* We only need to restore up to the n-1th element,
+ * the nth element will be replaced anyway
+ */
+ key.mv_size = sizeof(ID);
+ for ( n=0; nnumrdns-1; n++ ) {
+ key.mv_data = &isc->scopes[n+1].mid;
+ rc = mdb_cursor_get( isc->mc, &key, &data, MDB_SET );
+ if ( rc )
+ continue;
+ /* we can't use this data directly since its nrlen
+ * is missing the high bit setting, so copy it and
+ * set it properly. we just copy enough to satisfy
+ * mdb_dup_compare.
+ */
+ d = data.mv_data;
+ nrlen = ((d->nrdnlen[0] & 0x7f) << 8) | d->nrdnlen[1];
+ ptr = op->o_tmpalloc( nrlen+2, op->o_tmpmemctx );
+ memcpy( ptr, data.mv_data, nrlen+2 );
+ key.mv_data = &isc->scopes[n].mid;
+ data.mv_data = ptr;
+ data.mv_size = 1;
+ *ptr |= 0x80;
+ mdb_cursor_get( isc->mc, &key, &data, MDB_GET_BOTH );
+
+ /* now we're back to where we wanted to be */
+ d = data.mv_data;
+ isc->nrdns[n].bv_val = d->nrdn;
+ isc->rdns[n].bv_val = d->nrdn+isc->nrdns[n].bv_len+1;
+ }
+}