1 /* modrdn.c - bdb backend modrdn routine */
4 * Copyright 1998-2003 The OpenLDAP Foundation, All Rights Reserved.
5 * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
11 #include <ac/string.h>
17 bdb_modrdn( Operation *op, SlapReply *rs )
19 struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
20 AttributeDescription *children = slap_schema.si_ad_children;
21 AttributeDescription *entry = slap_schema.si_ad_entry;
22 struct berval p_dn, p_ndn;
23 struct berval new_dn = {0, NULL}, new_ndn = {0, NULL};
27 EntryInfo *ei = NULL, *eip = NULL, *nei = NULL, *neip = NULL;
28 /* LDAP v2 supporting correct attribute handling. */
29 LDAPRDN new_rdn = NULL;
30 LDAPRDN old_rdn = NULL;
31 char textbuf[SLAP_TEXT_BUFLEN];
32 size_t textlen = sizeof textbuf;
33 DB_TXN *ltid = NULL, *lt2;
34 struct bdb_op_info opinfo;
39 Entry *np = NULL; /* newSuperior Entry */
40 struct berval *np_dn = NULL; /* newSuperior dn */
41 struct berval *np_ndn = NULL; /* newSuperior ndn */
42 struct berval *new_parent_dn = NULL; /* np_dn, p_dn, or NULL */
44 /* Used to interface with bdb_modify_internal() */
45 Modifications *mod = NULL; /* Used to delete old rdn */
47 int manageDSAit = get_manageDSAit( op );
50 DB_LOCK lock, plock, nplock;
54 #if defined(LDAP_CLIENT_UPDATE) || defined(LDAP_SYNC)
56 struct psid_entry *pm_list, *pm_prev;
60 LDAP_LOG ( OPERATION, ENTRY, "==>bdb_modrdn(%s,%s,%s)\n",
61 op->o_req_dn.bv_val,op->oq_modrdn.rs_newrdn.bv_val,
62 op->oq_modrdn.rs_newSup ? op->oq_modrdn.rs_newSup->bv_val : "NULL" );
64 Debug( LDAP_DEBUG_TRACE, "==>bdb_modrdn(%s,%s,%s)\n",
65 op->o_req_dn.bv_val,op->oq_modrdn.rs_newrdn.bv_val,
66 op->oq_modrdn.rs_newSup ? op->oq_modrdn.rs_newSup->bv_val : "NULL" );
70 retry: /* transaction retry */
72 bdb_unlocked_cache_return_entry_w(&bdb->bi_cache, e);
76 bdb_unlocked_cache_return_entry_r(&bdb->bi_cache, p);
80 bdb_unlocked_cache_return_entry_r(&bdb->bi_cache, np);
84 LDAP_LOG ( OPERATION, DETAIL1, "==>bdb_modrdn: retrying...\n", 0, 0, 0);
86 Debug( LDAP_DEBUG_TRACE, "==>bdb_modrdn: retrying...\n", 0, 0, 0 );
89 #if defined(LDAP_CLIENT_UPDATE) || defined(LDAP_SYNC)
90 pm_list = LDAP_LIST_FIRST(&op->o_pm_list);
91 while ( pm_list != NULL ) {
92 LDAP_LIST_REMOVE ( pm_list, ps_link );
94 pm_list = LDAP_LIST_NEXT ( pm_list, ps_link );
99 rs->sr_err = TXN_ABORT( ltid );
101 op->o_private = NULL;
102 op->o_do_not_cache = opinfo.boi_acl_cache;
103 if( rs->sr_err != 0 ) {
104 rs->sr_err = LDAP_OTHER;
105 rs->sr_text = "internal error";
108 ldap_pvt_thread_yield();
111 /* begin transaction */
112 rs->sr_err = TXN_BEGIN( bdb->bi_dbenv, NULL, <id,
113 bdb->bi_db_opflags );
115 if( rs->sr_err != 0 ) {
117 LDAP_LOG ( OPERATION, ERR,
118 "==>bdb_modrdn: txn_begin failed: %s (%d)\n",
119 db_strerror(rs->sr_err), rs->sr_err, 0 );
121 Debug( LDAP_DEBUG_TRACE,
122 "bdb_delete: txn_begin failed: %s (%d)\n",
123 db_strerror(rs->sr_err), rs->sr_err, 0 );
125 rs->sr_err = LDAP_OTHER;
126 rs->sr_text = "internal error";
130 locker = TXN_ID ( ltid );
132 opinfo.boi_bdb = op->o_bd;
133 opinfo.boi_txn = ltid;
134 opinfo.boi_locker = locker;
136 opinfo.boi_acl_cache = op->o_do_not_cache;
137 op->o_private = &opinfo;
140 rs->sr_err = bdb_dn2entry( op->o_bd, ltid, &op->o_req_ndn, &ei, 1,
141 locker, &lock, op->o_tmpmemctx );
143 switch( rs->sr_err ) {
147 case DB_LOCK_DEADLOCK:
148 case DB_LOCK_NOTGRANTED:
151 rs->sr_text = "ldap server busy";
154 rs->sr_err = LDAP_OTHER;
155 rs->sr_text = "internal error";
160 if ( rs->sr_err == DB_NOTFOUND ) {
162 rs->sr_matched = ch_strdup( e->e_dn );
163 rs->sr_ref = is_entry_referral( e )
164 ? get_entry_referrals( op, e )
166 bdb_unlocked_cache_return_entry_r( &bdb->bi_cache, e);
170 rs->sr_ref = referral_rewrite( default_referral,
171 NULL, &op->o_req_dn, LDAP_SCOPE_DEFAULT );
174 rs->sr_err = LDAP_REFERRAL;
175 send_ldap_result( op, rs );
177 ber_bvarray_free( rs->sr_ref );
178 free( (char *)rs->sr_matched );
180 rs->sr_matched = NULL;
185 /* check write on old entry */
186 rs->sr_err = access_allowed( op, e, entry, NULL, ACL_WRITE, NULL );
188 if ( ! rs->sr_err ) {
189 switch( opinfo.boi_err ) {
190 case DB_LOCK_DEADLOCK:
191 case DB_LOCK_NOTGRANTED:
196 LDAP_LOG ( OPERATION, ERR,
197 "==>bdb_modrdn: no access to entry\n", 0, 0, 0 );
199 Debug( LDAP_DEBUG_TRACE, "no access to entry\n", 0,
202 rs->sr_text = "no write access to old entry";
203 rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
208 rs->sr_err = bdb_cache_children( op, ltid, e );
209 if ( rs->sr_err != DB_NOTFOUND ) {
210 switch( rs->sr_err ) {
211 case DB_LOCK_DEADLOCK:
212 case DB_LOCK_NOTGRANTED:
216 LDAP_LOG ( OPERATION, DETAIL1,
217 "<=- bdb_modrdn: non-leaf %s\n", op->o_req_dn.bv_val, 0, 0 );
219 Debug(LDAP_DEBUG_ARGS,
220 "<=- bdb_modrdn: non-leaf %s\n",
221 op->o_req_dn.bv_val, 0, 0);
223 rs->sr_err = LDAP_NOT_ALLOWED_ON_NONLEAF;
224 rs->sr_text = "subtree rename not supported";
228 LDAP_LOG ( OPERATION, ERR,
229 "<=- bdb_modrdn: has_children failed %s (%d)\n",
230 db_strerror(rs->sr_err), rs->sr_err, 0 );
232 Debug(LDAP_DEBUG_ARGS,
233 "<=- bdb_modrdn: has_children failed: %s (%d)\n",
234 db_strerror(rs->sr_err), rs->sr_err, 0 );
236 rs->sr_err = LDAP_OTHER;
237 rs->sr_text = "internal error";
241 ei->bei_state |= CACHE_ENTRY_NO_KIDS;
243 if (!manageDSAit && is_entry_referral( e ) ) {
244 /* parent is a referral, don't allow add */
245 rs->sr_ref = get_entry_referrals( op, e );
248 LDAP_LOG ( OPERATION, DETAIL1,
249 "==>bdb_modrdn: entry %s is referral \n", e->e_dn, 0, 0 );
251 Debug( LDAP_DEBUG_TRACE, "bdb_modrdn: entry %s is referral\n",
255 rs->sr_err = LDAP_REFERRAL,
256 rs->sr_matched = e->e_name.bv_val;
257 send_ldap_result( op, rs );
259 ber_bvarray_free( rs->sr_ref );
261 rs->sr_matched = NULL;
265 if ( be_issuffix( op->o_bd, &e->e_nname ) ) {
266 p_ndn = slap_empty_bv;
268 dnParent( &e->e_nname, &p_ndn );
271 if ( p_ndn.bv_len != 0 ) {
272 /* Make sure parent entry exist and we can write its
275 eip = ei->bei_parent;
276 rs->sr_err = bdb_cache_find_id( op->o_bd, ltid,
277 eip->bei_id, &eip, 0, locker, &plock, op->o_tmpmemctx );
279 switch( rs->sr_err ) {
283 case DB_LOCK_DEADLOCK:
284 case DB_LOCK_NOTGRANTED:
287 rs->sr_text = "ldap server busy";
290 rs->sr_err = LDAP_OTHER;
291 rs->sr_text = "internal error";
298 LDAP_LOG ( OPERATION, ERR,
299 "==>bdb_modrdn: parent does not exist\n", 0, 0, 0 );
301 Debug( LDAP_DEBUG_TRACE, "bdb_modrdn: parent does not exist\n",
304 rs->sr_err = LDAP_OTHER;
305 rs->sr_text = "old entry's parent does not exist";
309 /* check parent for "children" acl */
310 rs->sr_err = access_allowed( op, p,
311 children, NULL, ACL_WRITE, NULL );
313 if ( ! rs->sr_err ) {
314 switch( opinfo.boi_err ) {
315 case DB_LOCK_DEADLOCK:
316 case DB_LOCK_NOTGRANTED:
320 rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
322 LDAP_LOG ( OPERATION, ERR,
323 "==>bdb_modrdn: no access to parent\n", 0, 0, 0 );
325 Debug( LDAP_DEBUG_TRACE, "no access to parent\n", 0,
328 rs->sr_text = "no write access to old parent's children";
333 LDAP_LOG ( OPERATION, DETAIL1,
334 "==>bdb_modrdn: wr to children %s is OK\n", p_ndn.bv_val, 0, 0 );
336 Debug( LDAP_DEBUG_TRACE,
337 "bdb_modrdn: wr to children of entry %s OK\n",
338 p_ndn.bv_val, 0, 0 );
341 if ( p_ndn.bv_val == slap_empty_bv.bv_val ) {
342 p_dn = slap_empty_bv;
344 dnParent( &e->e_name, &p_dn );
348 LDAP_LOG ( OPERATION, DETAIL1,
349 "==>bdb_modrdn: parent dn=%s\n", p_dn.bv_val, 0, 0 );
351 Debug( LDAP_DEBUG_TRACE,
352 "bdb_modrdn: parent dn=%s\n",
357 /* no parent, modrdn entry directly under root */
358 isroot = be_isroot( op->o_bd, &op->o_ndn );
360 if ( be_issuffix( op->o_bd, (struct berval *)&slap_empty_bv )
361 || be_isupdate( op->o_bd, &op->o_ndn ) ) {
363 p = (Entry *)&slap_entry_root;
365 /* check parent for "children" acl */
366 rs->sr_err = access_allowed( op, p,
367 children, NULL, ACL_WRITE, NULL );
371 if ( ! rs->sr_err ) {
372 switch( opinfo.boi_err ) {
373 case DB_LOCK_DEADLOCK:
374 case DB_LOCK_NOTGRANTED:
378 rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
380 LDAP_LOG ( OPERATION, ERR,
381 "==>bdb_modrdn: no access to parent\n", 0, 0, 0 );
383 Debug( LDAP_DEBUG_TRACE,
384 "no access to parent\n",
387 rs->sr_text = "no write access to old parent";
392 LDAP_LOG ( OPERATION, DETAIL1,
393 "==>bdb_modrdn: wr to children of entry \"%s\" OK\n",
396 Debug( LDAP_DEBUG_TRACE,
397 "bdb_modrdn: wr to children of entry \"\" OK\n",
405 LDAP_LOG ( OPERATION, DETAIL1,
406 "==>bdb_modrdn: parent dn=\"\" \n", 0, 0, 0 );
408 Debug( LDAP_DEBUG_TRACE,
409 "bdb_modrdn: parent dn=\"\"\n",
415 LDAP_LOG ( OPERATION, ERR,
416 "==>bdb_modrdn: no parent, not root &\"\" is not "
417 "suffix\n", 0, 0, 0 );
419 Debug( LDAP_DEBUG_TRACE,
420 "bdb_modrdn: no parent, not root "
421 "& \"\" is not suffix\n",
424 rs->sr_text = "no write access to old parent";
425 rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
431 new_parent_dn = &p_dn; /* New Parent unless newSuperior given */
433 if ( op->oq_modrdn.rs_newSup != NULL ) {
435 LDAP_LOG ( OPERATION, DETAIL1,
436 "==>bdb_modrdn: new parent \"%s\" requested...\n",
437 op->oq_modrdn.rs_newSup->bv_val, 0, 0 );
439 Debug( LDAP_DEBUG_TRACE,
440 "bdb_modrdn: new parent \"%s\" requested...\n",
441 op->oq_modrdn.rs_newSup->bv_val, 0, 0 );
444 /* newSuperior == oldParent? */
445 if( dn_match( &p_ndn, op->oq_modrdn.rs_nnewSup ) ) {
447 LDAP_LOG( BACK_BDB, INFO, "bdb_back_modrdn: "
448 "new parent \"%s\" same as the old parent \"%s\"\n",
449 op->oq_modrdn.rs_newSup->bv_val, p_dn.bv_val, 0 );
451 Debug( LDAP_DEBUG_TRACE, "bdb_back_modrdn: "
452 "new parent \"%s\" same as the old parent \"%s\"\n",
453 op->oq_modrdn.rs_newSup->bv_val, p_dn.bv_val, 0 );
455 op->oq_modrdn.rs_newSup = NULL; /* ignore newSuperior */
459 if ( op->oq_modrdn.rs_newSup != NULL ) {
460 if ( op->oq_modrdn.rs_newSup->bv_len ) {
461 np_dn = op->oq_modrdn.rs_newSup;
462 np_ndn = op->oq_modrdn.rs_nnewSup;
464 /* newSuperior == oldParent?, if so ==> ERROR */
465 /* newSuperior == entry being moved?, if so ==> ERROR */
466 /* Get Entry with dn=newSuperior. Does newSuperior exist? */
468 rs->sr_err = bdb_dn2entry( op->o_bd, ltid, np_ndn,
469 &neip, 0, locker, &nplock, op->o_tmpmemctx );
471 switch( rs->sr_err ) {
472 case 0: np = neip->bei_e;
475 case DB_LOCK_DEADLOCK:
476 case DB_LOCK_NOTGRANTED:
479 rs->sr_text = "ldap server busy";
482 rs->sr_err = LDAP_OTHER;
483 rs->sr_text = "internal error";
489 LDAP_LOG ( OPERATION, DETAIL1,
490 "==>bdb_modrdn: newSup(ndn=%s) not here!\n",
491 np_ndn->bv_val, 0, 0 );
493 Debug( LDAP_DEBUG_TRACE,
494 "bdb_modrdn: newSup(ndn=%s) not here!\n",
495 np_ndn->bv_val, 0, 0);
497 rs->sr_text = "new superior not found";
498 rs->sr_err = LDAP_OTHER;
503 LDAP_LOG ( OPERATION, DETAIL1,
504 "==>bdb_modrdn: wr to new parent OK np=%p, id=%ld\n",
505 np, (long) np->e_id, 0 );
507 Debug( LDAP_DEBUG_TRACE,
508 "bdb_modrdn: wr to new parent OK np=%p, id=%ld\n",
509 np, (long) np->e_id, 0 );
512 /* check newSuperior for "children" acl */
513 rs->sr_err = access_allowed( op, np, children,
514 NULL, ACL_WRITE, NULL );
517 switch( opinfo.boi_err ) {
518 case DB_LOCK_DEADLOCK:
519 case DB_LOCK_NOTGRANTED:
524 LDAP_LOG ( OPERATION, DETAIL1,
525 "==>bdb_modrdn: no wr to newSup children\n", 0, 0, 0 );
527 Debug( LDAP_DEBUG_TRACE,
528 "bdb_modrdn: no wr to newSup children\n",
531 rs->sr_text = "no write access to new superior's children";
532 rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
537 if ( is_entry_alias( np ) ) {
538 /* parent is an alias, don't allow add */
540 LDAP_LOG ( OPERATION, DETAIL1,
541 "==>bdb_modrdn: entry is alias\n", 0, 0, 0 );
543 Debug( LDAP_DEBUG_TRACE, "bdb_modrdn: entry is alias\n",
546 rs->sr_text = "new superior is an alias";
547 rs->sr_err = LDAP_ALIAS_PROBLEM;
552 if ( is_entry_referral( np ) ) {
553 /* parent is a referral, don't allow add */
555 LDAP_LOG ( OPERATION, DETAIL1,
556 "==>bdb_modrdn: entry is referral\n", 0, 0, 0 );
558 Debug( LDAP_DEBUG_TRACE, "bdb_modrdn: entry is referral\n",
561 rs->sr_text = "new superior is a referral";
562 rs->sr_err = LDAP_OTHER;
567 if ( isroot == -1 ) {
568 isroot = be_isroot( op->o_bd, &op->o_ndn );
573 /* no parent, modrdn entry directly under root */
575 if ( be_issuffix( op->o_bd, (struct berval *)&slap_empty_bv )
576 || be_isupdate( op->o_bd, &op->o_ndn ) ) {
577 np = (Entry *)&slap_entry_root;
579 /* check parent for "children" acl */
580 rs->sr_err = access_allowed( op, np,
581 children, NULL, ACL_WRITE, NULL );
585 if ( ! rs->sr_err ) {
586 switch( opinfo.boi_err ) {
587 case DB_LOCK_DEADLOCK:
588 case DB_LOCK_NOTGRANTED:
592 rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
594 LDAP_LOG ( OPERATION, ERR,
595 "==>bdb_modrdn: no access to superior\n", 0, 0, 0 );
597 Debug( LDAP_DEBUG_TRACE,
598 "no access to new superior\n",
601 rs->sr_text = "no write access to new superior's children";
606 LDAP_LOG ( OPERATION, DETAIL1,
607 "bdb_modrdn: wr to children entry \"\" OK\n", 0, 0, 0 );
609 Debug( LDAP_DEBUG_TRACE,
610 "bdb_modrdn: wr to children of entry \"\" OK\n",
616 LDAP_LOG ( OPERATION, ERR,
617 "bdb_modrdn: new superior=\"\", not root & \"\" "
618 "is not suffix\n", 0, 0, 0 );
620 Debug( LDAP_DEBUG_TRACE,
621 "bdb_modrdn: new superior=\"\", not root "
622 "& \"\" is not suffix\n",
625 rs->sr_text = "no write access to new superior's children";
626 rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
632 LDAP_LOG ( OPERATION, DETAIL1,
633 "bdb_modrdn: new superior=\"\"\n", 0, 0, 0 );
635 Debug( LDAP_DEBUG_TRACE,
636 "bdb_modrdn: new superior=\"\"\n",
642 LDAP_LOG ( OPERATION, DETAIL1,
643 "bdb_modrdn: wr to new parent's children OK\n", 0, 0, 0 );
645 Debug( LDAP_DEBUG_TRACE,
646 "bdb_modrdn: wr to new parent's children OK\n",
650 new_parent_dn = np_dn;
653 /* Build target dn and make sure target entry doesn't exist already. */
654 if (!new_dn.bv_val) build_new_dn( &new_dn, new_parent_dn, &op->oq_modrdn.rs_newrdn );
656 if (!new_ndn.bv_val) {
657 struct berval bv = {0, NULL};
658 dnNormalize( 0, NULL, NULL, &new_dn, &bv, op->o_tmpmemctx );
659 ber_dupbv( &new_ndn, &bv );
663 LDAP_LOG ( OPERATION, RESULTS,
664 "bdb_modrdn: new ndn=%s\n", new_ndn.bv_val, 0, 0 );
666 Debug( LDAP_DEBUG_TRACE, "bdb_modrdn: new ndn=%s\n",
667 new_ndn.bv_val, 0, 0 );
670 /* Shortcut the search */
671 nei = neip ? neip : eip;
672 rs->sr_err = bdb_cache_find_ndn ( op->o_bd, ltid, &new_ndn,
673 &nei, locker, op->o_tmpmemctx );
674 if ( nei ) bdb_cache_entryinfo_unlock( nei );
675 switch( rs->sr_err ) {
676 case DB_LOCK_DEADLOCK:
677 case DB_LOCK_NOTGRANTED:
682 rs->sr_err = LDAP_ALREADY_EXISTS;
685 rs->sr_err = LDAP_OTHER;
686 rs->sr_text = "internal error";
690 /* Get attribute type and attribute value of our new rdn, we will
691 * need to add that to our new entry
693 if ( !new_rdn && ldap_bv2rdn_x( &op->oq_modrdn.rs_newrdn, &new_rdn, (char **)&rs->sr_text,
694 LDAP_DN_FORMAT_LDAP, op->o_tmpmemctx ) )
697 LDAP_LOG ( OPERATION, ERR,
698 "bdb_modrdn: can't figure out "
699 "type(s)/values(s) of newrdn\n",
702 Debug( LDAP_DEBUG_TRACE,
703 "bdb_modrdn: can't figure out "
704 "type(s)/values(s) of newrdn\n",
707 rs->sr_err = LDAP_INVALID_DN_SYNTAX;
708 rs->sr_text = "unknown type(s) used in RDN";
713 LDAP_LOG ( OPERATION, RESULTS,
714 "bdb_modrdn: new_rdn_type=\"%s\", "
715 "new_rdn_val=\"%s\"\n",
716 new_rdn[ 0 ]->la_attr.bv_val,
717 new_rdn[ 0 ]->la_value.bv_val, 0 );
719 Debug( LDAP_DEBUG_TRACE,
720 "bdb_modrdn: new_rdn_type=\"%s\", "
721 "new_rdn_val=\"%s\"\n",
722 new_rdn[ 0 ]->la_attr.bv_val,
723 new_rdn[ 0 ]->la_value.bv_val, 0 );
726 if ( op->oq_modrdn.rs_deleteoldrdn ) {
727 if ( !old_rdn && ldap_bv2rdn_x( &op->o_req_dn, &old_rdn, (char **)&rs->sr_text,
728 LDAP_DN_FORMAT_LDAP, op->o_tmpmemctx ) )
731 LDAP_LOG ( OPERATION, ERR,
732 "bdb_modrdn: can't figure out "
733 "type(s)/values(s) of old_rdn\n",
736 Debug( LDAP_DEBUG_TRACE,
737 "bdb_modrdn: can't figure out "
738 "the old_rdn type(s)/value(s)\n",
741 rs->sr_err = LDAP_OTHER;
742 rs->sr_text = "cannot parse RDN from old DN";
747 /* prepare modlist of modifications from old/new rdn */
749 rs->sr_err = slap_modrdn2mods( op, rs, e, old_rdn, new_rdn, &mod );
750 if ( rs->sr_err != LDAP_SUCCESS ) {
755 /* nested transaction */
756 rs->sr_err = TXN_BEGIN( bdb->bi_dbenv, ltid, <2,
757 bdb->bi_db_opflags );
759 if( rs->sr_err != 0 ) {
761 LDAP_LOG ( OPERATION, ERR,
762 "bdb_modrdn: txn_begin(2) failed: %s (%d)\n", db_strerror(rs->sr_err), rs->sr_err, 0 );
764 Debug( LDAP_DEBUG_TRACE,
765 "bdb_modrdn: txn_begin(2) failed: %s (%d)\n",
766 db_strerror(rs->sr_err), rs->sr_err, 0 );
768 rs->sr_err = LDAP_OTHER;
769 rs->sr_text = "internal error";
778 rs->sr_err = bdb_dn2id_delete( op->o_bd, lt2, eip, e,
780 if ( rs->sr_err != 0 ) {
782 LDAP_LOG ( OPERATION, ERR,
783 "<=- bdb_modrdn: dn2id del failed: %s (%d)\n",
784 db_strerror(rs->sr_err), rs->sr_err, 0 );
786 Debug(LDAP_DEBUG_TRACE,
787 "<=- bdb_modrdn: dn2id del failed: %s (%d)\n",
788 db_strerror(rs->sr_err), rs->sr_err, 0 );
790 switch( rs->sr_err ) {
791 case DB_LOCK_DEADLOCK:
792 case DB_LOCK_NOTGRANTED:
795 rs->sr_err = LDAP_OTHER;
796 rs->sr_text = "DN index delete fail";
800 /* Binary format uses a single contiguous block, cannot
801 * free individual fields. But if a previous modrdn has
802 * already happened, must free the names. The frees are
803 * done in bdb_cache_modrdn().
806 e->e_name.bv_val = ch_malloc(new_dn.bv_len + new_ndn.bv_len + 2);
807 e->e_name.bv_len = new_dn.bv_len;
808 e->e_nname.bv_val = e->e_name.bv_val + new_dn.bv_len + 1;
809 e->e_nname.bv_len = new_ndn.bv_len;
810 strcpy(e->e_name.bv_val, new_dn.bv_val);
811 strcpy(e->e_nname.bv_val, new_ndn.bv_val);
813 if( e->e_nname.bv_val < e->e_bv.bv_val || e->e_nname.bv_val >
814 e->e_bv.bv_val + e->e_bv.bv_len ) {
815 e->e_name.bv_val = NULL;
816 e->e_nname.bv_val = NULL;
819 e->e_nname = new_ndn;
820 new_dn.bv_val = NULL;
821 new_ndn.bv_val = NULL;
824 rs->sr_err = bdb_dn2id_add( op->o_bd, lt2, neip ? neip : eip, e,
826 if ( rs->sr_err != 0 ) {
828 LDAP_LOG ( OPERATION, ERR,
829 "<=- bdb_modrdn: dn2id add failed: %s (%d)\n",
830 db_strerror(rs->sr_err), rs->sr_err, 0 );
832 Debug(LDAP_DEBUG_TRACE,
833 "<=- bdb_modrdn: dn2id add failed: %s (%d)\n",
834 db_strerror(rs->sr_err), rs->sr_err, 0 );
836 switch( rs->sr_err ) {
837 case DB_LOCK_DEADLOCK:
838 case DB_LOCK_NOTGRANTED:
841 rs->sr_err = LDAP_OTHER;
842 rs->sr_text = "DN index add failed";
846 #if defined(LDAP_CLIENT_UPDATE) || defined(LDAP_SYNC)
847 if ( rs->sr_err == LDAP_SUCCESS && !op->o_noop ) {
848 LDAP_LIST_FOREACH ( ps_list, &bdb->bi_psearch_list, o_ps_link ) {
849 bdb_psearch( op, rs, ps_list, e, LDAP_PSEARCH_BY_PREMODIFY );
855 rs->sr_err = bdb_modify_internal( op, lt2, &mod[0], e,
856 &rs->sr_text, textbuf, textlen );
858 if( rs->sr_err != LDAP_SUCCESS ) {
860 LDAP_LOG ( OPERATION, ERR,
861 "<=- bdb_modrdn: modify failed: %s (%d)\n",
862 db_strerror(rs->sr_err), rs->sr_err, 0 );
864 Debug(LDAP_DEBUG_TRACE,
865 "<=- bdb_modrdn: modify failed: %s (%d)\n",
866 db_strerror(rs->sr_err), rs->sr_err, 0 );
868 if ( ( rs->sr_err == LDAP_INSUFFICIENT_ACCESS ) && opinfo.boi_err ) {
869 rs->sr_err = opinfo.boi_err;
871 switch( rs->sr_err ) {
872 case DB_LOCK_DEADLOCK:
873 case DB_LOCK_NOTGRANTED:
880 rs->sr_err = bdb_id2entry_update( op->o_bd, lt2, e );
881 if ( rs->sr_err != 0 ) {
883 LDAP_LOG ( OPERATION, ERR,
884 "<=- bdb_modrdn: id2entry failed: %s (%d)\n",
885 db_strerror(rs->sr_err), rs->sr_err, 0 );
887 Debug(LDAP_DEBUG_TRACE,
888 "<=- bdb_modrdn: id2entry failed: %s (%d)\n",
889 db_strerror(rs->sr_err), rs->sr_err, 0 );
891 switch( rs->sr_err ) {
892 case DB_LOCK_DEADLOCK:
893 case DB_LOCK_NOTGRANTED:
896 rs->sr_err = LDAP_OTHER;
897 rs->sr_text = "entry update failed";
900 if ( TXN_COMMIT( lt2, 0 ) != 0 ) {
901 rs->sr_err = LDAP_OTHER;
902 rs->sr_text = "txn_commit(2) failed";
907 if(( rs->sr_err=TXN_ABORT( ltid )) != 0 ) {
908 rs->sr_text = "txn_abort (no-op) failed";
911 rs->sr_err = LDAP_SUCCESS;
915 char gid[DB_XIDDATASIZE];
917 snprintf( gid, sizeof( gid ), "%s-%08lx-%08lx",
918 bdb_uuid.bv_val, (long) op->o_connid, (long) op->o_opid );
920 if(( rs->sr_err=TXN_PREPARE( ltid, gid )) != 0 ) {
921 rs->sr_text = "txn_prepare failed";
923 bdb_cache_modrdn( save, &op->orr_nnewrdn, e, neip,
924 bdb->bi_dbenv, locker, &lock );
925 if(( rs->sr_err=TXN_COMMIT( ltid, 0 )) != 0 ) {
926 rs->sr_text = "txn_commit failed";
928 rs->sr_err = LDAP_SUCCESS;
934 op->o_private = NULL;
936 if( rs->sr_err == LDAP_SUCCESS ) {
938 LDAP_LOG ( OPERATION, RESULTS,
939 "bdb_modrdn: rdn modified%s id=%08lx dn=\"%s\"\n",
940 op->o_noop ? " (no-op)" : "", e->e_id, e->e_dn );
942 Debug(LDAP_DEBUG_TRACE,
943 "bdb_modrdn: rdn modified%s id=%08lx dn=\"%s\"\n",
944 op->o_noop ? " (no-op)" : "", e->e_id, e->e_dn );
949 LDAP_LOG ( OPERATION, RESULTS, "bdb_modrdn: %s : %s (%d)\n",
950 rs->sr_text, db_strerror(rs->sr_err), rs->sr_err );
952 Debug( LDAP_DEBUG_TRACE, "bdb_add: %s : %s (%d)\n",
953 rs->sr_text, db_strerror(rs->sr_err), rs->sr_err );
955 rs->sr_err = LDAP_OTHER;
959 send_ldap_result( op, rs );
961 #if defined(LDAP_CLIENT_UPDATE) || defined(LDAP_SYNC)
962 if ( rs->sr_err == LDAP_SUCCESS && !op->o_noop ) {
963 /* Loop through in-scope entries for each psearch spec */
964 LDAP_LIST_FOREACH ( ps_list, &bdb->bi_psearch_list, o_ps_link ) {
965 bdb_psearch( op, rs, ps_list, e, LDAP_PSEARCH_BY_MODIFY );
967 pm_list = LDAP_LIST_FIRST(&op->o_pm_list);
968 while ( pm_list != NULL ) {
969 bdb_psearch(op, rs, pm_list->ps_op,
970 e, LDAP_PSEARCH_BY_SCOPEOUT);
972 LDAP_LIST_REMOVE ( pm_list, ps_link );
973 pm_list = LDAP_LIST_NEXT ( pm_list, ps_link );
979 if( rs->sr_err == LDAP_SUCCESS && bdb->bi_txn_cp ) {
980 ldap_pvt_thread_yield();
981 TXN_CHECKPOINT( bdb->bi_dbenv,
982 bdb->bi_txn_cp_kbyte, bdb->bi_txn_cp_min, 0 );
986 if( new_dn.bv_val != NULL ) free( new_dn.bv_val );
987 if( new_ndn.bv_val != NULL ) free( new_ndn.bv_val );
989 /* LDAP v2 supporting correct attribute handling. */
990 if ( new_rdn != NULL ) {
991 ldap_rdnfree_x( new_rdn, op->o_tmpmemctx );
993 if ( old_rdn != NULL ) {
994 ldap_rdnfree_x( old_rdn, op->o_tmpmemctx );
998 for (; mod; mod=tmp ) {
1000 if ( mod->sml_nvalues ) free( mod->sml_nvalues[0].bv_val );
1005 /* LDAP v3 Support */
1007 /* free new parent and reader lock */
1008 bdb_unlocked_cache_return_entry_r(&bdb->bi_cache, np);
1012 /* free parent and reader lock */
1013 bdb_unlocked_cache_return_entry_r(&bdb->bi_cache, p);
1018 bdb_unlocked_cache_return_entry_w( &bdb->bi_cache, e);
1021 if( ltid != NULL ) {
1022 #if defined(LDAP_CLIENT_UPDATE) || defined(LDAP_SYNC)
1023 pm_list = LDAP_LIST_FIRST(&op->o_pm_list);
1024 while ( pm_list != NULL ) {
1025 LDAP_LIST_REMOVE ( pm_list, ps_link );
1027 pm_list = LDAP_LIST_NEXT ( pm_list, ps_link );
1032 op->o_private = NULL;
1035 return ( ( rs->sr_err == LDAP_SUCCESS ) ? noop : rs->sr_err );