1 /* add.c - ldap ldbm back-end add routine */
4 * Copyright 1998-1999 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 #ifdef SLAPD_SCHEMA_NOT_COMPAT
34 static AttributeDescription *children = NULL;
36 static const char *children = "children";
40 Debug(LDAP_DEBUG_ARGS, "==> ldbm_back_add: %s\n", e->e_dn, 0, 0);
42 /* nobody else can add until we lock our parent */
43 ldap_pvt_thread_mutex_lock(&li->li_add_mutex);
45 if ( ( dn2id( be, e->e_ndn ) ) != NOID ) {
46 ldap_pvt_thread_mutex_unlock(&li->li_add_mutex);
48 send_ldap_result( conn, op, LDAP_ALREADY_EXISTS,
49 NULL, NULL, NULL, NULL );
53 if ( schema_check_entry( e ) != 0 ) {
54 ldap_pvt_thread_mutex_unlock(&li->li_add_mutex);
56 Debug( LDAP_DEBUG_TRACE, "entry failed schema check\n",
60 send_ldap_result( conn, op, LDAP_OBJECT_CLASS_VIOLATION,
61 NULL, NULL, NULL, NULL );
66 * Get the parent dn and see if the corresponding entry exists.
67 * If the parent does not exist, only allow the "root" user to
71 pdn = dn_parent( be, e->e_ndn );
73 if( pdn != NULL && *pdn != '\0' ) {
74 Entry *matched = NULL;
76 assert( *pdn != '\0' );
78 /* get parent with writer lock */
79 if ( (p = dn2entry_w( be, pdn, &matched )) == NULL ) {
83 ldap_pvt_thread_mutex_unlock(&li->li_add_mutex);
85 if ( matched != NULL ) {
86 matched_dn = ch_strdup( matched->e_dn );
87 refs = is_entry_referral( matched )
88 ? get_entry_referrals( be, conn, op, matched )
90 cache_return_entry_r( &li->li_cache, matched );
94 refs = default_referral;
97 Debug( LDAP_DEBUG_TRACE, "parent does not exist\n",
100 send_ldap_result( conn, op, LDAP_REFERRAL,
101 matched_dn, NULL, refs, NULL );
103 if( matched != NULL ) {
104 ber_bvecfree( refs );
113 /* don't need the add lock anymore */
114 ldap_pvt_thread_mutex_unlock(&li->li_add_mutex);
118 if ( ! access_allowed( be, conn, op, p,
119 children, NULL, ACL_WRITE ) )
121 /* free parent and writer lock */
122 cache_return_entry_w( &li->li_cache, p );
124 Debug( LDAP_DEBUG_TRACE, "no access to parent\n", 0,
126 send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
127 NULL, NULL, NULL, NULL );
134 if ( is_entry_alias( p ) ) {
135 /* parent is an alias, don't allow add */
137 /* free parent and writer lock */
138 cache_return_entry_w( &li->li_cache, p );
140 Debug( LDAP_DEBUG_TRACE, "parent is alias\n", 0,
143 send_ldap_result( conn, op, LDAP_ALIAS_PROBLEM,
144 NULL, NULL, NULL, NULL );
150 if ( is_entry_referral( p ) ) {
151 /* parent is a referral, don't allow add */
152 char *matched_dn = ch_strdup( p->e_dn );
153 struct berval **refs = is_entry_referral( p )
154 ? get_entry_referrals( be, conn, op, p )
157 /* free parent and writer lock */
158 cache_return_entry_w( &li->li_cache, p );
160 Debug( LDAP_DEBUG_TRACE, "parent is referral\n", 0,
162 send_ldap_result( conn, op, LDAP_REFERRAL,
163 matched_dn, NULL, refs, NULL );
165 ber_bvecfree( refs );
173 assert( *pdn == '\0' );
177 /* no parent, must be adding entry to root */
178 if ( !be_isroot( be, op->o_ndn ) && !be_issuffix( be, "" ) ) {
179 ldap_pvt_thread_mutex_unlock(&li->li_add_mutex);
181 Debug( LDAP_DEBUG_TRACE, "%s add denied\n",
182 pdn == NULL ? "suffix" : "entry at root",
185 send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
186 NULL, NULL, NULL, NULL );
193 * no parent, acquire the root write lock
194 * and release the add lock.
196 ldap_pvt_thread_mutex_lock(&li->li_root_mutex);
198 ldap_pvt_thread_mutex_unlock(&li->li_add_mutex);
201 e->e_id = next_id( be );
204 * Try to add the entry to the cache, assign it a new dnid.
206 rc = cache_add_entry_rw(&li->li_cache, e, CACHE_WRITE_LOCK);
210 /* free parent and writer lock */
211 cache_return_entry_w( &li->li_cache, p );
215 /* release root lock */
216 ldap_pvt_thread_mutex_unlock(&li->li_root_mutex);
219 Debug( LDAP_DEBUG_ANY, "cache_add_entry_lock failed\n", 0, 0,
225 send_ldap_result( conn, op,
226 rc > 0 ? LDAP_ALREADY_EXISTS : LDAP_OPERATIONS_ERROR,
227 NULL, NULL, NULL, NULL );
235 * Add the entry to the attribute indexes, then add it to
236 * the id2children index, dn2id index, and the id2entry index.
239 /* attribute indexes */
240 if ( index_add_entry( be, e ) != 0 ) {
241 Debug( LDAP_DEBUG_TRACE, "index_add_entry failed\n", 0,
243 send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
244 NULL, NULL, NULL, NULL );
250 if ( dn2id_add( be, e->e_ndn, e->e_id ) != 0 ) {
251 Debug( LDAP_DEBUG_TRACE, "dn2id_add failed\n", 0,
253 send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
254 NULL, NULL, NULL, NULL );
260 if ( id2entry_add( be, e ) != 0 ) {
261 Debug( LDAP_DEBUG_TRACE, "id2entry_add failed\n", 0,
263 (void) dn2id_delete( be, e->e_ndn, e->e_id );
264 send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
265 NULL, NULL, NULL, NULL );
270 send_ldap_result( conn, op, LDAP_SUCCESS,
271 NULL, NULL, NULL, NULL );
276 /* free parent and writer lock */
277 cache_return_entry_w( &li->li_cache, p );
281 /* release root lock */
282 ldap_pvt_thread_mutex_unlock(&li->li_root_mutex);
286 /* free entry and writer lock */
287 cache_return_entry_w( &li->li_cache, e );