]> git.sur5r.net Git - openldap/blob - servers/slapd/back-bdb2/add.c
expose oc_check_operational from schema.c
[openldap] / servers / slapd / back-bdb2 / add.c
1 /* add.c - ldap bdb2 back-end add routine */
2
3 #include "portable.h"
4
5 #include <stdio.h>
6
7 #include <ac/socket.h>
8 #include <ac/string.h>
9
10 #include "slap.h"
11 #include "back-bdb2.h"
12 #include "proto-back-bdb2.h"
13
14 static DB_LOCK         lock;
15
16
17 static int
18 bdb2i_back_add_internal(
19     BackendDB   *be,
20     Connection  *conn,
21     Operation   *op,
22     Entry       *e
23 )
24 {
25         struct ldbminfo *li = (struct ldbminfo *) be->be_private;
26         char            *pdn;
27         Entry           *p = NULL;
28         int                     rc; 
29         struct timeval  time1;
30
31         Debug(LDAP_DEBUG_ARGS, "==> bdb2i_back_add: %s\n", e->e_dn, 0, 0);
32
33         if ( ( bdb2i_dn2id( be, e->e_ndn ) ) != NOID ) {
34                 entry_free( e );
35                 send_ldap_result( conn, op, LDAP_ALREADY_EXISTS, "", "" );
36                 return( -1 );
37         }
38
39         if ( global_schemacheck && oc_schema_check( e ) != 0 ) {
40                 Debug( LDAP_DEBUG_TRACE, "entry failed schema check\n",
41                         0, 0, 0 );
42
43                 entry_free( e );
44                 send_ldap_result( conn, op, LDAP_OBJECT_CLASS_VIOLATION, "",
45                     "" );
46                 return( -1 );
47         }
48
49         /*
50          * Get the parent dn and see if the corresponding entry exists.
51          * If the parent does not exist, only allow the "root" user to
52          * add the entry.
53          */
54
55         pdn = dn_parent( be, e->e_ndn );
56
57         if( pdn != NULL && *pdn != '\0' && !be_issuffix(be, "") ) {
58                 char *matched = NULL;
59
60                 assert( *pdn != '\0' );
61
62                 /* get parent with writer lock */
63                 if ( (p = bdb2i_dn2entry_w( be, pdn, &matched )) == NULL ) {
64                         Debug( LDAP_DEBUG_TRACE, "parent does not exist\n", 0,
65                             0, 0 );
66                         send_ldap_result( conn, op, LDAP_NO_SUCH_OBJECT,
67                             matched, "" );
68
69                         if ( matched != NULL ) {
70                                 free( matched );
71                         }
72
73                         entry_free( e );
74                         free( pdn );
75                         return -1;
76                 }
77
78                 free(pdn);
79
80                 if ( matched != NULL ) {
81                         free( matched );
82                 }
83
84                 if ( ! access_allowed( be, conn, op, p,
85                         "children", NULL, ACL_WRITE ) )
86                 {
87                         Debug( LDAP_DEBUG_TRACE, "no access to parent\n", 0,
88                             0, 0 );
89                         send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
90                             "", "" );
91
92                         /* free parent and writer lock */
93                         bdb2i_cache_return_entry_w( &li->li_cache, p ); 
94
95                         entry_free( e );
96                         return -1;
97                 }
98
99         } else {
100                 if(pdn != NULL) {
101                         assert( *pdn == '\0' );
102                         free(pdn);
103                 }
104
105                 /* no parent, must be adding entry to root */
106                 if ( ! be_isroot( be, op->o_ndn ) ) {
107                         Debug( LDAP_DEBUG_TRACE, "%s add denied\n",
108                                 pdn == NULL ? "suffix" : "entry at root",
109                                 0, 0 );
110
111                         send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
112                             "", "" );
113
114                         entry_free( e );
115                         return -1;
116                 }
117         }
118
119         e->e_id = bdb2i_next_id( be );
120
121         /*
122          * Try to add the entry to the cache, assign it a new dnid.
123          */
124         bdb2i_start_timing( be->bd_info, &time1 );
125
126         rc = bdb2i_cache_add_entry_rw( &li->li_cache, e, CACHE_WRITE_LOCK );
127
128         bdb2i_stop_timing( be->bd_info, time1, "ADD-CACHE", conn, op );
129
130         if ( rc != 0 ) {
131                 if( p != NULL) {
132                         /* free parent and writer lock */
133                         bdb2i_cache_return_entry_w( &li->li_cache, p ); 
134                 }
135
136                 Debug( LDAP_DEBUG_ANY, "cache_add_entry_lock failed\n", 0, 0,
137                     0 );
138
139                 /* return the id */
140                 bdb2i_next_id_return( be, e->e_id );
141                 
142                 /* free the entry */
143                 entry_free( e );
144
145                 if(rc > 0) {
146                         send_ldap_result( conn, op, LDAP_ALREADY_EXISTS, "", "" );
147                 } else {
148                         send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "", "" );
149                 }
150
151                 return( -1 );
152         }
153
154         rc = -1;
155
156         /*
157          * add it to the id2children index for the parent
158          */
159
160         bdb2i_start_timing( be->bd_info, &time1 );
161
162         if ( bdb2i_id2children_add( be, p, e ) != 0 ) {
163                 Debug( LDAP_DEBUG_TRACE, "bdb2i_id2children_add failed\n", 0,
164                     0, 0 );
165                 send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "", "" );
166
167                 bdb2i_stop_timing( be->bd_info, time1, "ADD-ID2CHILDREN", conn, op );
168
169                 goto return_results;
170         }
171
172         bdb2i_stop_timing( be->bd_info, time1, "ADD-ID2CHILDREN", conn, op );
173
174         /*
175          * Add the entry to the attribute indexes, then add it to
176          * the id2children index, dn2id index, and the id2entry index.
177          */
178
179         bdb2i_start_timing( be->bd_info, &time1 );
180
181         /* attribute indexes */
182         if ( bdb2i_index_add_entry( be, e ) != 0 ) {
183                 Debug( LDAP_DEBUG_TRACE, "bdb2i_index_add_entry failed\n", 0,
184                     0, 0 );
185                 send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "", "" );
186
187                 bdb2i_stop_timing( be->bd_info, time1, "ADD-INDEX", conn, op );
188
189                 goto return_results;
190         }
191
192         bdb2i_stop_timing( be->bd_info, time1, "ADD-INDEX", conn, op );
193
194         bdb2i_start_timing( be->bd_info, &time1 );
195
196         /* dn2id index */
197         if ( bdb2i_dn2id_add( be, e->e_ndn, e->e_id ) != 0 ) {
198                 Debug( LDAP_DEBUG_TRACE, "bdb2i_dn2id_add failed\n", 0,
199                     0, 0 );
200                 send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "", "" );
201
202                 bdb2i_stop_timing( be->bd_info, time1, "ADD-DN2ID", conn, op );
203
204                 goto return_results;
205         }
206
207         bdb2i_stop_timing( be->bd_info, time1, "ADD-DN2ID", conn, op );
208
209         bdb2i_start_timing( be->bd_info, &time1 );
210
211         /* id2entry index */
212         if ( bdb2i_id2entry_add( be, e ) != 0 ) {
213                 Debug( LDAP_DEBUG_TRACE, "bdb2i_id2entry_add failed\n", 0,
214                     0, 0 );
215                 (void) bdb2i_dn2id_delete( be, e->e_ndn );
216                 send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "", "" );
217
218                 bdb2i_stop_timing( be->bd_info, time1, "ADD-ID2ENTRY", conn, op );
219
220                 goto return_results;
221         }
222
223         bdb2i_stop_timing( be->bd_info, time1, "ADD-ID2ENTRY", conn, op );
224
225         send_ldap_result( conn, op, LDAP_SUCCESS, "", "" );
226         rc = 0;
227
228 return_results:;
229         if (p != NULL) {
230                 /* free parent and writer lock */
231                 bdb2i_cache_return_entry_w( &li->li_cache, p ); 
232         }
233
234         if ( rc ) {
235                 /* free entry and writer lock */
236                 bdb2i_cache_return_entry_w( &li->li_cache, e );
237         }
238
239         return( rc );
240 }
241
242
243 int
244 bdb2_back_add(
245     BackendDB   *be,
246     Connection  *conn,
247     Operation   *op,
248     Entry       *e
249 )
250 {
251         struct ldbminfo *li  = (struct ldbminfo *) be->be_private;
252         struct timeval  time1;
253         int             ret;
254
255         bdb2i_start_timing( be->bd_info, &time1 );
256
257         if ( bdb2i_enter_backend_w( &lock ) != 0 ) {
258
259                 send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "", "" );
260                 return( -1 );
261
262         }
263
264         /*  check, if a new default attribute index will be created,
265                 in which case we have to open the index file BEFORE TP  */
266         switch ( slapMode ) {
267                 case SLAP_SERVER_MODE:
268                 case SLAP_TIMEDSERVER_MODE:
269                 case SLAP_TOOL_MODE:
270                 case SLAP_TOOLID_MODE:
271                         bdb2i_check_default_attr_index_add( li, e );
272                         break;
273         }
274
275         ret = bdb2i_back_add_internal( be, conn, op, e );
276
277         /*  if the operation was successful, we will delay the unlock  */
278         if ( ret )
279                 (void) bdb2i_leave_backend_w( lock );
280
281         bdb2i_stop_timing( be->bd_info, time1, "ADD", conn, op );
282
283         return( ret );
284 }
285
286
287 int
288 bdb2i_release_add_lock( void )
289 {
290         (void) bdb2i_leave_backend_w( lock );
291         return 0;
292 }
293
294