1 /* modify.c - ldbm backend modify routine */
4 * Copyright 1998-2003 The OpenLDAP Foundation, All Rights Reserved.
5 * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
12 #include <ac/string.h>
13 #include <ac/socket.h>
17 #include "back-ldbm.h"
18 #include "proto-back-ldbm.h"
20 /* We need this function because of LDAP modrdn. If we do not
21 * add this there would be a bunch of code replication here
22 * and there and of course the likelihood of bugs increases.
23 * Juan C. Gomez (gomez@engr.sgi.com) 05/18/99
25 int ldbm_modify_internal(
27 Modifications *modlist,
34 int rc = LDAP_SUCCESS;
37 Attribute *save_attrs;
41 LDAP_LOG( BACK_LDBM, ENTRY, "ldbm_modify_internal: %s\n", e->e_name.bv_val, 0, 0 );
43 Debug(LDAP_DEBUG_TRACE, "ldbm_modify_internal: %s\n", e->e_name.bv_val, 0, 0);
47 if ( !acl_check_modlist( op, e, modlist )) {
48 return LDAP_INSUFFICIENT_ACCESS;
51 save_attrs = e->e_attrs;
52 e->e_attrs = attrs_dup( e->e_attrs );
54 for ( ml = modlist; ml != NULL; ml = ml->sml_next ) {
57 switch ( mod->sm_op ) {
60 LDAP_LOG( BACK_LDBM, DETAIL1, "ldbm_modify_internal: add\n", 0, 0, 0);
62 Debug(LDAP_DEBUG_ARGS, "ldbm_modify_internal: add\n", 0, 0, 0);
65 rc = modify_add_values( e, mod, get_permissiveModify( op ),
66 text, textbuf, textlen );
67 if( rc != LDAP_SUCCESS ) {
69 LDAP_LOG( BACK_LDBM, INFO,
70 "ldbm_modify_internal: failed %d (%s)\n", rc, *text, 0 );
72 Debug(LDAP_DEBUG_ARGS, "ldbm_modify_internal: %d %s\n",
80 LDAP_LOG( BACK_LDBM, DETAIL1, "ldbm_modify_internal: delete\n", 0,0,0);
82 Debug(LDAP_DEBUG_ARGS, "ldbm_modify_internal: delete\n", 0, 0, 0);
85 rc = modify_delete_values( e, mod, get_permissiveModify( op ),
86 text, textbuf, textlen );
87 assert( rc != LDAP_TYPE_OR_VALUE_EXISTS );
88 if( rc != LDAP_SUCCESS ) {
90 LDAP_LOG( BACK_LDBM, INFO,
91 "ldbm_modify_internal: failed %d (%s)\n", rc, *text, 0 );
93 Debug(LDAP_DEBUG_ARGS, "ldbm_modify_internal: %d %s\n",
99 case LDAP_MOD_REPLACE:
101 LDAP_LOG( BACK_LDBM, DETAIL1, "ldbm_modify_internal: replace\n",0,0,0);
103 Debug(LDAP_DEBUG_ARGS, "ldbm_modify_internal: replace\n", 0, 0, 0);
106 rc = modify_replace_values( e, mod, get_permissiveModify( op ),
107 text, textbuf, textlen );
108 if( rc != LDAP_SUCCESS ) {
110 LDAP_LOG( BACK_LDBM, INFO,
111 "ldbm_modify_internal: failed %d (%s)\n", rc, *text, 0 );
113 Debug(LDAP_DEBUG_ARGS, "ldbm_modify_internal: %d %s\n",
119 case SLAP_MOD_SOFTADD:
121 LDAP_LOG( BACK_LDBM, DETAIL1,
122 "ldbm_modify_internal: softadd\n", 0, 0, 0 );
124 Debug(LDAP_DEBUG_ARGS, "ldbm_modify_internal: softadd\n", 0, 0, 0);
127 /* Avoid problems in index_add_mods()
128 * We need to add index if necessary.
130 mod->sm_op = LDAP_MOD_ADD;
132 rc = modify_add_values( e, mod, get_permissiveModify( op ),
133 text, textbuf, textlen );
134 if ( rc == LDAP_TYPE_OR_VALUE_EXISTS ) {
138 if( rc != LDAP_SUCCESS ) {
140 LDAP_LOG( BACK_LDBM, INFO,
141 "ldbm_modify_internal: failed %d (%s)\n", rc, *text, 0 );
143 Debug(LDAP_DEBUG_ARGS, "ldbm_modify_internal: %d %s\n",
151 LDAP_LOG( BACK_LDBM, ERR,
152 "ldbm_modify_internal: invalid op %d\n", mod->sm_op, 0, 0 );
154 Debug(LDAP_DEBUG_ANY, "ldbm_modify_internal: invalid op %d\n",
159 *text = "Invalid modify operation";
161 LDAP_LOG( BACK_LDBM, INFO,
162 "ldbm_modify_internal: %d (%s)\n", rc, *text, 0 );
164 Debug(LDAP_DEBUG_ARGS, "ldbm_modify_internal: %d %s\n",
169 if ( rc != LDAP_SUCCESS ) {
173 /* If objectClass was modified, reset the flags */
174 if ( mod->sm_desc == slap_schema.si_ad_objectClass ) {
178 /* check if modified attribute was indexed */
179 rc = index_is_indexed( op->o_bd, mod->sm_desc );
180 if ( rc == LDAP_SUCCESS ) {
181 ap = attr_find( save_attrs, mod->sm_desc );
182 if ( ap ) ap->a_flags |= SLAP_ATTR_IXDEL;
184 ap = attr_find( e->e_attrs, mod->sm_desc );
185 if ( ap ) ap->a_flags |= SLAP_ATTR_IXADD;
189 /* check that the entry still obeys the schema */
191 rc = entry_schema_check( op->o_bd, e, save_attrs, text, textbuf, textlen );
192 #else /* LDAP_CACHING */
193 if ( !op->o_caching_on ) {
194 rc = entry_schema_check( op->o_bd, e, save_attrs,
195 text, textbuf, textlen );
199 #endif /* LDAP_CACHING */
201 if ( rc != LDAP_SUCCESS ) {
203 LDAP_LOG( BACK_LDBM, ERR,
204 "ldbm_modify_internal: entry failed schema check: %s\n",
207 Debug( LDAP_DEBUG_ANY, "entry failed schema check: %s\n",
214 /* check for abandon */
215 if ( op->o_abandon ) {
220 /* update the indices of the modified attributes */
222 /* start with deleting the old index entries */
223 for ( ap = save_attrs; ap != NULL; ap = ap->a_next ) {
224 if ( ap->a_flags & SLAP_ATTR_IXDEL ) {
225 rc = index_values( op->o_bd, ap->a_desc,
227 e->e_id, SLAP_INDEX_DELETE_OP );
228 if ( rc != LDAP_SUCCESS ) {
230 LDAP_LOG( BACK_LDBM, ERR,
231 "ldbm_modify_internal: Attribute index delete failure\n",
234 Debug( LDAP_DEBUG_ANY,
235 "Attribute index delete failure",
240 ap->a_flags &= ~SLAP_ATTR_IXDEL;
244 /* add the new index entries */
245 for ( ap = e->e_attrs; ap != NULL; ap = ap->a_next ) {
246 if ( ap->a_flags & SLAP_ATTR_IXADD ) {
247 rc = index_values( op->o_bd, ap->a_desc,
249 e->e_id, SLAP_INDEX_ADD_OP );
250 if ( rc != LDAP_SUCCESS ) {
252 LDAP_LOG( BACK_LDBM, ERR,
253 "ldbm_modify_internal: Attribute index add failure\n",
256 Debug( LDAP_DEBUG_ANY,
257 "Attribute index add failure",
262 ap->a_flags &= ~SLAP_ATTR_IXADD;
267 if ( rc == LDAP_SUCCESS ) {
268 attrs_free( save_attrs );
270 for ( ap = save_attrs; ap; ap = ap->a_next ) {
273 attrs_free( e->e_attrs );
274 e->e_attrs = save_attrs;
285 struct ldbminfo *li = (struct ldbminfo *) op->o_bd->be_private;
288 int manageDSAit = get_manageDSAit( op );
289 char textbuf[SLAP_TEXT_BUFLEN];
290 size_t textlen = sizeof textbuf;
293 LDAP_LOG( BACK_LDBM, ENTRY, "ldbm_back_modify: enter\n", 0, 0, 0);
295 Debug(LDAP_DEBUG_ARGS, "ldbm_back_modify:\n", 0, 0, 0);
298 /* grab giant lock for writing */
299 ldap_pvt_thread_rdwr_wlock(&li->li_giant_rwlock);
301 /* acquire and lock entry */
302 if ( (e = dn2entry_w( op->o_bd, &op->o_req_ndn, &matched )) == NULL ) {
303 if ( matched != NULL ) {
304 rs->sr_matched = ch_strdup( matched->e_dn );
305 rs->sr_ref = is_entry_referral( matched )
306 ? get_entry_referrals( op, matched )
308 cache_return_entry_r( &li->li_cache, matched );
310 rs->sr_ref = referral_rewrite( default_referral,
311 NULL, &op->o_req_dn, LDAP_SCOPE_DEFAULT );
314 ldap_pvt_thread_rdwr_wunlock(&li->li_giant_rwlock);
315 rs->sr_err = LDAP_REFERRAL;
316 send_ldap_result( op, rs );
318 if ( rs->sr_ref ) ber_bvarray_free( rs->sr_ref );
319 free( (char *)rs->sr_matched );
325 if ( !manageDSAit && is_entry_referral( e ) )
326 #else /* LDAP_CACHING */
327 if ( !op->o_caching_on && !manageDSAit && is_entry_referral( e ) )
328 #endif /* LDAP_CACHING */
330 /* parent is a referral, don't allow add */
331 /* parent is an alias, don't allow add */
332 rs->sr_ref = get_entry_referrals( op, e );
335 LDAP_LOG( BACK_LDBM, INFO,
336 "ldbm_back_modify: entry (%s) is referral\n", op->o_req_ndn.bv_val, 0, 0 );
338 Debug( LDAP_DEBUG_TRACE, "entry is referral\n", 0,
342 rs->sr_err = LDAP_REFERRAL;
343 rs->sr_matched = e->e_name.bv_val;
344 send_ldap_result( op, rs );
346 if ( rs->sr_ref ) ber_bvarray_free( rs->sr_ref );
351 /* Modify the entry */
352 rs->sr_err = ldbm_modify_internal( op, op->oq_modify.rs_modlist, e,
353 &rs->sr_text, textbuf, textlen );
355 if( rs->sr_err != LDAP_SUCCESS ) {
356 if( rs->sr_err != SLAPD_ABANDON ) {
357 send_ldap_result( op, rs );
363 /* change the entry itself */
364 if ( id2entry_add( op->o_bd, e ) != 0 ) {
365 send_ldap_error( op, rs, LDAP_OTHER,
366 "id2entry failure" );
370 send_ldap_error( op, rs, LDAP_SUCCESS,
373 cache_return_entry_w( &li->li_cache, e );
374 ldap_pvt_thread_rdwr_wunlock(&li->li_giant_rwlock);
378 cache_return_entry_w( &li->li_cache, e );
379 ldap_pvt_thread_rdwr_wunlock(&li->li_giant_rwlock);