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