1 /* add.c - ldap ldbm back-end add routine */
11 #include "back-ldbm.h"
12 #include "proto-back-ldbm.h"
22 struct ldbminfo *li = (struct ldbminfo *) be->be_private;
28 Debug(LDAP_DEBUG_ARGS, "==> ldbm_back_add: %s\n", e->e_dn, 0, 0);
30 /* nobody else can add until we lock our parent */
31 ldap_pvt_thread_mutex_lock(&li->li_add_mutex);
33 if ( ( dn2id( be, e->e_ndn ) ) != NOID ) {
34 ldap_pvt_thread_mutex_unlock(&li->li_add_mutex);
36 send_ldap_result( conn, op, LDAP_ALREADY_EXISTS,
37 NULL, NULL, NULL, NULL );
41 if ( global_schemacheck && oc_schema_check( e ) != 0 ) {
42 ldap_pvt_thread_mutex_unlock(&li->li_add_mutex);
44 Debug( LDAP_DEBUG_TRACE, "entry failed schema check\n",
48 send_ldap_result( conn, op, LDAP_OBJECT_CLASS_VIOLATION,
49 NULL, NULL, NULL, NULL );
54 * Get the parent dn and see if the corresponding entry exists.
55 * If the parent does not exist, only allow the "root" user to
59 pdn = dn_parent( be, e->e_ndn );
61 if( pdn != NULL && *pdn != '\0' && !be_issuffix(be, "") ) {
62 Entry *matched = NULL;
64 assert( *pdn != '\0' );
66 /* get parent with writer lock */
67 if ( (p = dn2entry_w( be, pdn, &matched )) == NULL ) {
71 ldap_pvt_thread_mutex_unlock(&li->li_add_mutex);
73 if ( matched != NULL ) {
74 matched_dn = ch_strdup( matched->e_dn );
75 refs = is_entry_referral( matched )
76 ? get_entry_referrals( be, conn, op, matched )
78 cache_return_entry_r( &li->li_cache, matched );
82 refs = default_referral;
85 Debug( LDAP_DEBUG_TRACE, "parent does not exist\n",
88 send_ldap_result( conn, op, LDAP_REFERRAL,
89 matched_dn, NULL, refs, NULL );
91 if( matched != NULL ) {
101 /* don't need the add lock anymore */
102 ldap_pvt_thread_mutex_unlock(&li->li_add_mutex);
106 if ( ! access_allowed( be, conn, op, p,
107 "children", NULL, ACL_WRITE ) )
109 /* free parent and writer lock */
110 cache_return_entry_w( &li->li_cache, p );
112 Debug( LDAP_DEBUG_TRACE, "no access to parent\n", 0,
114 send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
115 NULL, NULL, NULL, NULL );
122 if ( is_entry_alias( p ) ) {
123 /* parent is an alias, don't allow add */
125 /* free parent and writer lock */
126 cache_return_entry_w( &li->li_cache, p );
128 Debug( LDAP_DEBUG_TRACE, "parent is alias\n", 0,
131 send_ldap_result( conn, op, LDAP_ALIAS_PROBLEM,
132 NULL, NULL, NULL, NULL );
138 if ( is_entry_referral( p ) ) {
139 /* parent is a referral, don't allow add */
140 char *matched_dn = ch_strdup( p->e_dn );
141 struct berval **refs = is_entry_referral( p )
142 ? get_entry_referrals( be, conn, op, p )
145 /* free parent and writer lock */
146 cache_return_entry_w( &li->li_cache, p );
148 Debug( LDAP_DEBUG_TRACE, "parent is referral\n", 0,
150 send_ldap_result( conn, op, LDAP_REFERRAL,
151 matched_dn, NULL, refs, NULL );
153 ber_bvecfree( refs );
161 assert( *pdn == '\0' );
165 /* no parent, must be adding entry to root */
166 if ( ! be_isroot( be, op->o_ndn ) ) {
167 ldap_pvt_thread_mutex_unlock(&li->li_add_mutex);
169 Debug( LDAP_DEBUG_TRACE, "%s add denied\n",
170 pdn == NULL ? "suffix" : "entry at root",
173 send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
174 NULL, NULL, NULL, NULL );
181 * no parent, acquire the root write lock
182 * and release the add lock.
184 ldap_pvt_thread_mutex_lock(&li->li_root_mutex);
186 ldap_pvt_thread_mutex_unlock(&li->li_add_mutex);
189 e->e_id = next_id( be );
192 * Try to add the entry to the cache, assign it a new dnid.
194 rc = cache_add_entry_rw(&li->li_cache, e, CACHE_WRITE_LOCK);
198 /* free parent and writer lock */
199 cache_return_entry_w( &li->li_cache, p );
203 /* release root lock */
204 ldap_pvt_thread_mutex_unlock(&li->li_root_mutex);
207 Debug( LDAP_DEBUG_ANY, "cache_add_entry_lock failed\n", 0, 0,
211 next_id_return( be, e->e_id );
216 send_ldap_result( conn, op,
217 rc > 0 ? LDAP_ALREADY_EXISTS : LDAP_OPERATIONS_ERROR,
218 NULL, NULL, NULL, NULL );
226 * add it to the id2children index for the parent
229 if ( id2children_add( be, p, e ) != 0 ) {
230 Debug( LDAP_DEBUG_TRACE, "id2children_add failed\n", 0,
232 send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
233 NULL, NULL, NULL, NULL );
239 * Add the entry to the attribute indexes, then add it to
240 * the id2children index, dn2id index, and the id2entry index.
243 /* attribute indexes */
244 if ( index_add_entry( be, e ) != 0 ) {
245 Debug( LDAP_DEBUG_TRACE, "index_add_entry failed\n", 0,
247 send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
248 NULL, NULL, NULL, NULL );
254 if ( dn2id_add( be, e->e_ndn, e->e_id ) != 0 ) {
255 Debug( LDAP_DEBUG_TRACE, "dn2id_add failed\n", 0,
257 send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
258 NULL, NULL, NULL, NULL );
264 if ( id2entry_add( be, e ) != 0 ) {
265 Debug( LDAP_DEBUG_TRACE, "id2entry_add failed\n", 0,
267 (void) dn2id_delete( be, e->e_ndn );
268 send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
269 NULL, NULL, NULL, NULL );
274 send_ldap_result( conn, op, LDAP_SUCCESS,
275 NULL, NULL, NULL, NULL );
280 /* free parent and writer lock */
281 cache_return_entry_w( &li->li_cache, p );
285 /* release root lock */
286 ldap_pvt_thread_mutex_unlock(&li->li_root_mutex);
290 /* free entry and writer lock */
291 cache_return_entry_w( &li->li_cache, e );