1 /* add.c - ldap ldbm back-end add routine */
4 * Copyright 1998-2000 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"
27 struct ldbminfo *li = (struct ldbminfo *) be->be_private;
33 const char *text = NULL;
34 AttributeDescription *children = slap_schema.si_ad_children;
35 char textbuf[SLAP_TEXT_BUFLEN];
36 size_t textlen = sizeof textbuf;
39 LDAP_LOG(( "backend", LDAP_LEVEL_ENTRY,"ldbm_back_add: %s\n",
42 Debug(LDAP_DEBUG_ARGS, "==> ldbm_back_add: %s\n", e->e_dn, 0, 0);
45 /* nobody else can add until we lock our parent */
46 ldap_pvt_thread_mutex_lock(&li->li_add_mutex);
48 if ( ( rc = dn2id( be, e->e_ndn, &id ) ) || id != NOID ) {
49 /* if (rc) something bad happened to ldbm cache */
50 ldap_pvt_thread_mutex_unlock(&li->li_add_mutex);
51 send_ldap_result( conn, op,
52 rc ? LDAP_OPERATIONS_ERROR : LDAP_ALREADY_EXISTS,
53 NULL, NULL, NULL, NULL );
57 rc = entry_schema_check( e, NULL, &text, textbuf, textlen );
59 if ( rc != LDAP_SUCCESS ) {
60 ldap_pvt_thread_mutex_unlock(&li->li_add_mutex);
63 LDAP_LOG(( "backend", LDAP_LEVEL_ERR,
64 "ldbm_back_add: entry (%s) failed schema check.\n",
67 Debug( LDAP_DEBUG_TRACE, "entry failed schema check: %s\n",
72 send_ldap_result( conn, op, rc,
73 NULL, text, NULL, NULL );
78 * Get the parent dn and see if the corresponding entry exists.
79 * If the parent does not exist, only allow the "root" user to
83 pdn = dn_parent( be, e->e_ndn );
85 if( pdn != NULL && *pdn != '\0' ) {
86 Entry *matched = NULL;
88 assert( *pdn != '\0' );
90 /* get parent with writer lock */
91 if ( (p = dn2entry_w( be, pdn, &matched )) == NULL ) {
92 char *matched_dn = NULL;
95 ldap_pvt_thread_mutex_unlock(&li->li_add_mutex);
97 if ( matched != NULL ) {
98 matched_dn = ch_strdup( matched->e_dn );
99 refs = is_entry_referral( matched )
100 ? get_entry_referrals( be, conn, op, matched )
102 cache_return_entry_r( &li->li_cache, matched );
105 refs = referral_rewrite( default_referral,
106 NULL, &e->e_name, LDAP_SCOPE_DEFAULT );
110 LDAP_LOG(( "backend", LDAP_LEVEL_ERR,
111 "ldbm_back_add: Parent of (%s) does not exist.\n",
114 Debug( LDAP_DEBUG_TRACE, "parent does not exist\n",
118 send_ldap_result( conn, op, LDAP_REFERRAL, matched_dn,
119 refs == NULL ? "parent does not exist" : "parent is referral",
122 ber_bvecfree( refs );
128 /* don't need the add lock anymore */
129 ldap_pvt_thread_mutex_unlock(&li->li_add_mutex);
131 if ( ! access_allowed( be, conn, op, p,
132 children, NULL, ACL_WRITE ) )
134 /* free parent and writer lock */
135 cache_return_entry_w( &li->li_cache, p );
138 LDAP_LOG(( "backend", LDAP_LEVEL_ERR,
139 "ldbm_back_add: No write access to parent (%s).\n",
142 Debug( LDAP_DEBUG_TRACE, "no write access to parent\n", 0,
146 send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
147 NULL, "no write access to parent", NULL, NULL );
153 if ( is_entry_alias( p ) ) {
154 /* parent is an alias, don't allow add */
156 /* free parent and writer lock */
157 cache_return_entry_w( &li->li_cache, p );
160 LDAP_LOG(( "backend", LDAP_LEVEL_ERR,
161 "ldbm_back_add: Parent is an alias.\n"));
163 Debug( LDAP_DEBUG_TRACE, "parent is alias\n", 0,
168 send_ldap_result( conn, op, LDAP_ALIAS_PROBLEM,
169 NULL, "parent is an alias", NULL, NULL );
174 if ( is_entry_referral( p ) ) {
175 /* parent is a referral, don't allow add */
176 char *matched_dn = ch_strdup( p->e_dn );
177 struct berval **refs = is_entry_referral( p )
178 ? get_entry_referrals( be, conn, op, p )
181 /* free parent and writer lock */
182 cache_return_entry_w( &li->li_cache, p );
185 LDAP_LOG(( "backend", LDAP_LEVEL_ERR,
186 "ldbm_back_add: Parent is referral.\n" ));
188 Debug( LDAP_DEBUG_TRACE, "parent is referral\n", 0,
192 send_ldap_result( conn, op, LDAP_REFERRAL,
193 matched_dn, NULL, refs, NULL );
195 ber_bvecfree( refs );
202 assert( *pdn == '\0' );
205 /* no parent, must be adding entry to root */
206 if ( !be_isroot( be, &op->o_ndn ) ) {
207 if ( be_issuffix( be, "" ) || be_isupdate( be, &op->o_ndn ) ) {
208 p = (Entry *)&slap_entry_root;
210 rc = access_allowed( be, conn, op, p,
211 children, NULL, ACL_WRITE );
215 ldap_pvt_thread_mutex_unlock(&li->li_add_mutex);
218 LDAP_LOG(( "backend", LDAP_LEVEL_ERR,
219 "ldbm_back_add: No write "
220 "access to parent (\"\").\n" ));
222 Debug( LDAP_DEBUG_TRACE,
223 "no write access to parent\n",
227 send_ldap_result( conn, op,
228 LDAP_INSUFFICIENT_ACCESS,
230 "no write access to parent",
237 ldap_pvt_thread_mutex_unlock(&li->li_add_mutex);
240 LDAP_LOG(( "backend", LDAP_LEVEL_ERR,
241 "ldbm_back_add: %s add denied.\n",
242 pdn == NULL ? "suffix"
243 : "entry at root" ));
245 Debug( LDAP_DEBUG_TRACE, "%s add denied\n",
246 pdn == NULL ? "suffix"
247 : "entry at root", 0, 0 );
250 send_ldap_result( conn, op,
251 LDAP_INSUFFICIENT_ACCESS,
252 NULL, NULL, NULL, NULL );
259 * no parent, acquire the root write lock
260 * and release the add lock.
262 ldap_pvt_thread_mutex_lock(&li->li_root_mutex);
264 ldap_pvt_thread_mutex_unlock(&li->li_add_mutex);
267 if ( next_id( be, &e->e_id ) ) {
269 /* free parent and writer lock */
270 cache_return_entry_w( &li->li_cache, p );
274 /* release root lock */
275 ldap_pvt_thread_mutex_unlock(&li->li_root_mutex);
279 LDAP_LOG(( "backend", LDAP_LEVEL_ERR,
280 "ldbm_back_add: next_id failed.\n" ));
282 Debug( LDAP_DEBUG_ANY, "ldbm_add: next_id failed\n",
287 send_ldap_result( conn, op, LDAP_OTHER,
288 NULL, "next_id add failed", NULL, NULL );
294 * Try to add the entry to the cache, assign it a new dnid.
296 rc = cache_add_entry_rw(&li->li_cache, e, CACHE_WRITE_LOCK);
300 /* free parent and writer lock */
301 cache_return_entry_w( &li->li_cache, p );
305 /* release root lock */
306 ldap_pvt_thread_mutex_unlock(&li->li_root_mutex);
310 LDAP_LOG(( "backend", LDAP_LEVEL_ERR,
311 "ldbm_back_add: cache_add_entry_lock failed.\n" ));
313 Debug( LDAP_DEBUG_ANY, "cache_add_entry_lock failed\n", 0, 0,
317 send_ldap_result( conn, op,
318 rc > 0 ? LDAP_ALREADY_EXISTS : LDAP_OTHER,
319 NULL, rc > 0 ? NULL : "cache add failed", NULL, NULL );
326 /* attribute indexes */
327 if ( index_entry_add( be, e, e->e_attrs ) != LDAP_SUCCESS ) {
329 LDAP_LOG(( "backend", LDAP_LEVEL_ERR,
330 "ldbm_back_add: index_entry_add failed.\n" ));
332 Debug( LDAP_DEBUG_TRACE, "index_entry_add failed\n", 0,
336 send_ldap_result( conn, op, LDAP_OTHER,
337 NULL, "index generation failed", NULL, NULL );
343 if ( dn2id_add( be, e->e_ndn, e->e_id ) != 0 ) {
345 LDAP_LOG(( "backend", LDAP_LEVEL_ERR,
346 "ldbm_back_add: dn2id_add failed.\n" ));
348 Debug( LDAP_DEBUG_TRACE, "dn2id_add failed\n", 0,
351 /* FIXME: delete attr indices? */
353 send_ldap_result( conn, op, LDAP_OTHER,
354 NULL, "DN index generation failed", NULL, NULL );
360 if ( id2entry_add( be, e ) != 0 ) {
362 LDAP_LOG(( "backend", LDAP_LEVEL_ERR,
363 "ldbm_back_add: id2entry_add failed.\n" ));
365 Debug( LDAP_DEBUG_TRACE, "id2entry_add failed\n", 0,
369 /* FIXME: delete attr indices? */
370 (void) dn2id_delete( be, e->e_ndn, e->e_id );
372 send_ldap_result( conn, op, LDAP_OTHER,
373 NULL, "entry store failed", NULL, NULL );
378 send_ldap_result( conn, op, LDAP_SUCCESS,
379 NULL, NULL, NULL, NULL );
381 /* marks the entry as committed, so it is added to the cache;
382 * otherwise it is removed from the cache, but not destroyed;
383 * it will be destroyed by the caller */
385 cache_entry_commit( e );
389 /* free parent and writer lock */
390 cache_return_entry_w( &li->li_cache, p );
394 /* release root lock */
395 ldap_pvt_thread_mutex_unlock(&li->li_root_mutex);
399 /* in case of error, writer lock is freed
400 * and entry's private data is destroyed */
401 cache_return_entry_w( &li->li_cache, e );