1 /* add.c - ldap ldbm back-end add routine */
4 * Copyright 1998-2003 The OpenLDAP Foundation, All Rights Reserved.
5 * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
12 #include <ac/socket.h>
13 #include <ac/string.h>
16 #include "back-ldbm.h"
17 #include "proto-back-ldbm.h"
24 struct ldbminfo *li = (struct ldbminfo *) op->o_bd->be_private;
28 AttributeDescription *children = slap_schema.si_ad_children;
29 AttributeDescription *entry = slap_schema.si_ad_entry;
30 char textbuf[SLAP_TEXT_BUFLEN];
31 size_t textlen = sizeof textbuf;
34 LDAP_LOG( BACK_LDBM, ENTRY, "ldbm_back_add: %s\n", op->o_req_dn.bv_val, 0, 0 );
36 Debug(LDAP_DEBUG_ARGS, "==> ldbm_back_add: %s\n", op->o_req_dn.bv_val, 0, 0);
40 rs->sr_err = entry_schema_check( op->o_bd, op->oq_add.rs_e, NULL, &rs->sr_text, textbuf, textlen );
41 #else /* LDAP_CACHING */
42 if ( !op->o_caching_on ) {
43 rs->sr_err = entry_schema_check( op->o_bd, op->oq_add.rs_e, NULL, &rs->sr_text, textbuf, textlen );
45 rs->sr_err = LDAP_SUCCESS;
47 #endif /* LDAP_CACHING */
49 if ( rs->sr_err != LDAP_SUCCESS ) {
51 LDAP_LOG( BACK_LDBM, ERR,
52 "ldbm_back_add: entry (%s) failed schema check.\n", op->o_req_dn.bv_val, 0, 0 );
54 Debug( LDAP_DEBUG_TRACE, "entry failed schema check: %s\n",
58 send_ldap_result( op, rs );
63 if ( !op->o_caching_on ) {
64 #endif /* LDAP_CACHING */
65 if ( !access_allowed( op, op->oq_add.rs_e,
66 entry, NULL, ACL_WRITE, NULL ) )
69 LDAP_LOG( BACK_LDBM, ERR,
70 "ldbm_back_add: No write access to entry (%s).\n",
71 op->o_req_dn.bv_val, 0, 0 );
73 Debug( LDAP_DEBUG_TRACE, "no write access to entry\n", 0,
77 send_ldap_error( op, rs, LDAP_INSUFFICIENT_ACCESS,
78 "no write access to entry" );
84 #endif /* LDAP_CACHING */
86 /* grab giant lock for writing */
87 ldap_pvt_thread_rdwr_wlock(&li->li_giant_rwlock);
89 if ( ( rs->sr_err = dn2id( op->o_bd, &op->o_req_ndn, &id ) ) || id != NOID ) {
90 /* if (rs->sr_err) something bad happened to ldbm cache */
91 ldap_pvt_thread_rdwr_wunlock(&li->li_giant_rwlock);
92 rs->sr_err = rs->sr_err ? LDAP_OTHER : LDAP_ALREADY_EXISTS;
93 send_ldap_result( op, rs );
98 * Get the parent dn and see if the corresponding entry exists.
99 * If the parent does not exist, only allow the "root" user to
103 if ( be_issuffix( op->o_bd, &op->o_req_ndn ) ) {
106 dnParent( &op->o_req_ndn, &pdn );
111 #else /* LDAP_CACHING */
112 if( pdn.bv_len && !op->o_caching_on )
113 #endif /* LDAP_CACHING */
115 Entry *matched = NULL;
117 /* get parent with writer lock */
118 if ( (p = dn2entry_w( op->o_bd, &pdn, &matched )) == NULL ) {
119 if ( matched != NULL ) {
120 rs->sr_matched = ch_strdup( matched->e_dn );
121 rs->sr_ref = is_entry_referral( matched )
122 ? get_entry_referrals( op, matched )
124 cache_return_entry_r( &li->li_cache, matched );
127 rs->sr_ref = referral_rewrite( default_referral,
128 NULL, &op->o_req_dn, LDAP_SCOPE_DEFAULT );
131 ldap_pvt_thread_rdwr_wunlock(&li->li_giant_rwlock);
134 LDAP_LOG( BACK_LDBM, ERR,
135 "ldbm_back_add: Parent of (%s) does not exist.\n",
136 op->o_req_dn.bv_val, 0, 0 );
138 Debug( LDAP_DEBUG_TRACE, "parent does not exist\n",
142 rs->sr_text = rs->sr_ref ? "parent is referral" : "parent does not exist";
143 rs->sr_err = LDAP_REFERRAL;
144 send_ldap_result( op, rs );
146 ber_bvarray_free( rs->sr_ref );
147 free( (char *)rs->sr_matched );
152 if ( ! access_allowed( op, p,
153 children, NULL, ACL_WRITE, NULL ) )
155 /* free parent and writer lock */
156 cache_return_entry_w( &li->li_cache, p );
157 ldap_pvt_thread_rdwr_wunlock(&li->li_giant_rwlock);
160 LDAP_LOG( BACK_LDBM, ERR,
161 "ldbm_back_add: No write access to parent (%s).\n",
162 op->o_req_dn.bv_val, 0, 0 );
164 Debug( LDAP_DEBUG_TRACE, "no write access to parent\n", 0,
168 send_ldap_error( op, rs, LDAP_INSUFFICIENT_ACCESS,
169 "no write access to parent" );
174 if ( is_entry_alias( p ) ) {
175 /* parent is an alias, don't allow add */
177 /* free parent and writer lock */
178 cache_return_entry_w( &li->li_cache, p );
179 ldap_pvt_thread_rdwr_wunlock(&li->li_giant_rwlock);
182 LDAP_LOG(BACK_LDBM, ERR,
183 "ldbm_back_add: Parent is an alias.\n", 0, 0, 0 );
185 Debug( LDAP_DEBUG_TRACE, "parent is alias\n", 0,
190 send_ldap_error( op, rs, LDAP_ALIAS_PROBLEM,
191 "parent is an alias" );
196 if ( is_entry_referral( p ) ) {
197 /* parent is a referral, don't allow add */
198 rs->sr_matched = ch_strdup( p->e_dn );
199 rs->sr_ref = is_entry_referral( p )
200 ? get_entry_referrals( op, p )
203 /* free parent and writer lock */
204 cache_return_entry_w( &li->li_cache, p );
205 ldap_pvt_thread_rdwr_wunlock(&li->li_giant_rwlock);
208 LDAP_LOG( BACK_LDBM, ERR,
209 "ldbm_back_add: Parent is referral.\n", 0, 0, 0 );
211 Debug( LDAP_DEBUG_TRACE, "parent is referral\n", 0,
214 rs->sr_err = LDAP_REFERRAL;
215 send_ldap_result( op, rs );
217 ber_bvarray_free( rs->sr_ref );
218 free( (char *)rs->sr_matched );
224 if( pdn.bv_val != NULL )
225 #else /* LDAP_CACHING */
226 if( pdn.bv_val != NULL && !op->o_caching_on )
227 #endif /* LDAP_CACHING */
229 assert( *pdn.bv_val == '\0' );
232 /* no parent, must be adding entry to root */
234 if ( !be_isroot( op->o_bd, &op->o_ndn ) )
235 #else /* LDAP_CACHING */
236 if ( !be_isroot( op->o_bd, &op->o_ndn ) && !op->o_caching_on )
237 #endif /* LDAP_CACHING */
239 if ( be_issuffix( op->o_bd, (struct berval *)&slap_empty_bv ) || be_isupdate( op->o_bd, &op->o_ndn ) ) {
240 p = (Entry *)&slap_entry_root;
242 rs->sr_err = access_allowed( op, p,
243 children, NULL, ACL_WRITE, NULL );
246 if ( ! rs->sr_err ) {
247 ldap_pvt_thread_rdwr_wunlock(&li->li_giant_rwlock);
250 LDAP_LOG( BACK_LDBM, ERR,
251 "ldbm_back_add: No write "
252 "access to parent (\"\").\n", 0, 0, 0 );
254 Debug( LDAP_DEBUG_TRACE,
255 "no write access to parent\n",
259 send_ldap_error( op, rs,
260 LDAP_INSUFFICIENT_ACCESS,
261 "no write access to parent" );
267 ldap_pvt_thread_rdwr_wunlock(&li->li_giant_rwlock);
270 LDAP_LOG( BACK_LDBM, ERR,
271 "ldbm_back_add: %s add denied.\n",
272 pdn.bv_val == NULL ? "suffix"
273 : "entry at root", 0, 0 );
275 Debug( LDAP_DEBUG_TRACE, "%s add denied\n",
276 pdn.bv_val == NULL ? "suffix"
277 : "entry at root", 0, 0 );
280 send_ldap_error( op, rs,
281 LDAP_INSUFFICIENT_ACCESS, NULL );
288 if ( next_id( op->o_bd, &op->oq_add.rs_e->e_id ) ) {
290 /* free parent and writer lock */
291 cache_return_entry_w( &li->li_cache, p );
294 ldap_pvt_thread_rdwr_wunlock(&li->li_giant_rwlock);
297 LDAP_LOG( BACK_LDBM, ERR,
298 "ldbm_back_add: next_id failed.\n", 0, 0, 0 );
300 Debug( LDAP_DEBUG_ANY, "ldbm_add: next_id failed\n",
304 send_ldap_error( op, rs, LDAP_OTHER,
305 "next_id add failed" );
311 * Try to add the entry to the cache, assign it a new dnid.
313 rs->sr_err = cache_add_entry_rw(&li->li_cache, op->oq_add.rs_e, CACHE_WRITE_LOCK);
315 if ( rs->sr_err != 0 ) {
317 /* free parent and writer lock */
318 cache_return_entry_w( &li->li_cache, p );
321 ldap_pvt_thread_rdwr_wunlock(&li->li_giant_rwlock);
324 LDAP_LOG( BACK_LDBM, ERR,
325 "ldbm_back_add: cache_add_entry_lock failed.\n", 0, 0, 0 );
327 Debug( LDAP_DEBUG_ANY, "cache_add_entry_lock failed\n", 0, 0,
331 rs->sr_text = rs->sr_err > 0 ? NULL : "cache add failed";
332 rs->sr_err = rs->sr_err > 0 ? LDAP_ALREADY_EXISTS : LDAP_OTHER;
333 send_ldap_result( op, rs );
340 /* attribute indexes */
341 if ( index_entry_add( op, op->oq_add.rs_e ) != LDAP_SUCCESS ) {
343 LDAP_LOG( BACK_LDBM, ERR,
344 "ldbm_back_add: index_entry_add failed.\n", 0, 0, 0 );
346 Debug( LDAP_DEBUG_TRACE, "index_entry_add failed\n", 0,
350 send_ldap_error( op, rs, LDAP_OTHER,
351 "index generation failed" );
357 if ( dn2id_add( op->o_bd, &op->oq_add.rs_e->e_nname, op->oq_add.rs_e->e_id ) != 0 ) {
359 LDAP_LOG( BACK_LDBM, ERR,
360 "ldbm_back_add: dn2id_add failed.\n", 0, 0, 0 );
362 Debug( LDAP_DEBUG_TRACE, "dn2id_add failed\n", 0,
365 /* FIXME: delete attr indices? */
367 send_ldap_error( op, rs, LDAP_OTHER,
368 "DN index generation failed" );
374 if ( id2entry_add( op->o_bd, op->oq_add.rs_e ) != 0 ) {
376 LDAP_LOG( BACK_LDBM, ERR,
377 "ldbm_back_add: id2entry_add failed.\n", 0, 0, 0 );
379 Debug( LDAP_DEBUG_TRACE, "id2entry_add failed\n", 0,
383 /* FIXME: delete attr indices? */
384 (void) dn2id_delete( op->o_bd, &op->oq_add.rs_e->e_nname, op->oq_add.rs_e->e_id );
386 send_ldap_error( op, rs, LDAP_OTHER,
387 "entry store failed" );
392 rs->sr_err = LDAP_SUCCESS;
393 send_ldap_result( op, rs );
395 /* marks the entry as committed, so it is added to the cache;
396 * otherwise it is removed from the cache, but not destroyed;
397 * it will be destroyed by the caller */
398 cache_entry_commit( op->oq_add.rs_e );
402 /* free parent and writer lock */
403 cache_return_entry_w( &li->li_cache, p );
408 * in case of error, writer lock is freed
409 * and entry's private data is destroyed.
410 * otherwise, this is done when entry is released
412 cache_return_entry_w( &li->li_cache, op->oq_add.rs_e );
413 ldap_pvt_thread_rdwr_wunlock(&li->li_giant_rwlock);
416 return( rs->sr_err );