]> git.sur5r.net Git - openldap/commitdiff
add support for ADD_IF_NOT_PRESENT and SOFTDEL internal modification types (ITS#6561)
authorPierangelo Masarati <ando@openldap.org>
Tue, 7 Sep 2010 13:21:20 +0000 (13:21 +0000)
committerPierangelo Masarati <ando@openldap.org>
Tue, 7 Sep 2010 13:21:20 +0000 (13:21 +0000)
servers/slapd/acl.c
servers/slapd/back-bdb/modify.c
servers/slapd/back-ldif/ldif.c
servers/slapd/back-ndb/modify.cpp
servers/slapd/back-sql/add.c
servers/slapd/bconfig.c
servers/slapd/modify.c
servers/slapd/overlays/constraint.c
servers/slapd/overlays/dds.c
servers/slapd/slap.h

index a1d52492b667eb9d637da0b55152b1b81bf0d5f0..476b9e667b1cc7d99c24a030c7cad196a8415883 100644 (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,
index 5db7aa984770e7676323c9b22fa9ca4be44f0a95..7bd80ea4f405f6f931ad56eb01870be9cd814ab8 100644 (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);
index 671550919b578513d6ccb31059889af965cfa632..a3f13b1365cff31cd7dd4ed2b88ae4b29d56eac8 100644 (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;
        }
index 274bc093f230ecf86b3d0a39979ae3e73f9b5a0d..73bb9f755cd1a3b5975956eb991d418b6d2b7601 100644 (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);
index 94d00732fe1691285586fa16eeb44912517c40e6..9c162e926af9aa61e4fa009d99e10e7c828b56c3 100644 (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(): "
index d08e3c98c8f4993e23b25e0ad8264ba52dd22219..de159d96e98faf86980623fe56c38909c807df61 100644 (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;
index 3b5f7271a0b118d903e88bfa6152eab5d55fca72..8898a8eebddcd91878b72ed3eca9db36f4a19805 100644 (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;
index ec640d9dad044dfdcf8e02caf43adbf3eceb879e..dc6039de436dcfe0ab810f8c9a4d50e8126bcc84 100644 (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;
index c0bbc40d84bff915d79dac946507b59d73c2bc12..450ba78b20d918551609b6ff1679d575e6b70312 100644 (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 ] ) );
 
index a4bf1e9bc23d8d4c1af4535c179ac92917611d7a..6b3d901937c6f0a038976fec6aee87aa66e7cdb0 100644 (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)