2 * Copyright 1998-2003 The OpenLDAP Foundation, All Rights Reserved.
3 * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
6 * Copyright (c) 1995 Regents of the University of Michigan.
9 * Redistribution and use in source and binary forms are permitted
10 * provided that this notice is preserved and that due credit is given
11 * to the University of Michigan at Ann Arbor. The name of the University
12 * may not be used to endorse or promote products derived from this
13 * software without specific prior written permission. This software
14 * is provided ``as is'' without express or implied warranty.
22 modify_check_duplicates(
23 AttributeDescription *ad,
29 char *textbuf, size_t textlen )
31 int i, j, numvals = 0, nummods,
32 rc = LDAP_SUCCESS, matched;
33 /* this function is no longer used */
43 char *textbuf, size_t textlen
49 MatchingRule *mr = mod->sm_desc->ad_type->sat_equality;
52 switch( mod->sm_op ) {
56 case LDAP_MOD_REPLACE:
64 a = attr_find( e->e_attrs, mod->sm_desc );
67 * With permissive set, as long as the attribute being added
68 * has the same value(s?) as the existing attribute, then the
69 * modify will succeed.
72 /* check if the values we're adding already exist */
73 if( mr == NULL || !mr->smr_match ) {
75 /* do not allow add of additional attribute
76 if no equality rule exists */
78 snprintf( textbuf, textlen,
79 "modify/%s: %s: no equality matching rule",
80 op, mod->sm_desc->ad_cname.bv_val );
81 return LDAP_INAPPROPRIATE_MATCHING;
84 for ( i = 0; mod->sm_bvalues[i].bv_val != NULL; i++ ) {
85 /* test asserted values against existing values */
87 for( matched = 0, j = 0; a->a_vals[j].bv_val != NULL; j++ ) {
88 if ( bvmatch( &mod->sm_bvalues[i], &a->a_vals[j] ) ) {
93 /* value exists already */
95 snprintf( textbuf, textlen,
96 "modify/%s: %s: value #%i already exists",
97 op, mod->sm_desc->ad_cname.bv_val, j );
98 return LDAP_TYPE_OR_VALUE_EXISTS;
101 if ( permissive && matched == j ) {
102 /* values already exist; do nothing */
107 /* test asserted values against themselves */
108 for( j = 0; j < i; j++ ) {
109 if ( bvmatch( &mod->sm_bvalues[i], &mod->sm_bvalues[j] ) ) {
110 /* value exists already */
112 snprintf( textbuf, textlen,
113 "modify/%s: %s: value #%i already exists",
114 op, mod->sm_desc->ad_cname.bv_val, j );
115 return LDAP_TYPE_OR_VALUE_EXISTS;
121 /* no normalization is done in this routine nor
122 * in the matching routines called by this routine.
123 * values are now normalized once on input to the
124 * server (whether from LDAP or from the underlying
126 * This should outperform the old code. No numbers
132 if ( mod->sm_bvalues[1].bv_val == 0 ) {
136 for ( matched = 0, i = 0; a->a_vals[ i ].bv_val; i++ ) {
139 if( mod->sm_nvalues ) {
140 rc = value_match( &match, mod->sm_desc, mr,
142 | SLAP_MR_VALUE_OF_ASSERTION_SYNTAX
143 | SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH
144 | SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH,
150 rc = value_match( &match, mod->sm_desc, mr,
152 | SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX,
159 if( rc == LDAP_SUCCESS && match == 0 ) {
165 snprintf( textbuf, textlen,
166 "modify/%s: %s: value #0 already exists",
167 op, mod->sm_desc->ad_cname.bv_val, 0 );
168 return LDAP_TYPE_OR_VALUE_EXISTS;
171 if ( permissive && matched == i ) {
172 /* values already exist; do nothing */
178 rc = modify_check_duplicates( mod->sm_desc, mr,
179 a ? a->a_vals : NULL, mod->sm_bvalues,
180 permissive, text, textbuf, textlen );
182 if ( permissive && rc == LDAP_TYPE_OR_VALUE_EXISTS ) {
186 if ( rc != LDAP_SUCCESS ) {
193 if( attr_merge( e, mod->sm_desc, mod->sm_values, mod->sm_nvalues ) != 0 )
195 /* this should return result of attr_merge */
197 snprintf( textbuf, textlen,
198 "modify/%s: %s: merge error",
199 op, mod->sm_desc->ad_cname.bv_val );
207 modify_delete_values(
212 char *textbuf, size_t textlen
215 int i, j, k, rc = LDAP_SUCCESS;
217 MatchingRule *mr = mod->sm_desc->ad_type->sat_equality;
221 * If permissive is set, then the non-existence of an
222 * attribute is not treated as an error.
225 /* delete the entire attribute */
226 if ( mod->sm_bvalues == NULL ) {
227 rc = attr_delete( &e->e_attrs, mod->sm_desc );
231 } else if( rc != LDAP_SUCCESS ) {
233 snprintf( textbuf, textlen,
234 "modify/delete: %s: no such attribute",
235 mod->sm_desc->ad_cname.bv_val );
236 rc = LDAP_NO_SUCH_ATTRIBUTE;
241 if( mr == NULL || !mr->smr_match ) {
242 /* disallow specific attributes from being deleted if
245 snprintf( textbuf, textlen,
246 "modify/delete: %s: no equality matching rule",
247 mod->sm_desc->ad_cname.bv_val );
248 return LDAP_INAPPROPRIATE_MATCHING;
251 /* delete specific values - find the attribute first */
252 if ( (a = attr_find( e->e_attrs, mod->sm_desc )) == NULL ) {
257 snprintf( textbuf, textlen,
258 "modify/delete: %s: no such attribute",
259 mod->sm_desc->ad_cname.bv_val );
260 return LDAP_NO_SUCH_ATTRIBUTE;
264 for ( i = 0; mod->sm_values[i].bv_val != NULL; i++ ) {
266 for ( j = 0; a->a_vals[j].bv_val != NULL; j++ )
270 if( mod->sm_nvalues ) {
271 assert( a->a_nvals );
272 rc = (*mr->smr_match)( &match,
273 SLAP_MR_VALUE_OF_ASSERTION_SYNTAX
274 | SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH
275 | SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH,
276 a->a_desc->ad_type->sat_syntax,
278 &mod->sm_nvalues[i] );
281 assert( a->a_nvals == NULL );
283 rc = (*mr->smr_match)( &match,
284 SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX,
285 a->a_desc->ad_type->sat_syntax,
287 &mod->sm_values[i] );
290 if ( rc != LDAP_SUCCESS ) {
292 snprintf( textbuf, textlen,
293 "%s: matching rule failed",
294 mod->sm_desc->ad_cname.bv_val );
304 /* delete value and mark it as dummy */
305 free( a->a_vals[j].bv_val );
306 a->a_vals[j].bv_val = &dummy;
307 if( a->a_nvals != a->a_vals ) {
308 free( a->a_nvals[j].bv_val );
309 a->a_nvals[j].bv_val = &dummy;
318 snprintf( textbuf, textlen,
319 "modify/delete: %s: no such value",
320 mod->sm_desc->ad_cname.bv_val );
321 rc = LDAP_NO_SUCH_ATTRIBUTE;
326 /* compact array skipping dummies */
327 for ( k = 0, j = 0; a->a_vals[k].bv_val != NULL; k++ )
330 if( a->a_vals[k].bv_val == &dummy ) {
331 assert( a->a_nvals == NULL || a->a_nvals[k].bv_val == &dummy );
335 a->a_vals[ j ] = a->a_vals[ k ];
336 if (a->a_nvals != a->a_vals) {
337 a->a_nvals[ j ] = a->a_nvals[ k ];
344 a->a_vals[j].bv_val = NULL;
345 if (a->a_nvals != a->a_vals) a->a_nvals[j].bv_val = NULL;
347 /* if no values remain, delete the entire attribute */
348 if ( a->a_vals[0].bv_val == NULL ) {
349 if ( attr_delete( &e->e_attrs, mod->sm_desc ) ) {
351 snprintf( textbuf, textlen,
352 "modify/delete: %s: no such attribute",
353 mod->sm_desc->ad_cname.bv_val );
354 rc = LDAP_NO_SUCH_ATTRIBUTE;
364 modify_replace_values(
369 char *textbuf, size_t textlen
372 (void) attr_delete( &e->e_attrs, mod->sm_desc );
374 if ( mod->sm_bvalues ) {
375 return modify_add_values( e, mod, permissive, text, textbuf, textlen );
387 if ( mod->sm_values != NULL ) ber_bvarray_free( mod->sm_values );
388 mod->sm_values = NULL;
390 if ( mod->sm_nvalues != NULL ) ber_bvarray_free( mod->sm_nvalues );
391 mod->sm_nvalues = NULL;
393 if( freeit ) free( mod );
403 for ( ; ml != NULL; ml = next ) {
406 slap_mod_free( &ml->sml_mod, 0 );