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