From 9f054b648b337ff63b0aca19c59ed959672503b1 Mon Sep 17 00:00:00 2001 From: Howard Chu Date: Thu, 14 Sep 2006 00:06:04 +0000 Subject: [PATCH] Support dynamic add/delete of attributeTypes and objectClasses --- servers/slapd/at.c | 181 +++++++++++++++++++++++++++--------- servers/slapd/bconfig.c | 133 ++++++++++++++++++++++---- servers/slapd/oc.c | 155 ++++++++++++++++++++++++++---- servers/slapd/proto-slap.h | 11 ++- servers/slapd/schema_prep.c | 4 +- servers/slapd/schemaparse.c | 10 +- servers/slapd/slap.h | 2 + 7 files changed, 404 insertions(+), 92 deletions(-) diff --git a/servers/slapd/at.c b/servers/slapd/at.c index 104aa5a7c9..2f5c57d700 100644 --- a/servers/slapd/at.c +++ b/servers/slapd/at.c @@ -110,9 +110,13 @@ at_bvfind( struct berval *name ) air = avl_find( attr_index, name, attr_index_name_cmp ); - if ( air && ( slapMode & SLAP_TOOL_MODE ) && at_oc_cache ) { - avl_insert( &attr_cache, (caddr_t) air, - attr_index_cmp, avl_dup_error ); + if ( air ) { + if ( air->air_at->sat_flags & SLAP_AT_DELETED ) { + air = NULL; + } else if (( slapMode & SLAP_TOOL_MODE ) && at_oc_cache ) { + avl_insert( &attr_cache, (caddr_t) air, + attr_index_cmp, avl_dup_error ); + } } return air != NULL ? air->air_at : NULL; @@ -204,46 +208,96 @@ at_find_in_list( return -1; } -void -at_destroy( void ) +static void +at_delete_names( AttributeType *at ) { - AttributeType *a; - avl_free(attr_index, ldap_memfree); + char **names = at->sat_names; + + while (*names) { + struct aindexrec tmpair, *air; + + ber_str2bv( *names, 0, 0, &tmpair.air_name ); + tmpair.air_at = at; + air = (struct aindexrec *)avl_delete( &attr_index, + (caddr_t)&tmpair, attr_index_cmp ); + assert( air != NULL ); + ldap_memfree( air ); + names++; + } +} - while( !LDAP_STAILQ_EMPTY(&attr_list) ) { - a = LDAP_STAILQ_FIRST(&attr_list); - LDAP_STAILQ_REMOVE_HEAD(&attr_list, sat_next); +/* Mark the attribute as deleted, remove from list, and remove all its + * names from the AVL tree. Leave the OID in the tree. + */ +int +at_delete( AttributeType *at ) +{ + at->sat_flags |= SLAP_AT_DELETED; - if ( a->sat_equality ) { - MatchingRule *mr; + LDAP_STAILQ_REMOVE(&attr_list,at,slap_attribute_type,sat_next); - mr = mr_find( a->sat_equality->smr_oid ); - assert( mr != NULL ); - if ( mr != a->sat_equality ) { - ch_free( a->sat_equality ); - a->sat_equality = NULL; - } + at_delete_names( at ); + + return 0; +} + +static void +at_clean( AttributeType *a ) +{ + if ( a->sat_equality ) { + MatchingRule *mr; + + mr = mr_find( a->sat_equality->smr_oid ); + assert( mr != NULL ); + if ( mr != a->sat_equality ) { + ch_free( a->sat_equality ); + a->sat_equality = NULL; } + } - assert( a->sat_syntax != NULL ); - if ( a->sat_syntax != NULL ) { - Syntax *syn; + assert( a->sat_syntax != NULL ); + if ( a->sat_syntax != NULL ) { + Syntax *syn; - syn = syn_find( a->sat_syntax->ssyn_oid ); - assert( syn != NULL ); - if ( syn != a->sat_syntax ) { - ch_free( a->sat_syntax ); - a->sat_syntax = NULL; - } + syn = syn_find( a->sat_syntax->ssyn_oid ); + assert( syn != NULL ); + if ( syn != a->sat_syntax ) { + ch_free( a->sat_syntax ); + a->sat_syntax = NULL; } + } + + if ( a->sat_oidmacro ) ldap_memfree( a->sat_oidmacro ); + if ( a->sat_subtypes ) ldap_memfree( a->sat_subtypes ); +} + +static void +at_destroy_one( void *v ) +{ + struct aindexrec *air = v; + AttributeType *a = air->air_at; + + at_clean( a ); + ad_destroy(a->sat_ad); + ldap_pvt_thread_mutex_destroy(&a->sat_ad_mutex); + ldap_attributetype_free((LDAPAttributeType *)a); + ldap_memfree(air); +} - if ( a->sat_oidmacro ) ldap_memfree( a->sat_oidmacro ); - if ( a->sat_subtypes ) ldap_memfree( a->sat_subtypes ); - ad_destroy(a->sat_ad); - ldap_pvt_thread_mutex_destroy(&a->sat_ad_mutex); - ldap_attributetype_free((LDAPAttributeType *)a); +void +at_destroy( void ) +{ + AttributeType *a; + + while( !LDAP_STAILQ_EMPTY(&attr_list) ) { + a = LDAP_STAILQ_FIRST(&attr_list); + LDAP_STAILQ_REMOVE_HEAD(&attr_list, sat_next); + + at_delete_names( a ); } + avl_free(attr_index, at_destroy_one); + if ( slap_schema.si_at_undefined ) { ad_destroy(slap_schema.si_at_undefined->sat_ad); } @@ -338,36 +392,72 @@ at_check_dup( return SLAP_SCHERR_ATTR_DUP; } +static struct aindexrec *air_old; + +static int +at_dup_error( void *left, void *right ) +{ + air_old = left; + return -1; +} static int at_insert( - AttributeType *sat, + AttributeType **rat, + AttributeType *prev, const char **err ) { struct aindexrec *air; char **names = NULL; - + AttributeType *sat = *rat; if ( sat->sat_oid ) { air = (struct aindexrec *) ch_calloc( 1, sizeof(struct aindexrec) ); ber_str2bv( sat->sat_oid, 0, 0, &air->air_name ); air->air_at = sat; + air_old = NULL; + if ( avl_insert( &attr_index, (caddr_t) air, - attr_index_cmp, avl_dup_error ) ) + attr_index_cmp, at_dup_error ) ) { AttributeType *old_sat; int rc; *err = sat->sat_oid; - old_sat = at_bvfind( &air->air_name ); - assert( old_sat != NULL ); - rc = at_check_dup( old_sat, sat ); + assert( air_old != NULL ); + old_sat = air_old->air_at; + + /* replacing a deleted definition? */ + if ( old_sat->sat_flags & SLAP_AT_DELETED ) { + AttributeType tmp; + + /* Keep old oid, free new oid; + * Keep old ads, free new ads; + * Keep new everything else, free old + */ + tmp = *old_sat; + *old_sat = *sat; + old_sat->sat_oid = tmp.sat_oid; + tmp.sat_oid = sat->sat_oid; + old_sat->sat_ad = tmp.sat_ad; + tmp.sat_ad = sat->sat_ad; + *sat = tmp; + + at_clean( sat ); + at_destroy_one( air ); + + air = air_old; + sat = old_sat; + *rat = sat; + } else { + ldap_memfree( air ); - ldap_memfree( air ); + rc = at_check_dup( old_sat, sat ); - return rc; + return rc; + } } /* FIX: temporal consistency check */ at_bvfind( &air->air_name ); @@ -437,7 +527,11 @@ at_insert( } } - LDAP_STAILQ_INSERT_TAIL( &attr_list, sat, sat_next ); + if ( prev ) { + LDAP_STAILQ_INSERT_AFTER( &attr_list, prev, sat, sat_next ); + } else { + LDAP_STAILQ_INSERT_TAIL( &attr_list, sat, sat_next ); + } return 0; } @@ -447,6 +541,7 @@ at_add( LDAPAttributeType *at, int user, AttributeType **rsat, + AttributeType *prev, const char **err ) { AttributeType *sat = NULL; @@ -769,7 +864,7 @@ at_add( sat->sat_substr = mr; } - code = at_insert( sat, err ); + code = at_insert( &sat, prev, err ); if ( code != 0 ) { error_return:; if ( sat ) { @@ -909,7 +1004,7 @@ register_at( char *def, AttributeDescription **rad, int dupok ) return code; } - code = at_add( at, 0, NULL, &err ); + code = at_add( at, 0, NULL, NULL, &err ); if ( code ) { if ( code == SLAP_SCHERR_ATTR_DUP && dupok ) { freeit = 1; diff --git a/servers/slapd/bconfig.c b/servers/slapd/bconfig.c index 0ed3bc41b6..da5986fc58 100644 --- a/servers/slapd/bconfig.c +++ b/servers/slapd/bconfig.c @@ -259,7 +259,7 @@ static ConfigTable config_back_cf_table[] = { "EQUALITY caseIgnoreMatch " "SYNTAX OMsDirectoryString )", NULL, NULL }, { "attribute", "attribute", 2, 0, STRLENOF( "attribute" ), - ARG_PAREN|ARG_MAGIC|CFG_ATTR|ARG_NO_DELETE|ARG_NO_INSERT, + ARG_PAREN|ARG_MAGIC|CFG_ATTR, &config_generic, "( OLcfgGlAt:4 NAME 'olcAttributeTypes' " "DESC 'OpenLDAP attributeTypes' " "EQUALITY caseIgnoreMatch " @@ -387,7 +387,7 @@ static ConfigTable config_back_cf_table[] = { ARG_MAGIC|CFG_MONITORING|ARG_DB|ARG_ON_OFF, &config_generic, "( OLcfgDbAt:0.18 NAME 'olcMonitoring' " "SYNTAX OMsBoolean SINGLE-VALUE )", NULL, NULL }, - { "objectclass", "objectclass", 2, 0, 0, ARG_PAREN|ARG_MAGIC|CFG_OC|ARG_NO_DELETE|ARG_NO_INSERT, + { "objectclass", "objectclass", 2, 0, 0, ARG_PAREN|ARG_MAGIC|CFG_OC, &config_generic, "( OLcfgGlAt:32 NAME 'olcObjectClasses' " "DESC 'OpenLDAP object classes' " "EQUALITY caseIgnoreMatch " @@ -1108,6 +1108,49 @@ config_generic(ConfigArgs *c) { } break; + case CFG_OC: { + CfEntryInfo *ce = c->ca_entry->e_private; + /* can't modify the hardcoded schema */ + if ( ce->ce_parent->ce_type == Cft_Global ) + return 1; + } + break; + + case CFG_ATTR: { + CfEntryInfo *ce = c->ca_entry->e_private; + /* can't modify the hardcoded schema */ + if ( ce->ce_parent->ce_type == Cft_Global ) + return 1; + } + cfn = c->private; + if ( c->valx < 0 ) { + AttributeType *at; + + for( at = cfn->c_at_head; at; at_next( &at )) { + at_delete( at ); + if ( at == cfn->c_at_tail ) + break; + } + cfn->c_at_head = cfn->c_at_tail = NULL; + } else { + AttributeType *at, *prev = NULL; + int i; + + for ( i=0, at=cfn->c_at_head; ivalx; i++) { + prev = at; + at_next( &at ); + } + at_delete( at ); + if ( cfn->c_at_tail == at ) { + cfn->c_at_tail = prev; + } + if ( cfn->c_at_head == at ) { + at_next( &at ); + cfn->c_at_head = at; + } + } + break; + case CFG_LIMITS: /* FIXME: there is no limits_free function */ case CFG_ATOPT: @@ -1116,9 +1159,7 @@ config_generic(ConfigArgs *c) { /* FIXME: there is no way to remove attributes added by a DSE file */ case CFG_OID: - case CFG_OC: case CFG_DIT: - case CFG_ATTR: case CFG_MODPATH: default: rc = 1; @@ -1243,6 +1284,8 @@ config_generic(ConfigArgs *c) { case CFG_OID: { OidMacro *om; + if ( c->op == LDAP_MOD_ADD && c->private && cfn != c->private ) + cfn = c->private; if(parse_oidm(c->fname, c->lineno, c->argc, c->argv, 1, &om)) return(1); if (!cfn->c_om_head) cfn->c_om_head = om; @@ -1251,32 +1294,80 @@ config_generic(ConfigArgs *c) { break; case CFG_OC: { - ObjectClass *oc; + ObjectClass *oc, *prev; - if(parse_oc(c->fname, c->lineno, p, c->argv, &oc)) return(1); + if ( c->op == LDAP_MOD_ADD && c->private && cfn != c->private ) + cfn = c->private; + if ( c->valx < 0 ) { + prev = cfn->c_oc_tail; + } else { + prev = NULL; + /* If adding anything after the first, prev is easy */ + if ( c->valx ) { + int i; + for (i=0, oc = cfn->c_oc_head; ivalx; i++) { + prev = oc; + oc_next( &oc ); + } + } else + /* If adding the first, and head exists, find its prev */ + if (cfn->c_oc_head) { + for ( oc_start( &oc ); oc != cfn->c_oc_head; ) { + prev = oc; + oc_next( &oc ); + } + } + /* else prev is NULL, append to end of global list */ + } + if(parse_oc(c->fname, c->lineno, p, c->argv, &oc, prev)) return(1); if (!cfn->c_oc_head) cfn->c_oc_head = oc; - cfn->c_oc_tail = oc; + if (cfn->c_oc_tail == prev) cfn->c_oc_tail = oc; + } + break; + + case CFG_ATTR: { + AttributeType *at, *prev; + + if ( c->op == LDAP_MOD_ADD && c->private && cfn != c->private ) + cfn = c->private; + if ( c->valx < 0 ) { + prev = cfn->c_at_tail; + } else { + prev = NULL; + /* If adding anything after the first, prev is easy */ + if ( c->valx ) { + int i; + for (i=0, at = cfn->c_at_head; ivalx; i++) { + prev = at; + at_next( &at ); + } + } else + /* If adding the first, and head exists, find its prev */ + if (cfn->c_at_head) { + for ( at_start( &at ); at != cfn->c_at_head; ) { + prev = at; + at_next( &at ); + } + } + /* else prev is NULL, append to end of global list */ + } + if(parse_at(c->fname, c->lineno, p, c->argv, &at, prev)) return(1); + if (!cfn->c_at_head) cfn->c_at_head = at; + if (cfn->c_at_tail == prev) cfn->c_at_tail = at; } break; case CFG_DIT: { ContentRule *cr; + if ( c->op == LDAP_MOD_ADD && c->private && cfn != c->private ) + cfn = c->private; if(parse_cr(c->fname, c->lineno, p, c->argv, &cr)) return(1); if (!cfn->c_cr_head) cfn->c_cr_head = cr; cfn->c_cr_tail = cr; } break; - case CFG_ATTR: { - AttributeType *at; - - if(parse_at(c->fname, c->lineno, p, c->argv, &at)) return(1); - if (!cfn->c_at_head) cfn->c_at_head = at; - cfn->c_at_tail = at; - } - break; - case CFG_ATOPT: ad_define_option(NULL, NULL, 0); for(i = 1; i < c->argc; i++) @@ -1388,6 +1479,8 @@ config_generic(ConfigArgs *c) { { struct berval bv; ber_str2bv( c->argv[1], 0, 1, &bv ); + if ( c->op == LDAP_MOD_ADD && c->private && cfn != c->private ) + cfn = c->private; ber_bvarray_add( &cfn->c_dseFiles, &bv ); } break; @@ -3416,7 +3509,7 @@ check_vals( ConfigTable *ct, ConfigArgs *ca, void *ptr, int isAttr ) AttributeDescription *ad; BerVarray vals; - int i, rc = 0, sort = 0; + int i, rc = 0; if ( isAttr ) { a = ptr; @@ -3429,7 +3522,6 @@ check_vals( ConfigTable *ct, ConfigArgs *ca, void *ptr, int isAttr ) } if ( a && ( ad->ad_type->sat_flags & SLAP_AT_ORDERED_VAL )) { - sort = 1; rc = ordered_value_sort( a, 1 ); if ( rc ) { snprintf(ca->msg, sizeof( ca->msg ), "ordered_value_sort failed on attr %s\n", @@ -3439,7 +3531,7 @@ check_vals( ConfigTable *ct, ConfigArgs *ca, void *ptr, int isAttr ) } for ( i=0; vals[i].bv_val; i++ ) { ca->line = vals[i].bv_val; - if ( sort ) { + if ( ad->ad_type->sat_flags & SLAP_AT_ORDERED_VAL ) { char *idx = strchr( ca->line, '}' ); if ( idx ) ca->line = idx+1; } @@ -4169,8 +4261,9 @@ config_modify_internal( CfEntryInfo *ce, Operation *op, SlapReply *rs, if ( rc ) rc = LDAP_OTHER; } if ( ml->sml_values ) { + d = d->next; ch_free( dels ); - dels = d->next; + dels = d; } if ( ml->sml_op == LDAP_MOD_REPLACE ) { ml->sml_values = vals; diff --git a/servers/slapd/oc.c b/servers/slapd/oc.c index 05411c7bc1..bbf7be86a3 100644 --- a/servers/slapd/oc.c +++ b/servers/slapd/oc.c @@ -386,23 +386,73 @@ oc_add_sups( return 0; } +static void +oc_delete_names( ObjectClass *oc ) +{ + char **names = oc->soc_names; + + while (*names) { + struct oindexrec tmpoir, *oir; + + ber_str2bv( *names, 0, 0, &tmpoir.oir_name ); + tmpoir.oir_oc = oc; + oir = (struct oindexrec *)avl_delete( &oc_index, + (caddr_t)&tmpoir, oc_index_cmp ); + assert( oir != NULL ); + ldap_memfree( oir ); + names++; + } +} + +/* Mark the ObjectClass as deleted, remove from list, and remove all its + * names from the AVL tree. Leave the OID in the tree. + */ +int +oc_delete( ObjectClass *oc ) +{ + oc->soc_flags |= SLAP_OC_DELETED; + + LDAP_STAILQ_REMOVE(&oc_list,oc,slap_object_class,soc_next); + + oc_delete_names( oc ); + + return 0; +} + +static void +oc_clean( ObjectClass *o ) +{ + if (o->soc_sups) ldap_memfree(o->soc_sups); + if (o->soc_required) ldap_memfree(o->soc_required); + if (o->soc_allowed) ldap_memfree(o->soc_allowed); + if (o->soc_oidmacro) ldap_memfree(o->soc_oidmacro); +} + +static void +oc_destroy_one( void *v ) +{ + struct oindexrec *oir = v; + ObjectClass *o = oir->oir_oc; + + oc_clean( o ); + ldap_objectclass_free((LDAPObjectClass *)o); + ldap_memfree(oir); +} + void oc_destroy( void ) { ObjectClass *o; - avl_free(oc_index, ldap_memfree); while( !LDAP_STAILQ_EMPTY(&oc_list) ) { o = LDAP_STAILQ_FIRST(&oc_list); LDAP_STAILQ_REMOVE_HEAD(&oc_list, soc_next); - if (o->soc_sups) ldap_memfree(o->soc_sups); - if (o->soc_required) ldap_memfree(o->soc_required); - if (o->soc_allowed) ldap_memfree(o->soc_allowed); - if (o->soc_oidmacro) ldap_memfree(o->soc_oidmacro); - ldap_objectclass_free((LDAPObjectClass *)o); + oc_delete_names( o ); } + avl_free( oc_index, oc_destroy_one ); + while( !LDAP_STAILQ_EMPTY(&oc_undef_list) ) { o = LDAP_STAILQ_FIRST(&oc_undef_list); LDAP_STAILQ_REMOVE_HEAD(&oc_undef_list, soc_next); @@ -411,6 +461,40 @@ oc_destroy( void ) } } +int +oc_start( ObjectClass **oc ) +{ + assert( oc != NULL ); + + *oc = LDAP_STAILQ_FIRST(&oc_list); + + return (*oc != NULL); +} + +int +oc_next( ObjectClass **oc ) +{ + assert( oc != NULL ); + +#if 1 /* pedantic check */ + { + ObjectClass *tmp = NULL; + + LDAP_STAILQ_FOREACH(tmp,&oc_list,soc_next) { + if ( tmp == *oc ) { + break; + } + } + + assert( tmp != NULL ); + } +#endif + + *oc = LDAP_STAILQ_NEXT(*oc,soc_next); + + return (*oc != NULL); +} + /* * check whether the two ObjectClasses actually __are__ identical, * or rather inconsistent @@ -462,38 +546,68 @@ oc_check_dup( return SLAP_SCHERR_CLASS_DUP; } +static struct oindexrec *oir_old; + +static int +oc_dup_error( void *left, void *right ) +{ + oir_old = left; + return -1; +} + static int oc_insert( - ObjectClass *soc, + ObjectClass **roc, + ObjectClass *prev, const char **err ) { struct oindexrec *oir; char **names; + ObjectClass *soc = *roc; if ( soc->soc_oid ) { oir = (struct oindexrec *) ch_calloc( 1, sizeof(struct oindexrec) ); - oir->oir_name.bv_val = soc->soc_oid; - oir->oir_name.bv_len = strlen( soc->soc_oid ); + ber_str2bv( soc->soc_oid, 0, 0, &oir->oir_name ); oir->oir_oc = soc; - - assert( oir->oir_name.bv_val != NULL ); - assert( oir->oir_oc != NULL ); + oir_old = NULL; if ( avl_insert( &oc_index, (caddr_t) oir, - oc_index_cmp, avl_dup_error ) ) + oc_index_cmp, oc_dup_error ) ) { ObjectClass *old_soc; int rc; *err = soc->soc_oid; - old_soc = oc_bvfind( &oir->oir_name ); - assert( old_soc != NULL ); - rc = oc_check_dup( old_soc, soc ); + assert( oir_old != NULL ); + old_soc = oir_old->oir_oc; + + /* replacing a deleted definition? */ + if ( old_soc->soc_flags & SLAP_OC_DELETED ) { + ObjectClass tmp; + + /* Keep old oid, free new oid; + * Keep new everything else, free old + */ + tmp = *old_soc; + *old_soc = *soc; + old_soc->soc_oid = tmp.soc_oid; + tmp.soc_oid = soc->soc_oid; + *soc = tmp; + + oc_clean( soc ); + oc_destroy_one( oir ); + + oir = oir_old; + soc = old_soc; + *roc = soc; + } else { + rc = oc_check_dup( old_soc, soc ); - ldap_memfree( oir ); - return rc; + ldap_memfree( oir ); + return rc; + } } /* FIX: temporal consistency check */ @@ -567,6 +681,7 @@ oc_add( LDAPObjectClass *oc, int user, ObjectClass **rsoc, + ObjectClass *prev, const char **err ) { ObjectClass *soc; @@ -646,7 +761,7 @@ oc_add( soc->soc_flags |= SLAP_OC_HARDCODE; } - code = oc_insert(soc,err); + code = oc_insert(&soc,prev,err); done:; if ( code != 0 ) { if ( soc->soc_sups ) { @@ -770,7 +885,7 @@ register_oc( char *def, ObjectClass **soc, int dupok ) def, ldap_scherr2str(code), err ); return code; } - code = oc_add(oc,0,NULL,&err); + code = oc_add(oc,0,NULL,NULL,&err); if ( code && ( code != SLAP_SCHERR_CLASS_DUP || !dupok )) { Debug( LDAP_DEBUG_ANY, "register_oc: objectclass \"%s\": %s, %s\n", diff --git a/servers/slapd/proto-slap.h b/servers/slapd/proto-slap.h index 0d48e5118b..ccf21d146a 100644 --- a/servers/slapd/proto-slap.h +++ b/servers/slapd/proto-slap.h @@ -217,7 +217,7 @@ LDAP_SLAPD_F (int) at_delete_from_list LDAP_P(( LDAP_SLAPD_F (int) at_schema_info LDAP_P(( Entry *e )); LDAP_SLAPD_F (int) at_add LDAP_P(( LDAPAttributeType *at, int user, - AttributeType **sat, const char **err )); + AttributeType **sat, AttributeType *prev, const char **err )); LDAP_SLAPD_F (void) at_destroy LDAP_P(( void )); LDAP_SLAPD_F (int) is_at_subtype LDAP_P(( @@ -1187,6 +1187,7 @@ LDAP_SLAPD_F (int) oc_add LDAP_P(( LDAPObjectClass *oc, int user, ObjectClass **soc, + ObjectClass *prev, const char **err)); LDAP_SLAPD_F (void) oc_destroy LDAP_P(( void )); @@ -1238,6 +1239,10 @@ LDAP_SLAPD_F (int) is_entry_objectclass LDAP_P(( : is_entry_objectclass((e), slap_schema.si_oc_syncConsumerSubentry, SLAP_OCF_SET_FLAGS)) LDAP_SLAPD_F (int) oc_schema_info( Entry *e ); + +LDAP_SLAPD_F (int) oc_start LDAP_P(( ObjectClass **at )); +LDAP_SLAPD_F (int) oc_next LDAP_P(( ObjectClass **at )); + LDAP_SLAPD_F (void) oc_unparse LDAP_P(( BerVarray *bva, ObjectClass *start, ObjectClass *end, int system )); @@ -1565,10 +1570,10 @@ LDAP_SLAPD_F (int) parse_cr LDAP_P(( ContentRule **scr )); LDAP_SLAPD_F (int) parse_oc LDAP_P(( const char *fname, int lineno, char *line, char **argv, - ObjectClass **soc )); + ObjectClass **soc, ObjectClass *prev )); LDAP_SLAPD_F (int) parse_at LDAP_P(( const char *fname, int lineno, char *line, char **argv, - AttributeType **sat )); + AttributeType **sat, AttributeType *prev )); LDAP_SLAPD_F (char *) scherr2str LDAP_P((int code)) LDAP_GCCATTR((const)); LDAP_SLAPD_F (int) dscompare LDAP_P(( const char *s1, const char *s2del, char delim )); diff --git a/servers/slapd/schema_prep.c b/servers/slapd/schema_prep.c index 85717e2c04..5bc607d3f1 100644 --- a/servers/slapd/schema_prep.c +++ b/servers/slapd/schema_prep.c @@ -1195,7 +1195,7 @@ slap_schema_load( void ) return LDAP_OTHER; } - code = at_add( at, 0, NULL, &err ); + code = at_add( at, 0, NULL, NULL, &err ); if ( code ) { ldap_attributetype_free( at ); fprintf( stderr, "slap_schema_load: AttributeType " @@ -1311,7 +1311,7 @@ slap_schema_load( void ) return LDAP_OTHER; } - code = oc_add(oc,0,NULL,&err); + code = oc_add(oc,0,NULL,NULL,&err); if ( code ) { ldap_objectclass_free( oc ); fprintf( stderr, "slap_schema_load: ObjectClass " diff --git a/servers/slapd/schemaparse.c b/servers/slapd/schemaparse.c index f802f1ad59..e00d3af70e 100644 --- a/servers/slapd/schemaparse.c +++ b/servers/slapd/schemaparse.c @@ -176,7 +176,8 @@ parse_oc( int lineno, char *line, char **argv, - ObjectClass **soc ) + ObjectClass **soc, + ObjectClass *prev ) { LDAPObjectClass *oc; int code; @@ -199,7 +200,7 @@ parse_oc( goto done; } - code = oc_add( oc, 1, soc, &err ); + code = oc_add( oc, 1, soc, prev, &err ); if ( code ) { fprintf( stderr, "%s: line %d: %s: \"%s\"\n", fname, lineno, scherr2str( code ), err ); @@ -267,7 +268,8 @@ parse_at( int lineno, char *line, char **argv, - AttributeType **sat ) + AttributeType **sat, + AttributeType *prev ) { LDAPAttributeType *at; int code; @@ -298,7 +300,7 @@ parse_at( goto done; } - code = at_add( at, 1, sat, &err); + code = at_add( at, 1, sat, prev, &err); if ( code ) { fprintf( stderr, "%s: line %d: %s: \"%s\"\n", fname, lineno, scherr2str(code), err); diff --git a/servers/slapd/slap.h b/servers/slapd/slap.h index dc28fc8c8f..d63eb0ae41 100644 --- a/servers/slapd/slap.h +++ b/servers/slapd/slap.h @@ -662,6 +662,7 @@ typedef struct slap_attribute_type { #define SLAP_AT_ORDERED 0x0003U /* value has order index */ #define SLAP_AT_HARDCODE 0x10000U /* hardcoded schema */ +#define SLAP_AT_DELETED 0x20000U slap_mask_t sat_flags; @@ -744,6 +745,7 @@ typedef struct slap_object_class { #define SLAP_OC_HIDE 0x8000 #endif #define SLAP_OC_HARDCODE 0x10000U /* This is hardcoded schema */ +#define SLAP_OC_DELETED 0x20000U /* * DIT content rule -- 2.39.5