1 /* add.c - ldap ldbm back-end add routine */
3 * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
4 * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
11 #include <ac/socket.h>
12 #include <ac/string.h>
15 #include "back-ldbm.h"
16 #include "proto-back-ldbm.h"
26 struct ldbminfo *li = (struct ldbminfo *) be->be_private;
32 Debug(LDAP_DEBUG_ARGS, "==> ldbm_back_add: %s\n", e->e_dn, 0, 0);
34 /* nobody else can add until we lock our parent */
35 ldap_pvt_thread_mutex_lock(&li->li_add_mutex);
37 if ( ( dn2id( be, e->e_ndn ) ) != NOID ) {
38 ldap_pvt_thread_mutex_unlock(&li->li_add_mutex);
40 send_ldap_result( conn, op, LDAP_ALREADY_EXISTS,
41 NULL, NULL, NULL, NULL );
45 if ( global_schemacheck && oc_schema_check( e ) != 0 ) {
46 ldap_pvt_thread_mutex_unlock(&li->li_add_mutex);
48 Debug( LDAP_DEBUG_TRACE, "entry failed schema check\n",
52 send_ldap_result( conn, op, LDAP_OBJECT_CLASS_VIOLATION,
53 NULL, NULL, NULL, NULL );
58 * Get the parent dn and see if the corresponding entry exists.
59 * If the parent does not exist, only allow the "root" user to
63 pdn = dn_parent( be, e->e_ndn );
65 if( pdn != NULL && *pdn != '\0' ) {
66 Entry *matched = NULL;
68 assert( *pdn != '\0' );
70 /* get parent with writer lock */
71 if ( (p = dn2entry_w( be, pdn, &matched )) == NULL ) {
75 ldap_pvt_thread_mutex_unlock(&li->li_add_mutex);
77 if ( matched != NULL ) {
78 matched_dn = ch_strdup( matched->e_dn );
79 refs = is_entry_referral( matched )
80 ? get_entry_referrals( be, conn, op, matched )
82 cache_return_entry_r( &li->li_cache, matched );
86 refs = default_referral;
89 Debug( LDAP_DEBUG_TRACE, "parent does not exist\n",
92 send_ldap_result( conn, op, LDAP_REFERRAL,
93 matched_dn, NULL, refs, NULL );
95 if( matched != NULL ) {
105 /* don't need the add lock anymore */
106 ldap_pvt_thread_mutex_unlock(&li->li_add_mutex);
110 if ( ! access_allowed( be, conn, op, p,
111 "children", NULL, ACL_WRITE ) )
113 /* free parent and writer lock */
114 cache_return_entry_w( &li->li_cache, p );
116 Debug( LDAP_DEBUG_TRACE, "no access to parent\n", 0,
118 send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
119 NULL, NULL, NULL, NULL );
126 if ( is_entry_alias( p ) ) {
127 /* parent is an alias, don't allow add */
129 /* free parent and writer lock */
130 cache_return_entry_w( &li->li_cache, p );
132 Debug( LDAP_DEBUG_TRACE, "parent is alias\n", 0,
135 send_ldap_result( conn, op, LDAP_ALIAS_PROBLEM,
136 NULL, NULL, NULL, NULL );
142 if ( is_entry_referral( p ) ) {
143 /* parent is a referral, don't allow add */
144 char *matched_dn = ch_strdup( p->e_dn );
145 struct berval **refs = is_entry_referral( p )
146 ? get_entry_referrals( be, conn, op, p )
149 /* free parent and writer lock */
150 cache_return_entry_w( &li->li_cache, p );
152 Debug( LDAP_DEBUG_TRACE, "parent is referral\n", 0,
154 send_ldap_result( conn, op, LDAP_REFERRAL,
155 matched_dn, NULL, refs, NULL );
157 ber_bvecfree( refs );
165 assert( *pdn == '\0' );
169 /* no parent, must be adding entry to root */
170 if ( !be_isroot( be, op->o_ndn ) && !be_issuffix( be, "" ) ) {
171 ldap_pvt_thread_mutex_unlock(&li->li_add_mutex);
173 Debug( LDAP_DEBUG_TRACE, "%s add denied\n",
174 pdn == NULL ? "suffix" : "entry at root",
177 send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
178 NULL, NULL, NULL, NULL );
185 * no parent, acquire the root write lock
186 * and release the add lock.
188 ldap_pvt_thread_mutex_lock(&li->li_root_mutex);
190 ldap_pvt_thread_mutex_unlock(&li->li_add_mutex);
193 e->e_id = next_id( be );
196 * Try to add the entry to the cache, assign it a new dnid.
198 rc = cache_add_entry_rw(&li->li_cache, e, CACHE_WRITE_LOCK);
202 /* free parent and writer lock */
203 cache_return_entry_w( &li->li_cache, p );
207 /* release root lock */
208 ldap_pvt_thread_mutex_unlock(&li->li_root_mutex);
211 Debug( LDAP_DEBUG_ANY, "cache_add_entry_lock failed\n", 0, 0,
217 send_ldap_result( conn, op,
218 rc > 0 ? LDAP_ALREADY_EXISTS : LDAP_OPERATIONS_ERROR,
219 NULL, NULL, NULL, NULL );
227 * Add the entry to the attribute indexes, then add it to
228 * the id2children index, dn2id index, and the id2entry index.
231 /* attribute indexes */
232 if ( index_add_entry( be, e ) != 0 ) {
233 Debug( LDAP_DEBUG_TRACE, "index_add_entry failed\n", 0,
235 send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
236 NULL, NULL, NULL, NULL );
242 if ( dn2id_add( be, e->e_ndn, e->e_id ) != 0 ) {
243 Debug( LDAP_DEBUG_TRACE, "dn2id_add failed\n", 0,
245 send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
246 NULL, NULL, NULL, NULL );
252 if ( id2entry_add( be, e ) != 0 ) {
253 Debug( LDAP_DEBUG_TRACE, "id2entry_add failed\n", 0,
255 (void) dn2id_delete( be, e->e_ndn );
256 send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
257 NULL, NULL, NULL, NULL );
262 send_ldap_result( conn, op, LDAP_SUCCESS,
263 NULL, NULL, NULL, NULL );
268 /* free parent and writer lock */
269 cache_return_entry_w( &li->li_cache, p );
273 /* release root lock */
274 ldap_pvt_thread_mutex_unlock(&li->li_root_mutex);
278 /* free entry and writer lock */
279 cache_return_entry_w( &li->li_cache, e );