]> git.sur5r.net Git - openldap/blob - servers/slapd/back-bdb/modrdn.c
Fix unindent commit
[openldap] / servers / slapd / back-bdb / modrdn.c
1 /* modrdn.c - bdb backend modrdn routine */
2 /* $OpenLDAP$ */
3 /*
4  * Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved.
5  * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
6  */
7
8 #include "portable.h"
9
10 #include <stdio.h>
11 #include <ac/string.h>
12
13 #include "back-bdb.h"
14 #include "external.h"
15
16 int
17 bdb_modrdn(
18         Backend *be,
19         Connection      *conn,
20         Operation       *op,
21         struct berval   *dn,
22         struct berval   *ndn,
23         struct berval   *newrdn,
24         struct berval   *nnewrdn,
25         int             deleteoldrdn,
26         struct berval   *newSuperior,
27         struct berval   *nnewSuperior )
28 {
29         struct bdb_info *bdb = (struct bdb_info *) be->be_private;
30         AttributeDescription *children = slap_schema.si_ad_children;
31         struct berval   p_dn, p_ndn;
32         struct berval   new_dn = {0, NULL}, new_ndn = {0, NULL};
33         int             isroot = -1;
34         Entry           *e = NULL;
35         Entry           *p = NULL;
36         Entry           *matched;
37         /* LDAP v2 supporting correct attribute handling. */
38         LDAPRDN         *new_rdn = NULL;
39         LDAPRDN         *old_rdn = NULL;
40         int                     rc;
41         const char *text;
42         char textbuf[SLAP_TEXT_BUFLEN];
43         size_t textlen = sizeof textbuf;
44         DB_TXN *        ltid = NULL;
45         struct bdb_op_info opinfo;
46
47         ID                      id;
48
49         Entry           *np = NULL;                     /* newSuperior Entry */
50         struct berval   *np_dn = NULL;                  /* newSuperior dn */
51         struct berval   *np_ndn = NULL;                 /* newSuperior ndn */
52         struct berval   *new_parent_dn = NULL;  /* np_dn, p_dn, or NULL */
53
54         /* Used to interface with bdb_modify_internal() */
55         Modifications   *mod = NULL;            /* Used to delete old rdn */
56
57         int             manageDSAit = get_manageDSAit( op );
58
59         u_int32_t       locker;
60         DB_LOCK         lock;
61
62 #ifdef NEW_LOGGING
63         LDAP_LOG ( OPERATION, ENTRY, "==>bdb_modrdn(%s,%s,%s)\n", 
64                 dn->bv_val,newrdn->bv_val, newSuperior ? newSuperior->bv_val : "NULL" );
65 #else
66         Debug( LDAP_DEBUG_TRACE, "==>bdb_modrdn(%s,%s,%s)\n",
67                 dn->bv_val, newrdn->bv_val,
68                 newSuperior ? newSuperior->bv_val : "NULL" );
69 #endif
70
71 #if 0
72         if( newSuperior != NULL ) {
73                 rc = LDAP_UNWILLING_TO_PERFORM;
74                 text = "newSuperior not implemented (yet)";
75                 goto return_results;
76         }
77 #endif
78
79         if( 0 ) {
80 retry:  /* transaction retry */
81                 if (e != NULL) {
82                         bdb_cache_delete_entry(&bdb->bi_cache, e);
83                         bdb_unlocked_cache_return_entry_w(&bdb->bi_cache, e);
84                 }
85                 if (p != NULL) {
86                         bdb_unlocked_cache_return_entry_r(&bdb->bi_cache, p);
87                 }
88                 if (np != NULL) {
89                         bdb_unlocked_cache_return_entry_r(&bdb->bi_cache, np);
90                 }
91 #ifdef NEW_LOGGING
92                 LDAP_LOG ( OPERATION, DETAIL1, "==>bdb_modrdn: retrying...\n", 0, 0, 0);
93 #else
94                 Debug( LDAP_DEBUG_TRACE, "==>bdb_modrdn: retrying...\n", 0, 0, 0 );
95 #endif
96                 rc = TXN_ABORT( ltid );
97                 ltid = NULL;
98                 op->o_private = NULL;
99                 if( rc != 0 ) {
100                         rc = LDAP_OTHER;
101                         text = "internal error";
102                         goto return_results;
103                 }
104                 ldap_pvt_thread_yield();
105         }
106
107         /* begin transaction */
108         rc = TXN_BEGIN( bdb->bi_dbenv, NULL, &ltid, 
109                 bdb->bi_db_opflags );
110         text = NULL;
111         if( rc != 0 ) {
112 #ifdef NEW_LOGGING
113                 LDAP_LOG ( OPERATION, ERR, 
114                         "==>bdb_modrdn: txn_begin failed: %s (%d)\n", 
115                         db_strerror(rc), rc, 0 );
116 #else
117                 Debug( LDAP_DEBUG_TRACE,
118                         "bdb_delete: txn_begin failed: %s (%d)\n",
119                         db_strerror(rc), rc, 0 );
120 #endif
121                 rc = LDAP_OTHER;
122                 text = "internal error";
123                 goto return_results;
124         }
125
126         locker = TXN_ID ( ltid );
127
128         opinfo.boi_bdb = be;
129         opinfo.boi_txn = ltid;
130         opinfo.boi_err = 0;
131         op->o_private = &opinfo;
132
133         /* get entry */
134         rc = bdb_dn2entry_w( be, ltid, ndn, &e, &matched, DB_RMW, locker, &lock );
135
136         switch( rc ) {
137         case 0:
138         case DB_NOTFOUND:
139                 break;
140         case DB_LOCK_DEADLOCK:
141         case DB_LOCK_NOTGRANTED:
142                 goto retry;
143         case LDAP_BUSY:
144                 text = "ldap server busy";
145                 goto return_results;
146         default:
147                 rc = LDAP_OTHER;
148                 text = "internal error";
149                 goto return_results;
150         }
151
152         if ( e == NULL ) {
153                 char* matched_dn = NULL;
154                 BerVarray refs;
155
156                 if( matched != NULL ) {
157                         matched_dn = ch_strdup( matched->e_dn );
158                         refs = is_entry_referral( matched )
159                                 ? get_entry_referrals( be, conn, op, matched )
160                                 : NULL;
161                         bdb_unlocked_cache_return_entry_r( &bdb->bi_cache, matched);
162                         matched = NULL;
163
164                 } else {
165                         refs = referral_rewrite( default_referral,
166                                 NULL, dn, LDAP_SCOPE_DEFAULT );
167                 }
168
169                 send_ldap_result( conn, op, rc = LDAP_REFERRAL,
170                         matched_dn, NULL, refs, NULL );
171
172                 ber_bvarray_free( refs );
173                 free( matched_dn );
174
175                 goto done;
176         }
177
178         if (!manageDSAit && is_entry_referral( e ) ) {
179                 /* parent is a referral, don't allow add */
180                 /* parent is an alias, don't allow add */
181                 BerVarray refs = get_entry_referrals( be,
182                         conn, op, e );
183
184 #ifdef NEW_LOGGING
185                 LDAP_LOG ( OPERATION, DETAIL1, 
186                         "==>bdb_modrdn: entry %s is referral \n", e->e_dn, 0, 0 );
187 #else
188                 Debug( LDAP_DEBUG_TRACE, "bdb_modrdn: entry %s is referral\n",
189                         e->e_dn, 0, 0 );
190 #endif
191
192                 send_ldap_result( conn, op, rc = LDAP_REFERRAL,
193                         e->e_dn, NULL, refs, NULL );
194
195                 ber_bvarray_free( refs );
196                 goto done;
197         }
198
199         if ( be_issuffix( be, &e->e_nname ) ) {
200                 p_ndn = slap_empty_bv;
201         } else {
202                 dnParent( &e->e_nname, &p_ndn );
203         }
204         np_ndn = &p_ndn;
205         if ( p_ndn.bv_len != 0 ) {
206                 /* Make sure parent entry exist and we can write its 
207                  * children.
208                  */
209                 rc = bdb_dn2entry_r( be, ltid, &p_ndn, &p, NULL, 0, locker, &lock );
210
211                 switch( rc ) {
212                 case 0:
213                 case DB_NOTFOUND:
214                         break;
215                 case DB_LOCK_DEADLOCK:
216                 case DB_LOCK_NOTGRANTED:
217                         goto retry;
218                 case LDAP_BUSY:
219                         text = "ldap server busy";
220                         goto return_results;
221                 default:
222                         rc = LDAP_OTHER;
223                         text = "internal error";
224                         goto return_results;
225                 }
226
227                 if( p == NULL) {
228 #ifdef NEW_LOGGING
229                         LDAP_LOG ( OPERATION, ERR, 
230                                 "==>bdb_modrdn: parent does not exist\n", 0, 0, 0 );
231 #else
232                         Debug( LDAP_DEBUG_TRACE, "bdb_modrdn: parent does not exist\n",
233                                 0, 0, 0);
234 #endif
235                         rc = LDAP_OTHER;
236                         goto return_results;
237                 }
238
239                 /* check parent for "children" acl */
240                 if ( ! access_allowed( be, conn, op, p,
241                         children, NULL, ACL_WRITE, NULL ) )
242                 {
243 #ifdef NEW_LOGGING
244                         LDAP_LOG ( OPERATION, ERR, 
245                                 "==>bdb_modrdn: no access to parent\n", 0, 0, 0 );
246 #else
247                         Debug( LDAP_DEBUG_TRACE, "no access to parent\n", 0,
248                                 0, 0 );
249 #endif
250                         send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
251                                 NULL, NULL, NULL, NULL );
252                         goto return_results;
253                 }
254
255 #ifdef NEW_LOGGING
256                 LDAP_LOG ( OPERATION, DETAIL1, 
257                         "==>bdb_modrdn: wr to children %s is OK\n", p_ndn.bv_val, 0, 0 );
258 #else
259                 Debug( LDAP_DEBUG_TRACE,
260                         "bdb_modrdn: wr to children of entry %s OK\n",
261                         p_ndn.bv_val, 0, 0 );
262 #endif
263                 
264                 if ( p_ndn.bv_val == slap_empty_bv.bv_val ) {
265                         p_dn = slap_empty_bv;
266                 } else {
267                         dnParent( &e->e_name, &p_dn );
268                 }
269
270 #ifdef NEW_LOGGING
271                 LDAP_LOG ( OPERATION, DETAIL1, 
272                         "==>bdb_modrdn: parent dn=%s\n", p_dn.bv_val, 0, 0 );
273 #else
274                 Debug( LDAP_DEBUG_TRACE,
275                         "bdb_modrdn: parent dn=%s\n",
276                         p_dn.bv_val, 0, 0 );
277 #endif
278
279         } else {
280                 /* no parent, modrdn entry directly under root */
281                 isroot = be_isroot( be, &op->o_ndn );
282                 if ( ! isroot ) {
283                         if ( be_issuffix( be, (struct berval *)&slap_empty_bv )
284                                 || be_isupdate( be, &op->o_ndn ) ) {
285
286                                 p = (Entry *)&slap_entry_root;
287
288                                 /* check parent for "children" acl */
289                                 rc = access_allowed( be, conn, op, p,
290                                         children, NULL, ACL_WRITE, NULL );
291
292                                 p = NULL;
293
294                                 if ( ! rc )
295                                 {
296 #ifdef NEW_LOGGING
297                                         LDAP_LOG ( OPERATION, ERR, 
298                                                 "==>bdb_modrdn: no access to parent\n", 0, 0, 0 );
299 #else
300                                         Debug( LDAP_DEBUG_TRACE, 
301                                                 "no access to parent\n", 
302                                                 0, 0, 0 );
303 #endif
304                                         send_ldap_result( conn, op, 
305                                                 LDAP_INSUFFICIENT_ACCESS,
306                                                 NULL, NULL, NULL, NULL );
307                                         goto return_results;
308                                 }
309
310 #ifdef NEW_LOGGING
311                                 LDAP_LOG ( OPERATION, DETAIL1, 
312                                         "==>bdb_modrdn: wr to children of entry \"%s\" OK\n", 
313                                         p_dn.bv_val, 0, 0 );
314 #else
315                                 Debug( LDAP_DEBUG_TRACE,
316                                         "bdb_modrdn: wr to children of entry \"\" OK\n",
317                                         0, 0, 0 );
318 #endif
319                 
320                                 p_dn.bv_val = "";
321                                 p_dn.bv_len = 0;
322
323 #ifdef NEW_LOGGING
324                                 LDAP_LOG ( OPERATION, DETAIL1, 
325                                         "==>bdb_modrdn: parent dn=\"\" \n", 0, 0, 0 );
326 #else
327                                 Debug( LDAP_DEBUG_TRACE,
328                                         "bdb_modrdn: parent dn=\"\"\n",
329                                         0, 0, 0 );
330 #endif
331
332                         } else {
333 #ifdef NEW_LOGGING
334                                 LDAP_LOG ( OPERATION, ERR, 
335                                         "==>bdb_modrdn: no parent, not root &\"\" is not "
336                                         "suffix\n", 0, 0, 0 );
337 #else
338                                 Debug( LDAP_DEBUG_TRACE,
339                                         "bdb_modrdn: no parent, not root "
340                                         "& \"\" is not suffix\n",
341                                         0, 0, 0);
342 #endif
343                                 rc = LDAP_INSUFFICIENT_ACCESS;
344                                 goto return_results;
345                         }
346                 }
347         }
348
349         new_parent_dn = &p_dn;  /* New Parent unless newSuperior given */
350
351         if ( newSuperior != NULL ) {
352 #ifdef NEW_LOGGING
353                 LDAP_LOG ( OPERATION, DETAIL1, 
354                         "==>bdb_modrdn: new parent \"%s\" requested...\n", 
355                         newSuperior->bv_val, 0, 0 );
356 #else
357                 Debug( LDAP_DEBUG_TRACE, 
358                         "bdb_modrdn: new parent \"%s\" requested...\n",
359                         newSuperior->bv_val, 0, 0 );
360 #endif
361
362                 if ( newSuperior->bv_len ) {
363                         np_dn = newSuperior;
364                         np_ndn = nnewSuperior;
365
366                         /* newSuperior == oldParent?, if so ==> ERROR */
367                         /* newSuperior == entry being moved?, if so ==> ERROR */
368                         /* Get Entry with dn=newSuperior. Does newSuperior exist? */
369
370                         rc = bdb_dn2entry_r( be, ltid, nnewSuperior, &np, NULL, 0, locker, &lock );
371
372                         switch( rc ) {
373                         case 0:
374                         case DB_NOTFOUND:
375                                 break;
376                         case DB_LOCK_DEADLOCK:
377                         case DB_LOCK_NOTGRANTED:
378                                 goto retry;
379                         case LDAP_BUSY:
380                                 text = "ldap server busy";
381                                 goto return_results;
382                         default:
383                                 rc = LDAP_OTHER;
384                                 text = "internal error";
385                                 goto return_results;
386                         }
387
388                         if( np == NULL) {
389 #ifdef NEW_LOGGING
390                                 LDAP_LOG ( OPERATION, DETAIL1, 
391                                         "==>bdb_modrdn: newSup(ndn=%s) not here!\n", 
392                                         np_ndn->bv_val, 0, 0 );
393 #else
394                                 Debug( LDAP_DEBUG_TRACE,
395                                         "bdb_modrdn: newSup(ndn=%s) not here!\n",
396                                         np_ndn->bv_val, 0, 0);
397 #endif
398                                 rc = LDAP_OTHER;
399                                 goto return_results;
400                         }
401
402 #ifdef NEW_LOGGING
403                         LDAP_LOG ( OPERATION, DETAIL1, 
404                                 "==>bdb_modrdn: wr to new parent OK np=%p, id=%ld\n", 
405                                 np, (long) np->e_id, 0 );
406 #else
407                         Debug( LDAP_DEBUG_TRACE,
408                                 "bdb_modrdn: wr to new parent OK np=%p, id=%ld\n",
409                                 np, (long) np->e_id, 0 );
410 #endif
411
412                         /* check newSuperior for "children" acl */
413                         if ( !access_allowed( be, conn, op, np, children, NULL, ACL_WRITE, NULL ) ) {
414 #ifdef NEW_LOGGING
415                                 LDAP_LOG ( OPERATION, DETAIL1, 
416                                         "==>bdb_modrdn: no wr to newSup children\n", 0, 0, 0 );
417 #else
418                                 Debug( LDAP_DEBUG_TRACE,
419                                         "bdb_modrdn: no wr to newSup children\n",
420                                         0, 0, 0 );
421 #endif
422                                 rc = LDAP_INSUFFICIENT_ACCESS;
423                                 goto return_results;
424                         }
425
426 #ifdef BDB_ALIASES
427                         if ( is_entry_alias( np ) ) {
428                                 /* parent is an alias, don't allow add */
429 #ifdef NEW_LOGGING
430                                 LDAP_LOG ( OPERATION, DETAIL1, 
431                                         "==>bdb_modrdn: entry is alias\n", 0, 0, 0 );
432 #else
433                                 Debug( LDAP_DEBUG_TRACE, "bdb_modrdn: entry is alias\n",
434                                         0, 0, 0 );
435 #endif
436
437                                 rc = LDAP_ALIAS_PROBLEM;
438                                 goto return_results;
439                         }
440 #endif
441
442                         if ( is_entry_referral( np ) ) {
443                                 /* parent is a referral, don't allow add */
444 #ifdef NEW_LOGGING
445                                 LDAP_LOG ( OPERATION, DETAIL1, 
446                                         "==>bdb_modrdn: entry is referral\n", 0, 0, 0 );
447 #else
448                                 Debug( LDAP_DEBUG_TRACE, "bdb_modrdn: entry is referral\n",
449                                         0, 0, 0 );
450 #endif
451
452                                 rc = LDAP_OTHER;
453                                 goto return_results;
454                         }
455
456                 } else {
457                         if ( isroot == -1 ) {
458                                 isroot = be_isroot( be, &op->o_ndn );
459                         }
460                         
461                         np_dn = NULL;
462
463                         /* no parent, modrdn entry directly under root */
464                         if ( ! isroot ) {
465                                 if ( be_issuffix( be, (struct berval *)&slap_empty_bv )
466                                         || be_isupdate( be, &op->o_ndn ) ) {
467                                         np = (Entry *)&slap_entry_root;
468
469                                         /* check parent for "children" acl */
470                                         rc = access_allowed( be, conn, op, np,
471                                                 children, NULL, ACL_WRITE, NULL );
472
473                                         np = NULL;
474
475                                         if ( ! rc )
476                                         {
477 #ifdef NEW_LOGGING
478                                                 LDAP_LOG ( OPERATION, ERR, 
479                                                         "==>bdb_modrdn: no access to superior\n", 0, 0, 0 );
480 #else
481                                                 Debug( LDAP_DEBUG_TRACE, 
482                                                         "no access to new superior\n", 
483                                                         0, 0, 0 );
484 #endif
485                                                 send_ldap_result( conn, op, 
486                                                         LDAP_INSUFFICIENT_ACCESS,
487                                                         NULL, NULL, NULL, NULL );
488                                                 goto return_results;
489                                         }
490
491 #ifdef NEW_LOGGING
492                                         LDAP_LOG ( OPERATION, DETAIL1, 
493                                                 "bdb_modrdn: wr to children entry \"\" OK\n", 0, 0, 0 );
494 #else
495                                         Debug( LDAP_DEBUG_TRACE,
496                                                 "bdb_modrdn: wr to children of entry \"\" OK\n",
497                                                 0, 0, 0 );
498 #endif
499                 
500                                 } else {
501 #ifdef NEW_LOGGING
502                                         LDAP_LOG ( OPERATION, ERR, 
503                                                 "bdb_modrdn: new superior=\"\", not root & \"\" "
504                                                 "is not suffix\n", 0, 0, 0 );
505 #else
506                                         Debug( LDAP_DEBUG_TRACE,
507                                                 "bdb_modrdn: new superior=\"\", not root "
508                                                 "& \"\" is not suffix\n",
509                                                 0, 0, 0);
510 #endif
511                                         rc = LDAP_INSUFFICIENT_ACCESS;
512                                         goto return_results;
513                                 }
514                         }
515
516 #ifdef NEW_LOGGING
517                         LDAP_LOG ( OPERATION, DETAIL1, 
518                                 "bdb_modrdn: new superior=\"\"\n", 0, 0, 0 );
519 #else
520                         Debug( LDAP_DEBUG_TRACE,
521                                 "bdb_modrdn: new superior=\"\"\n",
522                                 0, 0, 0 );
523 #endif
524                 }
525
526 #ifdef NEW_LOGGING
527                 LDAP_LOG ( OPERATION, DETAIL1, 
528                         "bdb_modrdn: wr to new parent's children OK\n", 0, 0, 0 );
529 #else
530                 Debug( LDAP_DEBUG_TRACE,
531                         "bdb_modrdn: wr to new parent's children OK\n",
532                         0, 0, 0 );
533 #endif
534
535                 new_parent_dn = np_dn;
536         }
537         
538         /* Build target dn and make sure target entry doesn't exist already. */
539         build_new_dn( &new_dn, new_parent_dn, newrdn ); 
540
541         dnNormalize2( NULL, &new_dn, &new_ndn );
542
543 #ifdef NEW_LOGGING
544         LDAP_LOG ( OPERATION, RESULTS, 
545                 "bdb_modrdn: new ndn=%s\n", new_ndn.bv_val, 0, 0 );
546 #else
547         Debug( LDAP_DEBUG_TRACE, "bdb_modrdn: new ndn=%s\n",
548                 new_ndn.bv_val, 0, 0 );
549 #endif
550
551         rc = bdb_dn2id ( be, ltid, &new_ndn, &id, 0 );
552         switch( rc ) {
553         case DB_LOCK_DEADLOCK:
554         case DB_LOCK_NOTGRANTED:
555                 goto retry;
556         case DB_NOTFOUND:
557                 break;
558         case 0:
559                 rc = LDAP_ALREADY_EXISTS;
560                 goto return_results;
561         default:
562                 rc = LDAP_OTHER;
563                 text = "internal error";
564                 goto return_results;
565         }
566
567 #ifdef NEW_LOGGING
568         LDAP_LOG ( OPERATION, ERR, 
569                 "bdb_modrdn: new ndn=%s does not exist\n", new_ndn.bv_val, 0, 0 );
570 #else
571         Debug( LDAP_DEBUG_TRACE,
572                 "bdb_modrdn: new ndn=%s does not exist\n",
573                 new_ndn.bv_val, 0, 0 );
574 #endif
575
576         /* Get attribute type and attribute value of our new rdn, we will
577          * need to add that to our new entry
578          */
579         if ( ldap_bv2rdn( newrdn, &new_rdn, (char **)&text,
580                 LDAP_DN_FORMAT_LDAP ) )
581         {
582 #ifdef NEW_LOGGING
583                 LDAP_LOG ( OPERATION, ERR, 
584                         "bdb_modrdn: can't figure out "
585                         "type(s)/values(s) of newrdn\n", 
586                         0, 0, 0 );
587 #else
588                 Debug( LDAP_DEBUG_TRACE,
589                         "bdb_modrdn: can't figure out "
590                         "type(s)/values(s) of newrdn\n", 
591                         0, 0, 0 );
592 #endif
593                 rc = LDAP_INVALID_DN_SYNTAX;
594                 text = "unknown type(s) used in RDN";
595                 goto return_results;
596         }
597
598 #ifdef NEW_LOGGING
599         LDAP_LOG ( OPERATION, RESULTS, 
600                 "bdb_modrdn: new_rdn_type=\"%s\", "
601                 "new_rdn_val=\"%s\"\n",
602                 new_rdn[ 0 ][ 0 ]->la_attr.bv_val, 
603                 new_rdn[ 0 ][ 0 ]->la_value.bv_val, 0 );
604 #else
605         Debug( LDAP_DEBUG_TRACE,
606                 "bdb_modrdn: new_rdn_type=\"%s\", "
607                 "new_rdn_val=\"%s\"\n",
608                 new_rdn[ 0 ][ 0 ]->la_attr.bv_val,
609                 new_rdn[ 0 ][ 0 ]->la_value.bv_val, 0 );
610 #endif
611
612         if ( deleteoldrdn ) {
613                 if ( ldap_bv2rdn( dn, &old_rdn, (char **)&text,
614                         LDAP_DN_FORMAT_LDAP ) )
615                 {
616 #ifdef NEW_LOGGING
617                         LDAP_LOG ( OPERATION, ERR, 
618                                 "bdb_modrdn: can't figure out "
619                                 "type(s)/values(s) of old_rdn\n", 
620                                 0, 0, 0 );
621 #else
622                         Debug( LDAP_DEBUG_TRACE,
623                                 "bdb_modrdn: can't figure out "
624                                 "the old_rdn type(s)/value(s)\n", 
625                                 0, 0, 0 );
626 #endif
627                         rc = LDAP_OTHER;
628                         text = "cannot parse RDN from old DN";
629                         goto return_results;            
630                 }
631         }
632
633         /* prepare modlist of modifications from old/new rdn */
634         rc = slap_modrdn2mods( be, conn, op, e, old_rdn, new_rdn, 
635                         deleteoldrdn, &mod );
636         if ( rc != LDAP_SUCCESS ) {
637                 goto return_results;
638         }
639         
640         /* delete old one */
641         rc = bdb_dn2id_delete( be, ltid, p_ndn.bv_val, e );
642         if ( rc != 0 ) {
643                 switch( rc ) {
644                 case DB_LOCK_DEADLOCK:
645                 case DB_LOCK_NOTGRANTED:
646                         goto retry;
647                 }
648                 rc = LDAP_OTHER;
649                 text = "DN index delete fail";
650                 goto return_results;
651         }
652
653         (void) bdb_cache_delete_entry(&bdb->bi_cache, e);
654
655         /* Binary format uses a single contiguous block, cannot
656          * free individual fields. Leave new_dn/new_ndn set so
657          * they can be individually freed later.
658          */
659         e->e_name = new_dn;
660         e->e_nname = new_ndn;
661
662         new_dn.bv_val = NULL;
663         new_ndn.bv_val = NULL;
664
665         /* add new one */
666         rc = bdb_dn2id_add( be, ltid, np_ndn, e );
667         if ( rc != 0 ) {
668                 switch( rc ) {
669                 case DB_LOCK_DEADLOCK:
670                 case DB_LOCK_NOTGRANTED:
671                         goto retry;
672                 }
673                 rc = LDAP_OTHER;
674                 text = "DN index add failed";
675                 goto return_results;
676         }
677
678         /* modify entry */
679         rc = bdb_modify_internal( be, conn, op, ltid, &mod[0], e,
680                 &text, textbuf, textlen );
681
682         if( rc != LDAP_SUCCESS ) {
683                 switch( rc ) {
684                 case DB_LOCK_DEADLOCK:
685                 case DB_LOCK_NOTGRANTED:
686                         goto retry;
687                 }
688                 goto return_results;
689         }
690         
691         /* id2entry index */
692         rc = bdb_id2entry_update( be, ltid, e );
693         if ( rc != 0 ) {
694                 switch( rc ) {
695                 case DB_LOCK_DEADLOCK:
696                 case DB_LOCK_NOTGRANTED:
697                         goto retry;
698                 }
699                 rc = LDAP_OTHER;
700                 text = "entry update failed";
701                 goto return_results;
702         }
703
704         if( op->o_noop ) {
705                 if(( rc=TXN_ABORT( ltid )) != 0 ) {
706                         text = "txn_abort (no-op) failed";
707                 } else {
708                         rc = LDAP_SUCCESS;
709                 }
710
711         } else {
712                 char gid[DB_XIDDATASIZE];
713
714                 snprintf( gid, sizeof( gid ), "%s-%08lx-%08lx",
715                         bdb_uuid.bv_val, (long) op->o_connid, (long) op->o_opid );
716
717                 if(( rc=TXN_PREPARE( ltid, gid )) != 0 ) {
718                         text = "txn_prepare failed";
719                 } else {
720                         if( bdb_cache_update_entry(&bdb->bi_cache, e) == -1 ) {
721                                 if(( rc=TXN_ABORT( ltid )) != 0 ) {
722                                         text ="cache update & txn_abort failed";
723                                 } else {
724                                         rc = LDAP_OTHER;
725                                         text = "cache update failed";
726                                 }
727
728                         } else {
729                                 if(( rc=TXN_COMMIT( ltid, 0 )) != 0 ) {
730                                         text = "txn_commit failed";
731                                 } else {
732                                         rc = LDAP_SUCCESS;
733                                 }
734                         }
735                 }
736         }
737  
738         ltid = NULL;
739         op->o_private = NULL;
740  
741         if( rc == LDAP_SUCCESS ) {
742 #ifdef NEW_LOGGING
743                 LDAP_LOG ( OPERATION, RESULTS, 
744                         "bdb_modrdn: rdn modified%s id=%08lx dn=\"%s\"\n", 
745                         op->o_noop ? " (no-op)" : "", e->e_id, e->e_dn );
746 #else
747                 Debug(LDAP_DEBUG_TRACE,
748                         "bdb_modrdn: rdn modified%s id=%08lx dn=\"%s\"\n",
749                         op->o_noop ? " (no-op)" : "", e->e_id, e->e_dn );
750 #endif
751                 text = NULL;
752                 bdb_cache_entry_commit( e );
753
754         } else {
755 #ifdef NEW_LOGGING
756                 LDAP_LOG ( OPERATION, RESULTS, "bdb_modrdn: %s : %s (%d)\n", 
757                         text, db_strerror(rc), rc );
758 #else
759                 Debug( LDAP_DEBUG_TRACE, "bdb_add: %s : %s (%d)\n",
760                         text, db_strerror(rc), rc );
761 #endif
762                 rc = LDAP_OTHER;
763         }
764
765 return_results:
766         send_ldap_result( conn, op, rc,
767                 NULL, text, NULL, NULL );
768
769         if( rc == LDAP_SUCCESS && bdb->bi_txn_cp ) {
770                 ldap_pvt_thread_yield();
771                 TXN_CHECKPOINT( bdb->bi_dbenv,
772                         bdb->bi_txn_cp_kbyte, bdb->bi_txn_cp_min, 0 );
773         }
774
775 done:
776         if( new_dn.bv_val != NULL ) free( new_dn.bv_val );
777         if( new_ndn.bv_val != NULL ) free( new_ndn.bv_val );
778
779         /* LDAP v2 supporting correct attribute handling. */
780         if ( new_rdn != NULL ) {
781                 ldap_rdnfree( new_rdn );
782         }
783         if ( old_rdn != NULL ) {
784                 ldap_rdnfree( old_rdn );
785         }
786         if( mod != NULL ) {
787                 Modifications *tmp;
788                 for (; mod; mod=tmp ) {
789                         tmp = mod->sml_next;
790                         free( mod );
791                 }
792         }
793
794         /* LDAP v3 Support */
795         if( np != NULL ) {
796                 /* free new parent and reader lock */
797                 bdb_unlocked_cache_return_entry_r(&bdb->bi_cache, np);
798         }
799
800         if( p != NULL ) {
801                 /* free parent and reader lock */
802                 bdb_unlocked_cache_return_entry_r(&bdb->bi_cache, p);
803         }
804
805         /* free entry */
806         if( e != NULL ) {
807                 bdb_unlocked_cache_return_entry_w( &bdb->bi_cache, e);
808         }
809
810         if( ltid != NULL ) {
811                 TXN_ABORT( ltid );
812                 op->o_private = NULL;
813         }
814
815         return rc;
816 }