From 8eaaa67db06e4dc16cac607b6e7e4decafd1bd81 Mon Sep 17 00:00:00 2001 From: Kurt Zeilenga Date: Sat, 19 Jan 2002 19:54:48 +0000 Subject: [PATCH] Move {add,replace,delete}_value() routines to frontend and share. Add error detail reporting. --- servers/slapd/acl.c | 6 +- servers/slapd/back-bdb/add.c | 22 ++- servers/slapd/back-bdb/delete.c | 13 ++ servers/slapd/back-bdb/modify.c | 231 +--------------------------- servers/slapd/back-ldbm/modify.c | 225 +-------------------------- servers/slapd/mods.c | 254 +++++++++++++++++++++++++++++++ servers/slapd/proto-slap.h | 10 ++ servers/slapd/tools/mimic.c | 5 - 8 files changed, 307 insertions(+), 459 deletions(-) diff --git a/servers/slapd/acl.c b/servers/slapd/acl.c index 189ea1bc95..0b78173e19 100644 --- a/servers/slapd/acl.c +++ b/servers/slapd/acl.c @@ -532,17 +532,17 @@ acl_mask( * user is bound as somebody in the same namespace as * the entry, OR the given dn matches the dn pattern */ - if ( ber_bvstrcmp( &b->a_dn_pat, &aci_bv_anonymous ) == 0 ) { + if ( ber_bvcmp( &b->a_dn_pat, &aci_bv_anonymous ) == 0 ) { if ( op->o_ndn.bv_len != 0 ) { continue; } - } else if ( ber_bvstrcmp( &b->a_dn_pat, &aci_bv_users ) == 0 ) { + } else if ( ber_bvcmp( &b->a_dn_pat, &aci_bv_users ) == 0 ) { if ( op->o_ndn.bv_len == 0 ) { continue; } - } else if ( ber_bvstrcmp( &b->a_dn_pat, &aci_bv_self ) == 0 ) { + } else if ( ber_bvcmp( &b->a_dn_pat, &aci_bv_self ) == 0 ) { if ( op->o_ndn.bv_len == 0 ) { continue; } diff --git a/servers/slapd/back-bdb/add.c b/servers/slapd/back-bdb/add.c index ba3ebc0e4e..ce179385dd 100644 --- a/servers/slapd/back-bdb/add.c +++ b/servers/slapd/back-bdb/add.c @@ -174,9 +174,19 @@ retry: rc = txn_abort( ltid ); goto done; } - if ( ! access_allowed( be, conn, op, p, - children, NULL, ACL_WRITE ) ) - { + rc = access_allowed( be, conn, op, p, + children, NULL, ACL_WRITE ); + + switch( opinfo.boi_err ) { + case DB_LOCK_DEADLOCK: + case DB_LOCK_NOTGRANTED: + /* free parent and writer lock */ + bdb_entry_return( be, p ); + p = NULL; + goto retry; + } + + if ( ! rc ) { Debug( LDAP_DEBUG_TRACE, "bdb_add: no write access to parent\n", 0, 0, 0 ); rc = LDAP_INSUFFICIENT_ACCESS; @@ -243,6 +253,12 @@ retry: rc = txn_abort( ltid ); children, NULL, ACL_WRITE ); p = NULL; + switch( opinfo.boi_err ) { + case DB_LOCK_DEADLOCK: + case DB_LOCK_NOTGRANTED: + goto retry; + } + if ( ! rc ) { Debug( LDAP_DEBUG_TRACE, "bdb_add: no write access to parent\n", diff --git a/servers/slapd/back-bdb/delete.c b/servers/slapd/back-bdb/delete.c index 36be9b186a..135afd0bcd 100644 --- a/servers/slapd/back-bdb/delete.c +++ b/servers/slapd/back-bdb/delete.c @@ -131,6 +131,12 @@ retry: /* transaction retry */ bdb_entry_return( be, p ); p = NULL; + switch( opinfo.boi_err ) { + case DB_LOCK_DEADLOCK: + case DB_LOCK_NOTGRANTED: + goto retry; + } + if ( !rc ) { Debug( LDAP_DEBUG_TRACE, "<=- bdb_delete: no access to parent\n", @@ -150,6 +156,12 @@ retry: /* transaction retry */ children, NULL, ACL_WRITE ); p = NULL; + switch( opinfo.boi_err ) { + case DB_LOCK_DEADLOCK: + case DB_LOCK_NOTGRANTED: + goto retry; + } + if ( !rc ) { Debug( LDAP_DEBUG_TRACE, "<=- bdb_delete: no access " @@ -166,6 +178,7 @@ retry: /* transaction retry */ goto return_results; } } + #if 0 if ( ltid ) { DBT obj; diff --git a/servers/slapd/back-bdb/modify.c b/servers/slapd/back-bdb/modify.c index 66df842a08..b00b60236c 100644 --- a/servers/slapd/back-bdb/modify.c +++ b/servers/slapd/back-bdb/modify.c @@ -14,10 +14,6 @@ #include "back-bdb.h" #include "external.h" -static int add_values( Entry *e, Modification *mod, char *dn ); -static int delete_values( Entry *e, Modification *mod, char *dn ); -static int replace_values( Entry *e, Modification *mod, char *dn ); - int bdb_modify_internal( BackendDB *be, Connection *conn, @@ -51,10 +47,8 @@ int bdb_modify_internal( switch ( mod->sm_op ) { case LDAP_MOD_ADD: Debug(LDAP_DEBUG_ARGS, "bdb_modify_internal: add\n", 0, 0, 0); - err = add_values( e, mod, op->o_ndn.bv_val ); - + err = modify_add_values( e, mod, text, textbuf, textlen ); if( err != LDAP_SUCCESS ) { - *text = "modify: add values failed"; Debug(LDAP_DEBUG_ARGS, "bdb_modify_internal: %d %s\n", err, *text, 0); } @@ -62,10 +56,9 @@ int bdb_modify_internal( case LDAP_MOD_DELETE: Debug(LDAP_DEBUG_ARGS, "bdb_modify_internal: delete\n", 0, 0, 0); - err = delete_values( e, mod, op->o_ndn.bv_val ); + err = modify_delete_values( e, mod, text, textbuf, textlen ); assert( err != LDAP_TYPE_OR_VALUE_EXISTS ); if( err != LDAP_SUCCESS ) { - *text = "modify: delete values failed"; Debug(LDAP_DEBUG_ARGS, "bdb_modify_internal: %d %s\n", err, *text, 0); } @@ -73,10 +66,9 @@ int bdb_modify_internal( case LDAP_MOD_REPLACE: Debug(LDAP_DEBUG_ARGS, "bdb_modify_internal: replace\n", 0, 0, 0); - err = replace_values( e, mod, op->o_ndn.bv_val ); + err = modify_replace_values( e, mod, text, textbuf, textlen ); assert( err != LDAP_TYPE_OR_VALUE_EXISTS ); if( err != LDAP_SUCCESS ) { - *text = "modify: replace values failed"; Debug(LDAP_DEBUG_ARGS, "bdb_modify_internal: %d %s\n", err, *text, 0); } @@ -88,14 +80,13 @@ int bdb_modify_internal( * We need to add index if necessary. */ mod->sm_op = LDAP_MOD_ADD; - err = add_values( e, mod, op->o_ndn.bv_val ); + err = modify_add_values( e, mod, text, textbuf, textlen ); if ( err == LDAP_TYPE_OR_VALUE_EXISTS ) { err = LDAP_SUCCESS; } if( err != LDAP_SUCCESS ) { - *text = "modify: (soft)add values failed"; Debug(LDAP_DEBUG_ARGS, "bdb_modify_internal: %d %s\n", err, *text, 0); } @@ -378,217 +369,3 @@ done: return rc; } -static int -add_values( - Entry *e, - Modification *mod, - char *dn -) -{ - int i, j; - Attribute *a; - - /* char *desc = mod->sm_desc->ad_cname.bv_val; */ - MatchingRule *mr = mod->sm_desc->ad_type->sat_equality; - - a = attr_find( e->e_attrs, mod->sm_desc ); - - /* check if the values we're adding already exist */ - if( mr == NULL || !mr->smr_match ) { - if ( a != NULL ) { - /* do not allow add of additional attribute - if no equality rule exists */ - return LDAP_INAPPROPRIATE_MATCHING; - } - - for ( i = 0; mod->sm_bvalues[i].bv_val != NULL; i++ ) { - /* test asserted values against existing values */ - if( a ) { - for( j = 0; a->a_vals[j].bv_val != NULL; j++ ) { - int rc = ber_bvcmp( &mod->sm_bvalues[i], - &a->a_vals[j] ); - - if( rc == 0 ) { - /* value exists already */ - return LDAP_TYPE_OR_VALUE_EXISTS; - } - } - } - - /* test asserted values against themselves */ - for( j = 0; j < i; j++ ) { - int rc = ber_bvcmp( &mod->sm_bvalues[i], - &mod->sm_bvalues[j] ); - - if( rc == 0 ) { - /* value exists already */ - return LDAP_TYPE_OR_VALUE_EXISTS; - } - } - } - - } else { - for ( i = 0; mod->sm_bvalues[i].bv_val != NULL; i++ ) { - int rc, match; - const char *text = NULL; - struct berval asserted; - - rc = value_normalize( mod->sm_desc, - SLAP_MR_EQUALITY, - &mod->sm_bvalues[i], - &asserted, - &text ); - - if( rc != LDAP_SUCCESS ) return rc; - - if( a ) { - for ( j = 0; a->a_vals[j].bv_val != NULL; j++ ) { - int rc = value_match( &match, mod->sm_desc, mr, - SLAP_MR_VALUE_SYNTAX_MATCH, - &a->a_vals[j], &asserted, &text ); - - if( rc == LDAP_SUCCESS && match == 0 ) { - free( asserted.bv_val ); - return LDAP_TYPE_OR_VALUE_EXISTS; - } - } - } - - for ( j = 0; j < i; j++ ) { - int rc = value_match( &match, mod->sm_desc, mr, - SLAP_MR_VALUE_SYNTAX_MATCH, - &mod->sm_bvalues[j], &asserted, &text ); - - if( rc == LDAP_SUCCESS && match == 0 ) { - free( asserted.bv_val ); - return LDAP_TYPE_OR_VALUE_EXISTS; - } - } - - free( asserted.bv_val ); - } - } - - /* no - add them */ - if( attr_merge( e, mod->sm_desc, mod->sm_bvalues ) != 0 ) { - /* this should return result of attr_merge */ - return LDAP_OTHER; - } - - return LDAP_SUCCESS; -} - -static int -delete_values( - Entry *e, - Modification *mod, - char *dn -) -{ - int i, j, k, found; - Attribute *a; - char *desc = mod->sm_desc->ad_cname.bv_val; - MatchingRule *mr = mod->sm_desc->ad_type->sat_equality; - - /* delete the entire attribute */ - if ( mod->sm_bvalues == NULL ) { - Debug( LDAP_DEBUG_TRACE, - "bdb_modify_delete: removing entire attribute %s\n", - desc, 0, 0 ); - return attr_delete( &e->e_attrs, mod->sm_desc ) - ? LDAP_NO_SUCH_ATTRIBUTE : LDAP_SUCCESS; - } - - if( mr == NULL || !mr->smr_match ) { - /* disallow specific attributes from being deleted if - no equality rule */ - return LDAP_INAPPROPRIATE_MATCHING; - } - - /* delete specific values - find the attribute first */ - if ( (a = attr_find( e->e_attrs, mod->sm_desc )) == NULL ) { - Debug( LDAP_DEBUG_TRACE, - "bdb_modify_delete: could not find attribute %s\n", - desc, 0, 0 ); - return LDAP_NO_SUCH_ATTRIBUTE; - } - - /* find each value to delete */ - for ( i = 0; mod->sm_bvalues[i].bv_val != NULL; i++ ) { - int rc; - const char *text = NULL; - - struct berval asserted; - - rc = value_normalize( mod->sm_desc, - SLAP_MR_EQUALITY, - &mod->sm_bvalues[i], - &asserted, - &text ); - - if( rc != LDAP_SUCCESS ) return rc; - - found = 0; - for ( j = 0; a->a_vals[j].bv_val != NULL; j++ ) { - int match; - int rc = value_match( &match, mod->sm_desc, mr, - SLAP_MR_VALUE_SYNTAX_MATCH, - &a->a_vals[j], &asserted, &text ); - - if( rc == LDAP_SUCCESS && match != 0 ) { - continue; - } - - /* found a matching value */ - found = 1; - - /* delete it */ - free( a->a_vals[j].bv_val ); - for ( k = j + 1; a->a_vals[k].bv_val != NULL; k++ ) { - a->a_vals[k - 1] = a->a_vals[k]; - } - a->a_vals[k - 1].bv_val = NULL; - a->a_vals[k - 1].bv_len = 0; - - break; - } - - free( asserted.bv_val ); - - /* looked through them all w/o finding it */ - if ( ! found ) { - Debug( LDAP_DEBUG_TRACE, - "bdb_modify_delete: could not find value for attr %s\n", - desc, 0, 0 ); - return LDAP_NO_SUCH_ATTRIBUTE; - } - } - - /* if no values remain, delete the entire attribute */ - if ( a->a_vals[0].bv_val == NULL ) { - Debug( LDAP_DEBUG_TRACE, - "bdb_modify_delete: removing entire attribute %s\n", - desc, 0, 0 ); - if ( attr_delete( &e->e_attrs, mod->sm_desc ) ) { - return LDAP_NO_SUCH_ATTRIBUTE; - } - } - - return LDAP_SUCCESS; -} - -static int -replace_values( - Entry *e, - Modification *mod, - char *dn -) -{ - (void) attr_delete( &e->e_attrs, mod->sm_desc ); - - if ( mod->sm_bvalues ) { - return add_values( e, mod, dn ); - } - - return LDAP_SUCCESS; -} diff --git a/servers/slapd/back-ldbm/modify.c b/servers/slapd/back-ldbm/modify.c index 8753991485..c7978238a2 100644 --- a/servers/slapd/back-ldbm/modify.c +++ b/servers/slapd/back-ldbm/modify.c @@ -17,10 +17,6 @@ #include "back-ldbm.h" #include "proto-back-ldbm.h" -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 * and there and of course the likelihood of bugs increases. @@ -71,10 +67,8 @@ int ldbm_modify_internal( Debug(LDAP_DEBUG_ARGS, "ldbm_modify_internal: add\n", 0, 0, 0); #endif - rc = add_values( e, mod, op->o_ndn.bv_val ); - + rc = modify_add_values( e, mod, text, textbuf, textlen ); if( rc != LDAP_SUCCESS ) { - *text = "modify: add values failed"; #ifdef NEW_LOGGING LDAP_LOG(( "backend", LDAP_LEVEL_INFO, "ldbm_modify_internal: failed %d (%s)\n", @@ -94,10 +88,9 @@ int ldbm_modify_internal( Debug(LDAP_DEBUG_ARGS, "ldbm_modify_internal: delete\n", 0, 0, 0); #endif - rc = delete_values( e, mod, op->o_ndn.bv_val ); + rc = modify_delete_values( e, mod, text, textbuf, textlen ); assert( rc != LDAP_TYPE_OR_VALUE_EXISTS ); if( rc != LDAP_SUCCESS ) { - *text = "modify: delete values failed"; #ifdef NEW_LOGGING LDAP_LOG(( "backend", LDAP_LEVEL_INFO, "ldbm_modify_internal: failed %d (%s)\n", rc, *text )); @@ -116,10 +109,9 @@ int ldbm_modify_internal( Debug(LDAP_DEBUG_ARGS, "ldbm_modify_internal: replace\n", 0, 0, 0); #endif - rc = replace_values( e, mod, op->o_ndn.bv_val ); + rc = modify_replace_values( e, mod, text, textbuf, textlen ); assert( rc != LDAP_TYPE_OR_VALUE_EXISTS ); if( rc != LDAP_SUCCESS ) { - *text = "modify: replace values failed"; #ifdef NEW_LOGGING LDAP_LOG(( "backend", LDAP_LEVEL_INFO, "ldbm_modify_internal: failed %d (%s)\n", rc, *text )); @@ -127,7 +119,6 @@ int ldbm_modify_internal( Debug(LDAP_DEBUG_ARGS, "ldbm_modify_internal: %d %s\n", rc, *text, 0); #endif - } break; @@ -143,14 +134,13 @@ int ldbm_modify_internal( * We need to add index if necessary. */ mod->sm_op = LDAP_MOD_ADD; - rc = add_values( e, mod, op->o_ndn.bv_val ); + rc = modify_add_values( e, mod, text, textbuf, textlen ); if ( rc == LDAP_TYPE_OR_VALUE_EXISTS ) { rc = LDAP_SUCCESS; } if( rc != LDAP_SUCCESS ) { - *text = "modify: (soft)add values failed"; #ifdef NEW_LOGGING LDAP_LOG(( "backend", LDAP_LEVEL_INFO, "ldbm_modify_internal: failed %d (%s)\n", rc, *text )); @@ -158,7 +148,6 @@ int ldbm_modify_internal( Debug(LDAP_DEBUG_ARGS, "ldbm_modify_internal: %d %s\n", rc, *text, 0); #endif - } break; @@ -180,7 +169,6 @@ int ldbm_modify_internal( Debug(LDAP_DEBUG_ARGS, "ldbm_modify_internal: %d %s\n", rc, *text, 0); #endif - } if ( rc != LDAP_SUCCESS ) { @@ -388,208 +376,3 @@ error_return:; cache_return_entry_w( &li->li_cache, e ); return( -1 ); } - -static int -add_values( - Entry *e, - Modification *mod, - char *dn -) -{ - int i; - Attribute *a; - - /* char *desc = mod->sm_desc->ad_cname.bv_val; */ - MatchingRule *mr = mod->sm_desc->ad_type->sat_equality; - - a = attr_find( e->e_attrs, mod->sm_desc ); - - /* check if the values we're adding already exist */ - if ( a != NULL ) { - if( mr == NULL || !mr->smr_match ) { - /* do not allow add of additional attribute - if no equality rule exists */ - return LDAP_INAPPROPRIATE_MATCHING; - } - - for ( i = 0; mod->sm_bvalues[i].bv_val != NULL; i++ ) { - int rc; - int j; - const char *text = NULL; - struct berval asserted; - - rc = value_normalize( mod->sm_desc, - SLAP_MR_EQUALITY, - &mod->sm_bvalues[i], - &asserted, - &text ); - - if( rc != LDAP_SUCCESS ) return rc; - - for ( j = 0; a->a_vals[j].bv_val != NULL; j++ ) { - int match; - int rc = value_match( &match, mod->sm_desc, mr, - SLAP_MR_VALUE_SYNTAX_MATCH, - &a->a_vals[j], &asserted, &text ); - - if( rc == LDAP_SUCCESS && match == 0 ) { - free( asserted.bv_val ); - return LDAP_TYPE_OR_VALUE_EXISTS; - } - } - - free( asserted.bv_val ); - } - } - - /* no - add them */ - if( attr_merge( e, mod->sm_desc, mod->sm_bvalues ) != 0 ) { - /* this should return result return of attr_merge */ - return LDAP_OTHER; - } - - return LDAP_SUCCESS; -} - -static int -delete_values( - Entry *e, - Modification *mod, - char *dn -) -{ - int i, j, k, found; - Attribute *a; - char *desc = mod->sm_desc->ad_cname.bv_val; - MatchingRule *mr = mod->sm_desc->ad_type->sat_equality; - - /* delete the entire attribute */ - if ( mod->sm_bvalues == NULL ) { -#ifdef NEW_LOGGING - LDAP_LOG(( "backend", LDAP_LEVEL_ENTRY, - "delete_values: removing entire attribute %s\n", desc )); -#else - Debug( LDAP_DEBUG_ARGS, "removing entire attribute %s\n", - desc, 0, 0 ); -#endif - - return( attr_delete( &e->e_attrs, mod->sm_desc ) ? - LDAP_NO_SUCH_ATTRIBUTE : LDAP_SUCCESS ); - } - - if( mr == NULL || !mr->smr_match ) { - /* disallow specific attributes from being deleted if - no equality rule */ - return LDAP_INAPPROPRIATE_MATCHING; - } - - /* delete specific values - find the attribute first */ - if ( (a = attr_find( e->e_attrs, mod->sm_desc )) == NULL ) { -#ifdef NEW_LOGGING - LDAP_LOG(( "backend", LDAP_LEVEL_INFO, - "ldap_modify_delete: Could not find attribute %s\n", desc )); -#else - Debug( LDAP_DEBUG_ARGS, "ldap_modify_delete: " - "could not find attribute %s\n", - desc, 0, 0 ); -#endif - - return( LDAP_NO_SUCH_ATTRIBUTE ); - } - - /* find each value to delete */ - for ( i = 0; mod->sm_bvalues[i].bv_val != NULL; i++ ) { - int rc; - const char *text = NULL; - - struct berval asserted; - - rc = value_normalize( mod->sm_desc, - SLAP_MR_EQUALITY, - &mod->sm_bvalues[i], - &asserted, - &text ); - - if( rc != LDAP_SUCCESS ) return rc; - - found = 0; - for ( j = 0; a->a_vals[j].bv_val != NULL; j++ ) { - int match; - int rc = value_match( &match, mod->sm_desc, mr, - SLAP_MR_VALUE_SYNTAX_MATCH, - &a->a_vals[j], &asserted, &text ); - - if( rc == LDAP_SUCCESS && match != 0 ) { - continue; - } - - /* found a matching value */ - found = 1; - - /* delete it */ - free( a->a_vals[j].bv_val ); - for ( k = j + 1; a->a_vals[k].bv_val != NULL; k++ ) { - a->a_vals[k - 1] = a->a_vals[k]; - } - a->a_vals[k - 1].bv_val = NULL; - - break; - } - - free( asserted.bv_val ); - - /* looked through them all w/o finding it */ - if ( ! found ) { -#ifdef NEW_LOGGING - LDAP_LOG(( "backend", LDAP_LEVEL_ARGS, - "delete_values: could not find value for attr %s\n", desc )); -#else - Debug( LDAP_DEBUG_ARGS, - "ldbm_modify_delete: could not find value for attr %s\n", - desc, 0, 0 ); -#endif - - return LDAP_NO_SUCH_ATTRIBUTE; - } - } - - /* if no values remain, delete the entire attribute */ - if ( a->a_vals[0].bv_val == NULL ) { -#ifdef NEW_LOGGING - LDAP_LOG(( "backend", LDAP_LEVEL_ENTRY, - "delete_values: removing entire attribute %s\n", desc )); -#else - Debug( LDAP_DEBUG_ARGS, - "removing entire attribute %s\n", - desc, 0, 0 ); -#endif - - if ( attr_delete( &e->e_attrs, mod->sm_desc ) ) { - return LDAP_NO_SUCH_ATTRIBUTE; - } - } - - return LDAP_SUCCESS; -} - -static int -replace_values( - Entry *e, - Modification *mod, - char *dn -) -{ - int rc = attr_delete( &e->e_attrs, mod->sm_desc ); - - if( rc != LDAP_SUCCESS && rc != LDAP_NO_SUCH_ATTRIBUTE ) { - return rc; - } - - if ( mod->sm_bvalues != NULL && - attr_merge( e, mod->sm_desc, mod->sm_bvalues ) != 0 ) - { - return LDAP_OTHER; - } - - return LDAP_SUCCESS; -} diff --git a/servers/slapd/mods.c b/servers/slapd/mods.c index 581f8a694e..203524666a 100644 --- a/servers/slapd/mods.c +++ b/servers/slapd/mods.c @@ -18,6 +18,260 @@ #include "slap.h" +int +modify_add_values( + Entry *e, + Modification *mod, + const char **text, + char *textbuf, size_t textlen +) +{ + int i, j; + Attribute *a; + MatchingRule *mr = mod->sm_desc->ad_type->sat_equality; + const char *op; + + switch( mod->sm_op ) { + case LDAP_MOD_ADD: + op = "add"; + break; + case LDAP_MOD_REPLACE: + op = "replace"; + break; + default: + op = "?"; + assert( 0 ); + } + + a = attr_find( e->e_attrs, mod->sm_desc ); + + /* check if the values we're adding already exist */ + if( mr == NULL || !mr->smr_match ) { + if ( a != NULL ) { + /* do not allow add of additional attribute + if no equality rule exists */ + *text = textbuf; + snprintf( textbuf, textlen, + "modify/%s: %s: no equality matching rule", + op, mod->sm_desc->ad_cname.bv_val ); + return LDAP_INAPPROPRIATE_MATCHING; + } + + for ( i = 0; mod->sm_bvalues[i].bv_val != NULL; i++ ) { + /* test asserted values against existing values */ + if( a ) { + for( j = 0; a->a_vals[j].bv_val != NULL; j++ ) { + int rc = ber_bvcmp( &mod->sm_bvalues[i], + &a->a_vals[j] ); + + if( rc == 0 ) { + /* value exists already */ + *text = textbuf; + snprintf( textbuf, textlen, + "modify/%s: %s: value #%i already exists", + op, mod->sm_desc->ad_cname.bv_val ); + return LDAP_TYPE_OR_VALUE_EXISTS; + } + } + } + + /* test asserted values against themselves */ + for( j = 0; j < i; j++ ) { + int rc = ber_bvcmp( &mod->sm_bvalues[i], + &mod->sm_bvalues[j] ); + + if( rc == 0 ) { + /* value exists already */ + *text = textbuf; + snprintf( textbuf, textlen, + "modify/%s: %s: value #%i already exists", + op, mod->sm_desc->ad_cname.bv_val ); + return LDAP_TYPE_OR_VALUE_EXISTS; + } + } + } + + } else { + for ( i = 0; mod->sm_bvalues[i].bv_val != NULL; i++ ) { + int rc, match; + struct berval asserted; + + rc = value_normalize( mod->sm_desc, + SLAP_MR_EQUALITY, + &mod->sm_bvalues[i], + &asserted, + text ); + + if( rc != LDAP_SUCCESS ) return rc; + + if( a ) { + for ( j = 0; a->a_vals[j].bv_val != NULL; j++ ) { + int rc = value_match( &match, mod->sm_desc, mr, + SLAP_MR_VALUE_SYNTAX_MATCH, + &a->a_vals[j], &asserted, text ); + + if( rc == LDAP_SUCCESS && match == 0 ) { + free( asserted.bv_val ); + return LDAP_TYPE_OR_VALUE_EXISTS; + } + } + } + + for ( j = 0; j < i; j++ ) { + int rc = value_match( &match, mod->sm_desc, mr, + SLAP_MR_VALUE_SYNTAX_MATCH, + &mod->sm_bvalues[j], &asserted, text ); + + if( rc == LDAP_SUCCESS && match == 0 ) { + free( asserted.bv_val ); + return LDAP_TYPE_OR_VALUE_EXISTS; + } + } + + free( asserted.bv_val ); + } + } + + /* no - add them */ + if( attr_merge( e, mod->sm_desc, mod->sm_bvalues ) != 0 ) { + /* this should return result of attr_merge */ + *text = textbuf; + snprintf( textbuf, textlen, + "modify/%s: %s: merge error", + op, mod->sm_desc->ad_cname.bv_val ); + return LDAP_OTHER; + } + + return LDAP_SUCCESS; +} + +int +modify_delete_values( + Entry *e, + Modification *mod, + const char **text, + char *textbuf, size_t textlen +) +{ + int i, j, k, found; + Attribute *a; + char *desc = mod->sm_desc->ad_cname.bv_val; + MatchingRule *mr = mod->sm_desc->ad_type->sat_equality; + + /* delete the entire attribute */ + if ( mod->sm_bvalues == NULL ) { + int rc = attr_delete( &e->e_attrs, mod->sm_desc ); + + if( rc != LDAP_SUCCESS ) { + *text = textbuf; + snprintf( textbuf, textlen, + "modify/delete: %s: no such attribute", + mod->sm_desc->ad_cname.bv_val ); + rc = LDAP_NO_SUCH_ATTRIBUTE; + } + return rc; + } + + if( mr == NULL || !mr->smr_match ) { + /* disallow specific attributes from being deleted if + no equality rule */ + *text = textbuf; + snprintf( textbuf, textlen, + "modify/delete: %s: no equality matching rule", + mod->sm_desc->ad_cname.bv_val ); + return LDAP_INAPPROPRIATE_MATCHING; + } + + /* delete specific values - find the attribute first */ + if ( (a = attr_find( e->e_attrs, mod->sm_desc )) == NULL ) { + *text = textbuf; + snprintf( textbuf, textlen, + "modify/delete: %s: no such attribute", + mod->sm_desc->ad_cname.bv_val ); + return LDAP_NO_SUCH_ATTRIBUTE; + } + + /* find each value to delete */ + for ( i = 0; mod->sm_bvalues[i].bv_val != NULL; i++ ) { + int rc; + struct berval asserted; + + rc = value_normalize( mod->sm_desc, + SLAP_MR_EQUALITY, + &mod->sm_bvalues[i], + &asserted, + text ); + + if( rc != LDAP_SUCCESS ) return rc; + + found = 0; + for ( j = 0; a->a_vals[j].bv_val != NULL; j++ ) { + int match; + int rc = value_match( &match, mod->sm_desc, mr, + SLAP_MR_VALUE_SYNTAX_MATCH, + &a->a_vals[j], &asserted, text ); + + if( rc == LDAP_SUCCESS && match != 0 ) { + continue; + } + + /* found a matching value */ + found = 1; + + /* delete it */ + free( a->a_vals[j].bv_val ); + for ( k = j + 1; a->a_vals[k].bv_val != NULL; k++ ) { + a->a_vals[k - 1] = a->a_vals[k]; + } + a->a_vals[k - 1].bv_val = NULL; + a->a_vals[k - 1].bv_len = 0; + + break; + } + + free( asserted.bv_val ); + + /* looked through them all w/o finding it */ + if ( ! found ) { + *text = textbuf; + snprintf( textbuf, textlen, + "modify/delete: %s: no such value", + mod->sm_desc->ad_cname.bv_val ); + return LDAP_NO_SUCH_ATTRIBUTE; + } + } + + /* if no values remain, delete the entire attribute */ + if ( a->a_vals[0].bv_val == NULL ) { + if ( attr_delete( &e->e_attrs, mod->sm_desc ) ) { + *text = textbuf; + snprintf( textbuf, textlen, + "modify/delete: %s: no such attribute", + mod->sm_desc->ad_cname.bv_val ); + return LDAP_NO_SUCH_ATTRIBUTE; + } + } + + return LDAP_SUCCESS; +} + +int +modify_replace_values( + Entry *e, + Modification *mod, + const char **text, + char *textbuf, size_t textlen +) +{ + (void) attr_delete( &e->e_attrs, mod->sm_desc ); + + if ( mod->sm_bvalues ) { + return modify_add_values( e, mod, text, textbuf, textlen ); + } + + return LDAP_SUCCESS; +} + void slap_mod_free( Modification *mod, diff --git a/servers/slapd/proto-slap.h b/servers/slapd/proto-slap.h index 3c276cacdb..e278a0bd72 100644 --- a/servers/slapd/proto-slap.h +++ b/servers/slapd/proto-slap.h @@ -539,6 +539,16 @@ LDAP_SLAPD_F( int ) slap_mods_opattrs( /* * mods.c */ +LDAP_SLAPD_F( int ) modify_add_values( Entry *e, + Modification *mod, + const char **text, char *textbuf, size_t textlen ); +LDAP_SLAPD_F( int ) modify_delete_values( Entry *e, + Modification *mod, + const char **text, char *textbuf, size_t textlen ); +LDAP_SLAPD_F( int ) modify_replace_values( Entry *e, + Modification *mod, + const char **text, char *textbuf, size_t textlen ); + LDAP_SLAPD_F( void ) slap_mod_free( Modification *mod, int freeit ); LDAP_SLAPD_F( void ) slap_mods_free( Modifications *mods ); LDAP_SLAPD_F( void ) slap_modlist_free( LDAPModList *ml ); diff --git a/servers/slapd/tools/mimic.c b/servers/slapd/tools/mimic.c index 9997df12b0..3f07f66caf 100644 --- a/servers/slapd/tools/mimic.c +++ b/servers/slapd/tools/mimic.c @@ -192,11 +192,6 @@ void replog( Backend *be, Operation *op, assert(0); } -void slap_mods_free( Modifications *ml ) -{ - assert(0); -} - int add_replica_info( Backend *be, const char *host ) { return 0; -- 2.39.5