diff options
Diffstat (limited to 'ldap/servers/slapd/entry.c')
-rw-r--r-- | ldap/servers/slapd/entry.c | 332 |
1 files changed, 300 insertions, 32 deletions
diff --git a/ldap/servers/slapd/entry.c b/ldap/servers/slapd/entry.c index fea08814..db641b63 100644 --- a/ldap/servers/slapd/entry.c +++ b/ldap/servers/slapd/entry.c @@ -150,9 +150,9 @@ str2entry_state_information_from_type(char *s,CSNSet **csnset,CSN **attributedel } } - +/* dn is not consumed. Caller needs to free it. */ static Slapi_Entry * -str2entry_fast( char *s, int flags, int read_stateinfo ) +str2entry_fast( const char *dn, char *s, int flags, int read_stateinfo ) { Slapi_Entry *e; char *next, *ptype=NULL; @@ -165,17 +165,24 @@ str2entry_fast( char *s, int flags, int read_stateinfo ) CSN *maxcsn = NULL; /* - * In string format, an entry looks like this: + * In string format, an entry looks like either of these: * * dn: <dn>\n * [<attr>:[:] <value>\n] * [<tab><continuedvalue>\n]* * ... * + * rdn: <rdn>\n + * [<attr>:[:] <value>\n] + * [<tab><continuedvalue>\n]* + * ... + * * If a double colon is used after a type, it means the * following value is encoded as a base 64 string. This * happens if the value contains a non-printing character * or newline. + * + * In case an entry starts with rdn:, dn must be provided. */ LDAPDebug( LDAP_DEBUG_TRACE, "=> str2entry_fast\n", 0, 0, 0 ); @@ -183,7 +190,7 @@ str2entry_fast( char *s, int flags, int read_stateinfo ) e = slapi_entry_alloc(); slapi_entry_init(e,NULL,NULL); - /* dn + attributes */ + /* dn|rdn + attributes */ next = s; /* get the read lock of name2asi for performance purpose. @@ -260,17 +267,24 @@ str2entry_fast( char *s, int flags, int read_stateinfo ) a = NULL; } - if ( strcasecmp( type, "dn" ) == 0 ) - { - if ( slapi_entry_get_dn_const(e)!=NULL ) - { + if ( dn ) { + if ( NULL == slapi_entry_get_dn_const( e )) { + slapi_entry_set_dn( e, slapi_ch_strdup( dn )); + } + if ( NULL == slapi_entry_get_rdn_const( e )) { + slapi_entry_set_rdn( e, (char *)dn ); + } + } + if ( strcasecmp( type, "dn" ) == 0 ) { + if ( slapi_entry_get_dn_const(e)!=NULL ) { char ebuf[ BUFSIZ ]; - LDAPDebug( LDAP_DEBUG_ANY, - "str2entry_fast: entry has multiple dns \"%s\" and \"%s\" (second ignored)\n", - escape_string( slapi_entry_get_dn_const(e), ebuf ), - escape_string( valuecharptr, ebuf ), 0 ); - /* the memory below was not allocated by the slapi_ch_ functions */ - if (retmalloc) slapi_ch_free((void **) &valuecharptr); + LDAPDebug( LDAP_DEBUG_TRACE, + "str2entry_fast: entry has multiple dns \"%s\" and " + "\"%s\" (second ignored)\n", + escape_string( slapi_entry_get_dn_const(e), ebuf ), + escape_string( valuecharptr, ebuf ), 0 ); + /* the memory below was not allocated by the slapi_ch_ functions */ + if (retmalloc) slapi_ch_free_string(&valuecharptr); if (freetype) slapi_ch_free_string(&type); continue; } @@ -278,9 +292,20 @@ str2entry_fast( char *s, int flags, int read_stateinfo ) /* the memory below was not allocated by the slapi_ch_ functions */ if (retmalloc) slapi_ch_free_string(&valuecharptr); if (freetype) slapi_ch_free_string(&type); - continue; + continue; + } + + if ( strcasecmp( type, "rdn" ) == 0 ) { + if ( NULL == slapi_entry_get_rdn_const( e )) { + slapi_entry_set_rdn( e, valuecharptr ); + } + /* the memory below was not allocated by the slapi_ch_ functions */ + if (retmalloc) slapi_ch_free_string(&valuecharptr); + if (freetype) slapi_ch_free_string(&type); + continue; } + /* retrieve uniqueid */ if ( strcasecmp (type, SLAPI_ATTR_UNIQUEID) == 0 ){ @@ -574,8 +599,9 @@ entry_attrs_find(entry_attrs *ea,char *type) if flags contains SLAPI_STR2ENTRY_REMOVEDUPVALS. */ +/* dn is not consumed. Caller needs to free it. */ static Slapi_Entry * -str2entry_dupcheck( char *s, int flags, int read_stateinfo ) +str2entry_dupcheck( const char *dn, char *s, int flags, int read_stateinfo ) { Slapi_Entry *e; str2entry_attr stack_attrs[STR2ENTRY_SMALL_BUFFER_SIZE]; @@ -630,7 +656,7 @@ str2entry_dupcheck( char *s, int flags, int read_stateinfo ) if ( (retmalloc = ldif_parse_line( s, &type, &valuecharptr, &valuelen )) < 0 ) { LDAPDebug( LDAP_DEBUG_TRACE, - "<= slapi_str2entry NULL (parse_line)\n", 0, 0, 0 ); + "<= str2entry_dupcheck NULL (parse_line)\n", 0, 0, 0 ); continue; } #if defined(USE_OPENLDAP) @@ -662,11 +688,20 @@ str2entry_dupcheck( char *s, int flags, int read_stateinfo ) csnset_free(&valuecsnset); } + if ( dn ) { + if ( NULL == slapi_entry_get_dn_const(e) ) { + slapi_entry_set_dn( e, slapi_ch_strdup( dn )); + } + if ( NULL == slapi_entry_get_rdn_const(e) ) { + slapi_entry_set_rdn( e, (char *)dn ); + } + } if ( strcasecmp( type, "dn" ) == 0 ) { if ( slapi_entry_get_dn_const(e)!=NULL ) { char ebuf[ BUFSIZ ]; - LDAPDebug( LDAP_DEBUG_ANY, - "slapi_str2entry: entry has multiple dns \"%s\" and \"%s\" (second ignored)\n", + LDAPDebug( LDAP_DEBUG_TRACE, + "str2entry_dupcheck: entry has multiple dns \"%s\" " + "and \"%s\" (second ignored)\n", escape_string( slapi_entry_get_dn_const(e), ebuf ), escape_string( valuecharptr, ebuf ), 0 ); /* the memory below was not allocated by the slapi_ch_ functions */ @@ -681,11 +716,21 @@ str2entry_dupcheck( char *s, int flags, int read_stateinfo ) continue; } + if ( strcasecmp( type, "rdn" ) == 0 ) { + if ( NULL == slapi_entry_get_rdn_const( e )) { + slapi_entry_set_rdn( e, valuecharptr ); + } + /* the memory below was not allocated by the slapi_ch_ functions */ + if (retmalloc) slapi_ch_free_string(&valuecharptr); + if (freetype) slapi_ch_free_string(&type); + continue; + } + /* retrieve uniqueid */ if ( strcasecmp (type, SLAPI_ATTR_UNIQUEID) == 0 ){ if (e->e_uniqueid != NULL){ - LDAPDebug (LDAP_DEBUG_ANY, "slapi_str2entry: entry has multiple " + LDAPDebug (LDAP_DEBUG_ANY, "str2entry_dupcheck: entry has multiple " "uniqueids %s and %s (second ignored)\n", e->e_uniqueid, valuecharptr, 0); }else{ @@ -787,7 +832,7 @@ str2entry_dupcheck( char *s, int flags, int read_stateinfo ) if ( slapi_attr_type2plugin( type,(void **)&(attrs[nattrs].sa_pi) ) != 0 ) { LDAPDebug( LDAP_DEBUG_ANY, - "<= slapi_str2entry NULL (slapi_attr_type2plugin)\n", + "<= str2entry_dupcheck NULL (slapi_attr_type2plugin)\n", 0, 0, 0 ); slapi_entry_free( e ); e = NULL; if (retmalloc) slapi_ch_free_string(&valuecharptr); @@ -911,7 +956,7 @@ str2entry_dupcheck( char *s, int flags, int read_stateinfo ) else { /* Failure adding to value tree */ - LDAPDebug( LDAP_DEBUG_ANY, "slapi_str2entry: unexpected failure %d constructing value tree\n", rc, 0, 0 ); + LDAPDebug( LDAP_DEBUG_ANY, "str2entry_dupcheck: unexpected failure %d constructing value tree\n", rc, 0, 0 ); slapi_entry_free( e ); e = NULL; goto free_and_return; } @@ -924,7 +969,7 @@ str2entry_dupcheck( char *s, int flags, int read_stateinfo ) if ( slapi_entry_get_dn_const(e)==NULL ) { if (!(SLAPI_STR2ENTRY_INCLUDE_VERSION_STR & flags)) - LDAPDebug( LDAP_DEBUG_ANY, "slapi_str2entry: entry has no dn\n", + LDAPDebug( LDAP_DEBUG_ANY, "str2entry_dupcheck: entry has no dn\n", 0, 0, 0 ); slapi_entry_free( e ); e = NULL; goto free_and_return; @@ -945,11 +990,11 @@ str2entry_dupcheck( char *s, int flags, int read_stateinfo ) if ( sa->sa_numdups > 0 ) { if ( sa->sa_numdups > 1 ) { - LDAPDebug( LDAP_DEBUG_ANY, "%d duplicate values for attribute " + LDAPDebug( LDAP_DEBUG_ANY, "str2entry_dupcheck: %d duplicate values for attribute " "type %s detected in entry %s. Extra values ignored.\n", sa->sa_numdups, sa->sa_type, slapi_entry_get_dn_const(e) ); } else { - LDAPDebug( LDAP_DEBUG_ANY, "Duplicate value for attribute " + LDAPDebug( LDAP_DEBUG_ANY, "str2entry_dupcheck: Duplicate value for attribute " "type %s detected in entry %s. Extra value ignored.\n", sa->sa_type, slapi_entry_get_dn_const(e), 0 ); } @@ -1014,7 +1059,7 @@ str2entry_dupcheck( char *s, int flags, int read_stateinfo ) if ( flags & SLAPI_STR2ENTRY_ADDRDNVALS ) { if ( slapi_entry_add_rdn_values( e ) != LDAP_SUCCESS ) { LDAPDebug( LDAP_DEBUG_TRACE, - "slapi_str2entry: entry has badly formatted dn\n", + "str2entry_dupcheck: entry has badly formatted dn\n", 0, 0, 0 ); slapi_entry_free( e ); e = NULL; goto free_and_return; @@ -1094,11 +1139,72 @@ slapi_str2entry( char *s, int flags ) if ( 0 != ( flags & SLAPI_STR2ENTRY_NOT_WELL_FORMED_LDIF ) || 0 != ( flags & ~SLAPI_STRENTRY_FLAGS_HANDLED_BY_STR2ENTRY_FAST )) { - e= str2entry_dupcheck( s, flags, read_stateinfo ); + e= str2entry_dupcheck( NULL/*dn*/, s, flags, read_stateinfo ); + } + else + { + e= str2entry_fast( NULL/*dn*/, s, flags, read_stateinfo ); + } + if (!e) + return e; /* e == NULL */ + + if ( flags & SLAPI_STR2ENTRY_EXPAND_OBJECTCLASSES ) + { + if ( flags & SLAPI_STR2ENTRY_NO_SCHEMA_LOCK ) + { + schema_expand_objectclasses_nolock( e ); + } + else + { + slapi_schema_expand_objectclasses( e ); + } + } + + if ( flags & SLAPI_STR2ENTRY_TOMBSTONE_CHECK ) + { + /* + * Check if the entry is a tombstone. + */ + if(slapi_entry_attr_hasvalue(e, SLAPI_ATTR_OBJECTCLASS, SLAPI_ATTR_VALUE_TOMBSTONE)) + { + e->e_flags |= SLAPI_ENTRY_FLAG_TOMBSTONE; + } + } + return e; +} + +/* + * string s does not include dn. + */ +Slapi_Entry * +slapi_str2entry_ext( const char *dn, char *s, int flags ) +{ + Slapi_Entry *e; + int read_stateinfo= ~( flags & SLAPI_STR2ENTRY_IGNORE_STATE ); + + if (NULL == dn) + { + return slapi_str2entry( s, flags ); + } + + LDAPDebug( LDAP_DEBUG_ARGS, + "slapi_str2entry_ext: flags=0x%x, dn=\"%s\", entry=\"%.50s...\"\n", + flags, dn, s ); + + + /* + * If well-formed LDIF has not been provided OR if a flag that is + * not handled by str2entry_fast() has been passed in, call the + * slower but more forgiving str2entry_dupcheck() function. + */ + if ( 0 != ( flags & SLAPI_STR2ENTRY_NOT_WELL_FORMED_LDIF ) || + 0 != ( flags & ~SLAPI_STRENTRY_FLAGS_HANDLED_BY_STR2ENTRY_FAST )) + { + e= str2entry_dupcheck( dn, s, flags, read_stateinfo ); } else { - e= str2entry_fast( s, flags, read_stateinfo ); + e= str2entry_fast( dn, s, flags, read_stateinfo ); } if (!e) return e; /* e == NULL */ @@ -1412,28 +1518,142 @@ entry2str_internal( Slapi_Entry *e, int *len, int entry2str_ctrl ) return ebuf; } +static char * +entry2str_internal_ext( Slapi_Entry *e, int *len, int entry2str_ctrl) +{ + if (entry2str_ctrl & SLAPI_DUMP_RDN_ENTRY) /* dump rdn: ... */ + { + char *ebuf; + char *ecur; + size_t elen = 0; + size_t typebuf_len = 64; + char *typebuf = (char *)slapi_ch_malloc(typebuf_len); + Slapi_Value rdnvalue; + /* + * In string format, an entry looks like this: + * rdn: <normalized rdn>\n + * [<attr>: <value>\n]* + */ + + ecur = ebuf = NULL; + + value_init(&rdnvalue, NULL, CSN_TYPE_NONE, NULL); + + /* find length of buffer needed to hold this entry */ + if (NULL == slapi_entry_get_rdn_const(e) && + NULL != slapi_entry_get_dn_const(e)) + { + /* e_srdn is not filled in, use e_sdn */ + slapi_rdn_init_all_sdn(&e->e_srdn, slapi_entry_get_sdn_const(e)); + } + if (NULL != slapi_entry_get_rdn_const(e)) + { + slapi_value_set_string(&rdnvalue, slapi_entry_get_rdn_const(e)); + elen += entry2str_internal_size_value("rdn", &rdnvalue, + entry2str_ctrl, + ATTRIBUTE_PRESENT, + VALUE_PRESENT); + } + + /* Count the space required for the present attributes */ + elen += entry2str_internal_size_attrlist(e->e_attrs, entry2str_ctrl, + ATTRIBUTE_PRESENT); + + /* Count the space required for the deleted attributes */ + if(entry2str_ctrl & SLAPI_DUMP_STATEINFO) + { + elen += entry2str_internal_size_attrlist(e->e_deleted_attrs, + entry2str_ctrl, + ATTRIBUTE_DELETED); + } + + elen += 1; + ecur = ebuf = (char *)slapi_ch_malloc(elen); + + /* put the rdn */ + if (slapi_entry_get_rdn_const(e) != NULL) + { + /* put "rdn: <normalized rdn>" */ + entry2str_internal_put_value("rdn", NULL, CSN_TYPE_NONE, + ATTRIBUTE_PRESENT, &rdnvalue, + VALUE_PRESENT, &ecur, &typebuf, + &typebuf_len, entry2str_ctrl); + } + + /* Put the present attributes */ + entry2str_internal_put_attrlist(e->e_attrs, ATTRIBUTE_PRESENT, + entry2str_ctrl, &ecur, + &typebuf, &typebuf_len ); + + /* Put the deleted attributes */ + if(entry2str_ctrl & SLAPI_DUMP_STATEINFO) + { + entry2str_internal_put_attrlist(e->e_deleted_attrs, + ATTRIBUTE_DELETED, entry2str_ctrl, + &ecur, &typebuf, &typebuf_len ); + } + + *ecur = '\0'; + if ((size_t)(ecur - ebuf + 1) > elen) + { + /* this should not happen */ + slapi_log_error (SLAPI_LOG_FATAL, NULL, + "entry2str_internal_ext: array boundary wrote: " + "bufsize=%ld wrote=%ld\n", + elen, (ecur - ebuf + 1)); + } + + if ( NULL != len ) { + *len = ecur - ebuf; + } + + slapi_ch_free((void**)&typebuf); + value_done(&rdnvalue); + + return ebuf; + } + else /* dump "dn: ..." */ + { + return entry2str_internal( e, len, entry2str_ctrl ); + } +} + +/* + * This function converts an entry to the entry string starting with "dn: ..." + */ char * slapi_entry2str( Slapi_Entry *e, int *len ) { return entry2str_internal(e, len, 0); } +/* + * This function converts an entry to the entry string starting with "dn: ..." + */ char * slapi_entry2str_dump_uniqueid( Slapi_Entry *e, int *len ) { return entry2str_internal(e, len, SLAPI_DUMP_UNIQUEID); } +/* + * This function converts an entry to the entry string starting with "dn: ..." + */ char * slapi_entry2str_no_opattrs( Slapi_Entry *e, int *len ) { return entry2str_internal(e, len, SLAPI_DUMP_NOOPATTRS); } +/* + * This function converts an entry to the entry string starting with "dn: ..." + * by default. If option includes SLAPI_DUMP_RDN_ENTRY bit, it does the entry + * to "rdn: ..." + */ char * slapi_entry2str_with_options( Slapi_Entry *e, int *len, int options ) { - return entry2str_internal(e, len, options); + return entry2str_internal_ext(e, len, options); } static int entry_type = -1; /* The type number assigned by the Factory for 'Entry' */ @@ -1474,6 +1694,8 @@ slapi_entry_alloc() { Slapi_Entry *e= (Slapi_Entry *) slapi_ch_calloc( 1, sizeof(struct slapi_entry) ); slapi_sdn_init(&e->e_sdn); + slapi_rdn_init(&e->e_srdn); + e->e_extension = factory_create_extension(get_entry_object_type(),e,NULL); if(!counters_created) { @@ -1514,6 +1736,8 @@ slapi_entry_free( Slapi_Entry *e ) /* JCM - Should be ** so that we can NULL the ENTRY_DUMP(e,"slapi_entry_free"); factory_destroy_extension(get_entry_object_type(),e,NULL/*Parent*/,&(e->e_extension)); slapi_sdn_done(&e->e_sdn); + slapi_rdn_done(&e->e_srdn); + csnset_free(&e->e_dncsnset); csn_free(&e->e_maxcsn); slapi_ch_free((void **)&e->e_uniqueid); @@ -1574,7 +1798,8 @@ slapi_entry_size(Slapi_Entry *e) if (e->e_uniqueid) size += strlen(e->e_uniqueid) + 1; if (e->e_dncsnset) size += csnset_size(e->e_dncsnset); if (e->e_maxcsn) size += sizeof( CSN ); - size += slapi_dn_size(&e->e_sdn); + size += slapi_dn_size(&e->e_sdn); /* covers rdn format, + since (rdn length < dn length) */ size += slapi_attrlist_size(e->e_attrs); if (e->e_deleted_attrs) size += slapi_attrlist_size(e->e_deleted_attrs); if (e->e_virtual_attrs) size += slapi_attrlist_size(e->e_virtual_attrs); @@ -1605,6 +1830,7 @@ slapi_entry_dup( const Slapi_Entry *e ) slapi_entry_init(ec,NULL,NULL); slapi_sdn_copy(slapi_entry_get_sdn_const(e),&ec->e_sdn); + slapi_srdn_copy(slapi_entry_get_srdn_const(e),&ec->e_srdn); /* duplicate the dncsn also */ ec->e_dncsnset= csnset_dup(e->e_dncsnset); @@ -1688,12 +1914,37 @@ slapi_entry_get_sdn( Slapi_Entry *e ) return &e->e_sdn; } +const Slapi_RDN * +slapi_entry_get_srdn_const( const Slapi_Entry *e ) +{ + return &e->e_srdn; +} + +Slapi_RDN * +slapi_entry_get_srdn( Slapi_Entry *e ) +{ + return &e->e_srdn; +} + const char * slapi_entry_get_dn_const( const Slapi_Entry *e ) { return (slapi_sdn_get_dn(slapi_entry_get_sdn_const(e))); } +const char * +slapi_entry_get_rdn_const( const Slapi_Entry *e ) +{ + return (slapi_rdn_get_rdn(slapi_entry_get_srdn_const(e))); +} + +/* slapi_rdn_get_nrdn could modify srdn in it. So, it cannot take const. */ +const char * +slapi_entry_get_nrdn_const( const Slapi_Entry *e ) +{ + return (slapi_rdn_get_nrdn(slapi_entry_get_srdn((Slapi_Entry *)e))); +} + /* * WARNING - The DN is passed in *not* copied. */ @@ -1703,12 +1954,28 @@ slapi_entry_set_dn( Slapi_Entry *e, char *dn ) slapi_sdn_set_dn_passin(slapi_entry_get_sdn(e),dn); } +/* + * WARNING - The DN is copied. + * The DN could be dn or RDN. + */ +void +slapi_entry_set_rdn( Slapi_Entry *e, char *dn ) +{ + slapi_rdn_set_all_dn(slapi_entry_get_srdn(e),dn); +} + void slapi_entry_set_sdn( Slapi_Entry *e, const Slapi_DN *sdn ) { slapi_sdn_copy(sdn,slapi_entry_get_sdn(e)); } +void +slapi_entry_set_srdn( Slapi_Entry *e, const Slapi_RDN *srdn ) +{ + slapi_srdn_copy(srdn, slapi_entry_get_srdn(e)); +} + const char * slapi_entry_get_uniqueid( const Slapi_Entry *e ) { @@ -2625,13 +2892,14 @@ int entry_apply_mods( Slapi_Entry *e, LDAPMod **mods ) { int err, j; + LDAPMod **mp = NULL; LDAPDebug( LDAP_DEBUG_TRACE, "=> entry_apply_mods\n", 0, 0, 0 ); err = LDAP_SUCCESS; - for ( j = 0; mods[j] != NULL; j++ ) + for ( mp = mods; mp && *mp; mp++ ) { - err= entry_apply_mod( e, mods[j] ); + err = entry_apply_mod( e, *mp ); if ( err != LDAP_SUCCESS ) { break; } |