Back to index

openldap  2.4.31
attr.c
Go to the documentation of this file.
00001 /* attr.c - backend routines for dealing with attributes */
00002 /* $OpenLDAP$ */
00003 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
00004  *
00005  * Copyright 2000-2012 The OpenLDAP Foundation.
00006  * All rights reserved.
00007  *
00008  * Redistribution and use in source and binary forms, with or without
00009  * modification, are permitted only as authorized by the OpenLDAP
00010  * Public License.
00011  *
00012  * A copy of this license is available in the file LICENSE in the
00013  * top-level directory of the distribution or, alternatively, at
00014  * <http://www.OpenLDAP.org/license.html>.
00015  */
00016 
00017 #include "portable.h"
00018 
00019 #include <stdio.h>
00020 
00021 #include <ac/socket.h>
00022 #include <ac/string.h>
00023 
00024 #include "slap.h"
00025 #include "back-bdb.h"
00026 #include "config.h"
00027 #include "lutil.h"
00028 
00029 /* Find the ad, return -1 if not found,
00030  * set point for insertion if ins is non-NULL
00031  */
00032 int
00033 bdb_attr_slot( struct bdb_info *bdb, AttributeDescription *ad, int *ins )
00034 {
00035        unsigned base = 0, cursor = 0;
00036        unsigned n = bdb->bi_nattrs;
00037        int val = 0;
00038        
00039        while ( 0 < n ) {
00040               unsigned pivot = n >> 1;
00041               cursor = base + pivot;
00042 
00043               val = SLAP_PTRCMP( ad, bdb->bi_attrs[cursor]->ai_desc );
00044               if ( val < 0 ) {
00045                      n = pivot;
00046               } else if ( val > 0 ) {
00047                      base = cursor + 1;
00048                      n -= pivot + 1;
00049               } else {
00050                      return cursor;
00051               }
00052        }
00053        if ( ins ) {
00054               if ( val > 0 )
00055                      ++cursor;
00056               *ins = cursor;
00057        }
00058        return -1;
00059 }
00060 
00061 static int
00062 ainfo_insert( struct bdb_info *bdb, AttrInfo *a )
00063 {
00064        int x;
00065        int i = bdb_attr_slot( bdb, a->ai_desc, &x );
00066 
00067        /* Is it a dup? */
00068        if ( i >= 0 )
00069               return -1;
00070 
00071        bdb->bi_attrs = ch_realloc( bdb->bi_attrs, ( bdb->bi_nattrs+1 ) * 
00072               sizeof( AttrInfo * ));
00073        if ( x < bdb->bi_nattrs )
00074               AC_MEMCPY( &bdb->bi_attrs[x+1], &bdb->bi_attrs[x],
00075                      ( bdb->bi_nattrs - x ) * sizeof( AttrInfo *));
00076        bdb->bi_attrs[x] = a;
00077        bdb->bi_nattrs++;
00078        return 0;
00079 }
00080 
00081 AttrInfo *
00082 bdb_attr_mask(
00083        struct bdb_info      *bdb,
00084        AttributeDescription *desc )
00085 {
00086        int i = bdb_attr_slot( bdb, desc, NULL );
00087        return i < 0 ? NULL : bdb->bi_attrs[i];
00088 }
00089 
00090 int
00091 bdb_attr_index_config(
00092        struct bdb_info      *bdb,
00093        const char           *fname,
00094        int                  lineno,
00095        int                  argc,
00096        char          **argv,
00097        struct        config_reply_s *c_reply)
00098 {
00099        int rc = 0;
00100        int    i;
00101        slap_mask_t mask;
00102        char **attrs;
00103        char **indexes = NULL;
00104 
00105        attrs = ldap_str2charray( argv[0], "," );
00106 
00107        if( attrs == NULL ) {
00108               fprintf( stderr, "%s: line %d: "
00109                      "no attributes specified: %s\n",
00110                      fname, lineno, argv[0] );
00111               return LDAP_PARAM_ERROR;
00112        }
00113 
00114        if ( argc > 1 ) {
00115               indexes = ldap_str2charray( argv[1], "," );
00116 
00117               if( indexes == NULL ) {
00118                      fprintf( stderr, "%s: line %d: "
00119                             "no indexes specified: %s\n",
00120                             fname, lineno, argv[1] );
00121                      rc = LDAP_PARAM_ERROR;
00122                      goto done;
00123               }
00124        }
00125 
00126        if( indexes == NULL ) {
00127               mask = bdb->bi_defaultmask;
00128 
00129        } else {
00130               mask = 0;
00131 
00132               for ( i = 0; indexes[i] != NULL; i++ ) {
00133                      slap_mask_t index;
00134                      rc = slap_str2index( indexes[i], &index );
00135 
00136                      if( rc != LDAP_SUCCESS ) {
00137                             if ( c_reply )
00138                             {
00139                                    snprintf(c_reply->msg, sizeof(c_reply->msg),
00140                                           "index type \"%s\" undefined", indexes[i] );
00141 
00142                                    fprintf( stderr, "%s: line %d: %s\n",
00143                                           fname, lineno, c_reply->msg );
00144                             }
00145                             rc = LDAP_PARAM_ERROR;
00146                             goto done;
00147                      }
00148 
00149                      mask |= index;
00150               }
00151        }
00152 
00153        if( !mask ) {
00154               if ( c_reply )
00155               {
00156                      snprintf(c_reply->msg, sizeof(c_reply->msg),
00157                             "no indexes selected" );
00158                      fprintf( stderr, "%s: line %d: %s\n",
00159                             fname, lineno, c_reply->msg );
00160               }
00161               rc = LDAP_PARAM_ERROR;
00162               goto done;
00163        }
00164 
00165        for ( i = 0; attrs[i] != NULL; i++ ) {
00166               AttrInfo      *a;
00167               AttributeDescription *ad;
00168               const char *text;
00169 #ifdef LDAP_COMP_MATCH
00170               ComponentReference* cr = NULL;
00171               AttrInfo *a_cr = NULL;
00172 #endif
00173 
00174               if( strcasecmp( attrs[i], "default" ) == 0 ) {
00175                      bdb->bi_defaultmask |= mask;
00176                      continue;
00177               }
00178 
00179 #ifdef LDAP_COMP_MATCH
00180               if ( is_component_reference( attrs[i] ) ) {
00181                      rc = extract_component_reference( attrs[i], &cr );
00182                      if ( rc != LDAP_SUCCESS ) {
00183                             if ( c_reply )
00184                             {
00185                                    snprintf(c_reply->msg, sizeof(c_reply->msg),
00186                                           "index component reference\"%s\" undefined",
00187                                           attrs[i] );
00188                                    fprintf( stderr, "%s: line %d: %s\n",
00189                                           fname, lineno, c_reply->msg );
00190                             }
00191                             goto done;
00192                      }
00193                      cr->cr_indexmask = mask;
00194                      /*
00195                       * After extracting a component reference
00196                       * only the name of a attribute will be remaining
00197                       */
00198               } else {
00199                      cr = NULL;
00200               }
00201 #endif
00202               ad = NULL;
00203               rc = slap_str2ad( attrs[i], &ad, &text );
00204 
00205               if( rc != LDAP_SUCCESS ) {
00206                      if ( c_reply )
00207                      {
00208                             snprintf(c_reply->msg, sizeof(c_reply->msg),
00209                                    "index attribute \"%s\" undefined",
00210                                    attrs[i] );
00211 
00212                             fprintf( stderr, "%s: line %d: %s\n",
00213                                    fname, lineno, c_reply->msg );
00214                      }
00215                      goto done;
00216               }
00217 
00218               if( ad == slap_schema.si_ad_entryDN || slap_ad_is_binary( ad ) ) {
00219                      if (c_reply) {
00220                             snprintf(c_reply->msg, sizeof(c_reply->msg),
00221                                    "index of attribute \"%s\" disallowed", attrs[i] );
00222                             fprintf( stderr, "%s: line %d: %s\n",
00223                                    fname, lineno, c_reply->msg );
00224                      }
00225                      rc = LDAP_UNWILLING_TO_PERFORM;
00226                      goto done;
00227               }
00228 
00229               if( IS_SLAP_INDEX( mask, SLAP_INDEX_APPROX ) && !(
00230                      ad->ad_type->sat_approx
00231                             && ad->ad_type->sat_approx->smr_indexer
00232                             && ad->ad_type->sat_approx->smr_filter ) )
00233               {
00234                      if (c_reply) {
00235                             snprintf(c_reply->msg, sizeof(c_reply->msg),
00236                                    "approx index of attribute \"%s\" disallowed", attrs[i] );
00237                             fprintf( stderr, "%s: line %d: %s\n",
00238                                    fname, lineno, c_reply->msg );
00239                      }
00240                      rc = LDAP_INAPPROPRIATE_MATCHING;
00241                      goto done;
00242               }
00243 
00244               if( IS_SLAP_INDEX( mask, SLAP_INDEX_EQUALITY ) && !(
00245                      ad->ad_type->sat_equality
00246                             && ad->ad_type->sat_equality->smr_indexer
00247                             && ad->ad_type->sat_equality->smr_filter ) )
00248               {
00249                      if (c_reply) {
00250                             snprintf(c_reply->msg, sizeof(c_reply->msg),
00251                                    "equality index of attribute \"%s\" disallowed", attrs[i] );
00252                             fprintf( stderr, "%s: line %d: %s\n",
00253                                    fname, lineno, c_reply->msg );
00254                      }
00255                      rc = LDAP_INAPPROPRIATE_MATCHING;
00256                      goto done;
00257               }
00258 
00259               if( IS_SLAP_INDEX( mask, SLAP_INDEX_SUBSTR ) && !(
00260                      ad->ad_type->sat_substr
00261                             && ad->ad_type->sat_substr->smr_indexer
00262                             && ad->ad_type->sat_substr->smr_filter ) )
00263               {
00264                      if (c_reply) {
00265                             snprintf(c_reply->msg, sizeof(c_reply->msg),
00266                                    "substr index of attribute \"%s\" disallowed", attrs[i] );
00267                             fprintf( stderr, "%s: line %d: %s\n",
00268                                    fname, lineno, c_reply->msg );
00269                      }
00270                      rc = LDAP_INAPPROPRIATE_MATCHING;
00271                      goto done;
00272               }
00273 
00274               Debug( LDAP_DEBUG_CONFIG, "index %s 0x%04lx\n",
00275                      ad->ad_cname.bv_val, mask, 0 ); 
00276 
00277               a = (AttrInfo *) ch_malloc( sizeof(AttrInfo) );
00278 
00279 #ifdef LDAP_COMP_MATCH
00280               a->ai_cr = NULL;
00281 #endif
00282               a->ai_desc = ad;
00283 
00284               if ( bdb->bi_flags & BDB_IS_OPEN ) {
00285                      a->ai_indexmask = 0;
00286                      a->ai_newmask = mask;
00287               } else {
00288                      a->ai_indexmask = mask;
00289                      a->ai_newmask = 0;
00290               }
00291 
00292 #ifdef LDAP_COMP_MATCH
00293               if ( cr ) {
00294                      a_cr = bdb_attr_mask( bdb, ad );
00295                      if ( a_cr ) {
00296                             /*
00297                              * AttrInfo is already in AVL
00298                              * just add the extracted component reference
00299                              * in the AttrInfo
00300                              */
00301                             rc = insert_component_reference( cr, &a_cr->ai_cr );
00302                             if ( rc != LDAP_SUCCESS) {
00303                                    fprintf( stderr, " error during inserting component reference in %s ", attrs[i]);
00304                                    rc = LDAP_PARAM_ERROR;
00305                                    goto done;
00306                             }
00307                             continue;
00308                      } else {
00309                             rc = insert_component_reference( cr, &a->ai_cr );
00310                             if ( rc != LDAP_SUCCESS) {
00311                                    fprintf( stderr, " error during inserting component reference in %s ", attrs[i]);
00312                                    rc = LDAP_PARAM_ERROR;
00313                                    goto done;
00314                             }
00315                      }
00316               }
00317 #endif
00318               rc = ainfo_insert( bdb, a );
00319               if( rc ) {
00320                      if ( bdb->bi_flags & BDB_IS_OPEN ) {
00321                             AttrInfo *b = bdb_attr_mask( bdb, ad );
00322                             /* If there is already an index defined for this attribute
00323                              * it must be replaced. Otherwise we end up with multiple 
00324                              * olcIndex values for the same attribute */
00325                             if ( b->ai_indexmask & BDB_INDEX_DELETING ) {
00326                                    /* If we were editing this attr, reset it */
00327                                    b->ai_indexmask &= ~BDB_INDEX_DELETING;
00328                                    /* If this is leftover from a previous add, commit it */
00329                                    if ( b->ai_newmask )
00330                                           b->ai_indexmask = b->ai_newmask;
00331                                    b->ai_newmask = a->ai_newmask;
00332                                    ch_free( a );
00333                                    rc = 0;
00334                                    continue;
00335                             }
00336                      }
00337                      if (c_reply) {
00338                             snprintf(c_reply->msg, sizeof(c_reply->msg),
00339                                    "duplicate index definition for attr \"%s\"",
00340                                    attrs[i] );
00341                             fprintf( stderr, "%s: line %d: %s\n",
00342                                    fname, lineno, c_reply->msg );
00343                      }
00344 
00345                      rc = LDAP_PARAM_ERROR;
00346                      goto done;
00347               }
00348        }
00349 
00350 done:
00351        ldap_charray_free( attrs );
00352        if ( indexes != NULL ) ldap_charray_free( indexes );
00353 
00354        return rc;
00355 }
00356 
00357 static int
00358 bdb_attr_index_unparser( void *v1, void *v2 )
00359 {
00360        AttrInfo *ai = v1;
00361        BerVarray *bva = v2;
00362        struct berval bv;
00363        char *ptr;
00364 
00365        slap_index2bvlen( ai->ai_indexmask, &bv );
00366        if ( bv.bv_len ) {
00367               bv.bv_len += ai->ai_desc->ad_cname.bv_len + 1;
00368               ptr = ch_malloc( bv.bv_len+1 );
00369               bv.bv_val = lutil_strcopy( ptr, ai->ai_desc->ad_cname.bv_val );
00370               *bv.bv_val++ = ' ';
00371               slap_index2bv( ai->ai_indexmask, &bv );
00372               bv.bv_val = ptr;
00373               ber_bvarray_add( bva, &bv );
00374        }
00375        return 0;
00376 }
00377 
00378 static AttributeDescription addef = { NULL, NULL, BER_BVC("default") };
00379 static AttrInfo aidef = { &addef };
00380 
00381 void
00382 bdb_attr_index_unparse( struct bdb_info *bdb, BerVarray *bva )
00383 {
00384        int i;
00385 
00386        if ( bdb->bi_defaultmask ) {
00387               aidef.ai_indexmask = bdb->bi_defaultmask;
00388               bdb_attr_index_unparser( &aidef, bva );
00389        }
00390        for ( i=0; i<bdb->bi_nattrs; i++ )
00391               bdb_attr_index_unparser( bdb->bi_attrs[i], bva );
00392 }
00393 
00394 void
00395 bdb_attr_info_free( AttrInfo *ai )
00396 {
00397 #ifdef LDAP_COMP_MATCH
00398        free( ai->ai_cr );
00399 #endif
00400        free( ai );
00401 }
00402 
00403 void
00404 bdb_attr_index_destroy( struct bdb_info *bdb )
00405 {
00406        int i;
00407 
00408        for ( i=0; i<bdb->bi_nattrs; i++ ) 
00409               bdb_attr_info_free( bdb->bi_attrs[i] );
00410 
00411        free( bdb->bi_attrs );
00412 }
00413 
00414 void bdb_attr_index_free( struct bdb_info *bdb, AttributeDescription *ad )
00415 {
00416        int i;
00417 
00418        i = bdb_attr_slot( bdb, ad, NULL );
00419        if ( i >= 0 ) {
00420               bdb_attr_info_free( bdb->bi_attrs[i] );
00421               bdb->bi_nattrs--;
00422               for (; i<bdb->bi_nattrs; i++)
00423                      bdb->bi_attrs[i] = bdb->bi_attrs[i+1];
00424        }
00425 }
00426 
00427 void bdb_attr_flush( struct bdb_info *bdb )
00428 {
00429        int i;
00430 
00431        for ( i=0; i<bdb->bi_nattrs; i++ ) {
00432               if ( bdb->bi_attrs[i]->ai_indexmask & BDB_INDEX_DELETING ) {
00433                      int j;
00434                      bdb_attr_info_free( bdb->bi_attrs[i] );
00435                      bdb->bi_nattrs--;
00436                      for (j=i; j<bdb->bi_nattrs; j++)
00437                             bdb->bi_attrs[j] = bdb->bi_attrs[j+1];
00438                      i--;
00439               }
00440        }
00441 }