1/* entry.c - routines for dealing with entries */ 2/* $OpenLDAP$ */ 3/* This work is part of OpenLDAP Software <http://www.openldap.org/>. 4 * 5 * Copyright 1998-2011 The OpenLDAP Foundation. 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted only as authorized by the OpenLDAP 10 * Public License. 11 * 12 * A copy of this license is available in the file LICENSE in the 13 * top-level directory of the distribution or, alternatively, at 14 * <http://www.OpenLDAP.org/license.html>. 15 */ 16/* Portions Copyright (c) 1995 Regents of the University of Michigan. 17 * All rights reserved. 18 * 19 * Redistribution and use in source and binary forms are permitted 20 * provided that this notice is preserved and that due credit is given 21 * to the University of Michigan at Ann Arbor. The name of the University 22 * may not be used to endorse or promote products derived from this 23 * software without specific prior written permission. This software 24 * is provided ``as is'' without express or implied warranty. 25 */ 26 27#include "portable.h" 28 29#include <stdio.h> 30 31#include <ac/ctype.h> 32#include <ac/errno.h> 33#include <ac/socket.h> 34#include <ac/string.h> 35 36#include "slap.h" 37#include "ldif.h" 38 39static char *ebuf; /* buf returned by entry2str */ 40static char *ecur; /* pointer to end of currently used ebuf */ 41static int emaxsize;/* max size of ebuf */ 42 43/* 44 * Empty root entry 45 */ 46const Entry slap_entry_root = { 47 NOID, { 0, "" }, { 0, "" }, NULL, 0, { 0, "" }, NULL 48}; 49 50/* 51 * these mutexes must be used when calling the entry2str() 52 * routine since it returns a pointer to static data. 53 */ 54ldap_pvt_thread_mutex_t entry2str_mutex; 55 56static const struct berval dn_bv = BER_BVC("dn"); 57 58/* 59 * Entry free list 60 * 61 * Allocate in chunks, minimum of 1000 at a time. 62 */ 63#define CHUNK_SIZE 1000 64typedef struct slap_list { 65 struct slap_list *next; 66} slap_list; 67static slap_list *entry_chunks; 68static Entry *entry_list; 69static ldap_pvt_thread_mutex_t entry_mutex; 70 71int entry_destroy(void) 72{ 73 slap_list *e; 74 if ( ebuf ) free( ebuf ); 75 ebuf = NULL; 76 ecur = NULL; 77 emaxsize = 0; 78 79 for ( e=entry_chunks; e; e=entry_chunks ) { 80 entry_chunks = e->next; 81 free( e ); 82 } 83 84 ldap_pvt_thread_mutex_destroy( &entry_mutex ); 85 ldap_pvt_thread_mutex_destroy( &entry2str_mutex ); 86 return attr_destroy(); 87} 88 89int 90entry_init(void) 91{ 92 ldap_pvt_thread_mutex_init( &entry2str_mutex ); 93 ldap_pvt_thread_mutex_init( &entry_mutex ); 94 return attr_init(); 95} 96 97Entry * 98str2entry( char *s ) 99{ 100 return str2entry2( s, 1 ); 101} 102 103#define bvcasematch(bv1, bv2) (ber_bvstrcasecmp(bv1, bv2) == 0) 104 105Entry * 106str2entry2( char *s, int checkvals ) 107{ 108 int rc; 109 Entry *e; 110 struct berval *type, *vals, *nvals; 111 char *freeval; 112 AttributeDescription *ad, *ad_prev; 113 const char *text; 114 char *next; 115 int attr_cnt; 116 int i, lines; 117 Attribute ahead, *atail; 118 119 /* 120 * LDIF is used as the string format. 121 * An entry looks like this: 122 * 123 * dn: <dn>\n 124 * [<attr>:[:] <value>\n] 125 * [<tab><continuedvalue>\n]* 126 * ... 127 * 128 * If a double colon is used after a type, it means the 129 * following value is encoded as a base 64 string. This 130 * happens if the value contains a non-printing character 131 * or newline. 132 */ 133 134 Debug( LDAP_DEBUG_TRACE, "=> str2entry: \"%s\"\n", 135 s ? s : "NULL", 0, 0 ); 136 137 e = entry_alloc(); 138 139 if( e == NULL ) { 140 Debug( LDAP_DEBUG_ANY, 141 "<= str2entry NULL (entry allocation failed)\n", 142 0, 0, 0 ); 143 return( NULL ); 144 } 145 146 /* initialize entry */ 147 e->e_id = NOID; 148 149 /* dn + attributes */ 150 atail = &ahead; 151 ahead.a_next = NULL; 152 ad = NULL; 153 ad_prev = NULL; 154 attr_cnt = 0; 155 next = s; 156 157 lines = ldif_countlines( s ); 158 type = ch_calloc( 1, (lines+1)*3*sizeof(struct berval)+lines ); 159 vals = type+lines+1; 160 nvals = vals+lines+1; 161 freeval = (char *)(nvals+lines+1); 162 i = -1; 163 164 /* parse into individual values, record DN */ 165 while ( (s = ldif_getline( &next )) != NULL ) { 166 int freev; 167 if ( *s == '\n' || *s == '\0' ) { 168 break; 169 } 170 i++; 171 if (i >= lines) { 172 Debug( LDAP_DEBUG_TRACE, 173 "<= str2entry ran past end of entry\n", 0, 0, 0 ); 174 goto fail; 175 } 176 177 rc = ldif_parse_line2( s, type+i, vals+i, &freev ); 178 freeval[i] = freev; 179 if ( rc ) { 180 Debug( LDAP_DEBUG_TRACE, 181 "<= str2entry NULL (parse_line)\n", 0, 0, 0 ); 182 continue; 183 } 184 185 if ( bvcasematch( &type[i], &dn_bv ) ) { 186 if ( e->e_dn != NULL ) { 187 Debug( LDAP_DEBUG_ANY, "str2entry: " 188 "entry %ld has multiple DNs \"%s\" and \"%s\"\n", 189 (long) e->e_id, e->e_dn, vals[i].bv_val ); 190 goto fail; 191 } 192 193 rc = dnPrettyNormal( NULL, &vals[i], &e->e_name, &e->e_nname, NULL ); 194 if( rc != LDAP_SUCCESS ) { 195 Debug( LDAP_DEBUG_ANY, "str2entry: " 196 "entry %ld has invalid DN \"%s\"\n", 197 (long) e->e_id, vals[i].bv_val, 0 ); 198 goto fail; 199 } 200 if ( freeval[i] ) free( vals[i].bv_val ); 201 vals[i].bv_val = NULL; 202 i--; 203 continue; 204 } 205 } 206 lines = i+1; 207 208 /* check to make sure there was a dn: line */ 209 if ( BER_BVISNULL( &e->e_name )) { 210 Debug( LDAP_DEBUG_ANY, "str2entry: entry %ld has no dn\n", 211 (long) e->e_id, 0, 0 ); 212 goto fail; 213 } 214 215 /* Make sure all attributes with multiple values are contiguous */ 216 if ( checkvals ) { 217 int j, k; 218 struct berval bv; 219 int fv; 220 221 for (i=0; i<lines; i++) { 222 for ( j=i+1; j<lines; j++ ) { 223 if ( bvcasematch( type+i, type+j )) { 224 /* out of order, move intervening attributes down */ 225 if ( j != i+1 ) { 226 bv = vals[j]; 227 fv = freeval[j]; 228 for ( k=j; k>i; k-- ) { 229 type[k] = type[k-1]; 230 vals[k] = vals[k-1]; 231 freeval[k] = freeval[k-1]; 232 } 233 k++; 234 type[k] = type[i]; 235 vals[k] = bv; 236 freeval[k] = fv; 237 } 238 i++; 239 } 240 } 241 } 242 } 243 244 if ( lines > 0 ) { 245 for ( i=0; i<=lines; i++ ) { 246 ad_prev = ad; 247 if ( !ad || ( i<lines && !bvcasematch( type+i, &ad->ad_cname ))) { 248 ad = NULL; 249 rc = slap_bv2ad( type+i, &ad, &text ); 250 251 if( rc != LDAP_SUCCESS ) { 252 Debug( slapMode & SLAP_TOOL_MODE 253 ? LDAP_DEBUG_ANY : LDAP_DEBUG_TRACE, 254 "<= str2entry: str2ad(%s): %s\n", type[i].bv_val, text, 0 ); 255 if( slapMode & SLAP_TOOL_MODE ) { 256 goto fail; 257 } 258 259 rc = slap_bv2undef_ad( type+i, &ad, &text, 0 ); 260 if( rc != LDAP_SUCCESS ) { 261 Debug( LDAP_DEBUG_ANY, 262 "<= str2entry: slap_str2undef_ad(%s): %s\n", 263 type[i].bv_val, text, 0 ); 264 goto fail; 265 } 266 } 267 268 /* require ';binary' when appropriate (ITS#5071) */ 269 if ( slap_syntax_is_binary( ad->ad_type->sat_syntax ) && !slap_ad_is_binary( ad ) ) { 270 Debug( LDAP_DEBUG_ANY, 271 "str2entry: attributeType %s #%d: " 272 "needs ';binary' transfer as per syntax %s\n", 273 ad->ad_cname.bv_val, 0, 274 ad->ad_type->sat_syntax->ssyn_oid ); 275 goto fail; 276 } 277 } 278 279 if (( ad_prev && ad != ad_prev ) || ( i == lines )) { 280 int j, k; 281 /* FIXME: we only need this when migrating from an unsorted DB */ 282 if ( atail != &ahead && atail->a_desc->ad_type->sat_flags & SLAP_AT_SORTED_VAL ) { 283 rc = slap_sort_vals( (Modifications *)atail, &text, &j, NULL ); 284 if ( rc == LDAP_SUCCESS ) { 285 atail->a_flags |= SLAP_ATTR_SORTED_VALS; 286 } else if ( rc == LDAP_TYPE_OR_VALUE_EXISTS ) { 287 Debug( LDAP_DEBUG_ANY, 288 "str2entry: attributeType %s value #%d provided more than once\n", 289 atail->a_desc->ad_cname.bv_val, j, 0 ); 290 goto fail; 291 } 292 } 293 atail->a_next = attr_alloc( NULL ); 294 atail = atail->a_next; 295 atail->a_flags = 0; 296 atail->a_numvals = attr_cnt; 297 atail->a_desc = ad_prev; 298 atail->a_vals = ch_malloc( (attr_cnt + 1) * sizeof(struct berval)); 299 if( ad_prev->ad_type->sat_equality && 300 ad_prev->ad_type->sat_equality->smr_normalize ) 301 atail->a_nvals = ch_malloc( (attr_cnt + 1) * sizeof(struct berval)); 302 else 303 atail->a_nvals = NULL; 304 k = i - attr_cnt; 305 for ( j=0; j<attr_cnt; j++ ) { 306 if ( freeval[k] ) 307 atail->a_vals[j] = vals[k]; 308 else 309 ber_dupbv( atail->a_vals+j, &vals[k] ); 310 vals[k].bv_val = NULL; 311 if ( atail->a_nvals ) { 312 atail->a_nvals[j] = nvals[k]; 313 nvals[k].bv_val = NULL; 314 } 315 k++; 316 } 317 BER_BVZERO( &atail->a_vals[j] ); 318 if ( atail->a_nvals ) { 319 BER_BVZERO( &atail->a_nvals[j] ); 320 } else { 321 atail->a_nvals = atail->a_vals; 322 } 323 attr_cnt = 0; 324 if ( i == lines ) break; 325 } 326 327 if ( BER_BVISNULL( &vals[i] ) ) { 328 Debug( LDAP_DEBUG_ANY, 329 "str2entry: attributeType %s #%d: " 330 "no value\n", 331 ad->ad_cname.bv_val, attr_cnt, 0 ); 332 goto fail; 333 } 334 335 if( slapMode & SLAP_TOOL_MODE ) { 336 struct berval pval; 337 slap_syntax_validate_func *validate = 338 ad->ad_type->sat_syntax->ssyn_validate; 339 slap_syntax_transform_func *pretty = 340 ad->ad_type->sat_syntax->ssyn_pretty; 341 342 if ( pretty ) { 343 rc = ordered_value_pretty( ad, 344 &vals[i], &pval, NULL ); 345 346 } else if ( validate ) { 347 /* 348 * validate value per syntax 349 */ 350 rc = ordered_value_validate( ad, &vals[i], LDAP_MOD_ADD ); 351 352 } else { 353 Debug( LDAP_DEBUG_ANY, 354 "str2entry: attributeType %s #%d: " 355 "no validator for syntax %s\n", 356 ad->ad_cname.bv_val, attr_cnt, 357 ad->ad_type->sat_syntax->ssyn_oid ); 358 goto fail; 359 } 360 361 if( rc != 0 ) { 362 Debug( LDAP_DEBUG_ANY, 363 "str2entry: invalid value " 364 "for attributeType %s #%d (syntax %s)\n", 365 ad->ad_cname.bv_val, attr_cnt, 366 ad->ad_type->sat_syntax->ssyn_oid ); 367 goto fail; 368 } 369 370 if( pretty ) { 371 if ( freeval[i] ) free( vals[i].bv_val ); 372 vals[i] = pval; 373 freeval[i] = 1; 374 } 375 } 376 377 if ( ad->ad_type->sat_equality && 378 ad->ad_type->sat_equality->smr_normalize ) 379 { 380 rc = ordered_value_normalize( 381 SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX, 382 ad, 383 ad->ad_type->sat_equality, 384 &vals[i], &nvals[i], NULL ); 385 386 if ( rc ) { 387 Debug( LDAP_DEBUG_ANY, 388 "<= str2entry NULL (smr_normalize %s %d)\n", ad->ad_cname.bv_val, rc, 0 ); 389 goto fail; 390 } 391 } 392 393 attr_cnt++; 394 } 395 } 396 397 free( type ); 398 atail->a_next = NULL; 399 e->e_attrs = ahead.a_next; 400 401 Debug(LDAP_DEBUG_TRACE, "<= str2entry(%s) -> 0x%lx\n", 402 e->e_dn, (unsigned long) e, 0 ); 403 return( e ); 404 405fail: 406 for ( i=0; i<lines; i++ ) { 407 if ( freeval[i] ) free( vals[i].bv_val ); 408 free( nvals[i].bv_val ); 409 } 410 free( type ); 411 entry_free( e ); 412 return NULL; 413} 414 415 416#define GRABSIZE BUFSIZ 417 418#define MAKE_SPACE( n ) { \ 419 while ( ecur + (n) > ebuf + emaxsize ) { \ 420 ptrdiff_t offset; \ 421 offset = (int) (ecur - ebuf); \ 422 ebuf = ch_realloc( ebuf, \ 423 emaxsize + GRABSIZE ); \ 424 emaxsize += GRABSIZE; \ 425 ecur = ebuf + offset; \ 426 } \ 427 } 428 429/* NOTE: only preserved for binary compatibility */ 430char * 431entry2str( 432 Entry *e, 433 int *len ) 434{ 435 return entry2str_wrap( e, len, LDIF_LINE_WIDTH ); 436} 437 438char * 439entry2str_wrap( 440 Entry *e, 441 int *len, 442 ber_len_t wrap ) 443{ 444 Attribute *a; 445 struct berval *bv; 446 int i; 447 ber_len_t tmplen; 448 449 assert( e != NULL ); 450 451 /* 452 * In string format, an entry looks like this: 453 * dn: <dn>\n 454 * [<attr>: <value>\n]* 455 */ 456 457 ecur = ebuf; 458 459 /* put the dn */ 460 if ( e->e_dn != NULL ) { 461 /* put "dn: <dn>" */ 462 tmplen = e->e_name.bv_len; 463 MAKE_SPACE( LDIF_SIZE_NEEDED( 2, tmplen )); 464 ldif_sput_wrap( &ecur, LDIF_PUT_VALUE, "dn", e->e_dn, tmplen, wrap ); 465 } 466 467 /* put the attributes */ 468 for ( a = e->e_attrs; a != NULL; a = a->a_next ) { 469 /* put "<type>:[:] <value>" line for each value */ 470 for ( i = 0; a->a_vals[i].bv_val != NULL; i++ ) { 471 bv = &a->a_vals[i]; 472 tmplen = a->a_desc->ad_cname.bv_len; 473 MAKE_SPACE( LDIF_SIZE_NEEDED( tmplen, bv->bv_len )); 474 ldif_sput_wrap( &ecur, LDIF_PUT_VALUE, 475 a->a_desc->ad_cname.bv_val, 476 bv->bv_val, bv->bv_len, wrap ); 477 } 478 } 479 MAKE_SPACE( 1 ); 480 *ecur = '\0'; 481 *len = ecur - ebuf; 482 483 return( ebuf ); 484} 485 486void 487entry_clean( Entry *e ) 488{ 489 /* free an entry structure */ 490 assert( e != NULL ); 491 492 /* e_private must be freed by the caller */ 493 assert( e->e_private == NULL ); 494 495 e->e_id = 0; 496 497 /* free DNs */ 498 if ( !BER_BVISNULL( &e->e_name ) ) { 499 free( e->e_name.bv_val ); 500 BER_BVZERO( &e->e_name ); 501 } 502 if ( !BER_BVISNULL( &e->e_nname ) ) { 503 free( e->e_nname.bv_val ); 504 BER_BVZERO( &e->e_nname ); 505 } 506 507 if ( !BER_BVISNULL( &e->e_bv ) ) { 508 free( e->e_bv.bv_val ); 509 BER_BVZERO( &e->e_bv ); 510 } 511 512 /* free attributes */ 513 if ( e->e_attrs ) { 514 attrs_free( e->e_attrs ); 515 e->e_attrs = NULL; 516 } 517 518 e->e_ocflags = 0; 519} 520 521void 522entry_free( Entry *e ) 523{ 524 entry_clean( e ); 525 526 ldap_pvt_thread_mutex_lock( &entry_mutex ); 527 e->e_private = entry_list; 528 entry_list = e; 529 ldap_pvt_thread_mutex_unlock( &entry_mutex ); 530} 531 532/* These parameters work well on AMD64 */ 533#if 0 534#define STRIDE 8 535#define STRIPE 5 536#else 537#define STRIDE 1 538#define STRIPE 1 539#endif 540#define STRIDE_FACTOR (STRIDE*STRIPE) 541 542int 543entry_prealloc( int num ) 544{ 545 Entry *e, **prev, *tmp; 546 slap_list *s; 547 int i, j; 548 549 if (!num) return 0; 550 551#if STRIDE_FACTOR > 1 552 /* Round up to our stride factor */ 553 num += STRIDE_FACTOR-1; 554 num /= STRIDE_FACTOR; 555 num *= STRIDE_FACTOR; 556#endif 557 558 s = ch_calloc( 1, sizeof(slap_list) + num * sizeof(Entry)); 559 s->next = entry_chunks; 560 entry_chunks = s; 561 562 prev = &tmp; 563 for (i=0; i<STRIPE; i++) { 564 e = (Entry *)(s+1); 565 e += i; 566 for (j=i; j<num; j+= STRIDE) { 567 *prev = e; 568 prev = (Entry **)&e->e_private; 569 e += STRIDE; 570 } 571 } 572 *prev = entry_list; 573 entry_list = (Entry *)(s+1); 574 575 return 0; 576} 577 578Entry * 579entry_alloc( void ) 580{ 581 Entry *e; 582 583 ldap_pvt_thread_mutex_lock( &entry_mutex ); 584 if ( !entry_list ) 585 entry_prealloc( CHUNK_SIZE ); 586 e = entry_list; 587 entry_list = e->e_private; 588 e->e_private = NULL; 589 ldap_pvt_thread_mutex_unlock( &entry_mutex ); 590 591 return e; 592} 593 594 595/* 596 * These routines are used only by Backend. 597 * 598 * the Entry has three entry points (ways to find things): 599 * 600 * by entry e.g., if you already have an entry from the cache 601 * and want to delete it. (really by entry ptr) 602 * by dn e.g., when looking for the base object of a search 603 * by id e.g., for search candidates 604 * 605 * these correspond to three different avl trees that are maintained. 606 */ 607 608int 609entry_cmp( Entry *e1, Entry *e2 ) 610{ 611 return SLAP_PTRCMP( e1, e2 ); 612} 613 614int 615entry_dn_cmp( const void *v_e1, const void *v_e2 ) 616{ 617 /* compare their normalized UPPERCASED dn's */ 618 const Entry *e1 = v_e1, *e2 = v_e2; 619 620 return ber_bvcmp( &e1->e_nname, &e2->e_nname ); 621} 622 623int 624entry_id_cmp( const void *v_e1, const void *v_e2 ) 625{ 626 const Entry *e1 = v_e1, *e2 = v_e2; 627 return( e1->e_id < e2->e_id ? -1 : (e1->e_id > e2->e_id ? 1 : 0) ); 628} 629 630/* This is like a ber_len */ 631#define entry_lenlen(l) (((l) < 0x80) ? 1 : ((l) < 0x100) ? 2 : \ 632 ((l) < 0x10000) ? 3 : ((l) < 0x1000000) ? 4 : 5) 633 634static void 635entry_putlen(unsigned char **buf, ber_len_t len) 636{ 637 ber_len_t lenlen = entry_lenlen(len); 638 639 if (lenlen == 1) { 640 **buf = (unsigned char) len; 641 } else { 642 int i; 643 **buf = 0x80 | ((unsigned char) lenlen - 1); 644 for (i=lenlen-1; i>0; i--) { 645 (*buf)[i] = (unsigned char) len; 646 len >>= 8; 647 } 648 } 649 *buf += lenlen; 650} 651 652static ber_len_t 653entry_getlen(unsigned char **buf) 654{ 655 ber_len_t len; 656 int i; 657 658 len = *(*buf)++; 659 if (len <= 0x7f) 660 return len; 661 i = len & 0x7f; 662 len = 0; 663 for (;i > 0; i--) { 664 len <<= 8; 665 len |= *(*buf)++; 666 } 667 return len; 668} 669 670/* Count up the sizes of the components of an entry */ 671void entry_partsize(Entry *e, ber_len_t *plen, 672 int *pnattrs, int *pnvals, int norm) 673{ 674 ber_len_t len, dnlen, ndnlen; 675 int i, nat = 0, nval = 0; 676 Attribute *a; 677 678 dnlen = e->e_name.bv_len; 679 len = dnlen + 1; /* trailing NUL byte */ 680 len += entry_lenlen(dnlen); 681 if (norm) { 682 ndnlen = e->e_nname.bv_len; 683 len += ndnlen + 1; 684 len += entry_lenlen(ndnlen); 685 } 686 for (a=e->e_attrs; a; a=a->a_next) { 687 /* For AttributeDesc, we only store the attr name */ 688 nat++; 689 len += a->a_desc->ad_cname.bv_len+1; 690 len += entry_lenlen(a->a_desc->ad_cname.bv_len); 691 for (i=0; a->a_vals[i].bv_val; i++) { 692 nval++; 693 len += a->a_vals[i].bv_len + 1; 694 len += entry_lenlen(a->a_vals[i].bv_len); 695 } 696 len += entry_lenlen(i); 697 nval++; /* empty berval at end */ 698 if (norm && a->a_nvals != a->a_vals) { 699 for (i=0; a->a_nvals[i].bv_val; i++) { 700 nval++; 701 len += a->a_nvals[i].bv_len + 1; 702 len += entry_lenlen(a->a_nvals[i].bv_len); 703 } 704 len += entry_lenlen(i); /* i nvals */ 705 nval++; 706 } else { 707 len += entry_lenlen(0); /* 0 nvals */ 708 } 709 } 710 len += entry_lenlen(nat); 711 len += entry_lenlen(nval); 712 *plen = len; 713 *pnattrs = nat; 714 *pnvals = nval; 715} 716 717/* Add up the size of the entry for a flattened buffer */ 718ber_len_t entry_flatsize(Entry *e, int norm) 719{ 720 ber_len_t len; 721 int nattrs, nvals; 722 723 entry_partsize(e, &len, &nattrs, &nvals, norm); 724 len += sizeof(Entry) + (nattrs * sizeof(Attribute)) + 725 (nvals * sizeof(struct berval)); 726 return len; 727} 728 729/* Flatten an Entry into a buffer. The buffer is filled with just the 730 * strings/bervals of all the entry components. Each field is preceded 731 * by its length, encoded the way ber_put_len works. Every field is NUL 732 * terminated. The entire buffer size is precomputed so that a single 733 * malloc can be performed. The entry size is also recorded, 734 * to aid in entry_decode. 735 */ 736int entry_encode(Entry *e, struct berval *bv) 737{ 738 ber_len_t len, dnlen, ndnlen, i; 739 int nattrs, nvals; 740 Attribute *a; 741 unsigned char *ptr; 742 743 Debug( LDAP_DEBUG_TRACE, "=> entry_encode(0x%08lx): %s\n", 744 (long) e->e_id, e->e_dn, 0 ); 745 746 dnlen = e->e_name.bv_len; 747 ndnlen = e->e_nname.bv_len; 748 749 entry_partsize( e, &len, &nattrs, &nvals, 1 ); 750 751 bv->bv_len = len; 752 bv->bv_val = ch_malloc(len); 753 ptr = (unsigned char *)bv->bv_val; 754 entry_putlen(&ptr, nattrs); 755 entry_putlen(&ptr, nvals); 756 entry_putlen(&ptr, dnlen); 757 AC_MEMCPY(ptr, e->e_dn, dnlen); 758 ptr += dnlen; 759 *ptr++ = '\0'; 760 entry_putlen(&ptr, ndnlen); 761 AC_MEMCPY(ptr, e->e_ndn, ndnlen); 762 ptr += ndnlen; 763 *ptr++ = '\0'; 764 765 for (a=e->e_attrs; a; a=a->a_next) { 766 entry_putlen(&ptr, a->a_desc->ad_cname.bv_len); 767 AC_MEMCPY(ptr, a->a_desc->ad_cname.bv_val, 768 a->a_desc->ad_cname.bv_len); 769 ptr += a->a_desc->ad_cname.bv_len; 770 *ptr++ = '\0'; 771 if (a->a_vals) { 772 for (i=0; a->a_vals[i].bv_val; i++); 773 assert( i == a->a_numvals ); 774 entry_putlen(&ptr, i); 775 for (i=0; a->a_vals[i].bv_val; i++) { 776 entry_putlen(&ptr, a->a_vals[i].bv_len); 777 AC_MEMCPY(ptr, a->a_vals[i].bv_val, 778 a->a_vals[i].bv_len); 779 ptr += a->a_vals[i].bv_len; 780 *ptr++ = '\0'; 781 } 782 if (a->a_nvals != a->a_vals) { 783 entry_putlen(&ptr, i); 784 for (i=0; a->a_nvals[i].bv_val; i++) { 785 entry_putlen(&ptr, a->a_nvals[i].bv_len); 786 AC_MEMCPY(ptr, a->a_nvals[i].bv_val, 787 a->a_nvals[i].bv_len); 788 ptr += a->a_nvals[i].bv_len; 789 *ptr++ = '\0'; 790 } 791 } else { 792 entry_putlen(&ptr, 0); 793 } 794 } 795 } 796 797 Debug( LDAP_DEBUG_TRACE, "<= entry_encode(0x%08lx): %s\n", 798 (long) e->e_id, e->e_dn, 0 ); 799 800 return 0; 801} 802 803/* Retrieve an Entry that was stored using entry_encode above. 804 * First entry_header must be called to decode the size of the entry. 805 * Then a single block of memory must be malloc'd to accomodate the 806 * bervals and the bulk data. Next the bulk data is retrieved from 807 * the DB and parsed by entry_decode. 808 * 809 * Note: everything is stored in a single contiguous block, so 810 * you can not free individual attributes or names from this 811 * structure. Attempting to do so will likely corrupt memory. 812 */ 813int entry_header(EntryHeader *eh) 814{ 815 unsigned char *ptr = (unsigned char *)eh->bv.bv_val; 816 817 /* Some overlays can create empty entries 818 * so don't check for zeros here. 819 */ 820 eh->nattrs = entry_getlen(&ptr); 821 eh->nvals = entry_getlen(&ptr); 822 eh->data = (char *)ptr; 823 return LDAP_SUCCESS; 824} 825 826int 827entry_decode_dn( EntryHeader *eh, struct berval *dn, struct berval *ndn ) 828{ 829 int i; 830 unsigned char *ptr = (unsigned char *)eh->bv.bv_val; 831 832 assert( dn != NULL || ndn != NULL ); 833 834 ptr = (unsigned char *)eh->data; 835 i = entry_getlen(&ptr); 836 if ( dn != NULL ) { 837 dn->bv_val = (char *) ptr; 838 dn->bv_len = i; 839 } 840 841 if ( ndn != NULL ) { 842 ptr += i + 1; 843 i = entry_getlen(&ptr); 844 ndn->bv_val = (char *) ptr; 845 ndn->bv_len = i; 846 } 847 848 Debug( LDAP_DEBUG_TRACE, 849 "entry_decode_dn: \"%s\"\n", 850 dn ? dn->bv_val : ndn->bv_val, 0, 0 ); 851 852 return 0; 853} 854 855#ifdef SLAP_ZONE_ALLOC 856int entry_decode(EntryHeader *eh, Entry **e, void *ctx) 857#else 858int entry_decode(EntryHeader *eh, Entry **e) 859#endif 860{ 861 int i, j, nattrs, nvals; 862 int rc; 863 Attribute *a; 864 Entry *x; 865 const char *text; 866 AttributeDescription *ad; 867 unsigned char *ptr = (unsigned char *)eh->bv.bv_val; 868 BerVarray bptr; 869 870 nattrs = eh->nattrs; 871 nvals = eh->nvals; 872 x = entry_alloc(); 873 x->e_attrs = attrs_alloc( nattrs ); 874 ptr = (unsigned char *)eh->data; 875 i = entry_getlen(&ptr); 876 x->e_name.bv_val = (char *) ptr; 877 x->e_name.bv_len = i; 878 ptr += i+1; 879 i = entry_getlen(&ptr); 880 x->e_nname.bv_val = (char *) ptr; 881 x->e_nname.bv_len = i; 882 ptr += i+1; 883 Debug( LDAP_DEBUG_TRACE, 884 "entry_decode: \"%s\"\n", 885 x->e_dn, 0, 0 ); 886 x->e_bv = eh->bv; 887 888 a = x->e_attrs; 889 bptr = (BerVarray)eh->bv.bv_val; 890 891 while ((i = entry_getlen(&ptr))) { 892 struct berval bv; 893 bv.bv_len = i; 894 bv.bv_val = (char *) ptr; 895 ad = NULL; 896 rc = slap_bv2ad( &bv, &ad, &text ); 897 898 if( rc != LDAP_SUCCESS ) { 899 Debug( LDAP_DEBUG_TRACE, 900 "<= entry_decode: str2ad(%s): %s\n", ptr, text, 0 ); 901 rc = slap_bv2undef_ad( &bv, &ad, &text, 0 ); 902 903 if( rc != LDAP_SUCCESS ) { 904 Debug( LDAP_DEBUG_ANY, 905 "<= entry_decode: slap_str2undef_ad(%s): %s\n", 906 ptr, text, 0 ); 907 return rc; 908 } 909 } 910 ptr += i + 1; 911 a->a_desc = ad; 912 a->a_flags = SLAP_ATTR_DONT_FREE_DATA | SLAP_ATTR_DONT_FREE_VALS; 913 j = entry_getlen(&ptr); 914 a->a_numvals = j; 915 a->a_vals = bptr; 916 917 while (j) { 918 i = entry_getlen(&ptr); 919 bptr->bv_len = i; 920 bptr->bv_val = (char *)ptr; 921 ptr += i+1; 922 bptr++; 923 j--; 924 } 925 bptr->bv_val = NULL; 926 bptr->bv_len = 0; 927 bptr++; 928 929 j = entry_getlen(&ptr); 930 if (j) { 931 a->a_nvals = bptr; 932 while (j) { 933 i = entry_getlen(&ptr); 934 bptr->bv_len = i; 935 bptr->bv_val = (char *)ptr; 936 ptr += i+1; 937 bptr++; 938 j--; 939 } 940 bptr->bv_val = NULL; 941 bptr->bv_len = 0; 942 bptr++; 943 } else { 944 a->a_nvals = a->a_vals; 945 } 946 /* FIXME: This is redundant once a sorted entry is saved into the DB */ 947 if ( a->a_desc->ad_type->sat_flags & SLAP_AT_SORTED_VAL ) { 948 rc = slap_sort_vals( (Modifications *)a, &text, &j, NULL ); 949 if ( rc == LDAP_SUCCESS ) { 950 a->a_flags |= SLAP_ATTR_SORTED_VALS; 951 } else if ( rc == LDAP_TYPE_OR_VALUE_EXISTS ) { 952 /* should never happen */ 953 Debug( LDAP_DEBUG_ANY, 954 "entry_decode: attributeType %s value #%d provided more than once\n", 955 a->a_desc->ad_cname.bv_val, j, 0 ); 956 return rc; 957 } 958 } 959 a = a->a_next; 960 nattrs--; 961 if ( !nattrs ) 962 break; 963 } 964 965 Debug(LDAP_DEBUG_TRACE, "<= entry_decode(%s)\n", 966 x->e_dn, 0, 0 ); 967 *e = x; 968 return 0; 969} 970 971Entry * 972entry_dup2( Entry *dest, Entry *source ) 973{ 974 assert( dest != NULL ); 975 assert( source != NULL ); 976 977 assert( dest->e_private == NULL ); 978 979 dest->e_id = source->e_id; 980 ber_dupbv( &dest->e_name, &source->e_name ); 981 ber_dupbv( &dest->e_nname, &source->e_nname ); 982 dest->e_attrs = attrs_dup( source->e_attrs ); 983 dest->e_ocflags = source->e_ocflags; 984 985 return dest; 986} 987 988Entry * 989entry_dup( Entry *e ) 990{ 991 return entry_dup2( entry_alloc(), e ); 992} 993 994#if 1 995/* Duplicates an entry using a single malloc. Saves CPU time, increases 996 * heap usage because a single large malloc is harder to satisfy than 997 * lots of small ones, and the freed space isn't as easily reusable. 998 * 999 * Probably not worth using this function. 1000 */ 1001Entry *entry_dup_bv( Entry *e ) 1002{ 1003 ber_len_t len; 1004 int nattrs, nvals; 1005 Entry *ret; 1006 struct berval *bvl; 1007 char *ptr; 1008 Attribute *src, *dst; 1009 1010 ret = entry_alloc(); 1011 1012 entry_partsize(e, &len, &nattrs, &nvals, 1); 1013 ret->e_id = e->e_id; 1014 ret->e_attrs = attrs_alloc( nattrs ); 1015 ret->e_ocflags = e->e_ocflags; 1016 ret->e_bv.bv_len = len + nvals * sizeof(struct berval); 1017 ret->e_bv.bv_val = ch_malloc( ret->e_bv.bv_len ); 1018 1019 bvl = (struct berval *)ret->e_bv.bv_val; 1020 ptr = (char *)(bvl + nvals); 1021 1022 ret->e_name.bv_len = e->e_name.bv_len; 1023 ret->e_name.bv_val = ptr; 1024 AC_MEMCPY( ptr, e->e_name.bv_val, e->e_name.bv_len ); 1025 ptr += e->e_name.bv_len; 1026 *ptr++ = '\0'; 1027 1028 ret->e_nname.bv_len = e->e_nname.bv_len; 1029 ret->e_nname.bv_val = ptr; 1030 AC_MEMCPY( ptr, e->e_nname.bv_val, e->e_nname.bv_len ); 1031 ptr += e->e_name.bv_len; 1032 *ptr++ = '\0'; 1033 1034 dst = ret->e_attrs; 1035 for (src = e->e_attrs; src; src=src->a_next,dst=dst->a_next ) { 1036 int i; 1037 dst->a_desc = src->a_desc; 1038 dst->a_flags = SLAP_ATTR_DONT_FREE_DATA | SLAP_ATTR_DONT_FREE_VALS; 1039 dst->a_vals = bvl; 1040 dst->a_numvals = src->a_numvals; 1041 for ( i=0; src->a_vals[i].bv_val; i++ ) { 1042 bvl->bv_len = src->a_vals[i].bv_len; 1043 bvl->bv_val = ptr; 1044 AC_MEMCPY( ptr, src->a_vals[i].bv_val, bvl->bv_len ); 1045 ptr += bvl->bv_len; 1046 *ptr++ = '\0'; 1047 bvl++; 1048 } 1049 BER_BVZERO(bvl); 1050 bvl++; 1051 if ( src->a_vals != src->a_nvals ) { 1052 dst->a_nvals = bvl; 1053 for ( i=0; src->a_nvals[i].bv_val; i++ ) { 1054 bvl->bv_len = src->a_nvals[i].bv_len; 1055 bvl->bv_val = ptr; 1056 AC_MEMCPY( ptr, src->a_nvals[i].bv_val, bvl->bv_len ); 1057 ptr += bvl->bv_len; 1058 *ptr++ = '\0'; 1059 bvl++; 1060 } 1061 BER_BVZERO(bvl); 1062 bvl++; 1063 } 1064 } 1065 return ret; 1066} 1067#endif 1068