mirror of
https://git.openldap.org/openldap/openldap.git
synced 2024-12-21 03:10:25 +08:00
Preliminary sorted value support
This commit is contained in:
parent
ebb9e029a7
commit
e8c2414831
@ -490,6 +490,9 @@ slap_mods2entry(
|
||||
} else {
|
||||
attr->a_nvals = attr->a_vals;
|
||||
}
|
||||
/* slap_mods_check() gives us sorted results */
|
||||
if ( attr->a_desc->ad_type->sat_flags & SLAP_AT_SORTED_VAL )
|
||||
attr->a_flags |= SLAP_ATTR_SORTED_VALS;
|
||||
|
||||
*tail = attr;
|
||||
tail = &attr->a_next;
|
||||
|
@ -281,6 +281,74 @@ attrs_dup( Attribute *a )
|
||||
return anew;
|
||||
}
|
||||
|
||||
int
|
||||
attr_valfind(
|
||||
Attribute *a,
|
||||
unsigned flags,
|
||||
struct berval *val,
|
||||
unsigned *slot,
|
||||
void *ctx )
|
||||
{
|
||||
struct berval nval = BER_BVNULL, *cval;
|
||||
MatchingRule *mr = a->a_desc->ad_type->sat_equality;
|
||||
const char *text;
|
||||
int match = -1, rc;
|
||||
unsigned i;
|
||||
|
||||
if( !SLAP_IS_MR_ASSERTED_VALUE_NORMALIZED_MATCH( flags ) &&
|
||||
mr->smr_normalize )
|
||||
{
|
||||
rc = (mr->smr_normalize)(
|
||||
flags & (SLAP_MR_TYPE_MASK|SLAP_MR_SUBTYPE_MASK|SLAP_MR_VALUE_OF_SYNTAX),
|
||||
a->a_desc->ad_type->sat_syntax,
|
||||
mr, val, &nval, ctx );
|
||||
|
||||
if( rc != LDAP_SUCCESS ) {
|
||||
return LDAP_INVALID_SYNTAX;
|
||||
}
|
||||
cval = &nval;
|
||||
} else {
|
||||
cval = val;
|
||||
}
|
||||
|
||||
if ( a->a_flags & SLAP_ATTR_SORTED_VALS ) {
|
||||
/* Binary search */
|
||||
unsigned base = 0, n = a->a_numvals;
|
||||
int val = 0;
|
||||
|
||||
while ( 0 < n ) {
|
||||
unsigned pivot = n >> 1;
|
||||
i = base + pivot;
|
||||
rc = value_match( &match, a->a_desc, mr, flags,
|
||||
&a->a_nvals[i], cval, &text );
|
||||
if ( rc == LDAP_SUCCESS && match == 0 )
|
||||
break;
|
||||
n = pivot;
|
||||
if ( match > 0 )
|
||||
base = i+1;
|
||||
}
|
||||
if ( match > 0 )
|
||||
i++;
|
||||
} else {
|
||||
/* Linear search */
|
||||
for ( i = 0; i < a->a_numvals; i++ ) {
|
||||
const char *text;
|
||||
|
||||
rc = ordered_value_match( &match, a->a_desc, mr, flags,
|
||||
&a->a_nvals[i], cval, &text );
|
||||
if ( rc == LDAP_SUCCESS && match == 0 )
|
||||
break;
|
||||
}
|
||||
}
|
||||
*slot = i;
|
||||
if ( match )
|
||||
rc = LDAP_NO_SUCH_ATTRIBUTE;
|
||||
if ( nval.bv_val )
|
||||
slap_sl_free( nval.bv_val, ctx );
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int
|
||||
attr_valadd(
|
||||
Attribute *a,
|
||||
@ -312,22 +380,52 @@ attr_valadd(
|
||||
a->a_nvals = a->a_vals;
|
||||
}
|
||||
|
||||
v2 = &a->a_vals[a->a_numvals];
|
||||
for ( i = 0 ; i < nn; i++ ) {
|
||||
ber_dupbv( &v2[i], &vals[i] );
|
||||
if ( BER_BVISNULL( &v2[i] ) ) break;
|
||||
}
|
||||
BER_BVZERO( &v2[i] );
|
||||
|
||||
if ( nvals ) {
|
||||
v2 = &a->a_nvals[a->a_numvals];
|
||||
/* If sorted and old vals exist, must insert */
|
||||
if (( a->a_flags & SLAP_ATTR_SORTED_VALS ) && a->a_numvals ) {
|
||||
unsigned slot;
|
||||
int j, rc;
|
||||
v2 = nvals ? nvals : vals;
|
||||
for ( i = 0; i < nn; i++ ) {
|
||||
rc = attr_valfind( a, SLAP_MR_EQUALITY | SLAP_MR_VALUE_OF_ASSERTION_SYNTAX |
|
||||
SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH | SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH,
|
||||
&v2[i], &slot, NULL );
|
||||
if ( rc != LDAP_NO_SUCH_ATTRIBUTE ) {
|
||||
/* should never happen */
|
||||
if ( rc == LDAP_SUCCESS )
|
||||
rc = LDAP_TYPE_OR_VALUE_EXISTS;
|
||||
return rc;
|
||||
}
|
||||
for ( j = a->a_numvals; j > slot; j-- ) {
|
||||
a->a_vals[j+1] = a->a_vals[j];
|
||||
if ( nvals )
|
||||
a->a_nvals[j+1] = a->a_nvals[j];
|
||||
}
|
||||
ber_dupbv( &a->a_nvals[j], &v2[i] );
|
||||
if ( nvals )
|
||||
ber_dupbv( &a->a_vals[j], &vals[i] );
|
||||
a->a_numvals++;
|
||||
}
|
||||
BER_BVZERO( &a->a_vals[a->a_numvals] );
|
||||
if ( a->a_vals != a->a_nvals )
|
||||
BER_BVZERO( &a->a_nvals[a->a_numvals] );
|
||||
} else {
|
||||
v2 = &a->a_vals[a->a_numvals];
|
||||
for ( i = 0 ; i < nn; i++ ) {
|
||||
ber_dupbv( &v2[i], &nvals[i] );
|
||||
ber_dupbv( &v2[i], &vals[i] );
|
||||
if ( BER_BVISNULL( &v2[i] ) ) break;
|
||||
}
|
||||
BER_BVZERO( &v2[i] );
|
||||
|
||||
if ( nvals ) {
|
||||
v2 = &a->a_nvals[a->a_numvals];
|
||||
for ( i = 0 ; i < nn; i++ ) {
|
||||
ber_dupbv( &v2[i], &nvals[i] );
|
||||
if ( BER_BVISNULL( &v2[i] ) ) break;
|
||||
}
|
||||
BER_BVZERO( &v2[i] );
|
||||
}
|
||||
a->a_numvals += i;
|
||||
}
|
||||
a->a_numvals += i;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -210,6 +210,7 @@ bdb_monitor_free(
|
||||
mod.sm_op = LDAP_MOD_DELETE;
|
||||
mod.sm_desc = slap_schema.si_ad_objectClass;
|
||||
mod.sm_values = values;
|
||||
mod.sm_numvals = 1;
|
||||
values[ 0 ] = oc_olmBDBDatabase->soc_cname;
|
||||
BER_BVZERO( &values[ 1 ] );
|
||||
|
||||
@ -218,9 +219,10 @@ bdb_monitor_free(
|
||||
/* don't care too much about return code... */
|
||||
|
||||
/* remove attrs */
|
||||
mod.sm_values = NULL;
|
||||
mod.sm_numvals = 0;
|
||||
for ( i = 0; s_at[ i ].desc != NULL; i++ ) {
|
||||
mod.sm_desc = *s_at[ i ].ad;
|
||||
mod.sm_values = NULL;
|
||||
rc = modify_delete_values( e, &mod, 1, &text,
|
||||
textbuf, sizeof( textbuf ) );
|
||||
/* don't care too much about return code... */
|
||||
|
@ -177,6 +177,7 @@ enum {
|
||||
CFG_HIDDEN,
|
||||
CFG_MONITORING,
|
||||
CFG_SERVERID,
|
||||
CFG_SORTVALS,
|
||||
|
||||
CFG_LAST
|
||||
};
|
||||
@ -552,6 +553,11 @@ static ConfigTable config_back_cf_table[] = {
|
||||
{ "sockbuf_max_incoming_auth", "max", 2, 2, 0, ARG_BER_LEN_T,
|
||||
&sockbuf_max_incoming_auth, "( OLcfgGlAt:62 NAME 'olcSockbufMaxIncomingAuth' "
|
||||
"SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL },
|
||||
{ "sortvals", "attr", 2, 0, 0, ARG_MAGIC|CFG_SORTVALS,
|
||||
&config_generic, "( OLcfgGlAt:83 NAME 'olcSortVals' "
|
||||
"DESC 'Attributes whose values will always be sorted' "
|
||||
"EQUALITY caseIgnoreMatch "
|
||||
"SYNTAX OMsDirectoryString )", NULL, NULL },
|
||||
{ "subordinate", "[advertise]", 1, 2, 0, ARG_DB|ARG_MAGIC,
|
||||
&config_subordinate, "( OLcfgDbAt:0.15 NAME 'olcSubordinate' "
|
||||
"SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
|
||||
@ -765,7 +771,7 @@ static ConfigOCs cf_ocs[] = {
|
||||
"NAME 'olcFrontendConfig' "
|
||||
"DESC 'OpenLDAP frontend configuration' "
|
||||
"AUXILIARY "
|
||||
"MAY ( olcDefaultSearchBase $ olcPasswordHash ) )",
|
||||
"MAY ( olcDefaultSearchBase $ olcPasswordHash $ olcSortVals ) )",
|
||||
Cft_Database, NULL, NULL },
|
||||
#ifdef SLAPD_MODULES
|
||||
{ "( OLcfgGlOc:8 "
|
||||
@ -786,6 +792,13 @@ typedef struct ServerID {
|
||||
|
||||
static ServerID *sid_list;
|
||||
|
||||
typedef struct ADlist {
|
||||
struct ADlist *al_next;
|
||||
AttributeDescription *al_desc;
|
||||
} ADlist;
|
||||
|
||||
static ADlist *sortVals;
|
||||
|
||||
static int
|
||||
config_generic(ConfigArgs *c) {
|
||||
int i;
|
||||
@ -1000,6 +1013,14 @@ config_generic(ConfigArgs *c) {
|
||||
case CFG_SSTR_IF_MIN:
|
||||
c->value_int = index_substr_if_minlen;
|
||||
break;
|
||||
case CFG_SORTVALS: {
|
||||
ADlist *sv;
|
||||
rc = 1;
|
||||
for ( sv = sortVals; sv; sv = sv->al_next ) {
|
||||
value_add_one( &c->rvalue_vals, &sv->al_desc->ad_cname );
|
||||
rc = 0;
|
||||
}
|
||||
} break;
|
||||
#ifdef SLAPD_MODULES
|
||||
case CFG_MODLOAD: {
|
||||
ModPaths *mp = c->private;
|
||||
@ -1224,6 +1245,27 @@ config_generic(ConfigArgs *c) {
|
||||
}
|
||||
}
|
||||
break;
|
||||
case CFG_SORTVALS:
|
||||
if ( c->valx < 0 ) {
|
||||
ADlist *sv;
|
||||
for ( sv = sortVals; sv; sv = sortVals ) {
|
||||
sortVals = sv->al_next;
|
||||
sv->al_desc->ad_type->sat_flags &= ~SLAP_AT_SORTED_VAL;
|
||||
ch_free( sv );
|
||||
}
|
||||
} else {
|
||||
ADlist *sv, **prev;
|
||||
int i = 0;
|
||||
|
||||
for ( prev = &sortVals, sv = sortVals; i < c->valx; i++ ) {
|
||||
prev = &sv->al_next;
|
||||
sv = sv->al_next;
|
||||
}
|
||||
sv->al_desc->ad_type->sat_flags &= ~SLAP_AT_SORTED_VAL;
|
||||
*prev = sv->al_next;
|
||||
ch_free( sv );
|
||||
}
|
||||
break;
|
||||
|
||||
case CFG_LIMITS:
|
||||
/* FIXME: there is no limits_free function */
|
||||
@ -1447,6 +1489,52 @@ config_generic(ConfigArgs *c) {
|
||||
return(1);
|
||||
break;
|
||||
|
||||
case CFG_SORTVALS: {
|
||||
ADlist *svnew = NULL, *svtail, *sv;
|
||||
|
||||
for ( i = 1; i < c->argc; i++ ) {
|
||||
AttributeDescription *ad = NULL;
|
||||
const char *text;
|
||||
int rc;
|
||||
|
||||
rc = slap_str2ad( c->argv[i], &ad, &text );
|
||||
if ( rc ) {
|
||||
snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> unknown attribute type #%d",
|
||||
c->argv[0], i );
|
||||
sortval_reject:
|
||||
Debug(LDAP_DEBUG_ANY, "%s: %s %s\n",
|
||||
c->log, c->cr_msg, c->argv[i] );
|
||||
for ( sv = svnew; sv; sv = svnew ) {
|
||||
svnew = sv->al_next;
|
||||
ch_free( sv );
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
if (( ad->ad_type->sat_flags & SLAP_AT_ORDERED ) ||
|
||||
ad->ad_type->sat_single_value ) {
|
||||
snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> inappropriate attribute type #%d",
|
||||
c->argv[0], i );
|
||||
goto sortval_reject;
|
||||
}
|
||||
sv = ch_malloc( sizeof( ADlist ));
|
||||
sv->al_desc = ad;
|
||||
if ( !svnew ) {
|
||||
svnew = sv;
|
||||
} else {
|
||||
svtail->al_next = sv;
|
||||
}
|
||||
svtail = sv;
|
||||
}
|
||||
for ( sv = svnew; sv; sv = sv->al_next )
|
||||
sv->al_desc->ad_type->sat_flags |= SLAP_AT_SORTED_VAL;
|
||||
for ( sv = sortVals; sv && sv->al_next; sv = sv->al_next );
|
||||
if ( sv )
|
||||
sv->al_next = svnew;
|
||||
else
|
||||
sortVals = svnew;
|
||||
}
|
||||
break;
|
||||
|
||||
case CFG_ACL:
|
||||
/* Don't append to the global ACL if we're on a specific DB */
|
||||
i = c->valx;
|
||||
@ -4544,7 +4632,7 @@ config_modify_internal( CfEntryInfo *ce, Operation *op, SlapReply *rs,
|
||||
*/
|
||||
if ( ct && ml->sml_values ) {
|
||||
delrec *d;
|
||||
for (i=0; ml->sml_values[i].bv_val; i++);
|
||||
i = ml->sml_numvals;
|
||||
d = ch_malloc( sizeof(delrec) + (i - 1)* sizeof(int));
|
||||
d->nidx = i;
|
||||
d->next = NULL;
|
||||
@ -4577,8 +4665,7 @@ config_modify_internal( CfEntryInfo *ce, Operation *op, SlapReply *rs,
|
||||
if ( ct->arg_type & ARG_NO_INSERT ) {
|
||||
Attribute *a = attr_find( e->e_attrs, ml->sml_desc );
|
||||
if ( a ) {
|
||||
for (i = 0; a->a_vals[i].bv_val; i++ );
|
||||
navals = i;
|
||||
navals = a->a_numvals;
|
||||
}
|
||||
}
|
||||
for ( i=0; !BER_BVISNULL( &ml->sml_values[i] ); i++ ) {
|
||||
|
@ -277,6 +277,18 @@ str2entry2( char *s, int checkvals )
|
||||
|
||||
if (( ad_prev && ad != ad_prev ) || ( i == lines )) {
|
||||
int j, k;
|
||||
/* FIXME: we only need this when migrating from an unsorted DB */
|
||||
if ( atail != &ahead && atail->a_desc->ad_type->sat_flags & SLAP_AT_SORTED_VAL ) {
|
||||
rc = slap_sort_vals( (Modifications *)atail, &text, &j, NULL );
|
||||
if ( rc == LDAP_SUCCESS ) {
|
||||
atail->a_flags |= SLAP_ATTR_SORTED_VALS;
|
||||
} else if ( rc == LDAP_TYPE_OR_VALUE_EXISTS ) {
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"str2entry: attributeType %s value #%d provided more than once\n",
|
||||
atail->a_desc->ad_cname.bv_val, j, 0 );
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
atail->a_next = attr_alloc( NULL );
|
||||
atail = atail->a_next;
|
||||
atail->a_flags = 0;
|
||||
@ -892,6 +904,19 @@ int entry_decode(EntryHeader *eh, Entry **e)
|
||||
} else {
|
||||
a->a_nvals = a->a_vals;
|
||||
}
|
||||
/* FIXME: This is redundant once a sorted entry is saved into the DB */
|
||||
if ( a->a_desc->ad_type->sat_flags & SLAP_AT_SORTED_VAL ) {
|
||||
rc = slap_sort_vals( (Modifications *)a, &text, &j, NULL );
|
||||
if ( rc == LDAP_SUCCESS ) {
|
||||
a->a_flags |= SLAP_ATTR_SORTED_VALS;
|
||||
} else if ( rc == LDAP_TYPE_OR_VALUE_EXISTS ) {
|
||||
/* should never happen */
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"entry_decode: attributeType %s value #%d provided more than once\n",
|
||||
a->a_desc->ad_cname.bv_val, j, 0 );
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
a = a->a_next;
|
||||
nattrs--;
|
||||
if ( !nattrs )
|
||||
|
@ -640,200 +640,200 @@ 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;
|
||||
|
||||
for ( i = 1; i < nvals ; i++ ) {
|
||||
/* test asserted values against themselves */
|
||||
for( j = 0; j < i; j++ ) {
|
||||
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,
|
||||
ml->sml_nvalues
|
||||
? &ml->sml_nvalues[i]
|
||||
: &ml->sml_values[i],
|
||||
ml->sml_nvalues
|
||||
? &ml->sml_nvalues[j]
|
||||
: &ml->sml_values[j],
|
||||
text );
|
||||
if ( rc == LDAP_SUCCESS && match == 0 ) {
|
||||
/* value exists already */
|
||||
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;
|
||||
|
||||
} else if ( rc != LDAP_SUCCESS ) {
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
int i;
|
||||
rc = slap_sort_vals( ml, text, &i, ctx );
|
||||
if ( rc == LDAP_TYPE_OR_VALUE_EXISTS ) {
|
||||
/* value exists already */
|
||||
snprintf( textbuf, textlen,
|
||||
"%s: value #%d provided more than once",
|
||||
ml->sml_desc->ad_cname.bv_val, i );
|
||||
*text = textbuf;
|
||||
}
|
||||
#else /* SLAP_MODS_CHECK_QUICKSORT */
|
||||
if ( rc )
|
||||
return rc;
|
||||
}
|
||||
} else {
|
||||
ml->sml_numvals = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Quicksort + Insertion sort for small arrays */
|
||||
return LDAP_SUCCESS;
|
||||
}
|
||||
|
||||
/* Sort a set of values. An (Attribute *) may be used interchangeably here
|
||||
* instead of a (Modifications *) structure.
|
||||
*
|
||||
* Uses Quicksort + Insertion sort for small arrays
|
||||
*/
|
||||
|
||||
int
|
||||
slap_sort_vals(
|
||||
Modifications *ml,
|
||||
const char **text,
|
||||
int *dup,
|
||||
void *ctx )
|
||||
{
|
||||
AttributeDescription *ad;
|
||||
MatchingRule *mr;
|
||||
int istack[sizeof(int)*16];
|
||||
int i, j, k, l, ir, jstack, match, *ix, itmp, nvals, rc;
|
||||
int is_norm;
|
||||
struct berval a, *cv;
|
||||
|
||||
#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 \
|
||||
ad, 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, 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 */
|
||||
ad = ml->sml_desc;
|
||||
nvals = ml->sml_numvals;
|
||||
|
||||
cv = ml->sml_nvalues ? ml->sml_nvalues : ml->sml_values;
|
||||
if ( ad == slap_schema.si_ad_objectClass )
|
||||
mr = NULL; /* shortcut matching */
|
||||
/* For Modifications, sml_nvalues is NULL if normalization wasn't needed.
|
||||
* For Attributes, sml_nvalues == sml_values when normalization isn't needed.
|
||||
*/
|
||||
if ( ml->sml_nvalues && ml->sml_nvalues != ml->sml_values ) {
|
||||
cv = ml->sml_nvalues;
|
||||
is_norm = 1;
|
||||
} else {
|
||||
cv = ml->sml_values;
|
||||
is_norm = 0;
|
||||
}
|
||||
|
||||
/* record indices to preserve input ordering */
|
||||
ix = slap_sl_malloc( nvals * sizeof(int), ctx );
|
||||
for (i=0; i<nvals; i++) ix[i] = i;
|
||||
if ( ad == slap_schema.si_ad_objectClass )
|
||||
mr = NULL; /* shortcut matching */
|
||||
else
|
||||
mr = ad->ad_type->sat_equality;
|
||||
|
||||
ir = nvals-1;
|
||||
l = 0;
|
||||
jstack = 0;
|
||||
/* record indices to preserve input ordering */
|
||||
ix = slap_sl_malloc( nvals * sizeof(int), ctx );
|
||||
for (i=0; i<nvals; i++) ix[i] = i;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
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);
|
||||
}
|
||||
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;
|
||||
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 );
|
||||
}
|
||||
#endif /* SLAP_MODS_CHECK_QUICKSORT */
|
||||
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 )
|
||||
*dup = ix[i];
|
||||
|
||||
/* For sorted attributes, put the values in index order */
|
||||
if ( rc == LDAP_SUCCESS && match &&
|
||||
( ad->ad_type->sat_flags & SLAP_AT_SORTED_VAL )) {
|
||||
BerVarray tmpv = slap_sl_malloc( sizeof( struct berval ) * nvals, ctx );
|
||||
for ( i = 0; i<nvals; i++ )
|
||||
tmpv[i] = cv[ix[i]];
|
||||
for ( i = 0; i<nvals; i++ )
|
||||
cv[i] = tmpv[i];
|
||||
/* Check if the non-normalized array needs to move too */
|
||||
if ( is_norm ) {
|
||||
cv = ml->sml_values;
|
||||
for ( i = 0; i<nvals; i++ )
|
||||
tmpv[i] = cv[ix[i]];
|
||||
for ( i = 0; i<nvals; i++ )
|
||||
cv[i] = tmpv[i];
|
||||
}
|
||||
slap_sl_free( tmpv, ctx );
|
||||
}
|
||||
|
||||
slap_sl_free( ix, ctx );
|
||||
|
||||
if ( rc != LDAP_SUCCESS ) {
|
||||
return rc;
|
||||
} else if ( match == 0 ) {
|
||||
/* value exists already */
|
||||
assert( i >= 0 );
|
||||
assert( i < nvals );
|
||||
return LDAP_TYPE_OR_VALUE_EXISTS;
|
||||
}
|
||||
return LDAP_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -56,11 +56,21 @@ modify_add_values(
|
||||
assert( 0 );
|
||||
}
|
||||
|
||||
/* FIXME: Catch old code that doesn't set sm_numvals.
|
||||
*/
|
||||
if ( !BER_BVISNULL( &mod->sm_values[mod->sm_numvals] )) {
|
||||
int i;
|
||||
for ( i = 0; !BER_BVISNULL( &mod->sm_values[i] ); i++ );
|
||||
assert( mod->sm_numvals == i );
|
||||
}
|
||||
|
||||
/* check if values to add exist in attribute */
|
||||
a = attr_find( e->e_attrs, mod->sm_desc );
|
||||
if ( a != NULL ) {
|
||||
int rc, i, j, p;
|
||||
MatchingRule *mr;
|
||||
struct berval *cvals;
|
||||
int rc, i, j, p;
|
||||
unsigned flags;
|
||||
|
||||
mr = mod->sm_desc->ad_type->sat_equality;
|
||||
if( mr == NULL || !mr->smr_match ) {
|
||||
@ -74,10 +84,7 @@ modify_add_values(
|
||||
}
|
||||
|
||||
if ( permissive ) {
|
||||
for ( i = 0; !BER_BVISNULL( &mod->sm_values[i] ); i++ ) {
|
||||
/* EMPTY -- just counting 'em */;
|
||||
}
|
||||
|
||||
i = mod->sm_numvals;
|
||||
pmod.sm_values = (BerVarray)ch_malloc(
|
||||
(i + 1) * sizeof( struct berval ));
|
||||
if ( pmod.sm_nvalues != NULL ) {
|
||||
@ -92,39 +99,32 @@ modify_add_values(
|
||||
* server (whether from LDAP or from the underlying
|
||||
* database).
|
||||
*/
|
||||
for ( p = i = 0; !BER_BVISNULL( &mod->sm_values[i] ); i++ ) {
|
||||
int match;
|
||||
flags = SLAP_MR_EQUALITY | SLAP_MR_VALUE_OF_ASSERTION_SYNTAX;
|
||||
if ( mod->sm_nvalues ) {
|
||||
flags |= SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH |
|
||||
SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH;
|
||||
cvals = mod->sm_nvalues;
|
||||
} else {
|
||||
cvals = mod->sm_values;
|
||||
}
|
||||
for ( p = i = 0; i < mod->sm_numvals; i++ ) {
|
||||
unsigned slot;
|
||||
|
||||
assert( a->a_vals[0].bv_val != NULL );
|
||||
for ( j = 0; !BER_BVISNULL( &a->a_vals[j] ); j++ ) {
|
||||
if ( mod->sm_nvalues ) {
|
||||
rc = ordered_value_match( &match, mod->sm_desc, mr,
|
||||
SLAP_MR_EQUALITY | SLAP_MR_VALUE_OF_ASSERTION_SYNTAX
|
||||
| SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH
|
||||
| SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH,
|
||||
&a->a_nvals[j], &mod->sm_nvalues[i], text );
|
||||
} else {
|
||||
rc = ordered_value_match( &match, mod->sm_desc, mr,
|
||||
SLAP_MR_EQUALITY | SLAP_MR_VALUE_OF_ASSERTION_SYNTAX,
|
||||
&a->a_vals[j], &mod->sm_values[i], text );
|
||||
}
|
||||
|
||||
if ( rc == LDAP_SUCCESS && match == 0 ) {
|
||||
rc = attr_valfind( a, flags, &cvals[i], &slot, NULL );
|
||||
if ( rc == LDAP_SUCCESS ) {
|
||||
if ( !permissive ) {
|
||||
/* value already exists */
|
||||
if ( permissive ) break;
|
||||
|
||||
*text = textbuf;
|
||||
snprintf( textbuf, textlen,
|
||||
"modify/%s: %s: value #%d already exists",
|
||||
op, mod->sm_desc->ad_cname.bv_val, i );
|
||||
return LDAP_TYPE_OR_VALUE_EXISTS;
|
||||
|
||||
} else if ( rc != LDAP_SUCCESS ) {
|
||||
return rc;
|
||||
}
|
||||
} else if ( rc != LDAP_NO_SUCH_ATTRIBUTE ) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
if ( permissive && match != 0 ) {
|
||||
if ( permissive && rc ) {
|
||||
if ( pmod.sm_nvalues ) {
|
||||
pmod.sm_nvalues[p] = mod->sm_nvalues[i];
|
||||
}
|
||||
@ -164,8 +164,8 @@ modify_add_values(
|
||||
/* this should return result of attr_merge */
|
||||
*text = textbuf;
|
||||
snprintf( textbuf, textlen,
|
||||
"modify/%s: %s: merge error",
|
||||
op, mod->sm_desc->ad_cname.bv_val );
|
||||
"modify/%s: %s: merge error (%d)",
|
||||
op, mod->sm_desc->ad_cname.bv_val, rc );
|
||||
return LDAP_OTHER;
|
||||
}
|
||||
|
||||
@ -192,11 +192,13 @@ modify_delete_vindex(
|
||||
char *textbuf, size_t textlen,
|
||||
int *idx )
|
||||
{
|
||||
int i, j, k, rc = LDAP_SUCCESS;
|
||||
Attribute *a;
|
||||
MatchingRule *mr = mod->sm_desc->ad_type->sat_equality;
|
||||
struct berval *cvals;
|
||||
int *id2 = NULL;
|
||||
int i, j, rc;
|
||||
unsigned flags;
|
||||
char dummy = '\0';
|
||||
int match = 0;
|
||||
|
||||
/*
|
||||
* If permissive is set, then the non-existence of an
|
||||
@ -219,6 +221,17 @@ modify_delete_vindex(
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* FIXME: Catch old code that doesn't set sm_numvals.
|
||||
*/
|
||||
if ( !BER_BVISNULL( &mod->sm_values[mod->sm_numvals] )) {
|
||||
for ( i = 0; !BER_BVISNULL( &mod->sm_values[i] ); i++ );
|
||||
assert( mod->sm_numvals == i );
|
||||
}
|
||||
if ( !idx ) {
|
||||
id2 = ch_malloc( mod->sm_numvals * sizeof( int ));
|
||||
idx = id2;
|
||||
}
|
||||
|
||||
if( mr == NULL || !mr->smr_match ) {
|
||||
/* disallow specific attributes from being deleted if
|
||||
no equality rule */
|
||||
@ -226,102 +239,90 @@ modify_delete_vindex(
|
||||
snprintf( textbuf, textlen,
|
||||
"modify/delete: %s: no equality matching rule",
|
||||
mod->sm_desc->ad_cname.bv_val );
|
||||
return LDAP_INAPPROPRIATE_MATCHING;
|
||||
rc = LDAP_INAPPROPRIATE_MATCHING;
|
||||
goto return_result;
|
||||
}
|
||||
|
||||
/* delete specific values - find the attribute first */
|
||||
if ( (a = attr_find( e->e_attrs, mod->sm_desc )) == NULL ) {
|
||||
if( permissive ) {
|
||||
return LDAP_SUCCESS;
|
||||
rc = LDAP_SUCCESS;
|
||||
goto return_result;
|
||||
}
|
||||
*text = textbuf;
|
||||
snprintf( textbuf, textlen,
|
||||
"modify/delete: %s: no such attribute",
|
||||
mod->sm_desc->ad_cname.bv_val );
|
||||
return LDAP_NO_SUCH_ATTRIBUTE;
|
||||
rc = LDAP_NO_SUCH_ATTRIBUTE;
|
||||
goto return_result;
|
||||
}
|
||||
|
||||
if ( mod->sm_nvalues ) {
|
||||
flags = SLAP_MR_EQUALITY | SLAP_MR_VALUE_OF_ASSERTION_SYNTAX
|
||||
| SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH
|
||||
| SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH;
|
||||
cvals = mod->sm_nvalues;
|
||||
} else {
|
||||
flags = SLAP_MR_EQUALITY | SLAP_MR_VALUE_OF_ASSERTION_SYNTAX;
|
||||
cvals = mod->sm_values;
|
||||
}
|
||||
|
||||
/* Locate values to delete */
|
||||
for ( i = 0; !BER_BVISNULL( &mod->sm_values[i] ); i++ ) {
|
||||
int found = 0;
|
||||
for ( j = 0; !BER_BVISNULL( &a->a_vals[j] ); j++ ) {
|
||||
/* skip already deleted values */
|
||||
if ( a->a_vals[j].bv_val == &dummy ) {
|
||||
unsigned sort;
|
||||
rc = attr_valfind( a, flags, &cvals[i], &sort, NULL );
|
||||
if ( rc == LDAP_SUCCESS ) {
|
||||
idx[i] = sort;
|
||||
} else if ( rc == LDAP_NO_SUCH_ATTRIBUTE ) {
|
||||
if ( permissive ) {
|
||||
idx[i] = -1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if( mod->sm_nvalues ) {
|
||||
assert( a->a_nvals != NULL );
|
||||
rc = ordered_value_match( &match, a->a_desc, mr,
|
||||
SLAP_MR_EQUALITY | SLAP_MR_VALUE_OF_ASSERTION_SYNTAX
|
||||
| SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH
|
||||
| SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH,
|
||||
&a->a_nvals[j], &mod->sm_nvalues[i], text );
|
||||
} else {
|
||||
#if 0
|
||||
assert( a->a_nvals == NULL );
|
||||
#endif
|
||||
rc = ordered_value_match( &match, a->a_desc, mr,
|
||||
SLAP_MR_EQUALITY | SLAP_MR_VALUE_OF_ASSERTION_SYNTAX,
|
||||
&a->a_vals[j], &mod->sm_values[i], text );
|
||||
}
|
||||
|
||||
if ( rc != LDAP_SUCCESS ) {
|
||||
*text = textbuf;
|
||||
snprintf( textbuf, textlen,
|
||||
"%s: matching rule failed",
|
||||
mod->sm_desc->ad_cname.bv_val );
|
||||
break;
|
||||
}
|
||||
|
||||
if ( match != 0 ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
found = 1;
|
||||
|
||||
if ( idx )
|
||||
idx[i] = j;
|
||||
|
||||
/* delete value and mark it as dummy */
|
||||
free( a->a_vals[j].bv_val );
|
||||
a->a_vals[j].bv_val = &dummy;
|
||||
if( a->a_nvals != a->a_vals ) {
|
||||
free( a->a_nvals[j].bv_val );
|
||||
a->a_nvals[j].bv_val = &dummy;
|
||||
}
|
||||
a->a_numvals--;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if ( found == 0 ) {
|
||||
*text = textbuf;
|
||||
snprintf( textbuf, textlen,
|
||||
"modify/delete: %s: no such value",
|
||||
mod->sm_desc->ad_cname.bv_val );
|
||||
rc = LDAP_NO_SUCH_ATTRIBUTE;
|
||||
if ( i > 0 ) {
|
||||
break;
|
||||
} else {
|
||||
goto return_results;
|
||||
}
|
||||
goto return_result;
|
||||
} else {
|
||||
*text = textbuf;
|
||||
snprintf( textbuf, textlen,
|
||||
"modify/delete: %s: matching rule failed",
|
||||
mod->sm_desc->ad_cname.bv_val );
|
||||
goto return_result;
|
||||
}
|
||||
}
|
||||
|
||||
/* Delete the values */
|
||||
for ( i = 0; i < mod->sm_numvals; i++ ) {
|
||||
/* Skip permissive values that weren't found */
|
||||
if ( idx[i] < 0 )
|
||||
continue;
|
||||
/* Skip duplicate delete specs */
|
||||
if ( a->a_vals[idx[i]].bv_val == &dummy )
|
||||
continue;
|
||||
/* delete value and mark it as gone */
|
||||
free( a->a_vals[idx[i]].bv_val );
|
||||
a->a_vals[idx[i]].bv_val = &dummy;
|
||||
if( a->a_nvals != a->a_vals ) {
|
||||
free( a->a_nvals[idx[i]].bv_val );
|
||||
a->a_nvals[idx[i]].bv_val = &dummy;
|
||||
}
|
||||
a->a_numvals--;
|
||||
}
|
||||
|
||||
/* compact array skipping dummies */
|
||||
for ( k = 0, j = 0; !BER_BVISNULL( &a->a_vals[k] ); k++ ) {
|
||||
for ( i = 0, j = 0; !BER_BVISNULL( &a->a_vals[i] ); i++ ) {
|
||||
/* skip dummies */
|
||||
if( a->a_vals[k].bv_val == &dummy ) {
|
||||
assert( a->a_nvals[k].bv_val == &dummy );
|
||||
if( a->a_vals[i].bv_val == &dummy ) {
|
||||
assert( a->a_nvals[i].bv_val == &dummy );
|
||||
continue;
|
||||
}
|
||||
if ( j != k ) {
|
||||
a->a_vals[ j ] = a->a_vals[ k ];
|
||||
if ( j != i ) {
|
||||
a->a_vals[ j ] = a->a_vals[ i ];
|
||||
if (a->a_nvals != a->a_vals) {
|
||||
a->a_nvals[ j ] = a->a_nvals[ k ];
|
||||
a->a_nvals[ j ] = a->a_nvals[ i ];
|
||||
}
|
||||
}
|
||||
|
||||
j++;
|
||||
}
|
||||
|
||||
@ -331,8 +332,9 @@ modify_delete_vindex(
|
||||
}
|
||||
|
||||
/* if no values remain, delete the entire attribute */
|
||||
if ( BER_BVISNULL( &a->a_vals[0] ) ) {
|
||||
if ( !a->a_numvals ) {
|
||||
if ( attr_delete( &e->e_attrs, mod->sm_desc ) ) {
|
||||
/* Can never happen */
|
||||
*text = textbuf;
|
||||
snprintf( textbuf, textlen,
|
||||
"modify/delete: %s: no such attribute",
|
||||
@ -343,9 +345,9 @@ modify_delete_vindex(
|
||||
/* For an ordered attribute, renumber the value indices */
|
||||
ordered_value_sort( a, 1 );
|
||||
}
|
||||
|
||||
return_results:;
|
||||
|
||||
return_result:
|
||||
if ( id2 )
|
||||
ch_free( id2 );
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
@ -189,6 +189,7 @@ dynlist_sc_update( Operation *op, SlapReply *rs )
|
||||
mod.sm_type = dlc->dlc_dli->dli_member_ad->ad_cname;
|
||||
mod.sm_values = vals;
|
||||
mod.sm_nvalues = nvals;
|
||||
mod.sm_numvals = 1;
|
||||
|
||||
(void)modify_add_values( e, &mod, /* permissive */ 1,
|
||||
&text, textbuf, sizeof( textbuf ) );
|
||||
@ -292,6 +293,7 @@ dynlist_sc_update( Operation *op, SlapReply *rs )
|
||||
mod.sm_type = a->a_desc->ad_cname;
|
||||
mod.sm_values = vals;
|
||||
mod.sm_nvalues = nvals;
|
||||
mod.sm_numvals = j;
|
||||
|
||||
(void)modify_add_values( e, &mod, /* permissive */ 1,
|
||||
&text, textbuf, sizeof( textbuf ) );
|
||||
|
@ -416,6 +416,7 @@ memberof_value_modify(
|
||||
op2.o_ndn = op->o_bd->be_rootndn;
|
||||
|
||||
ml = &mod[ 0 ];
|
||||
ml->sml_numvals = 1;
|
||||
ml->sml_values = &values[ 0 ];
|
||||
ml->sml_values[ 0 ] = mo->mo_dn;
|
||||
BER_BVZERO( &ml->sml_values[ 1 ] );
|
||||
@ -430,6 +431,7 @@ memberof_value_modify(
|
||||
op2.orm_modlist = ml;
|
||||
|
||||
ml = &mod[ 1 ];
|
||||
ml->sml_numvals = 1;
|
||||
ml->sml_values = &values[ 2 ];
|
||||
BER_BVZERO( &ml->sml_values[ 1 ] );
|
||||
ml->sml_nvalues = &nvalues[ 2 ];
|
||||
@ -812,6 +814,7 @@ memberof_op_modify( Operation *op, SlapReply *rs )
|
||||
BER_BVZERO( &ml->sml_values[ i ] );
|
||||
ber_memfree( ml->sml_nvalues[ i ].bv_val );
|
||||
BER_BVZERO( &ml->sml_nvalues[ i ] );
|
||||
ml->sml_numvals--;
|
||||
if ( j - i == 1 ) {
|
||||
break;
|
||||
}
|
||||
@ -909,6 +912,7 @@ memberof_op_modify( Operation *op, SlapReply *rs )
|
||||
ber_memfree( ml->sml_nvalues[ i ].bv_val );
|
||||
BER_BVZERO( &ml->sml_nvalues[ i ] );
|
||||
}
|
||||
ml->sml_numvals--;
|
||||
if ( j - i == 1 ) {
|
||||
break;
|
||||
}
|
||||
@ -1019,6 +1023,7 @@ memberof_op_modify( Operation *op, SlapReply *rs )
|
||||
ber_memfree( ml->sml_nvalues[ i ].bv_val );
|
||||
BER_BVZERO( &ml->sml_nvalues[ i ] );
|
||||
}
|
||||
ml->sml_numvals--;
|
||||
if ( j - i == 1 ) {
|
||||
break;
|
||||
}
|
||||
|
@ -1287,6 +1287,7 @@ syncprov_checkpoint( Operation *op, SlapReply *rs, slap_overinst *on )
|
||||
SlapReply rsm = { 0 };
|
||||
slap_callback cb = {0};
|
||||
|
||||
mod.sml_numvals = si->si_numcsns;
|
||||
mod.sml_values = si->si_ctxcsn;
|
||||
mod.sml_nvalues = NULL;
|
||||
mod.sml_desc = slap_schema.si_ad_contextCSN;
|
||||
|
@ -268,6 +268,11 @@ LDAP_SLAPD_F (void) comp_tree_free LDAP_P(( Attribute *a ));
|
||||
LDAP_SLAPD_F (Attribute *) attr_alloc LDAP_P(( AttributeDescription *ad ));
|
||||
LDAP_SLAPD_F (Attribute *) attrs_alloc LDAP_P(( int num ));
|
||||
LDAP_SLAPD_F (int) attr_prealloc LDAP_P(( int num ));
|
||||
LDAP_SLAPD_F (int) attr_valfind LDAP_P(( Attribute *a,
|
||||
unsigned flags,
|
||||
struct berval *val,
|
||||
unsigned *slot,
|
||||
void *ctx ));
|
||||
LDAP_SLAPD_F (int) attr_valadd LDAP_P(( Attribute *a,
|
||||
BerVarray vals,
|
||||
BerVarray nvals,
|
||||
@ -1166,6 +1171,12 @@ LDAP_SLAPD_F( int ) slap_mods_check(
|
||||
const char **text,
|
||||
char *textbuf, size_t textlen, void *ctx );
|
||||
|
||||
LDAP_SLAPD_F( int ) slap_sort_vals(
|
||||
Modifications *ml,
|
||||
const char **text,
|
||||
int *dup,
|
||||
void *ctx );
|
||||
|
||||
LDAP_SLAPD_F( void ) slap_timestamp(
|
||||
time_t *tm,
|
||||
struct berval *bv );
|
||||
|
@ -690,10 +690,19 @@ struct AttributeType {
|
||||
|
||||
#define SLAP_AT_MANAGEABLE 0x0800U /* no-user-mod can be by-passed */
|
||||
|
||||
/* Note: ORDERED values have an ordering specifically set by the
|
||||
* user, denoted by the {x} ordering prefix on the values.
|
||||
*
|
||||
* SORTED values are simply sorted by memcmp. SORTED values can
|
||||
* be efficiently located by binary search. ORDERED values have no
|
||||
* such advantage. An attribute cannot have both properties.
|
||||
*/
|
||||
#define SLAP_AT_ORDERED_VAL 0x0001U /* values are ordered */
|
||||
#define SLAP_AT_ORDERED_SIB 0x0002U /* siblings are ordered */
|
||||
#define SLAP_AT_ORDERED 0x0003U /* value has order index */
|
||||
|
||||
#define SLAP_AT_SORTED_VAL 0x0010U /* values should be sorted */
|
||||
|
||||
#define SLAP_AT_HARDCODE 0x10000U /* hardcoded schema */
|
||||
#define SLAP_AT_DELETED 0x20000U
|
||||
|
||||
@ -1109,22 +1118,23 @@ struct ValuesReturnFilter {
|
||||
|
||||
/*
|
||||
* represents an attribute (description + values)
|
||||
* desc, vals, nvals, numvals fields must align with Modification
|
||||
*/
|
||||
struct Attribute {
|
||||
AttributeDescription *a_desc;
|
||||
BerVarray a_vals; /* preserved values */
|
||||
BerVarray a_nvals; /* normalized values */
|
||||
#ifdef LDAP_COMP_MATCH
|
||||
ComponentData *a_comp_data; /* component values */
|
||||
#endif
|
||||
Attribute *a_next;
|
||||
unsigned a_numvals; /* number of vals */
|
||||
unsigned a_flags;
|
||||
#define SLAP_ATTR_IXADD 0x1U
|
||||
#define SLAP_ATTR_IXDEL 0x2U
|
||||
#define SLAP_ATTR_DONT_FREE_DATA 0x4U
|
||||
#define SLAP_ATTR_DONT_FREE_VALS 0x8U
|
||||
#define SLAP_ATTR_SORTED_VALS 0x10U
|
||||
#define SLAP_ATTR_SORTED_VALS 0x10U /* values are sorted */
|
||||
Attribute *a_next;
|
||||
#ifdef LDAP_COMP_MATCH
|
||||
ComponentData *a_comp_data; /* component values */
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
@ -1171,8 +1181,13 @@ struct Entry {
|
||||
|
||||
/*
|
||||
* A list of LDAPMods
|
||||
* desc, values, nvalues, numvals must align with Attribute
|
||||
*/
|
||||
struct Modification {
|
||||
AttributeDescription *sm_desc;
|
||||
BerVarray sm_values;
|
||||
BerVarray sm_nvalues;
|
||||
unsigned sm_numvals;
|
||||
short sm_op;
|
||||
short sm_flags;
|
||||
/* Set for internal mods, will bypass ACL checks. Only needed when
|
||||
@ -1180,12 +1195,7 @@ struct Modification {
|
||||
*/
|
||||
#define SLAP_MOD_INTERNAL 0x01
|
||||
#define SLAP_MOD_MANAGING 0x02
|
||||
|
||||
AttributeDescription *sm_desc;
|
||||
struct berval sm_type;
|
||||
BerVarray sm_values;
|
||||
BerVarray sm_nvalues;
|
||||
unsigned sm_numvals;
|
||||
};
|
||||
|
||||
struct Modifications {
|
||||
|
@ -72,7 +72,8 @@ static int checkBVString(const struct berval *bv)
|
||||
int
|
||||
bvptr2obj(
|
||||
struct berval **bvptr,
|
||||
BerVarray *bvobj )
|
||||
BerVarray *bvobj,
|
||||
unsigned *num )
|
||||
{
|
||||
int rc = LDAP_SUCCESS;
|
||||
int i;
|
||||
@ -85,6 +86,8 @@ bvptr2obj(
|
||||
for ( i = 0; bvptr != NULL && bvptr[i] != NULL; i++ ) {
|
||||
; /* EMPTY */
|
||||
}
|
||||
if ( num )
|
||||
*num = i;
|
||||
|
||||
tmpberval = (BerVarray)slapi_ch_malloc( (i + 1)*sizeof(struct berval));
|
||||
if ( tmpberval == NULL ) {
|
||||
@ -231,12 +234,12 @@ slapi_entry_attr_merge(
|
||||
return -1;
|
||||
}
|
||||
|
||||
rc = bvptr2obj( vals, &bv );
|
||||
rc = bvptr2obj( vals, &bv, NULL );
|
||||
if ( rc != LDAP_SUCCESS ) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
rc = attr_merge_normalize_one( e, ad, bv, NULL );
|
||||
rc = attr_merge_normalize( e, ad, bv, NULL );
|
||||
ch_free( bv );
|
||||
|
||||
return rc;
|
||||
@ -545,9 +548,10 @@ slapi_entry_add_values( Slapi_Entry *e, const char *type, struct berval **vals )
|
||||
* FIXME: sm_values = NULL ? */
|
||||
mod.sm_values = (BerVarray)ch_malloc( sizeof(struct berval) );
|
||||
mod.sm_values->bv_val = NULL;
|
||||
mod.sm_numvals = 0;
|
||||
|
||||
} else {
|
||||
rc = bvptr2obj( vals, &mod.sm_values );
|
||||
rc = bvptr2obj( vals, &mod.sm_values, &mod.sm_numvals );
|
||||
if ( rc != LDAP_SUCCESS ) {
|
||||
return LDAP_CONSTRAINT_VIOLATION;
|
||||
}
|
||||
@ -611,7 +615,7 @@ slapi_entry_delete_values( Slapi_Entry *e, const char *type, struct berval **val
|
||||
return attr_delete( &e->e_attrs, mod.sm_desc ) ? LDAP_OTHER : LDAP_SUCCESS;
|
||||
}
|
||||
|
||||
rc = bvptr2obj( vals, &mod.sm_values );
|
||||
rc = bvptr2obj( vals, &mod.sm_values, &mod.sm_numvals );
|
||||
if ( rc != LDAP_SUCCESS ) {
|
||||
return LDAP_CONSTRAINT_VIOLATION;
|
||||
}
|
||||
@ -730,7 +734,7 @@ slapi_entry_attr_replace_sv( Slapi_Entry *e, const char *type, Slapi_Value **val
|
||||
|
||||
attr_delete( &e->e_attrs, ad );
|
||||
|
||||
rc = bvptr2obj( vals, &bv );
|
||||
rc = bvptr2obj( vals, &bv, NULL );
|
||||
if ( rc != LDAP_SUCCESS ) {
|
||||
return -1;
|
||||
}
|
||||
@ -1350,7 +1354,7 @@ slapi_send_ldap_result(
|
||||
if ( pb->pb_op->o_tag == LDAP_REQ_SEARCH )
|
||||
rs->sr_nentries = nentries;
|
||||
if ( urls != NULL )
|
||||
bvptr2obj( urls, &rs->sr_ref );
|
||||
bvptr2obj( urls, &rs->sr_ref, NULL );
|
||||
|
||||
send_ldap_result( pb->pb_op, rs );
|
||||
|
||||
@ -1429,7 +1433,7 @@ slapi_send_ldap_search_reference(
|
||||
rs.sr_matched = NULL;
|
||||
rs.sr_text = NULL;
|
||||
|
||||
rc = bvptr2obj( references, &rs.sr_ref );
|
||||
rc = bvptr2obj( references, &rs.sr_ref, NULL );
|
||||
if ( rc != LDAP_SUCCESS ) {
|
||||
return rc;
|
||||
}
|
||||
@ -1440,7 +1444,7 @@ slapi_send_ldap_search_reference(
|
||||
rs.sr_entry = e;
|
||||
|
||||
if ( v2refs != NULL ) {
|
||||
rc = bvptr2obj( v2refs, &rs.sr_v2ref );
|
||||
rc = bvptr2obj( v2refs, &rs.sr_v2ref, NULL );
|
||||
if ( rc != LDAP_SUCCESS ) {
|
||||
slapi_ch_free( (void **)&rs.sr_ref );
|
||||
return rc;
|
||||
|
@ -2567,6 +2567,7 @@ syncrepl_updateCookie(
|
||||
mod[0].sml_type = mod[0].sml_desc->ad_cname;
|
||||
mod[0].sml_values = NULL;
|
||||
mod[0].sml_nvalues = NULL;
|
||||
mod[0].sml_numvals = 0;
|
||||
mod[0].sml_next = &mod[1];
|
||||
|
||||
mod[1].sml_op = LDAP_MOD_ADD;
|
||||
@ -2574,6 +2575,7 @@ syncrepl_updateCookie(
|
||||
mod[1].sml_type = mod[0].sml_desc->ad_cname;
|
||||
mod[1].sml_values = NULL;
|
||||
mod[1].sml_nvalues = NULL;
|
||||
mod[1].sml_numvals = 0;
|
||||
mod[1].sml_next = NULL;
|
||||
|
||||
ldap_pvt_thread_mutex_lock( &si->si_cookieState->cs_mutex );
|
||||
@ -2589,8 +2591,10 @@ syncrepl_updateCookie(
|
||||
si->si_cookieState->cs_vals[j].bv_val, len ) > 0 ) {
|
||||
ber_bvarray_add_x( &mod[0].sml_values,
|
||||
&si->si_cookieState->cs_vals[j], op->o_tmpmemctx );
|
||||
mod[0].sml_numvals++;
|
||||
ber_bvarray_add_x( &mod[1].sml_values,
|
||||
&syncCookie->ctxcsn[i], op->o_tmpmemctx );
|
||||
mod[1].sml_numvals++;
|
||||
if ( BER_BVISNULL( &first ))
|
||||
first = syncCookie->ctxcsn[i];
|
||||
}
|
||||
@ -2600,6 +2604,7 @@ syncrepl_updateCookie(
|
||||
if ( j == si->si_cookieState->cs_num ) {
|
||||
ber_bvarray_add_x( &mod[1].sml_values,
|
||||
&syncCookie->ctxcsn[i], op->o_tmpmemctx );
|
||||
mod[1].sml_numvals++;
|
||||
if ( BER_BVISNULL( &first ))
|
||||
first = syncCookie->ctxcsn[i];
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user