global SLAPI plugins) have access to op->ora_e.
Note that slap_mods2entry() is still called in fe_op_add() in order to
add any operational attributes.
/* temporary; remove if not invoking backend function */
op->ora_modlist = modlist;
+ /* call this so global overlays/SLAPI have access to ora_e */
+ rs->sr_err = slap_mods2entry( op->ora_modlist, &op->ora_e,
+ 1, 0, &rs->sr_text, textbuf, textlen );
+ if ( rs->sr_err != LDAP_SUCCESS ) {
+ send_ldap_result( op, rs );
+ goto done;
+ }
+
op->o_bd = frontendDB;
rc = frontendDB->be_add( op, rs );
if ( rc == 0 ) {
assert( (*modtail)->sml_desc != NULL );
}
+
rs->sr_err = slap_mods_opattrs( op, modlist,
modtail, &rs->sr_text,
textbuf, textlen, 1 );
send_ldap_result( op, rs );
goto done;
}
- }
- rs->sr_err = slap_mods2entry( modlist, &op->ora_e,
- repl_user, 0, &rs->sr_text, textbuf, textlen );
- if ( rs->sr_err != LDAP_SUCCESS ) {
- send_ldap_result( op, rs );
- goto done;
+ /* check for duplicate values */
+ rs->sr_err = slap_mods_no_repl_user_mod_check( op,
+ modlist, &rs->sr_text, textbuf, textlen );
+ if ( rs->sr_err != LDAP_SUCCESS ) {
+ send_ldap_result( op, rs );
+ goto done;
+ }
+
+ rs->sr_err = slap_mods2entry( *modtail, &op->ora_e,
+ 0, 0, &rs->sr_text, textbuf, textlen );
+ if ( rs->sr_err != LDAP_SUCCESS ) {
+ send_ldap_result( op, rs );
+ goto done;
+ }
}
#ifdef SLAPD_MULTIMASTER
slap_mods2entry(
Modifications *mods,
Entry **e,
- int repl_user,
+ int initial,
int dup,
const char **text,
char *textbuf, size_t textlen )
{
Attribute **tail = &(*e)->e_attrs;
- assert( *tail == NULL );
+
+ if ( initial ) {
+ assert( *tail == NULL );
+ }
*text = textbuf;
for( ; mods != NULL; mods = mods->sml_next ) {
Attribute *attr;
- if ( !repl_user ) {
- assert( mods->sml_op == LDAP_MOD_ADD );
- }
assert( mods->sml_desc != NULL );
attr = attr_find( (*e)->e_attrs, mods->sml_desc );
#ifdef SLURPD_FRIENDLY
ber_len_t i,j;
- if( !repl_user ) {
- snprintf( textbuf, textlen,
- "attribute '%s' provided more than once",
- mods->sml_desc->ad_cname.bv_val );
- return LDAP_TYPE_OR_VALUE_EXISTS;
- }
-
for( i=0; attr->a_vals[i].bv_val; i++ ) {
/* count them */
}
}
break;
case LDAP_REQ_ADD:
- {
- int cleanup_attrs = 0;
-
- if ( op->ora_e->e_attrs == NULL ) {
- char textbuf[ SLAP_TEXT_BUFLEN ];
- size_t textlen = sizeof( textbuf );
-
-#if 0
- /* FIXME: op->o_bd is still set to the BackendDB
- * structure of the database that tried to handle
- * the operation and actually returned a referral
- * ... */
- assert( SLAP_DBFLAGS( op->o_bd ) & SLAP_DBFLAG_GLOBAL_OVERLAY );
-#endif
-
- /* global overlay: create entry */
- /* NOTE: this is a hack to use the chain overlay
- * as global. I expect to be able to remove this
- * soon by using slap_mods2entry() earlier in
- * do_add(), adding the operational attrs later
- * if required. */
- rs->sr_err = slap_mods2entry( op->ora_modlist,
- &op->ora_e, 0, 1,
- &rs->sr_text, textbuf, textlen );
- if ( rs->sr_err != LDAP_SUCCESS ) {
- send_ldap_result( op, rs );
- rc = 1;
- break;
- }
- }
+ /* slap_mods2entry () should be called in do_add() */
+ assert( op->ora_e->e_attrs != NULL );
rc = ldap_chain_op( op, rs, lback->bi_op_add, ref );
- if ( cleanup_attrs ) {
- attrs_free( op->ora_e->e_attrs );
- op->ora_e->e_attrs = NULL;
- }
break;
- }
case LDAP_REQ_DELETE:
rc = ldap_chain_op( op, rs, lback->bi_op_delete, ref );
break;
return LDAP_SUCCESS;
}
+int
+slap_mods_no_repl_user_mod_check(
+ Operation *op,
+ Modifications *ml,
+ const char **text,
+ char *textbuf,
+ size_t textlen )
+{
+ Modifications *mods;
+ Modifications *modp;
+
+ for ( mods = ml; mods != NULL; mods = mods->sml_next ) {
+ assert( mods->sml_op == LDAP_MOD_ADD );
+
+ /* check doesn't already appear */
+ for ( modp = ml; modp != NULL; modp = modp->sml_next ) {
+ if ( mods->sml_desc == modp->sml_desc ) {
+ snprintf( textbuf, textlen,
+ "attribute '%s' provided more than once",
+ mods->sml_desc->ad_cname.bv_val );
+ return LDAP_TYPE_OR_VALUE_EXISTS;
+ }
+ }
+ }
+
+ return LDAP_SUCCESS;
+}
+
/*
* Do basic attribute type checking and syntax validation.
*/
* add.c
*/
LDAP_SLAPD_F (int) slap_mods2entry LDAP_P(( Modifications *mods, Entry **e,
- int repl_user, int dup, const char **text, char *textbuf, size_t textlen ));
+ int initial, int dup, const char **text, char *textbuf, size_t textlen ));
LDAP_SLAPD_F (int) slap_entry2mods LDAP_P(( Entry *e,
Modifications **mods, const char **text,
const char **text,
char *textbuf, size_t textlen );
+LDAP_SLAPD_F ( int ) slap_mods_no_repl_user_mod_check(
+ Operation *op,
+ Modifications *ml,
+ const char **text,
+ char *textbuf,
+ size_t textlen );
+
LDAP_SLAPD_F( int ) slap_mods_check(
Modifications *ml,
const char **text,
/* slapi_utils.c */
LDAP_SLAPI_F (LDAPMod **) slapi_int_modifications2ldapmods LDAP_P(( Modifications **, void *ctx ));
-LDAP_SLAPI_F (Modifications *) slapi_int_ldapmods2modifications LDAP_P(( LDAPMod **, void *ctx ));
+LDAP_SLAPI_F (Modifications *) slapi_int_ldapmods2modifications LDAP_P(( LDAPMod **, int dup, void *ctx ));
LDAP_SLAPI_F (void) slapi_int_free_ldapmods LDAP_P(( LDAPMod ** ));
LDAP_SLAPI_F (int) slapi_int_count_controls LDAP_P(( LDAPControl **ctrls ));
LDAP_SLAPI_F (char **) slapi_get_supported_extended_ops LDAP_P((void));
if ( BER_BVISNULL( &op->o_ndn ) ) {
/* set to root DN */
- be = select_backend( &op->o_req_ndn, 0, 0 );
+ be = select_backend( &op->o_req_ndn, get_manageDSAit( op ), 1 );
if ( be != NULL ) {
ber_dupbv( &op->o_dn, &be->be_rootdn );
ber_dupbv( &op->o_ndn, &be->be_rootndn );
}
break;
case LDAP_REQ_ADD:
- slapi_int_mods_free( op->ora_modlist );
+ slap_mods_free( op->ora_modlist );
break;
case LDAP_REQ_MODIFY:
- slapi_int_mods_free( op->orm_modlist );
+ slap_mods_free( op->orm_modlist );
break;
case LDAP_REQ_SEARCH:
if ( op->ors_attrs != NULL ) {
entry_orig = pb->pb_op->ora_e;
pb->pb_op->ora_e = NULL;
+ /*
+ * The caller can specify a new entry, or a target DN and set
+ * of modifications, but not both.
+ */
if ( entry_orig != NULL ) {
if ( pb->pb_op->ora_modlist != NULL || !BER_BVISNULL( &pb->pb_op->o_req_ndn )) {
rs->sr_err = LDAP_PARAM_ERROR;
goto cleanup;
}
- /*
- * The caller can specify a new entry, or a target DN and set
- * of modifications, but not both.
- */
pb->pb_op->ora_e = (Entry *)slapi_ch_calloc( 1, sizeof(Entry) );
ber_dupbv( &pb->pb_op->ora_e->e_name, &pb->pb_op->o_req_dn );
ber_dupbv( &pb->pb_op->ora_e->e_nname, &pb->pb_op->o_req_ndn );
goto cleanup;
}
+ /* Duplicate the values, because we may call slapi_entry_free() */
+ rs->sr_err = slap_mods2entry( pb->pb_op->ora_modlist, &pb->pb_op->ora_e,
+ 1, 1, &rs->sr_text, pb->pb_textbuf, sizeof( pb->pb_textbuf ) );
+ if ( rs->sr_err != LDAP_SUCCESS ) {
+ goto cleanup;
+ }
+
if ( slapi_int_func_internal_pb( pb, op_add ) == 0 ) {
if ( pb->pb_op->ora_e != NULL && pb->pb_op->o_private != NULL ) {
BackendDB *bd = pb->pb_op->o_bd;
- /* could we use SLAPI_BACKEND instead? */
pb->pb_op->o_bd = (BackendDB *)pb->pb_op->o_private;
pb->pb_op->o_private = NULL;
be_entry_release_w( pb->pb_op, pb->pb_op->ora_e );
}
if ( entry_orig != NULL ) {
pb->pb_op->ora_e = entry_orig;
- slapi_int_mods_free( pb->pb_op->ora_modlist );
+ slap_mods_free( pb->pb_op->ora_modlist );
pb->pb_op->ora_modlist = NULL;
}
break;
case SLAPI_ADD_ENTRY:
PBLOCK_ASSERT_OP( pb, 0 );
- if ( pb->pb_op->o_tag == LDAP_REQ_ADD ) {
+ if ( pb->pb_op->o_tag == LDAP_REQ_ADD )
pb->pb_op->ora_e = (Slapi_Entry *)value;
- } else {
+ else
rc = PBLOCK_ERROR;
- }
break;
case SLAPI_MODIFY_MODS: {
Modifications **mlp;
slapi_int_mods_free( *mlp );
*mlp = NULL;
}
- *mlp = slapi_int_ldapmods2modifications( (LDAPMod **)value, NULL );
+ /*
+ * Note: for internal operations, the modifications need to be
+ * duplicated because slap_mods_check() will free values before
+ * prettying, and we have no idea how the values were
+ * allocated. For frontend operations, slap_mods_check() will
+ * have already been called.
+ */
+ *mlp = slapi_int_ldapmods2modifications( (LDAPMod **)value, pb->pb_intop, NULL );
break;
}
case SLAPI_MODRDN_NEWRDN:
if ( pb == NULL || pb->pb_op == NULL )
return LDAP_PARAM_ERROR;
- ml = slapi_int_ldapmods2modifications( mods, NULL );
+ ml = slapi_int_ldapmods2modifications( mods, 0, NULL );
if ( ml == NULL ) {
return LDAP_OTHER;
}
* LDAPMods array; the latter MUST be freed with
* slapi_int_free_ldapmods() (see below).
*/
-Modifications *slapi_int_ldapmods2modifications ( LDAPMod **mods, void *memctx )
+Modifications *slapi_int_ldapmods2modifications ( LDAPMod **mods, int dup, void *memctx )
{
Modifications *modlist = NULL, **modtail;
LDAPMod **modp;
/* NB: This implicitly trusts a plugin to return valid modifications. */
if ( lmod->mod_op & LDAP_MOD_BVALUES ) {
for ( i = 0; lmod->mod_bvalues[i] != NULL; i++ ) {
- mod->sml_values[i].bv_val = lmod->mod_bvalues[i]->bv_val;
- mod->sml_values[i].bv_len = lmod->mod_bvalues[i]->bv_len;
+ if ( dup ) {
+ ber_dupbv( &mod->sml_values[i], lmod->mod_bvalues[i] );
+ } else {
+ mod->sml_values[i].bv_val = lmod->mod_bvalues[i]->bv_val;
+ mod->sml_values[i].bv_len = lmod->mod_bvalues[i]->bv_len;
+ }
}
} else {
for ( i = 0; lmod->mod_values[i] != NULL; i++ ) {
- mod->sml_values[i].bv_val = lmod->mod_values[i];
+ mod->sml_values[i].bv_val = dup ? slapi_ch_strdup( lmod->mod_values[i] ) :
+ lmod->mod_values[i];
mod->sml_values[i].bv_len = strlen( lmod->mod_values[i] );
}
}
/*
* This function only frees the parts of the mods array that
* are not shared with the Modification list that was created
- * by slapi_int_ldapmods2modifications().
+ * by slapi_int_ldapmods2modifications() (if dup == 0).
*/
void
slapi_int_free_ldapmods ( LDAPMod **mods )