X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=servers%2Fslapd%2Fmods.c;h=6e7d7ec1c5b8e1e42f227d37253cf8a831bac9dd;hb=f955f17076dc185a589d90baa2acd33afc4c1448;hp=147e2d82674ac5314d4ed03962273c08d2a5c7bf;hpb=4e15a84452f0493b1b5bc7b779c7bd1cd4fa4b73;p=openldap diff --git a/servers/slapd/mods.c b/servers/slapd/mods.c index 147e2d8267..6e7d7ec1c5 100644 --- a/servers/slapd/mods.c +++ b/servers/slapd/mods.c @@ -1,7 +1,7 @@ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * - * Copyright 1998-2003 The OpenLDAP Foundation. + * Copyright 1998-2005 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -29,37 +29,21 @@ #include "slap.h" -int -modify_check_duplicates( - AttributeDescription *ad, - MatchingRule *mr, - BerVarray vals, - BerVarray mods, - int permissive, - const char **text, - char *textbuf, size_t textlen ) -{ - int i, j, numvals = 0, nummods, - rc = LDAP_SUCCESS, matched; - /* this function is no longer used */ - return rc; -} - int modify_add_values( - Entry *e, + Entry *e, Modification *mod, - int permissive, + int permissive, const char **text, - char *textbuf, size_t textlen ) + char *textbuf, + size_t textlen ) { - int i, j; - int matched; + int rc; + const char *op; Attribute *a; - MatchingRule *mr = mod->sm_desc->ad_type->sat_equality; - const char *op; + Modification pmod = *mod; - switch( mod->sm_op ) { + switch ( mod->sm_op ) { case LDAP_MOD_ADD: op = "add"; break; @@ -71,17 +55,14 @@ modify_add_values( assert( 0 ); } + /* check if values to add exist in attribute */ a = attr_find( e->e_attrs, mod->sm_desc ); + if ( a != NULL ) { + int rc, i, j, p; + MatchingRule *mr; - /* - * With permissive set, as long as the attribute being added - * has the same value(s?) as the existing attribute, then the - * modify will succeed. - */ - - /* check if the values we're adding already exist */ - if( mr == NULL || !mr->smr_match ) { - if ( a != NULL ) { + mr = mod->sm_desc->ad_type->sat_equality; + if( mr == NULL || !mr->smr_match ) { /* do not allow add of additional attribute if no equality rule exists */ *text = textbuf; @@ -91,116 +72,85 @@ modify_add_values( return LDAP_INAPPROPRIATE_MATCHING; } - for ( i = 0; mod->sm_bvalues[i].bv_val != NULL; i++ ) { - /* test asserted values against existing values */ - if( a ) { - for( matched = 0, j = 0; a->a_vals[j].bv_val != NULL; j++ ) { - if ( bvmatch( &mod->sm_bvalues[i], &a->a_vals[j] ) ) { - if ( permissive ) { - matched++; - continue; - } - /* value exists already */ - *text = textbuf; - snprintf( textbuf, textlen, - "modify/%s: %s: value #%i already exists", - op, mod->sm_desc->ad_cname.bv_val, j ); - return LDAP_TYPE_OR_VALUE_EXISTS; - } - } - if ( permissive && matched == j ) { - /* values already exist; do nothing */ - return LDAP_SUCCESS; - } - } - - /* test asserted values against themselves */ - for( j = 0; j < i; j++ ) { - if ( bvmatch( &mod->sm_bvalues[i], &mod->sm_bvalues[j] ) ) { - /* value exists already */ - *text = textbuf; - snprintf( textbuf, textlen, - "modify/%s: %s: value #%i already exists", - op, mod->sm_desc->ad_cname.bv_val, j ); - return LDAP_TYPE_OR_VALUE_EXISTS; - } + if ( permissive ) { + for ( i = 0; !BER_BVISNULL( &mod->sm_values[i] ); i++ ) /* count 'em */; + pmod.sm_values = (BerVarray)ch_malloc( (i + 1)*sizeof( struct berval ) ); + if ( pmod.sm_nvalues != NULL ) { + pmod.sm_nvalues = (BerVarray)ch_malloc( + (i + 1)*sizeof( struct berval ) ); } } - } else { /* no normalization is done in this routine nor * in the matching routines called by this routine. * values are now normalized once on input to the * server (whether from LDAP or from the underlying * database). - * This should outperform the old code. No numbers - * are available yet. */ - - int rc; - - if ( mod->sm_bvalues[1].bv_val == 0 ) { - if ( a != NULL ) { - int i; - - for ( matched = 0, i = 0; a->a_vals[ i ].bv_val; i++ ) { - int match; - - if( mod->sm_nvalues ) { - rc = value_match( &match, mod->sm_desc, mr, - SLAP_MR_EQUALITY - | SLAP_MR_VALUE_OF_ASSERTION_SYNTAX - | SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH - | SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH, - &a->a_nvals[i], - &mod->sm_nvalues[0], - text ); - - } else { - rc = value_match( &match, mod->sm_desc, mr, - SLAP_MR_EQUALITY - | SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX, - &a->a_vals[i], - &mod->sm_values[0], - text ); - } - - - if( rc == LDAP_SUCCESS && match == 0 ) { - if ( permissive ) { - matched++; - continue; - } - *text = textbuf; - snprintf( textbuf, textlen, - "modify/%s: %s: value #0 already exists", - op, mod->sm_desc->ad_cname.bv_val ); - return LDAP_TYPE_OR_VALUE_EXISTS; - } + for ( p = i = 0; !BER_BVISNULL( &mod->sm_values[i] ); i++ ) { + int match; + + assert( a->a_vals[0].bv_val ); + for ( j = 0; !BER_BVISNULL( &a->a_vals[j] ); j++ ) { + if ( mod->sm_nvalues ) { + rc = value_match( &match, mod->sm_desc, mr, + SLAP_MR_EQUALITY | SLAP_MR_VALUE_OF_ASSERTION_SYNTAX + | SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH + | SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH, + &a->a_nvals[j], &mod->sm_nvalues[i], text ); + } else { + rc = value_match( &match, mod->sm_desc, mr, + SLAP_MR_EQUALITY | SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX, + &a->a_vals[j], &mod->sm_values[i], text ); } - if ( permissive && matched == i ) { - /* values already exist; do nothing */ - return LDAP_SUCCESS; + + if ( rc == LDAP_SUCCESS && match == 0 ) { + /* value already exists */ + if ( permissive ) break; + + *text = textbuf; + snprintf( textbuf, textlen, + "modify/%s: %s: value #%d already exists", + op, mod->sm_desc->ad_cname.bv_val, i ); + return LDAP_TYPE_OR_VALUE_EXISTS; + + } else if ( rc != LDAP_SUCCESS ) { + return rc; } } - } else { - rc = modify_check_duplicates( mod->sm_desc, mr, - a ? a->a_vals : NULL, mod->sm_bvalues, - permissive, text, textbuf, textlen ); + if ( permissive && match != 0 ) { + if ( pmod.sm_nvalues ) { + pmod.sm_nvalues[p] = mod->sm_nvalues[i]; + } + pmod.sm_values[p++] = mod->sm_values[i]; + } + } - if ( permissive && rc == LDAP_TYPE_OR_VALUE_EXISTS ) { + if ( permissive ) { + if ( p == 0 ) { + /* all new values match exist */ + ch_free( pmod.sm_values ); + if ( pmod.sm_nvalues ) ch_free( pmod.sm_nvalues ); return LDAP_SUCCESS; } - if ( rc != LDAP_SUCCESS ) { - return rc; + BER_BVZERO( &pmod.sm_values[p] ); + if ( pmod.sm_nvalues ) { + BER_BVZERO( &pmod.sm_nvalues[p] ); } } } /* no - add them */ - if( attr_merge( e, mod->sm_desc, mod->sm_values, mod->sm_nvalues ) != 0 ) { + rc = attr_merge( e, mod->sm_desc, pmod.sm_values, pmod.sm_nvalues ); + + if ( a != NULL && permissive ) { + ch_free( pmod.sm_values ); + if ( pmod.sm_nvalues ) ch_free( pmod.sm_nvalues ); + } + + if ( rc != 0 ) { /* this should return result of attr_merge */ *text = textbuf; snprintf( textbuf, textlen, @@ -218,14 +168,13 @@ modify_delete_values( Modification *mod, int permissive, const char **text, - char *textbuf, size_t textlen -) + char *textbuf, size_t textlen ) { int i, j, k, rc = LDAP_SUCCESS; Attribute *a; MatchingRule *mr = mod->sm_desc->ad_type->sat_equality; char dummy = '\0'; - int match = 0; + int match = 0; /* * If permissive is set, then the non-existence of an @@ -233,7 +182,7 @@ modify_delete_values( */ /* delete the entire attribute */ - if ( mod->sm_bvalues == NULL ) { + if ( mod->sm_values == NULL ) { rc = attr_delete( &e->e_attrs, mod->sm_desc ); if( permissive ) { @@ -270,10 +219,13 @@ modify_delete_values( return LDAP_NO_SUCH_ATTRIBUTE; } - - for ( i = 0; mod->sm_values[i].bv_val != NULL; i++ ) { + for ( i = 0; !BER_BVISNULL( &mod->sm_values[i] ); i++ ) { int found = 0; - for ( j = 0; a->a_vals[j].bv_val != NULL; j++ ) { + for ( j = 0; !BER_BVISNULL( &a->a_vals[j] ); j++ ) { + /* skip already deleted values */ + if ( a->a_vals[j].bv_val == &dummy ) { + continue; + } if( mod->sm_nvalues ) { assert( a->a_nvals ); @@ -335,7 +287,7 @@ modify_delete_values( } /* compact array skipping dummies */ - for ( k = 0, j = 0; a->a_vals[k].bv_val != NULL; k++ ) { + for ( k = 0, j = 0; !BER_BVISNULL( &a->a_vals[k] ); k++ ) { /* skip dummies */ if( a->a_vals[k].bv_val == &dummy ) { assert( a->a_nvals == NULL || a->a_nvals[k].bv_val == &dummy ); @@ -351,11 +303,13 @@ modify_delete_values( j++; } - a->a_vals[j].bv_val = NULL; - if (a->a_nvals != a->a_vals) a->a_nvals[j].bv_val = NULL; + BER_BVZERO( &a->a_vals[j] ); + if (a->a_nvals != a->a_vals) { + BER_BVZERO( &a->a_nvals[j] ); + } /* if no values remain, delete the entire attribute */ - if ( a->a_vals[0].bv_val == NULL ) { + if ( BER_BVISNULL( &a->a_vals[0] ) ) { if ( attr_delete( &e->e_attrs, mod->sm_desc ) ) { *text = textbuf; snprintf( textbuf, textlen, @@ -380,7 +334,7 @@ modify_replace_values( { (void) attr_delete( &e->e_attrs, mod->sm_desc ); - if ( mod->sm_bvalues ) { + if ( mod->sm_values ) { return modify_add_values( e, mod, permissive, text, textbuf, textlen ); } @@ -406,18 +360,17 @@ modify_increment_values( return LDAP_NO_SUCH_ATTRIBUTE; } - if ( !strcmp( a->a_desc->ad_type->sat_syntax_oid, SLAPD_INTEGER_SYNTAX )) { int i; char str[sizeof(long)*3 + 2]; /* overly long */ - long incr = atol( mod->sm_bvalues[0].bv_val ); + long incr = atol( mod->sm_values[0].bv_val ); /* treat zero and errors as a no-op */ if( incr == 0 ) { return LDAP_SUCCESS; } - for( i=0; a->a_nvals[i].bv_val != NULL; i++ ) { + for( i = 0; !BER_BVISNULL( &a->a_nvals[i] ); i++ ) { char *tmp; long value = atol( a->a_nvals[i].bv_val ); size_t strln = snprintf( str, sizeof(str), "%ld", value+incr );