add support for ADD_IF_NOT_PRESENT and SOFTDEL internal modification types (ITS#6561)

This commit is contained in:
Pierangelo Masarati 2010-09-07 13:21:20 +00:00
parent 8a8daa383e
commit 79d4e4cf6a
10 changed files with 190 additions and 8 deletions

View File

@ -1985,8 +1985,15 @@ acl_check_modlist(
/* fall thru to check value to add */
case LDAP_MOD_ADD:
case SLAP_MOD_ADD_IF_NOT_PRESENT:
assert( mlist->sml_values != NULL );
if ( mlist->sml_op == SLAP_MOD_ADD_IF_NOT_PRESENT
&& attr_find( e->e_attrs, mlist->sml_desc ) )
{
break;
}
for ( bv = mlist->sml_nvalues
? mlist->sml_nvalues : mlist->sml_values;
bv->bv_val != NULL; bv++ )
@ -2003,6 +2010,7 @@ acl_check_modlist(
break;
case LDAP_MOD_DELETE:
case SLAP_MOD_SOFTDEL:
if ( mlist->sml_values == NULL ) {
if ( ! access_allowed( op, e,
mlist->sml_desc, NULL,

View File

@ -215,6 +215,56 @@ int bdb_modify_internal(
}
break;
case SLAP_MOD_SOFTDEL:
Debug(LDAP_DEBUG_ARGS,
"bdb_modify_internal: softdel %s\n",
mod->sm_desc->ad_cname.bv_val, 0, 0);
/* Avoid problems in index_delete_mods()
* We need to add index if necessary.
*/
mod->sm_op = LDAP_MOD_DELETE;
err = modify_delete_values( e, mod, get_permissiveModify(op),
text, textbuf, textlen );
mod->sm_op = SLAP_MOD_SOFTDEL;
if ( err == LDAP_TYPE_OR_VALUE_EXISTS ) {
err = LDAP_SUCCESS;
}
if( err != LDAP_SUCCESS ) {
Debug(LDAP_DEBUG_ARGS, "bdb_modify_internal: %d %s\n",
err, *text, 0);
}
break;
case SLAP_MOD_ADD_IF_NOT_PRESENT:
if ( attr_find( e->e_attrs, mod->sm_desc ) != NULL ) {
/* skip */
err = LDAP_SUCCESS;
break;
}
Debug(LDAP_DEBUG_ARGS,
"bdb_modify_internal: add_if_not_present %s\n",
mod->sm_desc->ad_cname.bv_val, 0, 0);
/* Avoid problems in index_add_mods()
* We need to add index if necessary.
*/
mod->sm_op = LDAP_MOD_ADD;
err = modify_add_values( e, mod, get_permissiveModify(op),
text, textbuf, textlen );
mod->sm_op = SLAP_MOD_ADD_IF_NOT_PRESENT;
if( err != LDAP_SUCCESS ) {
Debug(LDAP_DEBUG_ARGS, "bdb_modify_internal: %d %s\n",
err, *text, 0);
}
break;
default:
Debug(LDAP_DEBUG_ANY, "bdb_modify_internal: invalid op %d\n",
mod->sm_op, 0, 0);

View File

@ -1073,6 +1073,31 @@ apply_modify_to_entry(
rc = LDAP_SUCCESS;
}
break;
case SLAP_MOD_SOFTDEL:
mods->sm_op = LDAP_MOD_DELETE;
rc = modify_delete_values(entry, mods,
get_permissiveModify(op),
&rs->sr_text, textbuf,
sizeof( textbuf ) );
mods->sm_op = SLAP_MOD_SOFTDEL;
if (rc == LDAP_NO_SUCH_ATTRIBUTE) {
rc = LDAP_SUCCESS;
}
break;
case SLAP_MOD_ADD_IF_NOT_PRESENT:
if ( attr_find( entry->e_attrs, mods->sm_desc ) ) {
rc = LDAP_SUCCESS;
break;
}
mods->sm_op = LDAP_MOD_ADD;
rc = modify_add_values(entry, mods,
get_permissiveModify(op),
&rs->sr_text, textbuf,
sizeof( textbuf ) );
mods->sm_op = SLAP_MOD_ADD_IF_NOT_PRESENT;
break;
}
if(rc != LDAP_SUCCESS) break;
}

View File

@ -300,6 +300,49 @@ int ndb_modify_internal(
}
break;
case SLAP_MOD_SOFTDEL:
Debug(LDAP_DEBUG_ARGS,
"ndb_modify_internal: softdel %s\n",
mod->sm_desc->ad_cname.bv_val, 0, 0);
mod->sm_op = LDAP_MOD_DELETE;
rc = modify_delete_values( NA->e, mod, get_permissiveModify(op),
text, textbuf, textlen );
mod->sm_op = SLAP_MOD_SOFTDEL;
if ( rc == LDAP_NO_SUCH_ATTRIBUTE) {
rc = LDAP_SUCCESS;
}
if( rc != LDAP_SUCCESS ) {
Debug(LDAP_DEBUG_ARGS, "ndb_modify_internal: %d %s\n",
rc, *text, 0);
}
break;
case SLAP_MOD_ADD_IF_NOT_PRESENT:
Debug(LDAP_DEBUG_ARGS,
"ndb_modify_internal: add_if_not_present %s\n",
mod->sm_desc->ad_cname.bv_val, 0, 0);
if ( attr_find( NA->e->e_attrs, mod->sm_desc ) ) {
rc = LDAP_SUCCESS;
break;
}
mod->sm_op = LDAP_MOD_ADD;
rc = modify_add_values( NA->e, mod, get_permissiveModify(op),
text, textbuf, textlen );
mod->sm_op = SLAP_MOD_ADD_IF_NOT_PRESENT;
if( rc != LDAP_SUCCESS ) {
Debug(LDAP_DEBUG_ARGS, "ndb_modify_internal: %d %s\n",
rc, *text, 0);
}
break;
default:
Debug(LDAP_DEBUG_ANY, "ndb_modify_internal: invalid op %d\n",
mod->sm_op, 0, 0);

View File

@ -389,6 +389,7 @@ del_all:
*/
case LDAP_MOD_ADD:
/* case SLAP_MOD_SOFTADD: */
/* case SLAP_MOD_ADD_IF_NOT_PRESENT: */
add_only:;
if ( at->bam_add_proc == NULL ) {
Debug( LDAP_DEBUG_TRACE,
@ -541,6 +542,7 @@ add_only:;
break;
case LDAP_MOD_DELETE:
/* case SLAP_MOD_SOFTDEL: */
if ( at->bam_delete_proc == NULL ) {
Debug( LDAP_DEBUG_TRACE,
" backsql_modify_internal(): "

View File

@ -5562,7 +5562,9 @@ config_modify_internal( CfEntryInfo *ce, Operation *op, SlapReply *rs,
ct = config_find_table( colst, nocs, ml->sml_desc, ca );
switch (ml->sml_op) {
case LDAP_MOD_DELETE:
case LDAP_MOD_REPLACE: {
case LDAP_MOD_REPLACE:
case SLAP_MOD_SOFTDEL:
{
BerVarray vals = NULL, nvals = NULL;
int *idx = NULL;
if ( ct && ( ct->arg_type & ARG_NO_DELETE )) {
@ -5601,11 +5603,24 @@ config_modify_internal( CfEntryInfo *ce, Operation *op, SlapReply *rs,
ml->sml_values = vals;
ml->sml_nvalues = nvals;
}
if ( rc == LDAP_NO_SUCH_ATTRIBUTE && ml->sml_op == SLAP_MOD_SOFTDEL )
{
rc = LDAP_SUCCESS;
}
/* FIXME: check rc before fallthru? */
if ( !vals )
break;
}
}
/* FALLTHRU: LDAP_MOD_REPLACE && vals */
case SLAP_MOD_ADD_IF_NOT_PRESENT:
if ( ml->sml_op == SLAP_MOD_ADD_IF_NOT_PRESENT
&& attr_find( e->e_attrs, ml->sml_desc ) )
{
rc = LDAP_SUCCESS;
break;
}
case LDAP_MOD_ADD:
case SLAP_MOD_SOFTADD: {
int mop = ml->sml_op;

View File

@ -878,6 +878,7 @@ void slap_mods_opattrs(
for ( modtail = modsp; *modtail; modtail = &(*modtail)->sml_next ) {
if ( (*modtail)->sml_op != LDAP_MOD_ADD &&
(*modtail)->sml_op != SLAP_MOD_SOFTADD &&
(*modtail)->sml_op != SLAP_MOD_ADD_IF_NOT_PRESENT &&
(*modtail)->sml_op != LDAP_MOD_REPLACE )
{
continue;

View File

@ -1027,6 +1027,29 @@ constraint_update( Operation *op, SlapReply *rs )
}
break;
case SLAP_MOD_SOFTDEL:
mod->sm_op = LDAP_MOD_ADD;
err = modify_delete_values( target_entry_copy,
mod, get_permissiveModify(op),
&text, textbuf, textlen );
mod->sm_op = SLAP_MOD_SOFTDEL;
if ( err == LDAP_NO_SUCH_ATTRIBUTE ) {
err = LDAP_SUCCESS;
}
break;
case SLAP_MOD_ADD_IF_NOT_PRESENT:
if ( attr_find( target_entry_copy->e_attrs, mod->sm_desc ) ) {
err = LDAP_SUCCESS;
break;
}
mod->sm_op = LDAP_MOD_ADD;
err = modify_add_values( target_entry_copy,
mod, get_permissiveModify(op),
&text, textbuf, textlen );
mod->sm_op = SLAP_MOD_ADD_IF_NOT_PRESENT;
break;
default:
err = LDAP_OTHER;
break;

View File

@ -587,6 +587,7 @@ dds_op_modify( Operation *op, SlapReply *rs )
switch ( mod->sml_op ) {
case LDAP_MOD_DELETE:
case SLAP_MOD_SOFTDEL: /* FIXME? */
if ( mod->sml_values != NULL ) {
if ( BER_BVISEMPTY( &bv_entryTtl )
|| !bvmatch( &bv_entryTtl, &mod->sml_values[ 0 ] ) )
@ -611,8 +612,9 @@ dds_op_modify( Operation *op, SlapReply *rs )
entryTtl = -1;
/* fallthru */
case SLAP_MOD_SOFTADD: /* FIXME? */
case LDAP_MOD_ADD:
case SLAP_MOD_SOFTADD: /* FIXME? */
case SLAP_MOD_ADD_IF_NOT_PRESENT: /* FIXME? */
assert( mod->sml_values != NULL );
assert( BER_BVISNULL( &mod->sml_values[ 1 ] ) );

View File

@ -111,12 +111,25 @@ LDAP_BEGIN_DECL
# define SLAP_STRING_UNKNOWN "unknown"
#endif /* ! TCP Wrappers */
/* LDAPMod.mod_op value ===> Must be kept in sync with ldap.h!
* This is a value used internally by the backends. It is needed to allow
* adding values that already exist without getting an error as required by
* modrdn when the new rdn was already an attribute value itself.
/* LDAPMod.mod_op value ===> Must be kept in sync with ldap.h! */
/* These values are used internally by the backends. */
/* SLAP_MOD_SOFTADD allows adding values that already exist without getting
* an error as required by modrdn when the new rdn was already an attribute
* value itself.
*/
#define SLAP_MOD_SOFTADD 0x1000
/* SLAP_MOD_SOFTDEL allows deleting values if they exist without getting
* an error otherwise.
*/
#define SLAP_MOD_SOFTDEL 0x1001
/* SLAP_MOD_ADD_IF_NOT_PRESENT allows adding values unless the attribute
* is already present without getting an error.
*/
#define SLAP_MOD_ADD_IF_NOT_PRESENT 0x1002
/* SLAP_MOD_DEL_IF_PRESENT allows deleting values if the attribute
* is present, without getting an error otherwise.
* The semantics can be obtained using SLAP_MOD_SOFTDEL with NULL values.
*/
#define SLAP_MOD_SOFTADD 0x1000
#define MAXREMATCHES (100)