X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=servers%2Fslapd%2Fentry.c;h=bf59a51f1e4e37efa99fea69ea589dcb5f768e13;hb=0445405299ebc97d0f11585031fb1abef031caf9;hp=6d003b942820c946ae5bcf58f3a55685ecc7e6db;hpb=32601a6e6acb43496dffbaf12bf3fea5d7bf585c;p=openldap diff --git a/servers/slapd/entry.c b/servers/slapd/entry.c index 6d003b9428..bf59a51f1e 100644 --- a/servers/slapd/entry.c +++ b/servers/slapd/entry.c @@ -1,7 +1,7 @@ /* entry.c - routines for dealing with entries */ /* $OpenLDAP$ */ /* - * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. * COPYING RESTRICTIONS APPLY, see COPYRIGHT file */ @@ -16,9 +16,9 @@ #include "slap.h" -static unsigned char *ebuf; /* buf returned by entry2str */ +static unsigned char *ebuf; /* buf returned by entry2str */ static unsigned char *ecur; /* pointer to end of currently used ebuf */ -static int emaxsize;/* max size of ebuf */ +static int emaxsize;/* max size of ebuf */ int entry_destroy(void) { @@ -29,19 +29,19 @@ int entry_destroy(void) return 0; } + Entry * str2entry( char *s ) { + int rc; Entry *e; - Attribute **a; + Attribute **a = NULL; char *type; - char *value; - char *next; - ber_len_t vlen; - int nvals, maxvals; - struct berval bval; + struct berval value; struct berval *vals[2]; - char ptype[64]; + AttributeDescription *ad; + const char *text; + char *next; /* * LDIF is used as the string format. @@ -58,18 +58,26 @@ str2entry( char *s ) * or newline. */ +#ifdef NEW_LOGGING + LDAP_LOG(( "operation", LDAP_LEVEL_DETAIL1, + "str2entry: \"%s\"\n", s ? s : "NULL" )); +#else Debug( LDAP_DEBUG_TRACE, "=> str2entry\n", s ? s : "NULL", 0, 0 ); - - next = s; +#endif /* initialize reader/writer lock */ e = (Entry *) ch_malloc( sizeof(Entry) ); if( e == NULL ) { - Debug( LDAP_DEBUG_TRACE, +#ifdef NEW_LOGGING + LDAP_LOG(( "operation", LDAP_LEVEL_ERR, + "str2entry: entry allocation failed.\n" )); +#else + Debug( LDAP_DEBUG_ANY, "<= str2entry NULL (entry allocation failed)\n", 0, 0, 0 ); +#endif return( NULL ); } @@ -81,78 +89,177 @@ str2entry( char *s ) e->e_private = NULL; /* dn + attributes */ - vals[0] = &bval; + vals[0] = &value; vals[1] = NULL; - ptype[0] = '\0'; + next = s; while ( (s = ldif_getline( &next )) != NULL ) { if ( *s == '\n' || *s == '\0' ) { break; } - if ( ldif_parse_line( s, &type, &value, &vlen ) != 0 ) { + if ( ldif_parse_line( s, &type, &value.bv_val, &value.bv_len ) != 0 ) { +#ifdef NEW_LOGGING + LDAP_LOG(( "operation", LDAP_LEVEL_DETAIL1, + "str2entry: NULL (parse_line)\n" )); +#else Debug( LDAP_DEBUG_TRACE, "<= str2entry NULL (parse_line)\n", 0, 0, 0 ); +#endif continue; } - if ( strcasecmp( type, ptype ) != 0 ) { - strncpy( ptype, type, sizeof(ptype) - 1 ); - nvals = 0; - maxvals = 0; - a = NULL; - } - if ( strcasecmp( type, "dn" ) == 0 ) { free( type ); if ( e->e_dn != NULL ) { +#ifdef NEW_LOGGING + LDAP_LOG(( "operation", LDAP_LEVEL_DETAIL1, + "str2entry: entry %ld has multiple dns \"%s\" and \"%s\" (second ignored)\n", + e->e_id, e->e_dn, value.bv_val != NULL ? value.bv_val : "" )); +#else Debug( LDAP_DEBUG_ANY, "str2entry: entry %ld has multiple dns \"%s\" and \"%s\" (second ignored)\n", e->e_id, e->e_dn, - value != NULL ? value : NULL ); - if( value != NULL ) free( value ); + value.bv_val != NULL ? value.bv_val : "" ); +#endif + if( value.bv_val != NULL ) free( value.bv_val ); continue; } - e->e_dn = value != NULL ? value : ch_strdup( "" ); + + e->e_dn = value.bv_val != NULL ? value.bv_val : ch_strdup( "" ); continue; } - bval.bv_val = value; - bval.bv_len = vlen; - if ( attr_merge_fast( e, type, vals, nvals, 1, &maxvals, &a ) - != 0 ) { - Debug( LDAP_DEBUG_TRACE, + ad = NULL; + rc = slap_str2ad( type, &ad, &text ); + + if( rc != LDAP_SUCCESS ) { +#ifdef NEW_LOGGING + LDAP_LOG(( "operation", LDAP_LEVEL_DETAIL1, + "str2entry: str2ad(%s): %s\n", type, text )); +#else + Debug( slapMode & SLAP_TOOL_MODE + ? LDAP_DEBUG_ANY : LDAP_DEBUG_TRACE, + "<= str2entry: str2ad(%s): %s\n", type, text, 0 ); +#endif + if( slapMode & SLAP_TOOL_MODE ) { + entry_free( e ); + free( value.bv_val ); + free( type ); + return NULL; + } + + rc = slap_str2undef_ad( type, &ad, &text ); + + if( rc != LDAP_SUCCESS ) { +#ifdef NEW_LOGGING + LDAP_LOG(( "operation", LDAP_LEVEL_DETAIL1, + "str2entry: str2undef_ad(%s): %s\n", type, text )); +#else + Debug( LDAP_DEBUG_ANY, + "<= str2entry: str2undef_ad(%s): %s\n", + type, text, 0 ); +#endif + entry_free( e ); + free( value.bv_val ); + free( type ); + return NULL; + } + } + + if( slapMode & SLAP_TOOL_MODE ) { + slap_syntax_validate_func *validate = + ad->ad_type->sat_syntax->ssyn_validate; + + if( !validate ) { +#ifdef NEW_LOGGING + LDAP_LOG(( "operation", LDAP_LEVEL_INFO, + "str2entry: no validator for syntax %s\n", + ad->ad_type->sat_syntax->ssyn_oid )); +#else + Debug( LDAP_DEBUG_ANY, + "str2entry: no validator for syntax %s\n", + ad->ad_type->sat_syntax->ssyn_oid, 0, 0 ); +#endif + entry_free( e ); + free( value.bv_val ); + free( type ); + return NULL; + } + + /* + * validate value per syntax + */ + rc = validate( ad->ad_type->sat_syntax, &value ); + + if( rc != 0 ) { +#ifdef NEW_LOGGING + LDAP_LOG(( "operation", LDAP_LEVEL_ERR, + "str2entry: invalid value for syntax %s\n", + ad->ad_type->sat_syntax->ssyn_oid )); +#else + Debug( LDAP_DEBUG_ANY, + "str2entry: invalid value for syntax %s\n", + ad->ad_type->sat_syntax->ssyn_oid, 0, 0 ); +#endif + entry_free( e ); + free( value.bv_val ); + free( type ); + return NULL; + } + } + + rc = attr_merge( e, ad, vals ); + + ad_free( ad, 1 ); + + if( rc != 0 ) { +#ifdef NEW_LOGGING + LDAP_LOG(( "operation", LDAP_LEVEL_DETAIL1, + "str2entry: NULL (attr_merge)\n" )); +#else + Debug( LDAP_DEBUG_ANY, "<= str2entry NULL (attr_merge)\n", 0, 0, 0 ); +#endif entry_free( e ); - free( value ); + free( value.bv_val ); free( type ); return( NULL ); } - free( value ); free( type ); - nvals++; + free( value.bv_val ); } /* check to make sure there was a dn: line */ if ( e->e_dn == NULL ) { +#ifdef NEW_LOGGING + LDAP_LOG(( "operation", LDAP_LEVEL_INFO, + "str2entry: entry %ld has no dn.\n", e->e_id )); +#else Debug( LDAP_DEBUG_ANY, "str2entry: entry %ld has no dn\n", e->e_id, 0, 0 ); +#endif entry_free( e ); return( NULL ); } /* generate normalized dn */ e->e_ndn = ch_strdup( e->e_dn ); - (void) dn_normalize_case( e->e_ndn ); - - Debug(LDAP_DEBUG_TRACE, "<= str2entry(%s) -> %ld (0x%lx)\n", - e->e_dn, e->e_id, (unsigned long)e ); - + (void) dn_normalize( e->e_ndn ); + +#ifdef NEW_LOGGING + LDAP_LOG(( "operation", LDAP_LEVEL_DETAIL2, + "str2entry(%s) -> 0x%lx\n", e->e_dn, (unsigned long)e )); +#else + Debug(LDAP_DEBUG_TRACE, "<= str2entry(%s) -> 0x%lx\n", + e->e_dn, (unsigned long) e, 0 ); +#endif return( e ); } + #define GRABSIZE BUFSIZ #define MAKE_SPACE( n ) { \ @@ -164,7 +271,7 @@ str2entry( char *s ) emaxsize += GRABSIZE; \ ecur = ebuf + offset; \ } \ -} + } char * entry2str( @@ -177,7 +284,6 @@ entry2str( /* * In string format, an entry looks like this: - * \n * dn: \n * [: \n]* */ @@ -197,9 +303,10 @@ entry2str( /* put ":[:] " line for each value */ for ( i = 0; a->a_vals[i] != NULL; i++ ) { bv = a->a_vals[i]; - tmplen = strlen( a->a_type ); + tmplen = a->a_desc->ad_cname->bv_len; MAKE_SPACE( LDIF_SIZE_NEEDED( tmplen, bv->bv_len )); - ldif_sput( (char **) &ecur, LDIF_PUT_VALUE, a->a_type, + ldif_sput( (char **) &ecur, LDIF_PUT_VALUE, + a->a_desc->ad_cname->bv_val, bv->bv_val, bv->bv_len ); } } @@ -213,8 +320,14 @@ entry2str( void entry_free( Entry *e ) { - Attribute *a, *next; + /* free an entry structure */ + assert( e != NULL ); + + /* e_private must be freed by the caller */ + assert( e->e_private == NULL ); + e->e_private = NULL; + /* free DNs */ if ( e->e_dn != NULL ) { free( e->e_dn ); e->e_dn = NULL; @@ -223,12 +336,11 @@ entry_free( Entry *e ) free( e->e_ndn ); e->e_ndn = NULL; } - for ( a = e->e_attrs; a != NULL; a = next ) { - next = a->a_next; - attr_free( a ); - } + + /* free attributes */ + attrs_free( e->e_attrs ); e->e_attrs = NULL; - e->e_private = NULL; + free( e ); } @@ -237,7 +349,7 @@ entry_free( Entry *e ) * * the Entry has three entry points (ways to find things): * - * by entry e.g., if you already have an entry from the cache + * by entry e.g., if you already have an entry from the cache * and want to delete it. (really by entry ptr) * by dn e.g., when looking for the base object of a search * by id e.g., for search candidates @@ -264,3 +376,238 @@ entry_id_cmp( Entry *e1, Entry *e2 ) return( e1->e_id < e2->e_id ? -1 : (e1->e_id > e2->e_id ? 1 : 0) ); } +#define SLAPD_SLEEPY 1 +#ifdef SLAPD_SLEEPY + +/* a DER encoded entry looks like: + * + * entry :== SEQUENCE { + * dn DistinguishedName, + * ndn NormalizedDistinguishedName, + * attrs SEQUENCE OF SEQUENCE { + * type AttributeType, + * values SET OF AttributeValue + * } + * } + * + * Encoding/Decoding of DER should be much faster than LDIF + */ + +int entry_decode( struct berval *bv, Entry **entry ) +{ + int rc; + BerElement *ber; + Entry *e; + ber_tag_t tag; + ber_len_t len; + char *last; + + ber = ber_init( bv ); + if( ber == NULL ) { +#ifdef NEW_LOGGING + LDAP_LOG(( "operation", LDAP_LEVEL_ERR, + "entry_decode: ber_init failed\n" )); +#else + Debug( LDAP_DEBUG_ANY, + "<= entry_decode: ber_init failed\n", + 0, 0, 0 ); +#endif + return LDAP_LOCAL_ERROR; + } + + /* initialize reader/writer lock */ + e = (Entry *) ch_malloc( sizeof(Entry) ); + + if( e == NULL ) { +#ifdef NEW_LOGGING + LDAP_LOG(( "operation", LDAP_LEVEL_ERR, + "entry_decode: entry allocation failed.\n" )); +#else + Debug( LDAP_DEBUG_ANY, + "<= entry_decode: entry allocation failed\n", + 0, 0, 0 ); +#endif + return LDAP_LOCAL_ERROR; + } + + /* initialize entry */ + e->e_id = NOID; + e->e_dn = NULL; + e->e_ndn = NULL; + e->e_attrs = NULL; + e->e_private = NULL; + + tag = ber_scanf( ber, "{aa" /*"}"*/, &e->e_dn, &e->e_ndn ); + if( tag == LBER_ERROR ) { + free( e ); + return LDAP_PROTOCOL_ERROR; + } + +#ifdef NEW_LOGGING + LDAP_LOG(( "operation", LDAP_LEVEL_DETAIL2, + "entry_decode: \"%s\"\n", e->e_dn )); +#else + Debug( LDAP_DEBUG_TRACE, + "entry_decode: \"%s\"\n", + e->e_dn, 0, 0 ); +#endif + /* get the attrs */ + for ( tag = ber_first_element( ber, &len, &last ); + tag != LBER_DEFAULT; + tag = ber_next_element( ber, &len, last ) ) + { + struct berval *type; + struct berval **vals; + AttributeDescription *ad; + const char *text; + + tag = ber_scanf( ber, "{O{V}}", &type, &vals ); + + if ( tag == LBER_ERROR ) { +#ifdef NEW_LOGGING + LDAP_LOG(( "operation", LDAP_LEVEL_ERR, + "entry_decode: decoding error (%s)\n", e->e_dn )); +#else + Debug( LDAP_DEBUG_ANY, "entry_decode: decoding error\n", 0, 0, 0 ); +#endif + entry_free( e ); + return LDAP_PROTOCOL_ERROR; + } + + if ( vals == NULL ) { +#ifdef NEW_LOGGING + LDAP_LOG(( "operation", LDAP_LEVEL_ERR, + "entry_decode: no values for type %s\n", type )); +#else + Debug( LDAP_DEBUG_ANY, "entry_decode: no values for type %s\n", + type, 0, 0 ); +#endif + ber_bvfree( type ); + entry_free( e ); + return LDAP_PROTOCOL_ERROR; + } + + ad = NULL; + rc = slap_bv2ad( type, &ad, &text ); + + if( rc != LDAP_SUCCESS ) { +#ifdef NEW_LOGGING + LDAP_LOG(( "operation", LDAP_LEVEL_INFO, + "entry_decode: str2ad(%s): %s\n", type, text )); +#else + Debug( LDAP_DEBUG_TRACE, + "<= entry_decode: str2ad(%s): %s\n", type, text, 0 ); +#endif + rc = slap_bv2undef_ad( type, &ad, &text ); + + if( rc != LDAP_SUCCESS ) { +#ifdef NEW_LOGGING + LDAP_LOG(( "operation", LDAP_LEVEL_INFO, + "entry_decode: str2undef_ad(%s): %s\n", type, text)); +#else + Debug( LDAP_DEBUG_ANY, + "<= entry_decode: str2undef_ad(%s): %s\n", + type, text, 0 ); +#endif + ber_bvfree( type ); + ber_bvecfree( vals ); + entry_free( e ); + return rc; + } + } + + rc = attr_merge( e, ad, vals ); + ad_free( ad, 1 ); + + if( rc != 0 ) { +#ifdef NEW_LOGGING + LDAP_LOG(( "operation", LDAP_LEVEL_INFO, + "entry_decode: attr_merge failed\n")); +#else + Debug( LDAP_DEBUG_ANY, + "<= entry_decode: attr_merge failed\n", 0, 0, 0 ); +#endif + ber_bvfree( type ); + ber_bvecfree( vals ); + entry_free( e ); + return LDAP_LOCAL_ERROR; + } + + free( type ); + ber_bvecfree( vals ); + } + + rc = ber_scanf( ber, /*"{"*/ "}" ); + if( rc < 0 ) { + entry_free( e ); + return LDAP_PROTOCOL_ERROR; + } + +#ifdef NEW_LOGGING + LDAP_LOG(( "operation", LDAP_LEVEL_DETAIL1, + "entry_decode: %s\n", e->e_dn )); +#else + Debug(LDAP_DEBUG_TRACE, "<= entry_decode(%s)\n", + e->e_dn, 0, 0 ); +#endif + + *entry = e; + return LDAP_SUCCESS; +} + +int entry_encode( + Entry *e, + struct berval **bv ) +{ + int rc = -1; + Attribute *a; + BerElement *ber; + +#ifdef NEW_LOGGING + LDAP_LOG(( "operation", LDAP_LEVEL_DETAIL1, + "entry_encode: id: 0x%08lx \"%s\"\n", + e->e_id, e->e_dn )); +#else + Debug( LDAP_DEBUG_TRACE, "=> entry_encode(0x%08lx): %s\n", + e->e_id, e->e_dn, 0 ); +#endif + ber = ber_alloc_t( LBER_USE_DER ); + if( ber == NULL ) { + goto done; + } + + rc = ber_printf( ber, "{ss{" /*"}}"*/, e->e_dn, e->e_ndn ); + if( rc < 0 ) { + goto done; + } + + for ( a = e->e_attrs; a != NULL; a = a->a_next ) { + rc = ber_printf( ber, "{O{V}}", + a->a_desc->ad_cname, + a->a_vals ); + if( rc < 0 ) { + goto done; + } + } + + rc = ber_printf( ber, /*"{{"*/ "}}" ); + if( rc < 0 ) { + goto done; + } + + rc = ber_flatten( ber, bv ); + +done: + ber_free( ber, 1 ); + if( rc ) { +#ifdef NEW_LOGGING + LDAP_LOG(( "operation", LDAP_LEVEL_INFO, + "entry_encode: id=0x%08lx failed (%d)\n", e->e_id, rc )); +#else + Debug( LDAP_DEBUG_ANY, "=> entry_encode(0x%08lx): failed (%d)\n", + e->e_id, rc, 0 ); +#endif + } + return rc; +} +#endif