]> git.sur5r.net Git - openldap/blobdiff - servers/slapd/modify.c
fix RID format
[openldap] / servers / slapd / modify.c
index 27e746050ad1cf046c714cf533450c3c337b8439..f84026220864d369fd6276fadf76659b3f2e2736 100644 (file)
@@ -171,7 +171,6 @@ do_modify(
 
        if( get_ctrls( op, rs, 1 ) != LDAP_SUCCESS ) {
                Debug( LDAP_DEBUG_ANY, "do_modify: get_ctrls failed\n", 0, 0, 0 );
-
                goto cleanup;
        }
 
@@ -184,7 +183,7 @@ do_modify(
                goto cleanup;
        }
 
-       rs->sr_err = slap_mods_check( modlist,
+       rs->sr_err = slap_mods_check( op, modlist,
                &rs->sr_text, textbuf, textlen, NULL );
 
        if ( rs->sr_err != LDAP_SUCCESS ) {
@@ -199,6 +198,13 @@ do_modify(
        op->o_bd = frontendDB;
        rs->sr_err = frontendDB->be_modify( op, rs );
 
+#ifdef LDAP_X_TXN
+       if( rs->sr_err == LDAP_X_TXN_SPECIFY_OKAY ) {
+               /* skip cleanup */
+               return rs->sr_err;
+       }
+#endif
+
 cleanup:
        op->o_tmpfree( op->o_req_dn.bv_val, op->o_tmpmemctx );
        op->o_tmpfree( op->o_req_ndn.bv_val, op->o_tmpmemctx );
@@ -270,7 +276,7 @@ fe_op_modify( Operation *op, SlapReply *rs )
                                Statslog( LDAP_DEBUG_STATS, "%s MOD attr=%s\n",
                                    op->o_log_prefix, abuf, 0, 0, 0 );
 
-                               len = 0;
+                               len = 0;
                                ptr = abuf;
 
                                if( 1 + tmp->sml_type.bv_len > sizeof(abuf)) {
@@ -364,13 +370,13 @@ fe_op_modify( Operation *op, SlapReply *rs )
                /* do the update here */
                int repl_user = be_isupdate( op );
 
-               /* Multimaster slapd does not have to check for replicator dn
+               /*
+                * Multimaster slapd does not have to check for replicator dn
                 * because it accepts each modify request
                 */
-               if ( !SLAP_SINGLE_SHADOW(op->o_bd) || repl_user )
-               {
-                       int             update = !BER_BVISEMPTY( &op->o_bd->be_update_ndn );
-                       slap_callback   cb = { NULL, slap_replog_cb, NULL, NULL };
+               if ( !SLAP_SINGLE_SHADOW(op->o_bd) || repl_user ) {
+                       int update = !BER_BVISEMPTY( &op->o_bd->be_update_ndn );
+                       slap_callback cb = { NULL, slap_replog_cb, NULL, NULL };
 
                        op->o_bd = op_be;
 
@@ -383,8 +389,7 @@ fe_op_modify( Operation *op, SlapReply *rs )
                                }
                        }
 
-                       if ( !repl_user )
-                       {
+                       if ( !repl_user ) {
                                /* but multimaster slapd logs only the ones 
                                 * not from a replicator user */
                                cb.sc_next = op->o_callback;
@@ -392,8 +397,7 @@ fe_op_modify( Operation *op, SlapReply *rs )
                        }
                        op->o_bd->be_modify( op, rs );
 
-               /* send a referral */
-               } else {
+               } else { /* send a referral */
                        BerVarray defref = op->o_bd->be_update_refs
                                ? op->o_bd->be_update_refs : default_referral;
                        if ( defref != NULL ) {
@@ -416,6 +420,7 @@ fe_op_modify( Operation *op, SlapReply *rs )
                                        "shadow context; no update referral" );
                        }
                }
+
        } else {
                send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
                    "operation not supported within namingContext" );
@@ -437,7 +442,7 @@ slap_mods_obsolete_check(
        char *textbuf,
        size_t textlen )
 {
-       if( get_manageDIT( op ) ) return LDAP_SUCCESS;
+       if( get_relax( op ) ) return LDAP_SUCCESS;
 
        for ( ; ml != NULL; ml = ml->sml_next ) {
                if ( is_at_obsolete( ml->sml_desc->ad_type ) &&
@@ -476,7 +481,7 @@ slap_mods_no_user_mod_check(
                        continue;
                }
 
-               if ( get_manageDIT( op ) ) {
+               if ( get_relax( op ) ) {
                        if ( ml->sml_desc->ad_type->sat_flags & SLAP_AT_MANAGEABLE ) {
                                ml->sml_flags |= SLAP_MOD_MANAGING;
                                continue;
@@ -534,6 +539,7 @@ slap_mods_no_repl_user_mod_check(
  * Do basic attribute type checking and syntax validation.
  */
 int slap_mods_check(
+       Operation *op,
        Modifications *ml,
        const char **text,
        char *textbuf,
@@ -548,6 +554,12 @@ int slap_mods_check(
                /* convert to attribute description */
                if ( ml->sml_desc == NULL ) {
                        rc = slap_bv2ad( &ml->sml_type, &ml->sml_desc, text );
+                       if( rc != LDAP_SUCCESS ) {
+                               if ( get_no_schema_check( op )) {
+                                       rc = slap_bv2undef_ad( &ml->sml_type, &ml->sml_desc,
+                                               text, 0 );
+                               }
+                       }
                        if( rc != LDAP_SUCCESS ) {
                                snprintf( textbuf, textlen, "%s: %s",
                                        ml->sml_type.bv_val, *text );
@@ -651,21 +663,11 @@ int slap_mods_check(
                                struct berval pval;
 
                                if ( pretty ) {
-#ifdef SLAP_ORDERED_PRETTYNORM
                                        rc = ordered_value_pretty( ad,
                                                &ml->sml_values[nvals], &pval, ctx );
-#else /* ! SLAP_ORDERED_PRETTYNORM */
-                                       rc = pretty( ad->ad_type->sat_syntax,
-                                               &ml->sml_values[nvals], &pval, ctx );
-#endif /* ! SLAP_ORDERED_PRETTYNORM */
                                } else {
-#ifdef SLAP_ORDERED_PRETTYNORM
                                        rc = ordered_value_validate( ad,
                                                &ml->sml_values[nvals], ml->sml_op );
-#else /* ! SLAP_ORDERED_PRETTYNORM */
-                                       rc = validate( ad->ad_type->sat_syntax,
-                                               &ml->sml_values[nvals] );
-#endif /* ! SLAP_ORDERED_PRETTYNORM */
                                }
 
                                if( rc != 0 ) {
@@ -711,19 +713,11 @@ int slap_mods_check(
                                        (nvals+1)*sizeof(struct berval), ctx );
 
                                for ( nvals = 0; !BER_BVISNULL( &ml->sml_values[nvals] ); nvals++ ) {
-#ifdef SLAP_ORDERED_PRETTYNORM
                                        rc = ordered_value_normalize(
                                                SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX,
                                                ad,
                                                ad->ad_type->sat_equality,
                                                &ml->sml_values[nvals], &ml->sml_nvalues[nvals], ctx );
-#else /* ! SLAP_ORDERED_PRETTYNORM */
-                                       rc = ad->ad_type->sat_equality->smr_normalize(
-                                               SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX,
-                                               ad->ad_type->sat_syntax,
-                                               ad->ad_type->sat_equality,
-                                               &ml->sml_values[nvals], &ml->sml_nvalues[nvals], ctx );
-#endif /* ! SLAP_ORDERED_PRETTYNORM */
                                        if ( rc ) {
                                                Debug( LDAP_DEBUG_ANY,
                                                        "<= str2entry NULL (ssyn_normalize %d)\n",
@@ -742,6 +736,8 @@ int slap_mods_check(
                        /* check for duplicates, but ignore Deletes.
                         */
                        if( nvals > 1 && ml->sml_op != LDAP_MOD_DELETE ) {
+#define        SLAP_MODS_CHECK_QUICKSORT
+#ifndef SLAP_MODS_CHECK_QUICKSORT
                                int             i, j, rc, match;
                                MatchingRule *mr = ad->ad_type->sat_equality;
 
@@ -773,8 +769,164 @@ int slap_mods_check(
                                                }
                                        }
                                }
+#else  /* SLAP_MODS_CHECK_QUICKSORT */
+
+/* Quicksort + Insertion sort for small arrays */
+
+#define SMALL  8
+#define        SWAP(a,b,tmp)   tmp=(a);(a)=(b);(b)=tmp
+#define        COMP(a,b)       match=0; rc = ordered_value_match( &match, \
+                                               ml->sml_desc, mr, SLAP_MR_EQUALITY \
+                                                               | SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX \
+                                                               | SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH \
+                                                               | SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH, \
+                                                               &(a), &(b), text );
+
+                                       MatchingRule *mr = ad->ad_type->sat_equality;
+                                       int istack[sizeof(int)*16];
+                                       int i,j,k,l,ir,jstack, rc, match, *ix, itmp;
+                                       struct berval a, *cv;
+
+/* If PRESERVE_ORDER is defined only the index array is sorted; the
+ * actual values are left in their incoming order. Otherwise, the
+ * only reason to keep the index array is to identify the offending
+ * value when duplicates are found.
+ */
+#define        PRESERVE_ORDER
+#ifndef PRESERVE_ORDER
+                                       struct berval va, *v, *nv, bvtmp;
+
+#define        IX(x)   x
+#define        EXCH(x,y)       SWAP(ix[x],ix[y],itmp); SWAP(cv[x],cv[y],bvtmp); \
+       if (nv) {SWAP(v[x],v[y],bvtmp);}
+#define        SETA(x) itmp = ix[x]; a = cv[x]; if (nv) va=v[x]
+#define        GETA(x) ix[x] = itmp; cv[x] = a; if (nv) v[x]=va
+#define        SET(x,y)        ix[x] = ix[y]; cv[x] = cv[y]; if (nv) v[x]=v[y]
+
+                                       v = ml->sml_values;
+                                       nv = ml->sml_nvalues;
+
+#else  /* PRESERVE_ORDER */
+
+#define        IX(x)   ix[x]
+#define        EXCH(x,y)       SWAP(ix[x],ix[y],itmp)
+#define        SETA(x) itmp = ix[x]; a = cv[itmp]
+#define        GETA(x) ix[x] = itmp;
+#define        SET(x,y)        ix[x] = ix[y]
+
+#endif /* PRESERVE_ORDER */
+
+                                       cv = ml->sml_nvalues ? ml->sml_nvalues : ml->sml_values;
+                                       if ( ad == slap_schema.si_ad_objectClass )
+                                               mr = NULL;      /* shortcut matching */
+
+                                       /* record indices to preserve input ordering */
+                                       ix = slap_sl_malloc( nvals * sizeof(int), ctx );
+                                       for (i=0; i<nvals; i++) ix[i] = i;
+
+                                       ir = nvals-1;
+                                       l = 0;
+                                       jstack = 0;
+
+                                       for(;;) {
+                                               if (ir - l < SMALL) {   /* Insertion sort */
+                                                       match=1;
+                                                       for (j=l+1;j<=ir;j++) {
+                                                               SETA(j);
+                                                               for (i=j-1;i>=0;i--) {
+                                                                       COMP(cv[IX(i)], a);
+                                                                       if ( match <= 0 )
+                                                                               break;
+                                                                       SET(i+1,i);
+                                                               }
+                                                               GETA(i+1);
+                                                               if ( match == 0 ) goto done;
+                                                       }
+                                                       if ( jstack == 0 ) break;
+                                                       if ( match == 0 ) break;
+                                                       ir = istack[jstack--];
+                                                       l = istack[jstack--];
+                                               } else {
+                                                       k = (l + ir) >> 1;      /* Choose median of left, center, right */
+                                                       EXCH(k, l+1);
+                                                       COMP( cv[IX(l)], cv[IX(ir)] );
+                                                       if ( match > 0 ) {
+                                                               EXCH(l, ir);
+                                                       } else if ( match == 0 ) {
+                                                               i = ir;
+                                                               break;
+                                                       }
+                                                       COMP( cv[IX(l+1)], cv[IX(ir)] );
+                                                       if ( match > 0 ) {
+                                                               EXCH(l+1, ir);
+                                                       } else if ( match == 0 ) {
+                                                               i = ir;
+                                                               break;
+                                                       }
+                                                       COMP( cv[IX(l)], cv[IX(l+1)] );
+                                                       if ( match > 0 ) {
+                                                               EXCH(l, l+1);
+                                                       } else if ( match == 0 ) {
+                                                               i = l;
+                                                               break;
+                                                       }
+                                                       i = l+1;
+                                                       j = ir;
+                                                       a = cv[IX(i)];
+                                                       for(;;) {
+                                                               do {
+                                                                       i++;
+                                                                       COMP( cv[IX(i)], a );
+                                                               } while( match < 0 );
+                                                               while( match > 0 ) {
+                                                                       j--;
+                                                                       COMP( cv[IX(j)], a );
+                                                               }
+                                                               if (j < i) {
+                                                                       match = 1;
+                                                                       break;
+                                                               }
+                                                               if ( match == 0 ) {
+                                                                       i = l+1;
+                                                                       break;
+                                                               }
+                                                               EXCH(i,j);
+                                                       }
+                                                       if ( match == 0 )
+                                                               break;
+                                                       EXCH(l+1,j);
+                                                       jstack += 2;
+                                                       if (ir-i+1 >= j) {
+                                                               istack[jstack] = ir;
+                                                               istack[jstack-1] = i;
+                                                               ir = j;
+                                                       } else {
+                                                               istack[jstack] = j;
+                                                               istack[jstack-1] = l;
+                                                               l = i;
+                                               }
+                                       }
+                               }
+done:
+                               if ( i >= 0 )
+                                       j = ix[i];
+
+                               slap_sl_free( ix, ctx );
+
+                               if ( rc != LDAP_SUCCESS ) {
+                                       return rc;
+                               } else if ( match == 0 ) {
+                                       /* value exists already */
+                                       assert( i >= 0 );
+                                       assert( i < nvals );
+                                       snprintf( textbuf, textlen,
+                                               "%s: value #%d provided more than once",
+                                               ml->sml_desc->ad_cname.bv_val, j );
+                                       *text = textbuf;
+                                       return LDAP_TYPE_OR_VALUE_EXISTS;
+                               }
+#endif /* SLAP_MODS_CHECK_QUICKSORT */
                        }
-
                }
        }