xref: /netbsd-src/external/bsd/openldap/dist/servers/slapd/entry.c (revision 376af7d777b42eee10027dba46d5ea44d5db14e7)
1 /*	$NetBSD: entry.c,v 1.1.1.5 2017/02/09 01:46: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-2016 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.1.1.5 2017/02/09 01:46: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", 0, 0 );
141 
142 	e = entry_alloc();
143 
144 	if( e == NULL ) {
145 		Debug( LDAP_DEBUG_ANY,
146 			"<= str2entry NULL (entry allocation failed)\n",
147 			0, 0, 0 );
148 		return( NULL );
149 	}
150 
151 	/* initialize entry */
152 	e->e_id = NOID;
153 
154 	/* dn + attributes */
155 	atail = &ahead;
156 	ahead.a_next = NULL;
157 	ad = NULL;
158 	ad_prev = NULL;
159 	attr_cnt = 0;
160 	next = s;
161 
162 	lines = ldif_countlines( s );
163 	type = ch_calloc( 1, (lines+1)*3*sizeof(struct berval)+lines );
164 	vals = type+lines+1;
165 	nvals = vals+lines+1;
166 	freeval = (char *)(nvals+lines+1);
167 	i = -1;
168 
169 	/* parse into individual values, record DN */
170 	while ( (s = ldif_getline( &next )) != NULL ) {
171 		int freev;
172 		if ( *s == '\n' || *s == '\0' ) {
173 			break;
174 		}
175 		i++;
176 		if (i >= lines) {
177 			Debug( LDAP_DEBUG_TRACE,
178 				"<= str2entry ran past end of entry\n", 0, 0, 0 );
179 			goto fail;
180 		}
181 
182 		rc = ldif_parse_line2( s, type+i, vals+i, &freev );
183 		freeval[i] = freev;
184 		if ( rc ) {
185 			Debug( LDAP_DEBUG_TRACE,
186 				"<= str2entry NULL (parse_line)\n", 0, 0, 0 );
187 			continue;
188 		}
189 
190 		if ( bvcasematch( &type[i], &dn_bv ) ) {
191 			if ( e->e_dn != NULL ) {
192 				Debug( LDAP_DEBUG_ANY, "str2entry: "
193 					"entry %ld has multiple DNs \"%s\" and \"%s\"\n",
194 					(long) e->e_id, e->e_dn, vals[i].bv_val );
195 				goto fail;
196 			}
197 
198 			rc = dnPrettyNormal( NULL, &vals[i], &e->e_name, &e->e_nname, NULL );
199 			if( rc != LDAP_SUCCESS ) {
200 				Debug( LDAP_DEBUG_ANY, "str2entry: "
201 					"entry %ld has invalid DN \"%s\"\n",
202 					(long) e->e_id, vals[i].bv_val, 0 );
203 				goto fail;
204 			}
205 			if ( freeval[i] ) free( vals[i].bv_val );
206 			vals[i].bv_val = NULL;
207 			i--;
208 			continue;
209 		}
210 	}
211 	lines = i+1;
212 
213 	/* check to make sure there was a dn: line */
214 	if ( BER_BVISNULL( &e->e_name )) {
215 		Debug( LDAP_DEBUG_ANY, "str2entry: entry %ld has no dn\n",
216 			(long) e->e_id, 0, 0 );
217 		goto fail;
218 	}
219 
220 	/* Make sure all attributes with multiple values are contiguous */
221 	if ( checkvals ) {
222 		int j, k;
223 		struct berval bv;
224 		int fv;
225 
226 		for (i=0; i<lines; i++) {
227 			for ( j=i+1; j<lines; j++ ) {
228 				if ( bvcasematch( type+i, type+j )) {
229 					/* out of order, move intervening attributes down */
230 					if ( j != i+1 ) {
231 						bv = vals[j];
232 						fv = freeval[j];
233 						for ( k=j; k>i; k-- ) {
234 							type[k] = type[k-1];
235 							vals[k] = vals[k-1];
236 							freeval[k] = freeval[k-1];
237 						}
238 						k++;
239 						type[k] = type[i];
240 						vals[k] = bv;
241 						freeval[k] = fv;
242 					}
243 					i++;
244 				}
245 			}
246 		}
247 	}
248 
249 	if ( lines > 0 ) {
250 		for ( i=0; i<=lines; i++ ) {
251 			ad_prev = ad;
252 			if ( !ad || ( i<lines && !bvcasematch( type+i, &ad->ad_cname ))) {
253 				ad = NULL;
254 				rc = slap_bv2ad( type+i, &ad, &text );
255 
256 				if( rc != LDAP_SUCCESS ) {
257 					int wtool = ( slapMode & (SLAP_TOOL_MODE|SLAP_TOOL_READONLY) ) == SLAP_TOOL_MODE;
258 					Debug( wtool ? LDAP_DEBUG_ANY : LDAP_DEBUG_TRACE,
259 						"<= str2entry: str2ad(%s): %s\n", type[i].bv_val, text, 0 );
260 					if( wtool ) {
261 						goto fail;
262 					}
263 
264 					rc = slap_bv2undef_ad( type+i, &ad, &text, 0 );
265 					if( rc != LDAP_SUCCESS ) {
266 						Debug( LDAP_DEBUG_ANY,
267 							"<= str2entry: slap_str2undef_ad(%s): %s\n",
268 								type[i].bv_val, text, 0 );
269 						goto fail;
270 					}
271 				}
272 
273 				/* require ';binary' when appropriate (ITS#5071) */
274 				if ( slap_syntax_is_binary( ad->ad_type->sat_syntax ) && !slap_ad_is_binary( ad ) ) {
275 					Debug( LDAP_DEBUG_ANY,
276 						"str2entry: attributeType %s #%d: "
277 						"needs ';binary' transfer as per syntax %s\n",
278 						ad->ad_cname.bv_val, 0,
279 						ad->ad_type->sat_syntax->ssyn_oid );
280 					goto fail;
281 				}
282 			}
283 
284 			if (( ad_prev && ad != ad_prev ) || ( i == lines )) {
285 				int j, k;
286 				atail->a_next = attr_alloc( NULL );
287 				atail = atail->a_next;
288 				atail->a_flags = 0;
289 				atail->a_numvals = attr_cnt;
290 				atail->a_desc = ad_prev;
291 				atail->a_vals = ch_malloc( (attr_cnt + 1) * sizeof(struct berval));
292 				if( ad_prev->ad_type->sat_equality &&
293 					ad_prev->ad_type->sat_equality->smr_normalize )
294 					atail->a_nvals = ch_malloc( (attr_cnt + 1) * sizeof(struct berval));
295 				else
296 					atail->a_nvals = NULL;
297 				k = i - attr_cnt;
298 				for ( j=0; j<attr_cnt; j++ ) {
299 					if ( freeval[k] )
300 						atail->a_vals[j] = vals[k];
301 					else
302 						ber_dupbv( atail->a_vals+j, &vals[k] );
303 					vals[k].bv_val = NULL;
304 					if ( atail->a_nvals ) {
305 						atail->a_nvals[j] = nvals[k];
306 						nvals[k].bv_val = NULL;
307 					}
308 					k++;
309 				}
310 				BER_BVZERO( &atail->a_vals[j] );
311 				if ( atail->a_nvals ) {
312 					BER_BVZERO( &atail->a_nvals[j] );
313 				} else {
314 					atail->a_nvals = atail->a_vals;
315 				}
316 				attr_cnt = 0;
317 				/* FIXME: we only need this when migrating from an unsorted DB */
318 				if ( atail->a_desc->ad_type->sat_flags & SLAP_AT_SORTED_VAL ) {
319 					rc = slap_sort_vals( (Modifications *)atail, &text, &j, NULL );
320 					if ( rc == LDAP_SUCCESS ) {
321 						atail->a_flags |= SLAP_ATTR_SORTED_VALS;
322 					} else if ( rc == LDAP_TYPE_OR_VALUE_EXISTS ) {
323 						Debug( LDAP_DEBUG_ANY,
324 							"str2entry: attributeType %s value #%d provided more than once\n",
325 							atail->a_desc->ad_cname.bv_val, j, 0 );
326 						goto fail;
327 					}
328 				}
329 				if ( i == lines ) break;
330 			}
331 
332 			if ( BER_BVISNULL( &vals[i] ) ) {
333 				Debug( LDAP_DEBUG_ANY,
334 					"str2entry: attributeType %s #%d: "
335 					"no value\n",
336 					ad->ad_cname.bv_val, attr_cnt, 0 );
337 				goto fail;
338 			}
339 
340 			if ( ad->ad_type->sat_equality &&
341 				ad->ad_type->sat_equality->smr_normalize )
342 			{
343 				rc = ordered_value_normalize(
344 					SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX,
345 					ad,
346 					ad->ad_type->sat_equality,
347 					&vals[i], &nvals[i], NULL );
348 
349 				if ( rc ) {
350 					Debug( LDAP_DEBUG_ANY,
351 				   		"<= str2entry NULL (smr_normalize %s %d)\n", ad->ad_cname.bv_val, rc, 0 );
352 					goto fail;
353 				}
354 			}
355 
356 			attr_cnt++;
357 		}
358 	}
359 
360 	free( type );
361 	atail->a_next = NULL;
362 	e->e_attrs = ahead.a_next;
363 
364 	Debug(LDAP_DEBUG_TRACE, "<= str2entry(%s) -> 0x%lx\n",
365 		e->e_dn, (unsigned long) e, 0 );
366 	return( e );
367 
368 fail:
369 	for ( i=0; i<lines; i++ ) {
370 		if ( freeval[i] ) free( vals[i].bv_val );
371 		free( nvals[i].bv_val );
372 	}
373 	free( type );
374 	entry_free( e );
375 	return NULL;
376 }
377 
378 
379 #define GRABSIZE	BUFSIZ
380 
381 #define MAKE_SPACE( n )	{ \
382 		while ( ecur + (n) > ebuf + emaxsize ) { \
383 			ptrdiff_t	offset; \
384 			offset = (int) (ecur - ebuf); \
385 			ebuf = ch_realloc( ebuf, \
386 				emaxsize + GRABSIZE ); \
387 			emaxsize += GRABSIZE; \
388 			ecur = ebuf + offset; \
389 		} \
390 	}
391 
392 /* NOTE: only preserved for binary compatibility */
393 char *
394 entry2str(
395 	Entry	*e,
396 	int		*len )
397 {
398 	return entry2str_wrap( e, len, LDIF_LINE_WIDTH );
399 }
400 
401 char *
402 entry2str_wrap(
403 	Entry		*e,
404 	int			*len,
405 	ber_len_t	wrap )
406 {
407 	Attribute	*a;
408 	struct berval	*bv;
409 	int		i;
410 	ber_len_t tmplen;
411 
412 	assert( e != NULL );
413 
414 	/*
415 	 * In string format, an entry looks like this:
416 	 *	dn: <dn>\n
417 	 *	[<attr>: <value>\n]*
418 	 */
419 
420 	ecur = ebuf;
421 
422 	/* put the dn */
423 	if ( e->e_dn != NULL ) {
424 		/* put "dn: <dn>" */
425 		tmplen = e->e_name.bv_len;
426 		MAKE_SPACE( LDIF_SIZE_NEEDED( 2, tmplen ));
427 		ldif_sput_wrap( &ecur, LDIF_PUT_VALUE, "dn", e->e_dn, tmplen, wrap );
428 	}
429 
430 	/* put the attributes */
431 	for ( a = e->e_attrs; a != NULL; a = a->a_next ) {
432 		/* put "<type>:[:] <value>" line for each value */
433 		for ( i = 0; a->a_vals[i].bv_val != NULL; i++ ) {
434 			bv = &a->a_vals[i];
435 			tmplen = a->a_desc->ad_cname.bv_len;
436 			MAKE_SPACE( LDIF_SIZE_NEEDED( tmplen, bv->bv_len ));
437 			ldif_sput_wrap( &ecur, LDIF_PUT_VALUE,
438 				a->a_desc->ad_cname.bv_val,
439 				bv->bv_val, bv->bv_len, wrap );
440 		}
441 	}
442 	MAKE_SPACE( 1 );
443 	*ecur = '\0';
444 	*len = ecur - ebuf;
445 
446 	return( ebuf );
447 }
448 
449 void
450 entry_clean( Entry *e )
451 {
452 	/* free an entry structure */
453 	assert( e != NULL );
454 
455 	/* e_private must be freed by the caller */
456 	assert( e->e_private == NULL );
457 
458 	e->e_id = 0;
459 
460 	/* free DNs */
461 	if ( !BER_BVISNULL( &e->e_name ) ) {
462 		free( e->e_name.bv_val );
463 		BER_BVZERO( &e->e_name );
464 	}
465 	if ( !BER_BVISNULL( &e->e_nname ) ) {
466 		free( e->e_nname.bv_val );
467 		BER_BVZERO( &e->e_nname );
468 	}
469 
470 	if ( !BER_BVISNULL( &e->e_bv ) ) {
471 		free( e->e_bv.bv_val );
472 		BER_BVZERO( &e->e_bv );
473 	}
474 
475 	/* free attributes */
476 	if ( e->e_attrs ) {
477 		attrs_free( e->e_attrs );
478 		e->e_attrs = NULL;
479 	}
480 
481 	e->e_ocflags = 0;
482 }
483 
484 void
485 entry_free( Entry *e )
486 {
487 	entry_clean( e );
488 
489 	ldap_pvt_thread_mutex_lock( &entry_mutex );
490 	e->e_private = entry_list;
491 	entry_list = e;
492 	ldap_pvt_thread_mutex_unlock( &entry_mutex );
493 }
494 
495 /* These parameters work well on AMD64 */
496 #if 0
497 #define	STRIDE 8
498 #define	STRIPE 5
499 #else
500 #define	STRIDE 1
501 #define	STRIPE 1
502 #endif
503 #define	STRIDE_FACTOR (STRIDE*STRIPE)
504 
505 int
506 entry_prealloc( int num )
507 {
508 	Entry *e, **prev, *tmp;
509 	slap_list *s;
510 	int i, j;
511 
512 	if (!num) return 0;
513 
514 #if STRIDE_FACTOR > 1
515 	/* Round up to our stride factor */
516 	num += STRIDE_FACTOR-1;
517 	num /= STRIDE_FACTOR;
518 	num *= STRIDE_FACTOR;
519 #endif
520 
521 	s = ch_calloc( 1, sizeof(slap_list) + num * sizeof(Entry));
522 	s->next = entry_chunks;
523 	entry_chunks = s;
524 
525 	prev = &tmp;
526 	for (i=0; i<STRIPE; i++) {
527 		e = (Entry *)(s+1);
528 		e += i;
529 		for (j=i; j<num; j+= STRIDE) {
530 			*prev = e;
531 			prev = (Entry **)&e->e_private;
532 			e += STRIDE;
533 		}
534 	}
535 	*prev = entry_list;
536 	entry_list = (Entry *)(s+1);
537 
538 	return 0;
539 }
540 
541 Entry *
542 entry_alloc( void )
543 {
544 	Entry *e;
545 
546 	ldap_pvt_thread_mutex_lock( &entry_mutex );
547 	if ( !entry_list )
548 		entry_prealloc( CHUNK_SIZE );
549 	e = entry_list;
550 	entry_list = e->e_private;
551 	e->e_private = NULL;
552 	ldap_pvt_thread_mutex_unlock( &entry_mutex );
553 
554 	return e;
555 }
556 
557 
558 /*
559  * These routines are used only by Backend.
560  *
561  * the Entry has three entry points (ways to find things):
562  *
563  *	by entry	e.g., if you already have an entry from the cache
564  *			and want to delete it. (really by entry ptr)
565  *	by dn		e.g., when looking for the base object of a search
566  *	by id		e.g., for search candidates
567  *
568  * these correspond to three different avl trees that are maintained.
569  */
570 
571 int
572 entry_cmp( Entry *e1, Entry *e2 )
573 {
574 	return SLAP_PTRCMP( e1, e2 );
575 }
576 
577 int
578 entry_dn_cmp( const void *v_e1, const void *v_e2 )
579 {
580 	/* compare their normalized UPPERCASED dn's */
581 	const Entry *e1 = v_e1, *e2 = v_e2;
582 
583 	return ber_bvcmp( &e1->e_nname, &e2->e_nname );
584 }
585 
586 int
587 entry_id_cmp( const void *v_e1, const void *v_e2 )
588 {
589 	const Entry *e1 = v_e1, *e2 = v_e2;
590 	return( e1->e_id < e2->e_id ? -1 : (e1->e_id > e2->e_id ? 1 : 0) );
591 }
592 
593 /* This is like a ber_len */
594 #define entry_lenlen(l)	(((l) < 0x80) ? 1 : ((l) < 0x100) ? 2 : \
595 	((l) < 0x10000) ? 3 : ((l) < 0x1000000) ? 4 : 5)
596 
597 static void
598 entry_putlen(unsigned char **buf, ber_len_t len)
599 {
600 	ber_len_t lenlen = entry_lenlen(len);
601 
602 	if (lenlen == 1) {
603 		**buf = (unsigned char) len;
604 	} else {
605 		int i;
606 		**buf = 0x80 | ((unsigned char) lenlen - 1);
607 		for (i=lenlen-1; i>0; i--) {
608 			(*buf)[i] = (unsigned char) len;
609 			len >>= 8;
610 		}
611 	}
612 	*buf += lenlen;
613 }
614 
615 static ber_len_t
616 entry_getlen(unsigned char **buf)
617 {
618 	ber_len_t len;
619 	int i;
620 
621 	len = *(*buf)++;
622 	if (len <= 0x7f)
623 		return len;
624 	i = len & 0x7f;
625 	len = 0;
626 	for (;i > 0; i--) {
627 		len <<= 8;
628 		len |= *(*buf)++;
629 	}
630 	return len;
631 }
632 
633 /* Count up the sizes of the components of an entry */
634 void entry_partsize(Entry *e, ber_len_t *plen,
635 	int *pnattrs, int *pnvals, int norm)
636 {
637 	ber_len_t len, dnlen, ndnlen;
638 	int i, nat = 0, nval = 0;
639 	Attribute *a;
640 
641 	dnlen = e->e_name.bv_len;
642 	len = dnlen + 1;	/* trailing NUL byte */
643 	len += entry_lenlen(dnlen);
644 	if (norm) {
645 		ndnlen = e->e_nname.bv_len;
646 		len += ndnlen + 1;
647 		len += entry_lenlen(ndnlen);
648 	}
649 	for (a=e->e_attrs; a; a=a->a_next) {
650 		/* For AttributeDesc, we only store the attr name */
651 		nat++;
652 		len += a->a_desc->ad_cname.bv_len+1;
653 		len += entry_lenlen(a->a_desc->ad_cname.bv_len);
654 		for (i=0; a->a_vals[i].bv_val; i++) {
655 			nval++;
656 			len += a->a_vals[i].bv_len + 1;
657 			len += entry_lenlen(a->a_vals[i].bv_len);
658 		}
659 		len += entry_lenlen(i);
660 		nval++;	/* empty berval at end */
661 		if (norm && a->a_nvals != a->a_vals) {
662 			for (i=0; a->a_nvals[i].bv_val; i++) {
663 				nval++;
664 				len += a->a_nvals[i].bv_len + 1;
665 				len += entry_lenlen(a->a_nvals[i].bv_len);
666 			}
667 			len += entry_lenlen(i);	/* i nvals */
668 			nval++;
669 		} else {
670 			len += entry_lenlen(0);	/* 0 nvals */
671 		}
672 	}
673 	len += entry_lenlen(nat);
674 	len += entry_lenlen(nval);
675 	*plen = len;
676 	*pnattrs = nat;
677 	*pnvals = nval;
678 }
679 
680 /* Add up the size of the entry for a flattened buffer */
681 ber_len_t entry_flatsize(Entry *e, int norm)
682 {
683 	ber_len_t len;
684 	int nattrs, nvals;
685 
686 	entry_partsize(e, &len, &nattrs, &nvals, norm);
687 	len += sizeof(Entry) + (nattrs * sizeof(Attribute)) +
688 		(nvals * sizeof(struct berval));
689 	return len;
690 }
691 
692 /* Flatten an Entry into a buffer. The buffer is filled with just the
693  * strings/bervals of all the entry components. Each field is preceded
694  * by its length, encoded the way ber_put_len works. Every field is NUL
695  * terminated.  The entire buffer size is precomputed so that a single
696  * malloc can be performed. The entry size is also recorded,
697  * to aid in entry_decode.
698  */
699 int entry_encode(Entry *e, struct berval *bv)
700 {
701 	ber_len_t len, dnlen, ndnlen, i;
702 	int nattrs, nvals;
703 	Attribute *a;
704 	unsigned char *ptr;
705 
706 	Debug( LDAP_DEBUG_TRACE, "=> entry_encode(0x%08lx): %s\n",
707 		(long) e->e_id, e->e_dn, 0 );
708 
709 	dnlen = e->e_name.bv_len;
710 	ndnlen = e->e_nname.bv_len;
711 
712 	entry_partsize( e, &len, &nattrs, &nvals, 1 );
713 
714 	bv->bv_len = len;
715 	bv->bv_val = ch_malloc(len);
716 	ptr = (unsigned char *)bv->bv_val;
717 	entry_putlen(&ptr, nattrs);
718 	entry_putlen(&ptr, nvals);
719 	entry_putlen(&ptr, dnlen);
720 	AC_MEMCPY(ptr, e->e_dn, dnlen);
721 	ptr += dnlen;
722 	*ptr++ = '\0';
723 	entry_putlen(&ptr, ndnlen);
724 	AC_MEMCPY(ptr, e->e_ndn, ndnlen);
725 	ptr += ndnlen;
726 	*ptr++ = '\0';
727 
728 	for (a=e->e_attrs; a; a=a->a_next) {
729 		entry_putlen(&ptr, a->a_desc->ad_cname.bv_len);
730 		AC_MEMCPY(ptr, a->a_desc->ad_cname.bv_val,
731 			a->a_desc->ad_cname.bv_len);
732 		ptr += a->a_desc->ad_cname.bv_len;
733 		*ptr++ = '\0';
734 		if (a->a_vals) {
735 			for (i=0; a->a_vals[i].bv_val; i++);
736 			assert( i == a->a_numvals );
737 			entry_putlen(&ptr, i);
738 			for (i=0; a->a_vals[i].bv_val; i++) {
739 				entry_putlen(&ptr, a->a_vals[i].bv_len);
740 				AC_MEMCPY(ptr, a->a_vals[i].bv_val,
741 					a->a_vals[i].bv_len);
742 				ptr += a->a_vals[i].bv_len;
743 				*ptr++ = '\0';
744 			}
745 			if (a->a_nvals != a->a_vals) {
746 				entry_putlen(&ptr, i);
747 				for (i=0; a->a_nvals[i].bv_val; i++) {
748 					entry_putlen(&ptr, a->a_nvals[i].bv_len);
749 					AC_MEMCPY(ptr, a->a_nvals[i].bv_val,
750 					a->a_nvals[i].bv_len);
751 					ptr += a->a_nvals[i].bv_len;
752 					*ptr++ = '\0';
753 				}
754 			} else {
755 				entry_putlen(&ptr, 0);
756 			}
757 		}
758 	}
759 
760 	Debug( LDAP_DEBUG_TRACE, "<= entry_encode(0x%08lx): %s\n",
761 		(long) e->e_id, e->e_dn, 0 );
762 
763 	return 0;
764 }
765 
766 /* Retrieve an Entry that was stored using entry_encode above.
767  * First entry_header must be called to decode the size of the entry.
768  * Then a single block of memory must be malloc'd to accomodate the
769  * bervals and the bulk data. Next the bulk data is retrieved from
770  * the DB and parsed by entry_decode.
771  *
772  * Note: everything is stored in a single contiguous block, so
773  * you can not free individual attributes or names from this
774  * structure. Attempting to do so will likely corrupt memory.
775  */
776 int entry_header(EntryHeader *eh)
777 {
778 	unsigned char *ptr = (unsigned char *)eh->bv.bv_val;
779 
780 	/* Some overlays can create empty entries
781 	 * so don't check for zeros here.
782 	 */
783 	eh->nattrs = entry_getlen(&ptr);
784 	eh->nvals = entry_getlen(&ptr);
785 	eh->data = (char *)ptr;
786 	return LDAP_SUCCESS;
787 }
788 
789 int
790 entry_decode_dn( EntryHeader *eh, struct berval *dn, struct berval *ndn )
791 {
792 	int i;
793 	unsigned char *ptr = (unsigned char *)eh->bv.bv_val;
794 
795 	assert( dn != NULL || ndn != NULL );
796 
797 	ptr = (unsigned char *)eh->data;
798 	i = entry_getlen(&ptr);
799 	if ( dn != NULL ) {
800 		dn->bv_val = (char *) ptr;
801 		dn->bv_len = i;
802 	}
803 
804 	if ( ndn != NULL ) {
805 		ptr += i + 1;
806 		i = entry_getlen(&ptr);
807 		ndn->bv_val = (char *) ptr;
808 		ndn->bv_len = i;
809 	}
810 
811 	Debug( LDAP_DEBUG_TRACE,
812 		"entry_decode_dn: \"%s\"\n",
813 		dn ? dn->bv_val : ndn->bv_val, 0, 0 );
814 
815 	return 0;
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 *
935 entry_dup2( Entry *dest, Entry *source )
936 {
937 	assert( dest != NULL );
938 	assert( source != NULL );
939 
940 	assert( dest->e_private == NULL );
941 
942 	dest->e_id = source->e_id;
943 	ber_dupbv( &dest->e_name, &source->e_name );
944 	ber_dupbv( &dest->e_nname, &source->e_nname );
945 	dest->e_attrs = attrs_dup( source->e_attrs );
946 	dest->e_ocflags = source->e_ocflags;
947 
948 	return dest;
949 }
950 
951 Entry *
952 entry_dup( Entry *e )
953 {
954 	return entry_dup2( entry_alloc(), e );
955 }
956 
957 #if 1
958 /* Duplicates an entry using a single malloc. Saves CPU time, increases
959  * heap usage because a single large malloc is harder to satisfy than
960  * lots of small ones, and the freed space isn't as easily reusable.
961  *
962  * Probably not worth using this function.
963  */
964 Entry *entry_dup_bv( Entry *e )
965 {
966 	ber_len_t len;
967 	int nattrs, nvals;
968 	Entry *ret;
969 	struct berval *bvl;
970 	char *ptr;
971 	Attribute *src, *dst;
972 
973 	ret = entry_alloc();
974 
975 	entry_partsize(e, &len, &nattrs, &nvals, 1);
976 	ret->e_id = e->e_id;
977 	ret->e_attrs = attrs_alloc( nattrs );
978 	ret->e_ocflags = e->e_ocflags;
979 	ret->e_bv.bv_len = len + nvals * sizeof(struct berval);
980 	ret->e_bv.bv_val = ch_malloc( ret->e_bv.bv_len );
981 
982 	bvl = (struct berval *)ret->e_bv.bv_val;
983 	ptr = (char *)(bvl + nvals);
984 
985 	ret->e_name.bv_len = e->e_name.bv_len;
986 	ret->e_name.bv_val = ptr;
987 	AC_MEMCPY( ptr, e->e_name.bv_val, e->e_name.bv_len );
988 	ptr += e->e_name.bv_len;
989 	*ptr++ = '\0';
990 
991 	ret->e_nname.bv_len = e->e_nname.bv_len;
992 	ret->e_nname.bv_val = ptr;
993 	AC_MEMCPY( ptr, e->e_nname.bv_val, e->e_nname.bv_len );
994 	ptr += e->e_name.bv_len;
995 	*ptr++ = '\0';
996 
997 	dst = ret->e_attrs;
998 	for (src = e->e_attrs; src; src=src->a_next,dst=dst->a_next ) {
999 		int i;
1000 		dst->a_desc = src->a_desc;
1001 		dst->a_flags = SLAP_ATTR_DONT_FREE_DATA | SLAP_ATTR_DONT_FREE_VALS;
1002 		dst->a_vals = bvl;
1003 		dst->a_numvals = src->a_numvals;
1004 		for ( i=0; src->a_vals[i].bv_val; i++ ) {
1005 			bvl->bv_len = src->a_vals[i].bv_len;
1006 			bvl->bv_val = ptr;
1007 			AC_MEMCPY( ptr, src->a_vals[i].bv_val, bvl->bv_len );
1008 			ptr += bvl->bv_len;
1009 			*ptr++ = '\0';
1010 			bvl++;
1011 		}
1012 		BER_BVZERO(bvl);
1013 		bvl++;
1014 		if ( src->a_vals != src->a_nvals ) {
1015 			dst->a_nvals = bvl;
1016 			for ( i=0; src->a_nvals[i].bv_val; i++ ) {
1017 				bvl->bv_len = src->a_nvals[i].bv_len;
1018 				bvl->bv_val = ptr;
1019 				AC_MEMCPY( ptr, src->a_nvals[i].bv_val, bvl->bv_len );
1020 				ptr += bvl->bv_len;
1021 				*ptr++ = '\0';
1022 				bvl++;
1023 			}
1024 			BER_BVZERO(bvl);
1025 			bvl++;
1026 		}
1027 	}
1028 	return ret;
1029 }
1030 #endif
1031