X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=servers%2Fslapd%2Fmods.c;h=76bb81f51ea2a70cd5081f5ca0507bbe5ec4dc71;hb=72d2ee4d19ee76e7d81d402c4056ce665f797045;hp=8d91c20327e2355c8bafda8f193028c5087e9ff0;hpb=cd84c58d4a4ecda7a0bcc5f8e8a0a51720b5ba45;p=openldap diff --git a/servers/slapd/mods.c b/servers/slapd/mods.c index 8d91c20327..76bb81f51e 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-2004 The OpenLDAP Foundation. + * Copyright 1998-2006 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -28,21 +28,23 @@ #include #include "slap.h" +#include "lutil.h" 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 rc; - const char *op; - Attribute *a; - Modification pmod = *mod; + int rc; + const char *op; + Attribute *a; + Modification pmod = *mod; - switch( mod->sm_op ) { + switch ( mod->sm_op ) { case LDAP_MOD_ADD: op = "add"; break; @@ -54,10 +56,11 @@ 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 ) { /* check if values to add exist in attribute */ - int rc, i, j, p; - MatchingRule *mr; + if ( a != NULL ) { + int rc, i, j, p; + MatchingRule *mr; mr = mod->sm_desc->ad_type->sat_equality; if( mr == NULL || !mr->smr_match ) { @@ -70,12 +73,16 @@ modify_add_values( return LDAP_INAPPROPRIATE_MATCHING; } - if( permissive ) { - for ( i=0; mod->sm_values[i].bv_val; i++ ) /* count 'em */; - pmod.sm_values = (BerVarray) ch_malloc( i*sizeof( struct berval )); - if( pmod.sm_nvalues != NULL ) { - pmod.sm_nvalues = (BerVarray) ch_malloc( - i*sizeof( struct berval )); + if ( permissive ) { + for ( i = 0; !BER_BVISNULL( &mod->sm_values[i] ); i++ ) { + /* EMPTY -- just counting '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 )); } } @@ -85,26 +92,27 @@ modify_add_values( * server (whether from LDAP or from the underlying * database). */ - for ( p=i=0; mod->sm_values[i].bv_val; i++ ) { - int match; - assert( a->a_vals[0].bv_val ); - for ( j=0; a->a_vals[j].bv_val; j++ ) { - if( mod->sm_nvalues ) { - rc = value_match( &match, mod->sm_desc, mr, + for ( p = i = 0; !BER_BVISNULL( &mod->sm_values[i] ); i++ ) { + int match; + + assert( a->a_vals[0].bv_val != NULL ); + for ( j = 0; !BER_BVISNULL( &a->a_vals[j] ); j++ ) { + if ( mod->sm_nvalues ) { + rc = ordered_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, + rc = ordered_value_match( &match, mod->sm_desc, mr, + SLAP_MR_EQUALITY | SLAP_MR_VALUE_OF_ASSERTION_SYNTAX, &a->a_vals[j], &mod->sm_values[i], text ); } - if( rc == LDAP_SUCCESS && match == 0 ) { - if( permissive ) break; - + if ( rc == LDAP_SUCCESS && match == 0 ) { /* value already exists */ + if ( permissive ) break; + *text = textbuf; snprintf( textbuf, textlen, "modify/%s: %s: value #%d already exists", @@ -116,31 +124,43 @@ modify_add_values( } } - if( permissive && !match ) { - if( pmod.sm_nvalues ) { + 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 && 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 ( 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; + } + + BER_BVZERO( &pmod.sm_values[p] ); + if ( pmod.sm_nvalues ) { + BER_BVZERO( &pmod.sm_nvalues[p] ); + } } } /* no - add them */ - rc = attr_merge( e, mod->sm_desc, pmod.sm_values, pmod.sm_nvalues ); + if ( mod->sm_desc->ad_type->sat_flags & SLAP_AT_ORDERED_VAL ) { + rc = ordered_value_add( e, mod->sm_desc, a, + pmod.sm_values, pmod.sm_nvalues ); + } else { + rc = attr_merge( e, mod->sm_desc, pmod.sm_values, pmod.sm_nvalues ); + } - if( a != NULL && permissive ) { + if ( a != NULL && permissive ) { ch_free( pmod.sm_values ); - if( pmod.sm_nvalues ) ch_free( pmod.sm_nvalues ); + if ( pmod.sm_nvalues ) ch_free( pmod.sm_nvalues ); } - if( rc != 0 ) { + if ( rc != 0 ) { /* this should return result of attr_merge */ *text = textbuf; snprintf( textbuf, textlen, @@ -154,17 +174,29 @@ modify_add_values( int modify_delete_values( + Entry *e, + Modification *m, + int perm, + const char **text, + char *textbuf, size_t textlen ) +{ + return modify_delete_vindex( e, m, perm, text, textbuf, textlen, NULL ); +} + +int +modify_delete_vindex( Entry *e, Modification *mod, int permissive, const char **text, - char *textbuf, size_t textlen ) + char *textbuf, size_t textlen, + int *idx ) { 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 @@ -209,28 +241,28 @@ 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 ); - rc = (*mr->smr_match)( &match, - SLAP_MR_VALUE_OF_ASSERTION_SYNTAX + assert( a->a_nvals != NULL ); + rc = ordered_value_match( &match, a->a_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_desc->ad_type->sat_syntax, - mr, &a->a_nvals[j], - &mod->sm_nvalues[i] ); + &a->a_nvals[j], &mod->sm_nvalues[i], text ); } else { #if 0 assert( a->a_nvals == NULL ); #endif - rc = (*mr->smr_match)( &match, - SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX, - a->a_desc->ad_type->sat_syntax, - mr, &a->a_vals[j], - &mod->sm_values[i] ); + rc = ordered_value_match( &match, a->a_desc, mr, + SLAP_MR_EQUALITY | SLAP_MR_VALUE_OF_ASSERTION_SYNTAX, + &a->a_vals[j], &mod->sm_values[i], text ); } if ( rc != LDAP_SUCCESS ) { @@ -247,6 +279,9 @@ modify_delete_values( found = 1; + if ( idx ) + idx[i] = j; + /* delete value and mark it as dummy */ free( a->a_vals[j].bv_val ); a->a_vals[j].bv_val = &dummy; @@ -273,10 +308,10 @@ 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 ); + assert( a->a_nvals[k].bv_val == &dummy ); continue; } if ( j != k ) { @@ -289,11 +324,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, @@ -301,6 +338,9 @@ modify_delete_values( mod->sm_desc->ad_cname.bv_val ); rc = LDAP_NO_SUCH_ATTRIBUTE; } + } else if ( a->a_desc->ad_type->sat_flags & SLAP_AT_ORDERED_VAL ) { + /* For an ordered attribute, renumber the value indices */ + ordered_value_sort( a, 1 ); } return_results:; @@ -347,22 +387,32 @@ modify_increment_values( 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_values[0].bv_val ); + long incr; + + if ( lutil_atol( &incr, mod->sm_values[0].bv_val ) != 0 ) { + *text = "modify/increment: invalid syntax of increment"; + return LDAP_INVALID_SYNTAX; + } /* 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 ); + long value; + size_t strln; + if ( lutil_atol( &value, a->a_nvals[i].bv_val ) != 0 ) { + *text = "modify/increment: invalid syntax of original value"; + return LDAP_INVALID_SYNTAX; + } + strln = snprintf( str, sizeof(str), "%ld", value+incr ); tmp = SLAP_REALLOC( a->a_nvals[i].bv_val, strln+1 ); if( tmp == NULL ) { *text = "modify/increment: reallocation error"; - return LDAP_OTHER;; + return LDAP_OTHER; } a->a_nvals[i].bv_val = tmp; a->a_nvals[i].bv_len = strln; @@ -397,14 +447,16 @@ slap_mod_free( void slap_mods_free( - Modifications *ml ) + Modifications *ml, + int freevals ) { Modifications *next; for ( ; ml != NULL; ml = next ) { next = ml->sml_next; - slap_mod_free( &ml->sml_mod, 0 ); + if ( freevals ) + slap_mod_free( &ml->sml_mod, 0 ); free( ml ); } }