]> git.sur5r.net Git - openldap/blobdiff - servers/slapd/back-ldbm/modrdn.c
Set peeraddr also for IPv6, fixes ITS#1918
[openldap] / servers / slapd / back-ldbm / modrdn.c
index 17efe09f314dbe73618b7253a6babb345c53fa1c..59aee6894c5d6a2318369dc978ef29c46b4a4701 100644 (file)
@@ -1,7 +1,7 @@
 /* modrdn.c - ldbm backend modrdn routine */
 /* $OpenLDAP$ */
 /*
- * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved.
+ * Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved.
  * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
  */
 
@@ -53,7 +53,6 @@ ldbm_back_modrdn(
        Entry           *e, *p = NULL;
        Entry           *matched;
        int             isroot = -1;
-       int             rootlock = 0;
 #define CAN_ROLLBACK   -1
 #define MUST_DESTROY   1
        int             rc = CAN_ROLLBACK;
@@ -63,8 +62,8 @@ ldbm_back_modrdn(
        char textbuf[SLAP_TEXT_BUFLEN];
        size_t textlen = sizeof textbuf;
        /* Added to support LDAP v2 correctly (deleteoldrdn thing) */
-       LDAPRDN         *new_rdn;
-       LDAPRDN         *old_rdn;
+       LDAPRDN         *new_rdn = NULL;
+       LDAPRDN         *old_rdn = NULL;
        int             a_cnt, d_cnt;
        /* Added to support newSuperior */ 
        Entry           *np = NULL;     /* newSuperior Entry */
@@ -88,10 +87,13 @@ ldbm_back_modrdn(
                        ? newSuperior->bv_val : "NULL", 0 );
 #endif
 
+       /* grab giant lock for writing */
+       ldap_pvt_thread_rdwr_wlock(&li->li_giant_rwlock);
+
        /* get entry with writer lock */
        if ( (e = dn2entry_w( be, ndn, &matched )) == NULL ) {
                char* matched_dn = NULL;
-               struct berval** refs;
+               BerVarray refs;
 
                if( matched != NULL ) {
                        matched_dn = strdup( matched->e_dn );
@@ -104,10 +106,12 @@ ldbm_back_modrdn(
                                NULL, dn, LDAP_SCOPE_DEFAULT );
                }
 
+               ldap_pvt_thread_rdwr_wunlock(&li->li_giant_rwlock);
+
                send_ldap_result( conn, op, LDAP_REFERRAL,
                        matched_dn, NULL, refs, NULL );
 
-               ber_bvecfree( refs );
+               if ( refs ) ber_bvarray_free( refs );
                free( matched_dn );
 
                return( -1 );
@@ -116,7 +120,7 @@ ldbm_back_modrdn(
        if (!manageDSAit && is_entry_referral( e ) ) {
                /* parent is a referral, don't allow add */
                /* parent is an alias, don't allow add */
-               struct berval **refs = get_entry_referrals( be,
+               BerVarray refs = get_entry_referrals( be,
                        conn, op, e );
 
 #ifdef NEW_LOGGING
@@ -130,7 +134,7 @@ ldbm_back_modrdn(
                send_ldap_result( conn, op, LDAP_REFERRAL,
                    e->e_dn, NULL, refs, NULL );
 
-               ber_bvecfree( refs );
+               if ( refs ) ber_bvarray_free( refs );
                goto return_results;
        }
 
@@ -148,11 +152,11 @@ ldbm_back_modrdn(
                goto return_results;
        }
 
-       p_ndn.bv_val = dn_parent( be, e->e_ndn );
-       if ( p_ndn.bv_val )
-               p_ndn.bv_len = e->e_nname.bv_len - (p_ndn.bv_val - e->e_ndn);
-       else
-               p_ndn.bv_len = 0;
+       if ( be_issuffix( be, &e->e_nname ) ) {
+               p_ndn = slap_empty_bv ;
+       } else {
+               dnParent( &e->e_nname, &p_ndn );
+       }
 
        if ( p_ndn.bv_len != 0 ) {
                /* Make sure parent entry exist and we can write its 
@@ -176,7 +180,7 @@ ldbm_back_modrdn(
 
                /* check parent for "children" acl */
                if ( ! access_allowed( be, conn, op, p,
-                       children, NULL, ACL_WRITE ) )
+                       children, NULL, ACL_WRITE, NULL ) )
                {
 #ifdef NEW_LOGGING
                        LDAP_LOG(( "backend", LDAP_LEVEL_INFO,
@@ -201,11 +205,11 @@ ldbm_back_modrdn(
                       p_ndn.bv_val, 0, 0 );
 #endif
 
-               p_dn.bv_val = dn_parent( be, e->e_dn );
-               if ( p_dn.bv_val )
-                       p_dn.bv_len = e->e_name.bv_len - (p_dn.bv_val - e->e_dn);
-               else
-                       p_dn.bv_len = 0;
+               if ( p_ndn.bv_val == slap_empty_bv.bv_val ) {
+                       p_dn = slap_empty_bv;
+               } else {
+                       dnParent( &e->e_name, &p_dn );
+               }
 
 #ifdef NEW_LOGGING
                LDAP_LOG(( "backend", LDAP_LEVEL_DETAIL1,
@@ -219,11 +223,11 @@ ldbm_back_modrdn(
                /* no parent, must be root to modify rdn */
                isroot = be_isroot( be, &op->o_ndn );
                if ( ! isroot ) {
-                       if ( be_issuffix( be, "" ) || be_isupdate( be, &op->o_ndn ) ) {
+                       if ( be_issuffix( be, (struct berval *)&slap_empty_bv ) || be_isupdate( be, &op->o_ndn ) ) {
                                p = (Entry *)&slap_entry_root;
                                
                                rc = access_allowed( be, conn, op, p,
-                                               children, NULL, ACL_WRITE );
+                                               children, NULL, ACL_WRITE, NULL );
                                p = NULL;
                                                                
                                /* check parent for "children" acl */
@@ -262,9 +266,6 @@ ldbm_back_modrdn(
                        }
                }
 
-               ldap_pvt_thread_mutex_lock(&li->li_root_mutex);
-               rootlock = 1;
-               
 #ifdef NEW_LOGGING
                LDAP_LOG(( "backend", LDAP_LEVEL_INFO,
                           "ldbm_back_modrdn: (%s) no parent, locked root.\n", e->e_dn ));
@@ -291,8 +292,7 @@ ldbm_back_modrdn(
                np_ndn = nnewSuperior;
 
                /* newSuperior == oldParent? */
-               if ( p_ndn.bv_len == np_ndn->bv_len &&
-                       strcmp( p_ndn.bv_val, np_ndn->bv_val ) == 0 ) {
+               if ( dn_match( &p_ndn, np_ndn ) ) {
 #ifdef NEW_LOGGING
                        LDAP_LOG(( "backend", LDAP_LEVEL_INFO, "ldbm_back_modrdn: "
                                "new parent\"%s\" seems to be the same as the "
@@ -341,7 +341,7 @@ ldbm_back_modrdn(
 
                        /* check newSuperior for "children" acl */
                        if ( !access_allowed( be, conn, op, np, children, NULL,
-                                             ACL_WRITE ) )
+                                             ACL_WRITE, NULL ) )
                        {
 #ifdef NEW_LOGGING
                                LDAP_LOG(( "backend", LDAP_LEVEL_INFO,
@@ -398,11 +398,11 @@ ldbm_back_modrdn(
                        }
 
                        if ( ! isroot ) {
-                               if ( be_issuffix( be, "" ) || be_isupdate( be, &op->o_ndn ) ) {
+                               if ( be_issuffix( be, (struct berval *)&slap_empty_bv ) || be_isupdate( be, &op->o_ndn ) ) {
                                        np = (Entry *)&slap_entry_root;
                                
                                        rc = access_allowed( be, conn, op, np,
-                                                       children, NULL, ACL_WRITE );
+                                                       children, NULL, ACL_WRITE, NULL );
                                        np = NULL;
                                                                
                                        /* check parent for "children" acl */
@@ -468,13 +468,10 @@ ldbm_back_modrdn(
 #endif
 
        /* check for abandon */
-       ldap_pvt_thread_mutex_lock( &op->o_abandonmutex );
        if ( op->o_abandon ) {
-               ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex );
                goto return_results;
        }
 
-       ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex );
        if ( ( rc_id = dn2id ( be, &new_ndn, &id ) ) || id != NOID ) {
                /* if (rc_id) something bad happened to ldbm cache */
                send_ldap_result( conn, op, 
@@ -496,7 +493,9 @@ ldbm_back_modrdn(
        /* Get attribute types and values of our new rdn, we will
         * need to add that to our new entry
         */
-       if ( ldap_str2rdn( newrdn->bv_val, &new_rdn, &text, LDAP_DN_FORMAT_LDAP ) ) {
+       if ( ldap_bv2rdn( newrdn, &new_rdn, (char **)&text,
+               LDAP_DN_FORMAT_LDAP ) )
+       {
 #ifdef NEW_LOGGING
                LDAP_LOG(( "backend", LDAP_LEVEL_INFO,
                        "ldbm_back_modrdn: can't figure out type(s)/value(s) of newrdn\n" ));
@@ -522,7 +521,9 @@ ldbm_back_modrdn(
 #endif
 
        /* Retrieve the old rdn from the entry's dn */
-       if ( ldap_str2rdn( dn->bv_val, &old_rdn, &text, LDAP_DN_FORMAT_LDAP ) ) {
+       if ( ldap_bv2rdn( dn, &old_rdn, (char **)&text,
+               LDAP_DN_FORMAT_LDAP ) )
+       {
 #ifdef NEW_LOGGING
                LDAP_LOG(( "backend", LDAP_LEVEL_INFO,
                           "ldbm_back_modrdn: can't figure out the old_rdn type(s)/value(s).\n" ));
@@ -588,7 +589,7 @@ ldbm_back_modrdn(
                }
 
                if ( ! access_allowed( be, conn, op, e, 
-                               desc, &new_rdn[0][a_cnt]->la_value, ACL_WRITE ) ) {
+                               desc, &new_rdn[0][a_cnt]->la_value, ACL_WRITE, NULL ) ) {
 #ifdef NEW_LOGGING
                        LDAP_LOG(( "backend", LDAP_LEVEL_INFO,
                                   "ldbm_back_modrdn: access "
@@ -608,11 +609,11 @@ ldbm_back_modrdn(
                }
 
                mod_tmp = (Modifications *)ch_malloc( sizeof( Modifications )
-                       + 2 * sizeof( struct berval ) );
+                       + 2 * sizeof( struct berval ) );
                mod_tmp->sml_desc = desc;
-               mod_tmp->sml_bvalues = (struct berval **)( mod_tmp + 1 );
-               mod_tmp->sml_bvalues[0] = &new_rdn[0][a_cnt]->la_value;
-               mod_tmp->sml_bvalues[1] = NULL;
+               mod_tmp->sml_bvalues = (BerVarray)( mod_tmp + 1 );
+               mod_tmp->sml_bvalues[0] = new_rdn[0][a_cnt]->la_value;
+               mod_tmp->sml_bvalues[1].bv_val = NULL;
                mod_tmp->sml_op = SLAP_MOD_SOFTADD;
                mod_tmp->sml_next = mod;
                mod = mod_tmp;
@@ -661,7 +662,7 @@ ldbm_back_modrdn(
                        }
 
                        if ( ! access_allowed( be, conn, op, e, 
-                                       desc, &old_rdn[0][d_cnt]->la_value, ACL_WRITE ) ) {
+                                       desc, &old_rdn[0][d_cnt]->la_value, ACL_WRITE, NULL ) ) {
 #ifdef NEW_LOGGING
                                LDAP_LOG(( "backend", LDAP_LEVEL_INFO,
                                           "ldbm_back_modrdn: access "
@@ -682,11 +683,11 @@ ldbm_back_modrdn(
 
                        /* Remove old value of rdn as an attribute. */
                        mod_tmp = (Modifications *)ch_malloc( sizeof( Modifications )
-                               + 2 * sizeof( struct berval ) );
+                               + 2 * sizeof( struct berval ) );
                        mod_tmp->sml_desc = desc;
-                       mod_tmp->sml_bvalues = (struct berval **)(mod_tmp+1);
-                       mod_tmp->sml_bvalues[0] = &old_rdn[0][d_cnt]->la_value;
-                       mod_tmp->sml_bvalues[1] = NULL;
+                       mod_tmp->sml_bvalues = (BerVarray)(mod_tmp+1);
+                       mod_tmp->sml_bvalues[0] = old_rdn[0][d_cnt]->la_value;
+                       mod_tmp->sml_bvalues[1].bv_val = NULL;
                        mod_tmp->sml_op = LDAP_MOD_DELETE;
                        mod_tmp->sml_next = mod;
                        mod = mod_tmp;
@@ -704,12 +705,9 @@ ldbm_back_modrdn(
 
        
        /* check for abandon */
-       ldap_pvt_thread_mutex_lock( &op->o_abandonmutex );
        if ( op->o_abandon ) {
-               ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex );
                goto return_results;
        }
-       ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex );
 
        /* delete old one */
        if ( dn2id_delete( be, &e->e_nname, e->e_id ) != 0 ) {
@@ -801,11 +799,6 @@ return_results:
                cache_return_entry_w( &li->li_cache, p );
        }
 
-       if ( rootlock ) {
-               /* release root writer lock */
-               ldap_pvt_thread_mutex_unlock(&li->li_root_mutex);
-       }
-
        /* free entry and writer lock */
        cache_return_entry_w( &li->li_cache, e );
        if ( rc == MUST_DESTROY ) {
@@ -814,5 +807,6 @@ return_results:
                 * the entry must be freed */
                entry_free( e );
        }
+       ldap_pvt_thread_rdwr_wunlock(&li->li_giant_rwlock);
        return( rc );
 }