Exemplo n.º 1
0
int
modify_delete_values(
	Entry	*e,
	Modification	*m,
	int	perm,
	const char	**text,
	char *textbuf, size_t textlen )
{
	return modify_delete_vindex( e, m, perm, text, textbuf, textlen, NULL );
}
Exemplo n.º 2
0
/* This is a copy from slapd/mods.c, but with compaction tweaked
 * to swap values from the tail into deleted slots, to reduce the
 * overall update traffic.
 */
static int
ndb_modify_delete(
	Entry	*e,
	Modification	*mod,
	int	permissive,
	const char	**text,
	char *textbuf, size_t textlen,
	int *idx )
{
	Attribute	*a;
	MatchingRule 	*mr = mod->sm_desc->ad_type->sat_equality;
	struct berval *cvals;
	int		*id2 = NULL;
	int		i, j, rc = 0, num;
	unsigned flags;
	char		dummy = '\0';

	/* For ordered vals, we have no choice but to preserve order */
	if ( mod->sm_desc->ad_type->sat_flags & SLAP_AT_ORDERED_VAL )
		return modify_delete_vindex( e, mod, permissive, text,
			textbuf, textlen, idx );

	/*
	 * If permissive is set, then the non-existence of an 
	 * attribute is not treated as an error.
	 */

	/* delete the entire attribute */
	if ( mod->sm_values == NULL ) {
		rc = attr_delete( &e->e_attrs, mod->sm_desc );

		if( permissive ) {
			rc = LDAP_SUCCESS;
		} else if( rc != LDAP_SUCCESS ) {
			*text = textbuf;
			snprintf( textbuf, textlen,
				"modify/delete: %s: no such attribute",
				mod->sm_desc->ad_cname.bv_val );
			rc = LDAP_NO_SUCH_ATTRIBUTE;
		}
		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 = (int *)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 */
		*text = textbuf;
		snprintf( textbuf, textlen,
			"modify/delete: %s: no equality matching rule",
			mod->sm_desc->ad_cname.bv_val );
		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 ) {
			rc = LDAP_SUCCESS;
			goto return_result;
		}
		*text = textbuf;
		snprintf( textbuf, textlen,
			"modify/delete: %s: no such attribute",
			mod->sm_desc->ad_cname.bv_val );
		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++ ) {
		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;
			}
			*text = textbuf;
			snprintf( textbuf, textlen,
				"modify/delete: %s: no such value",
				mod->sm_desc->ad_cname.bv_val );
			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;
		}
	}

	num = a->a_numvals;

	/* 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 */
	for ( i=0; i<num; i++ ) {
		if ( a->a_vals[i].bv_val != &dummy )
			continue;
		for ( --num; num > i && a->a_vals[num].bv_val == &dummy; num-- )
			;
		a->a_vals[i] = a->a_vals[num];
		if ( a->a_nvals != a->a_vals )
			a->a_nvals[i] = a->a_nvals[num];
	}

	BER_BVZERO( &a->a_vals[num] );
	if (a->a_nvals != a->a_vals) {
		BER_BVZERO( &a->a_nvals[num] );
	}

	/* if no values remain, delete the entire attribute */
	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",
				mod->sm_desc->ad_cname.bv_val );
			rc = LDAP_NO_SUCH_ATTRIBUTE;
		}
	}
return_result:
	if ( id2 )
		ch_free( id2 );
	return rc;
}