X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=servers%2Fslapd%2Foverlays%2Fcollect.c;h=2fc08ed4135d2d5c59502807bf36d998d245e061;hb=8eecc9a017584ea0b56b25f0e4750e3b16929de6;hp=f98040c5ebce1b7647dd4be125550eab2309bffc;hpb=4af9eb971559e3a1f0432615e93ec870dc753ddb;p=openldap diff --git a/servers/slapd/overlays/collect.c b/servers/slapd/overlays/collect.c index f98040c5eb..2fc08ed413 100644 --- a/servers/slapd/overlays/collect.c +++ b/servers/slapd/overlays/collect.c @@ -2,7 +2,7 @@ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * - * Copyright 2003-2009 The OpenLDAP Foundation. + * Copyright 2003-2011 The OpenLDAP Foundation. * Portions Copyright 2003 Howard Chu. * All rights reserved. * @@ -49,6 +49,28 @@ typedef struct collect_info { AttributeDescription *ci_ad[1]; } collect_info; +static int collect_cf( ConfigArgs *c ); + +static ConfigTable collectcfg[] = { + { "collectinfo", "dn> on_bi.bi_private taking into account * order. this means longer dn's (i.e. more specific dn's) will be found @@ -72,7 +94,7 @@ insert_ordered( slap_overinst *on, collect_info *ci ) { ci->ci_next = NULL; } found = 1; - } else if (find->ci_dn.bv_len <= ci->ci_dn.bv_len) { + } else if (find->ci_dn.bv_len < ci->ci_dn.bv_len) { /* insert into list here */ if (prev == NULL) { /* entry is head of list */ @@ -151,7 +173,11 @@ collect_cf( ConfigArgs *c ) collect_info **cip, *ci; int i; cip = (collect_info **)&on->on_bi.bi_private; - for ( i=0; i <= c->valx; i++, cip = &ci->ci_next ) ci = *cip; + ci = *cip; + for ( i=0; i < c->valx; i++ ) { + cip = &ci->ci_next; + ci = *cip; + } *cip = ci->ci_next; ch_free( ci->ci_dn.bv_val ); ch_free( ci ); @@ -174,10 +200,6 @@ collect_cf( ConfigArgs *c ) arg = strtok(NULL, ","); } - /* allocate config info with room for attribute array */ - ci = ch_malloc( sizeof( collect_info ) + - sizeof( AttributeDescription * ) * count ); - /* validate and normalize dn */ ber_str2bv( c->argv[1], 0, 0, &bv ); if ( dnNormalize( 0, NULL, NULL, &bv, &dn, NULL ) ) { @@ -188,6 +210,30 @@ collect_cf( ConfigArgs *c ) return ARG_BAD_CONF; } + /* check for duplicate DNs */ + for ( ci = (collect_info *)on->on_bi.bi_private; ci; + ci = ci->ci_next ) { + /* If new DN is longest, there are no possible matches */ + if ( dn.bv_len > ci->ci_dn.bv_len ) { + ci = NULL; + break; + } + if ( bvmatch( &dn, &ci->ci_dn )) { + break; + } + } + if ( ci ) { + snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s DN already configured: \"%s\"", + c->argv[0], c->argv[1] ); + Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE, + "%s: %s\n", c->log, c->cr_msg, 0 ); + return ARG_BAD_CONF; + } + + /* allocate config info with room for attribute array */ + ci = ch_malloc( sizeof( collect_info ) + + sizeof( AttributeDescription * ) * count ); + /* load attribute description for attribute list */ arg = c->argv[2]; for( idx=0; idxargv[0], arg); Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE, "%s: %s\n", c->log, c->cr_msg, 0 ); + ch_free( ci ); return ARG_BAD_CONF; } while(*arg!='\0') { @@ -219,31 +266,34 @@ collect_cf( ConfigArgs *c ) /* creates list of ci's ordered by dn length */ insert_ordered ( on, ci ); + /* New ci wasn't simply appended to end, adjust its + * position in the config entry's a_vals + */ + if ( c->ca_entry && ci->ci_next ) { + Attribute *a = attr_find( c->ca_entry->e_attrs, + collectcfg[0].ad ); + if ( a ) { + struct berval bv, nbv; + collect_info *c2 = (collect_info *)on->on_bi.bi_private; + int i, j; + for ( i=0; c2 != ci; i++, c2 = c2->ci_next ); + bv = a->a_vals[a->a_numvals-1]; + nbv = a->a_nvals[a->a_numvals-1]; + for ( j=a->a_numvals-1; j>i; j-- ) { + a->a_vals[j] = a->a_vals[j-1]; + a->a_nvals[j] = a->a_nvals[j-1]; + } + a->a_vals[j] = bv; + a->a_nvals[j] = nbv; + } + } + rc = 0; } } return rc; } -static ConfigTable collectcfg[] = { - { "collectinfo", "dn> sr_flags & REP_ENTRY_MODIFIABLE )) { - rs->sr_entry = entry_dup( rs->sr_entry ); - rs->sr_flags |= REP_ENTRY_MODIFIABLE | - REP_ENTRY_MUSTBEFREED; - } + rs_entry2modifiable( op, rs, on ); /* Loop for each attribute in this collectinfo */ for(idx=0; idxci_ad_num; idx++) {