at.c 7.82 KB
Newer Older
1
2
/* $OpenLDAP$ */
/*
Kurt Zeilenga's avatar
Kurt Zeilenga committed
3
 * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved.
4
5
 * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
 */
6
/* at.c - routines for dealing with attribute types */
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

#include "portable.h"

#include <stdio.h>

#include <ac/ctype.h>
#include <ac/errno.h>
#include <ac/socket.h>
#include <ac/string.h>
#include <ac/time.h>

#include "ldap_pvt.h"
#include "slap.h"


22
23
24
25
26
27
28
29
30
31
32
33
34
int is_at_syntax(
	AttributeType *at,
	const char *oid )
{
	for( ; at != NULL; at = at->sat_sup ) {
		if( at->sat_syntax_oid ) {
			return ( strcmp( at->sat_syntax_oid, oid ) == 0 );
		}
	}

	return 0;
}

35
36
37
38
39
40
41
int is_at_subtype(
	AttributeType *sub,
	AttributeType *sup )
{
	for( ; sub != NULL; sub = sub->sat_sup ) {
		if( sub == sup ) return 1;
	}
42

43
44
	return 0;
}
45
46

struct aindexrec {
Howard Chu's avatar
Howard Chu committed
47
	struct berval	air_name;
48
49
50
51
52
53
54
55
56
57
58
59
	AttributeType	*air_at;
};

static Avlnode	*attr_index = NULL;
static AttributeType *attr_list = NULL;

static int
attr_index_cmp(
    struct aindexrec	*air1,
    struct aindexrec	*air2
)
{
Howard Chu's avatar
Howard Chu committed
60
61
62
63
	int i = air1->air_name.bv_len - air2->air_name.bv_len;
	if (i)
		return i;
	return (strcasecmp( air1->air_name.bv_val, air2->air_name.bv_val ));
64
65
66
67
}

static int
attr_index_name_cmp(
68
69
70
71
    struct berval	*type,
    struct aindexrec	*air
)
{
Howard Chu's avatar
Howard Chu committed
72
73
74
75
76
	int i = type->bv_len - air->air_name.bv_len;
	if (i)
		return i;
	return (strncasecmp( type->bv_val, air->air_name.bv_val,
		type->bv_len ));
77
78
}

79
80
81
82
83
AttributeType *
at_find(
    const char		*name
)
{
Howard Chu's avatar
Howard Chu committed
84
	struct berval bv;
85

Howard Chu's avatar
Howard Chu committed
86
87
	bv.bv_val = (char *)name;
	bv.bv_len = strlen( name );
88

Howard Chu's avatar
Howard Chu committed
89
	return at_bvfind( &bv );
90
}
91
92
93
94
95
96
97
98
99

AttributeType *
at_bvfind(
    struct berval	*name
)
{
	struct aindexrec *air;

	air = (struct aindexrec *) avl_find( attr_index, name,
Howard Chu's avatar
Howard Chu committed
100
            (AVL_CMP) attr_index_name_cmp );
101
102
103

	return air != NULL ? air->air_at : NULL;
}
104
105
106
107
108
109
110
111
112
113
114
115
116
117

int
at_append_to_list(
    AttributeType	*sat,
    AttributeType	***listp
)
{
	AttributeType	**list;
	AttributeType	**list1;
	int		size;

	list = *listp;
	if ( !list ) {
		size = 2;
118
		list = ch_calloc(size, sizeof(AttributeType *));
119
120
121
122
123
124
125
126
127
128
129
		if ( !list ) {
			return -1;
		}
	} else {
		size = 0;
		list1 = *listp;
		while ( *list1 ) {
			size++;
			list1++;
		}
		size += 2;
130
		list1 = ch_realloc(list, size*sizeof(AttributeType *));
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
		if ( !list1 ) {
			return -1;
		}
		list = list1;
	}
	list[size-2] = sat;
	list[size-1] = NULL;
	*listp = list;
	return 0;
}

int
at_delete_from_list(
    int			pos,
    AttributeType	***listp
)
{
	AttributeType	**list;
	AttributeType	**list1;
	int		i;
	int		j;

	if ( pos < 0 ) {
		return -2;
	}
	list = *listp;
	for ( i=0; list[i]; i++ )
		;
	if ( pos >= i ) {
		return -2;
	}
	for ( i=pos, j=pos+1; list[j]; i++, j++ ) {
		list[i] = list[j];
	}
	list[i] = NULL;
	/* Tell the runtime this can be shrinked */
167
	list1 = ch_realloc(list, (i+1)*sizeof(AttributeType **));
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
	if ( !list1 ) {
		return -1;
	}
	*listp = list1;
	return 0;
}

int
at_find_in_list(
    AttributeType	*sat,
    AttributeType	**list
)
{
	int	i;

	if ( !list ) {
		return -1;
	}
	for ( i=0; list[i]; i++ ) {
		if ( sat == list[i] ) {
			return i;
		}
	}
	return -1;
}

194
195
196
197
198
199
200
201
void
at_destroy( void )
{
	AttributeType *a, *n;
	avl_free(attr_index, ldap_memfree);

	for (a=attr_list; a; a=n) {
		n = a->sat_next;
Howard Chu's avatar
Howard Chu committed
202
		if (a->sat_subtypes) ldap_memfree(a->sat_subtypes);
203
		ad_destroy(a->sat_ad);
204
		ldap_pvt_thread_mutex_destroy(&a->sat_ad_mutex);
205
206
		ldap_attributetype_free((LDAPAttributeType *)a);
	}
207
	ad_destroy(slap_schema.si_at_undefined->sat_ad);
208
209
}

210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
static int
at_insert(
    AttributeType	*sat,
    const char		**err
)
{
	AttributeType		**atp;
	struct aindexrec	*air;
	char			**names;

	atp = &attr_list;
	while ( *atp != NULL ) {
		atp = &(*atp)->sat_next;
	}
	*atp = sat;

	if ( sat->sat_oid ) {
		air = (struct aindexrec *)
			ch_calloc( 1, sizeof(struct aindexrec) );
Howard Chu's avatar
Howard Chu committed
229
230
		air->air_name.bv_val = sat->sat_oid;
		air->air_name.bv_len = strlen(sat->sat_oid);
231
232
233
234
235
236
237
238
239
		air->air_at = sat;
		if ( avl_insert( &attr_index, (caddr_t) air,
				 (AVL_CMP) attr_index_cmp,
				 (AVL_DUP) avl_dup_error ) ) {
			*err = sat->sat_oid;
			ldap_memfree(air);
			return SLAP_SCHERR_DUP_ATTR;
		}
		/* FIX: temporal consistency check */
Howard Chu's avatar
Howard Chu committed
240
		at_bvfind(&air->air_name);
241
242
243
244
245
246
	}

	if ( (names = sat->sat_names) ) {
		while ( *names ) {
			air = (struct aindexrec *)
				ch_calloc( 1, sizeof(struct aindexrec) );
Howard Chu's avatar
Howard Chu committed
247
248
			air->air_name.bv_val = *names;
			air->air_name.bv_len = strlen(*names);
249
250
251
252
253
254
255
256
257
			air->air_at = sat;
			if ( avl_insert( &attr_index, (caddr_t) air,
					 (AVL_CMP) attr_index_cmp,
					 (AVL_DUP) avl_dup_error ) ) {
				*err = *names;
				ldap_memfree(air);
				return SLAP_SCHERR_DUP_ATTR;
			}
			/* FIX: temporal consistency check */
Howard Chu's avatar
Howard Chu committed
258
			at_bvfind(&air->air_name);
259
260
261
262
263
264
265
266
267
			names++;
		}
	}

	return 0;
}

int
at_add(
268
    LDAPAttributeType	*at,
269
270
271
272
273
274
275
276
277
278
    const char		**err
)
{
	AttributeType	*sat;
	MatchingRule	*mr;
	Syntax		*syn;
	int		code;
	char			*cname;

	if ( at->at_names && at->at_names[0] ) {
Kurt Zeilenga's avatar
Kurt Zeilenga committed
279
280
281
282
283
284
285
286
		int i;

		for( i=0; at->at_names[i]; i++ ) {
			if( !slap_valid_descr( at->at_names[i] ) ) {
				return SLAP_SCHERR_BAD_DESCR;
			}
		}

287
		cname = at->at_names[0];
Kurt Zeilenga's avatar
Kurt Zeilenga committed
288

289
290
291
292
293
	} else if ( at->at_oid ) {
		cname = at->at_oid;
	} else {
		return SLAP_SCHERR_ATTR_INCOMPLETE;
	}
294
295
296
297
298

	if ( at->at_collective ) {
		return SLAP_SCHERR_NOT_SUPPORTED;
	}

299
	sat = (AttributeType *) ch_calloc( 1, sizeof(AttributeType) );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
300
	AC_MEMCPY( &sat->sat_atype, at, sizeof(LDAPAttributeType));
301

302
303
	sat->sat_cname.bv_val = cname;
	sat->sat_cname.bv_len = strlen( cname );
304
	ldap_pvt_thread_mutex_init(&sat->sat_ad_mutex);
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329

	if ( at->at_sup_oid ) {
		AttributeType *supsat = at_find(at->at_sup_oid);

		if ( (supsat == NULL ) ) {
			*err = at->at_sup_oid;
			return SLAP_SCHERR_ATTR_NOT_FOUND;
		}

		sat->sat_sup = supsat;

		if ( at_append_to_list(sat, &supsat->sat_subtypes) ) {
			*err = cname;
			return SLAP_SCHERR_OUTOFMEM;
		}
	}

	/*
	 * Inherit definitions from superiors.  We only check the
	 * direct superior since that one has already inherited from
	 * its own superiorss
	 */
	if ( sat->sat_sup ) {
		sat->sat_syntax = sat->sat_sup->sat_syntax;
		sat->sat_equality = sat->sat_sup->sat_equality;
330
		sat->sat_approx = sat->sat_sup->sat_approx;
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
		sat->sat_ordering = sat->sat_sup->sat_ordering;
		sat->sat_substr = sat->sat_sup->sat_substr;
	}

	if ( at->at_syntax_oid ) {
		if ( (syn = syn_find(sat->sat_syntax_oid)) ) {
			sat->sat_syntax = syn;
		} else {
			*err = sat->sat_syntax_oid;
			return SLAP_SCHERR_SYN_NOT_FOUND;
		}


	} else if ( sat->sat_syntax == NULL ) {
		return SLAP_SCHERR_ATTR_INCOMPLETE;
	}

	if ( sat->sat_equality_oid ) {
		if ( (mr = mr_find(sat->sat_equality_oid)) ) {
			sat->sat_equality = mr;
351
			sat->sat_approx = mr->smr_associated;
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
		} else {
			*err = sat->sat_equality_oid;
			return SLAP_SCHERR_MR_NOT_FOUND;
		}

	}

	if ( sat->sat_ordering_oid ) {
		if ( (mr = mr_find(sat->sat_ordering_oid)) ) {
			sat->sat_ordering = mr;
		} else {
			*err = sat->sat_ordering_oid;
			return SLAP_SCHERR_MR_NOT_FOUND;
		}
	}

	if ( sat->sat_substr_oid ) {
		if ( (mr = mr_find(sat->sat_substr_oid)) ) {
			sat->sat_substr = mr;
		} else {
			*err = sat->sat_substr_oid;
			return SLAP_SCHERR_MR_NOT_FOUND;
		}
	}

	code = at_insert(sat,err);
Kurt Zeilenga's avatar
Kurt Zeilenga committed
378
	return code;
379
380
381
382
383
384
385
386
}

#ifdef LDAP_DEBUG
static int
at_index_printnode( struct aindexrec *air )
{

	printf("%s = %s\n",
Howard Chu's avatar
Howard Chu committed
387
		air->air_name.bv_val,
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
		ldap_attributetype2str(&air->air_at->sat_atype) );
	return( 0 );
}

static void
at_index_print( void )
{
	printf("Printing attribute type index:\n");
	(void) avl_apply( attr_index, (AVL_APPLY) at_index_printnode,
		0, -1, AVL_INORDER );
}
#endif

#if defined( SLAPD_SCHEMA_DN )
int
at_schema_info( Entry *e )
{
405
	struct berval	vals[2];
406
407
	AttributeType	*at;

408
409
	AttributeDescription *ad_attributeTypes = slap_schema.si_ad_attributeTypes;

410
	vals[1].bv_val = NULL;
411
412

	for ( at = attr_list; at; at = at->sat_next ) {
413
		if ( ldap_attributetype2bv( &at->sat_atype, vals ) == NULL ) {
414
415
			return -1;
		}
416
#if 0
417
		Debug( LDAP_DEBUG_TRACE, "Merging at [%ld] %s\n",
418
		       (long) vals[0].bv_len, vals[0].bv_val, 0 );
419
#endif
420
		attr_merge( e, ad_attributeTypes, vals );
421
		ldap_memfree( vals[0].bv_val );
422
423
424
425
	}
	return 0;
}
#endif