X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=servers%2Fslapd%2Fback-ldbm%2Fmodify.c;h=54c71a8d76d5b8a9d07d69ac0fa25aa0d46556d7;hb=4710c74605d21f17a3292806ed7e02e81b9af450;hp=d9e9b8ed4c9b2e7935f8d47d037c9e886690ab0a;hpb=73276e84ae32e9e148197971d1d6729739980353;p=openldap diff --git a/servers/slapd/back-ldbm/modify.c b/servers/slapd/back-ldbm/modify.c index d9e9b8ed4c..54c71a8d76 100644 --- a/servers/slapd/back-ldbm/modify.c +++ b/servers/slapd/back-ldbm/modify.c @@ -1,4 +1,9 @@ /* modify.c - ldbm backend modify routine */ +/* $OpenLDAP$ */ +/* + * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. + * COPYING RESTRICTIONS APPLY, see COPYRIGHT file + */ #include "portable.h" @@ -12,80 +17,9 @@ #include "back-ldbm.h" #include "proto-back-ldbm.h" -static void add_lastmods(Operation *op, LDAPModList **ml); - - -static void -add_lastmods( Operation *op, LDAPModList **modlist ) -{ - char buf[22]; - struct berval bv; - struct berval *bvals[2]; - LDAPModList **m; - LDAPModList *tmp; - struct tm *ltm; - time_t currenttime; - - Debug( LDAP_DEBUG_TRACE, "add_lastmods\n", 0, 0, 0 ); - - bvals[0] = &bv; - bvals[1] = NULL; - - /* remove any attempts by the user to modify these attrs */ - for ( m = modlist; *m != NULL; m = &(*m)->ml_next ) { - if ( oc_check_no_usermod_attr( (*m)->ml_type ) ) { - Debug( LDAP_DEBUG_TRACE, - "add_lastmods: found no user mod attr: %s\n", - (*m)->ml_type, 0, 0 ); - tmp = *m; - *m = (*m)->ml_next; - free( tmp->ml_type ); - if ( tmp->ml_bvalues != NULL ) { - ber_bvecfree( tmp->ml_bvalues ); - } - free( tmp ); - if (!*m) - break; - } - } - - if ( op->o_dn == NULL || op->o_dn[0] == '\0' ) { - bv.bv_val = "NULLDN"; - bv.bv_len = strlen( bv.bv_val ); - } else { - bv.bv_val = op->o_dn; - bv.bv_len = strlen( bv.bv_val ); - } - tmp = (LDAPModList *) ch_calloc( 1, sizeof(LDAPModList) ); - tmp->ml_type = ch_strdup( "modifiersname" ); - tmp->ml_op = LDAP_MOD_REPLACE; - tmp->ml_bvalues = (struct berval **) ch_calloc(2, sizeof(struct berval *)); - tmp->ml_bvalues[0] = ber_bvdup( &bv ); - tmp->ml_next = *modlist; - *modlist = tmp; - - currenttime = slap_get_time(); - ldap_pvt_thread_mutex_lock( &gmtime_mutex ); -#ifndef LDAP_LOCALTIME - ltm = gmtime( ¤ttime ); - strftime( buf, sizeof(buf), "%Y%m%d%H%M%SZ", ltm ); -#else - ltm = localtime( ¤ttime ); - strftime( buf, sizeof(buf), "%y%m%d%H%M%SZ", ltm ); -#endif - ldap_pvt_thread_mutex_unlock( &gmtime_mutex ); - - bv.bv_val = buf; - bv.bv_len = strlen( bv.bv_val ); - tmp = (LDAPModList *) ch_calloc( 1, sizeof(LDAPModList) ); - tmp->ml_type = ch_strdup( "modifytimestamp" ); - tmp->ml_op = LDAP_MOD_REPLACE; - tmp->ml_bvalues = (struct berval **) ch_calloc(2, sizeof(struct berval *)); - tmp->ml_bvalues[0] = ber_bvdup( &bv ); - tmp->ml_next = *modlist; - *modlist = tmp; - -} +static int add_values LDAP_P(( Entry *e, Modification *mod, char *dn )); +static int delete_values LDAP_P(( Entry *e, Modification *mod, char *dn )); +static int replace_values LDAP_P(( Entry *e, Modification *mod, char *dn )); /* We need this function because of LDAP modrdn. If we do not * add this there would be a bunch of code replication here @@ -98,40 +32,31 @@ int ldbm_modify_internal( Connection *conn, Operation *op, char *dn, - LDAPModList *modlist, + Modifications *modlist, Entry *e ) { int err; - LDAPMod *mod; - LDAPModList *ml; - Attribute *a; + Modification *mod; + Modifications *ml; + 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 - * mod fails! - */ - add_lastmods( op, &modlist ); - - } - - - if ( (err = acl_check_modlist( be, conn, op, e, modlist )) - != LDAP_SUCCESS ) - { - send_ldap_result( conn, op, err, - NULL, NULL, NULL, NULL ); - return -1; + if ( !acl_check_modlist( be, conn, op, e, modlist )) { + return LDAP_INSUFFICIENT_ACCESS; } - for ( ml = modlist; ml != NULL; ml = ml->ml_next ) { + save_attrs = e->e_attrs; + e->e_attrs = attrs_dup( e->e_attrs ); - mod = &ml->ml_mod; + for ( ml = modlist; ml != NULL; ml = ml->sml_next ) { + mod = &ml->sml_mod; - switch ( mod->mod_op & ~LDAP_MOD_BVALUES ) { +#ifdef SLAPD_SCHEMA_NOT_COMPAT + switch ( mod->sm_op ) +#else + switch ( mod->mod_op ) +#endif + { case LDAP_MOD_ADD: err = add_values( e, mod, op->o_ndn ); break; @@ -141,80 +66,104 @@ int ldbm_modify_internal( 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_DELETE_OP); - } - err = replace_values( e, mod, op->o_ndn ); break; - case LDAP_MOD_SOFTADD: + case SLAP_MOD_SOFTADD: /* Avoid problems in index_add_mods() * We need to add index if necessary. */ +#ifdef SLAPD_SCHEMA_NOT_COMPAT + mod->sm_op = LDAP_MOD_ADD; +#else mod->mod_op = LDAP_MOD_ADD; - if ( (err = add_values( e, mod, op->o_ndn )) - == LDAP_TYPE_OR_VALUE_EXISTS ) { - +#endif + err = add_values( e, mod, op->o_ndn ); + if ( err == LDAP_TYPE_OR_VALUE_EXISTS ) { err = LDAP_SUCCESS; - mod->mod_op = LDAP_MOD_SOFTADD; +#ifdef SLAPD_SCHEMA_NOT_COMPAT + mod->sm_op = SLAP_MOD_SOFTADD; +#else + mod->mod_op = SLAP_MOD_SOFTADD; +#endif } break; } 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, NULL, NULL ); - return -1; + return err; } } - /* check that the entry still obeys the schema */ - if ( global_schemacheck && oc_schema_check( e ) != 0 ) { - Debug( LDAP_DEBUG_ANY, "entry failed schema check\n", 0, 0, 0 ); - send_ldap_result( conn, op, LDAP_OBJECT_CLASS_VIOLATION, - NULL, NULL, 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; + return SLAPD_ABANDON; } ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex ); - /* modify indexes */ - if ( index_add_mods( be, modlist, e->e_id ) != 0 ) { - send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, - NULL, NULL, NULL, NULL ); - return -1; + /* check that the entry still obeys the schema */ + if ( schema_check_entry( e ) != 0 ) { + attrs_free( e->e_attrs ); + e->e_attrs = save_attrs; + Debug( LDAP_DEBUG_ANY, "entry failed schema check\n", 0, 0, 0 ); + return LDAP_OBJECT_CLASS_VIOLATION; } /* 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; + return SLAPD_ABANDON; } ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex ); - return 0; + /* remove old indices */ + if( save_attrs != NULL ) { + for ( ml = modlist; ml != NULL; ml = ml->sml_next ) { + mod = &ml->sml_mod; +#ifdef SLAPD_SCHEMA_NOT_COMPAT + if ( mod->sm_op == LDAP_MOD_REPLACE ) +#else + if ( mod->mod_op == LDAP_MOD_REPLACE ) +#endif + { +#ifdef SLAPD_SCHEMA_NOT_COMPAT + /* not yet implemented */ +#else + /* Need to remove all values from indexes */ + Attribute *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, + SLAP_INDEX_DELETE_OP); + } +#endif + } + } + attrs_free( save_attrs ); + } -}/* int ldbm_modify_internal() */ + /* modify indexes */ + if ( index_add_mods( be, modlist, e->e_id ) != 0 ) { + /* our indices are likely hosed */ + return LDAP_OTHER; + } + + return LDAP_SUCCESS; +} int @@ -223,9 +172,11 @@ ldbm_back_modify( Connection *conn, Operation *op, char *dn, - LDAPModList *modlist + char *ndn, + Modifications *modlist ) { + int rc; struct ldbminfo *li = (struct ldbminfo *) be->be_private; Entry *matched; Entry *e; @@ -234,7 +185,7 @@ ldbm_back_modify( Debug(LDAP_DEBUG_ARGS, "ldbm_back_modify:\n", 0, 0, 0); /* acquire and lock entry */ - if ( (e = dn2entry_w( be, dn, &matched )) == NULL ) { + if ( (e = dn2entry_w( be, ndn, &matched )) == NULL ) { char* matched_dn = NULL; struct berval **refs = NULL; @@ -277,19 +228,27 @@ ldbm_back_modify( } /* Modify the entry */ - if ( ldbm_modify_internal( be, conn, op, dn, modlist, e ) != 0 ) { + rc = ldbm_modify_internal( be, conn, op, ndn, modlist, e ); + + if( rc != LDAP_SUCCESS ) { + if( rc != SLAPD_ABANDON ) { + send_ldap_result( conn, op, rc, + NULL, NULL, NULL, NULL ); + } + goto error_return; } /* change the entry itself */ if ( id2entry_add( be, e ) != 0 ) { - send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, + send_ldap_result( conn, op, LDAP_OTHER, NULL, NULL, NULL, NULL ); goto error_return; } send_ldap_result( conn, op, LDAP_SUCCESS, NULL, NULL, NULL, NULL ); + cache_return_entry_w( &li->li_cache, e ); return( 0 ); @@ -298,13 +257,16 @@ error_return:; return( -1 ); } -int +static int add_values( Entry *e, - LDAPMod *mod, + Modification *mod, char *dn ) { +#ifdef SLAPD_SCHEMA_NOT_COMPAT + /* not yet implemented */ +#else int i; Attribute *a; @@ -322,17 +284,21 @@ add_values( if( attr_merge( e, mod->mod_type, mod->mod_bvalues ) != 0 ) { return( LDAP_CONSTRAINT_VIOLATION ); } +#endif return( LDAP_SUCCESS ); } -int +static int delete_values( Entry *e, - LDAPMod *mod, + Modification *mod, char *dn ) { +#ifdef SLAPD_SCHEMA_NOT_COMPAT + /* not yet implemented */ +#else int i, j, k, found; Attribute *a; @@ -367,6 +333,17 @@ delete_values( a->a_vals[k - 1] = a->a_vals[k]; } a->a_vals[k - 1] = NULL; + + /* delete the entire attribute, if no values remain */ + if ( a->a_vals[0] == NULL) { + Debug( LDAP_DEBUG_ARGS, + "removing entire attribute %s\n", + mod->mod_type, 0, 0 ); + if ( attr_delete( &e->e_attrs, mod->mod_type ) ) { + return LDAP_NO_SUCH_ATTRIBUTE; + } + } + break; } @@ -378,27 +355,29 @@ delete_values( return( LDAP_NO_SUCH_ATTRIBUTE ); } } +#endif return( LDAP_SUCCESS ); } -int +static int replace_values( Entry *e, - LDAPMod *mod, + Modification *mod, char *dn ) { - - /* XXX: BEFORE YOU GET RID OF PREVIOUS VALUES REMOVE FROM INDEX - * FILES - */ - +#ifdef SLAPD_SCHEMA_NOT_COMPAT + /* not yet implemented */ +#else (void) attr_delete( &e->e_attrs, mod->mod_type ); - if ( attr_merge( e, mod->mod_type, mod->mod_bvalues ) != 0 ) { + if ( mod->mod_bvalues != NULL && + attr_merge( e, mod->mod_type, mod->mod_bvalues ) != 0 ) + { return( LDAP_CONSTRAINT_VIOLATION ); } +#endif return( LDAP_SUCCESS ); }