]> git.sur5r.net Git - openldap/blob - servers/slapd/attr.c
87bfb97a5bb85f12f2b922d702698db1172187df
[openldap] / servers / slapd / attr.c
1 /* attr.c - routines for dealing with attributes */
2 /* $OpenLDAP$ */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
4  *
5  * Copyright 1998-2004 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 #ifdef HAVE_FCNTL_H
32 #include <fcntl.h>
33 #endif
34
35 #include <ac/ctype.h>
36 #include <ac/errno.h>
37 #include <ac/socket.h>
38 #include <ac/string.h>
39 #include <ac/time.h>
40
41 #include "ldap_pvt.h"
42 #include "slap.h"
43
44 void
45 attr_free( Attribute *a )
46 {
47         if ( a->a_nvals && a->a_nvals != a->a_vals )
48                 ber_bvarray_free( a->a_nvals );
49         ber_bvarray_free( a->a_vals );
50         free( a );
51 }
52
53 void
54 attrs_free( Attribute *a )
55 {
56         Attribute *next;
57
58         for( ; a != NULL ; a = next ) {
59                 next = a->a_next;
60                 attr_free( a );
61         }
62 }
63
64 Attribute *
65 attr_dup( Attribute *a )
66 {
67         Attribute *tmp;
68
69         if ( a == NULL) return NULL;
70
71         tmp = ch_malloc( sizeof(Attribute) );
72
73         if ( a->a_vals != NULL ) {
74                 int i;
75
76                 for ( i = 0; !BER_BVISNULL( &a->a_vals[i] ); i++ ) {
77                         /* EMPTY */ ;
78                 }
79
80                 tmp->a_vals = ch_malloc( (i + 1) * sizeof(struct berval) );
81                 for ( i = 0; !BER_BVISNULL( &a->a_vals[i] ); i++ ) {
82                         ber_dupbv( &tmp->a_vals[i], &a->a_vals[i] );
83                         if ( BER_BVISNULL( &tmp->a_vals[i] ) ) break;
84                         /* FIXME: error? */
85                 }
86                 BER_BVZERO( &tmp->a_vals[i] );
87
88                 /* a_nvals must be non null; it may be equal to a_vals */
89                 assert( a->a_nvals );
90
91                 if ( a->a_nvals != a->a_vals ) {
92                         tmp->a_nvals = ch_malloc( (i + 1) * sizeof(struct berval) );
93                         for ( i = 0; !BER_BVISNULL( &a->a_nvals[i] ); i++ ) {
94                                 ber_dupbv( &tmp->a_nvals[i], &a->a_nvals[i] );
95                                 if ( BER_BVISNULL( &tmp->a_nvals[i] ) ) break;
96                                 /* FIXME: error? */
97                         }
98                         BER_BVZERO( &tmp->a_nvals[i] );
99
100                 } else {
101                         tmp->a_nvals = tmp->a_vals;
102                 }
103
104         } else {
105                 tmp->a_vals = NULL;
106                 tmp->a_nvals = NULL;
107         }
108
109         tmp->a_desc = a->a_desc;
110         tmp->a_next = NULL;
111         tmp->a_flags = 0;
112
113         return tmp;
114 }
115
116 Attribute *
117 attrs_dup( Attribute *a )
118 {
119         Attribute *tmp, **next;
120
121         if( a == NULL ) return NULL;
122
123         tmp = NULL;
124         next = &tmp;
125
126         for( ; a != NULL ; a = a->a_next ) {
127                 *next = attr_dup( a );
128                 next = &((*next)->a_next);
129         }
130         *next = NULL;
131
132         return tmp;
133 }
134
135
136
137 /*
138  * attr_merge - merge the given type and value with the list of
139  * attributes in attrs.
140  *
141  * nvals must be NULL if the attribute has no normalizer.
142  * In this case, a->a_nvals will be set equal to a->a_vals.
143  *
144  * returns      0       everything went ok
145  *              -1      trouble
146  */
147
148 int
149 attr_merge(
150         Entry           *e,
151         AttributeDescription *desc,
152         BerVarray       vals,
153         BerVarray       nvals )
154 {
155         int rc;
156
157         Attribute       **a;
158
159         for ( a = &e->e_attrs; *a != NULL; a = &(*a)->a_next ) {
160                 if ( ad_cmp( (*a)->a_desc, desc ) == 0 ) {
161                         break;
162                 }
163         }
164
165         if ( *a == NULL ) {
166                 *a = (Attribute *) ch_malloc( sizeof(Attribute) );
167                 (*a)->a_desc = desc;
168                 (*a)->a_vals = NULL;
169                 (*a)->a_nvals = NULL;
170                 (*a)->a_next = NULL;
171                 (*a)->a_flags = 0;
172         }
173
174         rc = value_add( &(*a)->a_vals, vals );
175
176         if ( rc == LDAP_SUCCESS ) {
177                 if ( nvals ) {
178                         rc = value_add( &(*a)->a_nvals, nvals );
179                         /* FIXME: what if rc != LDAP_SUCCESS ? */
180                 } else {
181                         (*a)->a_nvals = (*a)->a_vals;
182                 }
183         }
184
185         return rc;
186 }
187
188 int
189 attr_merge_normalize(
190         Entry           *e,
191         AttributeDescription *desc,
192         BerVarray       vals,
193         void     *memctx )
194 {
195         BerVarray       nvals = NULL;
196         int             rc;
197
198         if ( desc->ad_type->sat_equality &&
199                 desc->ad_type->sat_equality->smr_normalize )
200         {
201                 int     i;
202                 
203                 for ( i = 0; !BER_BVISNULL( &vals[i] ); i++ );
204
205                 nvals = slap_sl_calloc( sizeof(struct berval), i + 1, memctx );
206                 for ( i = 0; !BER_BVISNULL( &vals[i] ); i++ ) {
207                         rc = (*desc->ad_type->sat_equality->smr_normalize)(
208                                         SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX,
209                                         desc->ad_type->sat_syntax,
210                                         desc->ad_type->sat_equality,
211                                         &vals[i], &nvals[i], memctx );
212
213                         if ( rc != LDAP_SUCCESS ) {
214                                 BER_BVZERO( &nvals[i + 1] );
215                                 goto error_return;
216                         }
217                 }
218                 BER_BVZERO( &nvals[i] );
219         }
220
221         rc = attr_merge( e, desc, vals, nvals );
222
223 error_return:;
224         if ( nvals != NULL ) {
225                 ber_bvarray_free_x( nvals, memctx );
226         }
227         return rc;
228 }
229
230 int
231 attr_merge_one(
232         Entry           *e,
233         AttributeDescription *desc,
234         struct berval   *val,
235         struct berval   *nval )
236 {
237         int rc;
238         Attribute       **a;
239
240         for ( a = &e->e_attrs; *a != NULL; a = &(*a)->a_next ) {
241                 if ( ad_cmp( (*a)->a_desc, desc ) == 0 ) {
242                         break;
243                 }
244         }
245
246         if ( *a == NULL ) {
247                 *a = (Attribute *) ch_malloc( sizeof(Attribute) );
248                 (*a)->a_desc = desc;
249                 (*a)->a_vals = NULL;
250                 (*a)->a_nvals = NULL;
251                 (*a)->a_next = NULL;
252                 (*a)->a_flags = 0;
253         }
254
255         rc = value_add_one( &(*a)->a_vals, val );
256
257         if ( rc == LDAP_SUCCESS ) {
258                 if ( nval ) {
259                         rc = value_add_one( &(*a)->a_nvals, nval );
260                         /* FIXME: what if rc != LDAP_SUCCESS ? */
261                 } else {
262                         (*a)->a_nvals = (*a)->a_vals;
263                 }
264         }
265         return rc;
266 }
267
268 int
269 attr_merge_normalize_one(
270         Entry           *e,
271         AttributeDescription *desc,
272         struct berval   *val,
273         void            *memctx )
274 {
275         struct berval   nval;
276         struct berval   *nvalp = NULL;
277         int             rc;
278
279         if ( desc->ad_type->sat_equality &&
280                 desc->ad_type->sat_equality->smr_normalize )
281         {
282                 rc = (*desc->ad_type->sat_equality->smr_normalize)(
283                                 SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX,
284                                 desc->ad_type->sat_syntax,
285                                 desc->ad_type->sat_equality,
286                                 val, &nval, memctx );
287
288                 if ( rc != LDAP_SUCCESS ) {
289                         return rc;
290                 }
291                 nvalp = &nval;
292         }
293
294         rc = attr_merge_one( e, desc, val, nvalp );
295         if ( nvalp != NULL ) {
296                 slap_sl_free( nval.bv_val, memctx );
297         }
298         return rc;
299 }
300
301 /*
302  * attrs_find - find attribute(s) by AttributeDescription
303  * returns next attribute which is subtype of provided description.
304  */
305
306 Attribute *
307 attrs_find(
308     Attribute   *a,
309         AttributeDescription *desc )
310 {
311         for ( ; a != NULL; a = a->a_next ) {
312                 if ( is_ad_subtype( a->a_desc, desc ) ) {
313                         return( a );
314                 }
315         }
316
317         return( NULL );
318 }
319
320 /*
321  * attr_find - find attribute by type
322  */
323
324 Attribute *
325 attr_find(
326     Attribute   *a,
327         AttributeDescription *desc )
328 {
329         for ( ; a != NULL; a = a->a_next ) {
330                 if ( ad_cmp( a->a_desc, desc ) == 0 ) {
331                         return( a );
332                 }
333         }
334
335         return( NULL );
336 }
337
338 /*
339  * attr_delete - delete the attribute type in list pointed to by attrs
340  * return       0       deleted ok
341  *              1       not found in list a
342  *              -1      something bad happened
343  */
344
345 int
346 attr_delete(
347     Attribute   **attrs,
348         AttributeDescription *desc )
349 {
350         Attribute       **a;
351
352         for ( a = attrs; *a != NULL; a = &(*a)->a_next ) {
353                 if ( ad_cmp( (*a)->a_desc, desc ) == 0 ) {
354                         Attribute       *save = *a;
355                         *a = (*a)->a_next;
356                         attr_free( save );
357
358                         return LDAP_SUCCESS;
359                 }
360         }
361
362         return LDAP_NO_SUCH_ATTRIBUTE;
363 }
364