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.
19 #include <ac/string.h>
24 modify_check_duplicates(
25 AttributeDescription *ad,
31 char *textbuf, size_t textlen )
33 int i, j, numvals = 0, nummods,
34 rc = LDAP_SUCCESS, matched;
35 /* this function is no longer used */
45 char *textbuf, size_t textlen )
50 MatchingRule *mr = mod->sm_desc->ad_type->sat_equality;
53 switch( mod->sm_op ) {
57 case LDAP_MOD_REPLACE:
65 a = attr_find( e->e_attrs, mod->sm_desc );
68 * With permissive set, as long as the attribute being added
69 * has the same value(s?) as the existing attribute, then the
70 * modify will succeed.
73 /* check if the values we're adding already exist */
74 if( mr == NULL || !mr->smr_match ) {
76 /* do not allow add of additional attribute
77 if no equality rule exists */
79 snprintf( textbuf, textlen,
80 "modify/%s: %s: no equality matching rule",
81 op, mod->sm_desc->ad_cname.bv_val );
82 return LDAP_INAPPROPRIATE_MATCHING;
85 for ( i = 0; mod->sm_bvalues[i].bv_val != NULL; i++ ) {
86 /* test asserted values against existing values */
88 for( matched = 0, j = 0; a->a_vals[j].bv_val != NULL; j++ ) {
89 if ( bvmatch( &mod->sm_bvalues[i], &a->a_vals[j] ) ) {
94 /* value exists already */
96 snprintf( textbuf, textlen,
97 "modify/%s: %s: value #%i already exists",
98 op, mod->sm_desc->ad_cname.bv_val, j );
99 return LDAP_TYPE_OR_VALUE_EXISTS;
102 if ( permissive && matched == j ) {
103 /* values already exist; do nothing */
108 /* test asserted values against themselves */
109 for( j = 0; j < i; j++ ) {
110 if ( bvmatch( &mod->sm_bvalues[i], &mod->sm_bvalues[j] ) ) {
111 /* value exists already */
113 snprintf( textbuf, textlen,
114 "modify/%s: %s: value #%i already exists",
115 op, mod->sm_desc->ad_cname.bv_val, j );
116 return LDAP_TYPE_OR_VALUE_EXISTS;
122 /* no normalization is done in this routine nor
123 * in the matching routines called by this routine.
124 * values are now normalized once on input to the
125 * server (whether from LDAP or from the underlying
127 * This should outperform the old code. No numbers
133 if ( mod->sm_bvalues[1].bv_val == 0 ) {
137 for ( matched = 0, i = 0; a->a_vals[ i ].bv_val; i++ ) {
140 if( mod->sm_nvalues ) {
141 rc = value_match( &match, mod->sm_desc, mr,
143 | SLAP_MR_VALUE_OF_ASSERTION_SYNTAX
144 | SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH
145 | SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH,
151 rc = value_match( &match, mod->sm_desc, mr,
153 | SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX,
160 if( rc == LDAP_SUCCESS && match == 0 ) {
166 snprintf( textbuf, textlen,
167 "modify/%s: %s: value #0 already exists",
168 op, mod->sm_desc->ad_cname.bv_val );
169 return LDAP_TYPE_OR_VALUE_EXISTS;
172 if ( permissive && matched == i ) {
173 /* values already exist; do nothing */
179 rc = modify_check_duplicates( mod->sm_desc, mr,
180 a ? a->a_vals : NULL, mod->sm_bvalues,
181 permissive, text, textbuf, textlen );
183 if ( permissive && rc == LDAP_TYPE_OR_VALUE_EXISTS ) {
187 if ( rc != LDAP_SUCCESS ) {
194 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;
222 * If permissive is set, then the non-existence of an
223 * attribute is not treated as an error.
226 /* delete the entire attribute */
227 if ( mod->sm_bvalues == NULL ) {
228 rc = attr_delete( &e->e_attrs, mod->sm_desc );
232 } else if( rc != LDAP_SUCCESS ) {
234 snprintf( textbuf, textlen,
235 "modify/delete: %s: no such attribute",
236 mod->sm_desc->ad_cname.bv_val );
237 rc = LDAP_NO_SUCH_ATTRIBUTE;
242 if( mr == NULL || !mr->smr_match ) {
243 /* disallow specific attributes from being deleted if
246 snprintf( textbuf, textlen,
247 "modify/delete: %s: no equality matching rule",
248 mod->sm_desc->ad_cname.bv_val );
249 return LDAP_INAPPROPRIATE_MATCHING;
252 /* delete specific values - find the attribute first */
253 if ( (a = attr_find( e->e_attrs, mod->sm_desc )) == NULL ) {
258 snprintf( textbuf, textlen,
259 "modify/delete: %s: no such attribute",
260 mod->sm_desc->ad_cname.bv_val );
261 return LDAP_NO_SUCH_ATTRIBUTE;
265 for ( i = 0; mod->sm_values[i].bv_val != NULL; i++ ) {
267 for ( j = 0; a->a_vals[j].bv_val != NULL; j++ ) {
269 if( mod->sm_nvalues ) {
270 assert( a->a_nvals );
271 rc = (*mr->smr_match)( &match,
272 SLAP_MR_VALUE_OF_ASSERTION_SYNTAX
273 | SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH
274 | SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH,
275 a->a_desc->ad_type->sat_syntax,
277 &mod->sm_nvalues[i] );
280 assert( a->a_nvals == NULL );
282 rc = (*mr->smr_match)( &match,
283 SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX,
284 a->a_desc->ad_type->sat_syntax,
286 &mod->sm_values[i] );
289 if ( rc != LDAP_SUCCESS ) {
291 snprintf( textbuf, textlen,
292 "%s: matching rule failed",
293 mod->sm_desc->ad_cname.bv_val );
303 /* delete value and mark it as dummy */
304 free( a->a_vals[j].bv_val );
305 a->a_vals[j].bv_val = &dummy;
306 if( a->a_nvals != a->a_vals ) {
307 free( a->a_nvals[j].bv_val );
308 a->a_nvals[j].bv_val = &dummy;
316 snprintf( textbuf, textlen,
317 "modify/delete: %s: no such value",
318 mod->sm_desc->ad_cname.bv_val );
319 rc = LDAP_NO_SUCH_ATTRIBUTE;
324 /* compact array skipping dummies */
325 for ( k = 0, j = 0; a->a_vals[k].bv_val != NULL; k++ ) {
327 if( a->a_vals[k].bv_val == &dummy ) {
328 assert( a->a_nvals == NULL || a->a_nvals[k].bv_val == &dummy );
332 a->a_vals[ j ] = a->a_vals[ k ];
333 if (a->a_nvals != a->a_vals) {
334 a->a_nvals[ j ] = a->a_nvals[ k ];
341 a->a_vals[j].bv_val = NULL;
342 if (a->a_nvals != a->a_vals) a->a_nvals[j].bv_val = NULL;
344 /* if no values remain, delete the entire attribute */
345 if ( a->a_vals[0].bv_val == NULL ) {
346 if ( attr_delete( &e->e_attrs, mod->sm_desc ) ) {
348 snprintf( textbuf, textlen,
349 "modify/delete: %s: no such attribute",
350 mod->sm_desc->ad_cname.bv_val );
351 rc = LDAP_NO_SUCH_ATTRIBUTE;
361 modify_replace_values(
366 char *textbuf, size_t textlen )
368 (void) attr_delete( &e->e_attrs, mod->sm_desc );
370 if ( mod->sm_bvalues ) {
371 return modify_add_values( e, mod, permissive, text, textbuf, textlen );
378 modify_increment_values(
383 char *textbuf, size_t textlen )
387 a = attr_find( e->e_attrs, mod->sm_desc );
390 snprintf( textbuf, textlen,
391 "modify/increment: %s: no such attribute",
392 mod->sm_desc->ad_cname.bv_val );
393 return LDAP_NO_SUCH_ATTRIBUTE;
397 if ( !strcmp( a->a_desc->ad_type->sat_syntax_oid, SLAPD_INTEGER_SYNTAX )) {
399 char str[sizeof(long)*3 + 2]; /* overly long */
400 long incr = atol( mod->sm_bvalues[0].bv_val );
402 /* treat zero and errors as a no-op */
407 for( i=0; a->a_nvals[i].bv_val != NULL; i++ ) {
409 long value = atol( a->a_nvals[i].bv_val );
410 size_t strln = snprintf( str, sizeof(str), "%ld", value+incr );
412 tmp = SLAP_REALLOC( a->a_nvals[i].bv_val, strln+1 );
414 *text = "modify/increment: reallocation error";
417 a->a_nvals[i].bv_val = tmp;
418 a->a_nvals[i].bv_len = strln;
420 AC_MEMCPY( a->a_nvals[i].bv_val, str, strln+1 );
424 snprintf( textbuf, textlen,
425 "modify/increment: %s: increment not supported for value syntax %s",
426 mod->sm_desc->ad_cname.bv_val,
427 a->a_desc->ad_type->sat_syntax_oid );
428 return LDAP_CONSTRAINT_VIOLATION;
439 if ( mod->sm_values != NULL ) ber_bvarray_free( mod->sm_values );
440 mod->sm_values = NULL;
442 if ( mod->sm_nvalues != NULL ) ber_bvarray_free( mod->sm_nvalues );
443 mod->sm_nvalues = NULL;
445 if( freeit ) free( mod );
454 for ( ; ml != NULL; ml = next ) {
457 slap_mod_free( &ml->sml_mod, 0 );