/* 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++ )
break;
case LDAP_MOD_DELETE:
+ case SLAP_MOD_SOFTDEL:
if ( mlist->sml_values == NULL ) {
if ( ! access_allowed( op, e,
mlist->sml_desc, NULL,
}
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);
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;
}
}
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);
*/
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,
break;
case LDAP_MOD_DELETE:
+ /* case SLAP_MOD_SOFTDEL: */
if ( at->bam_delete_proc == NULL ) {
Debug( LDAP_DEBUG_TRACE,
" backsql_modify_internal(): "
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 )) {
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;
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;
}
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;
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 ] ) )
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 ] ) );
# 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)