X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=servers%2Fslapd%2Fback-bdb%2Fmodrdn.c;h=2e3824a2ac0a7d15b74a8a91f6a5b2661fb6be7f;hb=ac7ac5acefdf859251a37274167200374d37cba9;hp=b49df286fe2802208f67275d8ec36c49cd51e584;hpb=323689da57e7202986ca46f1b14f7e7e2d2f640d;p=openldap diff --git a/servers/slapd/back-bdb/modrdn.c b/servers/slapd/back-bdb/modrdn.c index b49df286fe..2e3824a2ac 100644 --- a/servers/slapd/back-bdb/modrdn.c +++ b/servers/slapd/back-bdb/modrdn.c @@ -1,7 +1,7 @@ /* modrdn.c - bdb backend modrdn routine */ /* $OpenLDAP$ */ /* - * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. + * Copyright 1998-2003 The OpenLDAP Foundation, All Rights Reserved. * COPYING RESTRICTIONS APPLY, see COPYRIGHT file */ @@ -14,580 +14,861 @@ #include "external.h" int -bdb_modrdn( - Backend *be, - Connection *conn, - Operation *op, - const char *dn, - const char *ndn, - const char *newrdn, - int deleteoldrdn, - const char *newSuperior -) +bdb_modrdn( Operation *op, SlapReply *rs ) { - struct bdb_info *bdb = (struct bdb_info *) be->be_private; + struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private; AttributeDescription *children = slap_schema.si_ad_children; - char *p_dn = NULL, *p_ndn = NULL; - char *new_dn = NULL, *new_ndn = NULL; + AttributeDescription *entry = slap_schema.si_ad_entry; + struct berval p_dn, p_ndn; + struct berval new_dn = {0, NULL}, new_ndn = {0, NULL}; int isroot = -1; - Entry *e, *p = NULL; - Entry *matched; - int rc; - const char *text; + Entry *e = NULL; + Entry *p = NULL; + EntryInfo *ei = NULL, *eip = NULL, *nei = NULL, *neip = NULL; + /* LDAP v2 supporting correct attribute handling. */ + LDAPRDN new_rdn = NULL; + LDAPRDN old_rdn = NULL; char textbuf[SLAP_TEXT_BUFLEN]; size_t textlen = sizeof textbuf; - DB_TXN * ltid = NULL; + DB_TXN *ltid = NULL, *lt2; struct bdb_op_info opinfo; + Entry dummy, *save; ID id; - char **new_rdn_vals = NULL; /* Vals of new rdn */ - char **new_rdn_types = NULL; /* Types of new rdn */ - int a_cnt, d_cnt; - char *old_rdn = NULL; /* Old rdn's attr type & val */ - char **old_rdn_types = NULL; /* Types of old rdn attr. */ - char **old_rdn_vals = NULL; /* Old rdn attribute values */ - - Entry *np = NULL; /* newSuperior Entry */ - char *np_dn = NULL; /* newSuperior dn */ - char *np_ndn = NULL; /* newSuperior ndn */ - char *new_parent_dn = NULL; /* np_dn, p_dn, or NULL */ + + Entry *np = NULL; /* newSuperior Entry */ + struct berval *np_dn = NULL; /* newSuperior dn */ + struct berval *np_ndn = NULL; /* newSuperior ndn */ + struct berval *new_parent_dn = NULL; /* np_dn, p_dn, or NULL */ /* Used to interface with bdb_modify_internal() */ Modifications *mod = NULL; /* Used to delete old rdn */ int manageDSAit = get_manageDSAit( op ); - Debug( LDAP_DEBUG_TRACE, "==>bdb_modrdn(%s,%s,%s)\n", - dn, newrdn, (newSuperior ? newSuperior : "NULL") ); + u_int32_t locker = 0; + DB_LOCK lock, plock, nplock; -#if 0 - if( newSuperior != NULL ) { - rc = LDAP_UNWILLING_TO_PERFORM; - text = "newSuperior not implemented (yet)"; - goto return_results; - } + int noop = 0; + +#if defined(LDAP_CLIENT_UPDATE) || defined(LDAP_SYNC) + Operation *ps_list; + struct psid_entry *pm_list, *pm_prev; #endif - if (0) { +#ifdef NEW_LOGGING + LDAP_LOG ( OPERATION, ENTRY, "==>bdb_modrdn(%s,%s,%s)\n", + op->o_req_dn.bv_val,op->oq_modrdn.rs_newrdn.bv_val, + op->oq_modrdn.rs_newSup ? op->oq_modrdn.rs_newSup->bv_val : "NULL" ); +#else + Debug( LDAP_DEBUG_TRACE, "==>bdb_modrdn(%s,%s,%s)\n", + op->o_req_dn.bv_val,op->oq_modrdn.rs_newrdn.bv_val, + op->oq_modrdn.rs_newSup ? op->oq_modrdn.rs_newSup->bv_val : "NULL" ); +#endif + + if( 0 ) { retry: /* transaction retry */ + if (e != NULL) { + bdb_unlocked_cache_return_entry_w(&bdb->bi_cache, e); + e = NULL; + } + if (p != NULL) { + bdb_unlocked_cache_return_entry_r(&bdb->bi_cache, p); + p = NULL; + } + if (np != NULL) { + bdb_unlocked_cache_return_entry_r(&bdb->bi_cache, np); + np = NULL; + } +#ifdef NEW_LOGGING + LDAP_LOG ( OPERATION, DETAIL1, "==>bdb_modrdn: retrying...\n", 0, 0, 0); +#else Debug( LDAP_DEBUG_TRACE, "==>bdb_modrdn: retrying...\n", 0, 0, 0 ); - rc = txn_abort( ltid ); +#endif + +#if defined(LDAP_CLIENT_UPDATE) || defined(LDAP_SYNC) + pm_list = LDAP_LIST_FIRST(&op->o_pm_list); + while ( pm_list != NULL ) { + LDAP_LIST_REMOVE ( pm_list, ps_link ); + pm_prev = pm_list; + pm_list = LDAP_LIST_NEXT ( pm_list, ps_link ); + ch_free( pm_prev ); + } +#endif + + rs->sr_err = TXN_ABORT( ltid ); ltid = NULL; op->o_private = NULL; - if( rc != 0 ) { - rc = LDAP_OTHER; - text = "internal error"; + op->o_do_not_cache = opinfo.boi_acl_cache; + if( rs->sr_err != 0 ) { + rs->sr_err = LDAP_OTHER; + rs->sr_text = "internal error"; goto return_results; } + ldap_pvt_thread_yield(); } - - if (bdb->bi_txn) { - /* begin transaction */ - rc = txn_begin( bdb->bi_dbenv, NULL, <id, 0 ); - text = NULL; - if( rc != 0 ) { + /* begin transaction */ + rs->sr_err = TXN_BEGIN( bdb->bi_dbenv, NULL, <id, + bdb->bi_db_opflags ); + rs->sr_text = NULL; + if( rs->sr_err != 0 ) { +#ifdef NEW_LOGGING + LDAP_LOG ( OPERATION, ERR, + "==>bdb_modrdn: txn_begin failed: %s (%d)\n", + db_strerror(rs->sr_err), rs->sr_err, 0 ); +#else Debug( LDAP_DEBUG_TRACE, "bdb_delete: txn_begin failed: %s (%d)\n", - db_strerror(rc), rc, 0 ); - rc = LDAP_OTHER; - text = "internal error"; + db_strerror(rs->sr_err), rs->sr_err, 0 ); +#endif + rs->sr_err = LDAP_OTHER; + rs->sr_text = "internal error"; goto return_results; - } } - opinfo.boi_bdb = be; + locker = TXN_ID ( ltid ); + + opinfo.boi_bdb = op->o_bd; opinfo.boi_txn = ltid; + opinfo.boi_locker = locker; opinfo.boi_err = 0; + opinfo.boi_acl_cache = op->o_do_not_cache; op->o_private = &opinfo; /* get entry */ - rc = bdb_dn2entry( be, ltid, ndn, &e, &matched, 0 ); + rs->sr_err = bdb_dn2entry( op->o_bd, ltid, &op->o_req_ndn, &ei, 1, + locker, &lock, op->o_tmpmemctx ); - switch( rc ) { + switch( rs->sr_err ) { case 0: case DB_NOTFOUND: break; case DB_LOCK_DEADLOCK: case DB_LOCK_NOTGRANTED: goto retry; + case LDAP_BUSY: + rs->sr_text = "ldap server busy"; + goto return_results; default: - rc = LDAP_OTHER; - text = "internal error"; + rs->sr_err = LDAP_OTHER; + rs->sr_text = "internal error"; goto return_results; } - if ( e == NULL ) { - char* matched_dn = NULL; - struct berval** refs; - - if( matched != NULL ) { - matched_dn = strdup( matched->e_dn ); - refs = is_entry_referral( matched ) - ? get_entry_referrals( be, conn, op, matched, - dn, LDAP_SCOPE_DEFAULT ) + e = ei->bei_e; + if ( rs->sr_err == DB_NOTFOUND ) { + if( e != NULL ) { + rs->sr_matched = ch_strdup( e->e_dn ); + rs->sr_ref = is_entry_referral( e ) + ? get_entry_referrals( op, e ) : NULL; - bdb_entry_return( be, matched ); - matched = NULL; + bdb_unlocked_cache_return_entry_r( &bdb->bi_cache, e); + e = NULL; } else { - refs = referral_rewrite( default_referral, - NULL, dn, LDAP_SCOPE_DEFAULT ); + rs->sr_ref = referral_rewrite( default_referral, + NULL, &op->o_req_dn, LDAP_SCOPE_DEFAULT ); } - send_ldap_result( conn, op, rc = LDAP_REFERRAL, - matched_dn, NULL, refs, NULL ); + rs->sr_err = LDAP_REFERRAL; + send_ldap_result( op, rs ); - ber_bvecfree( refs ); - free( matched_dn ); + ber_bvarray_free( rs->sr_ref ); + free( (char *)rs->sr_matched ); + rs->sr_ref = NULL; + rs->sr_matched = NULL; goto done; } + /* check write on old entry */ + rs->sr_err = access_allowed( op, e, entry, NULL, ACL_WRITE, NULL ); + + if ( ! rs->sr_err ) { + switch( opinfo.boi_err ) { + case DB_LOCK_DEADLOCK: + case DB_LOCK_NOTGRANTED: + goto retry; + } + +#ifdef NEW_LOGGING + LDAP_LOG ( OPERATION, ERR, + "==>bdb_modrdn: no access to entry\n", 0, 0, 0 ); +#else + Debug( LDAP_DEBUG_TRACE, "no access to entry\n", 0, + 0, 0 ); +#endif + rs->sr_text = "no write access to old entry"; + rs->sr_err = LDAP_INSUFFICIENT_ACCESS; + goto return_results; + } + +#ifndef BDB_HIER + rs->sr_err = bdb_cache_children( op, ltid, e ); + if ( rs->sr_err != DB_NOTFOUND ) { + switch( rs->sr_err ) { + case DB_LOCK_DEADLOCK: + case DB_LOCK_NOTGRANTED: + goto retry; + case 0: +#ifdef NEW_LOGGING + LDAP_LOG ( OPERATION, DETAIL1, + "<=- bdb_modrdn: non-leaf %s\n", op->o_req_dn.bv_val, 0, 0 ); +#else + Debug(LDAP_DEBUG_ARGS, + "<=- bdb_modrdn: non-leaf %s\n", + op->o_req_dn.bv_val, 0, 0); +#endif + rs->sr_err = LDAP_NOT_ALLOWED_ON_NONLEAF; + rs->sr_text = "subtree rename not supported"; + break; + default: +#ifdef NEW_LOGGING + LDAP_LOG ( OPERATION, ERR, + "<=- bdb_modrdn: has_children failed %s (%d)\n", + db_strerror(rs->sr_err), rs->sr_err, 0 ); +#else + Debug(LDAP_DEBUG_ARGS, + "<=- bdb_modrdn: has_children failed: %s (%d)\n", + db_strerror(rs->sr_err), rs->sr_err, 0 ); +#endif + rs->sr_err = LDAP_OTHER; + rs->sr_text = "internal error"; + } + goto return_results; + } + ei->bei_state |= CACHE_ENTRY_NO_KIDS; +#endif 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, - conn, op, e, dn, LDAP_SCOPE_DEFAULT ); + rs->sr_ref = get_entry_referrals( op, e ); +#ifdef NEW_LOGGING + LDAP_LOG ( OPERATION, DETAIL1, + "==>bdb_modrdn: entry %s is referral \n", e->e_dn, 0, 0 ); +#else Debug( LDAP_DEBUG_TRACE, "bdb_modrdn: entry %s is referral\n", e->e_dn, 0, 0 ); +#endif - send_ldap_result( conn, op, rc = LDAP_REFERRAL, - e->e_dn, NULL, refs, NULL ); + rs->sr_err = LDAP_REFERRAL, + rs->sr_matched = e->e_name.bv_val; + send_ldap_result( op, rs ); - ber_bvecfree( refs ); + ber_bvarray_free( rs->sr_ref ); + rs->sr_ref = NULL; + rs->sr_matched = NULL; goto done; } - p_ndn = dn_parent( be, e->e_ndn ); - if ( p_ndn != NULL && p_ndn[ 0 ] != '\0' ) { + if ( be_issuffix( op->o_bd, &e->e_nname ) ) { + p_ndn = slap_empty_bv; + } else { + dnParent( &e->e_nname, &p_ndn ); + } + np_ndn = &p_ndn; + if ( p_ndn.bv_len != 0 ) { /* Make sure parent entry exist and we can write its * children. */ + eip = ei->bei_parent; + rs->sr_err = bdb_cache_find_id( op->o_bd, ltid, + eip->bei_id, &eip, 0, locker, &plock, op->o_tmpmemctx ); - rc = bdb_dn2entry( be, ltid, p_ndn, &p, NULL, 0 ); - - switch( rc ) { + switch( rs->sr_err ) { case 0: case DB_NOTFOUND: break; case DB_LOCK_DEADLOCK: case DB_LOCK_NOTGRANTED: goto retry; + case LDAP_BUSY: + rs->sr_text = "ldap server busy"; + goto return_results; default: - rc = LDAP_OTHER; - text = "internal error"; + rs->sr_err = LDAP_OTHER; + rs->sr_text = "internal error"; goto return_results; } + p = eip->bei_e; if( p == NULL) { +#ifdef NEW_LOGGING + LDAP_LOG ( OPERATION, ERR, + "==>bdb_modrdn: parent does not exist\n", 0, 0, 0 ); +#else Debug( LDAP_DEBUG_TRACE, "bdb_modrdn: parent does not exist\n", 0, 0, 0); - rc = LDAP_OTHER; +#endif + rs->sr_err = LDAP_OTHER; + rs->sr_text = "old entry's parent does not exist"; goto return_results; } /* check parent for "children" acl */ - if ( ! access_allowed( be, conn, op, p, - children, NULL, ACL_WRITE ) ) - { + rs->sr_err = access_allowed( op, p, + children, NULL, ACL_WRITE, NULL ); + + if ( ! rs->sr_err ) { + switch( opinfo.boi_err ) { + case DB_LOCK_DEADLOCK: + case DB_LOCK_NOTGRANTED: + goto retry; + } + + rs->sr_err = LDAP_INSUFFICIENT_ACCESS; +#ifdef NEW_LOGGING + LDAP_LOG ( OPERATION, ERR, + "==>bdb_modrdn: no access to parent\n", 0, 0, 0 ); +#else Debug( LDAP_DEBUG_TRACE, "no access to parent\n", 0, 0, 0 ); - send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS, - NULL, NULL, NULL, NULL ); +#endif + rs->sr_text = "no write access to old parent's children"; goto return_results; } +#ifdef NEW_LOGGING + LDAP_LOG ( OPERATION, DETAIL1, + "==>bdb_modrdn: wr to children %s is OK\n", p_ndn.bv_val, 0, 0 ); +#else Debug( LDAP_DEBUG_TRACE, "bdb_modrdn: wr to children of entry %s OK\n", - p_ndn, 0, 0 ); + p_ndn.bv_val, 0, 0 ); +#endif - p_dn = dn_parent( be, e->e_dn ); + 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 ( OPERATION, DETAIL1, + "==>bdb_modrdn: parent dn=%s\n", p_dn.bv_val, 0, 0 ); +#else Debug( LDAP_DEBUG_TRACE, "bdb_modrdn: parent dn=%s\n", - p_dn, 0, 0 ); + p_dn.bv_val, 0, 0 ); +#endif } else { /* no parent, modrdn entry directly under root */ - isroot = be_isroot( be, op->o_ndn ); + isroot = be_isroot( op->o_bd, &op->o_ndn ); if ( ! isroot ) { - if ( be_issuffix( be, "" ) || be_isupdate( be, op->o_ndn ) ) { + if ( be_issuffix( op->o_bd, (struct berval *)&slap_empty_bv ) + || be_isupdate( op->o_bd, &op->o_ndn ) ) { p = (Entry *)&slap_entry_root; /* check parent for "children" acl */ - rc = access_allowed( be, conn, op, p, - children, NULL, ACL_WRITE ); + rs->sr_err = access_allowed( op, p, + children, NULL, ACL_WRITE, NULL ); p = NULL; - if ( ! rc ) - { + if ( ! rs->sr_err ) { + switch( opinfo.boi_err ) { + case DB_LOCK_DEADLOCK: + case DB_LOCK_NOTGRANTED: + goto retry; + } + + rs->sr_err = LDAP_INSUFFICIENT_ACCESS; +#ifdef NEW_LOGGING + LDAP_LOG ( OPERATION, ERR, + "==>bdb_modrdn: no access to parent\n", 0, 0, 0 ); +#else Debug( LDAP_DEBUG_TRACE, "no access to parent\n", 0, 0, 0 ); - send_ldap_result( conn, op, - LDAP_INSUFFICIENT_ACCESS, - NULL, NULL, NULL, NULL ); +#endif + rs->sr_text = "no write access to old parent"; goto return_results; } +#ifdef NEW_LOGGING + LDAP_LOG ( OPERATION, DETAIL1, + "==>bdb_modrdn: wr to children of entry \"%s\" OK\n", + p_dn.bv_val, 0, 0 ); +#else Debug( LDAP_DEBUG_TRACE, "bdb_modrdn: wr to children of entry \"\" OK\n", 0, 0, 0 ); +#endif - p_dn = ch_strdup( "" ); + p_dn.bv_val = ""; + p_dn.bv_len = 0; +#ifdef NEW_LOGGING + LDAP_LOG ( OPERATION, DETAIL1, + "==>bdb_modrdn: parent dn=\"\" \n", 0, 0, 0 ); +#else Debug( LDAP_DEBUG_TRACE, "bdb_modrdn: parent dn=\"\"\n", 0, 0, 0 ); +#endif } else { +#ifdef NEW_LOGGING + LDAP_LOG ( OPERATION, ERR, + "==>bdb_modrdn: no parent, not root &\"\" is not " + "suffix\n", 0, 0, 0 ); +#else Debug( LDAP_DEBUG_TRACE, "bdb_modrdn: no parent, not root " "& \"\" is not suffix\n", 0, 0, 0); - rc = LDAP_INSUFFICIENT_ACCESS; +#endif + rs->sr_text = "no write access to old parent"; + rs->sr_err = LDAP_INSUFFICIENT_ACCESS; goto return_results; } } } - new_parent_dn = p_dn; /* New Parent unless newSuperior given */ + new_parent_dn = &p_dn; /* New Parent unless newSuperior given */ - if ( newSuperior != NULL ) { + if ( op->oq_modrdn.rs_newSup != NULL ) { +#ifdef NEW_LOGGING + LDAP_LOG ( OPERATION, DETAIL1, + "==>bdb_modrdn: new parent \"%s\" requested...\n", + op->oq_modrdn.rs_newSup->bv_val, 0, 0 ); +#else Debug( LDAP_DEBUG_TRACE, "bdb_modrdn: new parent \"%s\" requested...\n", - newSuperior, 0, 0 ); + op->oq_modrdn.rs_newSup->bv_val, 0, 0 ); +#endif + + /* newSuperior == oldParent? */ + if( dn_match( &p_ndn, op->oq_modrdn.rs_nnewSup ) ) { +#ifdef NEW_LOGGING + LDAP_LOG( BACK_BDB, INFO, "bdb_back_modrdn: " + "new parent \"%s\" same as the old parent \"%s\"\n", + op->oq_modrdn.rs_newSup->bv_val, p_dn.bv_val, 0 ); +#else + Debug( LDAP_DEBUG_TRACE, "bdb_back_modrdn: " + "new parent \"%s\" same as the old parent \"%s\"\n", + op->oq_modrdn.rs_newSup->bv_val, p_dn.bv_val, 0 ); +#endif + op->oq_modrdn.rs_newSup = NULL; /* ignore newSuperior */ + } + } - if ( newSuperior[ 0 ] != '\0' ) { - np_dn = ch_strdup( newSuperior ); - np_ndn = ch_strdup( np_dn ); - (void) dn_normalize( np_ndn ); + if ( op->oq_modrdn.rs_newSup != NULL ) { + if ( op->oq_modrdn.rs_newSup->bv_len ) { + np_dn = op->oq_modrdn.rs_newSup; + np_ndn = op->oq_modrdn.rs_nnewSup; /* newSuperior == oldParent?, if so ==> ERROR */ /* newSuperior == entry being moved?, if so ==> ERROR */ /* Get Entry with dn=newSuperior. Does newSuperior exist? */ - rc = bdb_dn2entry( be, ltid, np_ndn, &np, NULL, 0 ); + rs->sr_err = bdb_dn2entry( op->o_bd, ltid, np_ndn, + &neip, 0, locker, &nplock, op->o_tmpmemctx ); - switch( rc ) { - case 0: + switch( rs->sr_err ) { + case 0: np = neip->bei_e; case DB_NOTFOUND: break; case DB_LOCK_DEADLOCK: case DB_LOCK_NOTGRANTED: goto retry; + case LDAP_BUSY: + rs->sr_text = "ldap server busy"; + goto return_results; default: - rc = LDAP_OTHER; - text = "internal error"; + rs->sr_err = LDAP_OTHER; + rs->sr_text = "internal error"; goto return_results; } if( np == NULL) { +#ifdef NEW_LOGGING + LDAP_LOG ( OPERATION, DETAIL1, + "==>bdb_modrdn: newSup(ndn=%s) not here!\n", + np_ndn->bv_val, 0, 0 ); +#else Debug( LDAP_DEBUG_TRACE, "bdb_modrdn: newSup(ndn=%s) not here!\n", - np_ndn, 0, 0); - rc = LDAP_OTHER; + np_ndn->bv_val, 0, 0); +#endif + rs->sr_text = "new superior not found"; + rs->sr_err = LDAP_OTHER; goto return_results; } +#ifdef NEW_LOGGING + LDAP_LOG ( OPERATION, DETAIL1, + "==>bdb_modrdn: wr to new parent OK np=%p, id=%ld\n", + (void *) np, (long) np->e_id, 0 ); +#else Debug( LDAP_DEBUG_TRACE, "bdb_modrdn: wr to new parent OK np=%p, id=%ld\n", - np, (long) np->e_id, 0 ); + (void *) np, (long) np->e_id, 0 ); +#endif /* check newSuperior for "children" acl */ - if ( !access_allowed( be, conn, op, np, children, NULL, ACL_WRITE ) ) { + rs->sr_err = access_allowed( op, np, children, + NULL, ACL_WRITE, NULL ); + + if( ! rs->sr_err ) { + switch( opinfo.boi_err ) { + case DB_LOCK_DEADLOCK: + case DB_LOCK_NOTGRANTED: + goto retry; + } + +#ifdef NEW_LOGGING + LDAP_LOG ( OPERATION, DETAIL1, + "==>bdb_modrdn: no wr to newSup children\n", 0, 0, 0 ); +#else Debug( LDAP_DEBUG_TRACE, "bdb_modrdn: no wr to newSup children\n", 0, 0, 0 ); - rc = LDAP_INSUFFICIENT_ACCESS; +#endif + rs->sr_text = "no write access to new superior's children"; + rs->sr_err = LDAP_INSUFFICIENT_ACCESS; goto return_results; } +#ifdef BDB_ALIASES if ( is_entry_alias( np ) ) { /* parent is an alias, don't allow add */ +#ifdef NEW_LOGGING + LDAP_LOG ( OPERATION, DETAIL1, + "==>bdb_modrdn: entry is alias\n", 0, 0, 0 ); +#else Debug( LDAP_DEBUG_TRACE, "bdb_modrdn: entry is alias\n", 0, 0, 0 ); - - rc = LDAP_ALIAS_PROBLEM; +#endif + rs->sr_text = "new superior is an alias"; + rs->sr_err = LDAP_ALIAS_PROBLEM; goto return_results; } +#endif if ( is_entry_referral( np ) ) { /* parent is a referral, don't allow add */ +#ifdef NEW_LOGGING + LDAP_LOG ( OPERATION, DETAIL1, + "==>bdb_modrdn: entry is referral\n", 0, 0, 0 ); +#else Debug( LDAP_DEBUG_TRACE, "bdb_modrdn: entry is referral\n", 0, 0, 0 ); - - rc = LDAP_OPERATIONS_ERROR; +#endif + rs->sr_text = "new superior is a referral"; + rs->sr_err = LDAP_OTHER; goto return_results; } } else { if ( isroot == -1 ) { - isroot = be_isroot( be, op->o_ndn ); + isroot = be_isroot( op->o_bd, &op->o_ndn ); } - np_dn = ch_strdup( "" ); + np_dn = NULL; /* no parent, modrdn entry directly under root */ if ( ! isroot ) { - if ( be_issuffix( be, "" ) || be_isupdate( be, op->o_ndn ) ) { - + if ( be_issuffix( op->o_bd, (struct berval *)&slap_empty_bv ) + || be_isupdate( op->o_bd, &op->o_ndn ) ) { np = (Entry *)&slap_entry_root; /* check parent for "children" acl */ - rc = access_allowed( be, conn, op, np, - children, NULL, ACL_WRITE ); + rs->sr_err = access_allowed( op, np, + children, NULL, ACL_WRITE, NULL ); np = NULL; - if ( ! rc ) - { + if ( ! rs->sr_err ) { + switch( opinfo.boi_err ) { + case DB_LOCK_DEADLOCK: + case DB_LOCK_NOTGRANTED: + goto retry; + } + + rs->sr_err = LDAP_INSUFFICIENT_ACCESS; +#ifdef NEW_LOGGING + LDAP_LOG ( OPERATION, ERR, + "==>bdb_modrdn: no access to superior\n", 0, 0, 0 ); +#else Debug( LDAP_DEBUG_TRACE, "no access to new superior\n", 0, 0, 0 ); - send_ldap_result( conn, op, - LDAP_INSUFFICIENT_ACCESS, - NULL, NULL, NULL, NULL ); +#endif + rs->sr_text = "no write access to new superior's children"; goto return_results; } +#ifdef NEW_LOGGING + LDAP_LOG ( OPERATION, DETAIL1, + "bdb_modrdn: wr to children entry \"\" OK\n", 0, 0, 0 ); +#else Debug( LDAP_DEBUG_TRACE, "bdb_modrdn: wr to children of entry \"\" OK\n", 0, 0, 0 ); +#endif } else { +#ifdef NEW_LOGGING + LDAP_LOG ( OPERATION, ERR, + "bdb_modrdn: new superior=\"\", not root & \"\" " + "is not suffix\n", 0, 0, 0 ); +#else Debug( LDAP_DEBUG_TRACE, "bdb_modrdn: new superior=\"\", not root " "& \"\" is not suffix\n", 0, 0, 0); - rc = LDAP_INSUFFICIENT_ACCESS; +#endif + rs->sr_text = "no write access to new superior's children"; + rs->sr_err = LDAP_INSUFFICIENT_ACCESS; goto return_results; } } +#ifdef NEW_LOGGING + LDAP_LOG ( OPERATION, DETAIL1, + "bdb_modrdn: new superior=\"\"\n", 0, 0, 0 ); +#else Debug( LDAP_DEBUG_TRACE, "bdb_modrdn: new superior=\"\"\n", 0, 0, 0 ); +#endif } +#ifdef NEW_LOGGING + LDAP_LOG ( OPERATION, DETAIL1, + "bdb_modrdn: wr to new parent's children OK\n", 0, 0, 0 ); +#else Debug( LDAP_DEBUG_TRACE, "bdb_modrdn: wr to new parent's children OK\n", 0, 0, 0 ); +#endif new_parent_dn = np_dn; } - + /* Build target dn and make sure target entry doesn't exist already. */ - build_new_dn( &new_dn, e->e_dn, new_parent_dn, newrdn ); + if (!new_dn.bv_val) build_new_dn( &new_dn, new_parent_dn, &op->oq_modrdn.rs_newrdn ); - new_ndn = ch_strdup(new_dn); - (void) dn_normalize( new_ndn ); + if (!new_ndn.bv_val) { + struct berval bv = {0, NULL}; + dnNormalize( 0, NULL, NULL, &new_dn, &bv, op->o_tmpmemctx ); + ber_dupbv( &new_ndn, &bv ); + } +#ifdef NEW_LOGGING + LDAP_LOG ( OPERATION, RESULTS, + "bdb_modrdn: new ndn=%s\n", new_ndn.bv_val, 0, 0 ); +#else Debug( LDAP_DEBUG_TRACE, "bdb_modrdn: new ndn=%s\n", - new_ndn, 0, 0 ); + new_ndn.bv_val, 0, 0 ); +#endif - rc = bdb_dn2id ( be, ltid, new_ndn, &id ); - switch( rc ) { + /* Shortcut the search */ + nei = neip ? neip : eip; + rs->sr_err = bdb_cache_find_ndn ( op->o_bd, ltid, &new_ndn, + &nei, locker, op->o_tmpmemctx ); + if ( nei ) bdb_cache_entryinfo_unlock( nei ); + switch( rs->sr_err ) { case DB_LOCK_DEADLOCK: case DB_LOCK_NOTGRANTED: goto retry; case DB_NOTFOUND: break; case 0: - rc = LDAP_ALREADY_EXISTS; + rs->sr_err = LDAP_ALREADY_EXISTS; goto return_results; default: - rc = LDAP_OTHER; - text = "internal error"; + rs->sr_err = LDAP_OTHER; + rs->sr_text = "internal error"; goto return_results; } - Debug( LDAP_DEBUG_TRACE, - "bdb_modrdn: new ndn=%s does not exist\n", - new_ndn, 0, 0 ); - /* Get attribute type and attribute value of our new rdn, we will * need to add that to our new entry */ - - if ( rdn_attrs( newrdn, &new_rdn_types, &new_rdn_vals ) ) { - Debug( LDAP_DEBUG_TRACE, - "bdb_modrdn: can't figure out type(s)/values(s) " - "of newrdn\n", 0, 0, 0 ); - rc = LDAP_OPERATIONS_ERROR; - text = "unknown type(s) used in RDN"; - goto return_results; - } - - Debug( LDAP_DEBUG_TRACE, - "bdb_modrdn: new_rdn_val=\"%s\", new_rdn_type=\"%s\"\n", - new_rdn_vals[ 0 ], new_rdn_types[ 0 ], 0 ); - - /* Retrieve the old rdn from the entry's dn */ - if ( ( old_rdn = dn_rdn( be, dn ) ) == NULL ) { - Debug( LDAP_DEBUG_TRACE, - "bdb_modrdn: can't figure out old_rdn from dn\n", + if ( !new_rdn && ldap_bv2rdn_x( &op->oq_modrdn.rs_newrdn, &new_rdn, (char **)&rs->sr_text, + LDAP_DN_FORMAT_LDAP, op->o_tmpmemctx ) ) + { +#ifdef NEW_LOGGING + LDAP_LOG ( OPERATION, ERR, + "bdb_modrdn: can't figure out " + "type(s)/values(s) of newrdn\n", 0, 0, 0 ); - rc = LDAP_OTHER; - text = "could not parse old DN"; - goto return_results; - } - - if ( rdn_attrs( old_rdn, &old_rdn_types, &old_rdn_vals ) ) { +#else Debug( LDAP_DEBUG_TRACE, - "bdb_back_modrdn: can't figure out the old_rdn " - "type(s)/value(s)\n", 0, 0, 0 ); - rc = LDAP_OTHER; - text = "cannot parse RDN from old DN"; - goto return_results; + "bdb_modrdn: can't figure out " + "type(s)/values(s) of newrdn\n", + 0, 0, 0 ); +#endif + rs->sr_err = LDAP_INVALID_DN_SYNTAX; + rs->sr_text = "unknown type(s) used in RDN"; + goto return_results; } - - if ( newSuperior == NULL - && charray_strcasecmp( ( const char ** )old_rdn_types, - ( const char ** )new_rdn_types ) != 0 ) { - /* Not a big deal but we may say something */ - Debug( LDAP_DEBUG_TRACE, - "bdb_modrdn: old_rdn_type(s)=%s, new_rdn_type(s)=%s " - "do not match\n", - old_rdn_types[ 0 ], new_rdn_types[ 0 ], 0 ); - } - - /* Add new attribute values to the entry */ - for ( a_cnt = 0; new_rdn_types[ a_cnt ]; a_cnt++ ) { - int rc; - AttributeDescription *desc = NULL; - Modifications *mod_tmp; - struct berval val; - rc = slap_str2ad( new_rdn_types[ a_cnt ], &desc, &text ); +#ifdef NEW_LOGGING + LDAP_LOG ( OPERATION, RESULTS, + "bdb_modrdn: new_rdn_type=\"%s\", " + "new_rdn_val=\"%s\"\n", + new_rdn[ 0 ]->la_attr.bv_val, + new_rdn[ 0 ]->la_value.bv_val, 0 ); +#else + Debug( LDAP_DEBUG_TRACE, + "bdb_modrdn: new_rdn_type=\"%s\", " + "new_rdn_val=\"%s\"\n", + new_rdn[ 0 ]->la_attr.bv_val, + new_rdn[ 0 ]->la_value.bv_val, 0 ); +#endif - if ( rc != LDAP_SUCCESS ) { + if ( op->oq_modrdn.rs_deleteoldrdn ) { + if ( !old_rdn && ldap_bv2rdn_x( &op->o_req_dn, &old_rdn, (char **)&rs->sr_text, + LDAP_DN_FORMAT_LDAP, op->o_tmpmemctx ) ) + { +#ifdef NEW_LOGGING + LDAP_LOG ( OPERATION, ERR, + "bdb_modrdn: can't figure out " + "type(s)/values(s) of old_rdn\n", + 0, 0, 0 ); +#else Debug( LDAP_DEBUG_TRACE, - "bdb_modrdn: %s: %s (new)\n", - text, new_rdn_types[ a_cnt ], 0 ); + "bdb_modrdn: can't figure out " + "the old_rdn type(s)/value(s)\n", + 0, 0, 0 ); +#endif + rs->sr_err = LDAP_OTHER; + rs->sr_text = "cannot parse RDN from old DN"; goto return_results; } + } - /* ACL check of newly added attrs */ - val.bv_val = new_rdn_vals[ a_cnt ]; - val.bv_len = strlen( val.bv_val ); - if ( !access_allowed( be, conn, op, e, - desc, &val, ACL_WRITE ) ) { - Debug( LDAP_DEBUG_TRACE, - "bdb_modrdn: access to attr \"%s\" " - "(new) not allowed\n", - new_rdn_types[ a_cnt ], 0, 0 ); - rc = LDAP_INSUFFICIENT_ACCESS; + /* prepare modlist of modifications from old/new rdn */ + if (!mod) { + rs->sr_err = slap_modrdn2mods( op, rs, e, old_rdn, new_rdn, &mod ); + if ( rs->sr_err != LDAP_SUCCESS ) { goto return_results; } + } - /* Apply modification */ - mod_tmp = ( Modifications * )ch_malloc( sizeof( Modifications ) ); - mod_tmp->sml_desc = desc; - mod_tmp->sml_bvalues = ( struct berval ** )ch_malloc( 2*sizeof( struct berval * ) ); - mod_tmp->sml_bvalues[ 0 ] = ber_bvstrdup( new_rdn_vals[ a_cnt ] ); - mod_tmp->sml_bvalues[ 1 ] = NULL; - mod_tmp->sml_op = SLAP_MOD_SOFTADD; - mod_tmp->sml_next = mod; - mod = mod_tmp; - } - - /* Remove old rdn value if required */ - if ( deleteoldrdn ) { - /* Get value of old rdn */ - if ( old_rdn_vals == NULL) { - Debug( LDAP_DEBUG_TRACE, - "bdb_modrdn: can't figure out old RDN value(s) " - "from old RDN\n", 0, 0, 0 ); - rc = LDAP_OTHER; - text = "could not parse value(s) from old RDN"; - goto return_results; - } - - for ( d_cnt = 0; old_rdn_types[ d_cnt ]; d_cnt++ ) { - int rc; - AttributeDescription *desc = NULL; - Modifications *mod_tmp; - struct berval val; - - rc = slap_str2ad( old_rdn_types[ d_cnt ], - &desc, &text ); - - if ( rc != LDAP_SUCCESS ) { - Debug( LDAP_DEBUG_TRACE, - "bdb_modrdn: %s: %s (old)\n", - text, old_rdn_types[ d_cnt ], 0 ); - goto return_results; - } + /* nested transaction */ + rs->sr_err = TXN_BEGIN( bdb->bi_dbenv, ltid, <2, + bdb->bi_db_opflags ); + rs->sr_text = NULL; + if( rs->sr_err != 0 ) { +#ifdef NEW_LOGGING + LDAP_LOG ( OPERATION, ERR, + "bdb_modrdn: txn_begin(2) failed: %s (%d)\n", db_strerror(rs->sr_err), rs->sr_err, 0 ); +#else + Debug( LDAP_DEBUG_TRACE, + "bdb_modrdn: txn_begin(2) failed: %s (%d)\n", + db_strerror(rs->sr_err), rs->sr_err, 0 ); +#endif + rs->sr_err = LDAP_OTHER; + rs->sr_text = "internal error"; + goto return_results; + } - /* ACL check of newly added attrs */ - val.bv_val = new_rdn_vals[ d_cnt ]; - val.bv_len = strlen( val.bv_val ); - if ( !access_allowed( be, conn, op, e, - desc, &val, ACL_WRITE ) ) { - Debug( LDAP_DEBUG_TRACE, - "bdb_modrdn: access to attr \"%s\" " - "(old) not allowed\n", - old_rdn_types[ d_cnt ], 0, 0 ); - rc = LDAP_INSUFFICIENT_ACCESS; - goto return_results; - } + dummy = *e; + save = e; + e = &dummy; - /* Apply modification */ - mod_tmp = ( Modifications * )ch_malloc( sizeof( Modifications ) ); - mod_tmp->sml_desc = desc; - mod_tmp->sml_bvalues = ( struct berval ** )ch_malloc( 2*sizeof( struct berval * ) ); - mod_tmp->sml_bvalues[ 0 ] = ber_bvstrdup( old_rdn_vals[ d_cnt ] ); - mod_tmp->sml_bvalues[ 1 ] = NULL; - mod_tmp->sml_op = LDAP_MOD_DELETE; - mod_tmp->sml_next = mod; - mod = mod_tmp; - } - } - /* delete old one */ - rc = bdb_dn2id_delete( be, ltid, e->e_ndn, e->e_id ); - if ( rc != 0 ) { - switch( rc ) { + rs->sr_err = bdb_dn2id_delete( op->o_bd, lt2, eip, e, + op->o_tmpmemctx ); + if ( rs->sr_err != 0 ) { +#ifdef NEW_LOGGING + LDAP_LOG ( OPERATION, ERR, + "<=- bdb_modrdn: dn2id del failed: %s (%d)\n", + db_strerror(rs->sr_err), rs->sr_err, 0 ); +#else + Debug(LDAP_DEBUG_TRACE, + "<=- bdb_modrdn: dn2id del failed: %s (%d)\n", + db_strerror(rs->sr_err), rs->sr_err, 0 ); +#endif + switch( rs->sr_err ) { case DB_LOCK_DEADLOCK: case DB_LOCK_NOTGRANTED: goto retry; } - rc = LDAP_OTHER; - text = "DN index delete fail"; + rs->sr_err = LDAP_OTHER; + rs->sr_text = "DN index delete fail"; goto return_results; } /* Binary format uses a single contiguous block, cannot - * free individual fields. Leave new_dn/new_ndn set so - * they can be individually freed later. + * free individual fields. But if a previous modrdn has + * already happened, must free the names. The frees are + * done in bdb_cache_modrdn(). */ - e->e_dn = new_dn; - e->e_ndn = new_ndn; - +#ifdef BDB_HIER + e->e_name.bv_val = ch_malloc(new_dn.bv_len + new_ndn.bv_len + 2); + e->e_name.bv_len = new_dn.bv_len; + e->e_nname.bv_val = e->e_name.bv_val + new_dn.bv_len + 1; + e->e_nname.bv_len = new_ndn.bv_len; + strcpy(e->e_name.bv_val, new_dn.bv_val); + strcpy(e->e_nname.bv_val, new_ndn.bv_val); +#else + if( e->e_nname.bv_val < e->e_bv.bv_val || e->e_nname.bv_val > + e->e_bv.bv_val + e->e_bv.bv_len ) { + e->e_name.bv_val = NULL; + e->e_nname.bv_val = NULL; + } + e->e_name = new_dn; + e->e_nname = new_ndn; + new_dn.bv_val = NULL; + new_ndn.bv_val = NULL; +#endif /* add new one */ - rc = bdb_dn2id_add( be, ltid, e->e_ndn, e->e_id ); - if ( rc != 0 ) { - switch( rc ) { + rs->sr_err = bdb_dn2id_add( op->o_bd, lt2, neip ? neip : eip, e, + op->o_tmpmemctx ); + if ( rs->sr_err != 0 ) { +#ifdef NEW_LOGGING + LDAP_LOG ( OPERATION, ERR, + "<=- bdb_modrdn: dn2id add failed: %s (%d)\n", + db_strerror(rs->sr_err), rs->sr_err, 0 ); +#else + Debug(LDAP_DEBUG_TRACE, + "<=- bdb_modrdn: dn2id add failed: %s (%d)\n", + db_strerror(rs->sr_err), rs->sr_err, 0 ); +#endif + switch( rs->sr_err ) { case DB_LOCK_DEADLOCK: case DB_LOCK_NOTGRANTED: goto retry; } - rc = LDAP_OTHER; - text = "DN index add failed"; + rs->sr_err = LDAP_OTHER; + rs->sr_text = "DN index add failed"; goto return_results; } - /* modify entry */ - rc = bdb_modify_internal( be, conn, op, ltid, &mod[0], e, - &text, textbuf, textlen ); +#if defined(LDAP_CLIENT_UPDATE) || defined(LDAP_SYNC) + if ( rs->sr_err == LDAP_SUCCESS && !op->o_noop ) { + LDAP_LIST_FOREACH ( ps_list, &bdb->bi_psearch_list, o_ps_link ) { + bdb_psearch( op, rs, ps_list, e, LDAP_PSEARCH_BY_PREMODIFY ); + } + } +#endif - if( rc != LDAP_SUCCESS ) { - switch( rc ) { + /* modify entry */ + rs->sr_err = bdb_modify_internal( op, lt2, &mod[0], e, + &rs->sr_text, textbuf, textlen ); + + if( rs->sr_err != LDAP_SUCCESS ) { +#ifdef NEW_LOGGING + LDAP_LOG ( OPERATION, ERR, + "<=- bdb_modrdn: modify failed: %s (%d)\n", + db_strerror(rs->sr_err), rs->sr_err, 0 ); +#else + Debug(LDAP_DEBUG_TRACE, + "<=- bdb_modrdn: modify failed: %s (%d)\n", + db_strerror(rs->sr_err), rs->sr_err, 0 ); +#endif + if ( ( rs->sr_err == LDAP_INSUFFICIENT_ACCESS ) && opinfo.boi_err ) { + rs->sr_err = opinfo.boi_err; + } + switch( rs->sr_err ) { case DB_LOCK_DEADLOCK: case DB_LOCK_NOTGRANTED: goto retry; @@ -596,85 +877,160 @@ retry: /* transaction retry */ } /* id2entry index */ - rc = bdb_id2entry_update( be, ltid, e ); - if ( rc != 0 ) { - switch( rc ) { + rs->sr_err = bdb_id2entry_update( op->o_bd, lt2, e ); + if ( rs->sr_err != 0 ) { +#ifdef NEW_LOGGING + LDAP_LOG ( OPERATION, ERR, + "<=- bdb_modrdn: id2entry failed: %s (%d)\n", + db_strerror(rs->sr_err), rs->sr_err, 0 ); +#else + Debug(LDAP_DEBUG_TRACE, + "<=- bdb_modrdn: id2entry failed: %s (%d)\n", + db_strerror(rs->sr_err), rs->sr_err, 0 ); +#endif + switch( rs->sr_err ) { case DB_LOCK_DEADLOCK: case DB_LOCK_NOTGRANTED: goto retry; } - rc = LDAP_OTHER; - text = "entry update failed"; + rs->sr_err = LDAP_OTHER; + rs->sr_text = "entry update failed"; goto return_results; } + if ( TXN_COMMIT( lt2, 0 ) != 0 ) { + rs->sr_err = LDAP_OTHER; + rs->sr_text = "txn_commit(2) failed"; + goto return_results; + } + + if( op->o_noop ) { + if(( rs->sr_err=TXN_ABORT( ltid )) != 0 ) { + rs->sr_text = "txn_abort (no-op) failed"; + } else { + noop = 1; + rs->sr_err = LDAP_SUCCESS; + } + + } else { + char gid[DB_XIDDATASIZE]; + + snprintf( gid, sizeof( gid ), "%s-%08lx-%08lx", + bdb_uuid.bv_val, (long) op->o_connid, (long) op->o_opid ); - if (bdb->bi_txn) - rc = txn_commit( ltid, 0 ); + if(( rs->sr_err=TXN_PREPARE( ltid, gid )) != 0 ) { + rs->sr_text = "txn_prepare failed"; + } else { + bdb_cache_modrdn( save, &op->orr_nnewrdn, e, neip, + bdb->bi_dbenv, locker, &lock ); + if(( rs->sr_err=TXN_COMMIT( ltid, 0 )) != 0 ) { + rs->sr_text = "txn_commit failed"; + } else { + rs->sr_err = LDAP_SUCCESS; + } + } + } + ltid = NULL; op->o_private = NULL; - - if( rc != 0 ) { - Debug( LDAP_DEBUG_TRACE, - "bdb_modrdn: txn_commit failed: %s (%d)\n", - db_strerror(rc), rc, 0 ); - rc = LDAP_OTHER; - text = "commit failed"; + + if( rs->sr_err == LDAP_SUCCESS ) { +#ifdef NEW_LOGGING + LDAP_LOG ( OPERATION, RESULTS, + "bdb_modrdn: rdn modified%s id=%08lx dn=\"%s\"\n", + op->o_noop ? " (no-op)" : "", e->e_id, e->e_dn ); +#else + Debug(LDAP_DEBUG_TRACE, + "bdb_modrdn: rdn modified%s id=%08lx dn=\"%s\"\n", + op->o_noop ? " (no-op)" : "", e->e_id, e->e_dn ); +#endif + rs->sr_text = NULL; } else { - Debug( LDAP_DEBUG_TRACE, - "bdb_modrdn: added id=%08lx dn=\"%s\"\n", - e->e_id, e->e_dn, 0 ); - rc = LDAP_SUCCESS; - text = NULL; +#ifdef NEW_LOGGING + LDAP_LOG ( OPERATION, RESULTS, "bdb_modrdn: %s : %s (%d)\n", + rs->sr_text, db_strerror(rs->sr_err), rs->sr_err ); +#else + Debug( LDAP_DEBUG_TRACE, "bdb_add: %s : %s (%d)\n", + rs->sr_text, db_strerror(rs->sr_err), rs->sr_err ); +#endif + rs->sr_err = LDAP_OTHER; } return_results: - send_ldap_result( conn, op, rc, - NULL, text, NULL, NULL ); + send_ldap_result( op, rs ); + +#if defined(LDAP_CLIENT_UPDATE) || defined(LDAP_SYNC) + if ( rs->sr_err == LDAP_SUCCESS && !op->o_noop ) { + /* Loop through in-scope entries for each psearch spec */ + LDAP_LIST_FOREACH ( ps_list, &bdb->bi_psearch_list, o_ps_link ) { + bdb_psearch( op, rs, ps_list, e, LDAP_PSEARCH_BY_MODIFY ); + } + pm_list = LDAP_LIST_FIRST(&op->o_pm_list); + while ( pm_list != NULL ) { + bdb_psearch(op, rs, pm_list->ps_op, + e, LDAP_PSEARCH_BY_SCOPEOUT); + pm_prev = pm_list; + LDAP_LIST_REMOVE ( pm_list, ps_link ); + pm_list = LDAP_LIST_NEXT ( pm_list, ps_link ); + ch_free( pm_prev ); + } + } +#endif - if(rc == LDAP_SUCCESS && bdb->bi_txn_cp ) { + if( rs->sr_err == LDAP_SUCCESS && bdb->bi_txn_cp ) { ldap_pvt_thread_yield(); - txn_checkpoint( bdb->bi_dbenv, + TXN_CHECKPOINT( bdb->bi_dbenv, bdb->bi_txn_cp_kbyte, bdb->bi_txn_cp_min, 0 ); } done: - if( new_dn != NULL ) free( new_dn ); - if( new_ndn != NULL ) free( new_ndn ); - - if( p_dn != NULL ) free( p_dn ); - if( p_ndn != NULL ) free( p_ndn ); + if( new_dn.bv_val != NULL ) free( new_dn.bv_val ); + if( new_ndn.bv_val != NULL ) free( new_ndn.bv_val ); /* LDAP v2 supporting correct attribute handling. */ - if( new_rdn_types != NULL ) charray_free(new_rdn_types); - if( new_rdn_vals != NULL ) charray_free(new_rdn_vals); - if( old_rdn != NULL ) free(old_rdn); - if( old_rdn_types != NULL ) charray_free(old_rdn_types); - if( old_rdn_vals != NULL ) charray_free(old_rdn_vals); - if( mod != NULL ) slap_mods_free(mod); + if ( new_rdn != NULL ) { + ldap_rdnfree_x( new_rdn, op->o_tmpmemctx ); + } + if ( old_rdn != NULL ) { + ldap_rdnfree_x( old_rdn, op->o_tmpmemctx ); + } + if( mod != NULL ) { + Modifications *tmp; + for (; mod; mod=tmp ) { + tmp = mod->sml_next; + if ( mod->sml_nvalues ) free( mod->sml_nvalues[0].bv_val ); + free( mod ); + } + } /* LDAP v3 Support */ - if ( np_dn != NULL ) free( np_dn ); - if ( np_ndn != NULL ) free( np_ndn ); - if( np != NULL ) { - /* free new parent and writer lock */ - bdb_entry_return( be, np ); + /* free new parent and reader lock */ + bdb_unlocked_cache_return_entry_r(&bdb->bi_cache, np); } if( p != NULL ) { - /* free parent and writer lock */ - bdb_entry_return( be, p ); + /* free parent and reader lock */ + bdb_unlocked_cache_return_entry_r(&bdb->bi_cache, p); } /* free entry */ if( e != NULL ) { - bdb_entry_return( be, e ); + bdb_unlocked_cache_return_entry_w( &bdb->bi_cache, e); } if( ltid != NULL ) { - txn_abort( ltid ); +#if defined(LDAP_CLIENT_UPDATE) || defined(LDAP_SYNC) + pm_list = LDAP_LIST_FIRST(&op->o_pm_list); + while ( pm_list != NULL ) { + LDAP_LIST_REMOVE ( pm_list, ps_link ); + pm_prev = pm_list; + pm_list = LDAP_LIST_NEXT ( pm_list, ps_link ); + ch_free( pm_prev ); + } +#endif + TXN_ABORT( ltid ); op->o_private = NULL; } - return rc; + return ( ( rs->sr_err == LDAP_SUCCESS ) ? noop : rs->sr_err ); }