1 1.3 christos /* $NetBSD: modrdn.c,v 1.4 2025/09/05 21:16:28 christos Exp $ */ 2 1.1 tron 3 1.1 tron /* modrdn.c - mdb backend modrdn routine */ 4 1.1 tron /* $OpenLDAP$ */ 5 1.1 tron /* This work is part of OpenLDAP Software <http://www.openldap.org/>. 6 1.1 tron * 7 1.4 christos * Copyright 2000-2024 The OpenLDAP Foundation. 8 1.1 tron * All rights reserved. 9 1.1 tron * 10 1.1 tron * Redistribution and use in source and binary forms, with or without 11 1.1 tron * modification, are permitted only as authorized by the OpenLDAP 12 1.1 tron * Public License. 13 1.1 tron * 14 1.1 tron * A copy of this license is available in the file LICENSE in the 15 1.1 tron * top-level directory of the distribution or, alternatively, at 16 1.1 tron * <http://www.OpenLDAP.org/license.html>. 17 1.1 tron */ 18 1.1 tron 19 1.2 christos #include <sys/cdefs.h> 20 1.3 christos __RCSID("$NetBSD: modrdn.c,v 1.4 2025/09/05 21:16:28 christos Exp $"); 21 1.2 christos 22 1.1 tron #include "portable.h" 23 1.1 tron 24 1.1 tron #include <stdio.h> 25 1.1 tron #include <ac/string.h> 26 1.1 tron 27 1.1 tron #include "back-mdb.h" 28 1.1 tron 29 1.1 tron int 30 1.1 tron mdb_modrdn( Operation *op, SlapReply *rs ) 31 1.1 tron { 32 1.1 tron struct mdb_info *mdb = (struct mdb_info *) op->o_bd->be_private; 33 1.1 tron AttributeDescription *children = slap_schema.si_ad_children; 34 1.1 tron AttributeDescription *entry = slap_schema.si_ad_entry; 35 1.1 tron struct berval p_dn, p_ndn; 36 1.1 tron Entry *e = NULL; 37 1.1 tron Entry *p = NULL; 38 1.1 tron /* LDAP v2 supporting correct attribute handling. */ 39 1.1 tron char textbuf[SLAP_TEXT_BUFLEN]; 40 1.1 tron size_t textlen = sizeof textbuf; 41 1.1 tron MDB_txn *txn = NULL; 42 1.1 tron MDB_cursor *mc; 43 1.1 tron struct mdb_op_info opinfo = {{{ 0 }}}, *moi = &opinfo; 44 1.1 tron Entry dummy = {0}; 45 1.1 tron 46 1.1 tron Entry *np = NULL; /* newSuperior Entry */ 47 1.1 tron struct berval *np_dn = NULL; /* newSuperior dn */ 48 1.1 tron struct berval *np_ndn = NULL; /* newSuperior ndn */ 49 1.1 tron struct berval *new_parent_dn = NULL; /* np_dn, p_dn, or NULL */ 50 1.1 tron 51 1.1 tron int manageDSAit = get_manageDSAit( op ); 52 1.1 tron 53 1.1 tron ID nid, nsubs; 54 1.1 tron LDAPControl **preread_ctrl = NULL; 55 1.1 tron LDAPControl **postread_ctrl = NULL; 56 1.1 tron LDAPControl *ctrls[SLAP_MAX_RESPONSE_CONTROLS]; 57 1.1 tron int num_ctrls = 0; 58 1.1 tron 59 1.1 tron int parent_is_glue = 0; 60 1.1 tron int parent_is_leaf = 0; 61 1.1 tron 62 1.1 tron Debug( LDAP_DEBUG_TRACE, "==>" LDAP_XSTRING(mdb_modrdn) "(%s,%s,%s)\n", 63 1.1 tron op->o_req_dn.bv_val,op->oq_modrdn.rs_newrdn.bv_val, 64 1.1 tron op->oq_modrdn.rs_newSup ? op->oq_modrdn.rs_newSup->bv_val : "NULL" ); 65 1.1 tron 66 1.1 tron ctrls[num_ctrls] = NULL; 67 1.1 tron 68 1.1 tron /* begin transaction */ 69 1.1 tron rs->sr_err = mdb_opinfo_get( op, mdb, 0, &moi ); 70 1.1 tron rs->sr_text = NULL; 71 1.1 tron if( rs->sr_err != 0 ) { 72 1.1 tron Debug( LDAP_DEBUG_TRACE, 73 1.1 tron LDAP_XSTRING(mdb_modrdn) ": txn_begin failed: " 74 1.3 christos "%s (%d)\n", mdb_strerror(rs->sr_err), rs->sr_err ); 75 1.1 tron rs->sr_err = LDAP_OTHER; 76 1.1 tron rs->sr_text = "internal error"; 77 1.1 tron goto return_results; 78 1.1 tron } 79 1.1 tron txn = moi->moi_txn; 80 1.1 tron 81 1.1 tron slap_mods_opattrs( op, &op->orr_modlist, 1 ); 82 1.1 tron 83 1.1 tron if ( be_issuffix( op->o_bd, &op->o_req_ndn ) ) { 84 1.1 tron #ifdef MDB_MULTIPLE_SUFFIXES 85 1.1 tron /* Allow renaming one suffix entry to another */ 86 1.1 tron p_ndn = slap_empty_bv; 87 1.1 tron #else 88 1.1 tron /* There can only be one suffix entry */ 89 1.1 tron rs->sr_err = LDAP_NAMING_VIOLATION; 90 1.1 tron rs->sr_text = "cannot rename suffix entry"; 91 1.1 tron goto return_results; 92 1.1 tron #endif 93 1.1 tron } else { 94 1.1 tron dnParent( &op->o_req_ndn, &p_ndn ); 95 1.1 tron } 96 1.1 tron np_ndn = &p_ndn; 97 1.1 tron /* Make sure parent entry exist and we can write its 98 1.1 tron * children. 99 1.1 tron */ 100 1.1 tron rs->sr_err = mdb_cursor_open( txn, mdb->mi_dn2id, &mc ); 101 1.1 tron if ( rs->sr_err != 0 ) { 102 1.1 tron Debug(LDAP_DEBUG_TRACE, 103 1.1 tron "<=- " LDAP_XSTRING(mdb_modrdn) 104 1.1 tron ": cursor_open failed: %s (%d)\n", 105 1.3 christos mdb_strerror(rs->sr_err), rs->sr_err ); 106 1.1 tron rs->sr_err = LDAP_OTHER; 107 1.1 tron rs->sr_text = "DN cursor_open failed"; 108 1.1 tron goto return_results; 109 1.1 tron } 110 1.1 tron rs->sr_err = mdb_dn2entry( op, txn, mc, &p_ndn, &p, NULL, 0 ); 111 1.1 tron switch( rs->sr_err ) { 112 1.1 tron case MDB_NOTFOUND: 113 1.1 tron Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(mdb_modrdn) 114 1.3 christos ": parent does not exist\n" ); 115 1.1 tron rs->sr_ref = referral_rewrite( default_referral, NULL, 116 1.1 tron &op->o_req_dn, LDAP_SCOPE_DEFAULT ); 117 1.1 tron rs->sr_err = LDAP_REFERRAL; 118 1.1 tron 119 1.1 tron send_ldap_result( op, rs ); 120 1.1 tron 121 1.1 tron ber_bvarray_free( rs->sr_ref ); 122 1.1 tron goto done; 123 1.1 tron case 0: 124 1.1 tron break; 125 1.1 tron case LDAP_BUSY: 126 1.1 tron rs->sr_text = "ldap server busy"; 127 1.1 tron goto return_results; 128 1.1 tron default: 129 1.1 tron rs->sr_err = LDAP_OTHER; 130 1.1 tron rs->sr_text = "internal error"; 131 1.1 tron goto return_results; 132 1.1 tron } 133 1.1 tron 134 1.1 tron /* check parent for "children" acl */ 135 1.1 tron rs->sr_err = access_allowed( op, p, 136 1.1 tron children, NULL, 137 1.1 tron op->oq_modrdn.rs_newSup == NULL ? 138 1.1 tron ACL_WRITE : ACL_WDEL, 139 1.1 tron NULL ); 140 1.1 tron 141 1.1 tron if ( ! rs->sr_err ) { 142 1.1 tron rs->sr_err = LDAP_INSUFFICIENT_ACCESS; 143 1.3 christos Debug( LDAP_DEBUG_TRACE, "no access to parent\n" ); 144 1.1 tron rs->sr_text = "no write access to parent's children"; 145 1.1 tron goto return_results; 146 1.1 tron } 147 1.1 tron 148 1.1 tron Debug( LDAP_DEBUG_TRACE, 149 1.1 tron LDAP_XSTRING(mdb_modrdn) ": wr to children " 150 1.3 christos "of entry %s OK\n", p_ndn.bv_val ); 151 1.1 tron 152 1.1 tron if ( p_ndn.bv_val == slap_empty_bv.bv_val ) { 153 1.1 tron p_dn = slap_empty_bv; 154 1.1 tron } else { 155 1.1 tron dnParent( &op->o_req_dn, &p_dn ); 156 1.1 tron } 157 1.1 tron 158 1.1 tron Debug( LDAP_DEBUG_TRACE, 159 1.1 tron LDAP_XSTRING(mdb_modrdn) ": parent dn=%s\n", 160 1.3 christos p_dn.bv_val ); 161 1.1 tron 162 1.1 tron /* get entry */ 163 1.1 tron rs->sr_err = mdb_dn2entry( op, txn, mc, &op->o_req_ndn, &e, &nsubs, 0 ); 164 1.1 tron switch( rs->sr_err ) { 165 1.1 tron case MDB_NOTFOUND: 166 1.1 tron e = p; 167 1.1 tron p = NULL; 168 1.1 tron case 0: 169 1.1 tron break; 170 1.1 tron case LDAP_BUSY: 171 1.1 tron rs->sr_text = "ldap server busy"; 172 1.1 tron goto return_results; 173 1.1 tron default: 174 1.1 tron rs->sr_err = LDAP_OTHER; 175 1.1 tron rs->sr_text = "internal error"; 176 1.1 tron goto return_results; 177 1.1 tron } 178 1.1 tron 179 1.1 tron /* FIXME: dn2entry() should return non-glue entry */ 180 1.1 tron if (( rs->sr_err == MDB_NOTFOUND ) || 181 1.1 tron ( !manageDSAit && e && is_entry_glue( e ))) 182 1.1 tron { 183 1.1 tron if( e != NULL ) { 184 1.1 tron rs->sr_matched = ch_strdup( e->e_dn ); 185 1.1 tron if ( is_entry_referral( e )) { 186 1.1 tron BerVarray ref = get_entry_referrals( op, e ); 187 1.1 tron rs->sr_ref = referral_rewrite( ref, &e->e_name, 188 1.1 tron &op->o_req_dn, LDAP_SCOPE_DEFAULT ); 189 1.1 tron ber_bvarray_free( ref ); 190 1.1 tron } else { 191 1.1 tron rs->sr_ref = NULL; 192 1.1 tron } 193 1.1 tron mdb_entry_return( op, e ); 194 1.1 tron e = NULL; 195 1.1 tron 196 1.1 tron } else { 197 1.1 tron rs->sr_ref = referral_rewrite( default_referral, NULL, 198 1.1 tron &op->o_req_dn, LDAP_SCOPE_DEFAULT ); 199 1.1 tron } 200 1.1 tron 201 1.1 tron rs->sr_err = LDAP_REFERRAL; 202 1.1 tron send_ldap_result( op, rs ); 203 1.1 tron 204 1.1 tron ber_bvarray_free( rs->sr_ref ); 205 1.1 tron free( (char *)rs->sr_matched ); 206 1.1 tron rs->sr_ref = NULL; 207 1.1 tron rs->sr_matched = NULL; 208 1.1 tron 209 1.1 tron goto done; 210 1.1 tron } 211 1.1 tron 212 1.1 tron if ( get_assert( op ) && 213 1.1 tron ( test_filter( op, e, get_assertion( op )) != LDAP_COMPARE_TRUE )) 214 1.1 tron { 215 1.1 tron rs->sr_err = LDAP_ASSERTION_FAILED; 216 1.1 tron goto return_results; 217 1.1 tron } 218 1.1 tron 219 1.1 tron /* check write on old entry */ 220 1.1 tron rs->sr_err = access_allowed( op, e, entry, NULL, ACL_WRITE, NULL ); 221 1.1 tron if ( ! rs->sr_err ) { 222 1.3 christos Debug( LDAP_DEBUG_TRACE, "no access to entry\n" ); 223 1.1 tron rs->sr_text = "no write access to old entry"; 224 1.1 tron rs->sr_err = LDAP_INSUFFICIENT_ACCESS; 225 1.1 tron goto return_results; 226 1.1 tron } 227 1.1 tron 228 1.1 tron if (!manageDSAit && is_entry_referral( e ) ) { 229 1.1 tron /* entry is a referral, don't allow rename */ 230 1.1 tron rs->sr_ref = get_entry_referrals( op, e ); 231 1.1 tron 232 1.1 tron Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(mdb_modrdn) 233 1.3 christos ": entry %s is referral\n", e->e_dn ); 234 1.1 tron 235 1.1 tron rs->sr_err = LDAP_REFERRAL, 236 1.1 tron rs->sr_matched = e->e_name.bv_val; 237 1.1 tron send_ldap_result( op, rs ); 238 1.1 tron 239 1.1 tron ber_bvarray_free( rs->sr_ref ); 240 1.1 tron rs->sr_ref = NULL; 241 1.1 tron rs->sr_matched = NULL; 242 1.1 tron goto done; 243 1.1 tron } 244 1.1 tron 245 1.1 tron new_parent_dn = &p_dn; /* New Parent unless newSuperior given */ 246 1.1 tron 247 1.1 tron if ( op->oq_modrdn.rs_newSup != NULL ) { 248 1.1 tron Debug( LDAP_DEBUG_TRACE, 249 1.1 tron LDAP_XSTRING(mdb_modrdn) 250 1.1 tron ": new parent \"%s\" requested...\n", 251 1.3 christos op->oq_modrdn.rs_newSup->bv_val ); 252 1.1 tron 253 1.1 tron /* newSuperior == oldParent? */ 254 1.1 tron if( dn_match( &p_ndn, op->oq_modrdn.rs_nnewSup ) ) { 255 1.1 tron Debug( LDAP_DEBUG_TRACE, "mdb_back_modrdn: " 256 1.1 tron "new parent \"%s\" same as the old parent \"%s\"\n", 257 1.3 christos op->oq_modrdn.rs_newSup->bv_val, p_dn.bv_val ); 258 1.1 tron op->oq_modrdn.rs_newSup = NULL; /* ignore newSuperior */ 259 1.1 tron } 260 1.1 tron } 261 1.1 tron 262 1.1 tron /* There's a MDB_MULTIPLE_SUFFIXES case here that this code doesn't 263 1.1 tron * support. E.g., two suffixes dc=foo,dc=com and dc=bar,dc=net. 264 1.1 tron * We do not allow modDN 265 1.1 tron * dc=foo,dc=com 266 1.1 tron * newrdn dc=bar 267 1.1 tron * newsup dc=net 268 1.1 tron * and we probably should. But since MULTIPLE_SUFFIXES is deprecated 269 1.1 tron * I'm ignoring this problem for now. 270 1.1 tron */ 271 1.1 tron if ( op->oq_modrdn.rs_newSup != NULL ) { 272 1.1 tron if ( op->oq_modrdn.rs_newSup->bv_len ) { 273 1.1 tron np_dn = op->oq_modrdn.rs_newSup; 274 1.1 tron np_ndn = op->oq_modrdn.rs_nnewSup; 275 1.1 tron 276 1.1 tron /* newSuperior == oldParent? - checked above */ 277 1.1 tron /* newSuperior == entry being moved?, if so ==> ERROR */ 278 1.1 tron if ( dnIsSuffix( np_ndn, &e->e_nname )) { 279 1.1 tron rs->sr_err = LDAP_NO_SUCH_OBJECT; 280 1.1 tron rs->sr_text = "new superior not found"; 281 1.1 tron goto return_results; 282 1.1 tron } 283 1.1 tron /* Get Entry with dn=newSuperior. Does newSuperior exist? */ 284 1.1 tron rs->sr_err = mdb_dn2entry( op, txn, NULL, np_ndn, &np, NULL, 0 ); 285 1.1 tron 286 1.1 tron switch( rs->sr_err ) { 287 1.1 tron case 0: 288 1.1 tron break; 289 1.1 tron case MDB_NOTFOUND: 290 1.1 tron Debug( LDAP_DEBUG_TRACE, 291 1.1 tron LDAP_XSTRING(mdb_modrdn) 292 1.1 tron ": newSup(ndn=%s) not here!\n", 293 1.3 christos np_ndn->bv_val ); 294 1.1 tron rs->sr_text = "new superior not found"; 295 1.1 tron rs->sr_err = LDAP_NO_SUCH_OBJECT; 296 1.1 tron goto return_results; 297 1.1 tron case LDAP_BUSY: 298 1.1 tron rs->sr_text = "ldap server busy"; 299 1.1 tron goto return_results; 300 1.1 tron default: 301 1.1 tron rs->sr_err = LDAP_OTHER; 302 1.1 tron rs->sr_text = "internal error"; 303 1.1 tron goto return_results; 304 1.1 tron } 305 1.1 tron 306 1.1 tron /* check newSuperior for "children" acl */ 307 1.1 tron rs->sr_err = access_allowed( op, np, children, 308 1.1 tron NULL, ACL_WADD, NULL ); 309 1.1 tron 310 1.1 tron if( ! rs->sr_err ) { 311 1.1 tron Debug( LDAP_DEBUG_TRACE, 312 1.1 tron LDAP_XSTRING(mdb_modrdn) 313 1.3 christos ": no wr to newSup children\n" ); 314 1.1 tron rs->sr_text = "no write access to new superior's children"; 315 1.1 tron rs->sr_err = LDAP_INSUFFICIENT_ACCESS; 316 1.1 tron goto return_results; 317 1.1 tron } 318 1.1 tron 319 1.1 tron Debug( LDAP_DEBUG_TRACE, 320 1.1 tron LDAP_XSTRING(mdb_modrdn) 321 1.1 tron ": wr to new parent OK np=%p, id=%ld\n", 322 1.3 christos (void *) np, (long) np->e_id ); 323 1.1 tron 324 1.1 tron if ( is_entry_alias( np ) ) { 325 1.1 tron /* parent is an alias, don't allow add */ 326 1.1 tron Debug( LDAP_DEBUG_TRACE, 327 1.1 tron LDAP_XSTRING(mdb_modrdn) 328 1.3 christos ": entry is alias\n" ); 329 1.1 tron rs->sr_text = "new superior is an alias"; 330 1.1 tron rs->sr_err = LDAP_ALIAS_PROBLEM; 331 1.1 tron goto return_results; 332 1.1 tron } 333 1.1 tron 334 1.1 tron if ( is_entry_referral( np ) ) { 335 1.1 tron /* parent is a referral, don't allow add */ 336 1.1 tron Debug( LDAP_DEBUG_TRACE, 337 1.1 tron LDAP_XSTRING(mdb_modrdn) 338 1.3 christos ": entry is referral\n" ); 339 1.1 tron rs->sr_text = "new superior is a referral"; 340 1.1 tron rs->sr_err = LDAP_OTHER; 341 1.1 tron goto return_results; 342 1.1 tron } 343 1.2 christos np_dn = &np->e_name; 344 1.1 tron 345 1.1 tron } else { 346 1.1 tron np_dn = NULL; 347 1.1 tron 348 1.1 tron /* no parent, modrdn entry directly under root */ 349 1.1 tron if ( be_issuffix( op->o_bd, (struct berval *)&slap_empty_bv ) 350 1.1 tron || be_isupdate( op ) ) { 351 1.1 tron np = (Entry *)&slap_entry_root; 352 1.1 tron 353 1.1 tron /* check parent for "children" acl */ 354 1.1 tron rs->sr_err = access_allowed( op, np, 355 1.1 tron children, NULL, ACL_WADD, NULL ); 356 1.1 tron 357 1.1 tron np = NULL; 358 1.1 tron 359 1.1 tron if ( ! rs->sr_err ) { 360 1.1 tron rs->sr_err = LDAP_INSUFFICIENT_ACCESS; 361 1.1 tron Debug( LDAP_DEBUG_TRACE, 362 1.3 christos "no access to new superior\n" ); 363 1.1 tron rs->sr_text = 364 1.1 tron "no write access to new superior's children"; 365 1.1 tron goto return_results; 366 1.1 tron } 367 1.1 tron } 368 1.1 tron } 369 1.1 tron 370 1.1 tron Debug( LDAP_DEBUG_TRACE, 371 1.1 tron LDAP_XSTRING(mdb_modrdn) 372 1.3 christos ": wr to new parent's children OK\n" ); 373 1.1 tron 374 1.1 tron new_parent_dn = np_dn; 375 1.1 tron } 376 1.1 tron 377 1.4 christos /* Make sure target entry doesn't exist already. */ 378 1.1 tron Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(mdb_modrdn) ": new ndn=%s\n", 379 1.4 christos op->orr_nnewDN.bv_val ); 380 1.1 tron 381 1.1 tron /* Shortcut the search */ 382 1.4 christos rs->sr_err = mdb_dn2id ( op, txn, NULL, &op->orr_nnewDN, &nid, NULL, NULL, NULL ); 383 1.1 tron switch( rs->sr_err ) { 384 1.1 tron case MDB_NOTFOUND: 385 1.1 tron break; 386 1.1 tron case 0: 387 1.1 tron /* Allow rename to same DN */ 388 1.1 tron if ( nid == e->e_id ) 389 1.1 tron break; 390 1.1 tron rs->sr_err = LDAP_ALREADY_EXISTS; 391 1.1 tron goto return_results; 392 1.1 tron default: 393 1.1 tron rs->sr_err = LDAP_OTHER; 394 1.1 tron rs->sr_text = "internal error"; 395 1.1 tron goto return_results; 396 1.1 tron } 397 1.1 tron 398 1.1 tron if( op->o_preread ) { 399 1.1 tron if( preread_ctrl == NULL ) { 400 1.1 tron preread_ctrl = &ctrls[num_ctrls++]; 401 1.1 tron ctrls[num_ctrls] = NULL; 402 1.1 tron } 403 1.1 tron if( slap_read_controls( op, rs, e, 404 1.1 tron &slap_pre_read_bv, preread_ctrl ) ) 405 1.1 tron { 406 1.1 tron Debug( LDAP_DEBUG_TRACE, 407 1.1 tron "<=- " LDAP_XSTRING(mdb_modrdn) 408 1.3 christos ": pre-read failed!\n" ); 409 1.1 tron if ( op->o_preread & SLAP_CONTROL_CRITICAL ) { 410 1.1 tron /* FIXME: is it correct to abort 411 1.1 tron * operation if control fails? */ 412 1.1 tron goto return_results; 413 1.1 tron } 414 1.1 tron } 415 1.1 tron } 416 1.1 tron 417 1.1 tron /* delete old DN 418 1.1 tron * If moving to a new parent, must delete current subtree count, 419 1.1 tron * otherwise leave it unchanged since we'll be adding it right back. 420 1.1 tron */ 421 1.1 tron rs->sr_err = mdb_dn2id_delete( op, mc, e->e_id, np ? nsubs : 0 ); 422 1.1 tron if ( rs->sr_err != 0 ) { 423 1.1 tron Debug(LDAP_DEBUG_TRACE, 424 1.1 tron "<=- " LDAP_XSTRING(mdb_modrdn) 425 1.1 tron ": dn2id del failed: %s (%d)\n", 426 1.3 christos mdb_strerror(rs->sr_err), rs->sr_err ); 427 1.1 tron rs->sr_err = LDAP_OTHER; 428 1.1 tron rs->sr_text = "DN index delete fail"; 429 1.1 tron goto return_results; 430 1.1 tron } 431 1.1 tron 432 1.1 tron /* copy the entry, then override some fields */ 433 1.1 tron dummy = *e; 434 1.4 christos dummy.e_name = op->orr_newDN; 435 1.4 christos dummy.e_nname = op->orr_nnewDN; 436 1.1 tron dummy.e_attrs = NULL; 437 1.1 tron 438 1.1 tron /* add new DN */ 439 1.1 tron rs->sr_err = mdb_dn2id_add( op, mc, mc, np ? np->e_id : p->e_id, 440 1.1 tron nsubs, np != NULL, &dummy ); 441 1.1 tron if ( rs->sr_err != 0 ) { 442 1.1 tron Debug(LDAP_DEBUG_TRACE, 443 1.1 tron "<=- " LDAP_XSTRING(mdb_modrdn) 444 1.1 tron ": dn2id add failed: %s (%d)\n", 445 1.3 christos mdb_strerror(rs->sr_err), rs->sr_err ); 446 1.1 tron rs->sr_err = LDAP_OTHER; 447 1.1 tron rs->sr_text = "DN index add failed"; 448 1.1 tron goto return_results; 449 1.1 tron } 450 1.1 tron 451 1.1 tron dummy.e_attrs = e->e_attrs; 452 1.1 tron 453 1.3 christos if ( op->orr_modlist != NULL ) { 454 1.3 christos /* modify entry */ 455 1.3 christos rs->sr_err = mdb_modify_internal( op, txn, op->orr_modlist, &dummy, 456 1.3 christos &rs->sr_text, textbuf, textlen ); 457 1.3 christos if( rs->sr_err != LDAP_SUCCESS ) { 458 1.3 christos Debug(LDAP_DEBUG_TRACE, 459 1.3 christos "<=- " LDAP_XSTRING(mdb_modrdn) 460 1.3 christos ": modify failed: %s (%d)\n", 461 1.3 christos mdb_strerror(rs->sr_err), rs->sr_err ); 462 1.3 christos goto return_results; 463 1.3 christos } 464 1.1 tron } 465 1.1 tron 466 1.1 tron /* id2entry index */ 467 1.1 tron rs->sr_err = mdb_id2entry_update( op, txn, NULL, &dummy ); 468 1.1 tron if ( rs->sr_err != 0 ) { 469 1.1 tron Debug(LDAP_DEBUG_TRACE, 470 1.1 tron "<=- " LDAP_XSTRING(mdb_modrdn) 471 1.1 tron ": id2entry failed: %s (%d)\n", 472 1.3 christos mdb_strerror(rs->sr_err), rs->sr_err ); 473 1.3 christos if ( rs->sr_err == LDAP_ADMINLIMIT_EXCEEDED ) { 474 1.3 christos rs->sr_text = "entry too big"; 475 1.3 christos } else { 476 1.3 christos rs->sr_err = LDAP_OTHER; 477 1.3 christos rs->sr_text = "entry update failed"; 478 1.3 christos } 479 1.1 tron goto return_results; 480 1.1 tron } 481 1.1 tron 482 1.1 tron if ( p_ndn.bv_len != 0 ) { 483 1.1 tron if ((parent_is_glue = is_entry_glue(p))) { 484 1.1 tron rs->sr_err = mdb_dn2id_children( op, txn, p ); 485 1.1 tron if ( rs->sr_err != MDB_NOTFOUND ) { 486 1.1 tron switch( rs->sr_err ) { 487 1.1 tron case 0: 488 1.1 tron break; 489 1.1 tron default: 490 1.1 tron Debug(LDAP_DEBUG_ARGS, 491 1.1 tron "<=- " LDAP_XSTRING(mdb_modrdn) 492 1.1 tron ": has_children failed: %s (%d)\n", 493 1.3 christos mdb_strerror(rs->sr_err), rs->sr_err ); 494 1.1 tron rs->sr_err = LDAP_OTHER; 495 1.1 tron rs->sr_text = "internal error"; 496 1.1 tron goto return_results; 497 1.1 tron } 498 1.1 tron } else { 499 1.1 tron parent_is_leaf = 1; 500 1.1 tron } 501 1.1 tron } 502 1.1 tron mdb_entry_return( op, p ); 503 1.1 tron p = NULL; 504 1.1 tron } 505 1.1 tron 506 1.1 tron if( op->o_postread ) { 507 1.1 tron if( postread_ctrl == NULL ) { 508 1.1 tron postread_ctrl = &ctrls[num_ctrls++]; 509 1.1 tron ctrls[num_ctrls] = NULL; 510 1.1 tron } 511 1.1 tron if( slap_read_controls( op, rs, &dummy, 512 1.1 tron &slap_post_read_bv, postread_ctrl ) ) 513 1.1 tron { 514 1.1 tron Debug( LDAP_DEBUG_TRACE, 515 1.1 tron "<=- " LDAP_XSTRING(mdb_modrdn) 516 1.3 christos ": post-read failed!\n" ); 517 1.1 tron if ( op->o_postread & SLAP_CONTROL_CRITICAL ) { 518 1.1 tron /* FIXME: is it correct to abort 519 1.1 tron * operation if control fails? */ 520 1.1 tron goto return_results; 521 1.1 tron } 522 1.1 tron } 523 1.1 tron } 524 1.1 tron 525 1.1 tron if( moi == &opinfo ) { 526 1.1 tron LDAP_SLIST_REMOVE( &op->o_extra, &opinfo.moi_oe, OpExtra, oe_next ); 527 1.1 tron opinfo.moi_oe.oe_key = NULL; 528 1.1 tron if( op->o_noop ) { 529 1.1 tron mdb_txn_abort( txn ); 530 1.1 tron rs->sr_err = LDAP_X_NO_OPERATION; 531 1.1 tron txn = NULL; 532 1.1 tron goto return_results; 533 1.1 tron 534 1.1 tron } else { 535 1.1 tron if(( rs->sr_err=mdb_txn_commit( txn )) != 0 ) { 536 1.1 tron rs->sr_text = "txn_commit failed"; 537 1.1 tron } else { 538 1.1 tron rs->sr_err = LDAP_SUCCESS; 539 1.1 tron } 540 1.1 tron txn = NULL; 541 1.1 tron } 542 1.1 tron } 543 1.1 tron 544 1.1 tron if( rs->sr_err != LDAP_SUCCESS ) { 545 1.1 tron Debug( LDAP_DEBUG_ANY, 546 1.1 tron LDAP_XSTRING(mdb_modrdn) ": %s : %s (%d)\n", 547 1.1 tron rs->sr_text, mdb_strerror(rs->sr_err), rs->sr_err ); 548 1.1 tron rs->sr_err = LDAP_OTHER; 549 1.1 tron 550 1.1 tron goto return_results; 551 1.1 tron } 552 1.1 tron 553 1.1 tron Debug(LDAP_DEBUG_TRACE, 554 1.1 tron LDAP_XSTRING(mdb_modrdn) 555 1.1 tron ": rdn modified%s id=%08lx dn=\"%s\"\n", 556 1.1 tron op->o_noop ? " (no-op)" : "", 557 1.1 tron dummy.e_id, op->o_req_dn.bv_val ); 558 1.1 tron rs->sr_text = NULL; 559 1.1 tron if( num_ctrls ) rs->sr_ctrls = ctrls; 560 1.1 tron 561 1.1 tron return_results: 562 1.3 christos if ( e != NULL && dummy.e_attrs != e->e_attrs ) { 563 1.1 tron attrs_free( dummy.e_attrs ); 564 1.1 tron } 565 1.1 tron send_ldap_result( op, rs ); 566 1.1 tron 567 1.1 tron #if 0 568 1.1 tron if( rs->sr_err == LDAP_SUCCESS && mdb->bi_txn_cp_kbyte ) { 569 1.1 tron TXN_CHECKPOINT( mdb->bi_dbenv, 570 1.1 tron mdb->bi_txn_cp_kbyte, mdb->bi_txn_cp_min, 0 ); 571 1.1 tron } 572 1.1 tron #endif 573 1.1 tron 574 1.1 tron if ( rs->sr_err == LDAP_SUCCESS && parent_is_glue && parent_is_leaf ) { 575 1.1 tron op->o_delete_glue_parent = 1; 576 1.1 tron } 577 1.1 tron 578 1.1 tron done: 579 1.1 tron slap_graduate_commit_csn( op ); 580 1.1 tron 581 1.1 tron /* LDAP v3 Support */ 582 1.1 tron if( np != NULL ) { 583 1.1 tron /* free new parent */ 584 1.1 tron mdb_entry_return( op, np ); 585 1.1 tron } 586 1.1 tron 587 1.1 tron if( p != NULL ) { 588 1.1 tron /* free parent */ 589 1.1 tron mdb_entry_return( op, p ); 590 1.1 tron } 591 1.1 tron 592 1.1 tron /* free entry */ 593 1.1 tron if( e != NULL ) { 594 1.1 tron mdb_entry_return( op, e ); 595 1.1 tron } 596 1.1 tron 597 1.1 tron if( moi == &opinfo ) { 598 1.1 tron if( txn != NULL ) { 599 1.1 tron mdb_txn_abort( txn ); 600 1.1 tron } 601 1.1 tron if ( opinfo.moi_oe.oe_key ) { 602 1.1 tron LDAP_SLIST_REMOVE( &op->o_extra, &opinfo.moi_oe, OpExtra, oe_next ); 603 1.1 tron } 604 1.1 tron } else { 605 1.1 tron moi->moi_ref--; 606 1.1 tron } 607 1.1 tron 608 1.1 tron if( preread_ctrl != NULL && (*preread_ctrl) != NULL ) { 609 1.1 tron slap_sl_free( (*preread_ctrl)->ldctl_value.bv_val, op->o_tmpmemctx ); 610 1.1 tron slap_sl_free( *preread_ctrl, op->o_tmpmemctx ); 611 1.1 tron } 612 1.1 tron if( postread_ctrl != NULL && (*postread_ctrl) != NULL ) { 613 1.1 tron slap_sl_free( (*postread_ctrl)->ldctl_value.bv_val, op->o_tmpmemctx ); 614 1.1 tron slap_sl_free( *postread_ctrl, op->o_tmpmemctx ); 615 1.1 tron } 616 1.1 tron return rs->sr_err; 617 1.1 tron } 618