+static int
+config_rename_attr( SlapReply *rs, Entry *e, struct berval *rdn,
+ Attribute **at )
+{
+ struct berval rtype, rval;
+ Attribute *a;
+ AttributeDescription *ad = NULL;
+
+ dnRdn( &e->e_name, rdn );
+ rval.bv_val = strchr(rdn->bv_val, '=' ) + 1;
+ rval.bv_len = rdn->bv_len - (rval.bv_val - rdn->bv_val);
+ rtype.bv_val = rdn->bv_val;
+ rtype.bv_len = rval.bv_val - rtype.bv_val - 1;
+
+ /* Find attr */
+ slap_bv2ad( &rtype, &ad, &rs->sr_text );
+ a = attr_find( e->e_attrs, ad );
+ if (!a ) return LDAP_NAMING_VIOLATION;
+ *at = a;
+
+ return 0;
+}
+
+static void
+config_rename_kids( CfEntryInfo *ce )
+{
+ CfEntryInfo *ce2;
+ struct berval rdn, nrdn;
+
+ for (ce2 = ce->ce_kids; ce2; ce2 = ce2->ce_sibs) {
+ dnRdn ( &ce2->ce_entry->e_name, &rdn );
+ dnRdn ( &ce2->ce_entry->e_nname, &nrdn );
+ free( ce2->ce_entry->e_name.bv_val );
+ free( ce2->ce_entry->e_nname.bv_val );
+ build_new_dn( &ce2->ce_entry->e_name, &ce->ce_entry->e_name,
+ &rdn, NULL );
+ build_new_dn( &ce2->ce_entry->e_nname, &ce->ce_entry->e_nname,
+ &nrdn, NULL );
+ config_rename_kids( ce2 );
+ }
+}
+
+static int
+config_rename_one( Operation *op, SlapReply *rs, Entry *e,
+ CfEntryInfo *parent, Attribute *a, struct berval *newrdn,
+ struct berval *nnewrdn, int use_ldif )
+{
+ char *ptr1;
+ int rc = 0;
+ struct berval odn, ondn;
+
+ odn = e->e_name;
+ ondn = e->e_nname;
+ build_new_dn( &e->e_name, &parent->ce_entry->e_name, newrdn, NULL );
+ build_new_dn( &e->e_nname, &parent->ce_entry->e_nname, nnewrdn, NULL );
+
+ /* Replace attr */
+ free( a->a_vals[0].bv_val );
+ ptr1 = strchr( newrdn->bv_val, '=' ) + 1;
+ a->a_vals[0].bv_len = newrdn->bv_len - (ptr1 - newrdn->bv_val);
+ a->a_vals[0].bv_val = ch_malloc( a->a_vals[0].bv_len + 1 );
+ strcpy( a->a_vals[0].bv_val, ptr1 );
+
+ if ( a->a_nvals != a->a_vals ) {
+ free( a->a_nvals[0].bv_val );
+ ptr1 = strchr( nnewrdn->bv_val, '=' ) + 1;
+ a->a_nvals[0].bv_len = nnewrdn->bv_len - (ptr1 - nnewrdn->bv_val);
+ a->a_nvals[0].bv_val = ch_malloc( a->a_nvals[0].bv_len + 1 );
+ strcpy( a->a_nvals[0].bv_val, ptr1 );
+ }
+ if ( use_ldif ) {
+ CfBackInfo *cfb = (CfBackInfo *)op->o_bd->be_private;
+ BackendDB *be = op->o_bd;
+ slap_callback sc = { NULL, slap_null_cb, NULL, NULL };
+ struct berval dn, ndn, xdn, xndn;
+
+ op->o_bd = &cfb->cb_db;
+
+ /* Save current rootdn; use the underlying DB's rootdn */
+ dn = op->o_dn;
+ ndn = op->o_ndn;
+ xdn = op->o_req_dn;
+ xndn = op->o_req_ndn;
+ op->o_dn = op->o_bd->be_rootdn;
+ op->o_ndn = op->o_bd->be_rootndn;
+ op->o_req_dn = odn;
+ op->o_req_ndn = ondn;
+
+ sc.sc_next = op->o_callback;
+ op->o_callback = ≻
+ op->orr_newrdn = *newrdn;
+ op->orr_nnewrdn = *nnewrdn;
+ op->orr_deleteoldrdn = 1;
+ op->orr_modlist = NULL;
+ slap_modrdn2mods( op, rs );
+ rc = op->o_bd->be_modrdn( op, rs );
+ slap_mods_free( op->orr_modlist, 1 );
+
+ op->o_bd = be;
+ op->o_callback = sc.sc_next;
+ op->o_dn = dn;
+ op->o_ndn = ndn;
+ op->o_req_dn = xdn;
+ op->o_req_ndn = xndn;
+ }
+ free( odn.bv_val );
+ free( ondn.bv_val );
+ if ( e->e_private )
+ config_rename_kids( e->e_private );
+ return rc;
+}
+
+static int
+config_renumber_one( Operation *op, SlapReply *rs, CfEntryInfo *parent,
+ Entry *e, int idx, int tailindex, int use_ldif )
+{
+ struct berval ival, newrdn, nnewrdn;
+ struct berval rdn;
+ Attribute *a;
+ char ibuf[32], *ptr1, *ptr2 = NULL;
+ int rc = 0;
+
+ rc = config_rename_attr( rs, e, &rdn, &a );
+ if ( rc ) return rc;
+
+ ival.bv_val = ibuf;
+ ival.bv_len = snprintf( ibuf, sizeof( ibuf ), SLAP_X_ORDERED_FMT, idx );
+ if ( ival.bv_len >= sizeof( ibuf ) ) {
+ return LDAP_NAMING_VIOLATION;
+ }
+
+ newrdn.bv_len = rdn.bv_len + ival.bv_len;
+ newrdn.bv_val = ch_malloc( newrdn.bv_len+1 );
+
+ if ( tailindex ) {
+ ptr1 = lutil_strncopy( newrdn.bv_val, rdn.bv_val, rdn.bv_len );
+ ptr1 = lutil_strcopy( ptr1, ival.bv_val );
+ } else {
+ int xlen;
+ ptr2 = ber_bvchr( &rdn, '}' );
+ if ( ptr2 ) {
+ ptr2++;
+ } else {
+ ptr2 = rdn.bv_val + a->a_desc->ad_cname.bv_len + 1;
+ }
+ xlen = rdn.bv_len - (ptr2 - rdn.bv_val);
+ ptr1 = lutil_strncopy( newrdn.bv_val, a->a_desc->ad_cname.bv_val,
+ a->a_desc->ad_cname.bv_len );
+ *ptr1++ = '=';
+ ptr1 = lutil_strcopy( ptr1, ival.bv_val );
+ ptr1 = lutil_strncopy( ptr1, ptr2, xlen );
+ *ptr1 = '\0';
+ }
+
+ /* Do the equivalent of ModRDN */
+ /* Replace DN / NDN */
+ newrdn.bv_len = ptr1 - newrdn.bv_val;
+ rdnNormalize( 0, NULL, NULL, &newrdn, &nnewrdn, NULL );
+ rc = config_rename_one( op, rs, e, parent, a, &newrdn, &nnewrdn, use_ldif );
+
+ free( nnewrdn.bv_val );
+ free( newrdn.bv_val );
+ return rc;
+}
+