attr.c 8.66 KB
Newer Older
Kurt Zeilenga's avatar
Kurt Zeilenga committed
1
2
/* attr.c - backend routines for dealing with attributes */
/* $OpenLDAP$ */
Kurt Zeilenga's avatar
Notices    
Kurt Zeilenga committed
3
4
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
 *
Kurt Zeilenga's avatar
Kurt Zeilenga committed
5
 * Copyright 2000-2008 The OpenLDAP Foundation.
Kurt Zeilenga's avatar
Notices    
Kurt Zeilenga committed
6
7
8
9
10
11
12
13
14
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted only as authorized by the OpenLDAP
 * Public License.
 *
 * A copy of this license is available in the file LICENSE in the
 * top-level directory of the distribution or, alternatively, at
 * <http://www.OpenLDAP.org/license.html>.
Kurt Zeilenga's avatar
Kurt Zeilenga committed
15
16
17
18
19
20
21
22
23
24
25
 */

#include "portable.h"

#include <stdio.h>

#include <ac/socket.h>
#include <ac/string.h>

#include "slap.h"
#include "back-bdb.h"
26
#include "lutil.h"
Kurt Zeilenga's avatar
Kurt Zeilenga committed
27

Howard Chu's avatar
Howard Chu committed
28
29
30
31
32
/* Find the ad, return -1 if not found,
 * set point for insertion if ins is non-NULL
 */
int
bdb_attr_slot( struct bdb_info *bdb, AttributeDescription *ad, unsigned *ins )
Kurt Zeilenga's avatar
Kurt Zeilenga committed
33
{
34
35
	unsigned base = 0, cursor = 0;
	unsigned n = bdb->bi_nattrs;
Howard Chu's avatar
Howard Chu committed
36
	int val = 0;
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
	
	while ( 0 < n ) {
		int pivot = n >> 1;
		cursor = base + pivot;

		val = SLAP_PTRCMP( ad, bdb->bi_attrs[cursor]->ai_desc );
		if ( val < 0 ) {
			n = pivot;
		} else if ( val > 0 ) {
			base = cursor + 1;
			n -= pivot + 1;
		} else {
			return cursor;
		}
	}
Howard Chu's avatar
Howard Chu committed
52
53
54
55
56
57
	if ( ins ) {
		if ( val > 0 )
			++cursor;
		*ins = cursor;
	}
	return -1;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
58
59
60
}

static int
61
ainfo_insert( struct bdb_info *bdb, AttrInfo *a )
Kurt Zeilenga's avatar
Kurt Zeilenga committed
62
{
Howard Chu's avatar
Howard Chu committed
63
64
	unsigned x;
	int i = bdb_attr_slot( bdb, a->ai_desc, &x );
65
66

	/* Is it a dup? */
Howard Chu's avatar
Howard Chu committed
67
	if ( i >= 0 )
68
69
70
71
72
73
74
75
76
77
		return -1;

	bdb->bi_attrs = ch_realloc( bdb->bi_attrs, ( bdb->bi_nattrs+1 ) * 
		sizeof( AttrInfo * ));
	if ( x < bdb->bi_nattrs )
		AC_MEMCPY( &bdb->bi_attrs[x+1], &bdb->bi_attrs[x],
			( bdb->bi_nattrs - x ) * sizeof( AttrInfo *));
	bdb->bi_attrs[x] = a;
	bdb->bi_nattrs++;
	return 0;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
78
79
}

Howard Chu's avatar
Howard Chu committed
80
AttrInfo *
Kurt Zeilenga's avatar
Kurt Zeilenga committed
81
bdb_attr_mask(
Kurt Zeilenga's avatar
Kurt Zeilenga committed
82
	struct bdb_info	*bdb,
Howard Chu's avatar
Howard Chu committed
83
	AttributeDescription *desc )
Kurt Zeilenga's avatar
Kurt Zeilenga committed
84
{
Howard Chu's avatar
Howard Chu committed
85
86
	int i = bdb_attr_slot( bdb, desc, NULL );
	return i < 0 ? NULL : bdb->bi_attrs[i];
Kurt Zeilenga's avatar
Kurt Zeilenga committed
87
88
89
90
}

int
bdb_attr_index_config(
Kurt Zeilenga's avatar
Kurt Zeilenga committed
91
92
93
94
95
	struct bdb_info	*bdb,
	const char		*fname,
	int			lineno,
	int			argc,
	char		**argv )
Kurt Zeilenga's avatar
Kurt Zeilenga committed
96
{
Howard Chu's avatar
Howard Chu committed
97
	int rc = 0;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
98
99
100
101
102
	int	i;
	slap_mask_t mask;
	char **attrs;
	char **indexes = NULL;

103
	attrs = ldap_str2charray( argv[0], "," );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
104
105
106
107
108
109
110
111
112

	if( attrs == NULL ) {
		fprintf( stderr, "%s: line %d: "
			"no attributes specified: %s\n",
			fname, lineno, argv[0] );
		return LDAP_PARAM_ERROR;
	}

	if ( argc > 1 ) {
113
		indexes = ldap_str2charray( argv[1], "," );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
114
115
116
117
118

		if( indexes == NULL ) {
			fprintf( stderr, "%s: line %d: "
				"no indexes specified: %s\n",
				fname, lineno, argv[1] );
Howard Chu's avatar
Howard Chu committed
119
120
			rc = LDAP_PARAM_ERROR;
			goto done;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
		}
	}

	if( indexes == NULL ) {
		mask = bdb->bi_defaultmask;

	} else {
		mask = 0;

		for ( i = 0; indexes[i] != NULL; i++ ) {
			slap_mask_t index;
			rc = slap_str2index( indexes[i], &index );

			if( rc != LDAP_SUCCESS ) {
				fprintf( stderr, "%s: line %d: "
					"index type \"%s\" undefined\n",
					fname, lineno, indexes[i] );
Howard Chu's avatar
Howard Chu committed
138
139
				rc = LDAP_PARAM_ERROR;
				goto done;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
140
141
142
143
144
145
			}

			mask |= index;
		}
	}

Kurt Zeilenga's avatar
Kurt Zeilenga committed
146
	if( !mask ) {
Kurt Zeilenga's avatar
Kurt Zeilenga committed
147
148
149
		fprintf( stderr, "%s: line %d: "
			"no indexes selected\n",
			fname, lineno );
Howard Chu's avatar
Howard Chu committed
150
151
		rc = LDAP_PARAM_ERROR;
		goto done;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
152
153
154
155
156
157
	}

	for ( i = 0; attrs[i] != NULL; i++ ) {
		AttrInfo	*a;
		AttributeDescription *ad;
		const char *text;
158
159
160
161
#ifdef LDAP_COMP_MATCH
		ComponentReference* cr = NULL;
		AttrInfo *a_cr = NULL;
#endif
Kurt Zeilenga's avatar
Kurt Zeilenga committed
162
163

		if( strcasecmp( attrs[i], "default" ) == 0 ) {
164
			bdb->bi_defaultmask |= mask;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
165
166
167
			continue;
		}

168
169
170
171
172
173
174
#ifdef LDAP_COMP_MATCH
		if ( is_component_reference( attrs[i] ) ) {
			rc = extract_component_reference( attrs[i], &cr );
			if ( rc != LDAP_SUCCESS ) {
				fprintf( stderr, "%s: line %d: "
					"index component reference\"%s\" undefined\n",
					fname, lineno, attrs[i] );
Howard Chu's avatar
Howard Chu committed
175
				goto done;
176
177
178
179
180
181
182
183
184
185
			}
			cr->cr_indexmask = mask;
			/*
			 * After extracting a component reference
			 * only the name of a attribute will be remaining
			 */
		} else {
			cr = NULL;
		}
#endif
Kurt Zeilenga's avatar
Kurt Zeilenga committed
186
187
188
189
190
191
192
		ad = NULL;
		rc = slap_str2ad( attrs[i], &ad, &text );

		if( rc != LDAP_SUCCESS ) {
			fprintf( stderr, "%s: line %d: "
				"index attribute \"%s\" undefined\n",
				fname, lineno, attrs[i] );
Howard Chu's avatar
Howard Chu committed
193
			goto done;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
194
195
196
197
198
199
		}

		if( slap_ad_is_binary( ad ) ) {
			fprintf( stderr, "%s: line %d: "
				"index of attribute \"%s\" disallowed\n",
				fname, lineno, attrs[i] );
Howard Chu's avatar
Howard Chu committed
200
201
			rc = LDAP_UNWILLING_TO_PERFORM;
			goto done;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
202
203
204
		}

		if( IS_SLAP_INDEX( mask, SLAP_INDEX_APPROX ) && !(
205
			ad->ad_type->sat_approx
Kurt Zeilenga's avatar
Kurt Zeilenga committed
206
				&& ad->ad_type->sat_approx->smr_indexer
207
				&& ad->ad_type->sat_approx->smr_filter ) )
Kurt Zeilenga's avatar
Kurt Zeilenga committed
208
209
210
211
		{
			fprintf( stderr, "%s: line %d: "
				"approx index of attribute \"%s\" disallowed\n",
				fname, lineno, attrs[i] );
Howard Chu's avatar
Howard Chu committed
212
213
			rc = LDAP_INAPPROPRIATE_MATCHING;
			goto done;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
214
215
216
217
218
219
220
221
222
223
		}

		if( IS_SLAP_INDEX( mask, SLAP_INDEX_EQUALITY ) && !(
			ad->ad_type->sat_equality
				&& ad->ad_type->sat_equality->smr_indexer
				&& ad->ad_type->sat_equality->smr_filter ) )
		{
			fprintf( stderr, "%s: line %d: "
				"equality index of attribute \"%s\" disallowed\n",
				fname, lineno, attrs[i] );
Howard Chu's avatar
Howard Chu committed
224
225
			rc = LDAP_INAPPROPRIATE_MATCHING;
			goto done;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
226
227
228
229
230
231
232
233
234
235
		}

		if( IS_SLAP_INDEX( mask, SLAP_INDEX_SUBSTR ) && !(
			ad->ad_type->sat_substr
				&& ad->ad_type->sat_substr->smr_indexer
				&& ad->ad_type->sat_substr->smr_filter ) )
		{
			fprintf( stderr, "%s: line %d: "
				"substr index of attribute \"%s\" disallowed\n",
				fname, lineno, attrs[i] );
Howard Chu's avatar
Howard Chu committed
236
237
			rc = LDAP_INAPPROPRIATE_MATCHING;
			goto done;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
238
239
		}

240
		Debug( LDAP_DEBUG_CONFIG, "index %s 0x%04lx\n",
241
			ad->ad_cname.bv_val, mask, 0 ); 
Kurt Zeilenga's avatar
Kurt Zeilenga committed
242

Howard Chu's avatar
Howard Chu committed
243
244
245
246
247
		a = (AttrInfo *) ch_malloc( sizeof(AttrInfo) );

#ifdef LDAP_COMP_MATCH
		a->ai_cr = NULL;
#endif
Kurt Zeilenga's avatar
Kurt Zeilenga committed
248
		a->ai_desc = ad;
Howard Chu's avatar
Howard Chu committed
249
250
251
252
253
254
255
256
257

		if ( bdb->bi_flags & BDB_IS_OPEN ) {
			a->ai_indexmask = 0;
			a->ai_newmask = mask;
		} else {
			a->ai_indexmask = mask;
			a->ai_newmask = 0;
		}

258
259
#ifdef LDAP_COMP_MATCH
		if ( cr ) {
260
			a_cr = bdb_attr_mask( bdb, ad );
261
262
263
264
265
266
267
268
269
			if ( a_cr ) {
				/*
				 * AttrInfo is already in AVL
				 * just add the extracted component reference
				 * in the AttrInfo
				 */
				rc = insert_component_reference( cr, &a_cr->ai_cr );
				if ( rc != LDAP_SUCCESS) {
					fprintf( stderr, " error during inserting component reference in %s ", attrs[i]);
Howard Chu's avatar
Howard Chu committed
270
271
					rc = LDAP_PARAM_ERROR;
					goto done;
272
273
274
275
276
277
				}
				continue;
			} else {
				rc = insert_component_reference( cr, &a->ai_cr );
				if ( rc != LDAP_SUCCESS) {
					fprintf( stderr, " error during inserting component reference in %s ", attrs[i]);
Howard Chu's avatar
Howard Chu committed
278
279
					rc = LDAP_PARAM_ERROR;
					goto done;
280
281
282
283
				}
			}
		}
#endif
284
		rc = ainfo_insert( bdb, a );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
285
		if( rc ) {
Howard Chu's avatar
Howard Chu committed
286
			if ( bdb->bi_flags & BDB_IS_OPEN ) {
287
				AttrInfo *b = bdb_attr_mask( bdb, ad );
Howard Chu's avatar
Howard Chu committed
288
289
290
291
292
293
294
				/* If we were editing this attr, reset it */
				b->ai_indexmask &= ~BDB_INDEX_DELETING;
				/* If this is leftover from a previous add, commit it */
				if ( b->ai_newmask )
					b->ai_indexmask = b->ai_newmask;
				b->ai_newmask = a->ai_newmask;
				ch_free( a );
Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
295
				rc = 0;
Howard Chu's avatar
Howard Chu committed
296
297
				continue;
			}
298
299
			fprintf( stderr,
				"%s: line %d: duplicate index definition for attr \"%s\".\n",
Kurt Zeilenga's avatar
Kurt Zeilenga committed
300
				fname, lineno, attrs[i] );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
301

Howard Chu's avatar
Howard Chu committed
302
303
			rc = LDAP_PARAM_ERROR;
			goto done;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
304
305
306
		}
	}

Howard Chu's avatar
Howard Chu committed
307
done:
308
309
	ldap_charray_free( attrs );
	if ( indexes != NULL ) ldap_charray_free( indexes );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
310

Howard Chu's avatar
Howard Chu committed
311
	return rc;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
312
313
}

314
static int
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
bdb_attr_index_unparser( void *v1, void *v2 )
{
	AttrInfo *ai = v1;
	BerVarray *bva = v2;
	struct berval bv;
	char *ptr;

	slap_index2bvlen( ai->ai_indexmask, &bv );
	if ( bv.bv_len ) {
		bv.bv_len += ai->ai_desc->ad_cname.bv_len + 1;
		ptr = ch_malloc( bv.bv_len+1 );
		bv.bv_val = lutil_strcopy( ptr, ai->ai_desc->ad_cname.bv_val );
		*bv.bv_val++ = ' ';
		slap_index2bv( ai->ai_indexmask, &bv );
		bv.bv_val = ptr;
		ber_bvarray_add( bva, &bv );
	}
332
	return 0;
333
334
335
336
337
338
339
340
}

static AttributeDescription addef = { NULL, NULL, BER_BVC("default") };
static AttrInfo aidef = { &addef };

void
bdb_attr_index_unparse( struct bdb_info *bdb, BerVarray *bva )
{
341
342
	int i;

343
344
345
346
	if ( bdb->bi_defaultmask ) {
		aidef.ai_indexmask = bdb->bi_defaultmask;
		bdb_attr_index_unparser( &aidef, bva );
	}
347
348
	for ( i=0; i<bdb->bi_nattrs; i++ )
		bdb_attr_index_unparser( bdb->bi_attrs[i], bva );
349
350
}

351
352
void
bdb_attr_info_free( AttrInfo *ai )
Howard Chu's avatar
Howard Chu committed
353
354
355
356
357
358
359
{
#ifdef LDAP_COMP_MATCH
	free( ai->ai_cr );
#endif
	free( ai );
}

Kurt Zeilenga's avatar
Kurt Zeilenga committed
360
void
361
bdb_attr_index_destroy( struct bdb_info *bdb )
Kurt Zeilenga's avatar
Kurt Zeilenga committed
362
{
363
	int i;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
364

365
366
	for ( i=0; i<bdb->bi_nattrs; i++ ) 
		bdb_attr_info_free( bdb->bi_attrs[i] );
Howard Chu's avatar
Howard Chu committed
367

368
	free( bdb->bi_attrs );
Howard Chu's avatar
Howard Chu committed
369
}
Howard Chu's avatar
Howard Chu committed
370

371
void bdb_attr_index_free( struct bdb_info *bdb, AttributeDescription *ad )
Howard Chu's avatar
Howard Chu committed
372
{
Howard Chu's avatar
Howard Chu committed
373
	int i;
374

Howard Chu's avatar
Howard Chu committed
375
376
	i = bdb_attr_slot( bdb, ad, NULL );
	if ( i >= 0 ) {
377
378
379
380
		bdb_attr_info_free( bdb->bi_attrs[i] );
		bdb->bi_nattrs--;
		for (; i<bdb->bi_nattrs; i++)
			bdb->bi_attrs[i] = bdb->bi_attrs[i+1];
Howard Chu's avatar
Howard Chu committed
381
382
383
384
385
	}
}

void bdb_attr_flush( struct bdb_info *bdb )
{
386
387
388
389
390
391
392
393
394
395
396
	int i;

	for ( i=0; i<bdb->bi_nattrs; i++ ) {
		if ( bdb->bi_attrs[i]->ai_indexmask & BDB_INDEX_DELETING ) {
			int j;
			bdb_attr_info_free( bdb->bi_attrs[i] );
			bdb->bi_nattrs--;
			for (j=i; j<bdb->bi_nattrs; j++)
				bdb->bi_attrs[j] = bdb->bi_attrs[j+1];
			i--;
		}
Howard Chu's avatar
Howard Chu committed
397
398
	}
}