]> git.sur5r.net Git - openldap/blobdiff - servers/slapd/back-mdb/id2entry.c
ITS#7920 fix for slapacl
[openldap] / servers / slapd / back-mdb / id2entry.c
index 9e6f840e8029087197ffbaf70917c4d4673d7515..7ff1e8e1960b9584f15911a96c29181376c02996 100644 (file)
@@ -2,7 +2,7 @@
 /* $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
@@ -72,7 +72,7 @@ again:
        if (rc == MDB_SUCCESS) {
                rc = mdb_entry_encode( op, e, &data, &ec );
                if( rc != LDAP_SUCCESS )
-                       return LDAP_OTHER;
+                       return rc;
        }
        if (rc) {
                /* Was there a hole from slapadd? */
@@ -188,7 +188,7 @@ int mdb_id2entry(
                rc = MDB_NOTFOUND;
        if ( rc ) return rc;
 
-       rc = mdb_entry_decode( op, &data, e );
+       rc = mdb_entry_decode( op, mdb_cursor_txn( mc ), &data, e );
        if ( rc ) return rc;
 
        (*e)->e_id = id;
@@ -242,6 +242,8 @@ int mdb_entry_return(
        Entry *e
 )
 {
+       if ( !e )
+               return 0;
        if ( e->e_private ) {
                if ( op->o_hdr ) {
                        op->o_tmpfree( e->e_nname.bv_val, op->o_tmpmemctx );
@@ -270,11 +272,11 @@ int mdb_entry_release(
        /* slapMode : SLAP_SERVER_MODE, SLAP_TOOL_MODE,
                        SLAP_TRUNCATE_MODE, SLAP_UNDEFINED_MODE */
  
-       mdb_entry_return( op, e );
-       if ( slapMode == SLAP_SERVER_MODE ) {
+       if ( slapMode & SLAP_SERVER_MODE ) {
                OpExtra *oex;
                LDAP_SLIST_FOREACH( oex, &op->o_extra, oe_next ) {
                        if ( oex->oe_key == mdb ) {
+                               mdb_entry_return( op, e );
                                moi = (mdb_op_info *)oex;
                                /* If it was setup by entry_get we should probably free it */
                                if ( moi->moi_flag & MOI_FREEIT ) {
@@ -289,6 +291,8 @@ int mdb_entry_release(
                                break;
                        }
                }
+       } else {
+               mdb_entry_return( op, e );
        }
  
        return 0;
@@ -363,14 +367,7 @@ int mdb_entry_get(
 return_results:
        if( rc != LDAP_SUCCESS ) {
                /* free entry */
-               if ( e )
-                       mdb_entry_return( op, e );
-
-               if (moi->moi_ref == 1) {
-                       LDAP_SLIST_REMOVE( &op->o_extra, &moi->moi_oe, OpExtra, oe_next );
-                       mdb_txn_reset( txn );
-                       op->o_tmpfree( moi, op->o_tmpmemctx );
-               }
+               mdb_entry_release( op, e, rw );
        } else {
                *ent = e;
        }
@@ -402,6 +399,8 @@ mdb_reader_flush( MDB_env *env )
        }
 }
 
+extern MDB_txn *mdb_tool_txn;
+
 int
 mdb_opinfo_get( Operation *op, struct mdb_info *mdb, int rdonly, mdb_op_info **moip )
 {
@@ -458,18 +457,26 @@ mdb_opinfo_get( Operation *op, struct mdb_info *mdb, int rdonly, mdb_op_info **m
                }
                moi->moi_ref++;
                if ( !moi->moi_txn ) {
-                       rc = mdb_txn_begin( mdb->mi_dbenv, NULL, 0, &moi->moi_txn );
-                       if (rc) {
-                               Debug( LDAP_DEBUG_ANY, "mdb_opinfo_get: err %s(%d)\n",
-                                       mdb_strerror(rc), rc, 0 );
+                       if (( slapMode & SLAP_TOOL_MODE ) && mdb_tool_txn ) {
+                               moi->moi_txn = mdb_tool_txn;
+                       } else {
+                               rc = mdb_txn_begin( mdb->mi_dbenv, NULL, 0, &moi->moi_txn );
+                               if (rc) {
+                                       Debug( LDAP_DEBUG_ANY, "mdb_opinfo_get: err %s(%d)\n",
+                                               mdb_strerror(rc), rc, 0 );
+                               }
+                               return rc;
                        }
-                       return rc;
                }
                return 0;
        }
 
        /* OK, this is a reader */
        if ( !moi->moi_txn ) {
+               if (( slapMode & SLAP_TOOL_MODE ) && mdb_tool_txn ) {
+                       moi->moi_txn = mdb_tool_txn;
+                       goto ok;
+               }
                if ( !ctx ) {
                        /* Shouldn't happen unless we're single-threaded */
                        rc = mdb_txn_begin( mdb->mi_dbenv, NULL, MDB_RDONLY, &moi->moi_txn );
@@ -501,11 +508,13 @@ mdb_opinfo_get( Operation *op, struct mdb_info *mdb, int rdonly, mdb_op_info **m
                }
                moi->moi_flag |= MOI_READER;
        }
+ok:
        if ( moi->moi_ref < 1 ) {
                moi->moi_ref = 0;
        }
        if ( renew ) {
-               mdb_txn_renew( moi->moi_txn );
+               rc = mdb_txn_renew( moi->moi_txn );
+               assert(!rc);
        }
        moi->moi_ref++;
        if ( *moip != moi )
@@ -565,7 +574,9 @@ static int mdb_entry_partsize(struct mdb_info *mdb, MDB_txn *txn, Entry *e,
  * entry, and the e_ocflags. It then contains a list of integers for each
  * attribute. For each attribute the first integer gives the index of the
  * matching AttributeDescription, followed by the number of values in the
- * attribute. If the high bit is set, the attribute also has normalized
+ * attribute. If the high bit of the attr index is set, the attribute's
+ * values are already sorted.
+ * If the high bit of numvals is set, the attribute also has normalized
  * values present. (Note - a_numvals is an unsigned int, so this means
  * it's possible to receive an attribute that we can't encode due to size
  * overflow. In practice, this should not be an issue.) Then the length
@@ -600,7 +611,12 @@ static int mdb_entry_encode(Operation *op, Entry *e, MDB_val *data, Ecount *eh)
        ptr = (unsigned char *)(lp + eh->offset);
 
        for (a=e->e_attrs; a; a=a->a_next) {
-               *lp++ = mdb->mi_adxs[a->a_desc->ad_index];
+               if (!a->a_desc->ad_index)
+                       return LDAP_UNDEFINED_TYPE;
+               l = mdb->mi_adxs[a->a_desc->ad_index];
+               if (a->a_flags & SLAP_ATTR_SORTED_VALS)
+                       l |= HIGH_BIT;
+               *lp++ = l;
                l = a->a_numvals;
                if (a->a_nvals != a->a_vals)
                        l |= HIGH_BIT;
@@ -640,7 +656,7 @@ static int mdb_entry_encode(Operation *op, Entry *e, MDB_val *data, Ecount *eh)
  * structure. Attempting to do so will likely corrupt memory.
  */
 
-int mdb_entry_decode(Operation *op, MDB_val *data, Entry **e)
+int mdb_entry_decode(Operation *op, MDB_txn *txn, MDB_val *data, Entry **e)
 {
        struct mdb_info *mdb = (struct mdb_info *) op->o_bd->be_private;
        int i, j, nattrs, nvals;
@@ -671,8 +687,24 @@ int mdb_entry_decode(Operation *op, MDB_val *data, Entry **e)
 
        for (;nattrs>0; nattrs--) {
                int have_nval = 0;
-               a->a_desc = mdb->mi_ads[*lp++];
                a->a_flags = SLAP_ATTR_DONT_FREE_DATA | SLAP_ATTR_DONT_FREE_VALS;
+               i = *lp++;
+               if (i & HIGH_BIT) {
+                       i ^= HIGH_BIT;
+                       a->a_flags |= SLAP_ATTR_SORTED_VALS;
+               }
+               if (i > mdb->mi_numads) {
+                       rc = mdb_ad_read(mdb, txn);
+                       if (rc)
+                               return rc;
+                       if (i > mdb->mi_numads) {
+                               Debug( LDAP_DEBUG_ANY,
+                                       "mdb_entry_decode: attribute index %d not recognized\n",
+                                       i, 0, 0 );
+                               return LDAP_OTHER;
+                       }
+               }
+               a->a_desc = mdb->mi_ads[i];
                a->a_numvals = *lp++;
                if (a->a_numvals & HIGH_BIT) {
                        a->a_numvals ^= HIGH_BIT;
@@ -704,7 +736,8 @@ int mdb_entry_decode(Operation *op, MDB_val *data, Entry **e)
                        a->a_nvals = a->a_vals;
                }
                /* FIXME: This is redundant once a sorted entry is saved into the DB */
-               if ( a->a_desc->ad_type->sat_flags & SLAP_AT_SORTED_VAL ) {
+               if (( a->a_desc->ad_type->sat_flags & SLAP_AT_SORTED_VAL )
+                       && !(a->a_flags & SLAP_ATTR_SORTED_VALS)) {
                        rc = slap_sort_vals( (Modifications *)a, &text, &j, NULL );
                        if ( rc == LDAP_SUCCESS ) {
                                a->a_flags |= SLAP_ATTR_SORTED_VALS;