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; + } +}