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