X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=servers%2Fslapd%2Foc.c;h=c6b50fde48d25e702533a9edcff09f7e67186457;hb=6193ee4003a1aeb8d70b59b90e1ee242100b190e;hp=2772d72711fb99387701221a70809497753c91c4;hpb=de90dbbc52d34e1430f689d730e6bca126360518;p=openldap diff --git a/servers/slapd/oc.c b/servers/slapd/oc.c index 2772d72711..c6b50fde48 100644 --- a/servers/slapd/oc.c +++ b/servers/slapd/oc.c @@ -2,7 +2,7 @@ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * - * Copyright 1998-2005 The OpenLDAP Foundation. + * Copyright 1998-2006 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -135,6 +135,8 @@ static Avlnode *oc_cache = NULL; static LDAP_STAILQ_HEAD(OCList, slap_object_class) oc_list = LDAP_STAILQ_HEAD_INITIALIZER(oc_list); +ObjectClass *oc_sys_tail; + static int oc_index_cmp( const void *v_oir1, @@ -236,10 +238,10 @@ oc_bvfind_undef( struct berval *ocname ) static int oc_create_required( - ObjectClass *soc, - char **attrs, + ObjectClass *soc, + char **attrs, int *op, - const char **err ) + const char **err ) { char **attrs1; AttributeType *sat; @@ -267,7 +269,7 @@ oc_create_required( } /* Now delete duplicates from the allowed list */ for ( satp = soc->soc_required; *satp; satp++ ) { - i = at_find_in_list(*satp,soc->soc_allowed); + i = at_find_in_list(*satp, soc->soc_allowed); if ( i >= 0 ) { at_delete_from_list(i, &soc->soc_allowed); } @@ -312,10 +314,10 @@ oc_create_allowed( static int oc_add_sups( - ObjectClass *soc, - char **sups, + ObjectClass *soc, + char **sups, int *op, - const char **err ) + const char **err ) { int code; ObjectClass *soc1; @@ -386,23 +388,71 @@ 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. + */ +void +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 ); +} + +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 */ @@ -524,6 +638,30 @@ oc_insert( rc = oc_check_dup( old_soc, soc ); ldap_memfree( oir ); + + while ( names > soc->soc_names ) { + struct oindexrec tmpoir; + + names--; + ber_str2bv( *names, 0, 0, &tmpoir.oir_name ); + tmpoir.oir_oc = soc; + oir = (struct oindexrec *)avl_delete( &oc_index, + (caddr_t)&tmpoir, oc_index_cmp ); + assert( oir != NULL ); + ldap_memfree( oir ); + } + + if ( soc->soc_oid ) { + struct oindexrec tmpoir; + + ber_str2bv( soc->soc_oid, 0, 0, &tmpoir.oir_name ); + tmpoir.oir_oc = soc; + oir = (struct oindexrec *)avl_delete( &oc_index, + (caddr_t)&tmpoir, oc_index_cmp ); + assert( oir != NULL ); + ldap_memfree( oir ); + } + return rc; } @@ -533,7 +671,15 @@ oc_insert( names++; } } - LDAP_STAILQ_INSERT_TAIL( &oc_list, soc, soc_next ); + if ( soc->soc_flags & SLAP_OC_HARDCODE ) { + prev = oc_sys_tail; + oc_sys_tail = soc; + } + if ( prev ) { + LDAP_STAILQ_INSERT_AFTER( &oc_list, prev, soc, soc_next ); + } else { + LDAP_STAILQ_INSERT_TAIL( &oc_list, soc, soc_next ); + } return 0; } @@ -543,6 +689,7 @@ oc_add( LDAPObjectClass *oc, int user, ObjectClass **rsoc, + ObjectClass *prev, const char **err ) { ObjectClass *soc; @@ -594,22 +741,54 @@ oc_add( code = oc_add_sups( soc, soc->soc_sup_oids, &op, err ); } - if ( code != 0 ) return code; - if( user && op ) return SLAP_SCHERR_CLASS_BAD_SUP; + if ( code != 0 ) { + goto done; + } + + if ( user && op ) { + code = SLAP_SCHERR_CLASS_BAD_SUP; + goto done; + } code = oc_create_required( soc, soc->soc_at_oids_must, &op, err ); - if ( code != 0 ) return code; + if ( code != 0 ) { + goto done; + } code = oc_create_allowed( soc, soc->soc_at_oids_may, &op, err ); - if ( code != 0 ) return code; + if ( code != 0 ) { + goto done; + } + + if ( user && op ) { + code = SLAP_SCHERR_CLASS_BAD_USAGE; + goto done; + } + + if ( !user ) { + soc->soc_flags |= SLAP_OC_HARDCODE; + } + + code = oc_insert(&soc,prev,err); +done:; + if ( code != 0 ) { + if ( soc->soc_sups ) { + ch_free( soc->soc_sups ); + } + + if ( soc->soc_required ) { + ch_free( soc->soc_required ); + } - if( user && op ) return SLAP_SCHERR_CLASS_BAD_USAGE; + if ( soc->soc_allowed ) { + ch_free( soc->soc_allowed ); + } - if( !user ) soc->soc_flags |= SLAP_OC_HARDCODE; + ch_free( soc ); - code = oc_insert(soc,err); - if ( code == 0 && rsoc ) + } else if ( rsoc ) { *rsoc = soc; + } return code; } @@ -627,7 +806,7 @@ oc_unparse( BerVarray *res, ObjectClass *start, ObjectClass *end, int sys ) /* count the result size */ i = 0; for ( oc=start; oc; oc=LDAP_STAILQ_NEXT(oc, soc_next)) { - if ( sys && !(oc->soc_flags & SLAP_OC_HARDCODE)) continue; + if ( sys && !(oc->soc_flags & SLAP_OC_HARDCODE)) break; i++; if ( oc == end ) break; } @@ -644,7 +823,7 @@ oc_unparse( BerVarray *res, ObjectClass *start, ObjectClass *end, int sys ) i = 0; for ( oc=start; oc; oc=LDAP_STAILQ_NEXT(oc, soc_next)) { LDAPObjectClass loc, *locp; - if ( sys && !(oc->soc_flags & SLAP_OC_HARDCODE)) continue; + if ( sys && !(oc->soc_flags & SLAP_OC_HARDCODE)) break; if ( oc->soc_oidmacro ) { loc = oc->soc_oclass; loc.oc_oid = oc->soc_oidmacro; @@ -699,3 +878,35 @@ oc_schema_info( Entry *e ) } return 0; } + +int +register_oc( char *def, ObjectClass **soc, int dupok ) +{ + LDAPObjectClass *oc; + int code; + const char *err; + + oc = ldap_str2objectclass( def, &code, &err, LDAP_SCHEMA_ALLOW_ALL ); + if ( !oc ) { + Debug( LDAP_DEBUG_ANY, + "register_oc: objectclass \"%s\": %s, %s\n", + def, ldap_scherr2str(code), err ); + return code; + } + 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", + def, scherr2str(code), err ); + ldap_objectclass_free(oc); + return code; + } + if ( soc ) + *soc = oc_find(oc->oc_names[0]); + if ( code ) { + ldap_objectclass_free(oc); + } else { + ldap_memfree(oc); + } + return 0; +}