1 /* entry.c - routines for dealing with entries */ 2 /* $OpenLDAP: pkg/ldap/servers/slapd/entry.c,v 1.148.2.7 2008/02/11 23:43:39 quanah Exp $ */ 3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>. 4 * 5 * Copyright 1998-2008 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 39 static char *ebuf; /* buf returned by entry2str */ 40 static char *ecur; /* pointer to end of currently used ebuf */ 41 static int emaxsize;/* max size of ebuf */ 42 43 /* 44 * Empty root entry 45 */ 46 const 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 */ 54 ldap_pvt_thread_mutex_t entry2str_mutex; 55 56 static 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 64 typedef struct slap_list { 65 struct slap_list *next; 66 } slap_list; 67 static slap_list *entry_chunks; 68 static Entry *entry_list; 69 static ldap_pvt_thread_mutex_t entry_mutex; 70 71 int 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 89 int 90 entry_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 97 Entry * 98 str2entry( char *s ) 99 { 100 return str2entry2( s, 1 ); 101 } 102 103 #define bvcasematch(bv1, bv2) (ber_bvstrcasecmp(bv1, bv2) == 0) 104 105 Entry * 106 str2entry2( 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 405 fail: 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 char * 430 entry2str( 431 Entry *e, 432 int *len ) 433 { 434 Attribute *a; 435 struct berval *bv; 436 int i; 437 ber_len_t tmplen; 438 439 assert( e != NULL ); 440 441 /* 442 * In string format, an entry looks like this: 443 * dn: <dn>\n 444 * [<attr>: <value>\n]* 445 */ 446 447 ecur = ebuf; 448 449 /* put the dn */ 450 if ( e->e_dn != NULL ) { 451 /* put "dn: <dn>" */ 452 tmplen = e->e_name.bv_len; 453 MAKE_SPACE( LDIF_SIZE_NEEDED( 2, tmplen )); 454 ldif_sput( &ecur, LDIF_PUT_VALUE, "dn", e->e_dn, tmplen ); 455 } 456 457 /* put the attributes */ 458 for ( a = e->e_attrs; a != NULL; a = a->a_next ) { 459 /* put "<type>:[:] <value>" line for each value */ 460 for ( i = 0; a->a_vals[i].bv_val != NULL; i++ ) { 461 bv = &a->a_vals[i]; 462 tmplen = a->a_desc->ad_cname.bv_len; 463 MAKE_SPACE( LDIF_SIZE_NEEDED( tmplen, bv->bv_len )); 464 ldif_sput( &ecur, LDIF_PUT_VALUE, 465 a->a_desc->ad_cname.bv_val, 466 bv->bv_val, bv->bv_len ); 467 } 468 } 469 MAKE_SPACE( 1 ); 470 *ecur = '\0'; 471 *len = ecur - ebuf; 472 473 return( ebuf ); 474 } 475 476 void 477 entry_clean( Entry *e ) 478 { 479 /* free an entry structure */ 480 assert( e != NULL ); 481 482 /* e_private must be freed by the caller */ 483 assert( e->e_private == NULL ); 484 485 e->e_id = 0; 486 487 /* free DNs */ 488 if ( !BER_BVISNULL( &e->e_name ) ) { 489 free( e->e_name.bv_val ); 490 BER_BVZERO( &e->e_name ); 491 } 492 if ( !BER_BVISNULL( &e->e_nname ) ) { 493 free( e->e_nname.bv_val ); 494 BER_BVZERO( &e->e_nname ); 495 } 496 497 if ( !BER_BVISNULL( &e->e_bv ) ) { 498 free( e->e_bv.bv_val ); 499 BER_BVZERO( &e->e_bv ); 500 } 501 502 /* free attributes */ 503 if ( e->e_attrs ) { 504 attrs_free( e->e_attrs ); 505 e->e_attrs = NULL; 506 } 507 508 e->e_ocflags = 0; 509 } 510 511 void 512 entry_free( Entry *e ) 513 { 514 entry_clean( e ); 515 516 ldap_pvt_thread_mutex_lock( &entry_mutex ); 517 e->e_private = entry_list; 518 entry_list = e; 519 ldap_pvt_thread_mutex_unlock( &entry_mutex ); 520 } 521 522 /* These parameters work well on AMD64 */ 523 #if 0 524 #define STRIDE 8 525 #define STRIPE 5 526 #else 527 #define STRIDE 1 528 #define STRIPE 1 529 #endif 530 #define STRIDE_FACTOR (STRIDE*STRIPE) 531 532 int 533 entry_prealloc( int num ) 534 { 535 Entry *e, **prev, *tmp; 536 slap_list *s; 537 int i, j; 538 539 if (!num) return 0; 540 541 #if STRIDE_FACTOR > 1 542 /* Round up to our stride factor */ 543 num += STRIDE_FACTOR-1; 544 num /= STRIDE_FACTOR; 545 num *= STRIDE_FACTOR; 546 #endif 547 548 s = ch_calloc( 1, sizeof(slap_list) + num * sizeof(Entry)); 549 s->next = entry_chunks; 550 entry_chunks = s; 551 552 prev = &tmp; 553 for (i=0; i<STRIPE; i++) { 554 e = (Entry *)(s+1); 555 e += i; 556 for (j=i; j<num; j+= STRIDE) { 557 *prev = e; 558 prev = (Entry **)&e->e_private; 559 e += STRIDE; 560 } 561 } 562 *prev = entry_list; 563 entry_list = (Entry *)(s+1); 564 565 return 0; 566 } 567 568 Entry * 569 entry_alloc( void ) 570 { 571 Entry *e; 572 573 ldap_pvt_thread_mutex_lock( &entry_mutex ); 574 if ( !entry_list ) 575 entry_prealloc( CHUNK_SIZE ); 576 e = entry_list; 577 entry_list = e->e_private; 578 e->e_private = NULL; 579 ldap_pvt_thread_mutex_unlock( &entry_mutex ); 580 581 return e; 582 } 583 584 585 /* 586 * These routines are used only by Backend. 587 * 588 * the Entry has three entry points (ways to find things): 589 * 590 * by entry e.g., if you already have an entry from the cache 591 * and want to delete it. (really by entry ptr) 592 * by dn e.g., when looking for the base object of a search 593 * by id e.g., for search candidates 594 * 595 * these correspond to three different avl trees that are maintained. 596 */ 597 598 int 599 entry_cmp( Entry *e1, Entry *e2 ) 600 { 601 return SLAP_PTRCMP( e1, e2 ); 602 } 603 604 int 605 entry_dn_cmp( const void *v_e1, const void *v_e2 ) 606 { 607 /* compare their normalized UPPERCASED dn's */ 608 const Entry *e1 = v_e1, *e2 = v_e2; 609 610 return ber_bvcmp( &e1->e_nname, &e2->e_nname ); 611 } 612 613 int 614 entry_id_cmp( const void *v_e1, const void *v_e2 ) 615 { 616 const Entry *e1 = v_e1, *e2 = v_e2; 617 return( e1->e_id < e2->e_id ? -1 : (e1->e_id > e2->e_id ? 1 : 0) ); 618 } 619 620 /* This is like a ber_len */ 621 #define entry_lenlen(l) (((l) < 0x80) ? 1 : ((l) < 0x100) ? 2 : \ 622 ((l) < 0x10000) ? 3 : ((l) < 0x1000000) ? 4 : 5) 623 624 static void 625 entry_putlen(unsigned char **buf, ber_len_t len) 626 { 627 ber_len_t lenlen = entry_lenlen(len); 628 629 if (lenlen == 1) { 630 **buf = (unsigned char) len; 631 } else { 632 int i; 633 **buf = 0x80 | ((unsigned char) lenlen - 1); 634 for (i=lenlen-1; i>0; i--) { 635 (*buf)[i] = (unsigned char) len; 636 len >>= 8; 637 } 638 } 639 *buf += lenlen; 640 } 641 642 static ber_len_t 643 entry_getlen(unsigned char **buf) 644 { 645 ber_len_t len; 646 int i; 647 648 len = *(*buf)++; 649 if (len <= 0x7f) 650 return len; 651 i = len & 0x7f; 652 len = 0; 653 for (;i > 0; i--) { 654 len <<= 8; 655 len |= *(*buf)++; 656 } 657 return len; 658 } 659 660 /* Count up the sizes of the components of an entry */ 661 void entry_partsize(Entry *e, ber_len_t *plen, 662 int *pnattrs, int *pnvals, int norm) 663 { 664 ber_len_t len, dnlen, ndnlen; 665 int i, nat = 0, nval = 0; 666 Attribute *a; 667 668 dnlen = e->e_name.bv_len; 669 len = dnlen + 1; /* trailing NUL byte */ 670 len += entry_lenlen(dnlen); 671 if (norm) { 672 ndnlen = e->e_nname.bv_len; 673 len += ndnlen + 1; 674 len += entry_lenlen(ndnlen); 675 } 676 for (a=e->e_attrs; a; a=a->a_next) { 677 /* For AttributeDesc, we only store the attr name */ 678 nat++; 679 len += a->a_desc->ad_cname.bv_len+1; 680 len += entry_lenlen(a->a_desc->ad_cname.bv_len); 681 for (i=0; a->a_vals[i].bv_val; i++) { 682 nval++; 683 len += a->a_vals[i].bv_len + 1; 684 len += entry_lenlen(a->a_vals[i].bv_len); 685 } 686 len += entry_lenlen(i); 687 nval++; /* empty berval at end */ 688 if (norm && a->a_nvals != a->a_vals) { 689 for (i=0; a->a_nvals[i].bv_val; i++) { 690 nval++; 691 len += a->a_nvals[i].bv_len + 1; 692 len += entry_lenlen(a->a_nvals[i].bv_len); 693 } 694 len += entry_lenlen(i); /* i nvals */ 695 nval++; 696 } else { 697 len += entry_lenlen(0); /* 0 nvals */ 698 } 699 } 700 len += entry_lenlen(nat); 701 len += entry_lenlen(nval); 702 *plen = len; 703 *pnattrs = nat; 704 *pnvals = nval; 705 } 706 707 /* Add up the size of the entry for a flattened buffer */ 708 ber_len_t entry_flatsize(Entry *e, int norm) 709 { 710 ber_len_t len; 711 int nattrs, nvals; 712 713 entry_partsize(e, &len, &nattrs, &nvals, norm); 714 len += sizeof(Entry) + (nattrs * sizeof(Attribute)) + 715 (nvals * sizeof(struct berval)); 716 return len; 717 } 718 719 /* Flatten an Entry into a buffer. The buffer is filled with just the 720 * strings/bervals of all the entry components. Each field is preceded 721 * by its length, encoded the way ber_put_len works. Every field is NUL 722 * terminated. The entire buffer size is precomputed so that a single 723 * malloc can be performed. The entry size is also recorded, 724 * to aid in entry_decode. 725 */ 726 int entry_encode(Entry *e, struct berval *bv) 727 { 728 ber_len_t len, dnlen, ndnlen; 729 int i, nattrs, nvals; 730 Attribute *a; 731 unsigned char *ptr; 732 733 Debug( LDAP_DEBUG_TRACE, "=> entry_encode(0x%08lx): %s\n", 734 (long) e->e_id, e->e_dn, 0 ); 735 dnlen = e->e_name.bv_len; 736 ndnlen = e->e_nname.bv_len; 737 738 entry_partsize( e, &len, &nattrs, &nvals, 1 ); 739 740 bv->bv_len = len; 741 bv->bv_val = ch_malloc(len); 742 ptr = (unsigned char *)bv->bv_val; 743 entry_putlen(&ptr, nattrs); 744 entry_putlen(&ptr, nvals); 745 entry_putlen(&ptr, dnlen); 746 AC_MEMCPY(ptr, e->e_dn, dnlen); 747 ptr += dnlen; 748 *ptr++ = '\0'; 749 entry_putlen(&ptr, ndnlen); 750 AC_MEMCPY(ptr, e->e_ndn, ndnlen); 751 ptr += ndnlen; 752 *ptr++ = '\0'; 753 754 for (a=e->e_attrs; a; a=a->a_next) { 755 entry_putlen(&ptr, a->a_desc->ad_cname.bv_len); 756 AC_MEMCPY(ptr, a->a_desc->ad_cname.bv_val, 757 a->a_desc->ad_cname.bv_len); 758 ptr += a->a_desc->ad_cname.bv_len; 759 *ptr++ = '\0'; 760 if (a->a_vals) { 761 for (i=0; a->a_vals[i].bv_val; i++); 762 assert( i == a->a_numvals ); 763 entry_putlen(&ptr, i); 764 for (i=0; a->a_vals[i].bv_val; i++) { 765 entry_putlen(&ptr, a->a_vals[i].bv_len); 766 AC_MEMCPY(ptr, a->a_vals[i].bv_val, 767 a->a_vals[i].bv_len); 768 ptr += a->a_vals[i].bv_len; 769 *ptr++ = '\0'; 770 } 771 if (a->a_nvals != a->a_vals) { 772 entry_putlen(&ptr, i); 773 for (i=0; a->a_nvals[i].bv_val; i++) { 774 entry_putlen(&ptr, a->a_nvals[i].bv_len); 775 AC_MEMCPY(ptr, a->a_nvals[i].bv_val, 776 a->a_nvals[i].bv_len); 777 ptr += a->a_nvals[i].bv_len; 778 *ptr++ = '\0'; 779 } 780 } else { 781 entry_putlen(&ptr, 0); 782 } 783 } 784 } 785 return 0; 786 } 787 788 /* Retrieve an Entry that was stored using entry_encode above. 789 * First entry_header must be called to decode the size of the entry. 790 * Then a single block of memory must be malloc'd to accomodate the 791 * bervals and the bulk data. Next the bulk data is retrieved from 792 * the DB and parsed by entry_decode. 793 * 794 * Note: everything is stored in a single contiguous block, so 795 * you can not free individual attributes or names from this 796 * structure. Attempting to do so will likely corrupt memory. 797 */ 798 int entry_header(EntryHeader *eh) 799 { 800 unsigned char *ptr = (unsigned char *)eh->bv.bv_val; 801 802 eh->nattrs = entry_getlen(&ptr); 803 if ( !eh->nattrs ) { 804 Debug( LDAP_DEBUG_ANY, 805 "entry_header: attribute count was zero\n", 0, 0, 0); 806 return LDAP_OTHER; 807 } 808 eh->nvals = entry_getlen(&ptr); 809 if ( !eh->nvals ) { 810 Debug( LDAP_DEBUG_ANY, 811 "entry_header: value count was zero\n", 0, 0, 0); 812 return LDAP_OTHER; 813 } 814 eh->data = (char *)ptr; 815 return LDAP_SUCCESS; 816 } 817 818 #ifdef SLAP_ZONE_ALLOC 819 int entry_decode(EntryHeader *eh, Entry **e, void *ctx) 820 #else 821 int entry_decode(EntryHeader *eh, Entry **e) 822 #endif 823 { 824 int i, j, nattrs, nvals; 825 int rc; 826 Attribute *a; 827 Entry *x; 828 const char *text; 829 AttributeDescription *ad; 830 unsigned char *ptr = (unsigned char *)eh->bv.bv_val; 831 BerVarray bptr; 832 833 nattrs = eh->nattrs; 834 nvals = eh->nvals; 835 x = entry_alloc(); 836 x->e_attrs = attrs_alloc( nattrs ); 837 ptr = (unsigned char *)eh->data; 838 i = entry_getlen(&ptr); 839 x->e_name.bv_val = (char *) ptr; 840 x->e_name.bv_len = i; 841 ptr += i+1; 842 i = entry_getlen(&ptr); 843 x->e_nname.bv_val = (char *) ptr; 844 x->e_nname.bv_len = i; 845 ptr += i+1; 846 Debug( LDAP_DEBUG_TRACE, 847 "entry_decode: \"%s\"\n", 848 x->e_dn, 0, 0 ); 849 x->e_bv = eh->bv; 850 851 a = x->e_attrs; 852 bptr = (BerVarray)eh->bv.bv_val; 853 854 while ((i = entry_getlen(&ptr))) { 855 struct berval bv; 856 bv.bv_len = i; 857 bv.bv_val = (char *) ptr; 858 ad = NULL; 859 rc = slap_bv2ad( &bv, &ad, &text ); 860 861 if( rc != LDAP_SUCCESS ) { 862 Debug( LDAP_DEBUG_TRACE, 863 "<= entry_decode: str2ad(%s): %s\n", ptr, text, 0 ); 864 rc = slap_bv2undef_ad( &bv, &ad, &text, 0 ); 865 866 if( rc != LDAP_SUCCESS ) { 867 Debug( LDAP_DEBUG_ANY, 868 "<= entry_decode: slap_str2undef_ad(%s): %s\n", 869 ptr, text, 0 ); 870 return rc; 871 } 872 } 873 ptr += i + 1; 874 a->a_desc = ad; 875 a->a_flags = SLAP_ATTR_DONT_FREE_DATA | SLAP_ATTR_DONT_FREE_VALS; 876 j = entry_getlen(&ptr); 877 a->a_numvals = j; 878 a->a_vals = bptr; 879 880 while (j) { 881 i = entry_getlen(&ptr); 882 bptr->bv_len = i; 883 bptr->bv_val = (char *)ptr; 884 ptr += i+1; 885 bptr++; 886 j--; 887 } 888 bptr->bv_val = NULL; 889 bptr->bv_len = 0; 890 bptr++; 891 892 j = entry_getlen(&ptr); 893 if (j) { 894 a->a_nvals = bptr; 895 while (j) { 896 i = entry_getlen(&ptr); 897 bptr->bv_len = i; 898 bptr->bv_val = (char *)ptr; 899 ptr += i+1; 900 bptr++; 901 j--; 902 } 903 bptr->bv_val = NULL; 904 bptr->bv_len = 0; 905 bptr++; 906 } else { 907 a->a_nvals = a->a_vals; 908 } 909 /* FIXME: This is redundant once a sorted entry is saved into the DB */ 910 if ( a->a_desc->ad_type->sat_flags & SLAP_AT_SORTED_VAL ) { 911 rc = slap_sort_vals( (Modifications *)a, &text, &j, NULL ); 912 if ( rc == LDAP_SUCCESS ) { 913 a->a_flags |= SLAP_ATTR_SORTED_VALS; 914 } else if ( rc == LDAP_TYPE_OR_VALUE_EXISTS ) { 915 /* should never happen */ 916 Debug( LDAP_DEBUG_ANY, 917 "entry_decode: attributeType %s value #%d provided more than once\n", 918 a->a_desc->ad_cname.bv_val, j, 0 ); 919 return rc; 920 } 921 } 922 a = a->a_next; 923 nattrs--; 924 if ( !nattrs ) 925 break; 926 } 927 928 Debug(LDAP_DEBUG_TRACE, "<= entry_decode(%s)\n", 929 x->e_dn, 0, 0 ); 930 *e = x; 931 return 0; 932 } 933 934 Entry *entry_dup( Entry *e ) 935 { 936 Entry *ret; 937 938 ret = entry_alloc(); 939 940 ret->e_id = e->e_id; 941 ber_dupbv( &ret->e_name, &e->e_name ); 942 ber_dupbv( &ret->e_nname, &e->e_nname ); 943 ret->e_attrs = attrs_dup( e->e_attrs ); 944 ret->e_ocflags = e->e_ocflags; 945 946 return ret; 947 } 948 949 #if 1 950 /* Duplicates an entry using a single malloc. Saves CPU time, increases 951 * heap usage because a single large malloc is harder to satisfy than 952 * lots of small ones, and the freed space isn't as easily reusable. 953 * 954 * Probably not worth using this function. 955 */ 956 Entry *entry_dup_bv( Entry *e ) 957 { 958 ber_len_t len; 959 int nattrs, nvals; 960 Entry *ret; 961 struct berval *bvl; 962 char *ptr; 963 Attribute *src, *dst; 964 965 ret = entry_alloc(); 966 967 entry_partsize(e, &len, &nattrs, &nvals, 1); 968 ret->e_id = e->e_id; 969 ret->e_attrs = attrs_alloc( nattrs ); 970 ret->e_ocflags = e->e_ocflags; 971 ret->e_bv.bv_len = len + nvals * sizeof(struct berval); 972 ret->e_bv.bv_val = ch_malloc( ret->e_bv.bv_len ); 973 974 bvl = (struct berval *)ret->e_bv.bv_val; 975 ptr = (char *)(bvl + nvals); 976 977 ret->e_name.bv_len = e->e_name.bv_len; 978 ret->e_name.bv_val = ptr; 979 AC_MEMCPY( ptr, e->e_name.bv_val, e->e_name.bv_len ); 980 ptr += e->e_name.bv_len; 981 *ptr++ = '\0'; 982 983 ret->e_nname.bv_len = e->e_nname.bv_len; 984 ret->e_nname.bv_val = ptr; 985 AC_MEMCPY( ptr, e->e_nname.bv_val, e->e_nname.bv_len ); 986 ptr += e->e_name.bv_len; 987 *ptr++ = '\0'; 988 989 dst = ret->e_attrs; 990 for (src = e->e_attrs; src; src=src->a_next,dst=dst->a_next ) { 991 int i; 992 dst->a_desc = src->a_desc; 993 dst->a_flags = SLAP_ATTR_DONT_FREE_DATA | SLAP_ATTR_DONT_FREE_VALS; 994 dst->a_vals = bvl; 995 dst->a_numvals = src->a_numvals; 996 for ( i=0; src->a_vals[i].bv_val; i++ ) { 997 bvl->bv_len = src->a_vals[i].bv_len; 998 bvl->bv_val = ptr; 999 AC_MEMCPY( ptr, src->a_vals[i].bv_val, bvl->bv_len ); 1000 ptr += bvl->bv_len; 1001 *ptr++ = '\0'; 1002 bvl++; 1003 } 1004 BER_BVZERO(bvl); 1005 bvl++; 1006 if ( src->a_vals != src->a_nvals ) { 1007 dst->a_nvals = bvl; 1008 for ( i=0; src->a_nvals[i].bv_val; i++ ) { 1009 bvl->bv_len = src->a_nvals[i].bv_len; 1010 bvl->bv_val = ptr; 1011 AC_MEMCPY( ptr, src->a_nvals[i].bv_val, bvl->bv_len ); 1012 ptr += bvl->bv_len; 1013 *ptr++ = '\0'; 1014 bvl++; 1015 } 1016 BER_BVZERO(bvl); 1017 bvl++; 1018 } 1019 } 1020 return ret; 1021 } 1022 #endif 1023