attr.c revision 1.1.1.1.6.2 1 1.1.1.1.6.2 tls /* $NetBSD: attr.c,v 1.1.1.1.6.2 2014/08/19 23:52:02 tls Exp $ */
2 1.1.1.1.6.2 tls
3 1.1.1.1.6.2 tls /* attr.c - backend routines for dealing with attributes */
4 1.1.1.1.6.2 tls /* $OpenLDAP$ */
5 1.1.1.1.6.2 tls /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
6 1.1.1.1.6.2 tls *
7 1.1.1.1.6.2 tls * Copyright 2000-2014 The OpenLDAP Foundation.
8 1.1.1.1.6.2 tls * All rights reserved.
9 1.1.1.1.6.2 tls *
10 1.1.1.1.6.2 tls * Redistribution and use in source and binary forms, with or without
11 1.1.1.1.6.2 tls * modification, are permitted only as authorized by the OpenLDAP
12 1.1.1.1.6.2 tls * Public License.
13 1.1.1.1.6.2 tls *
14 1.1.1.1.6.2 tls * A copy of this license is available in the file LICENSE in the
15 1.1.1.1.6.2 tls * top-level directory of the distribution or, alternatively, at
16 1.1.1.1.6.2 tls * <http://www.OpenLDAP.org/license.html>.
17 1.1.1.1.6.2 tls */
18 1.1.1.1.6.2 tls
19 1.1.1.1.6.2 tls #include "portable.h"
20 1.1.1.1.6.2 tls
21 1.1.1.1.6.2 tls #include <stdio.h>
22 1.1.1.1.6.2 tls
23 1.1.1.1.6.2 tls #include <ac/socket.h>
24 1.1.1.1.6.2 tls #include <ac/string.h>
25 1.1.1.1.6.2 tls
26 1.1.1.1.6.2 tls #include "slap.h"
27 1.1.1.1.6.2 tls #include "back-mdb.h"
28 1.1.1.1.6.2 tls #include "config.h"
29 1.1.1.1.6.2 tls #include "lutil.h"
30 1.1.1.1.6.2 tls
31 1.1.1.1.6.2 tls /* Find the ad, return -1 if not found,
32 1.1.1.1.6.2 tls * set point for insertion if ins is non-NULL
33 1.1.1.1.6.2 tls */
34 1.1.1.1.6.2 tls int
35 1.1.1.1.6.2 tls mdb_attr_slot( struct mdb_info *mdb, AttributeDescription *ad, int *ins )
36 1.1.1.1.6.2 tls {
37 1.1.1.1.6.2 tls unsigned base = 0, cursor = 0;
38 1.1.1.1.6.2 tls unsigned n = mdb->mi_nattrs;
39 1.1.1.1.6.2 tls int val = 0;
40 1.1.1.1.6.2 tls
41 1.1.1.1.6.2 tls while ( 0 < n ) {
42 1.1.1.1.6.2 tls unsigned pivot = n >> 1;
43 1.1.1.1.6.2 tls cursor = base + pivot;
44 1.1.1.1.6.2 tls
45 1.1.1.1.6.2 tls val = SLAP_PTRCMP( ad, mdb->mi_attrs[cursor]->ai_desc );
46 1.1.1.1.6.2 tls if ( val < 0 ) {
47 1.1.1.1.6.2 tls n = pivot;
48 1.1.1.1.6.2 tls } else if ( val > 0 ) {
49 1.1.1.1.6.2 tls base = cursor + 1;
50 1.1.1.1.6.2 tls n -= pivot + 1;
51 1.1.1.1.6.2 tls } else {
52 1.1.1.1.6.2 tls return cursor;
53 1.1.1.1.6.2 tls }
54 1.1.1.1.6.2 tls }
55 1.1.1.1.6.2 tls if ( ins ) {
56 1.1.1.1.6.2 tls if ( val > 0 )
57 1.1.1.1.6.2 tls ++cursor;
58 1.1.1.1.6.2 tls *ins = cursor;
59 1.1.1.1.6.2 tls }
60 1.1.1.1.6.2 tls return -1;
61 1.1.1.1.6.2 tls }
62 1.1.1.1.6.2 tls
63 1.1.1.1.6.2 tls static int
64 1.1.1.1.6.2 tls ainfo_insert( struct mdb_info *mdb, AttrInfo *a )
65 1.1.1.1.6.2 tls {
66 1.1.1.1.6.2 tls int x;
67 1.1.1.1.6.2 tls int i = mdb_attr_slot( mdb, a->ai_desc, &x );
68 1.1.1.1.6.2 tls
69 1.1.1.1.6.2 tls /* Is it a dup? */
70 1.1.1.1.6.2 tls if ( i >= 0 )
71 1.1.1.1.6.2 tls return -1;
72 1.1.1.1.6.2 tls
73 1.1.1.1.6.2 tls mdb->mi_attrs = ch_realloc( mdb->mi_attrs, ( mdb->mi_nattrs+1 ) *
74 1.1.1.1.6.2 tls sizeof( AttrInfo * ));
75 1.1.1.1.6.2 tls if ( x < mdb->mi_nattrs )
76 1.1.1.1.6.2 tls AC_MEMCPY( &mdb->mi_attrs[x+1], &mdb->mi_attrs[x],
77 1.1.1.1.6.2 tls ( mdb->mi_nattrs - x ) * sizeof( AttrInfo *));
78 1.1.1.1.6.2 tls mdb->mi_attrs[x] = a;
79 1.1.1.1.6.2 tls mdb->mi_nattrs++;
80 1.1.1.1.6.2 tls return 0;
81 1.1.1.1.6.2 tls }
82 1.1.1.1.6.2 tls
83 1.1.1.1.6.2 tls AttrInfo *
84 1.1.1.1.6.2 tls mdb_attr_mask(
85 1.1.1.1.6.2 tls struct mdb_info *mdb,
86 1.1.1.1.6.2 tls AttributeDescription *desc )
87 1.1.1.1.6.2 tls {
88 1.1.1.1.6.2 tls int i = mdb_attr_slot( mdb, desc, NULL );
89 1.1.1.1.6.2 tls return i < 0 ? NULL : mdb->mi_attrs[i];
90 1.1.1.1.6.2 tls }
91 1.1.1.1.6.2 tls
92 1.1.1.1.6.2 tls /* Open all un-opened index DB handles */
93 1.1.1.1.6.2 tls int
94 1.1.1.1.6.2 tls mdb_attr_dbs_open(
95 1.1.1.1.6.2 tls BackendDB *be, MDB_txn *tx0, ConfigReply *cr )
96 1.1.1.1.6.2 tls {
97 1.1.1.1.6.2 tls struct mdb_info *mdb = (struct mdb_info *) be->be_private;
98 1.1.1.1.6.2 tls MDB_txn *txn;
99 1.1.1.1.6.2 tls MDB_dbi *dbis = NULL;
100 1.1.1.1.6.2 tls int i, flags;
101 1.1.1.1.6.2 tls int rc;
102 1.1.1.1.6.2 tls
103 1.1.1.1.6.2 tls txn = tx0;
104 1.1.1.1.6.2 tls if ( txn == NULL ) {
105 1.1.1.1.6.2 tls rc = mdb_txn_begin( mdb->mi_dbenv, NULL, 0, &txn );
106 1.1.1.1.6.2 tls if ( rc ) {
107 1.1.1.1.6.2 tls snprintf( cr->msg, sizeof(cr->msg), "database \"%s\": "
108 1.1.1.1.6.2 tls "txn_begin failed: %s (%d).",
109 1.1.1.1.6.2 tls be->be_suffix[0].bv_val, mdb_strerror(rc), rc );
110 1.1.1.1.6.2 tls Debug( LDAP_DEBUG_ANY,
111 1.1.1.1.6.2 tls LDAP_XSTRING(mdb_attr_dbs) ": %s\n",
112 1.1.1.1.6.2 tls cr->msg, 0, 0 );
113 1.1.1.1.6.2 tls return rc;
114 1.1.1.1.6.2 tls }
115 1.1.1.1.6.2 tls dbis = ch_calloc( 1, mdb->mi_nattrs * sizeof(MDB_dbi) );
116 1.1.1.1.6.2 tls } else {
117 1.1.1.1.6.2 tls rc = 0;
118 1.1.1.1.6.2 tls }
119 1.1.1.1.6.2 tls
120 1.1.1.1.6.2 tls flags = MDB_DUPSORT|MDB_DUPFIXED|MDB_INTEGERDUP;
121 1.1.1.1.6.2 tls if ( !(slapMode & SLAP_TOOL_READONLY) )
122 1.1.1.1.6.2 tls flags |= MDB_CREATE;
123 1.1.1.1.6.2 tls
124 1.1.1.1.6.2 tls for ( i=0; i<mdb->mi_nattrs; i++ ) {
125 1.1.1.1.6.2 tls if ( mdb->mi_attrs[i]->ai_dbi ) /* already open */
126 1.1.1.1.6.2 tls continue;
127 1.1.1.1.6.2 tls rc = mdb_dbi_open( txn, mdb->mi_attrs[i]->ai_desc->ad_type->sat_cname.bv_val,
128 1.1.1.1.6.2 tls flags, &mdb->mi_attrs[i]->ai_dbi );
129 1.1.1.1.6.2 tls if ( rc ) {
130 1.1.1.1.6.2 tls snprintf( cr->msg, sizeof(cr->msg), "database \"%s\": "
131 1.1.1.1.6.2 tls "mdb_dbi_open(%s) failed: %s (%d).",
132 1.1.1.1.6.2 tls be->be_suffix[0].bv_val,
133 1.1.1.1.6.2 tls mdb->mi_attrs[i]->ai_desc->ad_type->sat_cname.bv_val,
134 1.1.1.1.6.2 tls mdb_strerror(rc), rc );
135 1.1.1.1.6.2 tls Debug( LDAP_DEBUG_ANY,
136 1.1.1.1.6.2 tls LDAP_XSTRING(mdb_attr_dbs) ": %s\n",
137 1.1.1.1.6.2 tls cr->msg, 0, 0 );
138 1.1.1.1.6.2 tls break;
139 1.1.1.1.6.2 tls }
140 1.1.1.1.6.2 tls /* Remember newly opened DBI handles */
141 1.1.1.1.6.2 tls if ( dbis )
142 1.1.1.1.6.2 tls dbis[i] = mdb->mi_attrs[i]->ai_dbi;
143 1.1.1.1.6.2 tls }
144 1.1.1.1.6.2 tls
145 1.1.1.1.6.2 tls /* Only commit if this is our txn */
146 1.1.1.1.6.2 tls if ( tx0 == NULL ) {
147 1.1.1.1.6.2 tls if ( !rc ) {
148 1.1.1.1.6.2 tls rc = mdb_txn_commit( txn );
149 1.1.1.1.6.2 tls if ( rc ) {
150 1.1.1.1.6.2 tls snprintf( cr->msg, sizeof(cr->msg), "database \"%s\": "
151 1.1.1.1.6.2 tls "txn_commit failed: %s (%d).",
152 1.1.1.1.6.2 tls be->be_suffix[0].bv_val, mdb_strerror(rc), rc );
153 1.1.1.1.6.2 tls Debug( LDAP_DEBUG_ANY,
154 1.1.1.1.6.2 tls LDAP_XSTRING(mdb_attr_dbs) ": %s\n",
155 1.1.1.1.6.2 tls cr->msg, 0, 0 );
156 1.1.1.1.6.2 tls }
157 1.1.1.1.6.2 tls } else {
158 1.1.1.1.6.2 tls mdb_txn_abort( txn );
159 1.1.1.1.6.2 tls }
160 1.1.1.1.6.2 tls /* Something failed, forget anything we just opened */
161 1.1.1.1.6.2 tls if ( rc ) {
162 1.1.1.1.6.2 tls for ( i=0; i<mdb->mi_nattrs; i++ ) {
163 1.1.1.1.6.2 tls if ( dbis[i] ) {
164 1.1.1.1.6.2 tls mdb->mi_attrs[i]->ai_dbi = 0;
165 1.1.1.1.6.2 tls mdb->mi_attrs[i]->ai_indexmask |= MDB_INDEX_DELETING;
166 1.1.1.1.6.2 tls }
167 1.1.1.1.6.2 tls }
168 1.1.1.1.6.2 tls mdb_attr_flush( mdb );
169 1.1.1.1.6.2 tls }
170 1.1.1.1.6.2 tls ch_free( dbis );
171 1.1.1.1.6.2 tls }
172 1.1.1.1.6.2 tls
173 1.1.1.1.6.2 tls return rc;
174 1.1.1.1.6.2 tls }
175 1.1.1.1.6.2 tls
176 1.1.1.1.6.2 tls void
177 1.1.1.1.6.2 tls mdb_attr_dbs_close(
178 1.1.1.1.6.2 tls struct mdb_info *mdb
179 1.1.1.1.6.2 tls )
180 1.1.1.1.6.2 tls {
181 1.1.1.1.6.2 tls int i;
182 1.1.1.1.6.2 tls for ( i=0; i<mdb->mi_nattrs; i++ )
183 1.1.1.1.6.2 tls if ( mdb->mi_attrs[i]->ai_dbi ) {
184 1.1.1.1.6.2 tls mdb_dbi_close( mdb->mi_dbenv, mdb->mi_attrs[i]->ai_dbi );
185 1.1.1.1.6.2 tls mdb->mi_attrs[i]->ai_dbi = 0;
186 1.1.1.1.6.2 tls }
187 1.1.1.1.6.2 tls }
188 1.1.1.1.6.2 tls
189 1.1.1.1.6.2 tls int
190 1.1.1.1.6.2 tls mdb_attr_index_config(
191 1.1.1.1.6.2 tls struct mdb_info *mdb,
192 1.1.1.1.6.2 tls const char *fname,
193 1.1.1.1.6.2 tls int lineno,
194 1.1.1.1.6.2 tls int argc,
195 1.1.1.1.6.2 tls char **argv,
196 1.1.1.1.6.2 tls struct config_reply_s *c_reply)
197 1.1.1.1.6.2 tls {
198 1.1.1.1.6.2 tls int rc = 0;
199 1.1.1.1.6.2 tls int i;
200 1.1.1.1.6.2 tls slap_mask_t mask;
201 1.1.1.1.6.2 tls char **attrs;
202 1.1.1.1.6.2 tls char **indexes = NULL;
203 1.1.1.1.6.2 tls
204 1.1.1.1.6.2 tls attrs = ldap_str2charray( argv[0], "," );
205 1.1.1.1.6.2 tls
206 1.1.1.1.6.2 tls if( attrs == NULL ) {
207 1.1.1.1.6.2 tls fprintf( stderr, "%s: line %d: "
208 1.1.1.1.6.2 tls "no attributes specified: %s\n",
209 1.1.1.1.6.2 tls fname, lineno, argv[0] );
210 1.1.1.1.6.2 tls return LDAP_PARAM_ERROR;
211 1.1.1.1.6.2 tls }
212 1.1.1.1.6.2 tls
213 1.1.1.1.6.2 tls if ( argc > 1 ) {
214 1.1.1.1.6.2 tls indexes = ldap_str2charray( argv[1], "," );
215 1.1.1.1.6.2 tls
216 1.1.1.1.6.2 tls if( indexes == NULL ) {
217 1.1.1.1.6.2 tls fprintf( stderr, "%s: line %d: "
218 1.1.1.1.6.2 tls "no indexes specified: %s\n",
219 1.1.1.1.6.2 tls fname, lineno, argv[1] );
220 1.1.1.1.6.2 tls rc = LDAP_PARAM_ERROR;
221 1.1.1.1.6.2 tls goto done;
222 1.1.1.1.6.2 tls }
223 1.1.1.1.6.2 tls }
224 1.1.1.1.6.2 tls
225 1.1.1.1.6.2 tls if( indexes == NULL ) {
226 1.1.1.1.6.2 tls mask = mdb->mi_defaultmask;
227 1.1.1.1.6.2 tls
228 1.1.1.1.6.2 tls } else {
229 1.1.1.1.6.2 tls mask = 0;
230 1.1.1.1.6.2 tls
231 1.1.1.1.6.2 tls for ( i = 0; indexes[i] != NULL; i++ ) {
232 1.1.1.1.6.2 tls slap_mask_t index;
233 1.1.1.1.6.2 tls rc = slap_str2index( indexes[i], &index );
234 1.1.1.1.6.2 tls
235 1.1.1.1.6.2 tls if( rc != LDAP_SUCCESS ) {
236 1.1.1.1.6.2 tls if ( c_reply )
237 1.1.1.1.6.2 tls {
238 1.1.1.1.6.2 tls snprintf(c_reply->msg, sizeof(c_reply->msg),
239 1.1.1.1.6.2 tls "index type \"%s\" undefined", indexes[i] );
240 1.1.1.1.6.2 tls
241 1.1.1.1.6.2 tls fprintf( stderr, "%s: line %d: %s\n",
242 1.1.1.1.6.2 tls fname, lineno, c_reply->msg );
243 1.1.1.1.6.2 tls }
244 1.1.1.1.6.2 tls rc = LDAP_PARAM_ERROR;
245 1.1.1.1.6.2 tls goto done;
246 1.1.1.1.6.2 tls }
247 1.1.1.1.6.2 tls
248 1.1.1.1.6.2 tls mask |= index;
249 1.1.1.1.6.2 tls }
250 1.1.1.1.6.2 tls }
251 1.1.1.1.6.2 tls
252 1.1.1.1.6.2 tls if( !mask ) {
253 1.1.1.1.6.2 tls if ( c_reply )
254 1.1.1.1.6.2 tls {
255 1.1.1.1.6.2 tls snprintf(c_reply->msg, sizeof(c_reply->msg),
256 1.1.1.1.6.2 tls "no indexes selected" );
257 1.1.1.1.6.2 tls fprintf( stderr, "%s: line %d: %s\n",
258 1.1.1.1.6.2 tls fname, lineno, c_reply->msg );
259 1.1.1.1.6.2 tls }
260 1.1.1.1.6.2 tls rc = LDAP_PARAM_ERROR;
261 1.1.1.1.6.2 tls goto done;
262 1.1.1.1.6.2 tls }
263 1.1.1.1.6.2 tls
264 1.1.1.1.6.2 tls for ( i = 0; attrs[i] != NULL; i++ ) {
265 1.1.1.1.6.2 tls AttrInfo *a;
266 1.1.1.1.6.2 tls AttributeDescription *ad;
267 1.1.1.1.6.2 tls const char *text;
268 1.1.1.1.6.2 tls #ifdef LDAP_COMP_MATCH
269 1.1.1.1.6.2 tls ComponentReference* cr = NULL;
270 1.1.1.1.6.2 tls AttrInfo *a_cr = NULL;
271 1.1.1.1.6.2 tls #endif
272 1.1.1.1.6.2 tls
273 1.1.1.1.6.2 tls if( strcasecmp( attrs[i], "default" ) == 0 ) {
274 1.1.1.1.6.2 tls mdb->mi_defaultmask |= mask;
275 1.1.1.1.6.2 tls continue;
276 1.1.1.1.6.2 tls }
277 1.1.1.1.6.2 tls
278 1.1.1.1.6.2 tls #ifdef LDAP_COMP_MATCH
279 1.1.1.1.6.2 tls if ( is_component_reference( attrs[i] ) ) {
280 1.1.1.1.6.2 tls rc = extract_component_reference( attrs[i], &cr );
281 1.1.1.1.6.2 tls if ( rc != LDAP_SUCCESS ) {
282 1.1.1.1.6.2 tls if ( c_reply )
283 1.1.1.1.6.2 tls {
284 1.1.1.1.6.2 tls snprintf(c_reply->msg, sizeof(c_reply->msg),
285 1.1.1.1.6.2 tls "index component reference\"%s\" undefined",
286 1.1.1.1.6.2 tls attrs[i] );
287 1.1.1.1.6.2 tls fprintf( stderr, "%s: line %d: %s\n",
288 1.1.1.1.6.2 tls fname, lineno, c_reply->msg );
289 1.1.1.1.6.2 tls }
290 1.1.1.1.6.2 tls goto done;
291 1.1.1.1.6.2 tls }
292 1.1.1.1.6.2 tls cr->cr_indexmask = mask;
293 1.1.1.1.6.2 tls /*
294 1.1.1.1.6.2 tls * After extracting a component reference
295 1.1.1.1.6.2 tls * only the name of a attribute will be remaining
296 1.1.1.1.6.2 tls */
297 1.1.1.1.6.2 tls } else {
298 1.1.1.1.6.2 tls cr = NULL;
299 1.1.1.1.6.2 tls }
300 1.1.1.1.6.2 tls #endif
301 1.1.1.1.6.2 tls ad = NULL;
302 1.1.1.1.6.2 tls rc = slap_str2ad( attrs[i], &ad, &text );
303 1.1.1.1.6.2 tls
304 1.1.1.1.6.2 tls if( rc != LDAP_SUCCESS ) {
305 1.1.1.1.6.2 tls if ( c_reply )
306 1.1.1.1.6.2 tls {
307 1.1.1.1.6.2 tls snprintf(c_reply->msg, sizeof(c_reply->msg),
308 1.1.1.1.6.2 tls "index attribute \"%s\" undefined",
309 1.1.1.1.6.2 tls attrs[i] );
310 1.1.1.1.6.2 tls
311 1.1.1.1.6.2 tls fprintf( stderr, "%s: line %d: %s\n",
312 1.1.1.1.6.2 tls fname, lineno, c_reply->msg );
313 1.1.1.1.6.2 tls }
314 1.1.1.1.6.2 tls goto done;
315 1.1.1.1.6.2 tls }
316 1.1.1.1.6.2 tls
317 1.1.1.1.6.2 tls if( ad == slap_schema.si_ad_entryDN || slap_ad_is_binary( ad ) ) {
318 1.1.1.1.6.2 tls if (c_reply) {
319 1.1.1.1.6.2 tls snprintf(c_reply->msg, sizeof(c_reply->msg),
320 1.1.1.1.6.2 tls "index of attribute \"%s\" disallowed", attrs[i] );
321 1.1.1.1.6.2 tls fprintf( stderr, "%s: line %d: %s\n",
322 1.1.1.1.6.2 tls fname, lineno, c_reply->msg );
323 1.1.1.1.6.2 tls }
324 1.1.1.1.6.2 tls rc = LDAP_UNWILLING_TO_PERFORM;
325 1.1.1.1.6.2 tls goto done;
326 1.1.1.1.6.2 tls }
327 1.1.1.1.6.2 tls
328 1.1.1.1.6.2 tls if( IS_SLAP_INDEX( mask, SLAP_INDEX_APPROX ) && !(
329 1.1.1.1.6.2 tls ad->ad_type->sat_approx
330 1.1.1.1.6.2 tls && ad->ad_type->sat_approx->smr_indexer
331 1.1.1.1.6.2 tls && ad->ad_type->sat_approx->smr_filter ) )
332 1.1.1.1.6.2 tls {
333 1.1.1.1.6.2 tls if (c_reply) {
334 1.1.1.1.6.2 tls snprintf(c_reply->msg, sizeof(c_reply->msg),
335 1.1.1.1.6.2 tls "approx index of attribute \"%s\" disallowed", attrs[i] );
336 1.1.1.1.6.2 tls fprintf( stderr, "%s: line %d: %s\n",
337 1.1.1.1.6.2 tls fname, lineno, c_reply->msg );
338 1.1.1.1.6.2 tls }
339 1.1.1.1.6.2 tls rc = LDAP_INAPPROPRIATE_MATCHING;
340 1.1.1.1.6.2 tls goto done;
341 1.1.1.1.6.2 tls }
342 1.1.1.1.6.2 tls
343 1.1.1.1.6.2 tls if( IS_SLAP_INDEX( mask, SLAP_INDEX_EQUALITY ) && !(
344 1.1.1.1.6.2 tls ad->ad_type->sat_equality
345 1.1.1.1.6.2 tls && ad->ad_type->sat_equality->smr_indexer
346 1.1.1.1.6.2 tls && ad->ad_type->sat_equality->smr_filter ) )
347 1.1.1.1.6.2 tls {
348 1.1.1.1.6.2 tls if (c_reply) {
349 1.1.1.1.6.2 tls snprintf(c_reply->msg, sizeof(c_reply->msg),
350 1.1.1.1.6.2 tls "equality index of attribute \"%s\" disallowed", attrs[i] );
351 1.1.1.1.6.2 tls fprintf( stderr, "%s: line %d: %s\n",
352 1.1.1.1.6.2 tls fname, lineno, c_reply->msg );
353 1.1.1.1.6.2 tls }
354 1.1.1.1.6.2 tls rc = LDAP_INAPPROPRIATE_MATCHING;
355 1.1.1.1.6.2 tls goto done;
356 1.1.1.1.6.2 tls }
357 1.1.1.1.6.2 tls
358 1.1.1.1.6.2 tls if( IS_SLAP_INDEX( mask, SLAP_INDEX_SUBSTR ) && !(
359 1.1.1.1.6.2 tls ad->ad_type->sat_substr
360 1.1.1.1.6.2 tls && ad->ad_type->sat_substr->smr_indexer
361 1.1.1.1.6.2 tls && ad->ad_type->sat_substr->smr_filter ) )
362 1.1.1.1.6.2 tls {
363 1.1.1.1.6.2 tls if (c_reply) {
364 1.1.1.1.6.2 tls snprintf(c_reply->msg, sizeof(c_reply->msg),
365 1.1.1.1.6.2 tls "substr index of attribute \"%s\" disallowed", attrs[i] );
366 1.1.1.1.6.2 tls fprintf( stderr, "%s: line %d: %s\n",
367 1.1.1.1.6.2 tls fname, lineno, c_reply->msg );
368 1.1.1.1.6.2 tls }
369 1.1.1.1.6.2 tls rc = LDAP_INAPPROPRIATE_MATCHING;
370 1.1.1.1.6.2 tls goto done;
371 1.1.1.1.6.2 tls }
372 1.1.1.1.6.2 tls
373 1.1.1.1.6.2 tls Debug( LDAP_DEBUG_CONFIG, "index %s 0x%04lx\n",
374 1.1.1.1.6.2 tls ad->ad_cname.bv_val, mask, 0 );
375 1.1.1.1.6.2 tls
376 1.1.1.1.6.2 tls a = (AttrInfo *) ch_malloc( sizeof(AttrInfo) );
377 1.1.1.1.6.2 tls
378 1.1.1.1.6.2 tls #ifdef LDAP_COMP_MATCH
379 1.1.1.1.6.2 tls a->ai_cr = NULL;
380 1.1.1.1.6.2 tls #endif
381 1.1.1.1.6.2 tls a->ai_cursor = NULL;
382 1.1.1.1.6.2 tls a->ai_flist = NULL;
383 1.1.1.1.6.2 tls a->ai_clist = NULL;
384 1.1.1.1.6.2 tls a->ai_root = NULL;
385 1.1.1.1.6.2 tls a->ai_desc = ad;
386 1.1.1.1.6.2 tls a->ai_dbi = 0;
387 1.1.1.1.6.2 tls
388 1.1.1.1.6.2 tls if ( mdb->mi_flags & MDB_IS_OPEN ) {
389 1.1.1.1.6.2 tls a->ai_indexmask = 0;
390 1.1.1.1.6.2 tls a->ai_newmask = mask;
391 1.1.1.1.6.2 tls } else {
392 1.1.1.1.6.2 tls a->ai_indexmask = mask;
393 1.1.1.1.6.2 tls a->ai_newmask = 0;
394 1.1.1.1.6.2 tls }
395 1.1.1.1.6.2 tls
396 1.1.1.1.6.2 tls #ifdef LDAP_COMP_MATCH
397 1.1.1.1.6.2 tls if ( cr ) {
398 1.1.1.1.6.2 tls a_cr = mdb_attr_mask( mdb, ad );
399 1.1.1.1.6.2 tls if ( a_cr ) {
400 1.1.1.1.6.2 tls /*
401 1.1.1.1.6.2 tls * AttrInfo is already in AVL
402 1.1.1.1.6.2 tls * just add the extracted component reference
403 1.1.1.1.6.2 tls * in the AttrInfo
404 1.1.1.1.6.2 tls */
405 1.1.1.1.6.2 tls rc = insert_component_reference( cr, &a_cr->ai_cr );
406 1.1.1.1.6.2 tls if ( rc != LDAP_SUCCESS) {
407 1.1.1.1.6.2 tls fprintf( stderr, " error during inserting component reference in %s ", attrs[i]);
408 1.1.1.1.6.2 tls rc = LDAP_PARAM_ERROR;
409 1.1.1.1.6.2 tls goto done;
410 1.1.1.1.6.2 tls }
411 1.1.1.1.6.2 tls continue;
412 1.1.1.1.6.2 tls } else {
413 1.1.1.1.6.2 tls rc = insert_component_reference( cr, &a->ai_cr );
414 1.1.1.1.6.2 tls if ( rc != LDAP_SUCCESS) {
415 1.1.1.1.6.2 tls fprintf( stderr, " error during inserting component reference in %s ", attrs[i]);
416 1.1.1.1.6.2 tls rc = LDAP_PARAM_ERROR;
417 1.1.1.1.6.2 tls goto done;
418 1.1.1.1.6.2 tls }
419 1.1.1.1.6.2 tls }
420 1.1.1.1.6.2 tls }
421 1.1.1.1.6.2 tls #endif
422 1.1.1.1.6.2 tls rc = ainfo_insert( mdb, a );
423 1.1.1.1.6.2 tls if( rc ) {
424 1.1.1.1.6.2 tls if ( mdb->mi_flags & MDB_IS_OPEN ) {
425 1.1.1.1.6.2 tls AttrInfo *b = mdb_attr_mask( mdb, ad );
426 1.1.1.1.6.2 tls /* If there is already an index defined for this attribute
427 1.1.1.1.6.2 tls * it must be replaced. Otherwise we end up with multiple
428 1.1.1.1.6.2 tls * olcIndex values for the same attribute */
429 1.1.1.1.6.2 tls if ( b->ai_indexmask & MDB_INDEX_DELETING ) {
430 1.1.1.1.6.2 tls /* If we were editing this attr, reset it */
431 1.1.1.1.6.2 tls b->ai_indexmask &= ~MDB_INDEX_DELETING;
432 1.1.1.1.6.2 tls /* If this is leftover from a previous add, commit it */
433 1.1.1.1.6.2 tls if ( b->ai_newmask )
434 1.1.1.1.6.2 tls b->ai_indexmask = b->ai_newmask;
435 1.1.1.1.6.2 tls b->ai_newmask = a->ai_newmask;
436 1.1.1.1.6.2 tls ch_free( a );
437 1.1.1.1.6.2 tls rc = 0;
438 1.1.1.1.6.2 tls continue;
439 1.1.1.1.6.2 tls }
440 1.1.1.1.6.2 tls }
441 1.1.1.1.6.2 tls if (c_reply) {
442 1.1.1.1.6.2 tls snprintf(c_reply->msg, sizeof(c_reply->msg),
443 1.1.1.1.6.2 tls "duplicate index definition for attr \"%s\"",
444 1.1.1.1.6.2 tls attrs[i] );
445 1.1.1.1.6.2 tls fprintf( stderr, "%s: line %d: %s\n",
446 1.1.1.1.6.2 tls fname, lineno, c_reply->msg );
447 1.1.1.1.6.2 tls }
448 1.1.1.1.6.2 tls
449 1.1.1.1.6.2 tls rc = LDAP_PARAM_ERROR;
450 1.1.1.1.6.2 tls goto done;
451 1.1.1.1.6.2 tls }
452 1.1.1.1.6.2 tls }
453 1.1.1.1.6.2 tls
454 1.1.1.1.6.2 tls done:
455 1.1.1.1.6.2 tls ldap_charray_free( attrs );
456 1.1.1.1.6.2 tls if ( indexes != NULL ) ldap_charray_free( indexes );
457 1.1.1.1.6.2 tls
458 1.1.1.1.6.2 tls return rc;
459 1.1.1.1.6.2 tls }
460 1.1.1.1.6.2 tls
461 1.1.1.1.6.2 tls static int
462 1.1.1.1.6.2 tls mdb_attr_index_unparser( void *v1, void *v2 )
463 1.1.1.1.6.2 tls {
464 1.1.1.1.6.2 tls AttrInfo *ai = v1;
465 1.1.1.1.6.2 tls BerVarray *bva = v2;
466 1.1.1.1.6.2 tls struct berval bv;
467 1.1.1.1.6.2 tls char *ptr;
468 1.1.1.1.6.2 tls
469 1.1.1.1.6.2 tls slap_index2bvlen( ai->ai_indexmask, &bv );
470 1.1.1.1.6.2 tls if ( bv.bv_len ) {
471 1.1.1.1.6.2 tls bv.bv_len += ai->ai_desc->ad_cname.bv_len + 1;
472 1.1.1.1.6.2 tls ptr = ch_malloc( bv.bv_len+1 );
473 1.1.1.1.6.2 tls bv.bv_val = lutil_strcopy( ptr, ai->ai_desc->ad_cname.bv_val );
474 1.1.1.1.6.2 tls *bv.bv_val++ = ' ';
475 1.1.1.1.6.2 tls slap_index2bv( ai->ai_indexmask, &bv );
476 1.1.1.1.6.2 tls bv.bv_val = ptr;
477 1.1.1.1.6.2 tls ber_bvarray_add( bva, &bv );
478 1.1.1.1.6.2 tls }
479 1.1.1.1.6.2 tls return 0;
480 1.1.1.1.6.2 tls }
481 1.1.1.1.6.2 tls
482 1.1.1.1.6.2 tls static AttributeDescription addef = { NULL, NULL, BER_BVC("default") };
483 1.1.1.1.6.2 tls static AttrInfo aidef = { &addef };
484 1.1.1.1.6.2 tls
485 1.1.1.1.6.2 tls void
486 1.1.1.1.6.2 tls mdb_attr_index_unparse( struct mdb_info *mdb, BerVarray *bva )
487 1.1.1.1.6.2 tls {
488 1.1.1.1.6.2 tls int i;
489 1.1.1.1.6.2 tls
490 1.1.1.1.6.2 tls if ( mdb->mi_defaultmask ) {
491 1.1.1.1.6.2 tls aidef.ai_indexmask = mdb->mi_defaultmask;
492 1.1.1.1.6.2 tls mdb_attr_index_unparser( &aidef, bva );
493 1.1.1.1.6.2 tls }
494 1.1.1.1.6.2 tls for ( i=0; i<mdb->mi_nattrs; i++ )
495 1.1.1.1.6.2 tls mdb_attr_index_unparser( mdb->mi_attrs[i], bva );
496 1.1.1.1.6.2 tls }
497 1.1.1.1.6.2 tls
498 1.1.1.1.6.2 tls void
499 1.1.1.1.6.2 tls mdb_attr_info_free( AttrInfo *ai )
500 1.1.1.1.6.2 tls {
501 1.1.1.1.6.2 tls #ifdef LDAP_COMP_MATCH
502 1.1.1.1.6.2 tls free( ai->ai_cr );
503 1.1.1.1.6.2 tls #endif
504 1.1.1.1.6.2 tls free( ai );
505 1.1.1.1.6.2 tls }
506 1.1.1.1.6.2 tls
507 1.1.1.1.6.2 tls void
508 1.1.1.1.6.2 tls mdb_attr_index_destroy( struct mdb_info *mdb )
509 1.1.1.1.6.2 tls {
510 1.1.1.1.6.2 tls int i;
511 1.1.1.1.6.2 tls
512 1.1.1.1.6.2 tls for ( i=0; i<mdb->mi_nattrs; i++ )
513 1.1.1.1.6.2 tls mdb_attr_info_free( mdb->mi_attrs[i] );
514 1.1.1.1.6.2 tls
515 1.1.1.1.6.2 tls free( mdb->mi_attrs );
516 1.1.1.1.6.2 tls }
517 1.1.1.1.6.2 tls
518 1.1.1.1.6.2 tls void mdb_attr_index_free( struct mdb_info *mdb, AttributeDescription *ad )
519 1.1.1.1.6.2 tls {
520 1.1.1.1.6.2 tls int i;
521 1.1.1.1.6.2 tls
522 1.1.1.1.6.2 tls i = mdb_attr_slot( mdb, ad, NULL );
523 1.1.1.1.6.2 tls if ( i >= 0 ) {
524 1.1.1.1.6.2 tls mdb_attr_info_free( mdb->mi_attrs[i] );
525 1.1.1.1.6.2 tls mdb->mi_nattrs--;
526 1.1.1.1.6.2 tls for (; i<mdb->mi_nattrs; i++)
527 1.1.1.1.6.2 tls mdb->mi_attrs[i] = mdb->mi_attrs[i+1];
528 1.1.1.1.6.2 tls }
529 1.1.1.1.6.2 tls }
530 1.1.1.1.6.2 tls
531 1.1.1.1.6.2 tls void mdb_attr_flush( struct mdb_info *mdb )
532 1.1.1.1.6.2 tls {
533 1.1.1.1.6.2 tls int i;
534 1.1.1.1.6.2 tls
535 1.1.1.1.6.2 tls for ( i=0; i<mdb->mi_nattrs; i++ ) {
536 1.1.1.1.6.2 tls if ( mdb->mi_attrs[i]->ai_indexmask & MDB_INDEX_DELETING ) {
537 1.1.1.1.6.2 tls int j;
538 1.1.1.1.6.2 tls mdb_attr_info_free( mdb->mi_attrs[i] );
539 1.1.1.1.6.2 tls mdb->mi_nattrs--;
540 1.1.1.1.6.2 tls for (j=i; j<mdb->mi_nattrs; j++)
541 1.1.1.1.6.2 tls mdb->mi_attrs[j] = mdb->mi_attrs[j+1];
542 1.1.1.1.6.2 tls i--;
543 1.1.1.1.6.2 tls }
544 1.1.1.1.6.2 tls }
545 1.1.1.1.6.2 tls }
546 1.1.1.1.6.2 tls
547 1.1.1.1.6.2 tls int mdb_ad_read( struct mdb_info *mdb, MDB_txn *txn )
548 1.1.1.1.6.2 tls {
549 1.1.1.1.6.2 tls int i, rc;
550 1.1.1.1.6.2 tls MDB_cursor *mc;
551 1.1.1.1.6.2 tls MDB_val key, data;
552 1.1.1.1.6.2 tls struct berval bdata;
553 1.1.1.1.6.2 tls const char *text;
554 1.1.1.1.6.2 tls AttributeDescription *ad;
555 1.1.1.1.6.2 tls
556 1.1.1.1.6.2 tls rc = mdb_cursor_open( txn, mdb->mi_ad2id, &mc );
557 1.1.1.1.6.2 tls if ( rc ) {
558 1.1.1.1.6.2 tls Debug( LDAP_DEBUG_ANY,
559 1.1.1.1.6.2 tls "mdb_ad_read: cursor_open failed %s(%d)\n",
560 1.1.1.1.6.2 tls mdb_strerror(rc), rc, 0);
561 1.1.1.1.6.2 tls return rc;
562 1.1.1.1.6.2 tls }
563 1.1.1.1.6.2 tls
564 1.1.1.1.6.2 tls /* our array is 1-based, an index of 0 means no data */
565 1.1.1.1.6.2 tls i = mdb->mi_numads+1;
566 1.1.1.1.6.2 tls key.mv_size = sizeof(int);
567 1.1.1.1.6.2 tls key.mv_data = &i;
568 1.1.1.1.6.2 tls
569 1.1.1.1.6.2 tls rc = mdb_cursor_get( mc, &key, &data, MDB_SET );
570 1.1.1.1.6.2 tls
571 1.1.1.1.6.2 tls while ( rc == MDB_SUCCESS ) {
572 1.1.1.1.6.2 tls bdata.bv_len = data.mv_size;
573 1.1.1.1.6.2 tls bdata.bv_val = data.mv_data;
574 1.1.1.1.6.2 tls ad = NULL;
575 1.1.1.1.6.2 tls rc = slap_bv2ad( &bdata, &ad, &text );
576 1.1.1.1.6.2 tls if ( rc ) {
577 1.1.1.1.6.2 tls rc = slap_bv2undef_ad( &bdata, &mdb->mi_ads[i], &text, 0 );
578 1.1.1.1.6.2 tls } else {
579 1.1.1.1.6.2 tls if ( ad->ad_index >= MDB_MAXADS ) {
580 1.1.1.1.6.2 tls Debug( LDAP_DEBUG_ANY,
581 1.1.1.1.6.2 tls "mdb_adb_read: too many AttributeDescriptions in use\n",
582 1.1.1.1.6.2 tls 0, 0, 0 );
583 1.1.1.1.6.2 tls return LDAP_OTHER;
584 1.1.1.1.6.2 tls }
585 1.1.1.1.6.2 tls mdb->mi_adxs[ad->ad_index] = i;
586 1.1.1.1.6.2 tls mdb->mi_ads[i] = ad;
587 1.1.1.1.6.2 tls }
588 1.1.1.1.6.2 tls i++;
589 1.1.1.1.6.2 tls rc = mdb_cursor_get( mc, &key, &data, MDB_NEXT );
590 1.1.1.1.6.2 tls }
591 1.1.1.1.6.2 tls mdb->mi_numads = i-1;
592 1.1.1.1.6.2 tls
593 1.1.1.1.6.2 tls done:
594 1.1.1.1.6.2 tls if ( rc == MDB_NOTFOUND )
595 1.1.1.1.6.2 tls rc = 0;
596 1.1.1.1.6.2 tls
597 1.1.1.1.6.2 tls mdb_cursor_close( mc );
598 1.1.1.1.6.2 tls
599 1.1.1.1.6.2 tls return rc;
600 1.1.1.1.6.2 tls }
601 1.1.1.1.6.2 tls
602 1.1.1.1.6.2 tls int mdb_ad_get( struct mdb_info *mdb, MDB_txn *txn, AttributeDescription *ad )
603 1.1.1.1.6.2 tls {
604 1.1.1.1.6.2 tls int i, rc;
605 1.1.1.1.6.2 tls MDB_val key, val;
606 1.1.1.1.6.2 tls
607 1.1.1.1.6.2 tls rc = mdb_ad_read( mdb, txn );
608 1.1.1.1.6.2 tls if (rc)
609 1.1.1.1.6.2 tls return rc;
610 1.1.1.1.6.2 tls
611 1.1.1.1.6.2 tls if ( mdb->mi_adxs[ad->ad_index] )
612 1.1.1.1.6.2 tls return 0;
613 1.1.1.1.6.2 tls
614 1.1.1.1.6.2 tls i = mdb->mi_numads+1;
615 1.1.1.1.6.2 tls key.mv_size = sizeof(int);
616 1.1.1.1.6.2 tls key.mv_data = &i;
617 1.1.1.1.6.2 tls val.mv_size = ad->ad_cname.bv_len;
618 1.1.1.1.6.2 tls val.mv_data = ad->ad_cname.bv_val;
619 1.1.1.1.6.2 tls
620 1.1.1.1.6.2 tls rc = mdb_put( txn, mdb->mi_ad2id, &key, &val, 0 );
621 1.1.1.1.6.2 tls if ( rc == MDB_SUCCESS ) {
622 1.1.1.1.6.2 tls mdb->mi_adxs[ad->ad_index] = i;
623 1.1.1.1.6.2 tls mdb->mi_ads[i] = ad;
624 1.1.1.1.6.2 tls mdb->mi_numads++;
625 1.1.1.1.6.2 tls } else {
626 1.1.1.1.6.2 tls Debug( LDAP_DEBUG_ANY,
627 1.1.1.1.6.2 tls "mdb_ad_get: mdb_put failed %s(%d)\n",
628 1.1.1.1.6.2 tls mdb_strerror(rc), rc, 0);
629 1.1.1.1.6.2 tls }
630 1.1.1.1.6.2 tls
631 1.1.1.1.6.2 tls return rc;
632 1.1.1.1.6.2 tls }
633