1 /* delete.c - ldbm backend delete routine */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5 * Copyright 1998-2004 The OpenLDAP Foundation.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted only as authorized by the OpenLDAP
12 * A copy of this license is available in the file LICENSE in the
13 * top-level directory of the distribution or, alternatively, at
14 * <http://www.OpenLDAP.org/license.html>.
21 #include <ac/string.h>
22 #include <ac/socket.h>
25 #include "back-ldbm.h"
26 #include "proto-back-ldbm.h"
33 struct ldbminfo *li = (struct ldbminfo *) op->o_bd->be_private;
38 int manageDSAit = get_manageDSAit( op );
39 AttributeDescription *children = slap_schema.si_ad_children;
40 AttributeDescription *entry = slap_schema.si_ad_entry;
43 LDAP_LOG( BACK_LDBM, ENTRY, "ldbm_back_delete: %s\n", op->o_req_dn.bv_val, 0, 0 );
45 Debug(LDAP_DEBUG_ARGS, "==> ldbm_back_delete: %s\n", op->o_req_dn.bv_val, 0, 0);
48 /* grab giant lock for writing */
49 ldap_pvt_thread_rdwr_wlock(&li->li_giant_rwlock);
51 /* get entry with writer lock */
52 e = dn2entry_w( op->o_bd, &op->o_req_ndn, &matched );
54 /* FIXME : dn2entry() should return non-glue entry */
55 if ( e == NULL || ( !manageDSAit && is_entry_glue( e ))) {
57 LDAP_LOG( BACK_LDBM, INFO,
58 "ldbm_back_delete: no such object %s\n", op->o_req_dn.bv_val, 0, 0 );
60 Debug(LDAP_DEBUG_ARGS, "<=- ldbm_back_delete: no such object %s\n",
61 op->o_req_dn.bv_val, 0, 0);
64 if ( matched != NULL ) {
65 rs->sr_matched = ch_strdup( matched->e_dn );
66 rs->sr_ref = is_entry_referral( matched )
67 ? get_entry_referrals( op, matched )
69 cache_return_entry_r( &li->li_cache, matched );
72 BerVarray deref = NULL;
73 if ( !LDAP_STAILQ_EMPTY( &op->o_bd->be_syncinfo )) {
75 LDAP_STAILQ_FOREACH( si, &op->o_bd->be_syncinfo, si_next ) {
77 ber_dupbv( &tmpbv, &si->si_provideruri_bv[0] );
78 ber_bvarray_add( &deref, &tmpbv );
81 deref = default_referral;
83 rs->sr_ref = referral_rewrite( deref, NULL, &op->o_req_dn,
87 ldap_pvt_thread_rdwr_wunlock(&li->li_giant_rwlock);
89 rs->sr_err = LDAP_REFERRAL;
90 send_ldap_result( op, rs );
92 if ( rs->sr_ref ) ber_bvarray_free( rs->sr_ref );
93 free( (char *)rs->sr_matched );
95 rs->sr_matched = NULL;
99 /* check entry for "entry" acl */
100 if ( ! access_allowed( op, e,
101 entry, NULL, ACL_WRITE, NULL ) )
104 LDAP_LOG( BACK_LDBM, ERR,
105 "ldbm_back_delete: no write access to entry of (%s)\n",
106 op->o_req_dn.bv_val, 0, 0 );
108 Debug( LDAP_DEBUG_TRACE,
109 "<=- ldbm_back_delete: no write access to entry\n", 0,
113 send_ldap_error( op, rs, LDAP_INSUFFICIENT_ACCESS,
114 "no write access to entry" );
116 rc = LDAP_INSUFFICIENT_ACCESS;
120 if ( !manageDSAit && is_entry_referral( e ) ) {
121 /* parent is a referral, don't allow add */
122 /* parent is an alias, don't allow add */
123 rs->sr_ref = get_entry_referrals( op, e );
126 LDAP_LOG( BACK_LDBM, INFO,
127 "ldbm_back_delete: entry (%s) is a referral.\n", e->e_dn, 0, 0 );
129 Debug( LDAP_DEBUG_TRACE, "entry is referral\n", 0,
133 rs->sr_err = LDAP_REFERRAL;
134 rs->sr_matched = e->e_name.bv_val;
135 send_ldap_result( op, rs );
137 if ( rs->sr_ref ) ber_bvarray_free( rs->sr_ref );
139 rs->sr_matched = NULL;
144 if ( has_children( op->o_bd, e ) ) {
146 LDAP_LOG( BACK_LDBM, ERR,
147 "ldbm_back_delete: (%s) is a non-leaf node.\n", op->o_req_dn.bv_val, 0,0);
149 Debug(LDAP_DEBUG_ARGS, "<=- ldbm_back_delete: non leaf %s\n",
150 op->o_req_dn.bv_val, 0, 0);
153 send_ldap_error( op, rs, LDAP_NOT_ALLOWED_ON_NONLEAF,
154 "subtree delete not supported" );
158 /* delete from parent's id2children entry */
159 if( !be_issuffix( op->o_bd, &e->e_nname ) && (dnParent( &e->e_nname, &pdn ),
161 if( (p = dn2entry_w( op->o_bd, &pdn, NULL )) == NULL) {
163 LDAP_LOG( BACK_LDBM, ERR,
164 "ldbm_back_delete: parent of (%s) does not exist\n", op->o_req_dn, 0, 0 );
166 Debug( LDAP_DEBUG_TRACE,
167 "<=- ldbm_back_delete: parent does not exist\n",
171 send_ldap_error( op, rs, LDAP_OTHER,
172 "could not locate parent of entry" );
176 /* check parent for "children" acl */
177 if ( ! access_allowed( op, p,
178 children, NULL, ACL_WRITE, NULL ) )
181 LDAP_LOG( BACK_LDBM, ERR,
182 "ldbm_back_delete: no access to parent of (%s)\n",
183 op->o_req_dn.bv_val, 0, 0 );
185 Debug( LDAP_DEBUG_TRACE,
186 "<=- ldbm_back_delete: no access to parent\n", 0,
190 send_ldap_error( op, rs, LDAP_INSUFFICIENT_ACCESS,
191 "no write access to parent" );
196 /* no parent, must be root to delete */
197 if( ! be_isroot( op->o_bd, &op->o_ndn ) ) {
198 if ( be_issuffix( op->o_bd, (struct berval *)&slap_empty_bv ) || be_isupdate( op->o_bd, &op->o_ndn ) ) {
199 p = (Entry *)&slap_entry_root;
201 rc = access_allowed( op, p,
202 children, NULL, ACL_WRITE, NULL );
205 /* check parent for "children" acl */
208 LDAP_LOG( BACK_LDBM, ERR,
209 "ldbm_back_delete: no access "
210 "to parent of ("")\n", 0, 0, 0 );
212 Debug( LDAP_DEBUG_TRACE,
213 "<=- ldbm_back_delete: no "
214 "access to parent\n", 0, 0, 0 );
217 send_ldap_error( op, rs, LDAP_INSUFFICIENT_ACCESS,
218 "no write access to parent" );
224 LDAP_LOG( BACK_LDBM, ERR,
225 "ldbm_back_delete: (%s) has no "
226 "parent & not a root.\n", op->o_ndn, 0, 0 );
228 Debug( LDAP_DEBUG_TRACE,
229 "<=- ldbm_back_delete: no parent & "
230 "not root\n", 0, 0, 0);
233 send_ldap_error( op, rs,
234 LDAP_INSUFFICIENT_ACCESS,
241 /* delete from dn2id mapping */
242 if ( dn2id_delete( op->o_bd, &e->e_nname, e->e_id ) != 0 ) {
244 LDAP_LOG( BACK_LDBM, ERR,
245 "ldbm_back_delete: (%s) operations error\n", op->o_req_dn.bv_val, 0, 0 );
247 Debug(LDAP_DEBUG_ARGS,
248 "<=- ldbm_back_delete: operations error %s\n",
249 op->o_req_dn.bv_val, 0, 0);
252 send_ldap_error( op, rs, LDAP_OTHER,
253 "DN index delete failed" );
257 /* delete from disk and cache */
258 if ( id2entry_delete( op->o_bd, e ) != 0 ) {
260 LDAP_LOG( BACK_LDBM, ERR,
261 "ldbm_back_delete: (%s) operations error\n", op->o_req_dn.bv_val, 0, 0 );
263 Debug(LDAP_DEBUG_ARGS,
264 "<=- ldbm_back_delete: operations error %s\n",
265 op->o_req_dn.bv_val, 0, 0);
268 send_ldap_error( op, rs, LDAP_OTHER,
269 "entry delete failed" );
273 /* delete attribute indices */
274 (void) index_entry_del( op, e );
276 rs->sr_err = LDAP_SUCCESS;
277 send_ldap_result( op, rs );
282 /* free parent and writer lock */
283 cache_return_entry_w( &li->li_cache, p );
286 /* free entry and writer lock */
287 cache_return_entry_w( &li->li_cache, e );
289 ldap_pvt_thread_rdwr_wunlock(&li->li_giant_rwlock);