]> git.sur5r.net Git - openldap/commitdiff
Fixed slapd ldbm modified attrs on failure (ITS#179) (ITS#181)
authorKurt Zeilenga <kurt@openldap.org>
Thu, 29 Jul 1999 23:13:47 +0000 (23:13 +0000)
committerKurt Zeilenga <kurt@openldap.org>
Thu, 29 Jul 1999 23:13:47 +0000 (23:13 +0000)
CHANGES
servers/slapd/attr.c
servers/slapd/back-ldbm/modify.c
servers/slapd/proto-slap.h

diff --git a/CHANGES b/CHANGES
index 626f45be37c509156458178e418f0e234eff7461..a48d2865bb3de4ca17fa378dd3024c3bd623556d 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -6,6 +6,7 @@ Changes included in OpenLDAP 1.2 Release Engineering
        Fixed slapd modify: delete of last attribute value bug (ITS#229)
        Fixed slapd print in signal handler bug (ITS#230)
        Fixed slapd index null vals bug (ITS#238)
+       Fixed slapd ldbm modified attrs on failure (ITS#179) (ITS#181)
        Import password security fix from -devel (ITS#232)
        Provided slapd workaround for "*" attribute type specifier (ITS#236)
        Fixed slapd attribute type list/only specifier on cn=monitor/config 
index 6467a13f05ecc54b146e7fb0763185504e8adbe6..1e99fc30f9971b3f2eab9566bc969d12d0ff22cd 100644 (file)
@@ -30,6 +30,69 @@ attr_free( Attribute *a )
        free( a );
 }
 
+void
+attrs_free( Attribute *a )
+{
+       Attribute *next;
+
+       for( ; a != NULL ; a = next ) {
+               next = a->a_next;
+               attr_free( a );
+       }
+}
+
+Attribute *attr_dup( Attribute *a )
+{
+       Attribute *tmp;
+
+       if( a == NULL) return NULL;
+
+       tmp = ch_malloc( sizeof(Attribute) );
+
+       if( a->a_vals != NULL ) {
+               int i;
+
+               for( i=0; a->a_vals[i] != NULL; i++ ) {
+                       /* EMPTY */ ;
+               }
+
+               tmp->a_vals = ch_malloc((i+1) * sizeof(struct berval*));
+
+               for( i=0; a->a_vals[i] != NULL; i++ ) {
+                       tmp->a_vals[i] = ber_bvdup( a->a_vals[i] );
+               }
+
+               tmp->a_vals[i] = NULL;
+
+       } else {
+               tmp->a_vals = NULL;
+       }
+
+       tmp->a_type = ch_strdup( a->a_type );
+       tmp->a_syntax = a->a_syntax;
+       tmp->a_next = NULL;
+
+       return tmp;
+}
+
+Attribute *attrs_dup( Attribute *a )
+{
+       Attribute *tmp, **next;
+
+       if( a == NULL ) return NULL;
+
+       tmp = NULL;
+       next = &tmp;
+
+       for( ; a != NULL ; a = a->a_next ) {
+               *next = attr_dup( a );
+               next = &((*next)->a_next);
+       }
+       *next = NULL;
+
+       return tmp;
+}
+
 /*
  * attr_normalize - normalize an attribute name (make it all lowercase)
  */
index e0f2e2330e9509675974d8c74053fd82aa005a9d..af91677b7be7fe2b8f341237a099b38c467ea6b0 100644 (file)
@@ -108,12 +108,13 @@ int ldbm_internal_modify(
        int             i, err;
        LDAPMod         *mod;
        Attribute       *a;
+       Attribute       *save_attrs;
 
        if ( ((be->be_lastmod == ON)
              || ((be->be_lastmod == UNDEFINED)&&(global_lastmod == ON)))
             && (be->be_update_ndn == NULL)) {
 
-               /* XXX: It may be wrong, it changes mod time even if 
+               /* XXX: It may be wrong, it changes mod time even if 
                 * mod fails! I also Think this is leaking memory...
                 */
                add_lastmods( op, &mods );
@@ -125,6 +126,9 @@ int ldbm_internal_modify(
                return -1;
        }
 
+       save_attrs = e->e_attrs;
+       e->e_attrs = attrs_dup( e->e_attrs );
+
        for ( mod = mods; mod != NULL; mod = mod->mod_next ) {
                switch ( mod->mod_op & ~LDAP_MOD_BVALUES ) {
                case LDAP_MOD_ADD:
@@ -136,21 +140,9 @@ int ldbm_internal_modify(
                        break;
 
                case LDAP_MOD_REPLACE:
-                       /* Need to remove all values from indexes before they
-                        * are lost.
-                        */
-                       if( e->e_attrs
-                           && ((a = attr_find( e->e_attrs, mod->mod_type ))
-                          != NULL) ) {
-
-                           (void) index_change_values( be,
-                                                       mod->mod_type,
-                                                       a->a_vals,
-                                                       e->e_id,
-                                                       __INDEX_DEL_OP);
-                       }
                        err = replace_values( e, mod, op->o_ndn );
                        break;
+
                case LDAP_MOD_SOFTADD:
                        /* Avoid problems in index_add_mods()
                         * We need to add index if necessary.
@@ -167,14 +159,28 @@ int ldbm_internal_modify(
                }
 
                if ( err != LDAP_SUCCESS ) {
+                       attrs_free( e->e_attrs );
+                       e->e_attrs = save_attrs;
                        /* unlock entry, delete from cache */
                        send_ldap_result( conn, op, err, NULL, NULL );
                        return -1;
                }
        }
 
+       /* check for abandon */
+       ldap_pvt_thread_mutex_lock( &op->o_abandonmutex );
+       if ( op->o_abandon ) {
+               attrs_free( e->e_attrs );
+               e->e_attrs = save_attrs;
+               ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex );
+               return -1;
+       }
+       ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex );
+
        /* check that the entry still obeys the schema */
        if ( global_schemacheck && oc_schema_check( e ) != 0 ) {
+               attrs_free( e->e_attrs );
+               e->e_attrs = save_attrs;
                Debug( LDAP_DEBUG_ANY, "entry failed schema check\n", 0, 0, 0 );
                send_ldap_result( conn, op, LDAP_OBJECT_CLASS_VIOLATION, NULL, NULL );
                return -1;
@@ -183,6 +189,8 @@ int ldbm_internal_modify(
        /* check for abandon */
        ldap_pvt_thread_mutex_lock( &op->o_abandonmutex );
        if ( op->o_abandon ) {
+               attrs_free( e->e_attrs );
+               e->e_attrs = save_attrs;
                ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex );
                return -1;
        }
@@ -190,10 +198,33 @@ int ldbm_internal_modify(
 
        /* modify indexes */
        if ( index_add_mods( be, mods, e->e_id ) != 0 ) {
+               attrs_free( e->e_attrs );
+               e->e_attrs = save_attrs;
                send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, NULL, NULL );
                return -1;
        }
 
+       if( save_attrs != NULL ) {
+               for ( mod = mods; mod != NULL; mod = mod->mod_next ) {
+                       if( ( mod->mod_op & ~LDAP_MOD_BVALUES )
+                               == LDAP_MOD_REPLACE )
+                       {
+                               /* Need to remove all values from indexes */
+                               a = attr_find( save_attrs, mod->mod_type );
+
+                               if( a != NULL ) {
+                                       (void) index_change_values( be,
+                                               mod->mod_type,
+                                               a->a_vals,
+                                               e->e_id,
+                                               __INDEX_DEL_OP);
+                               }
+
+                       }
+               }
+               attrs_free( save_attrs );
+       }
+
        /* check for abandon */
        ldap_pvt_thread_mutex_lock( &op->o_abandonmutex );
        if ( op->o_abandon ) {
@@ -203,8 +234,7 @@ int ldbm_internal_modify(
        ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex );
 
        return 0;
-
-}/* int ldbm_internal_modify() */
+}
 
 
 int
index 41d4ecd7e8faa189dfb5e3effeb4a981d86bbfd7..f0f671b1b43d7eb8880024db6588cb9a1e4ce2ee 100644 (file)
@@ -35,6 +35,7 @@ int str2access LDAP_P(( char *str ));
  */
 
 void attr_free LDAP_P(( Attribute *a ));
+Attribute *attr_dup LDAP_P(( Attribute *a ));
 char * attr_normalize LDAP_P(( char *s ));
 int attr_merge_fast LDAP_P(( Entry *e, char *type, struct berval **vals, int  nvals,
        int  naddvals, int  *maxvals, Attribute ***a ));
@@ -44,6 +45,9 @@ int attr_delete LDAP_P(( Attribute **attrs, char *type ));
 int attr_syntax LDAP_P(( char *type ));
 void attr_syntax_config LDAP_P(( char *fname, int lineno, int argc, char **argv ));
 
+void attrs_free LDAP_P(( Attribute *a ));
+Attribute *attrs_dup LDAP_P(( Attribute *a ));
+
 /*
  * ava.c
  */