modify.c 12.6 KB
Newer Older
Kurt Zeilenga's avatar
Kurt Zeilenga committed
1
/* modify.c - ldbm backend modify routine */
2
/* $OpenLDAP$ */
Kurt Zeilenga's avatar
Kurt Zeilenga committed
3
/*
Kurt Zeilenga's avatar
Kurt Zeilenga committed
4
 * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved.
Kurt Zeilenga's avatar
Kurt Zeilenga committed
5
6
 * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
 */
Kurt Zeilenga's avatar
Kurt Zeilenga committed
7

Kurt Zeilenga's avatar
Kurt Zeilenga committed
8
9
#include "portable.h"

Kurt Zeilenga's avatar
Kurt Zeilenga committed
10
#include <stdio.h>
Kurt Zeilenga's avatar
Kurt Zeilenga committed
11
12
13

#include <ac/string.h>
#include <ac/socket.h>
Kurt Zeilenga's avatar
Kurt Zeilenga committed
14
#include <ac/time.h>
Kurt Zeilenga's avatar
Kurt Zeilenga committed
15

Kurt Zeilenga's avatar
Kurt Zeilenga committed
16
17
#include "slap.h"
#include "back-ldbm.h"
18
#include "proto-back-ldbm.h"
Kurt Zeilenga's avatar
Kurt Zeilenga committed
19

20
21
22
23
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 ));

24
25
26
27
28
29
/* 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.
 * Juan C. Gomez (gomez@engr.sgi.com) 05/18/99
 */ 

30
int ldbm_modify_internal(
Kurt Zeilenga's avatar
Kurt Zeilenga committed
31
32
33
    Backend	*be,
    Connection	*conn,
    Operation	*op,
Kurt Zeilenga's avatar
Kurt Zeilenga committed
34
    const char	*dn,
35
    Modifications	*modlist,
36
    Entry	*e,
37
38
39
	const char **text,
	char *textbuf,
	size_t textlen
Kurt Zeilenga's avatar
Kurt Zeilenga committed
40
41
)
{
Kurt Zeilenga's avatar
Kurt Zeilenga committed
42
	int rc, err;
43
	Modification	*mod;
44
	Modifications	*ml;
45
	Attribute	*save_attrs;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
46

Gary Williams's avatar
Gary Williams committed
47
48
#ifdef NEW_LOGGING
	LDAP_LOG(( "backend", LDAP_LEVEL_ENTRY,
49
		"ldbm_modify_internal: %s\n", dn ));
Gary Williams's avatar
Gary Williams committed
50
#else
51
	Debug(LDAP_DEBUG_TRACE, "ldbm_modify_internal: %s\n", dn, 0, 0);
Gary Williams's avatar
Gary Williams committed
52
53
#endif

Kurt Zeilenga's avatar
Kurt Zeilenga committed
54

55
	if ( !acl_check_modlist( be, conn, op, e, modlist )) {
56
		return LDAP_INSUFFICIENT_ACCESS;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
57
58
	}

59
60
	save_attrs = e->e_attrs;
	e->e_attrs = attrs_dup( e->e_attrs );
61

62
63
	for ( ml = modlist; ml != NULL; ml = ml->sml_next ) {
		mod = &ml->sml_mod;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
64

65
		switch ( mod->sm_op ) {
Kurt Zeilenga's avatar
Kurt Zeilenga committed
66
		case LDAP_MOD_ADD:
Gary Williams's avatar
Gary Williams committed
67
68
#ifdef NEW_LOGGING
			LDAP_LOG(( "backend", LDAP_LEVEL_DETAIL1,
69
				"ldbm_modify_internal: add\n" ));
Gary Williams's avatar
Gary Williams committed
70
#else
Kurt Zeilenga's avatar
Kurt Zeilenga committed
71
			Debug(LDAP_DEBUG_ARGS, "ldbm_modify_internal: add\n", 0, 0, 0);
Gary Williams's avatar
Gary Williams committed
72
73
#endif

74
			err = add_values( e, mod, op->o_ndn.bv_val );
75
76

			if( err != LDAP_SUCCESS ) {
Gary Williams's avatar
Gary Williams committed
77
78
79
				*text = "modify: add values failed";
#ifdef NEW_LOGGING
				LDAP_LOG(( "backend", LDAP_LEVEL_INFO,
80
81
					"ldbm_modify_internal: failed %d (%s)\n",
					err, *text ));
Gary Williams's avatar
Gary Williams committed
82
#else
83
				Debug(LDAP_DEBUG_ARGS, "ldbm_modify_internal: %d %s\n",
84
					err, *text, 0);
Gary Williams's avatar
Gary Williams committed
85
#endif
86
			}
Kurt Zeilenga's avatar
Kurt Zeilenga committed
87
88
89
			break;

		case LDAP_MOD_DELETE:
Gary Williams's avatar
Gary Williams committed
90
91
#ifdef NEW_LOGGING
			LDAP_LOG(( "backend", LDAP_LEVEL_DETAIL1,
92
				"ldbm_modify_internal: delete\n" ));
Gary Williams's avatar
Gary Williams committed
93
#else
Kurt Zeilenga's avatar
Kurt Zeilenga committed
94
			Debug(LDAP_DEBUG_ARGS, "ldbm_modify_internal: delete\n", 0, 0, 0);
Gary Williams's avatar
Gary Williams committed
95
96
#endif

97
			err = delete_values( e, mod, op->o_ndn.bv_val );
98
99
			assert( err != LDAP_TYPE_OR_VALUE_EXISTS );
			if( err != LDAP_SUCCESS ) {
Gary Williams's avatar
Gary Williams committed
100
101
102
				*text = "modify: delete values failed";
#ifdef NEW_LOGGING
				LDAP_LOG(( "backend", LDAP_LEVEL_INFO,
103
					"ldbm_modify_internal: failed %d (%s)\n", err, *text ));
Gary Williams's avatar
Gary Williams committed
104
#else
105
				Debug(LDAP_DEBUG_ARGS, "ldbm_modify_internal: %d %s\n",
106
					err, *text, 0);
Gary Williams's avatar
Gary Williams committed
107
#endif
108
			}
Kurt Zeilenga's avatar
Kurt Zeilenga committed
109
110
111
			break;

		case LDAP_MOD_REPLACE:
Gary Williams's avatar
Gary Williams committed
112
113
#ifdef NEW_LOGGING
			LDAP_LOG(( "backend", LDAP_LEVEL_DETAIL1,
114
				"ldbm_modify_internal:  replace\n" ));
Gary Williams's avatar
Gary Williams committed
115
#else
Kurt Zeilenga's avatar
Kurt Zeilenga committed
116
			Debug(LDAP_DEBUG_ARGS, "ldbm_modify_internal: replace\n", 0, 0, 0);
Gary Williams's avatar
Gary Williams committed
117
118
#endif

119
			err = replace_values( e, mod, op->o_ndn.bv_val );
120
121
			assert( err != LDAP_TYPE_OR_VALUE_EXISTS );
			if( err != LDAP_SUCCESS ) {
Gary Williams's avatar
Gary Williams committed
122
123
124
				*text = "modify: replace values failed";
#ifdef NEW_LOGGING
				LDAP_LOG(( "backend", LDAP_LEVEL_INFO,
125
					"ldbm_modify_internal: failed %d (%s)\n", err, *text ));
Gary Williams's avatar
Gary Williams committed
126
#else
127
				Debug(LDAP_DEBUG_ARGS, "ldbm_modify_internal: %d %s\n",
128
					err, *text, 0);
Gary Williams's avatar
Gary Williams committed
129
130
#endif

131
			}
Kurt Zeilenga's avatar
Kurt Zeilenga committed
132
			break;
133

134
		case SLAP_MOD_SOFTADD:
Gary Williams's avatar
Gary Williams committed
135
136
#ifdef NEW_LOGGING
			LDAP_LOG(( "backend", LDAP_LEVEL_DETAIL1,
137
				"ldbm_modify_internal: softadd\n" ));
Gary Williams's avatar
Gary Williams committed
138
#else
Kurt Zeilenga's avatar
Kurt Zeilenga committed
139
			Debug(LDAP_DEBUG_ARGS, "ldbm_modify_internal: softadd\n", 0, 0, 0);
Gary Williams's avatar
Gary Williams committed
140
141
142
143
144
145
#endif

			/* Avoid problems in index_add_mods()
			 * We need to add index if necessary.
			 */
			mod->sm_op = LDAP_MOD_ADD;
146
			err = add_values( e, mod, op->o_ndn.bv_val );
147

Gary Williams's avatar
Gary Williams committed
148
149
150
			if ( err == LDAP_TYPE_OR_VALUE_EXISTS ) {
				err = LDAP_SUCCESS;
			}
151
152

			if( err != LDAP_SUCCESS ) {
Gary Williams's avatar
Gary Williams committed
153
154
155
156
157
				*text = "modify: (soft)add values failed";
#ifdef NEW_LOGGING
				LDAP_LOG(( "backend", LDAP_LEVEL_INFO,
					   "ldbm_modify_internal: failed %d (%s)\n", err, *text ));
#else
158
				Debug(LDAP_DEBUG_ARGS, "ldbm_modify_internal: %d %s\n",
159
					err, *text, 0);
Gary Williams's avatar
Gary Williams committed
160
161
#endif

162
			}
Gary Williams's avatar
Gary Williams committed
163
			break;
164
165

		default:
Gary Williams's avatar
Gary Williams committed
166
167
#ifdef NEW_LOGGING
			LDAP_LOG(( "backend", LDAP_LEVEL_ERR,
168
				"ldbm_modify_internal: invalid op %d\n", mod->sm_op ));
Gary Williams's avatar
Gary Williams committed
169
#else
Kurt Zeilenga's avatar
Kurt Zeilenga committed
170
171
			Debug(LDAP_DEBUG_ANY, "ldbm_modify_internal: invalid op %d\n",
				mod->sm_op, 0, 0);
Gary Williams's avatar
Gary Williams committed
172
173
#endif

174
			err = LDAP_OTHER;
Gary Williams's avatar
Gary Williams committed
175
176
177
			*text = "Invalid modify operation";
#ifdef NEW_LOGGING
			LDAP_LOG(( "backend", LDAP_LEVEL_INFO,
178
				"ldbm_modify_internal: %d (%s)\n", err, *text ));
Gary Williams's avatar
Gary Williams committed
179
#else
180
			Debug(LDAP_DEBUG_ARGS, "ldbm_modify_internal: %d %s\n",
181
				err, *text, 0);
Gary Williams's avatar
Gary Williams committed
182
183
#endif

Kurt Zeilenga's avatar
Kurt Zeilenga committed
184
185
186
		}

		if ( err != LDAP_SUCCESS ) {
187
188
			attrs_free( e->e_attrs );
			e->e_attrs = save_attrs;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
189
			/* unlock entry, delete from cache */
190
			return err; 
Kurt Zeilenga's avatar
Kurt Zeilenga committed
191
192
193
		}
	}

194
195
196
197
198
199
	/* check for abandon */
	ldap_pvt_thread_mutex_lock( &op->o_abandonmutex );
	if ( op->o_abandon ) {
		attrs_free( e->e_attrs );
		e->e_attrs = save_attrs;
		ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex );
200
		return SLAPD_ABANDON;
201
202
203
	}
	ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex );

204
	/* check that the entry still obeys the schema */
205
	rc = entry_schema_check( e, save_attrs, text, textbuf, textlen );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
206
	if ( rc != LDAP_SUCCESS ) {
207
208
		attrs_free( e->e_attrs );
		e->e_attrs = save_attrs;
Gary Williams's avatar
Gary Williams committed
209
210
#ifdef NEW_LOGGING
		LDAP_LOG(( "backend", LDAP_LEVEL_ERR,
211
212
			"ldbm_modify_internal: entry failed schema check: %s\n",
			*text ));
Gary Williams's avatar
Gary Williams committed
213
#else
Kurt Zeilenga's avatar
Kurt Zeilenga committed
214
		Debug( LDAP_DEBUG_ANY, "entry failed schema check: %s\n",
215
			*text, 0, 0 );
Gary Williams's avatar
Gary Williams committed
216
217
#endif

Kurt Zeilenga's avatar
Kurt Zeilenga committed
218
		return rc;
219
220
	}

Kurt Zeilenga's avatar
Kurt Zeilenga committed
221
	/* check for abandon */
222
	ldap_pvt_thread_mutex_lock( &op->o_abandonmutex );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
223
	if ( op->o_abandon ) {
224
225
		attrs_free( e->e_attrs );
		e->e_attrs = save_attrs;
226
		ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex );
227
		return SLAPD_ABANDON;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
228
	}
229
	ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
230

231
232
	/* delete indices for old attributes */
	index_entry_del( be, e, save_attrs);
233

234
235
	/* add indices for new attributes */
	index_entry_add( be, e, e->e_attrs);
236

237
238
	attrs_free( save_attrs );

239
	return LDAP_SUCCESS;
240
}
241
242
243
244
245
246
247


int
ldbm_back_modify(
    Backend	*be,
    Connection	*conn,
    Operation	*op,
248
249
    struct berval	*dn,
    struct berval	*ndn,
250
    Modifications	*modlist
251
252
)
{
253
	int rc;
254
	struct ldbminfo	*li = (struct ldbminfo *) be->be_private;
255
	Entry		*matched;
256
	Entry		*e;
257
	int		manageDSAit = get_manageDSAit( op );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
258
	const char *text = NULL;
259
260
	char textbuf[SLAP_TEXT_BUFLEN];
	size_t textlen = sizeof textbuf;
261

Gary Williams's avatar
Gary Williams committed
262
263
#ifdef NEW_LOGGING
	LDAP_LOG(( "backend", LDAP_LEVEL_ENTRY,
264
		"ldbm_back_modify: enter\n" ));
Gary Williams's avatar
Gary Williams committed
265
#else
266
	Debug(LDAP_DEBUG_ARGS, "ldbm_back_modify:\n", 0, 0, 0);
Gary Williams's avatar
Gary Williams committed
267
268
#endif

269
270

	/* acquire and lock entry */
271
	if ( (e = dn2entry_w( be, ndn->bv_val, &matched )) == NULL ) {
272
		char* matched_dn = NULL;
273
		struct berval **refs;
274

275
		if ( matched != NULL ) {
276
277
			matched_dn = ch_strdup( matched->e_dn );
			refs = is_entry_referral( matched )
278
				? get_entry_referrals( be, conn, op, matched )
279
280
281
				: NULL;
			cache_return_entry_r( &li->li_cache, matched );
		} else {
282
			refs = referral_rewrite( default_referral,
283
				NULL, dn, LDAP_SCOPE_DEFAULT );
284
		}
285
286
287
288

		send_ldap_result( conn, op, LDAP_REFERRAL,
			matched_dn, NULL, refs, NULL );

289
290
		ber_bvecfree( refs );
		free( matched_dn );
291

292
293
294
		return( -1 );
	}

295
296
297
298
    if ( !manageDSAit && is_entry_referral( e ) ) {
		/* parent is a referral, don't allow add */
		/* parent is an alias, don't allow add */
		struct berval **refs = get_entry_referrals( be,
299
			conn, op, e );
300

Gary Williams's avatar
Gary Williams committed
301
302
#ifdef NEW_LOGGING
		LDAP_LOG(( "backend", LDAP_LEVEL_INFO,
303
			   "ldbm_back_modify: entry (%s) is referral\n", ndn->bv_val ));
Gary Williams's avatar
Gary Williams committed
304
#else
305
306
		Debug( LDAP_DEBUG_TRACE, "entry is referral\n", 0,
		    0, 0 );
Gary Williams's avatar
Gary Williams committed
307
308
#endif

309
310
311
312
313
314
315
316
317

		send_ldap_result( conn, op, LDAP_REFERRAL,
		    e->e_dn, NULL, refs, NULL );

		ber_bvecfree( refs );

		goto error_return;
	}
	
318
	/* Modify the entry */
319
	rc = ldbm_modify_internal( be, conn, op, ndn->bv_val, modlist, e,
320
		&text, textbuf, textlen );
321
322
323
324

	if( rc != LDAP_SUCCESS ) {
		if( rc != SLAPD_ABANDON ) {
			send_ldap_result( conn, op, rc,
Gary Williams's avatar
Gary Williams committed
325
				NULL, text, NULL, NULL );
326
327
		}

328
329
330
		goto error_return;
	}

Kurt Zeilenga's avatar
Kurt Zeilenga committed
331
332
	/* change the entry itself */
	if ( id2entry_add( be, e ) != 0 ) {
333
		send_ldap_result( conn, op, LDAP_OTHER,
Kurt Zeilenga's avatar
Kurt Zeilenga committed
334
			NULL, "id2entry failure", NULL, NULL );
335
		goto error_return;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
336
337
	}

338
339
	send_ldap_result( conn, op, LDAP_SUCCESS,
		NULL, NULL, NULL, NULL );
340

341
	cache_return_entry_w( &li->li_cache, e );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
342
	return( 0 );
343
344

error_return:;
345
	cache_return_entry_w( &li->li_cache, e );
346
	return( -1 );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
347
348
}

349
static int
Kurt Zeilenga's avatar
Kurt Zeilenga committed
350
351
add_values(
    Entry	*e,
352
    Modification	*mod,
Kurt Zeilenga's avatar
Kurt Zeilenga committed
353
354
355
356
357
358
    char	*dn
)
{
	int		i;
	Attribute	*a;

359
	/* char *desc = mod->sm_desc->ad_cname.bv_val; */
360
361
362
	MatchingRule *mr = mod->sm_desc->ad_type->sat_equality;

	a = attr_find( e->e_attrs, mod->sm_desc );
363

Kurt Zeilenga's avatar
Kurt Zeilenga committed
364
	/* check if the values we're adding already exist */
365
	if ( a != NULL ) {
366
367
368
		if( mr == NULL || !mr->smr_match ) {
			/* do not allow add of additional attribute
				if no equality rule exists */
369
370
371
			return LDAP_INAPPROPRIATE_MATCHING;
		}

372
		for ( i = 0; mod->sm_bvalues[i] != NULL; i++ ) {
373
			int rc;
374
			int j;
375
			const char *text = NULL;
376
			struct berval asserted;
377
378
379
380
381
382
383
384
385

			rc = value_normalize( mod->sm_desc,
				SLAP_MR_EQUALITY,
				mod->sm_bvalues[i],
				&asserted,
				&text );

			if( rc != LDAP_SUCCESS ) return rc;

386
387
388
			for ( j = 0; a->a_vals[j] != NULL; j++ ) {
				int match;
				int rc = value_match( &match, mod->sm_desc, mr,
389
					SLAP_MR_VALUE_SYNTAX_MATCH,
390
					a->a_vals[j], &asserted, &text );
391
392

				if( rc == LDAP_SUCCESS && match == 0 ) {
393
					free( asserted.bv_val );
394
395
396
					return LDAP_TYPE_OR_VALUE_EXISTS;
				}
			}
397

398
			free( asserted.bv_val );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
399
400
401
402
		}
	}

	/* no - add them */
403
404
405
	if( attr_merge( e, mod->sm_desc, mod->sm_bvalues ) != 0 ) {
		/* this should return result return of attr_merge */
		return LDAP_OTHER;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
406
407
	}

408
	return LDAP_SUCCESS;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
409
410
}

411
static int
Kurt Zeilenga's avatar
Kurt Zeilenga committed
412
413
delete_values(
    Entry	*e,
414
    Modification	*mod,
Kurt Zeilenga's avatar
Kurt Zeilenga committed
415
416
417
418
419
    char	*dn
)
{
	int		i, j, k, found;
	Attribute	*a;
420
	char *desc = mod->sm_desc->ad_cname.bv_val;
421
422
	MatchingRule *mr = mod->sm_desc->ad_type->sat_equality;

Kurt Zeilenga's avatar
Kurt Zeilenga committed
423
	/* delete the entire attribute */
424
	if ( mod->sm_bvalues == NULL ) {
Gary Williams's avatar
Gary Williams committed
425
426
427
428
#ifdef NEW_LOGGING
		LDAP_LOG(( "backend", LDAP_LEVEL_ENTRY,
			   "delete_values: removing entire attribute %s\n", desc ));
#else
Kurt Zeilenga's avatar
Kurt Zeilenga committed
429
		Debug( LDAP_DEBUG_ARGS, "removing entire attribute %s\n",
430
		    desc, 0, 0 );
Gary Williams's avatar
Gary Williams committed
431
432
#endif

433
		return( attr_delete( &e->e_attrs, mod->sm_desc ) ?
Kurt Zeilenga's avatar
Kurt Zeilenga committed
434
435
436
		    LDAP_NO_SUCH_ATTRIBUTE : LDAP_SUCCESS );
	}

437
	if( mr == NULL || !mr->smr_match ) {
438
439
		/* disallow specific attributes from being deleted if
			no equality rule */
440
441
442
		return LDAP_INAPPROPRIATE_MATCHING;
	}

Kurt Zeilenga's avatar
Kurt Zeilenga committed
443
	/* delete specific values - find the attribute first */
444
	if ( (a = attr_find( e->e_attrs, mod->sm_desc )) == NULL ) {
Gary Williams's avatar
Gary Williams committed
445
446
447
448
#ifdef NEW_LOGGING
		LDAP_LOG(( "backend", LDAP_LEVEL_INFO,
			   "ldap_modify_delete: Could not find attribute %s\n", desc ));
#else
449
450
		Debug( LDAP_DEBUG_ARGS, "ldap_modify_delete: "
			"could not find attribute %s\n",
451
		    desc, 0, 0 );
Gary Williams's avatar
Gary Williams committed
452
453
#endif

Kurt Zeilenga's avatar
Kurt Zeilenga committed
454
455
456
457
		return( LDAP_NO_SUCH_ATTRIBUTE );
	}

	/* find each value to delete */
458
	for ( i = 0; mod->sm_bvalues[i] != NULL; i++ ) {
459
460
461
		int rc;
		const char *text = NULL;

462
		struct berval asserted;
463
464
465
466
467
468
469
470
471

		rc = value_normalize( mod->sm_desc,
			SLAP_MR_EQUALITY,
			mod->sm_bvalues[i],
			&asserted,
			&text );

		if( rc != LDAP_SUCCESS ) return rc;

Kurt Zeilenga's avatar
Kurt Zeilenga committed
472
473
		found = 0;
		for ( j = 0; a->a_vals[j] != NULL; j++ ) {
474
			int match;
475
			int rc = value_match( &match, mod->sm_desc, mr,
476
				SLAP_MR_VALUE_SYNTAX_MATCH,
477
				a->a_vals[j], &asserted, &text );
478

479
			if( rc == LDAP_SUCCESS && match != 0 ) {
Kurt Zeilenga's avatar
Kurt Zeilenga committed
480
481
				continue;
			}
482
483

			/* found a matching value */
Kurt Zeilenga's avatar
Kurt Zeilenga committed
484
485
			found = 1;

486
			/* delete it */
Kurt Zeilenga's avatar
Kurt Zeilenga committed
487
488
489
490
491
			ber_bvfree( a->a_vals[j] );
			for ( k = j + 1; a->a_vals[k] != NULL; k++ ) {
				a->a_vals[k - 1] = a->a_vals[k];
			}
			a->a_vals[k - 1] = NULL;
492

Kurt Zeilenga's avatar
Kurt Zeilenga committed
493
494
495
			break;
		}

496
		free( asserted.bv_val );
497

Kurt Zeilenga's avatar
Kurt Zeilenga committed
498
499
		/* looked through them all w/o finding it */
		if ( ! found ) {
Gary Williams's avatar
Gary Williams committed
500
501
502
503
#ifdef NEW_LOGGING
			LDAP_LOG(( "backend", LDAP_LEVEL_ARGS,
				   "delete_values: could not find value for attr %s\n", desc )); 
#else
Kurt Zeilenga's avatar
Kurt Zeilenga committed
504
			Debug( LDAP_DEBUG_ARGS,
505
			    "ldbm_modify_delete: could not find value for attr %s\n",
506
			    desc, 0, 0 );
Gary Williams's avatar
Gary Williams committed
507
508
#endif

Kurt Zeilenga's avatar
Kurt Zeilenga committed
509
			return LDAP_NO_SUCH_ATTRIBUTE;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
510
511
512
		}
	}

513
514
	/* if no values remain, delete the entire attribute */
	if ( a->a_vals[0] == NULL ) {
Gary Williams's avatar
Gary Williams committed
515
516
517
518
#ifdef NEW_LOGGING
		LDAP_LOG(( "backend", LDAP_LEVEL_ENTRY,
			   "delete_values: removing entire attribute %s\n", desc ));
#else
519
520
521
		Debug( LDAP_DEBUG_ARGS,
			"removing entire attribute %s\n",
			desc, 0, 0 );
Gary Williams's avatar
Gary Williams committed
522
523
#endif

524
525
526
527
528
		if ( attr_delete( &e->e_attrs, mod->sm_desc ) ) {
			return LDAP_NO_SUCH_ATTRIBUTE;
		}
	}

529
	return LDAP_SUCCESS;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
530
531
}

532
static int
Kurt Zeilenga's avatar
Kurt Zeilenga committed
533
534
replace_values(
    Entry	*e,
535
    Modification	*mod,
Kurt Zeilenga's avatar
Kurt Zeilenga committed
536
537
538
    char	*dn
)
{
539
540
541
542
543
	int rc = attr_delete( &e->e_attrs, mod->sm_desc );

	if( rc != LDAP_SUCCESS && rc != LDAP_NO_SUCH_ATTRIBUTE ) {
		return rc;
	}
Kurt Zeilenga's avatar
Kurt Zeilenga committed
544

545
546
	if ( mod->sm_bvalues != NULL &&
		attr_merge( e, mod->sm_desc, mod->sm_bvalues ) != 0 )
547
	{
548
		return LDAP_OTHER;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
549
550
	}

551
	return LDAP_SUCCESS;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
552
}