+ /* Drop the RDN-related mods from this op, because their
+ * equivalents were just setup by slap_modrdn2mods.
+ *
+ * If delOldRDN is TRUE then we should see a delete modop
+ * for oldDesc. We might see a replace instead.
+ * delete with no values: therefore newDesc != oldDesc.
+ * if oldNattr had only one value, then Drop this op.
+ * delete with 1 value: can only be the oldRDN value. Drop op.
+ * delete with N values: Drop oldRDN value, keep remainder.
+ * replace with 1 value: if oldNattr had only one value and
+ * newDesc == oldDesc, Drop this op.
+ * Any other cases must be left intact.
+ *
+ * We should also see an add modop for newDesc. (But not if
+ * we got a replace modop due to delOldRDN.) If it has
+ * multiple values, we'll have to drop the new RDN value.
+ */
+ modtail = &op->orr_modlist;
+ if ( dni.delOldRDN ) {
+ for ( ml = &dni.mods; *ml; ml = &(*ml)->sml_next ) {
+ if ( (*ml)->sml_desc == dni.oldDesc ) {
+ mod = *ml;
+ if ( mod->sml_op == LDAP_MOD_REPLACE &&
+ dni.oldDesc != dni.newDesc ) {
+ /* This Replace is due to other Mods.
+ * Just let it ride.
+ */
+ continue;
+ }
+ if ( mod->sml_numvals <= 1 &&
+ dni.oldNattr->a_numvals == 1 &&
+ ( mod->sml_op == LDAP_MOD_DELETE ||
+ mod->sml_op == LDAP_MOD_REPLACE )) {
+ if ( mod->sml_op == LDAP_MOD_REPLACE )
+ got_replace = 1;
+ /* Drop this op */
+ *ml = mod->sml_next;
+ mod->sml_next = NULL;
+ slap_mods_free( mod, 1 );
+ break;
+ }
+ if ( mod->sml_op != LDAP_MOD_DELETE || mod->sml_numvals == 0 )
+ continue;
+ for ( m2 = op->orr_modlist; m2; m2=m2->sml_next ) {
+ if ( m2->sml_desc == dni.oldDesc &&
+ m2->sml_op == LDAP_MOD_DELETE ) break;
+ }
+ for ( i=0; i<mod->sml_numvals; i++ ) {
+ if ( bvmatch( &mod->sml_values[i], &m2->sml_values[0] )) {
+ mod->sml_numvals--;
+ ch_free( mod->sml_values[i].bv_val );
+ mod->sml_values[i] = mod->sml_values[mod->sml_numvals];
+ BER_BVZERO( &mod->sml_values[mod->sml_numvals] );
+ if ( mod->sml_nvalues ) {
+ ch_free( mod->sml_nvalues[i].bv_val );
+ mod->sml_nvalues[i] = mod->sml_nvalues[mod->sml_numvals];
+ BER_BVZERO( &mod->sml_nvalues[mod->sml_numvals] );
+ }
+ break;
+ }
+ }
+ if ( !mod->sml_numvals ) {
+ /* Drop this op */
+ *ml = mod->sml_next;
+ mod->sml_next = NULL;
+ slap_mods_free( mod, 1 );
+ }
+ break;
+ }
+ }
+ }
+ if ( !got_replace ) {
+ for ( ml = &dni.mods; *ml; ml = &(*ml)->sml_next ) {
+ if ( (*ml)->sml_desc == dni.newDesc ) {
+ mod = *ml;
+ if ( mod->sml_op != LDAP_MOD_ADD )
+ continue;
+ if ( mod->sml_numvals == 1 ) {
+ /* Drop this op */
+ *ml = mod->sml_next;
+ mod->sml_next = NULL;
+ slap_mods_free( mod, 1 );
+ break;
+ }
+ for ( m2 = op->orr_modlist; m2; m2=m2->sml_next ) {
+ if ( m2->sml_desc == dni.oldDesc &&
+ m2->sml_op == SLAP_MOD_SOFTADD ) break;
+ }
+ for ( i=0; i<mod->sml_numvals; i++ ) {
+ if ( bvmatch( &mod->sml_values[i], &m2->sml_values[0] )) {
+ mod->sml_numvals--;
+ ch_free( mod->sml_values[i].bv_val );
+ mod->sml_values[i] = mod->sml_values[mod->sml_numvals];
+ BER_BVZERO( &mod->sml_values[mod->sml_numvals] );
+ if ( mod->sml_nvalues ) {
+ ch_free( mod->sml_nvalues[i].bv_val );
+ mod->sml_nvalues[i] = mod->sml_nvalues[mod->sml_numvals];
+ BER_BVZERO( &mod->sml_nvalues[mod->sml_numvals] );
+ }
+ break;
+ }
+ }
+ break;
+ }
+ }
+ }
+