]> git.sur5r.net Git - openldap/blob - servers/slapd/back-bdb2/delete.c
Merge in all devel changes since 2.0-alpha2.
[openldap] / servers / slapd / back-bdb2 / delete.c
1 /* delete.c - bdb2 backend delete routine */
2 /* $OpenLDAP$ */
3
4 #include "portable.h"
5
6 #include <stdio.h>
7
8 #include <ac/string.h>
9 #include <ac/socket.h>
10
11 #include "slap.h"
12 #include "back-bdb2.h"
13 #include "proto-back-bdb2.h"
14
15 static int
16 bdb2i_back_delete_internal(
17     BackendDB   *be,
18     Connection  *conn,
19     Operation   *op,
20     char        *dn
21 )
22 {
23         struct ldbminfo *li = (struct ldbminfo *) be->be_private;
24         Entry   *matched = NULL;
25         char    *pdn = NULL;
26         Entry   *e, *p = NULL;
27         int     rc = -1, manageDSAit;
28
29         Debug(LDAP_DEBUG_ARGS, "==> bdb2i_back_delete: %s\n", dn, 0, 0);
30
31         /* get entry with writer lock */
32         if ( (e = bdb2i_dn2entry_w( be, dn, &matched )) == NULL ) {
33                 char *matched_dn = NULL;
34                 struct berval **refs = NULL;
35
36                 Debug(LDAP_DEBUG_ARGS, "<=- bdb2i_back_delete: no such object %s\n",
37                         dn, 0, 0);
38
39                 if ( matched != NULL ) {
40                         matched_dn = ch_strdup( matched->e_dn );
41                         refs = is_entry_referral( matched )
42                                 ? get_entry_referrals( be, conn, op, matched )
43                                 : NULL;
44                         bdb2i_cache_return_entry_r( &li->li_cache, matched );
45                 } else {
46                         refs = default_referral;
47                 }
48
49                 send_ldap_result( conn, op, LDAP_REFERRAL,
50                         matched_dn, NULL, refs, NULL );
51
52                 if( matched != NULL ) {
53                         ber_bvecfree( refs );
54                         free( matched_dn );
55                 }
56
57                 return( -1 );
58         }
59
60         if (!manageDSAit && is_entry_referral( e ) ) {
61                 /* entry is a referral, don't allow add */
62                 struct berval **refs = get_entry_referrals( be,
63                         conn, op, e );
64
65                 Debug( LDAP_DEBUG_TRACE, "entry is referral\n", 0,
66                         0, 0 );
67
68                 send_ldap_result( conn, op, LDAP_REFERRAL,
69                         e->e_dn, NULL, refs, NULL );
70
71                 ber_bvecfree( refs );
72                 goto return_results;
73         }
74
75
76         if ( bdb2i_has_children( be, e ) ) {
77                 Debug(LDAP_DEBUG_ARGS, "<=- bdb2i_back_delete: non leaf %s\n",
78                         dn, 0, 0);
79                 send_ldap_result( conn, op, LDAP_NOT_ALLOWED_ON_NONLEAF,
80                         NULL, NULL, NULL, NULL );
81                 goto return_results;
82         }
83
84 #ifdef SLAPD_CHILD_MODIFICATION_WITH_ENTRY_ACL
85         if ( ! access_allowed( be, conn, op, e,
86                 "entry", NULL, ACL_WRITE ) )
87         {
88                 Debug(LDAP_DEBUG_ARGS,
89                         "<=- bdb2i_back_delete: insufficient access %s\n",
90                         dn, 0, 0);
91                 send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
92                         NULL, NULL, NULL, NULL );
93                 goto return_results;
94         }
95 #endif
96
97         /* find parent's entry */
98         if( (pdn = dn_parent( be, e->e_ndn )) != NULL ) {
99                 if( (p = bdb2i_dn2entry_w( be, pdn, &matched )) == NULL) {
100                         Debug( LDAP_DEBUG_TRACE,
101                                 "<=- bdb2i_back_delete: parent does not exist\n", 0, 0, 0);
102                         send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
103                                 NULL, NULL, NULL, NULL );
104                         goto return_results;
105                 }
106
107                 /* check parent for "children" acl */
108                 if ( ! access_allowed( be, conn, op, p,
109                         "children", NULL, ACL_WRITE ) )
110                 {
111                         Debug( LDAP_DEBUG_TRACE,
112                                 "<=- bdb2i_back_delete: no access to parent\n", 0, 0, 0 );
113                         send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
114                                 NULL, NULL, NULL, NULL );
115                         goto return_results;
116                 }
117
118         } else {
119                 /* no parent, must be root to delete */
120                 if( ! be_isroot( be, op->o_ndn ) ) {
121                         Debug( LDAP_DEBUG_TRACE,
122                                 "<=- bdb2i_back_delete: no parent & not root\n", 0, 0, 0);
123                         send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
124                                 NULL, NULL, NULL, NULL );
125                         goto return_results;
126                 }
127         }
128
129         /* delete from dn2id mapping */
130         if ( bdb2i_dn2id_delete( be, e->e_ndn, e->e_id ) != 0 ) {
131                 Debug(LDAP_DEBUG_ARGS,
132                         "<=- bdb2i_back_delete: operations error %s\n",
133                         dn, 0, 0);
134                 send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
135                         NULL, NULL, NULL, NULL );
136                 goto return_results;
137         }
138
139         /* delete from disk and cache */
140         if ( bdb2i_id2entry_delete( be, e ) != 0 ) {
141                 Debug(LDAP_DEBUG_ARGS,
142                         "<=- bdb2i_back_delete: operations error %s\n",
143                         dn, 0, 0);
144                 send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
145                         NULL, NULL, NULL, NULL );
146                 goto return_results;
147         }
148
149         send_ldap_result( conn, op, LDAP_SUCCESS,
150                 NULL, NULL, NULL, NULL );
151         rc = 0;
152
153 return_results:;
154         if ( pdn != NULL ) free(pdn);
155
156         if( p != NULL ) {
157                 /* free parent and writer lock */
158                 bdb2i_cache_return_entry_w( &li->li_cache, p );
159
160         }
161
162         /* free entry and writer lock */
163         bdb2i_cache_return_entry_w( &li->li_cache, e );
164
165         if ( matched != NULL ) free(matched);
166
167         return rc;
168 }
169
170
171 int
172 bdb2_back_delete(
173     BackendDB   *be,
174     Connection  *conn,
175     Operation   *op,
176     char        *dn
177 )
178 {
179         DB_LOCK         lock;
180         struct ldbminfo *li = (struct ldbminfo *) be->be_private;
181         struct timeval  time1;
182         int             ret;
183
184         bdb2i_start_timing( be->bd_info, &time1 );
185
186         if ( bdb2i_enter_backend_w( &lock ) != 0 ) {
187                 send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
188                         NULL, NULL, NULL, NULL );
189                 return( -1 );
190         }
191
192         ret = bdb2i_back_delete_internal( be, conn, op, dn );
193         (void) bdb2i_leave_backend_w( lock );
194         bdb2i_stop_timing( be->bd_info, time1, "DEL", conn, op );
195
196         return( ret );
197 }
198
199