1 /* attr.c - routines for dealing with attributes */
2 /* $OpenLDAP: pkg/ldap/servers/slapd/attr.c,v 1.112.2.8 2008/07/10 00:17:13 quanah Exp $ */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5 * Copyright 1998-2008 The OpenLDAP Foundation.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted only as authorized by the OpenLDAP
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>.
16 /* Portions Copyright (c) 1995 Regents of the University of Michigan.
17 * All rights reserved.
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.
37 #include <ac/socket.h>
38 #include <ac/string.h>
44 * Allocate in chunks, minimum of 1000 at a time.
46 #define CHUNK_SIZE 1000
47 typedef struct slap_list
{
48 struct slap_list
*next
;
50 static slap_list
*attr_chunks
;
51 static Attribute
*attr_list
;
52 static ldap_pvt_thread_mutex_t attr_mutex
;
55 attr_prealloc( int num
)
62 s
= ch_calloc( 1, sizeof(slap_list
) + num
* sizeof(Attribute
));
63 s
->next
= attr_chunks
;
66 a
= (Attribute
*)(s
+1);
67 for ( ;num
>1; num
--) {
71 a
->a_next
= attr_list
;
72 attr_list
= (Attribute
*)(s
+1);
78 attr_alloc( AttributeDescription
*ad
)
82 ldap_pvt_thread_mutex_lock( &attr_mutex
);
84 attr_prealloc( CHUNK_SIZE
);
86 attr_list
= a
->a_next
;
88 ldap_pvt_thread_mutex_unlock( &attr_mutex
);
95 /* Return a list of num attrs */
97 attrs_alloc( int num
)
99 Attribute
*head
= NULL
;
102 ldap_pvt_thread_mutex_lock( &attr_mutex
);
103 for ( a
= &attr_list
; *a
&& num
> 0; a
= &(*a
)->a_next
) {
110 attr_prealloc( num
> CHUNK_SIZE
? num
: CHUNK_SIZE
);
112 for ( ; *a
&& num
> 0; a
= &(*a
)->a_next
) {
120 ldap_pvt_thread_mutex_unlock( &attr_mutex
);
127 attr_clean( Attribute
*a
)
129 if ( a
->a_nvals
&& a
->a_nvals
!= a
->a_vals
&&
130 !( a
->a_flags
& SLAP_ATTR_DONT_FREE_VALS
)) {
131 if ( a
->a_flags
& SLAP_ATTR_DONT_FREE_DATA
) {
134 ber_bvarray_free( a
->a_nvals
);
137 /* a_vals may be equal to slap_dummy_bv, a static empty berval;
138 * this is used as a placeholder for attributes that do not carry
139 * values, e.g. when proxying search entries with the "attrsonly"
141 if ( a
->a_vals
!= &slap_dummy_bv
&&
142 !( a
->a_flags
& SLAP_ATTR_DONT_FREE_VALS
)) {
143 if ( a
->a_flags
& SLAP_ATTR_DONT_FREE_DATA
) {
146 ber_bvarray_free( a
->a_vals
);
152 #ifdef LDAP_COMP_MATCH
153 a
->a_comp_data
= NULL
;
160 attr_free( Attribute
*a
)
163 ldap_pvt_thread_mutex_lock( &attr_mutex
);
164 a
->a_next
= attr_list
;
166 ldap_pvt_thread_mutex_unlock( &attr_mutex
);
169 #ifdef LDAP_COMP_MATCH
171 comp_tree_free( Attribute
*a
)
175 for( ; a
!= NULL
; a
= next
) {
177 if ( component_destructor
&& a
->a_comp_data
) {
178 if ( a
->a_comp_data
->cd_mem_op
)
179 component_destructor( a
->a_comp_data
->cd_mem_op
);
180 free ( a
->a_comp_data
);
187 attrs_free( Attribute
*a
)
190 Attribute
*b
= (Attribute
*)0xBAD, *tail
, *next
;
202 ldap_pvt_thread_mutex_lock( &attr_mutex
);
203 /* replace NULL with current attr list and let attr list
204 * start from last attribute returned to list */
205 tail
->a_next
= attr_list
;
207 ldap_pvt_thread_mutex_unlock( &attr_mutex
);
212 attr_dup2( Attribute
*tmp
, Attribute
*a
)
214 tmp
->a_flags
= a
->a_flags
& SLAP_ATTR_PERSISTENT_FLAGS
;
215 if ( a
->a_vals
!= NULL
) {
218 tmp
->a_numvals
= a
->a_numvals
;
219 tmp
->a_vals
= ch_malloc( (tmp
->a_numvals
+ 1) * sizeof(struct berval
) );
220 for ( i
= 0; i
< tmp
->a_numvals
; i
++ ) {
221 ber_dupbv( &tmp
->a_vals
[i
], &a
->a_vals
[i
] );
222 if ( BER_BVISNULL( &tmp
->a_vals
[i
] ) ) break;
225 BER_BVZERO( &tmp
->a_vals
[i
] );
227 /* a_nvals must be non null; it may be equal to a_vals */
228 assert( a
->a_nvals
!= NULL
);
230 if ( a
->a_nvals
!= a
->a_vals
) {
233 tmp
->a_nvals
= ch_malloc( (tmp
->a_numvals
+ 1) * sizeof(struct berval
) );
234 for ( j
= 0; !BER_BVISNULL( &a
->a_nvals
[j
] ); j
++ ) {
236 ber_dupbv( &tmp
->a_nvals
[j
], &a
->a_nvals
[j
] );
237 if ( BER_BVISNULL( &tmp
->a_nvals
[j
] ) ) break;
241 BER_BVZERO( &tmp
->a_nvals
[j
] );
244 tmp
->a_nvals
= tmp
->a_vals
;
250 attr_dup( Attribute
*a
)
254 if ( a
== NULL
) return NULL
;
256 tmp
= attr_alloc( a
->a_desc
);
262 attrs_dup( Attribute
*a
)
265 Attribute
*tmp
, *anew
;
267 if( a
== NULL
) return NULL
;
270 for( tmp
=a
,i
=0; tmp
; tmp
=tmp
->a_next
) {
274 anew
= attrs_alloc( i
);
276 for( tmp
=anew
; a
; a
=a
->a_next
) {
277 tmp
->a_desc
= a
->a_desc
;
293 struct berval nval
= BER_BVNULL
, *cval
;
299 if ( flags
& SLAP_MR_ORDERING
)
300 mr
= a
->a_desc
->ad_type
->sat_ordering
;
302 mr
= a
->a_desc
->ad_type
->sat_equality
;
304 if( !SLAP_IS_MR_ASSERTED_VALUE_NORMALIZED_MATCH( flags
) &&
307 rc
= (mr
->smr_normalize
)(
308 flags
& (SLAP_MR_TYPE_MASK
|SLAP_MR_SUBTYPE_MASK
|SLAP_MR_VALUE_OF_SYNTAX
),
309 a
->a_desc
->ad_type
->sat_syntax
,
310 mr
, val
, &nval
, ctx
);
312 if( rc
!= LDAP_SUCCESS
) {
313 return LDAP_INVALID_SYNTAX
;
320 if ( a
->a_flags
& SLAP_ATTR_SORTED_VALS
) {
322 unsigned base
= 0, n
= a
->a_numvals
;
325 unsigned pivot
= n
>> 1;
327 rc
= value_match( &match
, a
->a_desc
, mr
, flags
,
328 &a
->a_nvals
[i
], cval
, &text
);
329 if ( rc
== LDAP_SUCCESS
&& match
== 0 )
342 for ( i
= 0; i
< a
->a_numvals
; i
++ ) {
345 rc
= ordered_value_match( &match
, a
->a_desc
, mr
, flags
,
346 &a
->a_nvals
[i
], cval
, &text
);
347 if ( rc
== LDAP_SUCCESS
&& match
== 0 )
354 rc
= LDAP_NO_SUCH_ATTRIBUTE
;
356 slap_sl_free( nval
.bv_val
, ctx
);
371 v2
= (BerVarray
) SLAP_REALLOC( (char *) a
->a_vals
,
372 (a
->a_numvals
+ nn
+ 1) * sizeof(struct berval
) );
374 Debug(LDAP_DEBUG_TRACE
,
375 "attr_valadd: SLAP_REALLOC failed.\n", 0, 0, 0 );
376 return LBER_ERROR_MEMORY
;
380 v2
= (BerVarray
) SLAP_REALLOC( (char *) a
->a_nvals
,
381 (a
->a_numvals
+ nn
+ 1) * sizeof(struct berval
) );
383 Debug(LDAP_DEBUG_TRACE
,
384 "attr_valadd: SLAP_REALLOC failed.\n", 0, 0, 0 );
385 return LBER_ERROR_MEMORY
;
389 a
->a_nvals
= a
->a_vals
;
392 /* If sorted and old vals exist, must insert */
393 if (( a
->a_flags
& SLAP_ATTR_SORTED_VALS
) && a
->a_numvals
) {
396 v2
= nvals
? nvals
: vals
;
397 for ( i
= 0; i
< nn
; i
++ ) {
398 rc
= attr_valfind( a
, SLAP_MR_EQUALITY
| SLAP_MR_VALUE_OF_ASSERTION_SYNTAX
|
399 SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH
| SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH
,
400 &v2
[i
], &slot
, NULL
);
401 if ( rc
!= LDAP_NO_SUCH_ATTRIBUTE
) {
402 /* should never happen */
403 if ( rc
== LDAP_SUCCESS
)
404 rc
= LDAP_TYPE_OR_VALUE_EXISTS
;
407 for ( j
= a
->a_numvals
; j
>= slot
; j
-- ) {
408 a
->a_vals
[j
+1] = a
->a_vals
[j
];
410 a
->a_nvals
[j
+1] = a
->a_nvals
[j
];
412 ber_dupbv( &a
->a_nvals
[slot
], &v2
[i
] );
414 ber_dupbv( &a
->a_vals
[slot
], &vals
[i
] );
417 BER_BVZERO( &a
->a_vals
[a
->a_numvals
] );
418 if ( a
->a_vals
!= a
->a_nvals
)
419 BER_BVZERO( &a
->a_nvals
[a
->a_numvals
] );
421 v2
= &a
->a_vals
[a
->a_numvals
];
422 for ( i
= 0 ; i
< nn
; i
++ ) {
423 ber_dupbv( &v2
[i
], &vals
[i
] );
424 if ( BER_BVISNULL( &v2
[i
] ) ) break;
426 BER_BVZERO( &v2
[i
] );
429 v2
= &a
->a_nvals
[a
->a_numvals
];
430 for ( i
= 0 ; i
< nn
; i
++ ) {
431 ber_dupbv( &v2
[i
], &nvals
[i
] );
432 if ( BER_BVISNULL( &v2
[i
] ) ) break;
434 BER_BVZERO( &v2
[i
] );
442 * attr_merge - merge the given type and value with the list of
443 * attributes in attrs.
445 * nvals must be NULL if the attribute has no normalizer.
446 * In this case, a->a_nvals will be set equal to a->a_vals.
448 * returns 0 everything went ok
455 AttributeDescription
*desc
,
463 for ( a
= &e
->e_attrs
; *a
!= NULL
; a
= &(*a
)->a_next
) {
464 if ( (*a
)->a_desc
== desc
) {
470 *a
= attr_alloc( desc
);
473 * FIXME: if the attribute already exists, the presence
474 * of nvals and the value of (*a)->a_nvals must be consistent
476 assert( ( nvals
== NULL
&& (*a
)->a_nvals
== (*a
)->a_vals
)
477 || ( nvals
!= NULL
&& (
478 ( (*a
)->a_vals
== NULL
&& (*a
)->a_nvals
== NULL
)
479 || ( (*a
)->a_nvals
!= (*a
)->a_vals
) ) ) );
482 if ( vals
!= NULL
) {
483 for ( ; !BER_BVISNULL( &vals
[i
] ); i
++ ) ;
485 return attr_valadd( *a
, vals
, nvals
, i
);
489 * if a normalization function is defined for the equality matchingRule
490 * of desc, the value is normalized and stored in nval; otherwise nval
495 AttributeDescription
*desc
,
500 int rc
= LDAP_SUCCESS
;
501 BerVarray nvals
= NULL
;
505 if ( desc
->ad_type
->sat_equality
&&
506 desc
->ad_type
->sat_equality
->smr_normalize
)
510 for ( i
= 0; !BER_BVISNULL( &vals
[i
] ); i
++ );
512 nvals
= slap_sl_calloc( sizeof(struct berval
), i
+ 1, memctx
);
513 for ( i
= 0; !BER_BVISNULL( &vals
[i
] ); i
++ ) {
514 rc
= desc
->ad_type
->sat_equality
->smr_normalize(
515 SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX
,
516 desc
->ad_type
->sat_syntax
,
517 desc
->ad_type
->sat_equality
,
518 &vals
[i
], &nvals
[i
], memctx
);
520 if ( rc
!= LDAP_SUCCESS
) {
521 BER_BVZERO( &nvals
[i
+ 1] );
525 BER_BVZERO( &nvals
[i
] );
529 if ( rc
!= LDAP_SUCCESS
&& nvals
!= NULL
) {
530 ber_bvarray_free_x( nvals
, memctx
);
537 attr_merge_normalize(
539 AttributeDescription
*desc
,
543 BerVarray nvals
= NULL
;
546 rc
= attr_normalize( desc
, vals
, &nvals
, memctx
);
547 if ( rc
== LDAP_SUCCESS
) {
548 rc
= attr_merge( e
, desc
, vals
, nvals
);
549 if ( nvals
!= NULL
) {
550 ber_bvarray_free_x( nvals
, memctx
);
560 AttributeDescription
*desc
,
562 struct berval
*nval
)
566 for ( a
= &e
->e_attrs
; *a
!= NULL
; a
= &(*a
)->a_next
) {
567 if ( (*a
)->a_desc
== desc
) {
573 *a
= attr_alloc( desc
);
576 return attr_valadd( *a
, val
, nval
, 1 );
580 * if a normalization function is defined for the equality matchingRule
581 * of desc, the value is normalized and stored in nval; otherwise nval
586 AttributeDescription
*desc
,
591 int rc
= LDAP_SUCCESS
;
595 if ( desc
->ad_type
->sat_equality
&&
596 desc
->ad_type
->sat_equality
->smr_normalize
)
598 rc
= desc
->ad_type
->sat_equality
->smr_normalize(
599 SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX
,
600 desc
->ad_type
->sat_syntax
,
601 desc
->ad_type
->sat_equality
,
604 if ( rc
!= LDAP_SUCCESS
) {
613 attr_merge_normalize_one(
615 AttributeDescription
*desc
,
619 struct berval nval
= BER_BVNULL
;
620 struct berval
*nvalp
= NULL
;
623 rc
= attr_normalize_one( desc
, val
, &nval
, memctx
);
624 if ( rc
== LDAP_SUCCESS
&& !BER_BVISNULL( &nval
) ) {
628 rc
= attr_merge_one( e
, desc
, val
, nvalp
);
629 if ( nvalp
!= NULL
) {
630 slap_sl_free( nval
.bv_val
, memctx
);
636 * attrs_find - find attribute(s) by AttributeDescription
637 * returns next attribute which is subtype of provided description.
643 AttributeDescription
*desc
)
645 for ( ; a
!= NULL
; a
= a
->a_next
) {
646 if ( is_ad_subtype( a
->a_desc
, desc
) ) {
655 * attr_find - find attribute by type
661 AttributeDescription
*desc
)
663 for ( ; a
!= NULL
; a
= a
->a_next
) {
664 if ( a
->a_desc
== desc
) {
673 * attr_delete - delete the attribute type in list pointed to by attrs
674 * return 0 deleted ok
675 * 1 not found in list a
676 * -1 something bad happened
682 AttributeDescription
*desc
)
686 for ( a
= attrs
; *a
!= NULL
; a
= &(*a
)->a_next
) {
687 if ( (*a
)->a_desc
== desc
) {
688 Attribute
*save
= *a
;
696 return LDAP_NO_SUCH_ATTRIBUTE
;
702 ldap_pvt_thread_mutex_init( &attr_mutex
);
711 for ( a
=attr_chunks
; a
; a
=attr_chunks
) {
712 attr_chunks
= a
->next
;
715 ldap_pvt_thread_mutex_destroy( &attr_mutex
);