mirror of
https://git.openldap.org/openldap/openldap.git
synced 2025-12-20 22:59:34 -05:00
Move LDBM to the attic
This commit is contained in:
parent
c48338233e
commit
037d513aee
32 changed files with 0 additions and 10066 deletions
|
|
@ -1,54 +0,0 @@
|
|||
# Makefile.in for back-ldbm
|
||||
# $OpenLDAP$
|
||||
## This work is part of OpenLDAP Software <http://www.openldap.org/>.
|
||||
##
|
||||
## Copyright 1998-2006 The OpenLDAP Foundation.
|
||||
## 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>.
|
||||
|
||||
SRCS = idl.c add.c search.c cache.c dbcache.c dn2id.c entry.c \
|
||||
id2entry.c index.c id2children.c nextid.c \
|
||||
compare.c modify.c modrdn.c delete.c init.c \
|
||||
config.c bind.c attr.c filterindex.c close.c \
|
||||
alias.c tools.c key.c extended.c \
|
||||
referral.c operational.c ldbm.c
|
||||
OBJS = idl.lo add.lo search.lo cache.lo dbcache.lo dn2id.lo entry.lo \
|
||||
id2entry.lo index.lo id2children.lo nextid.lo \
|
||||
compare.lo modify.lo modrdn.lo delete.lo init.lo \
|
||||
config.lo bind.lo attr.lo filterindex.lo close.lo \
|
||||
alias.lo tools.lo key.lo extended.lo \
|
||||
referral.lo operational.lo ldbm.lo
|
||||
|
||||
LDAP_INCDIR= ../../../include
|
||||
LDAP_LIBDIR= ../../../libraries
|
||||
|
||||
BUILD_OPT = "--enable-ldbm"
|
||||
BUILD_MOD = @BUILD_LDBM@
|
||||
|
||||
mod_DEFS = -DSLAPD_IMPORT
|
||||
MOD_DEFS = $(@BUILD_LDBM@_DEFS)
|
||||
MOD_LIBS = $(LDBM_LIBS)
|
||||
|
||||
shared_LDAP_LIBS = $(LDAP_LIBLDAP_R_LA) $(LDAP_LIBLBER_LA)
|
||||
NT_LINK_LIBS = -L.. -lslapd $(@BUILD_LIBS_DYNAMIC@_LDAP_LIBS)
|
||||
UNIX_LINK_LIBS = $(@BUILD_LIBS_DYNAMIC@_LDAP_LIBS)
|
||||
|
||||
LIBBASE = back_ldbm
|
||||
|
||||
XINCPATH = -I.. -I$(srcdir)/..
|
||||
XDEFS = $(MODULES_CPPFLAGS)
|
||||
XXSRCS = $(@BUILD_LDBM@_SRCS)
|
||||
|
||||
all-local-lib: ../.backend
|
||||
|
||||
../.backend: lib$(LIBBASE).a
|
||||
@touch $@
|
||||
|
||||
depend-common: $(XXSRCS)
|
||||
|
|
@ -1,338 +0,0 @@
|
|||
/* add.c - ldap ldbm back-end add routine */
|
||||
/* $OpenLDAP$ */
|
||||
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
|
||||
*
|
||||
* Copyright 1998-2006 The OpenLDAP Foundation.
|
||||
* 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>.
|
||||
*/
|
||||
|
||||
#include "portable.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <ac/socket.h>
|
||||
#include <ac/string.h>
|
||||
|
||||
#include "slap.h"
|
||||
#include "back-ldbm.h"
|
||||
#include "proto-back-ldbm.h"
|
||||
|
||||
static int
|
||||
ldbm_csn_cb(
|
||||
Operation *op,
|
||||
SlapReply *rs )
|
||||
{
|
||||
op->o_callback = op->o_callback->sc_next;
|
||||
slap_graduate_commit_csn( op );
|
||||
return SLAP_CB_CONTINUE;
|
||||
}
|
||||
|
||||
int
|
||||
ldbm_back_add(
|
||||
Operation *op,
|
||||
SlapReply *rs )
|
||||
{
|
||||
struct ldbminfo *li = (struct ldbminfo *) op->o_bd->be_private;
|
||||
struct berval pdn;
|
||||
Entry *p = NULL;
|
||||
ID id = NOID;
|
||||
AttributeDescription *children = slap_schema.si_ad_children;
|
||||
AttributeDescription *entry = slap_schema.si_ad_entry;
|
||||
char textbuf[SLAP_TEXT_BUFLEN];
|
||||
size_t textlen = sizeof textbuf;
|
||||
slap_callback cb = { NULL };
|
||||
int subentry;
|
||||
|
||||
Debug(LDAP_DEBUG_ARGS, "==> ldbm_back_add: %s\n",
|
||||
op->o_req_dn.bv_val, 0, 0);
|
||||
|
||||
slap_add_opattrs( op, &rs->sr_text, textbuf, textlen, 1 );
|
||||
|
||||
cb.sc_cleanup = ldbm_csn_cb;
|
||||
cb.sc_next = op->o_callback;
|
||||
op->o_callback = &cb;
|
||||
|
||||
rs->sr_err = entry_schema_check( op, op->oq_add.rs_e, NULL,
|
||||
get_manageDIT(op), &rs->sr_text, textbuf, textlen );
|
||||
|
||||
if ( rs->sr_err != LDAP_SUCCESS ) {
|
||||
Debug( LDAP_DEBUG_TRACE, "entry failed schema check: %s\n",
|
||||
rs->sr_text, 0, 0 );
|
||||
|
||||
send_ldap_result( op, rs );
|
||||
return rs->sr_err;
|
||||
}
|
||||
rs->sr_text = NULL;
|
||||
|
||||
subentry = is_entry_subentry( op->oq_add.rs_e );
|
||||
|
||||
if ( !access_allowed( op, op->oq_add.rs_e,
|
||||
entry, NULL, ACL_WADD, NULL ) )
|
||||
{
|
||||
Debug( LDAP_DEBUG_TRACE, "no write access to entry\n", 0,
|
||||
0, 0 );
|
||||
|
||||
send_ldap_error( op, rs, LDAP_INSUFFICIENT_ACCESS,
|
||||
"no write access to entry" );
|
||||
|
||||
return LDAP_INSUFFICIENT_ACCESS;
|
||||
}
|
||||
|
||||
/* grab giant lock for writing */
|
||||
ldap_pvt_thread_rdwr_wlock(&li->li_giant_rwlock);
|
||||
|
||||
rs->sr_err = dn2id( op->o_bd, &op->o_req_ndn, &id );
|
||||
if ( rs->sr_err || id != NOID ) {
|
||||
/* if (rs->sr_err) something bad happened to ldbm cache */
|
||||
ldap_pvt_thread_rdwr_wunlock(&li->li_giant_rwlock);
|
||||
rs->sr_err = rs->sr_err ? LDAP_OTHER : LDAP_ALREADY_EXISTS;
|
||||
send_ldap_result( op, rs );
|
||||
return rs->sr_err;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the parent dn and see if the corresponding entry exists.
|
||||
* If the parent does not exist, only allow the "root" user to
|
||||
* add the entry.
|
||||
*/
|
||||
|
||||
if ( be_issuffix( op->o_bd, &op->o_req_ndn ) ) {
|
||||
pdn = slap_empty_bv;
|
||||
} else {
|
||||
dnParent( &op->o_req_ndn, &pdn );
|
||||
}
|
||||
|
||||
if( pdn.bv_len ) {
|
||||
Entry *matched = NULL;
|
||||
|
||||
/* get parent with writer lock */
|
||||
if ( (p = dn2entry_w( op->o_bd, &pdn, &matched )) == NULL ) {
|
||||
if ( matched != NULL ) {
|
||||
rs->sr_matched = ch_strdup( matched->e_dn );
|
||||
rs->sr_ref = is_entry_referral( matched )
|
||||
? get_entry_referrals( op, matched )
|
||||
: NULL;
|
||||
cache_return_entry_r( &li->li_cache, matched );
|
||||
|
||||
} else {
|
||||
rs->sr_ref = referral_rewrite( default_referral,
|
||||
NULL, &op->o_req_dn, LDAP_SCOPE_DEFAULT );
|
||||
}
|
||||
|
||||
ldap_pvt_thread_rdwr_wunlock(&li->li_giant_rwlock);
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "parent does not exist\n",
|
||||
0, 0, 0 );
|
||||
|
||||
rs->sr_text = rs->sr_ref
|
||||
? "parent is referral" : "parent does not exist";
|
||||
rs->sr_err = LDAP_REFERRAL;
|
||||
send_ldap_result( op, rs );
|
||||
|
||||
ber_bvarray_free( rs->sr_ref );
|
||||
free( (char *)rs->sr_matched );
|
||||
rs->sr_ref = NULL;
|
||||
rs->sr_matched = NULL;
|
||||
return rs->sr_err;
|
||||
}
|
||||
|
||||
if ( ! access_allowed( op, p, children, NULL, ACL_WADD, NULL ) ) {
|
||||
/* free parent and writer lock */
|
||||
cache_return_entry_w( &li->li_cache, p );
|
||||
ldap_pvt_thread_rdwr_wunlock(&li->li_giant_rwlock);
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "no write access to parent\n", 0,
|
||||
0, 0 );
|
||||
|
||||
send_ldap_error( op, rs, LDAP_INSUFFICIENT_ACCESS,
|
||||
"no write access to parent" );
|
||||
|
||||
return LDAP_INSUFFICIENT_ACCESS;
|
||||
}
|
||||
|
||||
if ( is_entry_subentry( p )) {
|
||||
Debug( LDAP_DEBUG_TRACE, "bdb_add: parent is subentry\n",
|
||||
0, 0, 0 );
|
||||
rs->sr_err = LDAP_OBJECT_CLASS_VIOLATION;
|
||||
rs->sr_text = "parent is a subentry";
|
||||
goto return_results;
|
||||
}
|
||||
|
||||
if ( is_entry_alias( p ) ) {
|
||||
/* parent is an alias, don't allow add */
|
||||
|
||||
/* free parent and writer lock */
|
||||
cache_return_entry_w( &li->li_cache, p );
|
||||
ldap_pvt_thread_rdwr_wunlock(&li->li_giant_rwlock);
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "parent is alias\n", 0,
|
||||
0, 0 );
|
||||
|
||||
send_ldap_error( op, rs, LDAP_ALIAS_PROBLEM,
|
||||
"parent is an alias" );
|
||||
|
||||
return LDAP_ALIAS_PROBLEM;
|
||||
}
|
||||
|
||||
if ( is_entry_referral( p ) ) {
|
||||
/* parent is a referral, don't allow add */
|
||||
rs->sr_matched = ch_strdup( p->e_dn );
|
||||
rs->sr_ref = is_entry_referral( p )
|
||||
? get_entry_referrals( op, p )
|
||||
: NULL;
|
||||
|
||||
/* free parent and writer lock */
|
||||
cache_return_entry_w( &li->li_cache, p );
|
||||
ldap_pvt_thread_rdwr_wunlock(&li->li_giant_rwlock);
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "parent is referral\n", 0,
|
||||
0, 0 );
|
||||
rs->sr_err = LDAP_REFERRAL;
|
||||
send_ldap_result( op, rs );
|
||||
|
||||
ber_bvarray_free( rs->sr_ref );
|
||||
free( (char *)rs->sr_matched );
|
||||
rs->sr_ref = NULL;
|
||||
rs->sr_matched = NULL;
|
||||
return rs->sr_err;
|
||||
}
|
||||
|
||||
if ( subentry ) {
|
||||
/* FIXME: */
|
||||
/* parent must be an administrative point of the required kind */
|
||||
}
|
||||
|
||||
} else {
|
||||
assert( pdn.bv_val == NULL || *pdn.bv_val == '\0' );
|
||||
|
||||
if (( !be_isroot(op) && !be_shadow_update(op) )
|
||||
&& !is_entry_glue( op->oq_add.rs_e ))
|
||||
{
|
||||
ldap_pvt_thread_rdwr_wunlock(&li->li_giant_rwlock);
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "%s add denied\n",
|
||||
pdn.bv_val == NULL ? "suffix" : "entry at root", 0, 0 );
|
||||
|
||||
send_ldap_error( op, rs, LDAP_NO_SUCH_OBJECT, NULL );
|
||||
return LDAP_NO_SUCH_OBJECT;
|
||||
}
|
||||
}
|
||||
|
||||
if ( next_id( op->o_bd, &op->oq_add.rs_e->e_id ) ) {
|
||||
if( p != NULL) {
|
||||
/* free parent and writer lock */
|
||||
cache_return_entry_w( &li->li_cache, p );
|
||||
}
|
||||
|
||||
ldap_pvt_thread_rdwr_wunlock(&li->li_giant_rwlock);
|
||||
|
||||
Debug( LDAP_DEBUG_ANY, "ldbm_add: next_id failed\n",
|
||||
0, 0, 0 );
|
||||
|
||||
send_ldap_error( op, rs, LDAP_OTHER,
|
||||
"next_id add failed" );
|
||||
|
||||
return LDAP_OTHER;
|
||||
}
|
||||
|
||||
/*
|
||||
* Try to add the entry to the cache, assign it a new dnid.
|
||||
*/
|
||||
rs->sr_err = cache_add_entry_rw( &li->li_cache, op->oq_add.rs_e,
|
||||
CACHE_WRITE_LOCK );
|
||||
|
||||
if ( rs->sr_err != 0 ) {
|
||||
if( p != NULL) {
|
||||
/* free parent and writer lock */
|
||||
cache_return_entry_w( &li->li_cache, p );
|
||||
}
|
||||
|
||||
ldap_pvt_thread_rdwr_wunlock(&li->li_giant_rwlock);
|
||||
|
||||
Debug( LDAP_DEBUG_ANY, "cache_add_entry_lock failed\n", 0, 0,
|
||||
0 );
|
||||
|
||||
rs->sr_text = rs->sr_err > 0 ? NULL : "cache add failed";
|
||||
rs->sr_err = rs->sr_err > 0 ? LDAP_ALREADY_EXISTS : LDAP_OTHER;
|
||||
send_ldap_result( op, rs );
|
||||
|
||||
return rs->sr_err;
|
||||
}
|
||||
|
||||
rs->sr_err = -1;
|
||||
|
||||
/* attribute indexes */
|
||||
if ( index_entry_add( op, op->oq_add.rs_e ) != LDAP_SUCCESS ) {
|
||||
Debug( LDAP_DEBUG_TRACE, "index_entry_add failed\n", 0,
|
||||
0, 0 );
|
||||
|
||||
send_ldap_error( op, rs, LDAP_OTHER,
|
||||
"index generation failed" );
|
||||
|
||||
goto return_results;
|
||||
}
|
||||
|
||||
/* dn2id index */
|
||||
if ( dn2id_add( op->o_bd, &op->oq_add.rs_e->e_nname,
|
||||
op->oq_add.rs_e->e_id ) != 0 )
|
||||
{
|
||||
Debug( LDAP_DEBUG_TRACE, "dn2id_add failed\n", 0,
|
||||
0, 0 );
|
||||
/* FIXME: delete attr indices? */
|
||||
|
||||
send_ldap_error( op, rs, LDAP_OTHER,
|
||||
"DN index generation failed" );
|
||||
|
||||
goto return_results;
|
||||
}
|
||||
|
||||
/* id2entry index */
|
||||
if ( id2entry_add( op->o_bd, op->oq_add.rs_e ) != 0 ) {
|
||||
Debug( LDAP_DEBUG_TRACE, "id2entry_add failed\n", 0,
|
||||
0, 0 );
|
||||
|
||||
/* FIXME: delete attr indices? */
|
||||
(void) dn2id_delete( op->o_bd, &op->oq_add.rs_e->e_nname,
|
||||
op->oq_add.rs_e->e_id );
|
||||
|
||||
send_ldap_error( op, rs, LDAP_OTHER,
|
||||
"entry store failed" );
|
||||
|
||||
goto return_results;
|
||||
}
|
||||
|
||||
rs->sr_err = LDAP_SUCCESS;
|
||||
rs->sr_text = NULL;
|
||||
send_ldap_result( op, rs );
|
||||
|
||||
/* marks the entry as committed, so it is added to the cache;
|
||||
* otherwise it is removed from the cache, but not destroyed;
|
||||
* it will be destroyed by the caller */
|
||||
cache_entry_commit( op->oq_add.rs_e );
|
||||
|
||||
return_results:;
|
||||
if (p != NULL) {
|
||||
/* free parent and writer lock */
|
||||
cache_return_entry_w( &li->li_cache, p );
|
||||
}
|
||||
|
||||
if ( rs->sr_err ) {
|
||||
/*
|
||||
* in case of error, writer lock is freed
|
||||
* and entry's private data is destroyed.
|
||||
* otherwise, this is done when entry is released
|
||||
*/
|
||||
cache_return_entry_w( &li->li_cache, op->oq_add.rs_e );
|
||||
ldap_pvt_thread_rdwr_wunlock(&li->li_giant_rwlock);
|
||||
}
|
||||
|
||||
return( rs->sr_err );
|
||||
}
|
||||
|
|
@ -1,240 +0,0 @@
|
|||
/* $OpenLDAP$ */
|
||||
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
|
||||
*
|
||||
* Copyright 1998-2006 The OpenLDAP Foundation.
|
||||
* 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>.
|
||||
*/
|
||||
|
||||
#include "portable.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <ac/string.h>
|
||||
#include <ac/socket.h>
|
||||
#include "slap.h"
|
||||
#include "back-ldbm.h"
|
||||
#include "proto-back-ldbm.h"
|
||||
|
||||
|
||||
static void new_superior(
|
||||
struct berval *dn,
|
||||
struct berval *oldSup,
|
||||
struct berval *newSup,
|
||||
struct berval *res );
|
||||
|
||||
static int dnlist_subordinate(
|
||||
BerVarray dnlist,
|
||||
struct berval *dn );
|
||||
|
||||
Entry *deref_internal_r(
|
||||
Backend* be,
|
||||
Entry* alias,
|
||||
struct berval* dn_in,
|
||||
int* err,
|
||||
Entry** matched,
|
||||
const char** text )
|
||||
{
|
||||
struct berval dn;
|
||||
struct ldbminfo *li = (struct ldbminfo *) be->be_private;
|
||||
Entry *entry;
|
||||
Entry *sup;
|
||||
unsigned depth;
|
||||
BerVarray dnlist;
|
||||
|
||||
assert( ( alias != NULL && dn_in == NULL )
|
||||
|| ( alias == NULL && dn_in != NULL ) );
|
||||
|
||||
*matched = NULL;
|
||||
*err = LDAP_NO_SUCH_OBJECT;
|
||||
*text = NULL;
|
||||
|
||||
if( alias == NULL ) {
|
||||
ber_dupbv( &dn, dn_in );
|
||||
entry = dn2entry_r( be, &dn, &sup );
|
||||
|
||||
} else {
|
||||
ber_dupbv( &dn, &alias->e_nname );
|
||||
entry = alias;
|
||||
sup = NULL;
|
||||
}
|
||||
|
||||
dnlist = NULL;
|
||||
ber_bvarray_add( &dnlist, &dn );
|
||||
|
||||
for( depth=0 ; ; depth++ ) {
|
||||
if( entry != NULL ) {
|
||||
Entry *newe;
|
||||
struct berval aliasDN;
|
||||
|
||||
/* have entry, may be an alias */
|
||||
|
||||
if( !is_entry_alias( entry ) ) {
|
||||
/* entry is not an alias */
|
||||
break;
|
||||
}
|
||||
|
||||
/* entry is alias */
|
||||
if( depth > be->be_max_deref_depth ) {
|
||||
*matched = entry;
|
||||
entry = NULL;
|
||||
*err = LDAP_ALIAS_DEREF_PROBLEM;
|
||||
*text = "maximum deref depth exceeded";
|
||||
break;
|
||||
}
|
||||
|
||||
/* deref entry */
|
||||
if( get_alias_dn( entry, &aliasDN, err, text )) {
|
||||
*matched = entry;
|
||||
entry = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
/* check if aliasDN is a subordinate of any DN in our list */
|
||||
if( dnlist_subordinate( dnlist, &aliasDN ) ) {
|
||||
ch_free( aliasDN.bv_val );
|
||||
*matched = entry;
|
||||
entry = NULL;
|
||||
*err = LDAP_ALIAS_PROBLEM;
|
||||
*text = "circular alias";
|
||||
break;
|
||||
}
|
||||
|
||||
/* attempt to dereference alias */
|
||||
|
||||
newe = dn2entry_r( be, &aliasDN, &sup );
|
||||
ch_free( aliasDN.bv_val );
|
||||
|
||||
if( newe != NULL ) {
|
||||
cache_return_entry_r(&li->li_cache, entry );
|
||||
entry = newe;
|
||||
ber_dupbv( &dn, &entry->e_nname );
|
||||
ber_bvarray_add( &dnlist, &dn );
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( sup != NULL ) {
|
||||
cache_return_entry_r(&li->li_cache, entry );
|
||||
entry = NULL;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* no newe and no superior, we're done */
|
||||
break;
|
||||
|
||||
} else if( sup != NULL ) {
|
||||
/* have superior, may be an alias */
|
||||
Entry *newe;
|
||||
Entry *newSup;
|
||||
struct berval supDN;
|
||||
struct berval aliasDN;
|
||||
|
||||
if( !is_entry_alias( sup ) ) {
|
||||
/* entry is not an alias */
|
||||
*matched = sup;
|
||||
sup = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
/* entry is alias */
|
||||
if( depth > be->be_max_deref_depth ) {
|
||||
*matched = sup;
|
||||
entry = NULL;
|
||||
*err = LDAP_ALIAS_DEREF_PROBLEM;
|
||||
*text = "maximum deref depth exceeded";
|
||||
break;
|
||||
}
|
||||
|
||||
/* deref entry */
|
||||
if( get_alias_dn( sup, &supDN, err, text )) {
|
||||
*matched = sup;
|
||||
break;
|
||||
}
|
||||
|
||||
new_superior( &dn, &sup->e_nname, &supDN, &aliasDN );
|
||||
free(supDN.bv_val);
|
||||
|
||||
/* check if aliasDN is a subordinate of any DN in our list */
|
||||
if( dnlist_subordinate( dnlist, &aliasDN ) ) {
|
||||
free(aliasDN.bv_val);
|
||||
*matched = entry;
|
||||
entry = NULL;
|
||||
*err = LDAP_ALIAS_PROBLEM;
|
||||
*text = "subordinate circular alias";
|
||||
break;
|
||||
}
|
||||
|
||||
/* attempt to dereference alias */
|
||||
newe = dn2entry_r( be, &aliasDN, &newSup );
|
||||
|
||||
if( newe != NULL ) {
|
||||
free(aliasDN.bv_val);
|
||||
cache_return_entry_r(&li->li_cache, sup );
|
||||
entry = newe;
|
||||
ber_dupbv( &dn, &entry->e_nname );
|
||||
ber_bvarray_add( &dnlist, &dn );
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( newSup != NULL ) {
|
||||
cache_return_entry_r(&li->li_cache, sup );
|
||||
sup = newSup;
|
||||
ber_dupbv( &dn, &aliasDN );
|
||||
continue;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
} else {
|
||||
/* no newe and no superior, we're done */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ber_bvarray_free( dnlist );
|
||||
return entry;
|
||||
}
|
||||
|
||||
|
||||
static void new_superior(
|
||||
struct berval *dn,
|
||||
struct berval *oldSup,
|
||||
struct berval *newSup,
|
||||
struct berval *newDN )
|
||||
{
|
||||
size_t dnlen, olen, nlen;
|
||||
assert( dn && oldSup && newSup && newDN );
|
||||
|
||||
dnlen = dn->bv_len;
|
||||
olen = oldSup->bv_len;
|
||||
nlen = newSup->bv_len;
|
||||
|
||||
newDN->bv_val = ch_malloc( dnlen - olen + nlen + 1 );
|
||||
|
||||
AC_MEMCPY( newDN->bv_val, dn->bv_val, dnlen - olen );
|
||||
AC_MEMCPY( &newDN->bv_val[dnlen - olen], newSup->bv_val, nlen );
|
||||
newDN->bv_val[dnlen - olen + nlen] = '\0';
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static int dnlist_subordinate(
|
||||
BerVarray dnlist,
|
||||
struct berval *dn )
|
||||
{
|
||||
assert( dnlist != NULL );
|
||||
|
||||
for( ; dnlist->bv_val != NULL; dnlist++ ) {
|
||||
if( dnIsSuffix( dnlist, dn ) ) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1,231 +0,0 @@
|
|||
/* attr.c - backend routines for dealing with attributes */
|
||||
/* $OpenLDAP$ */
|
||||
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
|
||||
*
|
||||
* Copyright 1998-2006 The OpenLDAP Foundation.
|
||||
* 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>.
|
||||
*/
|
||||
|
||||
#include "portable.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <ac/socket.h>
|
||||
#include <ac/string.h>
|
||||
|
||||
#include "slap.h"
|
||||
#include "back-ldbm.h"
|
||||
|
||||
/* for the cache of attribute information (which are indexed, etc.) */
|
||||
typedef struct ldbm_attrinfo {
|
||||
AttributeDescription *ai_desc; /* attribute description cn;lang-en */
|
||||
slap_mask_t ai_indexmask; /* how the attr is indexed */
|
||||
} AttrInfo;
|
||||
|
||||
static int
|
||||
ainfo_type_cmp(
|
||||
const void *v_desc,
|
||||
const void *v_a
|
||||
)
|
||||
{
|
||||
const AttributeDescription *desc = v_desc;
|
||||
const AttrInfo *a = v_a;
|
||||
return SLAP_PTRCMP(desc, a->ai_desc);
|
||||
}
|
||||
|
||||
static int
|
||||
ainfo_cmp(
|
||||
const void *v_a,
|
||||
const void *v_b
|
||||
)
|
||||
{
|
||||
const AttrInfo *a = v_a, *b = v_b;
|
||||
return SLAP_PTRCMP(a->ai_desc, b->ai_desc);
|
||||
}
|
||||
|
||||
void
|
||||
attr_mask(
|
||||
struct ldbminfo *li,
|
||||
AttributeDescription *desc,
|
||||
slap_mask_t *indexmask )
|
||||
{
|
||||
AttrInfo *a;
|
||||
|
||||
a = avl_find( li->li_attrs, desc, ainfo_type_cmp );
|
||||
|
||||
*indexmask = a != NULL ? a->ai_indexmask : 0;
|
||||
}
|
||||
|
||||
int
|
||||
attr_index_config(
|
||||
struct ldbminfo *li,
|
||||
const char *fname,
|
||||
int lineno,
|
||||
int argc,
|
||||
char **argv )
|
||||
{
|
||||
int rc = LDAP_SUCCESS;
|
||||
int i;
|
||||
slap_mask_t mask;
|
||||
char **attrs;
|
||||
char **indexes = NULL;
|
||||
|
||||
attrs = ldap_str2charray( argv[0], "," );
|
||||
|
||||
if( attrs == NULL ) {
|
||||
fprintf( stderr, "%s: line %d: "
|
||||
"no attributes specified: %s\n",
|
||||
fname, lineno, argv[0] );
|
||||
return LDAP_PARAM_ERROR;
|
||||
}
|
||||
|
||||
if ( argc > 1 ) {
|
||||
indexes = ldap_str2charray( argv[1], "," );
|
||||
|
||||
if( indexes == NULL ) {
|
||||
fprintf( stderr, "%s: line %d: "
|
||||
"no indexes specified: %s\n",
|
||||
fname, lineno, argv[1] );
|
||||
rc = LDAP_PARAM_ERROR;
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
if( indexes == NULL ) {
|
||||
mask = li->li_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] );
|
||||
rc = LDAP_PARAM_ERROR;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
mask |= index;
|
||||
}
|
||||
}
|
||||
|
||||
if( !mask ) {
|
||||
fprintf( stderr, "%s: line %d: "
|
||||
"no indexes selected\n",
|
||||
fname, lineno );
|
||||
rc = LDAP_PARAM_ERROR;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
for ( i = 0; attrs[i] != NULL; i++ ) {
|
||||
AttrInfo *a;
|
||||
AttributeDescription *ad;
|
||||
const char *text;
|
||||
|
||||
if( strcasecmp( attrs[i], "default" ) == 0 ) {
|
||||
li->li_defaultmask = mask;
|
||||
continue;
|
||||
}
|
||||
|
||||
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] );
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if( slap_ad_is_binary( ad ) ) {
|
||||
fprintf( stderr, "%s: line %d: "
|
||||
"index of attribute \"%s\" disallowed\n",
|
||||
fname, lineno, attrs[i] );
|
||||
rc = LDAP_UNWILLING_TO_PERFORM;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if( IS_SLAP_INDEX( mask, SLAP_INDEX_APPROX ) && !(
|
||||
ad->ad_type->sat_approx
|
||||
&& ad->ad_type->sat_approx->smr_indexer
|
||||
&& ad->ad_type->sat_approx->smr_filter ) )
|
||||
{
|
||||
fprintf( stderr, "%s: line %d: "
|
||||
"approx index of attribute \"%s\" disallowed\n",
|
||||
fname, lineno, attrs[i] );
|
||||
rc = LDAP_INAPPROPRIATE_MATCHING;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
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] );
|
||||
rc = LDAP_INAPPROPRIATE_MATCHING;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
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] );
|
||||
|
||||
rc = LDAP_INAPPROPRIATE_MATCHING;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
Debug( LDAP_DEBUG_CONFIG, "index %s 0x%04lx\n",
|
||||
ad->ad_cname.bv_val, mask, 0 );
|
||||
|
||||
a = (AttrInfo *) ch_malloc( sizeof(AttrInfo) );
|
||||
|
||||
a->ai_desc = ad;
|
||||
|
||||
a->ai_indexmask = mask;
|
||||
|
||||
rc = avl_insert( &li->li_attrs, (caddr_t) a,
|
||||
ainfo_cmp, avl_dup_error );
|
||||
|
||||
if( rc ) {
|
||||
fprintf( stderr,
|
||||
"%s: line %d: duplicate index definition for attr \"%s\".\n",
|
||||
fname, lineno, attrs[i] );
|
||||
ch_free( a );
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
rc = LDAP_SUCCESS;
|
||||
|
||||
fail:
|
||||
if ( indexes != NULL ) ldap_charray_free( indexes );
|
||||
ldap_charray_free( attrs );
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
void
|
||||
attr_index_destroy( Avlnode *tree )
|
||||
{
|
||||
avl_free( tree, free );
|
||||
}
|
||||
|
|
@ -1,161 +0,0 @@
|
|||
/* back-ldbm.h - ldap ldbm back-end header file */
|
||||
/* $OpenLDAP$ */
|
||||
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
|
||||
*
|
||||
* Copyright 1998-2006 The OpenLDAP Foundation.
|
||||
* 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>.
|
||||
*/
|
||||
|
||||
#ifndef _BACK_LDBM_H_
|
||||
#define _BACK_LDBM_H_
|
||||
|
||||
#include "ldbm.h"
|
||||
#include "alock.h"
|
||||
|
||||
LDAP_BEGIN_DECL
|
||||
|
||||
#define DEFAULT_CACHE_SIZE 1000
|
||||
|
||||
#if defined(HAVE_BERKELEY_DB) && DB_VERSION_MAJOR >= 2
|
||||
# define DEFAULT_DBCACHE_SIZE (100 * DEFAULT_DB_PAGE_SIZE)
|
||||
#else
|
||||
# define DEFAULT_DBCACHE_SIZE 100000
|
||||
#endif
|
||||
|
||||
#define DN_BASE_PREFIX SLAP_INDEX_EQUALITY_PREFIX
|
||||
#define DN_ONE_PREFIX '%'
|
||||
#define DN_SUBTREE_PREFIX '@'
|
||||
|
||||
/*
|
||||
* there is a single index for each attribute. these prefixes ensure
|
||||
* that there is no collision among keys.
|
||||
*/
|
||||
|
||||
/* allow PREFIX + byte for continuate number */
|
||||
#define SLAP_INDEX_CONT_SIZE ( sizeof(SLAP_INDEX_CONT_PREFIX) + sizeof(unsigned char) )
|
||||
|
||||
#define DEFAULT_BLOCKSIZE 8192
|
||||
|
||||
/*
|
||||
* This structure represents an id block on disk and an id list
|
||||
* in core.
|
||||
*
|
||||
* The fields have the following meanings:
|
||||
*
|
||||
* b_nmax maximum number of ids in this block. if this is == ALLIDSBLOCK,
|
||||
* then this block represents all ids.
|
||||
* b_nids current number of ids in use in this block. if this
|
||||
* is == INDBLOCK, then this block is an indirect block
|
||||
* containing a list of other blocks containing actual ids.
|
||||
* the list is terminated by an id of NOID.
|
||||
* b_ids a list of the actual ids themselves
|
||||
*/
|
||||
|
||||
typedef ID ID_BLOCK;
|
||||
|
||||
#define ID_BLOCK_NMAX_OFFSET 0
|
||||
#define ID_BLOCK_NIDS_OFFSET 1
|
||||
#define ID_BLOCK_IDS_OFFSET 2
|
||||
|
||||
/* all ID_BLOCK macros operate on a pointer to a ID_BLOCK */
|
||||
|
||||
#define ID_BLOCK_NMAX(b) ((b)[ID_BLOCK_NMAX_OFFSET])
|
||||
|
||||
/* Use this macro to get the value, but not to set it.
|
||||
* By default this is identical to above.
|
||||
*/
|
||||
#define ID_BLOCK_NMAXN(b) ID_BLOCK_NMAX(b)
|
||||
#define ID_BLOCK_NIDS(b) ((b)[ID_BLOCK_NIDS_OFFSET])
|
||||
#define ID_BLOCK_ID(b, n) ((b)[ID_BLOCK_IDS_OFFSET+(n)])
|
||||
|
||||
#define ID_BLOCK_NOID(b, n) (ID_BLOCK_ID((b),(n)) == NOID)
|
||||
|
||||
#define ID_BLOCK_ALLIDS_VALUE 0
|
||||
#define ID_BLOCK_ALLIDS(b) (ID_BLOCK_NMAX(b) == ID_BLOCK_ALLIDS_VALUE)
|
||||
|
||||
#define ID_BLOCK_INDIRECT_VALUE 0
|
||||
#define ID_BLOCK_INDIRECT(b) (ID_BLOCK_NIDS(b) == ID_BLOCK_INDIRECT_VALUE)
|
||||
|
||||
#define USE_INDIRECT_NIDS 1
|
||||
|
||||
#ifdef USE_INDIRECT_NIDS
|
||||
/*
|
||||
* Use the high bit of ID_BLOCK_NMAX to indicate an INDIRECT block, thus
|
||||
* freeing up the ID_BLOCK_NIDS to store an actual count. This allows us
|
||||
* to use binary search on INDIRECT blocks.
|
||||
*/
|
||||
#undef ID_BLOCK_NMAXN
|
||||
#define ID_BLOCK_NMAXN(b) ((b)[ID_BLOCK_NMAX_OFFSET]&0x7fffffff)
|
||||
#undef ID_BLOCK_INDIRECT_VALUE
|
||||
#define ID_BLOCK_INDIRECT_VALUE 0x80000000
|
||||
#undef ID_BLOCK_INDIRECT
|
||||
#define ID_BLOCK_INDIRECT(b) (ID_BLOCK_NMAX(b) & ID_BLOCK_INDIRECT_VALUE)
|
||||
|
||||
#endif /* USE_INDIRECT_NIDS */
|
||||
|
||||
/* for the in-core cache of entries */
|
||||
typedef struct ldbm_cache {
|
||||
int c_maxsize;
|
||||
int c_cursize;
|
||||
Avlnode *c_dntree;
|
||||
Avlnode *c_idtree;
|
||||
Entry *c_lruhead; /* lru - add accessed entries here */
|
||||
Entry *c_lrutail; /* lru - rem lru entries from here */
|
||||
ldap_pvt_thread_mutex_t c_mutex;
|
||||
} Cache;
|
||||
|
||||
#define CACHE_READ_LOCK 0
|
||||
#define CACHE_WRITE_LOCK 1
|
||||
|
||||
/* for the cache of open index files */
|
||||
typedef struct ldbm_dbcache {
|
||||
int dbc_refcnt;
|
||||
int dbc_maxids;
|
||||
int dbc_maxindirect;
|
||||
int dbc_dirty;
|
||||
int dbc_flags;
|
||||
time_t dbc_lastref;
|
||||
long dbc_blksize;
|
||||
char *dbc_name;
|
||||
LDBM dbc_db;
|
||||
ldap_pvt_thread_mutex_t dbc_write_mutex;
|
||||
} DBCache;
|
||||
|
||||
#define MAXDBCACHE 128
|
||||
|
||||
struct ldbminfo {
|
||||
ldap_pvt_thread_rdwr_t li_giant_rwlock;
|
||||
ID li_nextid;
|
||||
int li_mode;
|
||||
slap_mask_t li_defaultmask;
|
||||
char *li_directory;
|
||||
Cache li_cache;
|
||||
Avlnode *li_attrs;
|
||||
int li_dblocking; /* lock databases */
|
||||
int li_dbwritesync; /* write sync */
|
||||
int li_dbcachesize;
|
||||
DBCache li_dbcache[MAXDBCACHE];
|
||||
ldap_pvt_thread_mutex_t li_dbcache_mutex;
|
||||
ldap_pvt_thread_cond_t li_dbcache_cv;
|
||||
DB_ENV *li_dbenv;
|
||||
int li_envdirok;
|
||||
int li_dbsyncfreq;
|
||||
int li_dbsyncwaitn;
|
||||
int li_dbsyncwaitinterval;
|
||||
int li_dbsyncwaitcount;
|
||||
alock_info_t li_alock_info;
|
||||
};
|
||||
|
||||
LDAP_END_DECL
|
||||
|
||||
#include "proto-back-ldbm.h"
|
||||
|
||||
#endif /* _back_ldbm_h_ */
|
||||
|
|
@ -1,195 +0,0 @@
|
|||
/* bind.c - ldbm backend bind and unbind routines */
|
||||
/* $OpenLDAP$ */
|
||||
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
|
||||
*
|
||||
* Copyright 1998-2006 The OpenLDAP Foundation.
|
||||
* 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>.
|
||||
*/
|
||||
|
||||
#include "portable.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <ac/krb.h>
|
||||
#include <ac/socket.h>
|
||||
#include <ac/string.h>
|
||||
#include <ac/unistd.h>
|
||||
|
||||
#include "slap.h"
|
||||
#include "back-ldbm.h"
|
||||
#include "proto-back-ldbm.h"
|
||||
|
||||
int
|
||||
ldbm_back_bind(
|
||||
Operation *op,
|
||||
SlapReply *rs )
|
||||
{
|
||||
struct ldbminfo *li = (struct ldbminfo *) op->o_bd->be_private;
|
||||
Entry *e;
|
||||
Attribute *a;
|
||||
int rc;
|
||||
Entry *matched;
|
||||
#ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND
|
||||
char krbname[MAX_K_NAME_SZ + 1];
|
||||
AttributeDescription *krbattr = slap_schema.si_ad_krbName;
|
||||
AUTH_DAT ad;
|
||||
#endif
|
||||
|
||||
AttributeDescription *password = slap_schema.si_ad_userPassword;
|
||||
|
||||
Debug(LDAP_DEBUG_ARGS,
|
||||
"==> ldbm_back_bind: dn: %s\n", op->o_req_dn.bv_val, 0, 0);
|
||||
|
||||
if ( op->oq_bind.rb_method == LDAP_AUTH_SIMPLE && be_isroot_pw( op ) ) {
|
||||
ber_dupbv( &op->oq_bind.rb_edn, be_root_dn( op->o_bd ) );
|
||||
/* front end will send result */
|
||||
return LDAP_SUCCESS;
|
||||
}
|
||||
|
||||
/* grab giant lock for reading */
|
||||
ldap_pvt_thread_rdwr_rlock(&li->li_giant_rwlock);
|
||||
|
||||
/* get entry with reader lock */
|
||||
if ( (e = dn2entry_r( op->o_bd, &op->o_req_ndn, &matched )) == NULL ) {
|
||||
if( matched != NULL ) {
|
||||
cache_return_entry_r( &li->li_cache, matched );
|
||||
}
|
||||
ldap_pvt_thread_rdwr_runlock(&li->li_giant_rwlock);
|
||||
|
||||
/* allow noauth binds */
|
||||
rc = 1;
|
||||
rs->sr_err = LDAP_INVALID_CREDENTIALS;
|
||||
send_ldap_result( op, rs );
|
||||
return rs->sr_err;
|
||||
}
|
||||
|
||||
/* check for deleted */
|
||||
|
||||
if ( is_entry_subentry( e ) ) {
|
||||
/* entry is an subentry, don't allow bind */
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"entry is subentry\n", 0, 0, 0 );
|
||||
rc = LDAP_INVALID_CREDENTIALS;
|
||||
goto return_results;
|
||||
}
|
||||
|
||||
if ( is_entry_alias( e ) ) {
|
||||
/* entry is an alias, don't allow bind */
|
||||
Debug( LDAP_DEBUG_TRACE, "entry is alias\n", 0, 0, 0 );
|
||||
|
||||
#if 1
|
||||
rc = LDAP_INVALID_CREDENTIALS;
|
||||
#else
|
||||
rs->sr_text = "entry is alias";
|
||||
rc = LDAP_ALIAS_PROBLEM;
|
||||
#endif
|
||||
goto return_results;
|
||||
}
|
||||
|
||||
if ( is_entry_referral( e ) ) {
|
||||
/* entry is a referral, don't allow bind */
|
||||
Debug( LDAP_DEBUG_TRACE, "entry is referral\n", 0, 0, 0 );
|
||||
|
||||
rc = LDAP_INVALID_CREDENTIALS;
|
||||
goto return_results;
|
||||
}
|
||||
|
||||
switch ( op->oq_bind.rb_method ) {
|
||||
case LDAP_AUTH_SIMPLE:
|
||||
if ( (a = attr_find( e->e_attrs, password )) == NULL ) {
|
||||
/* stop front end from sending result */
|
||||
rc = LDAP_INVALID_CREDENTIALS;
|
||||
goto return_results;
|
||||
}
|
||||
|
||||
if ( slap_passwd_check( op, e, a, &op->oq_bind.rb_cred,
|
||||
&rs->sr_text ) != 0 )
|
||||
{
|
||||
/* failure; stop front end from sending result */
|
||||
rc = LDAP_INVALID_CREDENTIALS;
|
||||
goto return_results;
|
||||
}
|
||||
|
||||
rc = 0;
|
||||
break;
|
||||
|
||||
#ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND
|
||||
case LDAP_AUTH_KRBV41:
|
||||
if ( krbv4_ldap_auth( op->o_bd, &op->oq_bind.rb_cred, &ad )
|
||||
!= LDAP_SUCCESS )
|
||||
{
|
||||
rc = LDAP_INVALID_CREDENTIALS;
|
||||
goto return_results;
|
||||
}
|
||||
|
||||
if ( ! access_allowed( op, e,
|
||||
krbattr, NULL, ACL_AUTH, NULL ) )
|
||||
{
|
||||
rc = LDAP_INSUFFICIENT_ACCESS;
|
||||
goto return_results;
|
||||
}
|
||||
|
||||
sprintf( krbname, "%s%s%s@%s", ad.pname, *ad.pinst ? "."
|
||||
: "", ad.pinst, ad.prealm );
|
||||
|
||||
if ( (a = attr_find( e->e_attrs, krbattr )) == NULL ) {
|
||||
/*
|
||||
* no krbname values present: check against DN
|
||||
*/
|
||||
if ( strcasecmp( op->o_req_dn.bv_val, krbname ) == 0 ) {
|
||||
rc = 0;
|
||||
break;
|
||||
}
|
||||
rc = LDAP_INAPPROPRIATE_AUTH;
|
||||
goto return_results;
|
||||
|
||||
} else { /* look for krbname match */
|
||||
struct berval krbval;
|
||||
|
||||
krbval.bv_val = krbname;
|
||||
krbval.bv_len = strlen( krbname );
|
||||
|
||||
if ( value_find( a->a_desc, a->a_vals, &krbval ) != 0 ) {
|
||||
rc = LDAP_INVALID_CREDENTIALS;
|
||||
goto return_results;
|
||||
}
|
||||
}
|
||||
rc = 0;
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
assert( 0 ); /* should not be reachable */
|
||||
rs->sr_text = "authentication method not supported";
|
||||
rc = LDAP_STRONG_AUTH_NOT_SUPPORTED;
|
||||
goto return_results;
|
||||
}
|
||||
|
||||
ber_dupbv( &op->oq_bind.rb_edn, &e->e_name );
|
||||
|
||||
return_results:;
|
||||
/* free entry and reader lock */
|
||||
cache_return_entry_r( &li->li_cache, e );
|
||||
ldap_pvt_thread_rdwr_runlock(&li->li_giant_rwlock);
|
||||
|
||||
if ( rc ) {
|
||||
rs->sr_err = rc;
|
||||
send_ldap_result( op, rs );
|
||||
if ( rs->sr_ref ) {
|
||||
ber_bvarray_free( rs->sr_ref );
|
||||
rs->sr_ref = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* front end will send result on success (rc==0) */
|
||||
return( rc );
|
||||
}
|
||||
|
||||
|
|
@ -1,675 +0,0 @@
|
|||
/* cache.c - routines to maintain an in-core cache of entries */
|
||||
/* $OpenLDAP$ */
|
||||
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
|
||||
*
|
||||
* Copyright 1998-2006 The OpenLDAP Foundation.
|
||||
* 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>.
|
||||
*/
|
||||
|
||||
#include "portable.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <ac/errno.h>
|
||||
#include <ac/string.h>
|
||||
#include <ac/socket.h>
|
||||
|
||||
#include "slap.h"
|
||||
|
||||
#include "back-ldbm.h"
|
||||
|
||||
/* LDBM backend specific entry info -- visible only to the cache */
|
||||
typedef struct ldbm_entry_info {
|
||||
/*
|
||||
* These items are specific to the LDBM backend and should
|
||||
* be hidden. Backend cache lock required to access.
|
||||
*/
|
||||
int lei_state; /* for the cache */
|
||||
#define CACHE_ENTRY_UNDEFINED 0
|
||||
#define CACHE_ENTRY_CREATING 1
|
||||
#define CACHE_ENTRY_READY 2
|
||||
#define CACHE_ENTRY_DELETED 3
|
||||
#define CACHE_ENTRY_COMMITTED 4
|
||||
|
||||
int lei_refcnt; /* # threads ref'ing this entry */
|
||||
Entry *lei_lrunext; /* for cache lru list */
|
||||
Entry *lei_lruprev;
|
||||
} EntryInfo;
|
||||
#undef LEI
|
||||
#define LEI(e) ((EntryInfo *) ((e)->e_private))
|
||||
|
||||
static int cache_delete_entry_internal(Cache *cache, Entry *e);
|
||||
#ifdef LDAP_DEBUG
|
||||
#ifdef SLAPD_UNUSED
|
||||
static void lru_print(Cache *cache);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
static int
|
||||
cache_entry_private_init( Entry*e )
|
||||
{
|
||||
assert( e->e_private == NULL );
|
||||
|
||||
if( e->e_private != NULL ) {
|
||||
/* this should never happen */
|
||||
return 1;
|
||||
}
|
||||
|
||||
e->e_private = ch_calloc(1, sizeof(struct ldbm_entry_info));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* marks an entry in CREATING state as committed, so it is really returned
|
||||
* to the cache. Otherwise an entry in CREATING state is removed.
|
||||
* Makes e_private be destroyed at the following cache_return_entry_w,
|
||||
* but lets the entry untouched (owned by someone else)
|
||||
*/
|
||||
void
|
||||
cache_entry_commit( Entry *e )
|
||||
{
|
||||
assert( e != NULL );
|
||||
assert( e->e_private != NULL );
|
||||
assert( LEI(e)->lei_state == CACHE_ENTRY_CREATING );
|
||||
/* assert( LEI(e)->lei_refcnt == 1 ); */
|
||||
|
||||
LEI(e)->lei_state = CACHE_ENTRY_COMMITTED;
|
||||
}
|
||||
|
||||
static int
|
||||
cache_entry_private_destroy( Entry*e )
|
||||
{
|
||||
assert( e->e_private != NULL );
|
||||
|
||||
free( e->e_private );
|
||||
e->e_private = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
cache_return_entry_rw( Cache *cache, Entry *e, int rw )
|
||||
{
|
||||
ID id;
|
||||
int refcnt, freeit = 1;
|
||||
|
||||
if ( slapMode != SLAP_SERVER_MODE ) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* set cache mutex */
|
||||
ldap_pvt_thread_mutex_lock( &cache->c_mutex );
|
||||
|
||||
assert( e->e_private != NULL );
|
||||
|
||||
id = e->e_id;
|
||||
refcnt = --LEI(e)->lei_refcnt;
|
||||
|
||||
/*
|
||||
* if the entry is returned when in CREATING state, it is deleted
|
||||
* but not freed because it may belong to someone else (do_add,
|
||||
* for instance)
|
||||
*/
|
||||
if ( LEI(e)->lei_state == CACHE_ENTRY_CREATING ) {
|
||||
cache_delete_entry_internal( cache, e );
|
||||
freeit = 0;
|
||||
/* now the entry is in DELETED state */
|
||||
}
|
||||
|
||||
if ( LEI(e)->lei_state == CACHE_ENTRY_COMMITTED ) {
|
||||
LEI(e)->lei_state = CACHE_ENTRY_READY;
|
||||
|
||||
/* free cache mutex */
|
||||
ldap_pvt_thread_mutex_unlock( &cache->c_mutex );
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"====> cache_return_entry_%s( %ld ): created (%d)\n",
|
||||
rw ? "w" : "r", id, refcnt );
|
||||
|
||||
} else if ( LEI(e)->lei_state == CACHE_ENTRY_DELETED ) {
|
||||
if( refcnt > 0 ) {
|
||||
/* free cache mutex */
|
||||
ldap_pvt_thread_mutex_unlock( &cache->c_mutex );
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"====> cache_return_entry_%s( %ld ): delete pending (%d)\n",
|
||||
rw ? "w" : "r", id, refcnt );
|
||||
|
||||
} else {
|
||||
cache_entry_private_destroy( e );
|
||||
if ( freeit ) {
|
||||
entry_free( e );
|
||||
}
|
||||
|
||||
/* free cache mutex */
|
||||
ldap_pvt_thread_mutex_unlock( &cache->c_mutex );
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"====> cache_return_entry_%s( %ld ): deleted (%d)\n",
|
||||
rw ? "w" : "r", id, refcnt );
|
||||
}
|
||||
|
||||
} else {
|
||||
/* free cache mutex */
|
||||
ldap_pvt_thread_mutex_unlock( &cache->c_mutex );
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"====> cache_return_entry_%s( %ld ): returned (%d)\n",
|
||||
rw ? "w" : "r", id, refcnt);
|
||||
}
|
||||
}
|
||||
|
||||
#define LRU_DELETE( cache, e ) do { \
|
||||
if ( LEI(e)->lei_lruprev != NULL ) { \
|
||||
LEI(LEI(e)->lei_lruprev)->lei_lrunext = LEI(e)->lei_lrunext; \
|
||||
} else { \
|
||||
(cache)->c_lruhead = LEI(e)->lei_lrunext; \
|
||||
} \
|
||||
if ( LEI(e)->lei_lrunext != NULL ) { \
|
||||
LEI(LEI(e)->lei_lrunext)->lei_lruprev = LEI(e)->lei_lruprev; \
|
||||
} else { \
|
||||
(cache)->c_lrutail = LEI(e)->lei_lruprev; \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#define LRU_ADD( cache, e ) do { \
|
||||
LEI(e)->lei_lrunext = (cache)->c_lruhead; \
|
||||
if ( LEI(e)->lei_lrunext != NULL ) { \
|
||||
LEI(LEI(e)->lei_lrunext)->lei_lruprev = (e); \
|
||||
} \
|
||||
(cache)->c_lruhead = (e); \
|
||||
LEI(e)->lei_lruprev = NULL; \
|
||||
if ( (cache)->c_lrutail == NULL ) { \
|
||||
(cache)->c_lrutail = (e); \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
/*
|
||||
* cache_add_entry_rw - create and lock an entry in the cache
|
||||
* returns: 0 entry has been created and locked
|
||||
* 1 entry already existed
|
||||
* -1 something bad happened
|
||||
*/
|
||||
int
|
||||
cache_add_entry_rw(
|
||||
Cache *cache,
|
||||
Entry *e,
|
||||
int rw
|
||||
)
|
||||
{
|
||||
int i, rc;
|
||||
Entry *ee;
|
||||
|
||||
/* set cache mutex */
|
||||
ldap_pvt_thread_mutex_lock( &cache->c_mutex );
|
||||
|
||||
assert( e->e_private == NULL );
|
||||
|
||||
if( cache_entry_private_init(e) != 0 ) {
|
||||
/* free cache mutex */
|
||||
ldap_pvt_thread_mutex_unlock( &cache->c_mutex );
|
||||
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"====> cache_add_entry( %ld ): \"%s\": private init failed!\n",
|
||||
e->e_id, e->e_dn, 0 );
|
||||
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
if ( avl_insert( &cache->c_dntree, (caddr_t) e,
|
||||
entry_dn_cmp, avl_dup_error ) != 0 )
|
||||
{
|
||||
/* free cache mutex */
|
||||
ldap_pvt_thread_mutex_unlock( &cache->c_mutex );
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"====> cache_add_entry( %ld ): \"%s\": already in dn cache\n",
|
||||
e->e_id, e->e_dn, 0 );
|
||||
|
||||
cache_entry_private_destroy(e);
|
||||
|
||||
return( 1 );
|
||||
}
|
||||
|
||||
/* id tree */
|
||||
if ( avl_insert( &cache->c_idtree, (caddr_t) e,
|
||||
entry_id_cmp, avl_dup_error ) != 0 )
|
||||
{
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"====> cache_add_entry( %ld ): \"%s\": already in id cache\n",
|
||||
e->e_id, e->e_dn, 0 );
|
||||
|
||||
/* delete from dn tree inserted above */
|
||||
if ( avl_delete( &cache->c_dntree, (caddr_t) e,
|
||||
entry_dn_cmp ) == NULL )
|
||||
{
|
||||
Debug( LDAP_DEBUG_ANY, "====> can't delete from dn cache\n",
|
||||
0, 0, 0 );
|
||||
}
|
||||
|
||||
cache_entry_private_destroy(e);
|
||||
|
||||
/* free cache mutex */
|
||||
ldap_pvt_thread_mutex_unlock( &cache->c_mutex );
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
/* put the entry into 'CREATING' state */
|
||||
/* will be marked after when entry is returned */
|
||||
LEI(e)->lei_state = CACHE_ENTRY_CREATING;
|
||||
LEI(e)->lei_refcnt = 1;
|
||||
|
||||
/* lru */
|
||||
LRU_ADD( cache, e );
|
||||
if ( ++cache->c_cursize > cache->c_maxsize ) {
|
||||
/*
|
||||
* find the lru entry not currently in use and delete it.
|
||||
* in case a lot of entries are in use, only look at the
|
||||
* first 10 on the tail of the list.
|
||||
*/
|
||||
i = 0;
|
||||
while ( cache->c_lrutail != NULL &&
|
||||
LEI(cache->c_lrutail)->lei_refcnt != 0 &&
|
||||
i < 10 )
|
||||
{
|
||||
/* move this in-use entry to the front of the q */
|
||||
ee = cache->c_lrutail;
|
||||
LRU_DELETE( cache, ee );
|
||||
LRU_ADD( cache, ee );
|
||||
i++;
|
||||
}
|
||||
|
||||
/*
|
||||
* found at least one to delete - try to get back under
|
||||
* the max cache size.
|
||||
*/
|
||||
while ( cache->c_lrutail != NULL &&
|
||||
LEI(cache->c_lrutail)->lei_refcnt == 0 &&
|
||||
cache->c_cursize > cache->c_maxsize )
|
||||
{
|
||||
e = cache->c_lrutail;
|
||||
|
||||
/* delete from cache and lru q */
|
||||
/* XXX do we need rc ? */
|
||||
rc = cache_delete_entry_internal( cache, e );
|
||||
cache_entry_private_destroy( e );
|
||||
entry_free( e );
|
||||
}
|
||||
}
|
||||
|
||||
/* free cache mutex */
|
||||
ldap_pvt_thread_mutex_unlock( &cache->c_mutex );
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
/*
|
||||
* cache_update_entry - update a LOCKED entry which has been deleted.
|
||||
* returns: 0 entry has been created and locked
|
||||
* 1 entry already existed
|
||||
* -1 something bad happened
|
||||
*/
|
||||
int
|
||||
cache_update_entry(
|
||||
Cache *cache,
|
||||
Entry *e
|
||||
)
|
||||
{
|
||||
int i, rc;
|
||||
Entry *ee;
|
||||
|
||||
/* set cache mutex */
|
||||
ldap_pvt_thread_mutex_lock( &cache->c_mutex );
|
||||
|
||||
assert( e->e_private != NULL );
|
||||
|
||||
if ( avl_insert( &cache->c_dntree, (caddr_t) e,
|
||||
entry_dn_cmp, avl_dup_error ) != 0 )
|
||||
{
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"====> cache_update_entry( %ld ): \"%s\": already in dn cache\n",
|
||||
e->e_id, e->e_dn, 0 );
|
||||
|
||||
/* free cache mutex */
|
||||
ldap_pvt_thread_mutex_unlock( &cache->c_mutex );
|
||||
return( 1 );
|
||||
}
|
||||
|
||||
/* id tree */
|
||||
if ( avl_insert( &cache->c_idtree, (caddr_t) e,
|
||||
entry_id_cmp, avl_dup_error ) != 0 )
|
||||
{
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"====> cache_update_entry( %ld ): \"%s\": already in id cache\n",
|
||||
e->e_id, e->e_dn, 0 );
|
||||
|
||||
/* delete from dn tree inserted above */
|
||||
if ( avl_delete( &cache->c_dntree, (caddr_t) e,
|
||||
entry_dn_cmp ) == NULL )
|
||||
{
|
||||
Debug( LDAP_DEBUG_ANY, "====> can't delete from dn cache\n",
|
||||
0, 0, 0 );
|
||||
}
|
||||
|
||||
/* free cache mutex */
|
||||
ldap_pvt_thread_mutex_unlock( &cache->c_mutex );
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
/* put the entry into 'CREATING' state */
|
||||
/* will be marked after when entry is returned */
|
||||
LEI(e)->lei_state = CACHE_ENTRY_CREATING;
|
||||
|
||||
/* lru */
|
||||
LRU_ADD( cache, e );
|
||||
if ( ++cache->c_cursize > cache->c_maxsize ) {
|
||||
/*
|
||||
* find the lru entry not currently in use and delete it.
|
||||
* in case a lot of entries are in use, only look at the
|
||||
* first 10 on the tail of the list.
|
||||
*/
|
||||
i = 0;
|
||||
while ( cache->c_lrutail != NULL &&
|
||||
LEI(cache->c_lrutail)->lei_refcnt != 0 &&
|
||||
i < 10 )
|
||||
{
|
||||
/* move this in-use entry to the front of the q */
|
||||
ee = cache->c_lrutail;
|
||||
LRU_DELETE( cache, ee );
|
||||
LRU_ADD( cache, ee );
|
||||
i++;
|
||||
}
|
||||
|
||||
/*
|
||||
* found at least one to delete - try to get back under
|
||||
* the max cache size.
|
||||
*/
|
||||
while ( cache->c_lrutail != NULL &&
|
||||
LEI(cache->c_lrutail)->lei_refcnt == 0 &&
|
||||
cache->c_cursize > cache->c_maxsize )
|
||||
{
|
||||
e = cache->c_lrutail;
|
||||
|
||||
/* delete from cache and lru q */
|
||||
/* XXX do we need rc ? */
|
||||
rc = cache_delete_entry_internal( cache, e );
|
||||
cache_entry_private_destroy( e );
|
||||
entry_free( e );
|
||||
}
|
||||
}
|
||||
|
||||
/* free cache mutex */
|
||||
ldap_pvt_thread_mutex_unlock( &cache->c_mutex );
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
ID
|
||||
cache_find_entry_ndn2id(
|
||||
Backend *be,
|
||||
Cache *cache,
|
||||
struct berval *ndn
|
||||
)
|
||||
{
|
||||
Entry e, *ep;
|
||||
ID id;
|
||||
int count = 0;
|
||||
|
||||
/* this function is always called with normalized DN */
|
||||
e.e_nname = *ndn;
|
||||
|
||||
try_again:
|
||||
/* set cache mutex */
|
||||
ldap_pvt_thread_mutex_lock( &cache->c_mutex );
|
||||
|
||||
if ( (ep = (Entry *) avl_find( cache->c_dntree, (caddr_t) &e,
|
||||
entry_dn_cmp )) != NULL )
|
||||
{
|
||||
int state;
|
||||
count++;
|
||||
|
||||
/*
|
||||
* ep now points to an unlocked entry
|
||||
* we do not need to lock the entry if we only
|
||||
* check the state, refcnt, LRU, and id.
|
||||
*/
|
||||
assert( ep->e_private != NULL );
|
||||
|
||||
/* save id */
|
||||
id = ep->e_id;
|
||||
state = LEI(ep)->lei_state;
|
||||
|
||||
/*
|
||||
* entry is deleted or not fully created yet
|
||||
*/
|
||||
if ( state != CACHE_ENTRY_READY ) {
|
||||
assert(state != CACHE_ENTRY_UNDEFINED);
|
||||
|
||||
/* free cache mutex */
|
||||
ldap_pvt_thread_mutex_unlock( &cache->c_mutex );
|
||||
|
||||
Debug(LDAP_DEBUG_TRACE,
|
||||
"====> cache_find_entry_ndn2id(\"%s\"): %ld (not ready) %d\n",
|
||||
ndn->bv_val, id, state);
|
||||
|
||||
ldap_pvt_thread_yield();
|
||||
goto try_again;
|
||||
}
|
||||
|
||||
/* lru */
|
||||
LRU_DELETE( cache, ep );
|
||||
LRU_ADD( cache, ep );
|
||||
|
||||
/* free cache mutex */
|
||||
ldap_pvt_thread_mutex_unlock( &cache->c_mutex );
|
||||
|
||||
Debug(LDAP_DEBUG_TRACE,
|
||||
"====> cache_find_entry_ndn2id(\"%s\"): %ld (%d tries)\n",
|
||||
ndn->bv_val, id, count);
|
||||
|
||||
} else {
|
||||
/* free cache mutex */
|
||||
ldap_pvt_thread_mutex_unlock( &cache->c_mutex );
|
||||
id = NOID;
|
||||
}
|
||||
|
||||
return( id );
|
||||
}
|
||||
|
||||
/*
|
||||
* cache_find_entry_id - find an entry in the cache, given id
|
||||
*/
|
||||
|
||||
Entry *
|
||||
cache_find_entry_id(
|
||||
Cache *cache,
|
||||
ID id,
|
||||
int rw
|
||||
)
|
||||
{
|
||||
Entry e;
|
||||
Entry *ep;
|
||||
int count = 0;
|
||||
|
||||
e.e_id = id;
|
||||
|
||||
try_again:
|
||||
/* set cache mutex */
|
||||
ldap_pvt_thread_mutex_lock( &cache->c_mutex );
|
||||
|
||||
if ( (ep = (Entry *) avl_find( cache->c_idtree, (caddr_t) &e,
|
||||
entry_id_cmp )) != NULL )
|
||||
{
|
||||
int state;
|
||||
ID ep_id;
|
||||
|
||||
count++;
|
||||
|
||||
assert( ep->e_private != NULL );
|
||||
|
||||
ep_id = ep->e_id;
|
||||
state = LEI(ep)->lei_state;
|
||||
|
||||
/*
|
||||
* entry is deleted or not fully created yet
|
||||
*/
|
||||
if ( state != CACHE_ENTRY_READY ) {
|
||||
assert(state != CACHE_ENTRY_UNDEFINED);
|
||||
|
||||
/* free cache mutex */
|
||||
ldap_pvt_thread_mutex_unlock( &cache->c_mutex );
|
||||
|
||||
Debug(LDAP_DEBUG_TRACE,
|
||||
"====> cache_find_entry_id( %ld ): %ld (not ready) %d\n",
|
||||
id, ep_id, state);
|
||||
|
||||
ldap_pvt_thread_yield();
|
||||
goto try_again;
|
||||
}
|
||||
|
||||
/* lru */
|
||||
LRU_DELETE( cache, ep );
|
||||
LRU_ADD( cache, ep );
|
||||
|
||||
LEI(ep)->lei_refcnt++;
|
||||
|
||||
/* free cache mutex */
|
||||
ldap_pvt_thread_mutex_unlock( &cache->c_mutex );
|
||||
|
||||
Debug(LDAP_DEBUG_TRACE,
|
||||
"====> cache_find_entry_id( %ld ) \"%s\" (found) (%d tries)\n",
|
||||
ep_id, ep->e_dn, count);
|
||||
|
||||
return( ep );
|
||||
}
|
||||
|
||||
/* free cache mutex */
|
||||
ldap_pvt_thread_mutex_unlock( &cache->c_mutex );
|
||||
|
||||
return( NULL );
|
||||
}
|
||||
|
||||
/*
|
||||
* cache_delete_entry - delete the entry e from the cache. the caller
|
||||
* should have obtained e (increasing its ref count) via a call to one
|
||||
* of the cache_find_* routines. the caller should *not* call the
|
||||
* cache_return_entry() routine prior to calling cache_delete_entry().
|
||||
* it performs this function.
|
||||
*
|
||||
* returns: 0 e was deleted ok
|
||||
* 1 e was not in the cache
|
||||
* -1 something bad happened
|
||||
*/
|
||||
int
|
||||
cache_delete_entry(
|
||||
Cache *cache,
|
||||
Entry *e
|
||||
)
|
||||
{
|
||||
int rc;
|
||||
|
||||
/* set cache mutex */
|
||||
ldap_pvt_thread_mutex_lock( &cache->c_mutex );
|
||||
|
||||
assert( e->e_private != NULL );
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "====> cache_delete_entry( %ld )\n",
|
||||
e->e_id, 0, 0 );
|
||||
|
||||
rc = cache_delete_entry_internal( cache, e );
|
||||
|
||||
/* free cache mutex */
|
||||
ldap_pvt_thread_mutex_unlock( &cache->c_mutex );
|
||||
return( rc );
|
||||
}
|
||||
|
||||
static int
|
||||
cache_delete_entry_internal(
|
||||
Cache *cache,
|
||||
Entry *e
|
||||
)
|
||||
{
|
||||
int rc = 0; /* return code */
|
||||
|
||||
/* dn tree */
|
||||
if ( avl_delete( &cache->c_dntree, (caddr_t) e, entry_dn_cmp ) == NULL )
|
||||
{
|
||||
rc = -1;
|
||||
}
|
||||
|
||||
/* id tree */
|
||||
if ( avl_delete( &cache->c_idtree, (caddr_t) e, entry_id_cmp ) == NULL )
|
||||
{
|
||||
rc = -1;
|
||||
}
|
||||
|
||||
if (rc != 0) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* lru */
|
||||
LRU_DELETE( cache, e );
|
||||
cache->c_cursize--;
|
||||
|
||||
/*
|
||||
* flag entry to be freed later by a call to cache_return_entry()
|
||||
*/
|
||||
LEI(e)->lei_state = CACHE_ENTRY_DELETED;
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
void
|
||||
cache_release_all( Cache *cache )
|
||||
{
|
||||
Entry *e;
|
||||
int rc;
|
||||
|
||||
/* set cache mutex */
|
||||
ldap_pvt_thread_mutex_lock( &cache->c_mutex );
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "====> cache_release_all\n", 0, 0, 0 );
|
||||
|
||||
|
||||
while ( (e = cache->c_lrutail) != NULL && LEI(e)->lei_refcnt == 0 ) {
|
||||
/* delete from cache and lru q */
|
||||
/* XXX do we need rc ? */
|
||||
rc = cache_delete_entry_internal( cache, e );
|
||||
cache_entry_private_destroy( e );
|
||||
entry_free( e );
|
||||
}
|
||||
|
||||
if ( cache->c_cursize ) {
|
||||
Debug( LDAP_DEBUG_TRACE, "Entry-cache could not be emptied\n", 0, 0, 0 );
|
||||
}
|
||||
|
||||
/* free cache mutex */
|
||||
ldap_pvt_thread_mutex_unlock( &cache->c_mutex );
|
||||
}
|
||||
|
||||
#ifdef LDAP_DEBUG
|
||||
#ifdef SLAPD_UNUSED
|
||||
static void
|
||||
lru_print( Cache *cache )
|
||||
{
|
||||
Entry *e;
|
||||
|
||||
fprintf( stderr, "LRU queue (head to tail):\n" );
|
||||
for ( e = cache->c_lruhead; e != NULL; e = LEI(e)->lei_lrunext ) {
|
||||
fprintf( stderr, "\tdn \"%20s\" id %ld refcnt %d\n",
|
||||
e->e_dn, e->e_id, LEI(e)->lei_refcnt );
|
||||
}
|
||||
fprintf( stderr, "LRU queue (tail to head):\n" );
|
||||
for ( e = cache->c_lrutail; e != NULL; e = LEI(e)->lei_lruprev ) {
|
||||
fprintf( stderr, "\tdn \"%20s\" id %ld refcnt %d\n",
|
||||
e->e_dn, e->e_id, LEI(e)->lei_refcnt );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
|
@ -1,43 +0,0 @@
|
|||
/* close.c - close ldbm backend */
|
||||
/* $OpenLDAP$ */
|
||||
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
|
||||
*
|
||||
* Copyright 1998-2006 The OpenLDAP Foundation.
|
||||
* 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>.
|
||||
*/
|
||||
|
||||
#include "portable.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <ac/socket.h>
|
||||
|
||||
#include "slap.h"
|
||||
#include "back-ldbm.h"
|
||||
|
||||
int
|
||||
ldbm_back_db_close( Backend *be )
|
||||
{
|
||||
struct ldbminfo *li = be->be_private;
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "ldbm backend syncing\n", 0, 0, 0 );
|
||||
|
||||
ldbm_cache_flush_all( be );
|
||||
Debug( LDAP_DEBUG_TRACE, "ldbm backend done syncing\n", 0, 0, 0 );
|
||||
|
||||
cache_release_all( &li->li_cache );
|
||||
if ( alock_close( &li->li_alock_info )) {
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"ldbm_back_db_close: alock_close failed\n", 0, 0, 0 );
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1,133 +0,0 @@
|
|||
/* compare.c - ldbm backend compare routine */
|
||||
/* $OpenLDAP$ */
|
||||
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
|
||||
*
|
||||
* Copyright 1998-2006 The OpenLDAP Foundation.
|
||||
* 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>.
|
||||
*/
|
||||
|
||||
#include "portable.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <ac/socket.h>
|
||||
#include <ac/string.h>
|
||||
|
||||
#include "slap.h"
|
||||
#include "back-ldbm.h"
|
||||
#include "proto-back-ldbm.h"
|
||||
|
||||
int
|
||||
ldbm_back_compare(
|
||||
Operation *op,
|
||||
SlapReply *rs )
|
||||
{
|
||||
struct ldbminfo *li = (struct ldbminfo *) op->o_bd->be_private;
|
||||
Entry *matched;
|
||||
Entry *e;
|
||||
Attribute *a;
|
||||
int manageDSAit = get_manageDSAit( op );
|
||||
|
||||
rs->sr_matched = NULL;
|
||||
rs->sr_ref = NULL;
|
||||
|
||||
/* grab giant lock for reading */
|
||||
ldap_pvt_thread_rdwr_rlock(&li->li_giant_rwlock);
|
||||
|
||||
/* get entry with reader lock */
|
||||
e = dn2entry_r( op->o_bd, &op->o_req_ndn, &matched );
|
||||
if ( e == NULL ) {
|
||||
if ( matched != NULL ) {
|
||||
rs->sr_matched = ch_strdup( matched->e_dn );
|
||||
rs->sr_ref = is_entry_referral( matched )
|
||||
? get_entry_referrals( op, matched )
|
||||
: NULL;
|
||||
cache_return_entry_r( &li->li_cache, matched );
|
||||
} else {
|
||||
rs->sr_ref = referral_rewrite( default_referral,
|
||||
NULL, &op->o_req_dn, LDAP_SCOPE_DEFAULT );
|
||||
}
|
||||
|
||||
ldap_pvt_thread_rdwr_runlock(&li->li_giant_rwlock);
|
||||
|
||||
rs->sr_err = LDAP_REFERRAL;
|
||||
goto return_results;
|
||||
}
|
||||
|
||||
if ( !manageDSAit && is_entry_referral( e ) ) {
|
||||
struct berval bv;
|
||||
|
||||
/* entry is a referral, don't allow add */
|
||||
rs->sr_ref = get_entry_referrals( op, e );
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "entry is referral\n", 0,
|
||||
0, 0 );
|
||||
|
||||
|
||||
rs->sr_err = LDAP_REFERRAL;
|
||||
ber_dupbv_x( &bv, &e->e_name, op->o_tmpmemctx );
|
||||
rs->sr_matched = bv.bv_val;
|
||||
|
||||
goto return_results;
|
||||
}
|
||||
|
||||
if ( ! access_allowed( op, e,
|
||||
op->oq_compare.rs_ava->aa_desc, &op->oq_compare.rs_ava->aa_value, ACL_COMPARE, NULL ) )
|
||||
{
|
||||
send_ldap_error( op, rs, LDAP_INSUFFICIENT_ACCESS,
|
||||
NULL );
|
||||
goto return_results;
|
||||
}
|
||||
|
||||
rs->sr_err = LDAP_NO_SUCH_ATTRIBUTE;
|
||||
|
||||
for(a = attrs_find( e->e_attrs, op->oq_compare.rs_ava->aa_desc );
|
||||
a != NULL;
|
||||
a = attrs_find( a->a_next, op->oq_compare.rs_ava->aa_desc ))
|
||||
{
|
||||
rs->sr_err = LDAP_COMPARE_FALSE;
|
||||
|
||||
if ( value_find_ex( op->oq_compare.rs_ava->aa_desc,
|
||||
SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH |
|
||||
SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH,
|
||||
a->a_nvals, &op->oq_compare.rs_ava->aa_value,
|
||||
op->o_tmpmemctx ) == 0 )
|
||||
{
|
||||
rs->sr_err = LDAP_COMPARE_TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return_results:;
|
||||
if ( e ) cache_return_entry_r( &li->li_cache, e );
|
||||
ldap_pvt_thread_rdwr_runlock(&li->li_giant_rwlock);
|
||||
|
||||
send_ldap_result( op, rs );
|
||||
|
||||
switch ( rs->sr_err ) {
|
||||
case LDAP_COMPARE_FALSE:
|
||||
case LDAP_COMPARE_TRUE:
|
||||
rs->sr_err = LDAP_SUCCESS;
|
||||
break;
|
||||
}
|
||||
|
||||
if ( rs->sr_ref != NULL ) {
|
||||
ber_bvarray_free( rs->sr_ref );
|
||||
rs->sr_ref = NULL;
|
||||
}
|
||||
|
||||
if ( rs->sr_matched != NULL ) {
|
||||
op->o_tmpfree( (char *)rs->sr_matched, op->o_tmpmemctx );
|
||||
rs->sr_matched = NULL;
|
||||
}
|
||||
|
||||
return rs->sr_err;
|
||||
}
|
||||
|
|
@ -1,186 +0,0 @@
|
|||
/* config.c - ldbm backend configuration file routine */
|
||||
/* $OpenLDAP$ */
|
||||
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
|
||||
*
|
||||
* Copyright 1998-2006 The OpenLDAP Foundation.
|
||||
* 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>.
|
||||
*/
|
||||
|
||||
#include "portable.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <ac/socket.h>
|
||||
#include <ac/string.h>
|
||||
|
||||
#include "slap.h"
|
||||
#include "back-ldbm.h"
|
||||
#include "lutil.h"
|
||||
|
||||
int
|
||||
ldbm_back_db_config(
|
||||
Backend *be,
|
||||
const char *fname,
|
||||
int lineno,
|
||||
int argc,
|
||||
char **argv
|
||||
)
|
||||
{
|
||||
int rc;
|
||||
struct ldbminfo *li = (struct ldbminfo *) be->be_private;
|
||||
|
||||
if ( li == NULL ) {
|
||||
fprintf( stderr, "%s: line %d: ldbm database info is null!\n",
|
||||
fname, lineno );
|
||||
return( 1 );
|
||||
}
|
||||
|
||||
/* directory where database files live */
|
||||
if ( strcasecmp( argv[0], "directory" ) == 0 ) {
|
||||
if ( argc < 2 ) {
|
||||
fprintf( stderr,
|
||||
"%s: line %d: missing dir in \"directory <dir>\" line\n",
|
||||
fname, lineno );
|
||||
return( 1 );
|
||||
}
|
||||
if ( li->li_directory )
|
||||
free( li->li_directory );
|
||||
li->li_directory = ch_strdup( argv[1] );
|
||||
|
||||
/* mode with which to create new database files */
|
||||
} else if ( strcasecmp( argv[0], "mode" ) == 0 ) {
|
||||
if ( argc < 2 ) {
|
||||
fprintf( stderr,
|
||||
"%s: line %d: missing mode in \"mode <mode>\" line\n",
|
||||
fname, lineno );
|
||||
return( 1 );
|
||||
}
|
||||
if ( lutil_atoix( &li->li_mode, argv[1], 0 ) != 0 ) {
|
||||
fprintf( stderr,
|
||||
"%s: line %d: unable to parse mode=\"%s\" in \"mode <mode>\" line\n",
|
||||
fname, lineno, argv[1] );
|
||||
return( 1 );
|
||||
}
|
||||
|
||||
/* attribute to index */
|
||||
} else if ( strcasecmp( argv[0], "index" ) == 0 ) {
|
||||
if ( argc < 2 ) {
|
||||
fprintf( stderr,
|
||||
"%s: line %d: missing attr in \"index <attr> [pres,eq,approx,sub]\" line\n",
|
||||
fname, lineno );
|
||||
return( 1 );
|
||||
} else if ( argc > 3 ) {
|
||||
fprintf( stderr, "%s: line %d: extra junk "
|
||||
"after \"index <attr> [pres,eq,approx,sub]\" line.\n",
|
||||
fname, lineno );
|
||||
return( 1 );
|
||||
}
|
||||
rc = attr_index_config( li, fname, lineno, argc - 1, &argv[1] );
|
||||
|
||||
if( rc != LDAP_SUCCESS ) return 1;
|
||||
|
||||
/* size of the cache in entries */
|
||||
} else if ( strcasecmp( argv[0], "cachesize" ) == 0 ) {
|
||||
if ( argc < 2 ) {
|
||||
fprintf( stderr,
|
||||
"%s: line %d: missing size in \"cachesize <size>\" line\n",
|
||||
fname, lineno );
|
||||
return( 1 );
|
||||
}
|
||||
if ( lutil_atoi( &li->li_cache.c_maxsize, argv[1] ) != 0 ) {
|
||||
fprintf( stderr,
|
||||
"%s: line %d: unable to parse cachesize \"%s\"\n",
|
||||
fname, lineno, argv[1] );
|
||||
return( 1 );
|
||||
}
|
||||
|
||||
/* size of each dbcache in bytes */
|
||||
} else if ( strcasecmp( argv[0], "dbcachesize" ) == 0 ) {
|
||||
if ( argc < 2 ) {
|
||||
fprintf( stderr,
|
||||
"%s: line %d: missing size in \"dbcachesize <size>\" line\n",
|
||||
fname, lineno );
|
||||
return( 1 );
|
||||
}
|
||||
if ( lutil_atoi( &li->li_dbcachesize, argv[1] ) ) {
|
||||
fprintf( stderr,
|
||||
"%s: line %d: unable to parse dbcachesize \"%s\"\n",
|
||||
fname, lineno, argv[1] );
|
||||
return( 1 );
|
||||
}
|
||||
|
||||
/* no locking (not safe) */
|
||||
} else if ( strcasecmp( argv[0], "dbnolocking" ) == 0 ) {
|
||||
li->li_dblocking = 0;
|
||||
|
||||
/* no write sync (not safe) */
|
||||
} else if ( ( strcasecmp( argv[0], "dbnosync" ) == 0 )
|
||||
|| ( strcasecmp( argv[0], "dbcachenowsync" ) == 0 ) )
|
||||
{
|
||||
li->li_dbwritesync = 0;
|
||||
|
||||
/* run sync thread */
|
||||
} else if ( strcasecmp( argv[0], "dbsync" ) == 0 ) {
|
||||
#ifndef NO_THREADS
|
||||
int i;
|
||||
if ( argc < 2 ) {
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"%s: line %d: missing frquency value in \"dbsync <frequency> [<wait-times> [wait-interval]]\" line\n",
|
||||
fname, lineno, 0 );
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ( lutil_atoi( &i, argv[1] ) != 0 || i < 0 ) {
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"%s: line %d: frquency value (%d) invalid \"dbsync <frequency> [<wait-times> [wait-interval]]\" line\n",
|
||||
fname, lineno, i );
|
||||
return 1;
|
||||
}
|
||||
|
||||
li->li_dbsyncfreq = i;
|
||||
|
||||
if ( argc > 2 ) {
|
||||
if ( lutil_atoi( &i, argv[2] ) != 0 || i < 0 ) {
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"%s: line %d: frquency value (%d) invalid \"dbsync <frequency> [<wait-times> [wait-interval]]\" line\n",
|
||||
fname, lineno, i );
|
||||
return 1;
|
||||
}
|
||||
li ->li_dbsyncwaitn = i;
|
||||
}
|
||||
|
||||
if ( argc > 3 ) {
|
||||
if ( lutil_atoi( &i, argv[3] ) != 0 || i <= 0 ) {
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"%s: line %d: frquency value (%d) invalid \"dbsync <frequency> [<wait-times> [wait-interval]]\" line\n",
|
||||
fname, lineno, i );
|
||||
return 1;
|
||||
}
|
||||
li ->li_dbsyncwaitinterval = i;
|
||||
}
|
||||
|
||||
/* turn off writesync when sync policy is in place */
|
||||
li->li_dbwritesync = 0;
|
||||
|
||||
#else
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"\"dbsync\" policies not supported in non-threaded environments\n", 0, 0, 0);
|
||||
return 1;
|
||||
#endif
|
||||
|
||||
|
||||
/* anything else */
|
||||
} else {
|
||||
return SLAP_CONF_UNKNOWN;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1,356 +0,0 @@
|
|||
/* ldbmcache.c - maintain a cache of open ldbm files */
|
||||
/* $OpenLDAP$ */
|
||||
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
|
||||
*
|
||||
* Copyright 1998-2006 The OpenLDAP Foundation.
|
||||
* 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>.
|
||||
*/
|
||||
|
||||
#include "portable.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <ac/errno.h>
|
||||
#include <ac/socket.h>
|
||||
#include <ac/string.h>
|
||||
#include <ac/time.h>
|
||||
#include <ac/unistd.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "slap.h"
|
||||
#include "back-ldbm.h"
|
||||
#include <ldap_rq.h>
|
||||
|
||||
DBCache *
|
||||
ldbm_cache_open(
|
||||
Backend *be,
|
||||
const char *name,
|
||||
const char *suffix,
|
||||
int flags
|
||||
)
|
||||
{
|
||||
struct ldbminfo *li = (struct ldbminfo *) be->be_private;
|
||||
int i, lru, empty;
|
||||
time_t oldtime;
|
||||
char buf[MAXPATHLEN];
|
||||
#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
|
||||
struct stat st;
|
||||
#endif
|
||||
|
||||
if (li->li_envdirok)
|
||||
sprintf( buf, "%s%s", name, suffix );
|
||||
else
|
||||
sprintf( buf, "%s" LDAP_DIRSEP "%s%s",
|
||||
li->li_directory, name, suffix );
|
||||
|
||||
if( li->li_dblocking ) {
|
||||
flags |= LDBM_LOCKING;
|
||||
} else {
|
||||
flags |= LDBM_NOLOCKING;
|
||||
}
|
||||
|
||||
if( li->li_dbwritesync ) {
|
||||
flags |= LDBM_SYNC;
|
||||
} else {
|
||||
flags |= LDBM_NOSYNC;
|
||||
}
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "=> ldbm_cache_open( \"%s\", %d, %o )\n", buf,
|
||||
flags, li->li_mode );
|
||||
|
||||
|
||||
empty = MAXDBCACHE;
|
||||
|
||||
ldap_pvt_thread_mutex_lock( &li->li_dbcache_mutex );
|
||||
do {
|
||||
lru = 0;
|
||||
oldtime = 1;
|
||||
for ( i = 0; i < MAXDBCACHE; i++ ) {
|
||||
/* see if this slot is free */
|
||||
if ( li->li_dbcache[i].dbc_name == NULL) {
|
||||
if (empty == MAXDBCACHE)
|
||||
empty = i;
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( strcmp( li->li_dbcache[i].dbc_name, buf ) == 0 ) {
|
||||
/* already open - return it */
|
||||
if (li->li_dbcache[i].dbc_flags != flags
|
||||
&& li->li_dbcache[i].dbc_refcnt == 0)
|
||||
{
|
||||
/* we don't want to use an open cache with different
|
||||
* permissions (esp. if we need write but the open
|
||||
* cache is read-only). So close this one if
|
||||
* possible, and re-open below.
|
||||
*
|
||||
* FIXME: what about the case where the refcount
|
||||
* is > 0? right now, we're using it anyway and
|
||||
* just praying. Can there be more than one open
|
||||
* cache to the same db?
|
||||
*
|
||||
* Also, it's really only necessary to compare the
|
||||
* read-only flag, instead of all of the flags,
|
||||
* but for now I'm checking all of them.
|
||||
*/
|
||||
lru = i;
|
||||
empty = MAXDBCACHE;
|
||||
break;
|
||||
}
|
||||
li->li_dbcache[i].dbc_refcnt++;
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"<= ldbm_cache_open (cache %d)\n", i, 0, 0 );
|
||||
|
||||
ldap_pvt_thread_mutex_unlock( &li->li_dbcache_mutex );
|
||||
return( &li->li_dbcache[i] );
|
||||
}
|
||||
|
||||
/* keep track of lru db */
|
||||
if (( li->li_dbcache[i].dbc_refcnt == 0 ) &&
|
||||
(( oldtime == 1 ) ||
|
||||
( li->li_dbcache[i].dbc_lastref < oldtime )) )
|
||||
{
|
||||
lru = i;
|
||||
oldtime = li->li_dbcache[i].dbc_lastref;
|
||||
}
|
||||
}
|
||||
|
||||
i = empty;
|
||||
if ( i == MAXDBCACHE ) {
|
||||
/* no empty slots, not already open - close lru and use that slot */
|
||||
if ( li->li_dbcache[lru].dbc_refcnt == 0 ) {
|
||||
i = lru;
|
||||
ldbm_close( li->li_dbcache[i].dbc_db );
|
||||
free( li->li_dbcache[i].dbc_name );
|
||||
li->li_dbcache[i].dbc_name = NULL;
|
||||
} else {
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"ldbm_cache_open no unused db to close - waiting\n",
|
||||
0, 0, 0 );
|
||||
|
||||
ldap_pvt_thread_cond_wait( &li->li_dbcache_cv,
|
||||
&li->li_dbcache_mutex );
|
||||
/* after waiting for a free slot, go back to square
|
||||
* one: look for an open cache for this db, or an
|
||||
* empty slot, or an unref'ed cache, or wait again.
|
||||
*/
|
||||
}
|
||||
}
|
||||
} while (i == MAXDBCACHE);
|
||||
|
||||
if ( (li->li_dbcache[i].dbc_db = ldbm_open( li->li_dbenv, buf, flags, li->li_mode,
|
||||
li->li_dbcachesize )) == NULL )
|
||||
{
|
||||
int err = errno;
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"<= ldbm_cache_open NULL \"%s\" errno=%d reason=\"%s\")\n",
|
||||
buf, err, err > -1 && err < sys_nerr ?
|
||||
sys_errlist[err] : "unknown" );
|
||||
|
||||
ldap_pvt_thread_mutex_unlock( &li->li_dbcache_mutex );
|
||||
return( NULL );
|
||||
}
|
||||
li->li_dbcache[i].dbc_name = ch_strdup( buf );
|
||||
li->li_dbcache[i].dbc_refcnt = 1;
|
||||
li->li_dbcache[i].dbc_lastref = slap_get_time();
|
||||
li->li_dbcache[i].dbc_flags = flags;
|
||||
li->li_dbcache[i].dbc_dirty = 0;
|
||||
#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
|
||||
if ( stat( buf, &st ) == 0 ) {
|
||||
li->li_dbcache[i].dbc_blksize = st.st_blksize;
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
li->li_dbcache[i].dbc_blksize = DEFAULT_BLOCKSIZE;
|
||||
}
|
||||
li->li_dbcache[i].dbc_maxids = (li->li_dbcache[i].dbc_blksize /
|
||||
sizeof(ID)) - ID_BLOCK_IDS_OFFSET;
|
||||
li->li_dbcache[i].dbc_maxindirect = ( SLAPD_LDBM_MIN_MAXIDS /
|
||||
li->li_dbcache[i].dbc_maxids ) + 1;
|
||||
|
||||
assert( li->li_dbcache[i].dbc_maxindirect < 256 );
|
||||
|
||||
Debug( LDAP_DEBUG_ARGS,
|
||||
"ldbm_cache_open (blksize %ld) (maxids %d) (maxindirect %d)\n",
|
||||
li->li_dbcache[i].dbc_blksize, li->li_dbcache[i].dbc_maxids,
|
||||
li->li_dbcache[i].dbc_maxindirect );
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "<= ldbm_cache_open (opened %d)\n", i, 0, 0 );
|
||||
|
||||
ldap_pvt_thread_mutex_init( &li->li_dbcache[i].dbc_write_mutex );
|
||||
|
||||
ldap_pvt_thread_mutex_unlock( &li->li_dbcache_mutex );
|
||||
return( &li->li_dbcache[i] );
|
||||
}
|
||||
|
||||
void
|
||||
ldbm_cache_close( Backend *be, DBCache *db )
|
||||
{
|
||||
struct ldbminfo *li = (struct ldbminfo *) be->be_private;
|
||||
|
||||
if( li->li_dbwritesync && db->dbc_dirty ) {
|
||||
ldbm_sync( db->dbc_db );
|
||||
db->dbc_dirty = 0;
|
||||
}
|
||||
|
||||
ldap_pvt_thread_mutex_lock( &li->li_dbcache_mutex );
|
||||
if ( --db->dbc_refcnt <= 0 ) {
|
||||
db->dbc_refcnt = 0;
|
||||
ldap_pvt_thread_cond_signal( &li->li_dbcache_cv );
|
||||
}
|
||||
ldap_pvt_thread_mutex_unlock( &li->li_dbcache_mutex );
|
||||
}
|
||||
|
||||
void
|
||||
ldbm_cache_really_close( Backend *be, DBCache *db )
|
||||
{
|
||||
struct ldbminfo *li = (struct ldbminfo *) be->be_private;
|
||||
|
||||
ldap_pvt_thread_mutex_lock( &li->li_dbcache_mutex );
|
||||
if ( --db->dbc_refcnt <= 0 ) {
|
||||
db->dbc_refcnt = 0;
|
||||
ldap_pvt_thread_cond_signal( &li->li_dbcache_cv );
|
||||
ldbm_close( db->dbc_db );
|
||||
free( db->dbc_name );
|
||||
db->dbc_name = NULL;
|
||||
ldap_pvt_thread_mutex_destroy( &db->dbc_write_mutex );
|
||||
}
|
||||
ldap_pvt_thread_mutex_unlock( &li->li_dbcache_mutex );
|
||||
}
|
||||
|
||||
void
|
||||
ldbm_cache_flush_all( Backend *be )
|
||||
{
|
||||
struct ldbminfo *li = (struct ldbminfo *) be->be_private;
|
||||
int i;
|
||||
|
||||
ldap_pvt_thread_mutex_lock( &li->li_dbcache_mutex );
|
||||
for ( i = 0; i < MAXDBCACHE; i++ ) {
|
||||
if ( li->li_dbcache[i].dbc_name != NULL ) {
|
||||
Debug( LDAP_DEBUG_TRACE, "ldbm flushing db (%s)\n",
|
||||
li->li_dbcache[i].dbc_name, 0, 0 );
|
||||
|
||||
ldbm_sync( li->li_dbcache[i].dbc_db );
|
||||
li->li_dbcache[i].dbc_dirty = 0;
|
||||
if ( li->li_dbcache[i].dbc_refcnt != 0 ) {
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"refcnt = %d, couldn't close db (%s)\n",
|
||||
li->li_dbcache[i].dbc_refcnt,
|
||||
li->li_dbcache[i].dbc_name, 0 );
|
||||
|
||||
} else {
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"ldbm closing db (%s)\n",
|
||||
li->li_dbcache[i].dbc_name, 0, 0 );
|
||||
|
||||
ldap_pvt_thread_cond_signal( &li->li_dbcache_cv );
|
||||
ldbm_close( li->li_dbcache[i].dbc_db );
|
||||
free( li->li_dbcache[i].dbc_name );
|
||||
li->li_dbcache[i].dbc_name = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
ldap_pvt_thread_mutex_unlock( &li->li_dbcache_mutex );
|
||||
}
|
||||
|
||||
void
|
||||
ldbm_cache_sync( Backend *be )
|
||||
{
|
||||
struct ldbminfo *li = (struct ldbminfo *) be->be_private;
|
||||
int i;
|
||||
int do_log = 1;
|
||||
|
||||
ldap_pvt_thread_mutex_lock( &li->li_dbcache_mutex );
|
||||
for ( i = 0; i < MAXDBCACHE; i++ ) {
|
||||
if ( li->li_dbcache[i].dbc_name != NULL && li->li_dbcache[i].dbc_dirty ) {
|
||||
if ( do_log ) {
|
||||
do_log = 0;
|
||||
Debug( LDAP_DEBUG_TRACE, "syncing %s\n",
|
||||
li->li_directory, 0, 0 );
|
||||
}
|
||||
Debug( LDAP_DEBUG_TRACE, "ldbm syncing db (%s)\n",
|
||||
li->li_dbcache[i].dbc_name, 0, 0 );
|
||||
ldbm_sync( li->li_dbcache[i].dbc_db );
|
||||
li->li_dbcache[i].dbc_dirty = 0;
|
||||
}
|
||||
}
|
||||
ldap_pvt_thread_mutex_unlock( &li->li_dbcache_mutex );
|
||||
}
|
||||
|
||||
#if 0 /* macro in proto-back-ldbm.h */
|
||||
Datum
|
||||
ldbm_cache_fetch(
|
||||
DBCache *db,
|
||||
Datum key
|
||||
)
|
||||
{
|
||||
return ldbm_fetch( db->dbc_db, key );
|
||||
}
|
||||
#endif /* 0 */
|
||||
|
||||
int
|
||||
ldbm_cache_store(
|
||||
DBCache *db,
|
||||
Datum key,
|
||||
Datum data,
|
||||
int flags
|
||||
)
|
||||
{
|
||||
int rc;
|
||||
|
||||
db->dbc_dirty = 1;
|
||||
rc = ldbm_store( db->dbc_db, key, data, flags );
|
||||
|
||||
return( rc );
|
||||
}
|
||||
|
||||
int
|
||||
ldbm_cache_delete(
|
||||
DBCache *db,
|
||||
Datum key
|
||||
)
|
||||
{
|
||||
int rc;
|
||||
|
||||
db->dbc_dirty = 1;
|
||||
rc = ldbm_delete( db->dbc_db, key );
|
||||
|
||||
return( rc );
|
||||
}
|
||||
|
||||
void *
|
||||
ldbm_cache_sync_daemon(
|
||||
void *ctx,
|
||||
void *arg
|
||||
)
|
||||
{
|
||||
struct re_s *rtask = arg;
|
||||
Backend *be = rtask->arg;
|
||||
struct ldbminfo *li = (struct ldbminfo *) be->be_private;
|
||||
|
||||
/* If server is idle, or we've already waited the limit */
|
||||
if ( li->li_dbsyncwaitcount == li->li_dbsyncwaitn ||
|
||||
ldap_pvt_thread_pool_backload(&connection_pool) < 2 ) {
|
||||
rtask->interval.tv_sec = li->li_dbsyncfreq;
|
||||
li->li_dbsyncwaitcount = 0;
|
||||
ldbm_cache_sync( be );
|
||||
} else {
|
||||
rtask->interval.tv_sec = li->li_dbsyncwaitinterval;
|
||||
li->li_dbsyncwaitcount++;
|
||||
Debug( LDAP_DEBUG_TRACE, "delay #%d syncing %s\n",
|
||||
li->li_dbsyncwaitcount, li->li_directory, 0 );
|
||||
}
|
||||
|
||||
ldap_pvt_thread_mutex_lock( &slapd_rq.rq_mutex );
|
||||
ldap_pvt_runqueue_stoptask( &slapd_rq, rtask );
|
||||
ldap_pvt_runqueue_resched( &slapd_rq, rtask, 0 );
|
||||
ldap_pvt_thread_mutex_unlock( &slapd_rq.rq_mutex );
|
||||
return NULL;
|
||||
}
|
||||
|
|
@ -1,223 +0,0 @@
|
|||
/* delete.c - ldbm backend delete routine */
|
||||
/* $OpenLDAP$ */
|
||||
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
|
||||
*
|
||||
* Copyright 1998-2006 The OpenLDAP Foundation.
|
||||
* 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>.
|
||||
*/
|
||||
|
||||
#include "portable.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <ac/string.h>
|
||||
#include <ac/socket.h>
|
||||
|
||||
#include "slap.h"
|
||||
#include "back-ldbm.h"
|
||||
#include "proto-back-ldbm.h"
|
||||
#include "lutil.h"
|
||||
|
||||
int
|
||||
ldbm_back_delete(
|
||||
Operation *op,
|
||||
SlapReply *rs )
|
||||
{
|
||||
struct ldbminfo *li = (struct ldbminfo *) op->o_bd->be_private;
|
||||
Entry *matched;
|
||||
struct berval pdn;
|
||||
Entry *e, *p = NULL;
|
||||
int rc = -1;
|
||||
int manageDSAit = get_manageDSAit( op );
|
||||
AttributeDescription *children = slap_schema.si_ad_children;
|
||||
AttributeDescription *entry = slap_schema.si_ad_entry;
|
||||
|
||||
Debug(LDAP_DEBUG_ARGS, "==> ldbm_back_delete: %s\n", op->o_req_dn.bv_val, 0, 0);
|
||||
|
||||
/* grab giant lock for writing */
|
||||
ldap_pvt_thread_rdwr_wlock(&li->li_giant_rwlock);
|
||||
|
||||
/* allocate CSN */
|
||||
if ( BER_BVISEMPTY( &op->o_csn )) {
|
||||
struct berval csn;
|
||||
char csnbuf[LDAP_LUTIL_CSNSTR_BUFSIZE];
|
||||
|
||||
csn.bv_val = csnbuf;
|
||||
csn.bv_len = sizeof(csnbuf);
|
||||
slap_get_csn( op, &csn, 1 );
|
||||
}
|
||||
|
||||
/* get entry with writer lock */
|
||||
e = dn2entry_w( op->o_bd, &op->o_req_ndn, &matched );
|
||||
|
||||
/* FIXME : dn2entry() should return non-glue entry */
|
||||
if ( e == NULL || ( !manageDSAit && is_entry_glue( e ))) {
|
||||
Debug(LDAP_DEBUG_ARGS, "<=- ldbm_back_delete: no such object %s\n",
|
||||
op->o_req_dn.bv_val, 0, 0);
|
||||
|
||||
if ( matched != NULL ) {
|
||||
rs->sr_matched = ch_strdup( matched->e_dn );
|
||||
rs->sr_ref = is_entry_referral( matched )
|
||||
? get_entry_referrals( op, matched )
|
||||
: NULL;
|
||||
cache_return_entry_r( &li->li_cache, matched );
|
||||
|
||||
} else {
|
||||
rs->sr_ref = referral_rewrite( default_referral, NULL,
|
||||
&op->o_req_dn, LDAP_SCOPE_DEFAULT );
|
||||
}
|
||||
|
||||
rs->sr_err = LDAP_REFERRAL;
|
||||
rs->sr_flags |= REP_MATCHED_MUSTBEFREED | REP_REF_MUSTBEFREED;
|
||||
goto return_results;
|
||||
}
|
||||
|
||||
/* check entry for "entry" acl */
|
||||
if ( ! access_allowed( op, e, entry, NULL, ACL_WDEL, NULL ) )
|
||||
{
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"<=- ldbm_back_delete: no write access to entry\n", 0,
|
||||
0, 0 );
|
||||
|
||||
rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
|
||||
rs->sr_text = "no write access to entry";
|
||||
goto return_results;
|
||||
}
|
||||
|
||||
if ( !manageDSAit && is_entry_referral( e ) ) {
|
||||
/* parent is a referral, don't allow add */
|
||||
/* parent is an alias, don't allow add */
|
||||
rs->sr_ref = get_entry_referrals( op, e );
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "entry is referral\n", 0,
|
||||
0, 0 );
|
||||
|
||||
rs->sr_err = LDAP_REFERRAL;
|
||||
rs->sr_matched = ch_strdup( e->e_name.bv_val );
|
||||
rs->sr_flags = REP_MATCHED_MUSTBEFREED | REP_REF_MUSTBEFREED;
|
||||
goto return_results;
|
||||
}
|
||||
|
||||
if ( has_children( op->o_bd, e ) ) {
|
||||
Debug(LDAP_DEBUG_ARGS, "<=- ldbm_back_delete: non leaf %s\n",
|
||||
op->o_req_dn.bv_val, 0, 0);
|
||||
|
||||
rs->sr_err = LDAP_NOT_ALLOWED_ON_NONLEAF;
|
||||
rs->sr_text = "subordinate objects must be deleted first";
|
||||
goto return_results;
|
||||
}
|
||||
|
||||
/* delete from parent's id2children entry */
|
||||
if( !be_issuffix( op->o_bd, &e->e_nname ) && (dnParent( &e->e_nname, &pdn ),
|
||||
pdn.bv_len) ) {
|
||||
if( (p = dn2entry_w( op->o_bd, &pdn, NULL )) == NULL) {
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"<=- ldbm_back_delete: parent does not exist\n",
|
||||
0, 0, 0);
|
||||
|
||||
rs->sr_err = LDAP_OTHER;
|
||||
rs->sr_text = "could not locate parent of entry";
|
||||
goto return_results;
|
||||
}
|
||||
|
||||
/* check parent for "children" acl */
|
||||
if ( ! access_allowed( op, p,
|
||||
children, NULL, ACL_WDEL, NULL ) )
|
||||
{
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"<=- ldbm_back_delete: no access to parent\n", 0,
|
||||
0, 0 );
|
||||
|
||||
rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
|
||||
rs->sr_text = "no write access to parent";
|
||||
goto return_results;
|
||||
}
|
||||
|
||||
} else {
|
||||
/* no parent, must be root to delete */
|
||||
if( ! be_isroot( op ) ) {
|
||||
if ( be_issuffix( op->o_bd, (struct berval *)&slap_empty_bv )
|
||||
|| be_shadow_update( op ) ) {
|
||||
p = (Entry *)&slap_entry_root;
|
||||
|
||||
rc = access_allowed( op, p,
|
||||
children, NULL, ACL_WDEL, NULL );
|
||||
p = NULL;
|
||||
|
||||
/* check parent for "children" acl */
|
||||
if ( ! rc ) {
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"<=- ldbm_back_delete: no "
|
||||
"access to parent\n", 0, 0, 0 );
|
||||
|
||||
rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
|
||||
rs->sr_text = "no write access to parent";
|
||||
goto return_results;
|
||||
}
|
||||
|
||||
} else {
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"<=- ldbm_back_delete: no parent & "
|
||||
"not root\n", 0, 0, 0);
|
||||
|
||||
rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
|
||||
goto return_results;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* delete from dn2id mapping */
|
||||
if ( dn2id_delete( op->o_bd, &e->e_nname, e->e_id ) != 0 ) {
|
||||
Debug(LDAP_DEBUG_ARGS,
|
||||
"<=- ldbm_back_delete: operations error %s\n",
|
||||
op->o_req_dn.bv_val, 0, 0);
|
||||
|
||||
rs->sr_err = LDAP_OTHER;
|
||||
rs->sr_text = "DN index delete failed";
|
||||
goto return_results;
|
||||
}
|
||||
|
||||
/* delete from disk and cache */
|
||||
if ( id2entry_delete( op->o_bd, e ) != 0 ) {
|
||||
Debug(LDAP_DEBUG_ARGS,
|
||||
"<=- ldbm_back_delete: operations error %s\n",
|
||||
op->o_req_dn.bv_val, 0, 0);
|
||||
|
||||
rs->sr_err = LDAP_OTHER;
|
||||
rs->sr_text = "entry delete failed";
|
||||
goto return_results;
|
||||
}
|
||||
|
||||
/* delete attribute indices */
|
||||
(void) index_entry_del( op, e );
|
||||
|
||||
rs->sr_err = LDAP_SUCCESS;
|
||||
|
||||
return_results:;
|
||||
rc = rs->sr_err;
|
||||
|
||||
if( p != NULL ) {
|
||||
/* free parent and writer lock */
|
||||
cache_return_entry_w( &li->li_cache, p );
|
||||
}
|
||||
|
||||
if ( e != NULL ) {
|
||||
/* free entry and writer lock */
|
||||
cache_return_entry_w( &li->li_cache, e );
|
||||
}
|
||||
|
||||
ldap_pvt_thread_rdwr_wunlock(&li->li_giant_rwlock);
|
||||
|
||||
send_ldap_result( op, rs );
|
||||
slap_graduate_commit_csn( op );
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
|
@ -1,371 +0,0 @@
|
|||
/* dn2id.c - routines to deal with the dn2id index */
|
||||
/* $OpenLDAP$ */
|
||||
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
|
||||
*
|
||||
* Copyright 1998-2006 The OpenLDAP Foundation.
|
||||
* 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>.
|
||||
*/
|
||||
|
||||
#include "portable.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <ac/string.h>
|
||||
#include <ac/socket.h>
|
||||
|
||||
#include "slap.h"
|
||||
#include "back-ldbm.h"
|
||||
#include "proto-back-ldbm.h"
|
||||
|
||||
int
|
||||
dn2id_add(
|
||||
Backend *be,
|
||||
struct berval *dn,
|
||||
ID id
|
||||
)
|
||||
{
|
||||
int rc, flags;
|
||||
DBCache *db;
|
||||
Datum key, data;
|
||||
char *buf;
|
||||
struct berval ptr, pdn;
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "=> dn2id_add( \"%s\", %ld )\n", dn->bv_val, id, 0 );
|
||||
|
||||
assert( id != NOID );
|
||||
|
||||
db = ldbm_cache_open( be, "dn2id", LDBM_SUFFIX, LDBM_WRCREAT );
|
||||
if ( db == NULL ) {
|
||||
Debug( LDAP_DEBUG_ANY, "Could not open/create dn2id%s\n",
|
||||
LDBM_SUFFIX, 0, 0 );
|
||||
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
ldbm_datum_init( key );
|
||||
key.dsize = dn->bv_len + 2;
|
||||
buf = ch_malloc( key.dsize );
|
||||
key.dptr = buf;
|
||||
buf[0] = DN_BASE_PREFIX;
|
||||
ptr.bv_val = buf + 1;
|
||||
ptr.bv_len = dn->bv_len;
|
||||
AC_MEMCPY( ptr.bv_val, dn->bv_val, dn->bv_len );
|
||||
ptr.bv_val[ dn->bv_len ] = '\0';
|
||||
|
||||
ldbm_datum_init( data );
|
||||
data.dptr = (char *) &id;
|
||||
data.dsize = sizeof(ID);
|
||||
|
||||
flags = LDBM_INSERT;
|
||||
rc = ldbm_cache_store( db, key, data, flags );
|
||||
|
||||
if ( rc != -1 && !be_issuffix( be, &ptr )) {
|
||||
buf[0] = DN_SUBTREE_PREFIX;
|
||||
ldap_pvt_thread_mutex_lock( &db->dbc_write_mutex );
|
||||
rc = idl_insert_key( be, db, key, id );
|
||||
ldap_pvt_thread_mutex_unlock( &db->dbc_write_mutex );
|
||||
|
||||
if ( rc != -1 ) {
|
||||
dnParent( &ptr, &pdn );
|
||||
|
||||
pdn.bv_val[-1] = DN_ONE_PREFIX;
|
||||
key.dsize = pdn.bv_len + 2;
|
||||
key.dptr = pdn.bv_val - 1;
|
||||
ptr = pdn;
|
||||
ldap_pvt_thread_mutex_lock( &db->dbc_write_mutex );
|
||||
rc = idl_insert_key( be, db, key, id );
|
||||
ldap_pvt_thread_mutex_unlock( &db->dbc_write_mutex );
|
||||
}
|
||||
}
|
||||
|
||||
while ( rc != -1 && !be_issuffix( be, &ptr )) {
|
||||
ptr.bv_val[-1] = DN_SUBTREE_PREFIX;
|
||||
|
||||
ldap_pvt_thread_mutex_lock( &db->dbc_write_mutex );
|
||||
rc = idl_insert_key( be, db, key, id );
|
||||
ldap_pvt_thread_mutex_unlock( &db->dbc_write_mutex );
|
||||
|
||||
if( rc != 0 ) break;
|
||||
dnParent( &ptr, &pdn );
|
||||
key.dsize = pdn.bv_len + 2;
|
||||
key.dptr = pdn.bv_val - 1;
|
||||
ptr = pdn;
|
||||
}
|
||||
|
||||
free( buf );
|
||||
ldbm_cache_close( be, db );
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "<= dn2id_add %d\n", rc, 0, 0 );
|
||||
|
||||
return( rc );
|
||||
}
|
||||
|
||||
int
|
||||
dn2id(
|
||||
Backend *be,
|
||||
struct berval *dn,
|
||||
ID *idp
|
||||
)
|
||||
{
|
||||
struct ldbminfo *li = (struct ldbminfo *) be->be_private;
|
||||
DBCache *db;
|
||||
Datum key, data;
|
||||
unsigned char *tmp;
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "=> dn2id( \"%s\" )\n", dn->bv_val, 0, 0 );
|
||||
|
||||
assert( idp != NULL );
|
||||
|
||||
/* first check the cache */
|
||||
*idp = cache_find_entry_ndn2id( be, &li->li_cache, dn );
|
||||
if ( *idp != NOID ) {
|
||||
Debug( LDAP_DEBUG_TRACE, "<= dn2id %ld (in cache)\n", *idp,
|
||||
0, 0 );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
db = ldbm_cache_open( be, "dn2id", LDBM_SUFFIX, LDBM_WRCREAT );
|
||||
if ( db == NULL ) {
|
||||
Debug( LDAP_DEBUG_ANY, "<= dn2id could not open dn2id%s\n",
|
||||
LDBM_SUFFIX, 0, 0 );
|
||||
/*
|
||||
* return code !0 if ldbm cache open failed;
|
||||
* callers should handle this
|
||||
*/
|
||||
*idp = NOID;
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
ldbm_datum_init( key );
|
||||
|
||||
key.dsize = dn->bv_len + 2;
|
||||
key.dptr = ch_malloc( key.dsize );
|
||||
tmp = (unsigned char *)key.dptr;
|
||||
tmp[0] = DN_BASE_PREFIX;
|
||||
tmp++;
|
||||
AC_MEMCPY( tmp, dn->bv_val, dn->bv_len );
|
||||
tmp[dn->bv_len] = '\0';
|
||||
|
||||
data = ldbm_cache_fetch( db, key );
|
||||
|
||||
ldbm_cache_close( be, db );
|
||||
|
||||
free( key.dptr );
|
||||
|
||||
if ( data.dptr == NULL ) {
|
||||
Debug( LDAP_DEBUG_TRACE, "<= dn2id NOID\n", 0, 0, 0 );
|
||||
|
||||
*idp = NOID;
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
AC_MEMCPY( (char *) idp, data.dptr, sizeof(ID) );
|
||||
|
||||
assert( *idp != NOID );
|
||||
|
||||
ldbm_datum_free( db->dbc_db, data );
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "<= dn2id %ld\n", *idp, 0, 0 );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
int
|
||||
dn2idl(
|
||||
Backend *be,
|
||||
struct berval *dn,
|
||||
int prefix,
|
||||
ID_BLOCK **idlp
|
||||
)
|
||||
{
|
||||
DBCache *db;
|
||||
Datum key;
|
||||
unsigned char *tmp;
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "=> dn2idl( \"%c%s\" )\n", prefix, dn->bv_val, 0 );
|
||||
|
||||
assert( idlp != NULL );
|
||||
*idlp = NULL;
|
||||
|
||||
if ( prefix == DN_SUBTREE_PREFIX && be_issuffix(be, dn) ) {
|
||||
*idlp = idl_allids( be );
|
||||
return 0;
|
||||
}
|
||||
|
||||
db = ldbm_cache_open( be, "dn2id", LDBM_SUFFIX, LDBM_WRCREAT );
|
||||
if ( db == NULL ) {
|
||||
Debug( LDAP_DEBUG_ANY, "<= dn2idl could not open dn2id%s\n",
|
||||
LDBM_SUFFIX, 0, 0 );
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
ldbm_datum_init( key );
|
||||
|
||||
key.dsize = dn->bv_len + 2;
|
||||
key.dptr = ch_malloc( key.dsize );
|
||||
tmp = (unsigned char *)key.dptr;
|
||||
tmp[0] = prefix;
|
||||
tmp++;
|
||||
AC_MEMCPY( tmp, dn->bv_val, dn->bv_len );
|
||||
tmp[dn->bv_len] = '\0';
|
||||
|
||||
*idlp = idl_fetch( be, db, key );
|
||||
|
||||
ldbm_cache_close( be, db );
|
||||
|
||||
free( key.dptr );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
dn2id_delete(
|
||||
Backend *be,
|
||||
struct berval *dn,
|
||||
ID id
|
||||
)
|
||||
{
|
||||
DBCache *db;
|
||||
Datum key;
|
||||
int rc;
|
||||
char *buf;
|
||||
struct berval ptr, pdn;
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "=> dn2id_delete( \"%s\", %ld )\n", dn->bv_val, id, 0 );
|
||||
|
||||
|
||||
assert( id != NOID );
|
||||
|
||||
db = ldbm_cache_open( be, "dn2id", LDBM_SUFFIX, LDBM_WRCREAT );
|
||||
if ( db == NULL ) {
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"<= dn2id_delete could not open dn2id%s\n", LDBM_SUFFIX,
|
||||
0, 0 );
|
||||
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
ldbm_datum_init( key );
|
||||
key.dsize = dn->bv_len + 2;
|
||||
buf = ch_malloc( key.dsize );
|
||||
key.dptr = buf;
|
||||
buf[0] = DN_BASE_PREFIX;
|
||||
ptr.bv_val = buf + 1;
|
||||
ptr.bv_len = dn->bv_len;
|
||||
AC_MEMCPY( ptr.bv_val, dn->bv_val, dn->bv_len );
|
||||
ptr.bv_val[dn->bv_len] = '\0';
|
||||
|
||||
rc = ldbm_cache_delete( db, key );
|
||||
|
||||
if( !be_issuffix( be, &ptr )) {
|
||||
buf[0] = DN_SUBTREE_PREFIX;
|
||||
ldap_pvt_thread_mutex_lock( &db->dbc_write_mutex );
|
||||
(void) idl_delete_key( be, db, key, id );
|
||||
ldap_pvt_thread_mutex_unlock( &db->dbc_write_mutex );
|
||||
|
||||
dnParent( &ptr, &pdn );
|
||||
|
||||
pdn.bv_val[-1] = DN_ONE_PREFIX;
|
||||
key.dsize = pdn.bv_len + 2;
|
||||
key.dptr = pdn.bv_val - 1;
|
||||
ptr = pdn;
|
||||
|
||||
ldap_pvt_thread_mutex_lock( &db->dbc_write_mutex );
|
||||
(void) idl_delete_key( be, db, key, id );
|
||||
ldap_pvt_thread_mutex_unlock( &db->dbc_write_mutex );
|
||||
}
|
||||
|
||||
while ( rc != -1 && !be_issuffix( be, &ptr )) {
|
||||
ptr.bv_val[-1] = DN_SUBTREE_PREFIX;
|
||||
|
||||
ldap_pvt_thread_mutex_lock( &db->dbc_write_mutex );
|
||||
(void) idl_delete_key( be, db, key, id );
|
||||
ldap_pvt_thread_mutex_unlock( &db->dbc_write_mutex );
|
||||
|
||||
dnParent( &ptr, &pdn );
|
||||
key.dsize = pdn.bv_len + 2;
|
||||
key.dptr = pdn.bv_val - 1;
|
||||
ptr = pdn;
|
||||
}
|
||||
|
||||
free( buf );
|
||||
|
||||
ldbm_cache_close( be, db );
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "<= dn2id_delete %d\n", rc, 0, 0 );
|
||||
|
||||
return( rc );
|
||||
}
|
||||
|
||||
/*
|
||||
* dn2entry - look up dn in the cache/indexes and return the corresponding
|
||||
* entry.
|
||||
*/
|
||||
|
||||
Entry *
|
||||
dn2entry_rw(
|
||||
Backend *be,
|
||||
struct berval *dn,
|
||||
Entry **matched,
|
||||
int rw
|
||||
)
|
||||
{
|
||||
ID id;
|
||||
Entry *e = NULL;
|
||||
struct berval pdn;
|
||||
|
||||
Debug(LDAP_DEBUG_TRACE, "dn2entry_%s: dn: \"%s\"\n",
|
||||
rw ? "w" : "r", dn->bv_val, 0);
|
||||
|
||||
|
||||
if( matched != NULL ) {
|
||||
/* caller cares about match */
|
||||
*matched = NULL;
|
||||
}
|
||||
|
||||
if ( dn2id( be, dn, &id ) ) {
|
||||
/* something bad happened to ldbm cache */
|
||||
return( NULL );
|
||||
|
||||
}
|
||||
|
||||
if ( id != NOID ) {
|
||||
/* try to return the entry */
|
||||
if ((e = id2entry_rw( be, id, rw )) != NULL ) {
|
||||
return( e );
|
||||
}
|
||||
|
||||
Debug(LDAP_DEBUG_ANY,
|
||||
"dn2entry_%s: no entry for valid id (%ld), dn \"%s\"\n",
|
||||
rw ? "w" : "r", id, dn->bv_val);
|
||||
|
||||
/* must have been deleted from underneath us */
|
||||
/* treat as if NOID was found */
|
||||
}
|
||||
|
||||
/* caller doesn't care about match */
|
||||
if( matched == NULL ) return NULL;
|
||||
|
||||
/* entry does not exist - see how much of the dn does exist */
|
||||
if ( !be_issuffix( be, dn ) && (dnParent( dn, &pdn ), pdn.bv_len) ) {
|
||||
/* get entry with reader lock */
|
||||
if ((e = dn2entry_r( be, &pdn, matched )) != NULL )
|
||||
{
|
||||
*matched = e;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
@ -1,140 +0,0 @@
|
|||
/* entry.c - ldbm backend entry_release routine */
|
||||
/* $OpenLDAP$ */
|
||||
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
|
||||
*
|
||||
* Copyright 1998-2006 The OpenLDAP Foundation.
|
||||
* 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>.
|
||||
*/
|
||||
|
||||
#include "portable.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <ac/socket.h>
|
||||
#include <ac/string.h>
|
||||
|
||||
#include "slap.h"
|
||||
#include "back-ldbm.h"
|
||||
#include "proto-back-ldbm.h"
|
||||
|
||||
|
||||
int
|
||||
ldbm_back_entry_release_rw(
|
||||
Operation *op,
|
||||
Entry *e,
|
||||
int rw
|
||||
)
|
||||
{
|
||||
struct ldbminfo *li = (struct ldbminfo *) op->o_bd->be_private;
|
||||
|
||||
if ( slapMode == SLAP_SERVER_MODE ) {
|
||||
/* free entry and reader or writer lock */
|
||||
cache_return_entry_rw( &li->li_cache, e, rw );
|
||||
/* only do_add calls here with a write lock.
|
||||
* get_entry doesn't obtain the giant lock, because its
|
||||
* caller has already obtained it.
|
||||
*/
|
||||
if( rw ) {
|
||||
ldap_pvt_thread_rdwr_wunlock( &li->li_giant_rwlock );
|
||||
}
|
||||
#if 0
|
||||
else {
|
||||
ldap_pvt_thread_rdwr_runlock( &li->li_giant_rwlock );
|
||||
}
|
||||
#endif
|
||||
|
||||
} else {
|
||||
if ( e->e_private ) {
|
||||
free( e->e_private );
|
||||
e->e_private = NULL;
|
||||
}
|
||||
entry_free( e );
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* return LDAP_SUCCESS IFF we can retrieve the specified entry.
|
||||
*/
|
||||
int ldbm_back_entry_get(
|
||||
Operation *op,
|
||||
struct berval *ndn,
|
||||
ObjectClass *oc,
|
||||
AttributeDescription *at,
|
||||
int rw,
|
||||
Entry **ent )
|
||||
{
|
||||
struct ldbminfo *li = (struct ldbminfo *) op->o_bd->be_private;
|
||||
Entry *e;
|
||||
int rc;
|
||||
const char *at_name = at ? at->ad_cname.bv_val : "(null)";
|
||||
|
||||
Debug( LDAP_DEBUG_ARGS,
|
||||
"=> ldbm_back_entry_get: ndn: \"%s\"\n", ndn->bv_val, 0, 0 );
|
||||
Debug( LDAP_DEBUG_ARGS,
|
||||
"=> ldbm_back_entry_get: oc: \"%s\", at: \"%s\"\n",
|
||||
oc ? oc->soc_cname.bv_val : "(null)", at_name, 0);
|
||||
|
||||
/* don't grab the giant lock - our caller has already gotten it. */
|
||||
|
||||
/* can we find entry */
|
||||
e = dn2entry_rw( op->o_bd, ndn, NULL, rw );
|
||||
if (e == NULL) {
|
||||
Debug( LDAP_DEBUG_ACL,
|
||||
"=> ldbm_back_entry_get: cannot find entry: \"%s\"\n",
|
||||
ndn->bv_val, 0, 0 );
|
||||
return LDAP_NO_SUCH_OBJECT;
|
||||
}
|
||||
|
||||
Debug( LDAP_DEBUG_ACL,
|
||||
"=> ldbm_back_entry_get: found entry: \"%s\"\n",
|
||||
ndn->bv_val, 0, 0 );
|
||||
|
||||
#ifdef BDB_ALIASES
|
||||
/* find attribute values */
|
||||
if( is_entry_alias( e ) ) {
|
||||
Debug( LDAP_DEBUG_ACL,
|
||||
"<= ldbm_back_entry_get: entry is an alias\n", 0, 0, 0 );
|
||||
rc = LDAP_ALIAS_PROBLEM;
|
||||
goto return_results;
|
||||
}
|
||||
#endif
|
||||
|
||||
if( is_entry_referral( e ) ) {
|
||||
Debug( LDAP_DEBUG_ACL,
|
||||
"<= ldbm_back_entry_get: entry is a referral\n", 0, 0, 0 );
|
||||
rc = LDAP_REFERRAL;
|
||||
goto return_results;
|
||||
}
|
||||
|
||||
if ( oc && !is_entry_objectclass( e, oc, 0 )) {
|
||||
Debug( LDAP_DEBUG_ACL,
|
||||
"<= ldbm_back_entry_get: failed to find objectClass %s\n",
|
||||
oc->soc_cname.bv_val, 0, 0 );
|
||||
rc = LDAP_NO_SUCH_ATTRIBUTE;
|
||||
goto return_results;
|
||||
}
|
||||
|
||||
rc = LDAP_SUCCESS;
|
||||
|
||||
return_results:
|
||||
if( rc != LDAP_SUCCESS ) {
|
||||
/* free entry */
|
||||
cache_return_entry_rw(&li->li_cache, e, rw);
|
||||
} else {
|
||||
*ent = e;
|
||||
}
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"ldbm_back_entry_get: rc=%d\n",
|
||||
rc, 0, 0 );
|
||||
return(rc);
|
||||
}
|
||||
|
|
@ -1,52 +0,0 @@
|
|||
/* extended.c - ldbm backend extended routines */
|
||||
/* $OpenLDAP$ */
|
||||
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
|
||||
*
|
||||
* Copyright 1998-2006 The OpenLDAP Foundation.
|
||||
* 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>.
|
||||
*/
|
||||
|
||||
#include "portable.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <ac/socket.h>
|
||||
#include <ac/string.h>
|
||||
|
||||
#include "slap.h"
|
||||
#include "back-ldbm.h"
|
||||
#include "proto-back-ldbm.h"
|
||||
#include "lber_pvt.h"
|
||||
|
||||
struct exop {
|
||||
struct berval *oid;
|
||||
BI_op_extended *extended;
|
||||
} exop_table[] = {
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
int
|
||||
ldbm_back_extended(
|
||||
Operation *op,
|
||||
SlapReply *rs )
|
||||
{
|
||||
int i;
|
||||
|
||||
for( i=0; exop_table[i].extended != NULL; i++ ) {
|
||||
if( ber_bvcmp( exop_table[i].oid, &op->oq_extended.rs_reqoid ) == 0 ) {
|
||||
return exop_table[i].extended( op, rs );
|
||||
}
|
||||
}
|
||||
|
||||
rs->sr_text = "not supported within naming context";
|
||||
return LDAP_UNWILLING_TO_PERFORM;
|
||||
}
|
||||
|
||||
|
|
@ -1,684 +0,0 @@
|
|||
/* filterindex.c - generate the list of candidate entries from a filter */
|
||||
/* $OpenLDAP$ */
|
||||
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
|
||||
*
|
||||
* Copyright 1998-2006 The OpenLDAP Foundation.
|
||||
* 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>.
|
||||
*/
|
||||
|
||||
#include "portable.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <ac/socket.h>
|
||||
#include <ac/string.h>
|
||||
|
||||
#include "slap.h"
|
||||
#include "back-ldbm.h"
|
||||
|
||||
static ID_BLOCK *presence_candidates(
|
||||
Operation *op,
|
||||
AttributeDescription *desc );
|
||||
static ID_BLOCK *equality_candidates(
|
||||
Operation *op, AttributeAssertion *ava );
|
||||
static ID_BLOCK *approx_candidates(
|
||||
Operation *op, AttributeAssertion *ava );
|
||||
static ID_BLOCK *substring_candidates(
|
||||
Operation *op,
|
||||
SubstringsAssertion *sub );
|
||||
static ID_BLOCK *list_candidates(
|
||||
Operation *op,
|
||||
Filter *flist,
|
||||
int ftype );
|
||||
|
||||
ID_BLOCK *
|
||||
filter_candidates(
|
||||
Operation *op,
|
||||
Filter *f
|
||||
)
|
||||
{
|
||||
char *sub = "SUBTREE";
|
||||
ID_BLOCK *result;
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "=> filter_candidates\n", 0, 0, 0 );
|
||||
|
||||
|
||||
result = NULL;
|
||||
switch ( f->f_choice ) {
|
||||
case SLAPD_FILTER_COMPUTED:
|
||||
switch( f->f_result ) {
|
||||
case SLAPD_COMPARE_UNDEFINED:
|
||||
/* This technically is not the same as FALSE, but it
|
||||
* certainly will produce no matches.
|
||||
*/
|
||||
/* FALLTHRU */
|
||||
case LDAP_COMPARE_FALSE:
|
||||
result = NULL;
|
||||
break;
|
||||
case LDAP_COMPARE_TRUE:
|
||||
result = idl_allids( op->o_bd );
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case SLAPD_FILTER_DN_ONE:
|
||||
Debug( LDAP_DEBUG_FILTER, "\tDN ONE\n", 0, 0, 0 );
|
||||
|
||||
/* an error is treated as an empty list */
|
||||
if ( dn2idl( op->o_bd, f->f_dn, DN_ONE_PREFIX, &result ) != 0
|
||||
&& result != NULL ) {
|
||||
idl_free( result );
|
||||
result = NULL;
|
||||
}
|
||||
break;
|
||||
|
||||
#ifdef SLAPD_FILTER_DN_CHILDREN
|
||||
case SLAPD_FILTER_DN_CHILDREN:
|
||||
sub = "CHILDREN";
|
||||
#endif
|
||||
case SLAPD_FILTER_DN_SUBTREE:
|
||||
Debug( LDAP_DEBUG_FILTER,
|
||||
"\tDN %s\n", sub, 0, 0 );
|
||||
|
||||
/* an error is treated as an empty list */
|
||||
if ( dn2idl( op->o_bd, f->f_dn, DN_SUBTREE_PREFIX, &result ) != 0
|
||||
&& result != NULL ) {
|
||||
idl_free( result );
|
||||
result = NULL;
|
||||
}
|
||||
break;
|
||||
|
||||
case LDAP_FILTER_PRESENT:
|
||||
Debug( LDAP_DEBUG_FILTER, "\tPRESENT\n", 0, 0, 0 );
|
||||
|
||||
result = presence_candidates( op, f->f_desc );
|
||||
break;
|
||||
|
||||
case LDAP_FILTER_EQUALITY:
|
||||
Debug( LDAP_DEBUG_FILTER, "\tEQUALITY\n", 0, 0, 0 );
|
||||
|
||||
result = equality_candidates( op, f->f_ava );
|
||||
break;
|
||||
|
||||
case LDAP_FILTER_APPROX:
|
||||
Debug( LDAP_DEBUG_FILTER, "\tAPPROX\n", 0, 0, 0 );
|
||||
|
||||
result = approx_candidates( op, f->f_ava );
|
||||
break;
|
||||
|
||||
case LDAP_FILTER_SUBSTRINGS:
|
||||
Debug( LDAP_DEBUG_FILTER, "\tSUBSTRINGS\n", 0, 0, 0 );
|
||||
|
||||
result = substring_candidates( op, f->f_sub );
|
||||
break;
|
||||
|
||||
case LDAP_FILTER_GE:
|
||||
Debug( LDAP_DEBUG_FILTER, "\tGE\n", 0, 0, 0 );
|
||||
|
||||
result = presence_candidates( op, f->f_ava->aa_desc );
|
||||
break;
|
||||
|
||||
case LDAP_FILTER_LE:
|
||||
Debug( LDAP_DEBUG_FILTER, "\tLE\n", 0, 0, 0 );
|
||||
|
||||
result = presence_candidates( op, f->f_ava->aa_desc );
|
||||
break;
|
||||
|
||||
case LDAP_FILTER_AND:
|
||||
Debug( LDAP_DEBUG_FILTER, "\tAND\n", 0, 0, 0 );
|
||||
|
||||
result = list_candidates( op, f->f_and, LDAP_FILTER_AND );
|
||||
break;
|
||||
|
||||
case LDAP_FILTER_OR:
|
||||
Debug( LDAP_DEBUG_FILTER, "\tOR\n", 0, 0, 0 );
|
||||
|
||||
result = list_candidates( op, f->f_or, LDAP_FILTER_OR );
|
||||
break;
|
||||
|
||||
case LDAP_FILTER_NOT:
|
||||
Debug( LDAP_DEBUG_FILTER, "\tNOT\n", 0, 0, 0 );
|
||||
|
||||
/*
|
||||
* As candidates lists may contain entries which do
|
||||
* not match the assertion, negation of the inner candidate
|
||||
* list could result in matching entries be excluded from
|
||||
* the returned candidate list.
|
||||
*/
|
||||
result = idl_allids( op->o_bd );
|
||||
break;
|
||||
default:
|
||||
Debug( LDAP_DEBUG_FILTER, "\tUNKNOWN\n", 0, 0, 0 );
|
||||
/* unknown filters must not return NULL, to allow
|
||||
* extended filter processing to be done later.
|
||||
*/
|
||||
result = idl_allids( op->o_bd );
|
||||
break;
|
||||
}
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "<= filter_candidates %ld\n",
|
||||
result ? ID_BLOCK_NIDS(result) : 0, 0, 0 );
|
||||
|
||||
return( result );
|
||||
}
|
||||
|
||||
static ID_BLOCK *
|
||||
presence_candidates(
|
||||
Operation *op,
|
||||
AttributeDescription *desc
|
||||
)
|
||||
{
|
||||
ID_BLOCK *idl;
|
||||
DBCache *db;
|
||||
int rc;
|
||||
char *dbname;
|
||||
slap_mask_t mask;
|
||||
struct berval prefix = {0, NULL};
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "=> presence_candidates\n", 0, 0, 0 );
|
||||
|
||||
idl = idl_allids( op->o_bd );
|
||||
|
||||
if( desc == slap_schema.si_ad_objectClass ) {
|
||||
return idl;
|
||||
}
|
||||
|
||||
rc = index_param( op->o_bd, desc, LDAP_FILTER_PRESENT,
|
||||
&dbname, &mask, &prefix );
|
||||
|
||||
if( rc != LDAP_SUCCESS ) {
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"<= presence_candidates: index_param returned=%d\n",
|
||||
rc, 0, 0 );
|
||||
|
||||
return idl;
|
||||
}
|
||||
|
||||
if( dbname == NULL ) {
|
||||
/* not indexed */
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"<= presense_candidates: not indexed\n",
|
||||
0, 0, 0 );
|
||||
|
||||
return idl;
|
||||
}
|
||||
|
||||
db = ldbm_cache_open( op->o_bd, dbname, LDBM_SUFFIX, LDBM_WRCREAT );
|
||||
|
||||
if ( db == NULL ) {
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"<= presense_candidates db open failed (%s%s)\n",
|
||||
dbname, LDBM_SUFFIX, 0 );
|
||||
|
||||
return idl;
|
||||
}
|
||||
|
||||
if( prefix.bv_val != NULL ) {
|
||||
idl_free( idl );
|
||||
idl = NULL;
|
||||
|
||||
rc = key_read( op->o_bd, db, &prefix, &idl );
|
||||
|
||||
if( rc != LDAP_SUCCESS ) {
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"<= presense_candidates key read failed (%d)\n",
|
||||
rc, 0, 0 );
|
||||
|
||||
|
||||
} else if( idl == NULL ) {
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"<= presense_candidates NULL\n",
|
||||
0, 0, 0 );
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
ldbm_cache_close( op->o_bd, db );
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "<= presence_candidates %ld\n",
|
||||
idl ? ID_BLOCK_NIDS(idl) : 0, 0, 0 );
|
||||
|
||||
return( idl );
|
||||
}
|
||||
|
||||
static ID_BLOCK *
|
||||
equality_candidates(
|
||||
Operation *op,
|
||||
AttributeAssertion *ava
|
||||
)
|
||||
{
|
||||
ID_BLOCK *idl;
|
||||
DBCache *db;
|
||||
int i;
|
||||
int rc;
|
||||
char *dbname;
|
||||
slap_mask_t mask;
|
||||
struct berval prefix = {0, NULL};
|
||||
struct berval *keys = NULL;
|
||||
MatchingRule *mr;
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "=> equality_candidates\n", 0, 0, 0 );
|
||||
|
||||
|
||||
idl = idl_allids( op->o_bd );
|
||||
|
||||
rc = index_param( op->o_bd, ava->aa_desc, LDAP_FILTER_EQUALITY,
|
||||
&dbname, &mask, &prefix );
|
||||
|
||||
if( rc != LDAP_SUCCESS ) {
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"<= equality_candidates: index_param returned=%d\n",
|
||||
rc, 0, 0 );
|
||||
|
||||
return idl;
|
||||
}
|
||||
|
||||
if( dbname == NULL ) {
|
||||
/* not indexed */
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"<= equality_candidates: not indexed\n",
|
||||
0, 0, 0 );
|
||||
|
||||
return idl;
|
||||
}
|
||||
|
||||
mr = ava->aa_desc->ad_type->sat_equality;
|
||||
if( !mr ) {
|
||||
return idl;
|
||||
}
|
||||
|
||||
if( !mr->smr_filter ) {
|
||||
return idl;
|
||||
}
|
||||
|
||||
rc = (mr->smr_filter)(
|
||||
LDAP_FILTER_EQUALITY,
|
||||
mask,
|
||||
ava->aa_desc->ad_type->sat_syntax,
|
||||
mr,
|
||||
&prefix,
|
||||
&ava->aa_value,
|
||||
&keys, op->o_tmpmemctx );
|
||||
|
||||
if( rc != LDAP_SUCCESS ) {
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"<= equality_candidates: (%s%s) MR filter failed (%d)\n",
|
||||
dbname, LDBM_SUFFIX, rc );
|
||||
|
||||
return idl;
|
||||
}
|
||||
|
||||
if( keys == NULL ) {
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"<= equality_candidates: no keys (%s%s)\n",
|
||||
dbname, LDBM_SUFFIX, 0 );
|
||||
|
||||
return idl;
|
||||
}
|
||||
|
||||
db = ldbm_cache_open( op->o_bd, dbname, LDBM_SUFFIX, LDBM_WRCREAT );
|
||||
|
||||
if ( db == NULL ) {
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"<= equality_candidates db open failed (%s%s)\n",
|
||||
dbname, LDBM_SUFFIX, 0 );
|
||||
|
||||
return idl;
|
||||
}
|
||||
|
||||
for ( i= 0; keys[i].bv_val != NULL; i++ ) {
|
||||
ID_BLOCK *save;
|
||||
ID_BLOCK *tmp;
|
||||
|
||||
rc = key_read( op->o_bd, db, &keys[i], &tmp );
|
||||
|
||||
if( rc != LDAP_SUCCESS ) {
|
||||
idl_free( idl );
|
||||
idl = NULL;
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"<= equality_candidates key read failed (%d)\n",
|
||||
rc, 0, 0 );
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if( tmp == NULL ) {
|
||||
idl_free( idl );
|
||||
idl = NULL;
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"<= equality_candidates NULL\n",
|
||||
0, 0, 0 );
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
save = idl;
|
||||
idl = idl_intersection( op->o_bd, idl, tmp );
|
||||
idl_free( save );
|
||||
idl_free( tmp );
|
||||
|
||||
if( idl == NULL ) break;
|
||||
}
|
||||
|
||||
ber_bvarray_free_x( keys, op->o_tmpmemctx );
|
||||
|
||||
ldbm_cache_close( op->o_bd, db );
|
||||
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "<= equality_candidates %ld\n",
|
||||
idl ? ID_BLOCK_NIDS(idl) : 0, 0, 0 );
|
||||
|
||||
return( idl );
|
||||
}
|
||||
|
||||
static ID_BLOCK *
|
||||
approx_candidates(
|
||||
Operation *op,
|
||||
AttributeAssertion *ava
|
||||
)
|
||||
{
|
||||
ID_BLOCK *idl;
|
||||
DBCache *db;
|
||||
int i;
|
||||
int rc;
|
||||
char *dbname;
|
||||
slap_mask_t mask;
|
||||
struct berval prefix = {0, NULL};
|
||||
struct berval *keys = NULL;
|
||||
MatchingRule *mr;
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "=> approx_candidates\n", 0, 0, 0 );
|
||||
|
||||
|
||||
idl = idl_allids( op->o_bd );
|
||||
|
||||
rc = index_param( op->o_bd, ava->aa_desc, LDAP_FILTER_APPROX,
|
||||
&dbname, &mask, &prefix );
|
||||
|
||||
if( rc != LDAP_SUCCESS ) {
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"<= approx_candidates: index_param returned=%d\n",
|
||||
rc, 0, 0 );
|
||||
|
||||
return idl;
|
||||
}
|
||||
|
||||
if( dbname == NULL ) {
|
||||
/* not indexed */
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"<= approx_candidates: not indexed\n",
|
||||
0, 0, 0 );
|
||||
|
||||
return idl;
|
||||
}
|
||||
|
||||
mr = ava->aa_desc->ad_type->sat_approx;
|
||||
if( !mr ) {
|
||||
/* no approx matching rule, try equality matching rule */
|
||||
mr = ava->aa_desc->ad_type->sat_equality;
|
||||
}
|
||||
|
||||
if( !mr ) {
|
||||
return idl;
|
||||
}
|
||||
|
||||
if( !mr->smr_filter ) {
|
||||
return idl;
|
||||
}
|
||||
|
||||
rc = (mr->smr_filter)(
|
||||
LDAP_FILTER_APPROX,
|
||||
mask,
|
||||
ava->aa_desc->ad_type->sat_syntax,
|
||||
mr,
|
||||
&prefix,
|
||||
&ava->aa_value,
|
||||
&keys, op->o_tmpmemctx );
|
||||
|
||||
if( rc != LDAP_SUCCESS ) {
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"<= approx_candidates: (%s%s) MR filter failed (%d)\n",
|
||||
dbname, LDBM_SUFFIX, rc );
|
||||
|
||||
return idl;
|
||||
}
|
||||
|
||||
if( keys == NULL ) {
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"<= approx_candidates: no keys (%s%s)\n",
|
||||
dbname, LDBM_SUFFIX, 0 );
|
||||
|
||||
return idl;
|
||||
}
|
||||
|
||||
db = ldbm_cache_open( op->o_bd, dbname, LDBM_SUFFIX, LDBM_WRCREAT );
|
||||
|
||||
if ( db == NULL ) {
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"<= approx_candidates db open failed (%s%s)\n",
|
||||
dbname, LDBM_SUFFIX, 0 );
|
||||
|
||||
return idl;
|
||||
}
|
||||
|
||||
for ( i= 0; keys[i].bv_val != NULL; i++ ) {
|
||||
ID_BLOCK *save;
|
||||
ID_BLOCK *tmp;
|
||||
|
||||
rc = key_read( op->o_bd, db, &keys[i], &tmp );
|
||||
|
||||
if( rc != LDAP_SUCCESS ) {
|
||||
idl_free( idl );
|
||||
idl = NULL;
|
||||
Debug( LDAP_DEBUG_TRACE, "<= approx_candidates key read failed (%d)\n",
|
||||
rc, 0, 0 );
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if( tmp == NULL ) {
|
||||
idl_free( idl );
|
||||
idl = NULL;
|
||||
Debug( LDAP_DEBUG_TRACE, "<= approx_candidates NULL\n",
|
||||
0, 0, 0 );
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
save = idl;
|
||||
idl = idl_intersection( op->o_bd, idl, tmp );
|
||||
idl_free( save );
|
||||
idl_free( tmp );
|
||||
|
||||
if( idl == NULL ) break;
|
||||
}
|
||||
|
||||
ber_bvarray_free_x( keys, op->o_tmpmemctx );
|
||||
|
||||
ldbm_cache_close( op->o_bd, db );
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "<= approx_candidates %ld\n",
|
||||
idl ? ID_BLOCK_NIDS(idl) : 0, 0, 0 );
|
||||
|
||||
return( idl );
|
||||
}
|
||||
|
||||
static ID_BLOCK *
|
||||
list_candidates(
|
||||
Operation *op,
|
||||
Filter *flist,
|
||||
int ftype
|
||||
)
|
||||
{
|
||||
ID_BLOCK *idl, *tmp, *tmp2;
|
||||
Filter *f;
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "=> list_candidates 0x%x\n", ftype, 0, 0 );
|
||||
|
||||
|
||||
idl = NULL;
|
||||
for ( f = flist; f != NULL; f = f->f_next ) {
|
||||
if ( (tmp = filter_candidates( op, f )) == NULL &&
|
||||
ftype == LDAP_FILTER_AND ) {
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"<= list_candidates NULL\n", 0, 0, 0 );
|
||||
|
||||
idl_free( idl );
|
||||
return( NULL );
|
||||
}
|
||||
|
||||
tmp2 = idl;
|
||||
if ( idl == NULL ) {
|
||||
idl = tmp;
|
||||
} else if ( ftype == LDAP_FILTER_AND ) {
|
||||
idl = idl_intersection( op->o_bd, idl, tmp );
|
||||
idl_free( tmp );
|
||||
idl_free( tmp2 );
|
||||
} else {
|
||||
idl = idl_union( op->o_bd, idl, tmp );
|
||||
idl_free( tmp );
|
||||
idl_free( tmp2 );
|
||||
}
|
||||
}
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "<= list_candidates %ld\n",
|
||||
idl ? ID_BLOCK_NIDS(idl) : 0, 0, 0 );
|
||||
|
||||
return( idl );
|
||||
}
|
||||
|
||||
static ID_BLOCK *
|
||||
substring_candidates(
|
||||
Operation *op,
|
||||
SubstringsAssertion *sub
|
||||
)
|
||||
{
|
||||
ID_BLOCK *idl;
|
||||
DBCache *db;
|
||||
int i;
|
||||
int rc;
|
||||
char *dbname;
|
||||
slap_mask_t mask;
|
||||
struct berval prefix = {0, NULL};
|
||||
struct berval *keys = NULL;
|
||||
MatchingRule *mr;
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "=> substrings_candidates\n", 0, 0, 0 );
|
||||
|
||||
|
||||
idl = idl_allids( op->o_bd );
|
||||
|
||||
rc = index_param( op->o_bd, sub->sa_desc, LDAP_FILTER_SUBSTRINGS,
|
||||
&dbname, &mask, &prefix );
|
||||
|
||||
if( rc != LDAP_SUCCESS ) {
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"<= substrings_candidates: index_param returned=%d\n",
|
||||
rc, 0, 0 );
|
||||
|
||||
return idl;
|
||||
}
|
||||
|
||||
if( dbname == NULL ) {
|
||||
/* not indexed */
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"<= substrings_candidates: not indexed\n",
|
||||
0, 0, 0 );
|
||||
|
||||
return idl;
|
||||
}
|
||||
|
||||
mr = sub->sa_desc->ad_type->sat_substr;
|
||||
|
||||
if( !mr ) {
|
||||
return idl;
|
||||
}
|
||||
|
||||
if( !mr->smr_filter ) {
|
||||
return idl;
|
||||
}
|
||||
|
||||
rc = (mr->smr_filter)(
|
||||
LDAP_FILTER_SUBSTRINGS,
|
||||
mask,
|
||||
sub->sa_desc->ad_type->sat_syntax,
|
||||
mr,
|
||||
&prefix,
|
||||
sub,
|
||||
&keys, op->o_tmpmemctx );
|
||||
|
||||
if( rc != LDAP_SUCCESS ) {
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"<= substrings_candidates: (%s%s) MR filter failed (%d)\n",
|
||||
dbname, LDBM_SUFFIX, rc );
|
||||
|
||||
return idl;
|
||||
}
|
||||
|
||||
if( keys == NULL ) {
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"<= substrings_candidates: (0x%04lx) no keys (%s%s)\n",
|
||||
mask, dbname, LDBM_SUFFIX );
|
||||
|
||||
return idl;
|
||||
}
|
||||
|
||||
db = ldbm_cache_open( op->o_bd, dbname, LDBM_SUFFIX, LDBM_WRCREAT );
|
||||
|
||||
if ( db == NULL ) {
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"<= substrings_candidates db open failed (%s%s)\n",
|
||||
dbname, LDBM_SUFFIX, 0 );
|
||||
|
||||
return idl;
|
||||
}
|
||||
|
||||
for ( i= 0; keys[i].bv_val != NULL; i++ ) {
|
||||
ID_BLOCK *save;
|
||||
ID_BLOCK *tmp;
|
||||
|
||||
rc = key_read( op->o_bd, db, &keys[i], &tmp );
|
||||
|
||||
if( rc != LDAP_SUCCESS ) {
|
||||
idl_free( idl );
|
||||
idl = NULL;
|
||||
Debug( LDAP_DEBUG_TRACE, "<= substrings_candidates key read failed (%d)\n",
|
||||
rc, 0, 0 );
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if( tmp == NULL ) {
|
||||
idl_free( idl );
|
||||
idl = NULL;
|
||||
Debug( LDAP_DEBUG_TRACE, "<= substrings_candidates NULL\n",
|
||||
0, 0, 0 );
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
save = idl;
|
||||
idl = idl_intersection( op->o_bd, idl, tmp );
|
||||
idl_free( save );
|
||||
idl_free( tmp );
|
||||
|
||||
if( idl == NULL ) break;
|
||||
}
|
||||
|
||||
ber_bvarray_free_x( keys, op->o_tmpmemctx );
|
||||
|
||||
ldbm_cache_close( op->o_bd, db );
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "<= substrings_candidates %ld\n",
|
||||
idl ? ID_BLOCK_NIDS(idl) : 0, 0, 0 );
|
||||
|
||||
return( idl );
|
||||
}
|
||||
|
|
@ -1,71 +0,0 @@
|
|||
/* id2children.c - routines to deal with the id2children index */
|
||||
/* $OpenLDAP$ */
|
||||
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
|
||||
*
|
||||
* Copyright 1998-2006 The OpenLDAP Foundation.
|
||||
* 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>.
|
||||
*/
|
||||
|
||||
#include "portable.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <ac/string.h>
|
||||
|
||||
#include <ac/socket.h>
|
||||
|
||||
#include "slap.h"
|
||||
#include "back-ldbm.h"
|
||||
|
||||
int
|
||||
has_children(
|
||||
Backend *be,
|
||||
Entry *p
|
||||
)
|
||||
{
|
||||
DBCache *db;
|
||||
Datum key;
|
||||
int rc = 0;
|
||||
ID_BLOCK *idl;
|
||||
|
||||
ldbm_datum_init( key );
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "=> has_children( %ld )\n", p->e_id , 0, 0 );
|
||||
|
||||
|
||||
if ( (db = ldbm_cache_open( be, "dn2id", LDBM_SUFFIX,
|
||||
LDBM_WRCREAT )) == NULL ) {
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"<= has_children -1 could not open \"dn2id%s\"\n",
|
||||
LDBM_SUFFIX, 0, 0 );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
key.dsize = strlen( p->e_ndn ) + 2;
|
||||
key.dptr = ch_malloc( key.dsize );
|
||||
sprintf( key.dptr, "%c%s", DN_ONE_PREFIX, p->e_ndn );
|
||||
|
||||
idl = idl_fetch( be, db, key );
|
||||
|
||||
free( key.dptr );
|
||||
|
||||
ldbm_cache_close( be, db );
|
||||
|
||||
if( idl != NULL ) {
|
||||
idl_free( idl );
|
||||
rc = 1;
|
||||
}
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "<= has_children( %ld ): %s\n",
|
||||
p->e_id, rc ? "yes" : "no", 0 );
|
||||
|
||||
return( rc );
|
||||
}
|
||||
|
|
@ -1,234 +0,0 @@
|
|||
/* id2entry.c - routines to deal with the id2entry index */
|
||||
/* $OpenLDAP$ */
|
||||
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
|
||||
*
|
||||
* Copyright 1998-2006 The OpenLDAP Foundation.
|
||||
* 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>.
|
||||
*/
|
||||
|
||||
#include "portable.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <ac/socket.h>
|
||||
|
||||
#include "slap.h"
|
||||
#include "back-ldbm.h"
|
||||
|
||||
/*
|
||||
* This routine adds (or updates) an entry on disk.
|
||||
* The cache should already be updated.
|
||||
*/
|
||||
|
||||
int
|
||||
id2entry_add( Backend *be, Entry *e )
|
||||
{
|
||||
DBCache *db;
|
||||
Datum key, data;
|
||||
int len, rc, flags;
|
||||
#ifndef WORDS_BIGENDIAN
|
||||
ID id;
|
||||
#endif
|
||||
|
||||
ldbm_datum_init( key );
|
||||
ldbm_datum_init( data );
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "=> id2entry_add( %ld, \"%s\" )\n", e->e_id,
|
||||
e->e_dn, 0 );
|
||||
|
||||
|
||||
if ( (db = ldbm_cache_open( be, "id2entry", LDBM_SUFFIX, LDBM_WRCREAT ))
|
||||
== NULL ) {
|
||||
Debug( LDAP_DEBUG_ANY, "Could not open/create id2entry%s\n",
|
||||
LDBM_SUFFIX, 0, 0 );
|
||||
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
key.dptr = (char *) &e->e_id;
|
||||
#else
|
||||
id = htonl(e->e_id);
|
||||
key.dptr = (char *) &id;
|
||||
#endif
|
||||
key.dsize = sizeof(ID);
|
||||
|
||||
ldap_pvt_thread_mutex_lock( &entry2str_mutex );
|
||||
data.dptr = entry2str( e, &len );
|
||||
data.dsize = len + 1;
|
||||
|
||||
/* store it */
|
||||
flags = LDBM_REPLACE;
|
||||
rc = ldbm_cache_store( db, key, data, flags );
|
||||
|
||||
ldap_pvt_thread_mutex_unlock( &entry2str_mutex );
|
||||
|
||||
ldbm_cache_close( be, db );
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "<= id2entry_add %d\n", rc, 0, 0 );
|
||||
|
||||
|
||||
return( rc );
|
||||
}
|
||||
|
||||
int
|
||||
id2entry_delete( Backend *be, Entry *e )
|
||||
{
|
||||
struct ldbminfo *li = (struct ldbminfo *) be->be_private;
|
||||
DBCache *db;
|
||||
Datum key;
|
||||
int rc;
|
||||
#ifndef WORDS_BIGENDIAN
|
||||
ID id;
|
||||
#endif
|
||||
|
||||
Debug(LDAP_DEBUG_TRACE, "=> id2entry_delete( %ld, \"%s\" )\n", e->e_id,
|
||||
e->e_dn, 0 );
|
||||
|
||||
|
||||
#ifdef notdef
|
||||
#ifdef LDAP_RDWR_DEBUG
|
||||
/* check for writer lock */
|
||||
assert(ldap_pvt_thread_rdwr_writers(&e->e_rdwr) == 1);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
ldbm_datum_init( key );
|
||||
|
||||
if ( (db = ldbm_cache_open( be, "id2entry", LDBM_SUFFIX, LDBM_WRCREAT ))
|
||||
== NULL ) {
|
||||
Debug( LDAP_DEBUG_ANY, "Could not open/create id2entry%s\n",
|
||||
LDBM_SUFFIX, 0, 0 );
|
||||
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
if ( cache_delete_entry( &li->li_cache, e ) != 0 ) {
|
||||
Debug(LDAP_DEBUG_ANY, "could not delete %ld (%s) from cache\n",
|
||||
e->e_id, e->e_dn, 0 );
|
||||
|
||||
}
|
||||
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
key.dptr = (char *) &e->e_id;
|
||||
#else
|
||||
id = htonl(e->e_id);
|
||||
key.dptr = (char *) &id;
|
||||
#endif
|
||||
key.dsize = sizeof(ID);
|
||||
|
||||
rc = ldbm_cache_delete( db, key );
|
||||
|
||||
ldbm_cache_close( be, db );
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "<= id2entry_delete %d\n", rc, 0, 0 );
|
||||
|
||||
return( rc );
|
||||
}
|
||||
|
||||
/* returns entry with reader/writer lock */
|
||||
Entry *
|
||||
id2entry_rw( Backend *be, ID id, int rw )
|
||||
{
|
||||
struct ldbminfo *li = (struct ldbminfo *) be->be_private;
|
||||
DBCache *db;
|
||||
Datum key, data;
|
||||
Entry *e;
|
||||
#ifndef WORDS_BIGENDIAN
|
||||
ID id2;
|
||||
#endif
|
||||
|
||||
ldbm_datum_init( key );
|
||||
ldbm_datum_init( data );
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "=> id2entry_%s( %ld )\n",
|
||||
rw ? "w" : "r", id, 0 );
|
||||
|
||||
|
||||
if ( (e = cache_find_entry_id( &li->li_cache, id, rw )) != NULL ) {
|
||||
Debug( LDAP_DEBUG_TRACE, "<= id2entry_%s( %ld ) 0x%lx (cache)\n",
|
||||
rw ? "w" : "r", id, (unsigned long) e );
|
||||
|
||||
return( e );
|
||||
}
|
||||
|
||||
if ( (db = ldbm_cache_open( be, "id2entry", LDBM_SUFFIX, LDBM_WRCREAT ))
|
||||
== NULL ) {
|
||||
Debug( LDAP_DEBUG_ANY, "Could not open id2entry%s\n",
|
||||
LDBM_SUFFIX, 0, 0 );
|
||||
|
||||
return( NULL );
|
||||
}
|
||||
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
key.dptr = (char *) &id;
|
||||
#else
|
||||
id2 = htonl(id);
|
||||
key.dptr = (char *) &id2;
|
||||
#endif
|
||||
key.dsize = sizeof(ID);
|
||||
|
||||
data = ldbm_cache_fetch( db, key );
|
||||
|
||||
if ( data.dptr == NULL ) {
|
||||
Debug( LDAP_DEBUG_TRACE, "<= id2entry_%s( %ld ) not found\n",
|
||||
rw ? "w" : "r", id, 0 );
|
||||
|
||||
ldbm_cache_close( be, db );
|
||||
return( NULL );
|
||||
}
|
||||
|
||||
e = str2entry2( data.dptr, 0 );
|
||||
ldbm_datum_free( db->dbc_db, data );
|
||||
ldbm_cache_close( be, db );
|
||||
|
||||
if ( e == NULL ) {
|
||||
Debug( LDAP_DEBUG_TRACE, "<= id2entry_%s( %ld ) (failed)\n",
|
||||
rw ? "w" : "r", id, 0 );
|
||||
|
||||
return( NULL );
|
||||
}
|
||||
|
||||
e->e_id = id;
|
||||
|
||||
if ( slapMode == SLAP_SERVER_MODE
|
||||
&& cache_add_entry_rw( &li->li_cache, e, rw ) != 0 )
|
||||
{
|
||||
entry_free( e );
|
||||
|
||||
/* XXX this is a kludge.
|
||||
* maybe the entry got added underneath us
|
||||
* There are many underlying race condtions in the cache/disk code.
|
||||
*/
|
||||
if ( (e = cache_find_entry_id( &li->li_cache, id, rw )) != NULL ) {
|
||||
Debug( LDAP_DEBUG_TRACE, "<= id2entry_%s( %ld ) 0x%lx (cache)\n",
|
||||
rw ? "w" : "r", id, (unsigned long) e );
|
||||
|
||||
return( e );
|
||||
}
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "<= id2entry_%s( %ld ) (cache add failed)\n",
|
||||
rw ? "w" : "r", id, 0 );
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "<= id2entry_%s( %ld ) 0x%lx (disk)\n",
|
||||
rw ? "w" : "r", id, (unsigned long) e );
|
||||
|
||||
if ( slapMode == SLAP_SERVER_MODE ) {
|
||||
/* marks the entry as committed, so it will get added to the cache
|
||||
* when the lock is released */
|
||||
cache_entry_commit( e );
|
||||
}
|
||||
|
||||
return( e );
|
||||
}
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,327 +0,0 @@
|
|||
/* index.c - routines for dealing with attribute indexes */
|
||||
/* $OpenLDAP$ */
|
||||
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
|
||||
*
|
||||
* Copyright 1998-2006 The OpenLDAP Foundation.
|
||||
* 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>.
|
||||
*/
|
||||
|
||||
#include "portable.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <ac/string.h>
|
||||
#include <ac/socket.h>
|
||||
|
||||
#include "slap.h"
|
||||
#include "back-ldbm.h"
|
||||
|
||||
static slap_mask_t index_mask(
|
||||
Backend *be,
|
||||
AttributeDescription *desc,
|
||||
char **dbname,
|
||||
struct berval *atname )
|
||||
{
|
||||
AttributeType *at;
|
||||
slap_mask_t mask = 0;
|
||||
|
||||
attr_mask( be->be_private, desc, &mask );
|
||||
|
||||
if( mask ) {
|
||||
*atname = desc->ad_cname;
|
||||
*dbname = desc->ad_cname.bv_val;
|
||||
return mask;
|
||||
}
|
||||
|
||||
/* If there is a tagging option, did we ever index the base
|
||||
* type? If so, check for mask, otherwise it's not there.
|
||||
*/
|
||||
if( slap_ad_is_tagged( desc ) && desc != desc->ad_type->sat_ad ) {
|
||||
/* has tagging option */
|
||||
attr_mask( be->be_private, desc->ad_type->sat_ad, &mask );
|
||||
|
||||
if( mask && ( mask ^ SLAP_INDEX_NOTAGS ) ) {
|
||||
*atname = desc->ad_type->sat_cname;
|
||||
*dbname = desc->ad_type->sat_cname.bv_val;
|
||||
return mask;
|
||||
}
|
||||
}
|
||||
|
||||
/* see if supertype defined mask for its subtypes */
|
||||
for( at = desc->ad_type->sat_sup; at != NULL ; at = at->sat_sup ) {
|
||||
/* If no AD, we've never indexed this type */
|
||||
if (!at->sat_ad)
|
||||
continue;
|
||||
|
||||
attr_mask( be->be_private, at->sat_ad, &mask );
|
||||
|
||||
if( mask && ( mask ^ SLAP_INDEX_NOSUBTYPES ) ) {
|
||||
*atname = at->sat_cname;
|
||||
*dbname = at->sat_cname.bv_val;
|
||||
return mask;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int index_is_indexed(
|
||||
Backend *be,
|
||||
AttributeDescription *desc )
|
||||
{
|
||||
slap_mask_t mask;
|
||||
char *dbname;
|
||||
struct berval prefix;
|
||||
|
||||
mask = index_mask( be, desc, &dbname, &prefix );
|
||||
|
||||
if( mask == 0 ) {
|
||||
return LDAP_INAPPROPRIATE_MATCHING;
|
||||
}
|
||||
|
||||
return LDAP_SUCCESS;
|
||||
}
|
||||
|
||||
int index_param(
|
||||
Backend *be,
|
||||
AttributeDescription *desc,
|
||||
int ftype,
|
||||
char **dbnamep,
|
||||
slap_mask_t *maskp,
|
||||
struct berval *prefixp )
|
||||
{
|
||||
slap_mask_t mask;
|
||||
char *dbname;
|
||||
|
||||
mask = index_mask( be, desc, &dbname, prefixp );
|
||||
|
||||
if( mask == 0 ) {
|
||||
return LDAP_INAPPROPRIATE_MATCHING;
|
||||
}
|
||||
|
||||
switch( ftype ) {
|
||||
case LDAP_FILTER_PRESENT:
|
||||
if( IS_SLAP_INDEX( mask, SLAP_INDEX_PRESENT ) ) {
|
||||
goto done;
|
||||
}
|
||||
break;
|
||||
|
||||
case LDAP_FILTER_APPROX:
|
||||
if ( desc->ad_type->sat_approx ) {
|
||||
if( IS_SLAP_INDEX( mask, SLAP_INDEX_APPROX ) ) {
|
||||
goto done;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/* Use EQUALITY rule and index for approximate match */
|
||||
/* fall thru */
|
||||
|
||||
case LDAP_FILTER_EQUALITY:
|
||||
if( IS_SLAP_INDEX( mask, SLAP_INDEX_EQUALITY ) ) {
|
||||
goto done;
|
||||
}
|
||||
break;
|
||||
|
||||
case LDAP_FILTER_SUBSTRINGS:
|
||||
if( IS_SLAP_INDEX( mask, SLAP_INDEX_SUBSTR ) ) {
|
||||
goto done;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return LDAP_OTHER;
|
||||
}
|
||||
|
||||
return LDAP_INAPPROPRIATE_MATCHING;
|
||||
|
||||
done:
|
||||
*dbnamep = dbname;
|
||||
*maskp = mask;
|
||||
return LDAP_SUCCESS;
|
||||
}
|
||||
|
||||
static int indexer(
|
||||
Operation *op,
|
||||
char *dbname,
|
||||
struct berval *atname,
|
||||
BerVarray vals,
|
||||
ID id,
|
||||
int opid,
|
||||
slap_mask_t mask )
|
||||
{
|
||||
int rc, i;
|
||||
const char *text;
|
||||
DBCache *db;
|
||||
AttributeDescription *ad = NULL;
|
||||
struct berval *keys;
|
||||
|
||||
assert( mask != 0 );
|
||||
|
||||
rc = slap_bv2ad( atname, &ad, &text );
|
||||
|
||||
if( rc != LDAP_SUCCESS ) return rc;
|
||||
|
||||
db = ldbm_cache_open( op->o_bd, dbname, LDBM_SUFFIX, LDBM_WRCREAT );
|
||||
|
||||
if ( db == NULL ) {
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"<= index_read NULL (could not open %s%s)\n",
|
||||
dbname, LDBM_SUFFIX, 0 );
|
||||
|
||||
return LDAP_OTHER;
|
||||
}
|
||||
|
||||
if( IS_SLAP_INDEX( mask, SLAP_INDEX_PRESENT ) ) {
|
||||
key_change( op->o_bd, db, atname, id, opid );
|
||||
}
|
||||
|
||||
if( IS_SLAP_INDEX( mask, SLAP_INDEX_EQUALITY ) ) {
|
||||
rc = ad->ad_type->sat_equality->smr_indexer(
|
||||
LDAP_FILTER_EQUALITY,
|
||||
mask,
|
||||
ad->ad_type->sat_syntax,
|
||||
ad->ad_type->sat_equality,
|
||||
atname, vals, &keys, op->o_tmpmemctx );
|
||||
|
||||
if( rc == LDAP_SUCCESS && keys != NULL ) {
|
||||
for( i=0; keys[i].bv_val != NULL; i++ ) {
|
||||
key_change( op->o_bd, db, &keys[i], id, opid );
|
||||
}
|
||||
ber_bvarray_free_x( keys, op->o_tmpmemctx );
|
||||
}
|
||||
}
|
||||
|
||||
if( IS_SLAP_INDEX( mask, SLAP_INDEX_APPROX ) ) {
|
||||
rc = ad->ad_type->sat_approx->smr_indexer(
|
||||
LDAP_FILTER_APPROX,
|
||||
mask,
|
||||
ad->ad_type->sat_syntax,
|
||||
ad->ad_type->sat_approx,
|
||||
atname, vals, &keys, op->o_tmpmemctx );
|
||||
|
||||
if( rc == LDAP_SUCCESS && keys != NULL ) {
|
||||
for( i=0; keys[i].bv_val != NULL; i++ ) {
|
||||
key_change( op->o_bd, db, &keys[i], id, opid );
|
||||
}
|
||||
ber_bvarray_free_x( keys, op->o_tmpmemctx );
|
||||
}
|
||||
}
|
||||
|
||||
if( IS_SLAP_INDEX( mask, SLAP_INDEX_SUBSTR ) ) {
|
||||
rc = ad->ad_type->sat_substr->smr_indexer(
|
||||
LDAP_FILTER_SUBSTRINGS,
|
||||
mask,
|
||||
ad->ad_type->sat_syntax,
|
||||
ad->ad_type->sat_substr,
|
||||
atname, vals, &keys, op->o_tmpmemctx );
|
||||
|
||||
if( rc == LDAP_SUCCESS && keys != NULL ) {
|
||||
for( i=0; keys[i].bv_val != NULL; i++ ) {
|
||||
key_change( op->o_bd, db, &keys[i], id, opid );
|
||||
}
|
||||
ber_bvarray_free_x( keys, op->o_tmpmemctx );
|
||||
}
|
||||
}
|
||||
|
||||
ldbm_cache_close( op->o_bd, db );
|
||||
|
||||
return LDAP_SUCCESS;
|
||||
}
|
||||
|
||||
static int index_at_values(
|
||||
Operation *op,
|
||||
AttributeType *type,
|
||||
struct berval *tags,
|
||||
BerVarray vals,
|
||||
ID id,
|
||||
int opid )
|
||||
{
|
||||
slap_mask_t mask = 0;
|
||||
|
||||
if( type->sat_sup ) {
|
||||
/* recurse */
|
||||
(void) index_at_values( op,
|
||||
type->sat_sup, tags,
|
||||
vals, id, opid );
|
||||
}
|
||||
|
||||
/* If this type has no AD, we've never used it before */
|
||||
if( type->sat_ad ) {
|
||||
attr_mask( op->o_bd->be_private, type->sat_ad, &mask );
|
||||
}
|
||||
|
||||
if( mask ) {
|
||||
indexer( op, type->sat_cname.bv_val,
|
||||
&type->sat_cname,
|
||||
vals, id, opid,
|
||||
mask );
|
||||
}
|
||||
|
||||
if( tags->bv_len ) {
|
||||
AttributeDescription *desc;
|
||||
|
||||
mask = 0;
|
||||
|
||||
desc = ad_find_tags(type, tags);
|
||||
if( desc ) {
|
||||
attr_mask( op->o_bd->be_private, desc, &mask );
|
||||
}
|
||||
|
||||
if( mask ) {
|
||||
indexer( op, desc->ad_cname.bv_val, &desc->ad_cname,
|
||||
vals, id, opid,
|
||||
mask );
|
||||
}
|
||||
}
|
||||
|
||||
return LDAP_SUCCESS;
|
||||
}
|
||||
|
||||
int index_values(
|
||||
Operation *op,
|
||||
AttributeDescription *desc,
|
||||
BerVarray vals,
|
||||
ID id,
|
||||
int opid )
|
||||
{
|
||||
(void) index_at_values( op,
|
||||
desc->ad_type, &desc->ad_tags,
|
||||
vals, id, opid );
|
||||
|
||||
return LDAP_SUCCESS;
|
||||
}
|
||||
|
||||
int
|
||||
index_entry(
|
||||
Operation *op,
|
||||
int opid,
|
||||
Entry *e )
|
||||
{
|
||||
Attribute *ap = e->e_attrs;
|
||||
Debug( LDAP_DEBUG_TRACE, "=> index_entry_%s( %ld, \"%s\" )\n",
|
||||
opid == SLAP_INDEX_ADD_OP ? "add" : "del",
|
||||
e->e_id, e->e_dn );
|
||||
|
||||
/* add each attribute to the indexes */
|
||||
for ( ; ap != NULL; ap = ap->a_next ) {
|
||||
index_values( op, ap->a_desc,
|
||||
ap->a_nvals,
|
||||
e->e_id, opid );
|
||||
}
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "<= index_entry_%s( %ld, \"%s\" ) success\n",
|
||||
opid == SLAP_INDEX_ADD_OP ? "add" : "del",
|
||||
e->e_id, e->e_dn );
|
||||
|
||||
return LDAP_SUCCESS;
|
||||
}
|
||||
|
||||
|
|
@ -1,266 +0,0 @@
|
|||
/* init.c - initialize ldbm backend */
|
||||
/* $OpenLDAP$ */
|
||||
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
|
||||
*
|
||||
* Copyright 1998-2006 The OpenLDAP Foundation.
|
||||
* 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>.
|
||||
*/
|
||||
|
||||
#include "portable.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <ac/string.h>
|
||||
#include <ac/socket.h>
|
||||
|
||||
#include "slap.h"
|
||||
#include "back-ldbm.h"
|
||||
#include <ldap_rq.h>
|
||||
|
||||
int
|
||||
ldbm_back_initialize(
|
||||
BackendInfo *bi
|
||||
)
|
||||
{
|
||||
static char *controls[] = {
|
||||
LDAP_CONTROL_MANAGEDSAIT,
|
||||
LDAP_CONTROL_X_PERMISSIVE_MODIFY,
|
||||
NULL
|
||||
};
|
||||
|
||||
bi->bi_controls = controls;
|
||||
|
||||
bi->bi_flags |=
|
||||
SLAP_BFLAG_INCREMENT |
|
||||
SLAP_BFLAG_SUBENTRIES |
|
||||
SLAP_BFLAG_ALIASES |
|
||||
SLAP_BFLAG_REFERRALS;
|
||||
|
||||
bi->bi_open = ldbm_back_open;
|
||||
bi->bi_config = NULL;
|
||||
bi->bi_close = ldbm_back_close;
|
||||
bi->bi_destroy = ldbm_back_destroy;
|
||||
|
||||
bi->bi_db_init = ldbm_back_db_init;
|
||||
bi->bi_db_config = ldbm_back_db_config;
|
||||
bi->bi_db_open = ldbm_back_db_open;
|
||||
bi->bi_db_close = ldbm_back_db_close;
|
||||
bi->bi_db_destroy = ldbm_back_db_destroy;
|
||||
|
||||
bi->bi_op_bind = ldbm_back_bind;
|
||||
bi->bi_op_unbind = 0;
|
||||
bi->bi_op_search = ldbm_back_search;
|
||||
bi->bi_op_compare = ldbm_back_compare;
|
||||
bi->bi_op_modify = ldbm_back_modify;
|
||||
bi->bi_op_modrdn = ldbm_back_modrdn;
|
||||
bi->bi_op_add = ldbm_back_add;
|
||||
bi->bi_op_delete = ldbm_back_delete;
|
||||
bi->bi_op_abandon = 0;
|
||||
|
||||
bi->bi_extended = ldbm_back_extended;
|
||||
|
||||
bi->bi_entry_release_rw = ldbm_back_entry_release_rw;
|
||||
bi->bi_entry_get_rw = ldbm_back_entry_get;
|
||||
bi->bi_chk_referrals = ldbm_back_referrals;
|
||||
bi->bi_operational = ldbm_back_operational;
|
||||
bi->bi_has_subordinates = ldbm_back_hasSubordinates;
|
||||
|
||||
/*
|
||||
* hooks for slap tools
|
||||
*/
|
||||
bi->bi_tool_entry_open = ldbm_tool_entry_open;
|
||||
bi->bi_tool_entry_close = ldbm_tool_entry_close;
|
||||
bi->bi_tool_entry_first = ldbm_tool_entry_first;
|
||||
bi->bi_tool_entry_next = ldbm_tool_entry_next;
|
||||
bi->bi_tool_entry_get = ldbm_tool_entry_get;
|
||||
bi->bi_tool_entry_put = ldbm_tool_entry_put;
|
||||
bi->bi_tool_entry_reindex = ldbm_tool_entry_reindex;
|
||||
bi->bi_tool_sync = ldbm_tool_sync;
|
||||
|
||||
bi->bi_tool_dn2id_get = 0;
|
||||
bi->bi_tool_id2entry_get = 0;
|
||||
bi->bi_tool_entry_modify = 0;
|
||||
|
||||
bi->bi_connection_init = 0;
|
||||
bi->bi_connection_destroy = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
ldbm_back_destroy(
|
||||
BackendInfo *bi
|
||||
)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
ldbm_back_open(
|
||||
BackendInfo *bi
|
||||
)
|
||||
{
|
||||
int rc;
|
||||
|
||||
/* initialize the underlying database system */
|
||||
rc = ldbm_initialize( NULL );
|
||||
return rc;
|
||||
}
|
||||
|
||||
int
|
||||
ldbm_back_close(
|
||||
BackendInfo *bi
|
||||
)
|
||||
{
|
||||
/* terminate the underlying database system */
|
||||
ldbm_shutdown();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
ldbm_back_db_init(
|
||||
Backend *be
|
||||
)
|
||||
{
|
||||
struct ldbminfo *li;
|
||||
|
||||
/* allocate backend-database-specific stuff */
|
||||
li = (struct ldbminfo *) ch_calloc( 1, sizeof(struct ldbminfo) );
|
||||
|
||||
/* arrange to read nextid later (on first request for it) */
|
||||
li->li_nextid = NOID;
|
||||
|
||||
/* default cache size */
|
||||
li->li_cache.c_maxsize = DEFAULT_CACHE_SIZE;
|
||||
|
||||
/* default database cache size */
|
||||
li->li_dbcachesize = DEFAULT_DBCACHE_SIZE;
|
||||
|
||||
/* default db mode is with locking */
|
||||
li->li_dblocking = 1;
|
||||
|
||||
/* default db mode is with write synchronization */
|
||||
li->li_dbwritesync = 1;
|
||||
|
||||
/* default file creation mode */
|
||||
li->li_mode = SLAPD_DEFAULT_DB_MODE;
|
||||
|
||||
/* default database directory */
|
||||
li->li_directory = ch_strdup( SLAPD_DEFAULT_DB_DIR );
|
||||
|
||||
/* DB_ENV environment pointer for DB3 */
|
||||
li->li_dbenv = 0;
|
||||
|
||||
/* envdirok is turned on by ldbm_initialize_env if DB3 */
|
||||
li->li_envdirok = 0;
|
||||
|
||||
/* syncfreq is 0 if disabled, or # seconds */
|
||||
li->li_dbsyncfreq = 0;
|
||||
|
||||
/* wait up to dbsyncwaitn times if server is busy */
|
||||
li->li_dbsyncwaitn = 12;
|
||||
|
||||
/* delay interval */
|
||||
li->li_dbsyncwaitinterval = 5;
|
||||
|
||||
/* current wait counter */
|
||||
li->li_dbsyncwaitcount = 0;
|
||||
|
||||
/* initialize various mutex locks & condition variables */
|
||||
ldap_pvt_thread_rdwr_init( &li->li_giant_rwlock );
|
||||
ldap_pvt_thread_mutex_init( &li->li_cache.c_mutex );
|
||||
ldap_pvt_thread_mutex_init( &li->li_dbcache_mutex );
|
||||
ldap_pvt_thread_cond_init( &li->li_dbcache_cv );
|
||||
|
||||
be->be_private = li;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
ldbm_back_db_open(
|
||||
BackendDB *be
|
||||
)
|
||||
{
|
||||
struct ldbminfo *li = (struct ldbminfo *) be->be_private;
|
||||
int rc;
|
||||
|
||||
rc = alock_open( &li->li_alock_info, "slapd",
|
||||
li->li_directory, ALOCK_UNIQUE );
|
||||
if ( rc == ALOCK_BUSY ) {
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"ldbm_back_db_open: database already in use\n",
|
||||
0, 0, 0 );
|
||||
return -1;
|
||||
} else if ( rc == ALOCK_RECOVER ) {
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"ldbm_back_db_open: unclean shutdown detected;"
|
||||
" database may be inconsistent!\n",
|
||||
0, 0, 0 );
|
||||
rc = alock_recover( &li->li_alock_info );
|
||||
}
|
||||
if ( rc != ALOCK_CLEAN ) {
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"ldbm_back_db_open: alock package is unstable;"
|
||||
" database may be inconsistent!\n",
|
||||
0, 0, 0 );
|
||||
}
|
||||
li->li_dbenv = ldbm_initialize_env( li->li_directory,
|
||||
li->li_dbcachesize, &li->li_envdirok );
|
||||
|
||||
/* If we're in server mode and a sync frequency was set,
|
||||
* submit a task to perform periodic db syncs.
|
||||
*/
|
||||
if (( slapMode & SLAP_SERVER_MODE ) && li->li_dbsyncfreq > 0 )
|
||||
{
|
||||
ldap_pvt_thread_mutex_lock( &slapd_rq.rq_mutex );
|
||||
ldap_pvt_runqueue_insert( &slapd_rq, li->li_dbsyncfreq,
|
||||
ldbm_cache_sync_daemon, be,
|
||||
"ldbm_cache_sync", be->be_suffix[0].bv_val );
|
||||
ldap_pvt_thread_mutex_unlock( &slapd_rq.rq_mutex );
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
ldbm_back_db_destroy(
|
||||
BackendDB *be
|
||||
)
|
||||
{
|
||||
/* should free/destroy every in be_private */
|
||||
struct ldbminfo *li = (struct ldbminfo *) be->be_private;
|
||||
|
||||
if (li->li_dbenv)
|
||||
ldbm_shutdown_env(li->li_dbenv);
|
||||
|
||||
free( li->li_directory );
|
||||
attr_index_destroy( li->li_attrs );
|
||||
|
||||
ldap_pvt_thread_rdwr_destroy( &li->li_giant_rwlock );
|
||||
ldap_pvt_thread_mutex_destroy( &li->li_cache.c_mutex );
|
||||
ldap_pvt_thread_mutex_destroy( &li->li_dbcache_mutex );
|
||||
ldap_pvt_thread_cond_destroy( &li->li_dbcache_cv );
|
||||
|
||||
free( be->be_private );
|
||||
be->be_private = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if SLAPD_LDBM == SLAPD_MOD_DYNAMIC
|
||||
|
||||
/* conditionally define the init_module() function */
|
||||
SLAP_BACKEND_INIT_MODULE( ldbm )
|
||||
|
||||
#endif /* SLAPD_LDBM == SLAPD_MOD_DYNAMIC */
|
||||
|
||||
|
||||
|
|
@ -1,95 +0,0 @@
|
|||
/* index.c - routines for dealing with attribute indexes */
|
||||
/* $OpenLDAP$ */
|
||||
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
|
||||
*
|
||||
* Copyright 1998-2006 The OpenLDAP Foundation.
|
||||
* 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>.
|
||||
*/
|
||||
|
||||
#include "portable.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <ac/string.h>
|
||||
#include <ac/socket.h>
|
||||
|
||||
#include "slap.h"
|
||||
#include "back-ldbm.h"
|
||||
|
||||
/* read a key */
|
||||
int
|
||||
key_read(
|
||||
Backend *be,
|
||||
DBCache *db,
|
||||
struct berval *k,
|
||||
ID_BLOCK **idout
|
||||
)
|
||||
{
|
||||
Datum key;
|
||||
ID_BLOCK *idl;
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "=> key_read\n", 0, 0, 0 );
|
||||
|
||||
|
||||
ldbm_datum_init( key );
|
||||
key.dptr = k->bv_val;
|
||||
key.dsize = k->bv_len;
|
||||
|
||||
idl = idl_fetch( be, db, key );
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "<= index_read %ld candidates\n",
|
||||
idl ? ID_BLOCK_NIDS(idl) : 0, 0, 0 );
|
||||
|
||||
|
||||
*idout = idl;
|
||||
return LDAP_SUCCESS;
|
||||
}
|
||||
|
||||
/* Add or remove stuff from index files */
|
||||
int
|
||||
key_change(
|
||||
Backend *be,
|
||||
DBCache *db,
|
||||
struct berval *k,
|
||||
ID id,
|
||||
int op
|
||||
)
|
||||
{
|
||||
int rc;
|
||||
Datum key;
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "=> key_change(%s,%lx)\n",
|
||||
op == SLAP_INDEX_ADD_OP ? "ADD":"DELETE", (long) id, 0 );
|
||||
|
||||
|
||||
ldbm_datum_init( key );
|
||||
key.dptr = k->bv_val;
|
||||
key.dsize = k->bv_len;
|
||||
|
||||
ldap_pvt_thread_mutex_lock( &db->dbc_write_mutex );
|
||||
if (op == SLAP_INDEX_ADD_OP) {
|
||||
/* Add values */
|
||||
rc = idl_insert_key( be, db, key, id );
|
||||
|
||||
} else {
|
||||
/* Delete values */
|
||||
rc = idl_delete_key( be, db, key, id );
|
||||
}
|
||||
ldap_pvt_thread_mutex_unlock( &db->dbc_write_mutex );
|
||||
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "<= key_change %d\n", rc, 0, 0 );
|
||||
|
||||
|
||||
ldap_pvt_thread_yield();
|
||||
|
||||
return rc;
|
||||
}
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,278 +0,0 @@
|
|||
/* ldbm.h - ldap dbm compatibility routine header file */
|
||||
/* $OpenLDAP$ */
|
||||
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
|
||||
*
|
||||
* Copyright 1998-2006 The OpenLDAP Foundation.
|
||||
* 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 file LICENSE in the
|
||||
* top-level directory of the distribution or, alternatively, at
|
||||
* <http://www.OpenLDAP.org/license.html>.
|
||||
*/
|
||||
|
||||
#ifndef _LDBM_H_
|
||||
#define _LDBM_H_
|
||||
|
||||
#include <ldap_cdefs.h>
|
||||
#include <ac/string.h>
|
||||
|
||||
/* dummy DB_ENV for non Berkeley DB */
|
||||
#if !defined( LDBM_USE_DBBTREE ) && !defined( LDBM_USE_DBHASH )
|
||||
# define DB_ENV void
|
||||
#endif
|
||||
|
||||
#if defined( LDBM_USE_DBBTREE ) || defined( LDBM_USE_DBHASH )
|
||||
|
||||
/*****************************************************************
|
||||
* *
|
||||
* use berkeley db btree or hash package *
|
||||
* *
|
||||
*****************************************************************/
|
||||
#include <sys/types.h>
|
||||
#include <limits.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#ifdef HAVE_DB_185_H
|
||||
# include <db_185.h>
|
||||
#else
|
||||
# ifdef HAVE_DB1_DB_H
|
||||
# include <db1/db.h>
|
||||
# else
|
||||
# include <db.h>
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef DB_VERSION_MAJOR
|
||||
# define DB_VERSION_MAJOR 1
|
||||
#endif
|
||||
#ifndef DB_VERSION_MINOR
|
||||
# define DB_VERSION_MINOR 85
|
||||
#endif
|
||||
|
||||
#if DB_VERSION_MAJOR >= 2
|
||||
# define R_NOOVERWRITE DB_NOOVERWRITE
|
||||
# ifndef DEFAULT_DB_PAGE_SIZE
|
||||
# define DEFAULT_DB_PAGE_SIZE 4096
|
||||
# endif
|
||||
#else
|
||||
# define DB_ENV void
|
||||
#endif
|
||||
|
||||
|
||||
LDAP_BEGIN_DECL
|
||||
|
||||
typedef DBT Datum;
|
||||
#define dsize size
|
||||
#define dptr data
|
||||
|
||||
typedef DB *LDBM;
|
||||
|
||||
|
||||
/* for ldbm_open */
|
||||
#if DB_VERSION_MAJOR >= 2
|
||||
typedef DBC LDBMCursor;
|
||||
|
||||
# define LDBM_READER DB_RDONLY
|
||||
# define LDBM_WRITER 0x00000 /* hopefully */
|
||||
# if defined( HAVE_BERKELEY_DB_THREAD )
|
||||
# define LDBM_WRCREAT (DB_NOMMAP|DB_CREATE|DB_THREAD)
|
||||
# define LDBM_NEWDB (DB_TRUNCATE|DB_CREATE|DB_THREAD)
|
||||
# else
|
||||
# define LDBM_WRCREAT (DB_NOMMAP|DB_CREATE)
|
||||
# define LDBM_NEWDB (DB_TRUNCATE|DB_CREATE)
|
||||
# endif
|
||||
|
||||
#else
|
||||
typedef void LDBMCursor;
|
||||
# define LDBM_READER O_RDONLY
|
||||
# define LDBM_WRITER O_RDWR
|
||||
# define LDBM_WRCREAT (O_RDWR|O_CREAT)
|
||||
# define LDBM_NEWDB (O_RDWR|O_TRUNC|O_CREAT)
|
||||
#endif
|
||||
|
||||
LDAP_END_DECL
|
||||
|
||||
/* for ldbm_open */
|
||||
#define LDBM_NOSYNC 0
|
||||
#define LDBM_SYNC 0
|
||||
#define LDBM_LOCKING 0
|
||||
#define LDBM_NOLOCKING 0
|
||||
|
||||
/* for ldbm_insert */
|
||||
#define LDBM_INSERT R_NOOVERWRITE
|
||||
#define LDBM_REPLACE 0
|
||||
|
||||
#ifdef LDBM_USE_DBBTREE
|
||||
# define LDBM_ORDERED 1
|
||||
# define LDBM_SUFFIX ".dbb"
|
||||
# define DB_TYPE DB_BTREE
|
||||
#else
|
||||
# define LDBM_SUFFIX ".dbh"
|
||||
# define DB_TYPE DB_HASH
|
||||
#endif
|
||||
|
||||
#elif defined( HAVE_GDBM )
|
||||
|
||||
/*****************************************************************
|
||||
* *
|
||||
* use gdbm if possible *
|
||||
* *
|
||||
*****************************************************************/
|
||||
|
||||
#include <gdbm.h>
|
||||
|
||||
LDAP_BEGIN_DECL
|
||||
|
||||
typedef datum Datum;
|
||||
typedef Datum LDBMCursor;
|
||||
typedef GDBM_FILE LDBM;
|
||||
|
||||
LDAP_END_DECL
|
||||
|
||||
/* for ldbm_open */
|
||||
#define LDBM_READER GDBM_READER
|
||||
#define LDBM_WRITER GDBM_WRITER
|
||||
#define LDBM_WRCREAT GDBM_WRCREAT
|
||||
#define LDBM_NEWDB GDBM_NEWDB
|
||||
|
||||
#ifdef GDBM_FAST
|
||||
#define LDBM_NOSYNC GDBM_FAST
|
||||
#else
|
||||
#define LDBM_NOSYNC 0
|
||||
#endif
|
||||
|
||||
#ifdef GDBM_SYNC
|
||||
#define LDBM_SYNC GDBM_SYNC
|
||||
#else
|
||||
#define LDBM_SYNC 0
|
||||
#endif
|
||||
|
||||
#define LDBM_LOCKING 0
|
||||
#ifdef GDBM_NOLOCK
|
||||
#define LDBM_NOLOCKING GDBM_NOLOCK
|
||||
#else
|
||||
#define LDBM_NOLOCKING 0
|
||||
#endif
|
||||
|
||||
#define LDBM_SUFFIX ".gdbm"
|
||||
|
||||
/* for ldbm_insert */
|
||||
#define LDBM_INSERT GDBM_INSERT
|
||||
#define LDBM_REPLACE GDBM_REPLACE
|
||||
|
||||
#elif defined( HAVE_MDBM )
|
||||
|
||||
/*****************************************************************
|
||||
* *
|
||||
* use mdbm if possible *
|
||||
* *
|
||||
*****************************************************************/
|
||||
|
||||
#include <mdbm.h>
|
||||
|
||||
LDAP_BEGIN_DECL
|
||||
|
||||
typedef datum Datum;
|
||||
typedef int LDBMCursor;
|
||||
typedef MDBM *LDBM;
|
||||
|
||||
LDAP_END_DECL
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
/* for ldbm_open */
|
||||
#define LDBM_READER O_RDONLY
|
||||
#define LDBM_WRITER O_RDWR
|
||||
#define LDBM_WRCREAT (O_RDWR|O_CREAT)
|
||||
#define LDBM_NEWDB (O_RDWR|O_TRUNC|O_CREAT)
|
||||
|
||||
#define LDBM_SYNC 0
|
||||
#define LDBM_NOSYNC 0
|
||||
#define LDBM_LOCKING 0
|
||||
#define LDBM_NOLOCKING 0
|
||||
|
||||
#define LDBM_SUFFIX ".mdbm"
|
||||
|
||||
/* for ldbm_insert */
|
||||
#define LDBM_INSERT MDBM_INSERT
|
||||
#define LDBM_REPLACE MDBM_REPLACE
|
||||
|
||||
#elif defined( HAVE_NDBM )
|
||||
|
||||
/*****************************************************************
|
||||
* *
|
||||
* if none of the above use ndbm, the standard unix thing *
|
||||
* *
|
||||
*****************************************************************/
|
||||
|
||||
#include <ndbm.h>
|
||||
|
||||
#ifdef HAVE_FCNTL_H
|
||||
#include <fcntl.h>
|
||||
#endif
|
||||
|
||||
LDAP_BEGIN_DECL
|
||||
|
||||
typedef datum Datum;
|
||||
typedef int LDBMCursor;
|
||||
typedef DBM *LDBM;
|
||||
|
||||
LDAP_END_DECL
|
||||
|
||||
/* for ldbm_open */
|
||||
#define LDBM_READER O_RDONLY
|
||||
#define LDBM_WRITER O_WRONLY
|
||||
#define LDBM_WRCREAT (O_RDWR|O_CREAT)
|
||||
#define LDBM_NEWDB (O_RDWR|O_TRUNC|O_CREAT)
|
||||
|
||||
#define LDBM_NOSYNC 0
|
||||
#define LDBM_SYNC 0
|
||||
#define LDBM_NOLOCK 0
|
||||
#define LDBM_SYNC 0
|
||||
|
||||
#define LDBM_SUFFIX ".ndbm"
|
||||
|
||||
/* for ldbm_insert */
|
||||
#define LDBM_INSERT DBM_INSERT
|
||||
#define LDBM_REPLACE DBM_REPLACE
|
||||
|
||||
#endif
|
||||
|
||||
LDAP_BEGIN_DECL
|
||||
|
||||
LDAP_LDBM_F (int) ldbm_initialize( const char * );
|
||||
LDAP_LDBM_F (int) ldbm_shutdown( void );
|
||||
|
||||
LDAP_LDBM_F (DB_ENV*) ldbm_initialize_env(const char *, int dbcachesize, int *envdirok);
|
||||
LDAP_LDBM_F (void) ldbm_shutdown_env(DB_ENV *);
|
||||
|
||||
LDAP_LDBM_F (int) ldbm_errno( LDBM ldbm );
|
||||
LDAP_LDBM_F (LDBM) ldbm_open( DB_ENV *env, char *name, int rw, int mode, int dbcachesize );
|
||||
LDAP_LDBM_F (void) ldbm_close( LDBM ldbm );
|
||||
LDAP_LDBM_F (void) ldbm_sync( LDBM ldbm );
|
||||
LDAP_LDBM_F (void) ldbm_datum_free( LDBM ldbm, Datum data );
|
||||
LDAP_LDBM_F (Datum) ldbm_datum_dup( LDBM ldbm, Datum data );
|
||||
LDAP_LDBM_F (Datum) ldbm_fetch( LDBM ldbm, Datum key );
|
||||
LDAP_LDBM_F (int) ldbm_store( LDBM ldbm, Datum key, Datum data, int flags );
|
||||
LDAP_LDBM_F (int) ldbm_delete( LDBM ldbm, Datum key );
|
||||
|
||||
LDAP_LDBM_F (Datum) ldbm_firstkey( LDBM ldbm, LDBMCursor **cursor );
|
||||
LDAP_LDBM_F (Datum) ldbm_nextkey( LDBM ldbm, Datum key, LDBMCursor *cursor );
|
||||
|
||||
/* initialization of Datum structures */
|
||||
#if defined( HAVE_BERKELEY_DB ) && (DB_VERSION_MAJOR >= 2)
|
||||
LDAP_LDBM_F (void *) ldbm_malloc( size_t size );
|
||||
# define ldbm_datum_init(d) ((void)memset(&(d), '\0', sizeof(Datum)))
|
||||
#else
|
||||
# define ldbm_datum_init(d) ((void)0)
|
||||
#endif /* HAVE_BERKELEY_DB */
|
||||
|
||||
LDAP_END_DECL
|
||||
|
||||
#endif /* _ldbm_h_ */
|
||||
|
|
@ -1,305 +0,0 @@
|
|||
/* modify.c - ldbm backend modify routine */
|
||||
/* $OpenLDAP$ */
|
||||
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
|
||||
*
|
||||
* Copyright 1998-2006 The OpenLDAP Foundation.
|
||||
* 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>.
|
||||
*/
|
||||
|
||||
#include "portable.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <ac/string.h>
|
||||
#include <ac/socket.h>
|
||||
#include <ac/time.h>
|
||||
|
||||
#include "slap.h"
|
||||
#include "back-ldbm.h"
|
||||
#include "proto-back-ldbm.h"
|
||||
|
||||
/* We need this function because of LDAP modrdn. If we do not
|
||||
* add this there would be a bunch of code replication here
|
||||
* and there and of course the likelihood of bugs increases.
|
||||
* Juan C. Gomez (gomez@engr.sgi.com) 05/18/99
|
||||
*/
|
||||
int ldbm_modify_internal(
|
||||
Operation *op,
|
||||
Modifications *modlist,
|
||||
Entry *e,
|
||||
const char **text,
|
||||
char *textbuf,
|
||||
size_t textlen )
|
||||
{
|
||||
int rc = LDAP_SUCCESS;
|
||||
Modification *mod;
|
||||
Modifications *ml;
|
||||
Attribute *save_attrs;
|
||||
Attribute *ap;
|
||||
|
||||
Debug(LDAP_DEBUG_TRACE,
|
||||
"ldbm_modify_internal: %s\n",
|
||||
e->e_name.bv_val,
|
||||
get_permissiveModify(op) ? " (permissive)" : "",
|
||||
0 );
|
||||
|
||||
if ( !acl_check_modlist( op, e, modlist )) {
|
||||
return LDAP_INSUFFICIENT_ACCESS;
|
||||
}
|
||||
|
||||
save_attrs = e->e_attrs;
|
||||
e->e_attrs = attrs_dup( e->e_attrs );
|
||||
|
||||
for ( ml = modlist; ml != NULL; ml = ml->sml_next ) {
|
||||
mod = &ml->sml_mod;
|
||||
|
||||
switch ( mod->sm_op ) {
|
||||
case LDAP_MOD_ADD:
|
||||
Debug(LDAP_DEBUG_ARGS,
|
||||
"ldbm_modify_internal: add\n", 0, 0, 0);
|
||||
|
||||
rc = modify_add_values( e, mod, get_permissiveModify( op ),
|
||||
text, textbuf, textlen );
|
||||
if( rc != LDAP_SUCCESS ) {
|
||||
Debug(LDAP_DEBUG_ARGS, "ldbm_modify_internal: %d %s\n",
|
||||
rc, *text, 0);
|
||||
}
|
||||
break;
|
||||
|
||||
case LDAP_MOD_DELETE:
|
||||
Debug(LDAP_DEBUG_ARGS,
|
||||
"ldbm_modify_internal: delete\n", 0, 0, 0);
|
||||
|
||||
rc = modify_delete_values( e, mod, get_permissiveModify( op ),
|
||||
text, textbuf, textlen );
|
||||
assert( rc != LDAP_TYPE_OR_VALUE_EXISTS );
|
||||
if( rc != LDAP_SUCCESS ) {
|
||||
Debug(LDAP_DEBUG_ARGS, "ldbm_modify_internal: %d %s\n",
|
||||
rc, *text, 0);
|
||||
}
|
||||
break;
|
||||
|
||||
case LDAP_MOD_REPLACE:
|
||||
Debug(LDAP_DEBUG_ARGS,
|
||||
"ldbm_modify_internal: replace\n", 0, 0, 0);
|
||||
|
||||
rc = modify_replace_values( e, mod, get_permissiveModify( op ),
|
||||
text, textbuf, textlen );
|
||||
if( rc != LDAP_SUCCESS ) {
|
||||
Debug(LDAP_DEBUG_ARGS, "ldbm_modify_internal: %d %s\n",
|
||||
rc, *text, 0);
|
||||
}
|
||||
break;
|
||||
|
||||
case LDAP_MOD_INCREMENT:
|
||||
Debug(LDAP_DEBUG_ARGS,
|
||||
"ldbm_modify_internal: increment\n",0,0,0);
|
||||
|
||||
rc = modify_increment_values( e, mod, get_permissiveModify( op ),
|
||||
text, textbuf, textlen );
|
||||
if( rc != LDAP_SUCCESS ) {
|
||||
Debug(LDAP_DEBUG_ARGS, "ldbm_modify_internal: %d %s\n",
|
||||
rc, *text, 0);
|
||||
}
|
||||
break;
|
||||
|
||||
case SLAP_MOD_SOFTADD:
|
||||
Debug(LDAP_DEBUG_ARGS,
|
||||
"ldbm_modify_internal: softadd\n", 0, 0, 0);
|
||||
|
||||
/* Avoid problems in index_add_mods()
|
||||
* We need to add index if necessary.
|
||||
*/
|
||||
mod->sm_op = LDAP_MOD_ADD;
|
||||
|
||||
rc = modify_add_values( e, mod, get_permissiveModify( op ),
|
||||
text, textbuf, textlen );
|
||||
mod->sm_op = SLAP_MOD_SOFTADD;
|
||||
if ( rc == LDAP_TYPE_OR_VALUE_EXISTS ) {
|
||||
rc = LDAP_SUCCESS;
|
||||
}
|
||||
|
||||
if( rc != LDAP_SUCCESS ) {
|
||||
Debug(LDAP_DEBUG_ARGS, "ldbm_modify_internal: %d %s\n",
|
||||
rc, *text, 0);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
Debug(LDAP_DEBUG_ANY, "ldbm_modify_internal: invalid op %d\n",
|
||||
mod->sm_op, 0, 0);
|
||||
|
||||
rc = LDAP_OTHER;
|
||||
*text = "Invalid modify operation";
|
||||
Debug(LDAP_DEBUG_ARGS, "ldbm_modify_internal: %d %s\n",
|
||||
rc, *text, 0);
|
||||
}
|
||||
|
||||
if ( rc != LDAP_SUCCESS ) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* If objectClass was modified, reset the flags */
|
||||
if ( mod->sm_desc == slap_schema.si_ad_objectClass ) {
|
||||
e->e_ocflags = 0;
|
||||
}
|
||||
|
||||
/* check if modified attribute was indexed */
|
||||
rc = index_is_indexed( op->o_bd, mod->sm_desc );
|
||||
if ( rc == LDAP_SUCCESS ) {
|
||||
ap = attr_find( save_attrs, mod->sm_desc );
|
||||
if ( ap ) ap->a_flags |= SLAP_ATTR_IXDEL;
|
||||
|
||||
ap = attr_find( e->e_attrs, mod->sm_desc );
|
||||
if ( ap ) ap->a_flags |= SLAP_ATTR_IXADD;
|
||||
}
|
||||
}
|
||||
|
||||
/* check that the entry still obeys the schema */
|
||||
rc = entry_schema_check( op, e, save_attrs, get_manageDIT(op),
|
||||
text, textbuf, textlen );
|
||||
if ( rc != LDAP_SUCCESS ) {
|
||||
Debug( LDAP_DEBUG_ANY, "entry failed schema check: %s\n",
|
||||
*text, 0, 0 );
|
||||
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* check for abandon */
|
||||
if ( op->o_abandon ) {
|
||||
rc = SLAPD_ABANDON;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* update the indices of the modified attributes */
|
||||
|
||||
/* start with deleting the old index entries */
|
||||
for ( ap = save_attrs; ap != NULL; ap = ap->a_next ) {
|
||||
if ( ap->a_flags & SLAP_ATTR_IXDEL ) {
|
||||
rc = index_values( op, ap->a_desc,
|
||||
ap->a_nvals,
|
||||
e->e_id, SLAP_INDEX_DELETE_OP );
|
||||
if ( rc != LDAP_SUCCESS ) {
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"ldbm_modify_internal: Attribute index delete failure\n",
|
||||
0, 0, 0 );
|
||||
goto exit;
|
||||
}
|
||||
ap->a_flags &= ~SLAP_ATTR_IXDEL;
|
||||
}
|
||||
}
|
||||
|
||||
/* add the new index entries */
|
||||
for ( ap = e->e_attrs; ap != NULL; ap = ap->a_next ) {
|
||||
if ( ap->a_flags & SLAP_ATTR_IXADD ) {
|
||||
rc = index_values( op, ap->a_desc,
|
||||
ap->a_nvals,
|
||||
e->e_id, SLAP_INDEX_ADD_OP );
|
||||
if ( rc != LDAP_SUCCESS ) {
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"ldbm_modify_internal: Attribute index add failure\n",
|
||||
0, 0, 0 );
|
||||
goto exit;
|
||||
}
|
||||
ap->a_flags &= ~SLAP_ATTR_IXADD;
|
||||
}
|
||||
}
|
||||
|
||||
exit:
|
||||
if ( rc == LDAP_SUCCESS ) {
|
||||
attrs_free( save_attrs );
|
||||
} else {
|
||||
for ( ap = save_attrs; ap; ap = ap->a_next ) {
|
||||
ap->a_flags = 0;
|
||||
}
|
||||
attrs_free( e->e_attrs );
|
||||
e->e_attrs = save_attrs;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int
|
||||
ldbm_back_modify(
|
||||
Operation *op,
|
||||
SlapReply *rs )
|
||||
{
|
||||
struct ldbminfo *li = (struct ldbminfo *) op->o_bd->be_private;
|
||||
Entry *matched;
|
||||
Entry *e;
|
||||
int manageDSAit = get_manageDSAit( op );
|
||||
char textbuf[SLAP_TEXT_BUFLEN];
|
||||
size_t textlen = sizeof textbuf;
|
||||
|
||||
Debug(LDAP_DEBUG_ARGS, "ldbm_back_modify:\n", 0, 0, 0);
|
||||
|
||||
slap_mods_opattrs( op, &op->orm_modlist, 1 );
|
||||
|
||||
/* grab giant lock for writing */
|
||||
ldap_pvt_thread_rdwr_wlock(&li->li_giant_rwlock);
|
||||
|
||||
/* acquire and lock entry */
|
||||
e = dn2entry_w( op->o_bd, &op->o_req_ndn, &matched );
|
||||
|
||||
/* FIXME: dn2entry() should return non-glue entry */
|
||||
if (( e == NULL ) || ( !manageDSAit && e && is_entry_glue( e ))) {
|
||||
if ( matched != NULL ) {
|
||||
rs->sr_matched = ber_strdup_x( matched->e_dn, op->o_tmpmemctx );
|
||||
rs->sr_ref = is_entry_referral( matched )
|
||||
? get_entry_referrals( op, matched )
|
||||
: NULL;
|
||||
cache_return_entry_r( &li->li_cache, matched );
|
||||
} else {
|
||||
rs->sr_ref = referral_rewrite( default_referral, NULL,
|
||||
&op->o_req_dn, LDAP_SCOPE_DEFAULT );
|
||||
}
|
||||
|
||||
rs->sr_err = LDAP_REFERRAL;
|
||||
rs->sr_flags = REP_MATCHED_MUSTBEFREED | REP_REF_MUSTBEFREED;
|
||||
goto return_results;
|
||||
}
|
||||
|
||||
if ( !manageDSAit && is_entry_referral( e ) ) {
|
||||
/* parent is a referral, don't allow add */
|
||||
/* parent is an alias, don't allow add */
|
||||
rs->sr_ref = get_entry_referrals( op, e );
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "entry is referral\n", 0,
|
||||
0, 0 );
|
||||
|
||||
rs->sr_err = LDAP_REFERRAL;
|
||||
rs->sr_matched = ber_strdup_x( e->e_name.bv_val, op->o_tmpmemctx );
|
||||
rs->sr_flags = REP_MATCHED_MUSTBEFREED | REP_REF_MUSTBEFREED;
|
||||
goto return_results;
|
||||
}
|
||||
|
||||
/* Modify the entry */
|
||||
rs->sr_err = ldbm_modify_internal( op, op->oq_modify.rs_modlist, e,
|
||||
&rs->sr_text, textbuf, textlen );
|
||||
|
||||
/* change the entry itself */
|
||||
if( rs->sr_err == LDAP_SUCCESS ) {
|
||||
if ( id2entry_add( op->o_bd, e ) != 0 ) {
|
||||
rs->sr_err = LDAP_OTHER;
|
||||
rs->sr_text = "id2entry failure";
|
||||
}
|
||||
}
|
||||
|
||||
return_results:;
|
||||
if( e != NULL ) cache_return_entry_w( &li->li_cache, e );
|
||||
ldap_pvt_thread_rdwr_wunlock(&li->li_giant_rwlock);
|
||||
|
||||
send_ldap_result( op, rs );
|
||||
slap_graduate_commit_csn( op );
|
||||
|
||||
rs->sr_text = NULL;
|
||||
return rs->sr_err;
|
||||
}
|
||||
|
|
@ -1,445 +0,0 @@
|
|||
/* modrdn.c - ldbm backend modrdn routine */
|
||||
/* $OpenLDAP$ */
|
||||
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
|
||||
*
|
||||
* Copyright 1998-2006 The OpenLDAP Foundation.
|
||||
* 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>.
|
||||
*/
|
||||
/* Portions Copyright 1999, Juan C. Gomez, All rights reserved.
|
||||
* This software is not subject to any license of Silicon Graphics
|
||||
* Inc. or Purdue University.
|
||||
*
|
||||
* Redistribution and use in source and binary forms are permitted
|
||||
* without restriction or fee of any kind as long as this notice
|
||||
* is preserved.
|
||||
*/
|
||||
|
||||
#include "portable.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <ac/string.h>
|
||||
#include <ac/socket.h>
|
||||
|
||||
#include "slap.h"
|
||||
#include "back-ldbm.h"
|
||||
#include "proto-back-ldbm.h"
|
||||
|
||||
int
|
||||
ldbm_back_modrdn(
|
||||
Operation *op,
|
||||
SlapReply *rs )
|
||||
{
|
||||
AttributeDescription *children = slap_schema.si_ad_children;
|
||||
AttributeDescription *entry = slap_schema.si_ad_entry;
|
||||
struct ldbminfo *li = (struct ldbminfo *) op->o_bd->be_private;
|
||||
struct berval p_dn, p_ndn;
|
||||
struct berval new_dn = BER_BVNULL, new_ndn = BER_BVNULL;
|
||||
struct berval old_ndn = BER_BVNULL;
|
||||
Entry *e, *p = NULL;
|
||||
Entry *matched;
|
||||
/* LDAP v2 supporting correct attribute handling. */
|
||||
int rc_id = 0;
|
||||
ID id = NOID;
|
||||
char textbuf[SLAP_TEXT_BUFLEN];
|
||||
size_t textlen = sizeof textbuf;
|
||||
/* Added to support newSuperior */
|
||||
Entry *np = NULL; /* newSuperior Entry */
|
||||
struct berval *np_ndn = NULL; /* newSuperior ndn */
|
||||
struct berval *new_parent_dn = NULL; /* np_dn, p_dn, or NULL */
|
||||
/* Used to interface with ldbm_modify_internal() */
|
||||
int manageDSAit = get_manageDSAit( op );
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"==>ldbm_back_modrdn: dn: %s newSuperior=%s\n",
|
||||
op->o_req_dn.bv_len ? op->o_req_dn.bv_val : "NULL",
|
||||
( op->oq_modrdn.rs_newSup && op->oq_modrdn.rs_newSup->bv_len )
|
||||
? op->oq_modrdn.rs_newSup->bv_val : "NULL", 0 );
|
||||
|
||||
slap_mods_opattrs( op, &op->orr_modlist, 1 );
|
||||
|
||||
/* grab giant lock for writing */
|
||||
ldap_pvt_thread_rdwr_wlock(&li->li_giant_rwlock);
|
||||
|
||||
e = dn2entry_w( op->o_bd, &op->o_req_ndn, &matched );
|
||||
|
||||
/* get entry with writer lock */
|
||||
/* FIXME: dn2entry() should return non-glue entry */
|
||||
if (( e == NULL ) || ( !manageDSAit && e && is_entry_glue( e ))) {
|
||||
if ( matched != NULL ) {
|
||||
rs->sr_matched = strdup( matched->e_dn );
|
||||
rs->sr_ref = is_entry_referral( matched )
|
||||
? get_entry_referrals( op, matched )
|
||||
: NULL;
|
||||
cache_return_entry_r( &li->li_cache, matched );
|
||||
} else {
|
||||
rs->sr_ref = referral_rewrite( default_referral, NULL,
|
||||
&op->o_req_dn, LDAP_SCOPE_DEFAULT );
|
||||
}
|
||||
|
||||
ldap_pvt_thread_rdwr_wunlock(&li->li_giant_rwlock);
|
||||
|
||||
rs->sr_err = LDAP_REFERRAL;
|
||||
send_ldap_result( op, rs );
|
||||
|
||||
if ( rs->sr_ref ) ber_bvarray_free( rs->sr_ref );
|
||||
free( (char *)rs->sr_matched );
|
||||
rs->sr_ref = NULL;
|
||||
rs->sr_matched = NULL;
|
||||
return rs->sr_err;
|
||||
}
|
||||
|
||||
/* check entry for "entry" acl */
|
||||
if ( ! access_allowed( op, e, entry, NULL, ACL_WRITE, NULL ) )
|
||||
{
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"<=- ldbm_back_modrdn: no write access to entry\n", 0,
|
||||
0, 0 );
|
||||
|
||||
send_ldap_error( op, rs, LDAP_INSUFFICIENT_ACCESS,
|
||||
"no write access to entry" );
|
||||
|
||||
goto return_results;
|
||||
}
|
||||
|
||||
if (!manageDSAit && is_entry_referral( e ) ) {
|
||||
/* parent is a referral, don't allow add */
|
||||
/* parent is an alias, don't allow add */
|
||||
rs->sr_ref = get_entry_referrals( op, e );
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "entry %s is referral\n", e->e_dn,
|
||||
0, 0 );
|
||||
|
||||
rs->sr_err = LDAP_REFERRAL;
|
||||
rs->sr_matched = e->e_name.bv_val;
|
||||
send_ldap_result( op, rs );
|
||||
|
||||
if ( rs->sr_ref ) ber_bvarray_free( rs->sr_ref );
|
||||
rs->sr_ref = NULL;
|
||||
rs->sr_matched = NULL;
|
||||
goto return_results;
|
||||
}
|
||||
|
||||
if ( has_children( op->o_bd, e ) ) {
|
||||
Debug( LDAP_DEBUG_TRACE, "entry %s has children\n", e->e_dn,
|
||||
0, 0 );
|
||||
|
||||
send_ldap_error( op, rs, LDAP_NOT_ALLOWED_ON_NONLEAF,
|
||||
"subtree rename not supported" );
|
||||
goto return_results;
|
||||
}
|
||||
|
||||
if ( be_issuffix( op->o_bd, &e->e_nname ) ) {
|
||||
p_ndn = slap_empty_bv ;
|
||||
} else {
|
||||
dnParent( &e->e_nname, &p_ndn );
|
||||
}
|
||||
|
||||
if ( p_ndn.bv_len != 0 ) {
|
||||
/* Make sure parent entry exist and we can write its
|
||||
* children.
|
||||
*/
|
||||
|
||||
if( (p = dn2entry_w( op->o_bd, &p_ndn, NULL )) == NULL) {
|
||||
Debug( LDAP_DEBUG_TRACE, "parent does not exist\n",
|
||||
0, 0, 0);
|
||||
|
||||
send_ldap_error( op, rs, LDAP_OTHER,
|
||||
"parent entry does not exist" );
|
||||
|
||||
goto return_results;
|
||||
}
|
||||
} else {
|
||||
p = (Entry *)&slap_entry_root;
|
||||
}
|
||||
|
||||
/* check parent for "children" acl */
|
||||
rs->sr_err = access_allowed( op, p, children, NULL,
|
||||
op->oq_modrdn.rs_newSup != NULL ?
|
||||
ACL_WDEL : ACL_WRITE,
|
||||
NULL );
|
||||
|
||||
if ( BER_BVISEMPTY( &p_ndn ))
|
||||
p = NULL;
|
||||
|
||||
if ( !rs->sr_err )
|
||||
{
|
||||
Debug( LDAP_DEBUG_TRACE, "no access to parent\n", 0,
|
||||
0, 0 );
|
||||
|
||||
send_ldap_error( op, rs, LDAP_INSUFFICIENT_ACCESS,
|
||||
NULL );
|
||||
goto return_results;
|
||||
}
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"ldbm_back_modrdn: wr to children of entry %s OK\n",
|
||||
p_ndn.bv_val, 0, 0 );
|
||||
|
||||
if ( p_ndn.bv_val == slap_empty_bv.bv_val ) {
|
||||
p_dn = slap_empty_bv;
|
||||
} else {
|
||||
dnParent( &e->e_name, &p_dn );
|
||||
}
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "ldbm_back_modrdn: parent dn=%s\n",
|
||||
p_dn.bv_val, 0, 0 );
|
||||
|
||||
new_parent_dn = &p_dn; /* New Parent unless newSuperior given */
|
||||
|
||||
if ( op->oq_modrdn.rs_newSup != NULL ) {
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"ldbm_back_modrdn: new parent \"%s\" requested...\n",
|
||||
op->oq_modrdn.rs_newSup->bv_val, 0, 0 );
|
||||
|
||||
np_ndn = op->oq_modrdn.rs_nnewSup;
|
||||
|
||||
/* newSuperior == oldParent? */
|
||||
if ( dn_match( &p_ndn, np_ndn ) ) {
|
||||
Debug( LDAP_DEBUG_TRACE, "ldbm_back_modrdn: "
|
||||
"new parent\"%s\" seems to be the same as the "
|
||||
"old parent \"%s\"\n",
|
||||
op->oq_modrdn.rs_newSup->bv_val, p_dn.bv_val, 0 );
|
||||
|
||||
op->oq_modrdn.rs_newSup = NULL; /* ignore newSuperior */
|
||||
}
|
||||
}
|
||||
|
||||
if ( op->oq_modrdn.rs_newSup != NULL ) {
|
||||
/* newSuperior == entry being moved?, if so ==> ERROR */
|
||||
/* Get Entry with dn=newSuperior. Does newSuperior exist? */
|
||||
|
||||
if ( op->oq_modrdn.rs_nnewSup->bv_len ) {
|
||||
if( (np = dn2entry_w( op->o_bd, np_ndn, NULL )) == NULL) {
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"ldbm_back_modrdn: newSup(ndn=%s) not here!\n",
|
||||
np_ndn->bv_val, 0, 0);
|
||||
|
||||
send_ldap_error( op, rs, LDAP_NO_SUCH_OBJECT,
|
||||
"newSuperior not found" );
|
||||
goto return_results;
|
||||
}
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"ldbm_back_modrdn: wr to new parent OK np=%p, id=%ld\n",
|
||||
(void *) np, np->e_id, 0 );
|
||||
|
||||
/* check newSuperior for "children" acl */
|
||||
if ( !access_allowed( op, np, children, NULL,
|
||||
ACL_WADD, NULL ) )
|
||||
{
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"ldbm_back_modrdn: no wr to newSup children\n",
|
||||
0, 0, 0 );
|
||||
|
||||
send_ldap_error( op, rs, LDAP_INSUFFICIENT_ACCESS, NULL );
|
||||
goto return_results;
|
||||
}
|
||||
|
||||
if ( is_entry_alias( np ) ) {
|
||||
/* parent is an alias, don't allow add */
|
||||
Debug( LDAP_DEBUG_TRACE, "entry is alias\n", 0, 0, 0 );
|
||||
|
||||
|
||||
send_ldap_error( op, rs, LDAP_ALIAS_PROBLEM,
|
||||
"newSuperior is an alias" );
|
||||
|
||||
goto return_results;
|
||||
}
|
||||
|
||||
if ( is_entry_referral( np ) ) {
|
||||
/* parent is a referral, don't allow add */
|
||||
Debug( LDAP_DEBUG_TRACE, "entry (%s) is referral\n",
|
||||
np->e_dn, 0, 0 );
|
||||
|
||||
send_ldap_error( op, rs, LDAP_OTHER,
|
||||
"newSuperior is a referral" );
|
||||
|
||||
goto return_results;
|
||||
}
|
||||
|
||||
} else {
|
||||
if ( be_issuffix( op->o_bd, (struct berval *)&slap_empty_bv )
|
||||
|| be_shadow_update( op ) ) {
|
||||
int can_access;
|
||||
np = (Entry *)&slap_entry_root;
|
||||
|
||||
can_access = access_allowed( op, np,
|
||||
children, NULL, ACL_WADD, NULL );
|
||||
np = NULL;
|
||||
|
||||
/* check parent for "children" acl */
|
||||
if ( ! can_access ) {
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"<=- ldbm_back_modrdn: no "
|
||||
"access to new superior\n", 0, 0, 0 );
|
||||
|
||||
send_ldap_error( op, rs,
|
||||
LDAP_INSUFFICIENT_ACCESS,
|
||||
NULL );
|
||||
goto return_results;
|
||||
}
|
||||
|
||||
} else {
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"<=- ldbm_back_modrdn: \"\" "
|
||||
"not allowed as new superior\n",
|
||||
0, 0, 0);
|
||||
|
||||
send_ldap_error( op, rs,
|
||||
LDAP_INSUFFICIENT_ACCESS,
|
||||
NULL );
|
||||
goto return_results;
|
||||
}
|
||||
}
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"ldbm_back_modrdn: wr to new parent's children OK\n",
|
||||
0, 0, 0 );
|
||||
|
||||
new_parent_dn = op->oq_modrdn.rs_newSup;
|
||||
}
|
||||
|
||||
/* Build target dn and make sure target entry doesn't exist already. */
|
||||
build_new_dn( &new_dn, new_parent_dn, &op->oq_modrdn.rs_newrdn, NULL );
|
||||
dnNormalize( 0, NULL, NULL, &new_dn, &new_ndn, NULL );
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "ldbm_back_modrdn: new ndn=%s\n",
|
||||
new_ndn.bv_val, 0, 0 );
|
||||
|
||||
/* check for abandon */
|
||||
if ( op->o_abandon ) {
|
||||
rs->sr_err = SLAPD_ABANDON;
|
||||
goto return_results;
|
||||
}
|
||||
|
||||
if ( ( rc_id = dn2id ( op->o_bd, &new_ndn, &id ) ) || id != NOID ) {
|
||||
/* if (rc_id) something bad happened to ldbm cache */
|
||||
rs->sr_err = rc_id ? LDAP_OTHER : LDAP_ALREADY_EXISTS;
|
||||
send_ldap_result( op, rs );
|
||||
goto return_results;
|
||||
}
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"ldbm_back_modrdn: new ndn=%s does not exist\n",
|
||||
new_ndn.bv_val, 0, 0 );
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "ldbm_back_modrdn: DN_X500\n",
|
||||
0, 0, 0 );
|
||||
|
||||
assert( op->orr_modlist != NULL );
|
||||
|
||||
/* check for abandon */
|
||||
if ( op->o_abandon ) {
|
||||
rs->sr_err = SLAPD_ABANDON;
|
||||
goto return_results;
|
||||
}
|
||||
|
||||
(void) cache_delete_entry( &li->li_cache, e );
|
||||
|
||||
free( e->e_dn );
|
||||
old_ndn = e->e_nname;
|
||||
e->e_name = new_dn;
|
||||
e->e_nname = new_ndn;
|
||||
new_dn.bv_val = NULL;
|
||||
new_ndn.bv_val = NULL;
|
||||
|
||||
/* NOTE: after this you must not free new_dn or new_ndn!
|
||||
* They are used by cache.
|
||||
*/
|
||||
|
||||
/* modify memory copy of entry */
|
||||
rs->sr_err = ldbm_modify_internal( op, op->orr_modlist, e,
|
||||
&rs->sr_text, textbuf, textlen );
|
||||
switch ( rs->sr_err ) {
|
||||
case LDAP_SUCCESS:
|
||||
break;
|
||||
|
||||
default:
|
||||
send_ldap_result( op, rs );
|
||||
/* FALLTHRU */
|
||||
case SLAPD_ABANDON:
|
||||
goto return_results;
|
||||
}
|
||||
|
||||
/*
|
||||
* NOTE: the backend MUST delete then add the entry,
|
||||
* otherwise indexing may get hosed
|
||||
* FIXME: if a new ID was used, the add could be done first.
|
||||
* that would be safer.
|
||||
*/
|
||||
|
||||
/* delete old one */
|
||||
if ( dn2id_delete( op->o_bd, &old_ndn, e->e_id ) != 0 ) {
|
||||
send_ldap_error( op, rs, LDAP_OTHER,
|
||||
"DN index delete fail" );
|
||||
goto return_results;
|
||||
}
|
||||
|
||||
/* add new one */
|
||||
if ( dn2id_add( op->o_bd, &e->e_nname, e->e_id ) != 0 ) {
|
||||
/* try to repair old entry - probably hopeless */
|
||||
if( dn2id_add( op->o_bd, &old_ndn, e->e_id) != 0 ) {
|
||||
send_ldap_error( op, rs, LDAP_OTHER,
|
||||
"DN index add and repair failed" );
|
||||
} else {
|
||||
send_ldap_error( op, rs, LDAP_OTHER,
|
||||
"DN index add failed" );
|
||||
}
|
||||
goto return_results;
|
||||
}
|
||||
|
||||
/* id2entry index */
|
||||
if ( id2entry_add( op->o_bd, e ) != 0 ) {
|
||||
/* Try to undo */
|
||||
int rc;
|
||||
rc = dn2id_delete( op->o_bd, &e->e_nname, e->e_id );
|
||||
rc |= dn2id_add( op->o_bd, &old_ndn, e->e_id );
|
||||
if( rc ) {
|
||||
send_ldap_error( op, rs, LDAP_OTHER,
|
||||
"entry update and repair failed" );
|
||||
} else {
|
||||
send_ldap_error( op, rs, LDAP_OTHER,
|
||||
"entry update failed" );
|
||||
}
|
||||
goto return_results;
|
||||
}
|
||||
|
||||
(void) cache_update_entry( &li->li_cache, e );
|
||||
|
||||
rs->sr_err = LDAP_SUCCESS;
|
||||
rs->sr_text = NULL;
|
||||
send_ldap_result( op, rs );
|
||||
cache_entry_commit( e );
|
||||
|
||||
return_results:
|
||||
slap_graduate_commit_csn( op );
|
||||
if( new_dn.bv_val != NULL ) free( new_dn.bv_val );
|
||||
if( new_ndn.bv_val != NULL ) free( new_ndn.bv_val );
|
||||
if( old_ndn.bv_val != NULL ) free( old_ndn.bv_val );
|
||||
|
||||
/* LDAP v3 Support */
|
||||
if( np != NULL ) {
|
||||
/* free new parent and writer lock */
|
||||
cache_return_entry_w( &li->li_cache, np );
|
||||
}
|
||||
|
||||
if( p != NULL ) {
|
||||
/* free parent and writer lock */
|
||||
cache_return_entry_w( &li->li_cache, p );
|
||||
}
|
||||
|
||||
/* free entry and writer lock */
|
||||
cache_return_entry_w( &li->li_cache, e );
|
||||
ldap_pvt_thread_rdwr_wunlock(&li->li_giant_rwlock);
|
||||
rs->sr_text = NULL;
|
||||
return( rs->sr_err );
|
||||
}
|
||||
|
|
@ -1,135 +0,0 @@
|
|||
/* nextid.c - keep track of the next id to be given out */
|
||||
/* $OpenLDAP$ */
|
||||
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
|
||||
*
|
||||
* Copyright 1998-2006 The OpenLDAP Foundation.
|
||||
* 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>.
|
||||
*/
|
||||
|
||||
#include "portable.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <ac/string.h>
|
||||
#include <ac/socket.h>
|
||||
#include <ac/param.h>
|
||||
|
||||
#include "slap.h"
|
||||
#include "back-ldbm.h"
|
||||
|
||||
static int
|
||||
next_id_read( Backend *be, ID *idp )
|
||||
{
|
||||
Datum key, data;
|
||||
DBCache *db;
|
||||
|
||||
*idp = NOID;
|
||||
|
||||
if ( (db = ldbm_cache_open( be, "nextid", LDBM_SUFFIX, LDBM_WRCREAT ))
|
||||
== NULL ) {
|
||||
Debug( LDAP_DEBUG_ANY, "Could not open/create nextid" LDBM_SUFFIX "\n",
|
||||
0, 0, 0 );
|
||||
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
ldbm_datum_init( key );
|
||||
key.dptr = (char *) idp;
|
||||
key.dsize = sizeof(ID);
|
||||
|
||||
data = ldbm_cache_fetch( db, key );
|
||||
|
||||
if( data.dptr != NULL ) {
|
||||
AC_MEMCPY( idp, data.dptr, sizeof( ID ) );
|
||||
ldbm_datum_free( db->dbc_db, data );
|
||||
|
||||
} else {
|
||||
*idp = 1;
|
||||
}
|
||||
|
||||
ldbm_cache_close( be, db );
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
int
|
||||
next_id_write( Backend *be, ID id )
|
||||
{
|
||||
Datum key, data;
|
||||
DBCache *db;
|
||||
ID noid = NOID;
|
||||
int flags, rc = 0;
|
||||
|
||||
if ( (db = ldbm_cache_open( be, "nextid", LDBM_SUFFIX, LDBM_WRCREAT ))
|
||||
== NULL ) {
|
||||
Debug( LDAP_DEBUG_ANY, "Could not open/create nextid" LDBM_SUFFIX "\n",
|
||||
0, 0, 0 );
|
||||
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
ldbm_datum_init( key );
|
||||
ldbm_datum_init( data );
|
||||
|
||||
key.dptr = (char *) &noid;
|
||||
key.dsize = sizeof(ID);
|
||||
|
||||
data.dptr = (char *) &id;
|
||||
data.dsize = sizeof(ID);
|
||||
|
||||
flags = LDBM_REPLACE;
|
||||
if ( ldbm_cache_store( db, key, data, flags ) != 0 ) {
|
||||
rc = -1;
|
||||
}
|
||||
|
||||
ldbm_cache_close( be, db );
|
||||
return( rc );
|
||||
}
|
||||
|
||||
int
|
||||
next_id_get( Backend *be, ID *idp )
|
||||
{
|
||||
struct ldbminfo *li = (struct ldbminfo *) be->be_private;
|
||||
int rc = 0;
|
||||
|
||||
*idp = NOID;
|
||||
|
||||
if ( li->li_nextid == NOID ) {
|
||||
if ( ( rc = next_id_read( be, idp ) ) ) {
|
||||
return( rc );
|
||||
}
|
||||
li->li_nextid = *idp;
|
||||
}
|
||||
|
||||
*idp = li->li_nextid;
|
||||
|
||||
return( rc );
|
||||
}
|
||||
|
||||
int
|
||||
next_id( Backend *be, ID *idp )
|
||||
{
|
||||
struct ldbminfo *li = (struct ldbminfo *) be->be_private;
|
||||
int rc = 0;
|
||||
|
||||
if ( li->li_nextid == NOID ) {
|
||||
if ( ( rc = next_id_read( be, idp ) ) ) {
|
||||
return( rc );
|
||||
}
|
||||
li->li_nextid = *idp;
|
||||
}
|
||||
|
||||
*idp = li->li_nextid++;
|
||||
if ( next_id_write( be, li->li_nextid ) ) {
|
||||
rc = -1;
|
||||
}
|
||||
|
||||
return( rc );
|
||||
}
|
||||
|
|
@ -1,77 +0,0 @@
|
|||
/* operational.c - ldbm backend operational attributes function */
|
||||
/* $OpenLDAP$ */
|
||||
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
|
||||
*
|
||||
* Copyright 1998-2006 The OpenLDAP Foundation.
|
||||
* 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>.
|
||||
*/
|
||||
|
||||
#include "portable.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <ac/string.h>
|
||||
#include <ac/socket.h>
|
||||
|
||||
#include "slap.h"
|
||||
#include "back-ldbm.h"
|
||||
#include "proto-back-ldbm.h"
|
||||
|
||||
/*
|
||||
* sets *hasSubordinates to LDAP_COMPARE_TRUE/LDAP_COMPARE_FALSE
|
||||
* if the entry has children or not.
|
||||
*/
|
||||
int
|
||||
ldbm_back_hasSubordinates(
|
||||
Operation *op,
|
||||
Entry *e,
|
||||
int *hasSubordinates )
|
||||
{
|
||||
if ( has_children( op->o_bd, e ) ) {
|
||||
*hasSubordinates = LDAP_COMPARE_TRUE;
|
||||
|
||||
} else {
|
||||
*hasSubordinates = LDAP_COMPARE_FALSE;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* sets the supported operational attributes (if required)
|
||||
*/
|
||||
int
|
||||
ldbm_back_operational(
|
||||
Operation *op,
|
||||
SlapReply *rs )
|
||||
{
|
||||
Attribute **ap;
|
||||
|
||||
assert( rs->sr_entry != NULL );
|
||||
|
||||
for ( ap = &rs->sr_operational_attrs; *ap; ap = &(*ap)->a_next )
|
||||
/* just count */ ;
|
||||
|
||||
if ( SLAP_OPATTRS( rs->sr_attr_flags ) ||
|
||||
ad_inlist( slap_schema.si_ad_hasSubordinates, rs->sr_attrs ) )
|
||||
{
|
||||
int hs;
|
||||
|
||||
hs = has_children( op->o_bd, rs->sr_entry );
|
||||
*ap = slap_operational_hasSubordinate( hs );
|
||||
assert( *ap != NULL );
|
||||
|
||||
ap = &(*ap)->a_next;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -1,263 +0,0 @@
|
|||
/* $OpenLDAP$ */
|
||||
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
|
||||
*
|
||||
* Copyright 1998-2006 The OpenLDAP Foundation.
|
||||
* 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>.
|
||||
*/
|
||||
|
||||
#ifndef _PROTO_BACK_LDBM
|
||||
#define _PROTO_BACK_LDBM
|
||||
|
||||
#include <ldap_cdefs.h>
|
||||
|
||||
LDAP_BEGIN_DECL
|
||||
|
||||
/*
|
||||
* alias.c
|
||||
*/
|
||||
Entry *deref_internal_r LDAP_P((
|
||||
Backend *be,
|
||||
Entry *e,
|
||||
struct berval *dn,
|
||||
int *err,
|
||||
Entry **matched,
|
||||
const char **text ));
|
||||
|
||||
#define deref_entry_r( be, e, err, matched, text ) \
|
||||
deref_internal_r( be, e, NULL, err, matched, text )
|
||||
#define deref_dn_r( be, dn, err, matched, text ) \
|
||||
deref_internal_r( be, NULL, dn, err, matched, text)
|
||||
|
||||
/*
|
||||
* attr.c
|
||||
*/
|
||||
|
||||
void attr_mask LDAP_P(( struct ldbminfo *li,
|
||||
AttributeDescription *desc,
|
||||
slap_mask_t *indexmask ));
|
||||
|
||||
int attr_index_config LDAP_P(( struct ldbminfo *li,
|
||||
const char *fname, int lineno,
|
||||
int argc, char **argv ));
|
||||
void attr_index_destroy LDAP_P(( Avlnode *tree ));
|
||||
|
||||
/*
|
||||
* cache.c
|
||||
*/
|
||||
|
||||
int cache_add_entry_rw LDAP_P(( Cache *cache, Entry *e, int rw ));
|
||||
int cache_update_entry LDAP_P(( Cache *cache, Entry *e ));
|
||||
void cache_return_entry_rw LDAP_P(( Cache *cache, Entry *e, int rw ));
|
||||
#define cache_return_entry_r(c, e) cache_return_entry_rw((c), (e), 0)
|
||||
#define cache_return_entry_w(c, e) cache_return_entry_rw((c), (e), 1)
|
||||
void cache_entry_commit LDAP_P(( Entry *e ));
|
||||
|
||||
ID cache_find_entry_ndn2id LDAP_P(( Backend *be, Cache *cache, struct berval *ndn ));
|
||||
Entry * cache_find_entry_id LDAP_P(( Cache *cache, ID id, int rw ));
|
||||
int cache_delete_entry LDAP_P(( Cache *cache, Entry *e ));
|
||||
void cache_release_all LDAP_P(( Cache *cache ));
|
||||
|
||||
/*
|
||||
* dbcache.c
|
||||
*/
|
||||
|
||||
DBCache * ldbm_cache_open LDAP_P(( Backend *be,
|
||||
const char *name, const char *suffix, int flags ));
|
||||
void ldbm_cache_close LDAP_P(( Backend *be, DBCache *db ));
|
||||
void ldbm_cache_really_close LDAP_P(( Backend *be, DBCache *db ));
|
||||
void ldbm_cache_flush_all LDAP_P(( Backend *be ));
|
||||
void ldbm_cache_sync LDAP_P(( Backend *be ));
|
||||
#if 0 /* replaced by macro */
|
||||
Datum ldbm_cache_fetch LDAP_P(( DBCache *db, Datum key ));
|
||||
#else /* 1 */
|
||||
#define ldbm_cache_fetch( db, key ) ldbm_fetch( (db)->dbc_db, (key) )
|
||||
#endif /* 1 */
|
||||
int ldbm_cache_store LDAP_P(( DBCache *db, Datum key, Datum data, int flags ));
|
||||
int ldbm_cache_delete LDAP_P(( DBCache *db, Datum key ));
|
||||
void *ldbm_cache_sync_daemon LDAP_P(( void *ctx, void *arg ));
|
||||
|
||||
/*
|
||||
* dn2id.c
|
||||
*/
|
||||
|
||||
int dn2id_add LDAP_P(( Backend *be, struct berval *dn, ID id ));
|
||||
int dn2id LDAP_P(( Backend *be, struct berval *dn, ID *idp ));
|
||||
int dn2idl LDAP_P(( Backend *be, struct berval *dn, int prefix, ID_BLOCK **idlp ));
|
||||
int dn2id_delete LDAP_P(( Backend *be, struct berval *dn, ID id ));
|
||||
|
||||
Entry * dn2entry_rw LDAP_P(( Backend *be, struct berval *dn, Entry **matched, int rw ));
|
||||
#define dn2entry_r(be, dn, m) dn2entry_rw((be), (dn), (m), 0)
|
||||
#define dn2entry_w(be, dn, m) dn2entry_rw((be), (dn), (m), 1)
|
||||
|
||||
/*
|
||||
* entry.c
|
||||
*/
|
||||
BI_entry_release_rw ldbm_back_entry_release_rw;
|
||||
BI_entry_get_rw ldbm_back_entry_get;
|
||||
|
||||
/*
|
||||
* filterindex.c
|
||||
*/
|
||||
|
||||
ID_BLOCK * filter_candidates LDAP_P(( Operation *op, Filter *f ));
|
||||
|
||||
/*
|
||||
* id2children.c
|
||||
*/
|
||||
|
||||
int id2children_add LDAP_P(( Backend *be, Entry *p, Entry *e ));
|
||||
int id2children_remove LDAP_P(( Backend *be, Entry *p, Entry *e ));
|
||||
int has_children LDAP_P(( Backend *be, Entry *p ));
|
||||
|
||||
/*
|
||||
* id2entry.c
|
||||
*/
|
||||
|
||||
int id2entry_add LDAP_P(( Backend *be, Entry *e ));
|
||||
int id2entry_delete LDAP_P(( Backend *be, Entry *e ));
|
||||
|
||||
Entry * id2entry_rw LDAP_P(( Backend *be, ID id, int rw ));
|
||||
#define id2entry_r(be, id) id2entry_rw((be), (id), 0)
|
||||
#define id2entry_w(be, id) id2entry_rw((be), (id), 1)
|
||||
|
||||
/*
|
||||
* idl.c
|
||||
*/
|
||||
|
||||
ID_BLOCK * idl_alloc LDAP_P(( unsigned int nids ));
|
||||
ID_BLOCK * idl_allids LDAP_P(( Backend *be ));
|
||||
void idl_free LDAP_P(( ID_BLOCK *idl ));
|
||||
ID_BLOCK * idl_fetch LDAP_P(( Backend *be, DBCache *db, Datum key ));
|
||||
int idl_insert_key LDAP_P(( Backend *be, DBCache *db, Datum key, ID id ));
|
||||
int idl_insert LDAP_P(( ID_BLOCK **idl, ID id, unsigned int maxids ));
|
||||
int idl_delete_key LDAP_P(( Backend *be, DBCache *db, Datum key, ID id ));
|
||||
ID_BLOCK * idl_intersection LDAP_P(( Backend *be, ID_BLOCK *a, ID_BLOCK *b ));
|
||||
ID_BLOCK * idl_union LDAP_P(( Backend *be, ID_BLOCK *a, ID_BLOCK *b ));
|
||||
ID_BLOCK * idl_notin LDAP_P(( Backend *be, ID_BLOCK *a, ID_BLOCK *b ));
|
||||
ID idl_firstid LDAP_P(( ID_BLOCK *idl, ID *cursor ));
|
||||
ID idl_nextid LDAP_P(( ID_BLOCK *idl, ID *cursor ));
|
||||
|
||||
/*
|
||||
* index.c
|
||||
*/
|
||||
extern int
|
||||
index_is_indexed LDAP_P((
|
||||
Backend *be,
|
||||
AttributeDescription *desc ));
|
||||
|
||||
extern int
|
||||
index_param LDAP_P((
|
||||
Backend *be,
|
||||
AttributeDescription *desc,
|
||||
int ftype,
|
||||
char **dbname,
|
||||
slap_mask_t *mask,
|
||||
struct berval *prefix ));
|
||||
|
||||
extern int
|
||||
index_values LDAP_P((
|
||||
Operation *op,
|
||||
AttributeDescription *desc,
|
||||
BerVarray vals,
|
||||
ID id,
|
||||
int opid ));
|
||||
|
||||
int index_entry LDAP_P(( Operation *op, int r, Entry *e ));
|
||||
#define index_entry_add(be,e) index_entry((be),SLAP_INDEX_ADD_OP,(e))
|
||||
#define index_entry_del(be,e) index_entry((be),SLAP_INDEX_DELETE_OP,(e))
|
||||
|
||||
|
||||
/*
|
||||
* key.c
|
||||
*/
|
||||
extern int
|
||||
key_change LDAP_P((
|
||||
Backend *be,
|
||||
DBCache *db,
|
||||
struct berval *k,
|
||||
ID id,
|
||||
int op ));
|
||||
extern int
|
||||
key_read LDAP_P((
|
||||
Backend *be,
|
||||
DBCache *db,
|
||||
struct berval *k,
|
||||
ID_BLOCK **idout ));
|
||||
|
||||
/*
|
||||
* modify.c
|
||||
* These prototypes are placed here because they are used by modify and
|
||||
* modify rdn which are implemented in different files.
|
||||
*
|
||||
* We need ldbm_internal_modify here because of LDAP modrdn & modify use
|
||||
* it. If we do not add this, there would be a bunch of code replication
|
||||
* here and there and of course the likelihood of bugs increases.
|
||||
* Juan C. Gomez (gomez@engr.sgi.com) 05/18/99
|
||||
*
|
||||
*/
|
||||
|
||||
/* returns LDAP error code indicating error OR SLAPD_ABANDON */
|
||||
int ldbm_modify_internal LDAP_P(( Operation *op,
|
||||
Modifications *mods, Entry *e,
|
||||
const char **text, char *textbuf, size_t textlen ));
|
||||
|
||||
/*
|
||||
* nextid.c
|
||||
*/
|
||||
|
||||
int next_id LDAP_P(( Backend *be, ID *idp ));
|
||||
int next_id_get LDAP_P(( Backend *be, ID *idp ));
|
||||
int next_id_write LDAP_P(( Backend *be, ID id ));
|
||||
|
||||
/*
|
||||
* former external.h
|
||||
*/
|
||||
|
||||
extern BI_init ldbm_back_initialize;
|
||||
|
||||
extern BI_open ldbm_back_open;
|
||||
extern BI_close ldbm_back_close;
|
||||
extern BI_destroy ldbm_back_destroy;
|
||||
|
||||
extern BI_db_init ldbm_back_db_init;
|
||||
extern BI_db_open ldbm_back_db_open;
|
||||
extern BI_db_close ldbm_back_db_close;
|
||||
extern BI_db_destroy ldbm_back_db_destroy;
|
||||
extern BI_db_config ldbm_back_db_config;
|
||||
|
||||
extern BI_op_extended ldbm_back_extended;
|
||||
extern BI_op_bind ldbm_back_bind;
|
||||
extern BI_op_search ldbm_back_search;
|
||||
extern BI_op_compare ldbm_back_compare;
|
||||
extern BI_op_modify ldbm_back_modify;
|
||||
extern BI_op_modrdn ldbm_back_modrdn;
|
||||
extern BI_op_add ldbm_back_add;
|
||||
extern BI_op_delete ldbm_back_delete;
|
||||
|
||||
extern BI_operational ldbm_back_operational;
|
||||
extern BI_has_subordinates ldbm_back_hasSubordinates;
|
||||
|
||||
/* hooks for slap tools */
|
||||
extern BI_tool_entry_open ldbm_tool_entry_open;
|
||||
extern BI_tool_entry_close ldbm_tool_entry_close;
|
||||
extern BI_tool_entry_first ldbm_tool_entry_first;
|
||||
extern BI_tool_entry_next ldbm_tool_entry_next;
|
||||
extern BI_tool_entry_get ldbm_tool_entry_get;
|
||||
extern BI_tool_entry_put ldbm_tool_entry_put;
|
||||
|
||||
extern BI_tool_entry_reindex ldbm_tool_entry_reindex;
|
||||
extern BI_tool_sync ldbm_tool_sync;
|
||||
|
||||
extern BI_chk_referrals ldbm_back_referrals;
|
||||
|
||||
LDAP_END_DECL
|
||||
|
||||
#endif /* _PROTO_BACK_LDBM */
|
||||
|
|
@ -1,127 +0,0 @@
|
|||
/* referral.c - LDBM backend referral handler */
|
||||
/* $OpenLDAP$ */
|
||||
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
|
||||
*
|
||||
* Copyright 1998-2006 The OpenLDAP Foundation.
|
||||
* 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>.
|
||||
*/
|
||||
|
||||
#include "portable.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <ac/string.h>
|
||||
#include <ac/socket.h>
|
||||
|
||||
#include "slap.h"
|
||||
#include "back-ldbm.h"
|
||||
|
||||
int
|
||||
ldbm_back_referrals(
|
||||
Operation *op,
|
||||
SlapReply *rs )
|
||||
{
|
||||
struct ldbminfo *li = (struct ldbminfo *) op->o_bd->be_private;
|
||||
Entry *e, *matched;
|
||||
int rc = LDAP_SUCCESS;
|
||||
|
||||
if( op->o_tag == LDAP_REQ_SEARCH ) {
|
||||
/* let search take care of itself */
|
||||
return LDAP_SUCCESS;
|
||||
}
|
||||
|
||||
if( get_manageDSAit( op ) ) {
|
||||
/* let op take care of DSA management */
|
||||
return LDAP_SUCCESS;
|
||||
}
|
||||
|
||||
/* grab giant lock for reading */
|
||||
ldap_pvt_thread_rdwr_rlock(&li->li_giant_rwlock);
|
||||
|
||||
/* get entry with reader lock */
|
||||
e = dn2entry_r( op->o_bd, &op->o_req_ndn, &matched );
|
||||
if ( e == NULL ) {
|
||||
if ( matched != NULL ) {
|
||||
rs->sr_matched = ch_strdup( matched->e_dn );
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"ldbm_referrals: op=%ld target=\"%s\" matched=\"%s\"\n",
|
||||
op->o_tag, op->o_req_dn.bv_val, rs->sr_matched );
|
||||
|
||||
if ( is_entry_referral( matched ) ) {
|
||||
rc = rs->sr_err = LDAP_OTHER;
|
||||
rs->sr_ref = get_entry_referrals( op, matched );
|
||||
}
|
||||
|
||||
cache_return_entry_r( &li->li_cache, matched );
|
||||
|
||||
} else if ( !be_issuffix( op->o_bd, &op->o_req_ndn ) && default_referral != NULL ) {
|
||||
rc = rs->sr_err = LDAP_OTHER;
|
||||
rs->sr_ref = referral_rewrite( default_referral,
|
||||
NULL, &op->o_req_dn, LDAP_SCOPE_DEFAULT );
|
||||
}
|
||||
|
||||
ldap_pvt_thread_rdwr_runlock(&li->li_giant_rwlock);
|
||||
|
||||
if ( rs->sr_ref != NULL ) {
|
||||
/* send referrals */
|
||||
rc = rs->sr_err = LDAP_REFERRAL;
|
||||
|
||||
} else {
|
||||
rs->sr_text = rs->sr_matched ? "bad referral object" : "bad default referral";
|
||||
}
|
||||
|
||||
if ( rc != LDAP_SUCCESS ) {
|
||||
send_ldap_result( op, rs );
|
||||
}
|
||||
|
||||
if ( rs->sr_matched ) free( (char *)rs->sr_matched );
|
||||
if ( rs->sr_ref ) ber_bvarray_free( rs->sr_ref );
|
||||
rs->sr_text = NULL;
|
||||
rs->sr_ref = NULL;
|
||||
rs->sr_matched = NULL;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
if ( is_entry_referral( e ) ) {
|
||||
/* entry is a referral */
|
||||
BerVarray refs = get_entry_referrals( op, e );
|
||||
rs->sr_ref = referral_rewrite(
|
||||
refs, &e->e_name, &op->o_req_dn, LDAP_SCOPE_DEFAULT );
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"ldbm_referrals: op=%ld target=\"%s\" matched=\"%s\"\n",
|
||||
op->o_tag, op->o_req_dn.bv_val, e->e_dn );
|
||||
|
||||
rs->sr_matched = e->e_name.bv_val;
|
||||
if( rs->sr_ref != NULL ) {
|
||||
rc = rs->sr_err = LDAP_REFERRAL;
|
||||
rs->sr_text = NULL;
|
||||
|
||||
} else {
|
||||
rc = rs->sr_err = LDAP_OTHER;
|
||||
rs->sr_text = "bad referral object";
|
||||
}
|
||||
send_ldap_result( op, rs );
|
||||
|
||||
if ( refs != NULL ) ber_bvarray_free( refs );
|
||||
rs->sr_err = rc;
|
||||
rs->sr_ref = NULL;
|
||||
rs->sr_text = NULL;
|
||||
rs->sr_matched = NULL;
|
||||
}
|
||||
|
||||
cache_return_entry_r( &li->li_cache, e );
|
||||
ldap_pvt_thread_rdwr_runlock(&li->li_giant_rwlock);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
|
@ -1,571 +0,0 @@
|
|||
/* search.c - ldbm backend search function */
|
||||
/* $OpenLDAP$ */
|
||||
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
|
||||
*
|
||||
* Copyright 1998-2006 The OpenLDAP Foundation.
|
||||
* 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>.
|
||||
*/
|
||||
|
||||
#include "portable.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <ac/string.h>
|
||||
#include <ac/socket.h>
|
||||
|
||||
#include "slap.h"
|
||||
#include "back-ldbm.h"
|
||||
#include "proto-back-ldbm.h"
|
||||
|
||||
static ID_BLOCK *base_candidate(
|
||||
Backend *be, Entry *e );
|
||||
|
||||
static ID_BLOCK *search_candidates(
|
||||
Operation *op, Entry *e, Filter *filter,
|
||||
int scope, int deref, int manageDSAit );
|
||||
|
||||
|
||||
int
|
||||
ldbm_back_search(
|
||||
Operation *op,
|
||||
SlapReply *rs )
|
||||
{
|
||||
struct ldbminfo *li = (struct ldbminfo *) op->o_bd->be_private;
|
||||
int rc;
|
||||
time_t stoptime;
|
||||
ID_BLOCK *candidates;
|
||||
ID id, cursor;
|
||||
Entry *e;
|
||||
Entry *matched = NULL;
|
||||
struct berval realbase = BER_BVNULL;
|
||||
int manageDSAit = get_manageDSAit( op );
|
||||
#ifdef SLAP_ACL_HONOR_DISCLOSE
|
||||
slap_mask_t mask;
|
||||
#endif
|
||||
|
||||
Debug(LDAP_DEBUG_TRACE, "=> ldbm_back_search\n", 0, 0, 0);
|
||||
|
||||
/* grab giant lock for reading */
|
||||
ldap_pvt_thread_rdwr_rlock(&li->li_giant_rwlock);
|
||||
|
||||
if ( op->o_req_ndn.bv_len == 0 ) {
|
||||
/* DIT root special case */
|
||||
e = (Entry *) &slap_entry_root;
|
||||
|
||||
/* need normalized dn below */
|
||||
ber_dupbv( &realbase, &e->e_nname );
|
||||
|
||||
candidates = search_candidates( op, e, op->ors_filter,
|
||||
op->ors_scope, op->ors_deref,
|
||||
manageDSAit || get_domainScope(op) );
|
||||
|
||||
goto searchit;
|
||||
|
||||
} else if ( op->ors_deref & LDAP_DEREF_FINDING ) {
|
||||
/* deref dn and get entry with reader lock */
|
||||
e = deref_dn_r( op->o_bd, &op->o_req_ndn,
|
||||
&rs->sr_err, &matched, &rs->sr_text );
|
||||
|
||||
if( rs->sr_err == LDAP_NO_SUCH_OBJECT ) rs->sr_err = LDAP_REFERRAL;
|
||||
|
||||
} else {
|
||||
/* get entry with reader lock */
|
||||
e = dn2entry_r( op->o_bd, &op->o_req_ndn, &matched );
|
||||
rs->sr_err = e != NULL ? LDAP_SUCCESS : LDAP_REFERRAL;
|
||||
rs->sr_text = NULL;
|
||||
}
|
||||
|
||||
if ( e == NULL ) {
|
||||
struct berval matched_dn = BER_BVNULL;
|
||||
|
||||
if ( matched != NULL ) {
|
||||
BerVarray erefs = NULL;
|
||||
|
||||
#ifdef SLAP_ACL_HONOR_DISCLOSE
|
||||
if ( ! access_allowed( op, matched,
|
||||
slap_schema.si_ad_entry,
|
||||
NULL, ACL_DISCLOSE, NULL ) )
|
||||
{
|
||||
rs->sr_err = LDAP_NO_SUCH_OBJECT;
|
||||
|
||||
} else
|
||||
#endif /* SLAP_ACL_HONOR_DISCLOSE */
|
||||
{
|
||||
ber_dupbv( &matched_dn, &matched->e_name );
|
||||
|
||||
erefs = is_entry_referral( matched )
|
||||
? get_entry_referrals( op, matched )
|
||||
: NULL;
|
||||
}
|
||||
|
||||
cache_return_entry_r( &li->li_cache, matched );
|
||||
|
||||
if ( erefs ) {
|
||||
rs->sr_ref = referral_rewrite( erefs, &matched_dn,
|
||||
&op->o_req_dn, op->ors_scope );
|
||||
|
||||
ber_bvarray_free( erefs );
|
||||
}
|
||||
|
||||
} else {
|
||||
rs->sr_ref = referral_rewrite( default_referral,
|
||||
NULL, &op->o_req_dn, op->ors_scope );
|
||||
}
|
||||
|
||||
ldap_pvt_thread_rdwr_runlock(&li->li_giant_rwlock);
|
||||
|
||||
rs->sr_matched = matched_dn.bv_val;
|
||||
send_ldap_result( op, rs );
|
||||
|
||||
ber_bvarray_free( rs->sr_ref );
|
||||
ber_memfree( matched_dn.bv_val );
|
||||
rs->sr_ref = NULL;
|
||||
rs->sr_matched = NULL;
|
||||
return rs->sr_err;
|
||||
}
|
||||
|
||||
#ifdef SLAP_ACL_HONOR_DISCLOSE
|
||||
/* NOTE: __NEW__ "search" access is required
|
||||
* on searchBase object */
|
||||
if ( ! access_allowed_mask( op, e, slap_schema.si_ad_entry,
|
||||
NULL, ACL_SEARCH, NULL, &mask ) )
|
||||
{
|
||||
if ( !ACL_GRANT( mask, ACL_DISCLOSE ) ) {
|
||||
rs->sr_err = LDAP_NO_SUCH_OBJECT;
|
||||
} else {
|
||||
rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
|
||||
}
|
||||
|
||||
cache_return_entry_r( &li->li_cache, e );
|
||||
ldap_pvt_thread_rdwr_runlock(&li->li_giant_rwlock);
|
||||
|
||||
send_ldap_result( op, rs );
|
||||
return rs->sr_err;
|
||||
}
|
||||
#endif /* SLAP_ACL_HONOR_DISCLOSE */
|
||||
|
||||
if ( !manageDSAit && is_entry_referral( e ) ) {
|
||||
/* entry is a referral, don't allow add */
|
||||
struct berval matched_dn = BER_BVNULL;
|
||||
BerVarray erefs = NULL;
|
||||
|
||||
rs->sr_ref = NULL;
|
||||
rs->sr_err = LDAP_OTHER;
|
||||
rs->sr_text = "bad referral object";
|
||||
|
||||
ber_dupbv( &matched_dn, &e->e_name );
|
||||
erefs = get_entry_referrals( op, e );
|
||||
|
||||
cache_return_entry_r( &li->li_cache, e );
|
||||
ldap_pvt_thread_rdwr_runlock(&li->li_giant_rwlock);
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"ldbm_search: entry is referral\n",
|
||||
0, 0, 0 );
|
||||
|
||||
if ( erefs ) {
|
||||
rs->sr_ref = referral_rewrite( erefs, &matched_dn,
|
||||
&op->o_req_dn, op->ors_scope );
|
||||
|
||||
ber_bvarray_free( erefs );
|
||||
|
||||
if ( rs->sr_ref ) {
|
||||
rs->sr_err = LDAP_REFERRAL;
|
||||
rs->sr_text = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
rs->sr_matched = matched_dn.bv_val;
|
||||
send_ldap_result( op, rs );
|
||||
ber_bvarray_free( rs->sr_ref );
|
||||
ber_memfree( matched_dn.bv_val );
|
||||
rs->sr_ref = NULL;
|
||||
rs->sr_matched = NULL;
|
||||
return rs->sr_err;
|
||||
}
|
||||
|
||||
if ( is_entry_alias( e ) ) {
|
||||
/* don't deref */
|
||||
op->ors_deref = LDAP_DEREF_NEVER;
|
||||
}
|
||||
|
||||
if ( op->ors_scope == LDAP_SCOPE_BASE ) {
|
||||
candidates = base_candidate( op->o_bd, e );
|
||||
|
||||
} else {
|
||||
candidates = search_candidates( op, e, op->ors_filter,
|
||||
op->ors_scope, op->ors_deref, manageDSAit );
|
||||
}
|
||||
|
||||
/* need normalized dn below */
|
||||
ber_dupbv( &realbase, &e->e_nname );
|
||||
|
||||
cache_return_entry_r( &li->li_cache, e );
|
||||
|
||||
searchit:
|
||||
if ( candidates == NULL ) {
|
||||
/* no candidates */
|
||||
Debug( LDAP_DEBUG_TRACE, "ldbm_search: no candidates\n",
|
||||
0, 0, 0 );
|
||||
|
||||
rs->sr_err = LDAP_SUCCESS;
|
||||
send_ldap_result( op, rs );
|
||||
|
||||
rc = LDAP_SUCCESS;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* if candidates exceed to-be-checked entries, abort */
|
||||
if ( op->ors_limit /* isroot == FALSE */
|
||||
&& op->ors_limit->lms_s_unchecked != -1
|
||||
&& ID_BLOCK_NIDS( candidates ) > (unsigned) op->ors_limit->lms_s_unchecked )
|
||||
{
|
||||
send_ldap_error( op, rs, LDAP_ADMINLIMIT_EXCEEDED, NULL );
|
||||
rc = LDAP_SUCCESS;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* compute it anyway; root does not use it */
|
||||
stoptime = op->o_time + op->ors_tlimit;
|
||||
rs->sr_attrs = op->ors_attrs;
|
||||
|
||||
for ( id = idl_firstid( candidates, &cursor ); id != NOID;
|
||||
id = idl_nextid( candidates, &cursor ) )
|
||||
{
|
||||
int scopeok = 0;
|
||||
int result = 0;
|
||||
|
||||
/* check for abandon */
|
||||
if ( op->o_abandon ) {
|
||||
rc = SLAPD_ABANDON;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* check time limit */
|
||||
if ( op->ors_tlimit != SLAP_NO_LIMIT
|
||||
&& slap_get_time() > stoptime )
|
||||
{
|
||||
rs->sr_err = LDAP_TIMELIMIT_EXCEEDED;
|
||||
send_ldap_result( op, rs );
|
||||
rc = LDAP_SUCCESS;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* get the entry with reader lock */
|
||||
e = id2entry_r( op->o_bd, id );
|
||||
|
||||
if ( e == NULL ) {
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"ldbm_search: candidate %ld not found\n",
|
||||
id, 0, 0 );
|
||||
|
||||
goto loop_continue;
|
||||
}
|
||||
|
||||
rs->sr_entry = e;
|
||||
|
||||
if ( is_entry_subentry( e ) ) {
|
||||
if( op->ors_scope != LDAP_SCOPE_BASE ) {
|
||||
if(!get_subentries_visibility( op )) {
|
||||
/* only subentries are visible */
|
||||
goto loop_continue;
|
||||
}
|
||||
} else if ( get_subentries( op ) &&
|
||||
!get_subentries_visibility( op ))
|
||||
{
|
||||
/* only subentries are visible */
|
||||
goto loop_continue;
|
||||
}
|
||||
} else if ( get_subentries_visibility( op )) {
|
||||
/* only subentries are visible */
|
||||
goto loop_continue;
|
||||
}
|
||||
|
||||
if ( op->ors_deref & LDAP_DEREF_SEARCHING &&
|
||||
is_entry_alias( e ) )
|
||||
{
|
||||
Entry *matched;
|
||||
int err;
|
||||
const char *text;
|
||||
|
||||
e = deref_entry_r( op->o_bd, e, &err, &matched, &text );
|
||||
|
||||
if( e == NULL ) {
|
||||
e = matched;
|
||||
goto loop_continue;
|
||||
}
|
||||
|
||||
if( e->e_id == id ) {
|
||||
/* circular loop */
|
||||
goto loop_continue;
|
||||
}
|
||||
|
||||
/* need to skip alias which deref into scope */
|
||||
if( op->ors_scope == LDAP_SCOPE_ONELEVEL ) {
|
||||
struct berval pdn;
|
||||
dnParent( &e->e_nname, &pdn );
|
||||
if ( ber_bvcmp( &pdn, &realbase ) ) {
|
||||
goto loop_continue;
|
||||
}
|
||||
|
||||
} else if ( dnIsSuffix( &e->e_nname, &realbase ) ) {
|
||||
/* alias is within scope */
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"ldbm_search: alias \"%s\" in subtree\n",
|
||||
e->e_dn, 0, 0 );
|
||||
|
||||
goto loop_continue;
|
||||
}
|
||||
|
||||
rs->sr_entry = e;
|
||||
|
||||
scopeok = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* If it's a referral, add it to the list of referrals.
|
||||
* Only do this for non-base searches, and don't check
|
||||
* the filter explicitly here since it's only a candidate
|
||||
* anyway.
|
||||
*/
|
||||
if ( !manageDSAit && op->ors_scope != LDAP_SCOPE_BASE &&
|
||||
is_entry_referral( e ) )
|
||||
{
|
||||
struct berval dn;
|
||||
|
||||
/* check scope */
|
||||
if ( !scopeok && op->ors_scope == LDAP_SCOPE_ONELEVEL ) {
|
||||
if ( !be_issuffix( op->o_bd, &e->e_nname ) ) {
|
||||
dnParent( &e->e_nname, &dn );
|
||||
scopeok = dn_match( &dn, &realbase );
|
||||
} else {
|
||||
scopeok = (realbase.bv_len == 0);
|
||||
}
|
||||
|
||||
} else if ( !scopeok
|
||||
&& op->ors_scope == LDAP_SCOPE_SUBTREE )
|
||||
{
|
||||
scopeok = dnIsSuffix( &e->e_nname, &realbase );
|
||||
|
||||
#ifdef LDAP_SCOPE_SUBORDINATE
|
||||
} else if ( !scopeok
|
||||
&& op->ors_scope == LDAP_SCOPE_SUBORDINATE )
|
||||
{
|
||||
scopeok = !dn_match( &e->e_nname, &realbase )
|
||||
&& dnIsSuffix( &e->e_nname, &realbase );
|
||||
#endif
|
||||
|
||||
} else {
|
||||
scopeok = 1;
|
||||
}
|
||||
|
||||
if( scopeok ) {
|
||||
BerVarray erefs = get_entry_referrals( op, e );
|
||||
rs->sr_ref = referral_rewrite( erefs,
|
||||
&e->e_name, NULL,
|
||||
op->ors_scope == LDAP_SCOPE_ONELEVEL
|
||||
? LDAP_SCOPE_BASE
|
||||
: LDAP_SCOPE_SUBTREE );
|
||||
|
||||
ber_bvarray_free( erefs );
|
||||
|
||||
send_search_reference( op, rs );
|
||||
|
||||
ber_bvarray_free( rs->sr_ref );
|
||||
rs->sr_ref = NULL;
|
||||
|
||||
} else {
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"ldbm_search: candidate referral %ld scope not okay\n",
|
||||
id, 0, 0 );
|
||||
}
|
||||
|
||||
goto loop_continue;
|
||||
}
|
||||
|
||||
if ( !manageDSAit && is_entry_glue( e )) {
|
||||
goto loop_continue;
|
||||
}
|
||||
|
||||
/* if it matches the filter and scope, send it */
|
||||
result = test_filter( op, e, op->ors_filter );
|
||||
|
||||
if ( result == LDAP_COMPARE_TRUE ) {
|
||||
struct berval dn;
|
||||
|
||||
/* check scope */
|
||||
if ( !scopeok && op->ors_scope == LDAP_SCOPE_ONELEVEL ) {
|
||||
if ( !be_issuffix( op->o_bd, &e->e_nname ) ) {
|
||||
dnParent( &e->e_nname, &dn );
|
||||
scopeok = dn_match( &dn, &realbase );
|
||||
} else {
|
||||
scopeok = (realbase.bv_len == 0);
|
||||
}
|
||||
|
||||
} else if ( !scopeok &&
|
||||
op->ors_scope == LDAP_SCOPE_SUBTREE )
|
||||
{
|
||||
scopeok = dnIsSuffix( &e->e_nname, &realbase );
|
||||
|
||||
} else if ( !scopeok &&
|
||||
op->ors_scope == LDAP_SCOPE_SUBORDINATE )
|
||||
{
|
||||
scopeok = !dn_match( &e->e_nname, &realbase )
|
||||
&& dnIsSuffix( &e->e_nname, &realbase );
|
||||
|
||||
} else {
|
||||
scopeok = 1;
|
||||
}
|
||||
|
||||
if ( scopeok ) {
|
||||
if (e) {
|
||||
rs->sr_flags = 0;
|
||||
rs->sr_err = send_search_entry( op, rs );
|
||||
|
||||
switch ( rs->sr_err ) {
|
||||
case LDAP_UNAVAILABLE: /* connection closed */
|
||||
cache_return_entry_r( &li->li_cache, e );
|
||||
rc = LDAP_SUCCESS;
|
||||
goto done;
|
||||
case LDAP_SIZELIMIT_EXCEEDED:
|
||||
cache_return_entry_r( &li->li_cache, e );
|
||||
rc = rs->sr_err;
|
||||
rs->sr_entry = NULL;
|
||||
send_ldap_result( op, rs );
|
||||
rc = LDAP_SUCCESS;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"ldbm_search: candidate entry %ld scope not okay\n",
|
||||
id, 0, 0 );
|
||||
}
|
||||
|
||||
} else {
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"ldbm_search: candidate entry %ld does not match filter\n",
|
||||
id, 0, 0 );
|
||||
}
|
||||
|
||||
loop_continue:
|
||||
if( e != NULL ) {
|
||||
/* free reader lock */
|
||||
cache_return_entry_r( &li->li_cache, e );
|
||||
}
|
||||
|
||||
ldap_pvt_thread_yield();
|
||||
}
|
||||
|
||||
rs->sr_err = rs->sr_v2ref ? LDAP_REFERRAL : LDAP_SUCCESS;
|
||||
rs->sr_ref = rs->sr_v2ref;
|
||||
send_ldap_result( op, rs );
|
||||
|
||||
rc = LDAP_SUCCESS;
|
||||
|
||||
done:
|
||||
ldap_pvt_thread_rdwr_runlock(&li->li_giant_rwlock);
|
||||
|
||||
if( candidates != NULL )
|
||||
idl_free( candidates );
|
||||
|
||||
if( rs->sr_v2ref ) ber_bvarray_free( rs->sr_v2ref );
|
||||
if( realbase.bv_val ) free( realbase.bv_val );
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static ID_BLOCK *
|
||||
base_candidate(
|
||||
Backend *be,
|
||||
Entry *e )
|
||||
{
|
||||
ID_BLOCK *idl;
|
||||
|
||||
Debug(LDAP_DEBUG_TRACE, "base_candidates: base: \"%s\"\n",
|
||||
e->e_dn, 0, 0);
|
||||
|
||||
|
||||
idl = idl_alloc( 1 );
|
||||
idl_insert( &idl, e->e_id, 1 );
|
||||
|
||||
return( idl );
|
||||
}
|
||||
|
||||
static ID_BLOCK *
|
||||
search_candidates(
|
||||
Operation *op,
|
||||
Entry *e,
|
||||
Filter *filter,
|
||||
int scope,
|
||||
int deref,
|
||||
int manageDSAit )
|
||||
{
|
||||
ID_BLOCK *candidates;
|
||||
Filter f, fand, rf, af, xf;
|
||||
AttributeAssertion aa_ref, aa_alias;
|
||||
struct berval bv_ref = { sizeof("referral")-1, "referral" };
|
||||
struct berval bv_alias = { sizeof("alias")-1, "alias" };
|
||||
Filter sf;
|
||||
AttributeAssertion aa_subentry;
|
||||
|
||||
Debug(LDAP_DEBUG_TRACE,
|
||||
"search_candidates: base=\"%s\" s=%d d=%d\n",
|
||||
e->e_ndn, scope, deref );
|
||||
|
||||
|
||||
xf.f_or = filter;
|
||||
xf.f_choice = LDAP_FILTER_OR;
|
||||
xf.f_next = NULL;
|
||||
|
||||
if( !manageDSAit ) {
|
||||
/* match referrals */
|
||||
rf.f_choice = LDAP_FILTER_EQUALITY;
|
||||
rf.f_ava = &aa_ref;
|
||||
rf.f_av_desc = slap_schema.si_ad_objectClass;
|
||||
rf.f_av_value = bv_ref;
|
||||
rf.f_next = xf.f_or;
|
||||
xf.f_or = &rf;
|
||||
}
|
||||
|
||||
if( deref & LDAP_DEREF_SEARCHING ) {
|
||||
/* match aliases */
|
||||
af.f_choice = LDAP_FILTER_EQUALITY;
|
||||
af.f_ava = &aa_alias;
|
||||
af.f_av_desc = slap_schema.si_ad_objectClass;
|
||||
af.f_av_value = bv_alias;
|
||||
af.f_next = xf.f_or;
|
||||
xf.f_or = ⁡
|
||||
}
|
||||
|
||||
f.f_next = NULL;
|
||||
f.f_choice = LDAP_FILTER_AND;
|
||||
f.f_and = &fand;
|
||||
fand.f_choice = scope == LDAP_SCOPE_ONELEVEL
|
||||
? SLAPD_FILTER_DN_ONE
|
||||
: SLAPD_FILTER_DN_SUBTREE;
|
||||
fand.f_dn = &e->e_nname;
|
||||
fand.f_next = xf.f_or == filter ? filter : &xf ;
|
||||
|
||||
if ( get_subentries_visibility( op )) {
|
||||
struct berval bv_subentry = { sizeof("SUBENTRY")-1, "SUBENTRY" };
|
||||
sf.f_choice = LDAP_FILTER_EQUALITY;
|
||||
sf.f_ava = &aa_subentry;
|
||||
sf.f_av_desc = slap_schema.si_ad_objectClass;
|
||||
sf.f_av_value = bv_subentry;
|
||||
sf.f_next = fand.f_next;
|
||||
fand.f_next = &sf;
|
||||
}
|
||||
|
||||
candidates = filter_candidates( op, &f );
|
||||
return( candidates );
|
||||
}
|
||||
|
|
@ -1,316 +0,0 @@
|
|||
/* tools.c - tools for slap tools */
|
||||
/* $OpenLDAP$ */
|
||||
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
|
||||
*
|
||||
* Copyright 1998-2006 The OpenLDAP Foundation.
|
||||
* 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>.
|
||||
*/
|
||||
|
||||
#include "portable.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <ac/string.h>
|
||||
#include <ac/socket.h>
|
||||
|
||||
#include "slap.h"
|
||||
#include "back-ldbm.h"
|
||||
|
||||
static LDBMCursor *cursorp = NULL;
|
||||
static DBCache *id2entry = NULL;
|
||||
|
||||
int ldbm_tool_entry_open(
|
||||
BackendDB *be, int mode )
|
||||
{
|
||||
struct ldbminfo *li = (struct ldbminfo *) be->be_private;
|
||||
int flags;
|
||||
|
||||
assert( slapMode & SLAP_TOOL_MODE );
|
||||
assert( id2entry == NULL );
|
||||
|
||||
switch( mode ) {
|
||||
case 1:
|
||||
flags = LDBM_WRCREAT;
|
||||
break;
|
||||
case 2:
|
||||
#ifdef TRUNCATE_MODE
|
||||
flags = LDBM_NEWDB;
|
||||
#else
|
||||
flags = LDBM_WRCREAT;
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
flags = LDBM_READER;
|
||||
}
|
||||
|
||||
li->li_dbwritesync = 0;
|
||||
|
||||
if ( (id2entry = ldbm_cache_open( be, "id2entry", LDBM_SUFFIX, flags ))
|
||||
== NULL ) {
|
||||
Debug( LDAP_DEBUG_ANY, "Could not open/create id2entry" LDBM_SUFFIX "\n",
|
||||
0, 0, 0 );
|
||||
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ldbm_tool_entry_close(
|
||||
BackendDB *be )
|
||||
{
|
||||
struct ldbminfo *li = (struct ldbminfo *) be->be_private;
|
||||
|
||||
assert( slapMode & SLAP_TOOL_MODE );
|
||||
assert( id2entry != NULL );
|
||||
|
||||
ldbm_cache_close( be, id2entry );
|
||||
li->li_dbwritesync = 1;
|
||||
id2entry = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
ID ldbm_tool_entry_first(
|
||||
BackendDB *be )
|
||||
{
|
||||
Datum key;
|
||||
ID id;
|
||||
|
||||
assert( slapMode & SLAP_TOOL_MODE );
|
||||
assert( id2entry != NULL );
|
||||
|
||||
key = ldbm_firstkey( id2entry->dbc_db, &cursorp );
|
||||
|
||||
if( key.dptr == NULL ) {
|
||||
return NOID;
|
||||
}
|
||||
|
||||
AC_MEMCPY( &id, key.dptr, key.dsize );
|
||||
#ifndef WORDS_BIGENDIAN
|
||||
id = ntohl( id );
|
||||
#endif
|
||||
|
||||
ldbm_datum_free( id2entry->dbc_db, key );
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
ID ldbm_tool_entry_next(
|
||||
BackendDB *be )
|
||||
{
|
||||
Datum key;
|
||||
ID id;
|
||||
|
||||
assert( slapMode & SLAP_TOOL_MODE );
|
||||
assert( id2entry != NULL );
|
||||
|
||||
/* allow for NEXTID */
|
||||
ldbm_datum_init( key );
|
||||
|
||||
key = ldbm_nextkey( id2entry->dbc_db, key, cursorp );
|
||||
|
||||
if( key.dptr == NULL ) {
|
||||
return NOID;
|
||||
}
|
||||
|
||||
AC_MEMCPY( &id, key.dptr, key.dsize );
|
||||
#ifndef WORDS_BIGENDIAN
|
||||
id = ntohl( id );
|
||||
#endif
|
||||
|
||||
ldbm_datum_free( id2entry->dbc_db, key );
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
Entry* ldbm_tool_entry_get( BackendDB *be, ID id )
|
||||
{
|
||||
Entry *e;
|
||||
Datum key, data;
|
||||
#ifndef WORDS_BIGENDIAN
|
||||
ID id2;
|
||||
#endif
|
||||
assert( slapMode & SLAP_TOOL_MODE );
|
||||
assert( id2entry != NULL );
|
||||
|
||||
ldbm_datum_init( key );
|
||||
|
||||
#ifndef WORDS_BIGENDIAN
|
||||
id2 = htonl( id );
|
||||
key.dptr = (char *) &id2;
|
||||
#else
|
||||
key.dptr = (char *) &id;
|
||||
#endif
|
||||
key.dsize = sizeof(ID);
|
||||
|
||||
data = ldbm_cache_fetch( id2entry, key );
|
||||
|
||||
if ( data.dptr == NULL ) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
e = str2entry2( data.dptr, 0 );
|
||||
ldbm_datum_free( id2entry->dbc_db, data );
|
||||
|
||||
if( e != NULL ) {
|
||||
e->e_id = id;
|
||||
}
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
ID ldbm_tool_entry_put(
|
||||
BackendDB *be,
|
||||
Entry *e,
|
||||
struct berval *text )
|
||||
{
|
||||
struct ldbminfo *li = (struct ldbminfo *) be->be_private;
|
||||
Datum key, data;
|
||||
int rc, len;
|
||||
ID id;
|
||||
Operation op = {0};
|
||||
Opheader ohdr = {0};
|
||||
|
||||
assert( slapMode & SLAP_TOOL_MODE );
|
||||
assert( id2entry != NULL );
|
||||
|
||||
assert( text != NULL );
|
||||
assert( text->bv_val != NULL );
|
||||
assert( text->bv_val[0] == '\0' ); /* overconservative? */
|
||||
|
||||
if ( next_id_get( be, &id ) || id == NOID ) {
|
||||
strncpy( text->bv_val, "unable to get nextid", text->bv_len );
|
||||
return NOID;
|
||||
}
|
||||
|
||||
e->e_id = li->li_nextid++;
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "=> ldbm_tool_entry_put( %ld, \"%s\" )\n",
|
||||
e->e_id, e->e_dn, 0 );
|
||||
|
||||
if ( dn2id( be, &e->e_nname, &id ) ) {
|
||||
/* something bad happened to ldbm cache */
|
||||
strncpy( text->bv_val, "ldbm cache corrupted", text->bv_len );
|
||||
return NOID;
|
||||
}
|
||||
|
||||
if( id != NOID ) {
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"<= ldbm_tool_entry_put: \"%s\" already exists (id=%ld)\n",
|
||||
e->e_ndn, id, 0 );
|
||||
strncpy( text->bv_val, "already exists", text->bv_len );
|
||||
return NOID;
|
||||
}
|
||||
|
||||
op.o_hdr = &ohdr;
|
||||
op.o_bd = be;
|
||||
op.o_tmpmemctx = NULL;
|
||||
op.o_tmpmfuncs = &ch_mfuncs;
|
||||
|
||||
rc = index_entry_add( &op, e );
|
||||
if( rc != 0 ) {
|
||||
strncpy( text->bv_val, "index add failed", text->bv_len );
|
||||
return NOID;
|
||||
}
|
||||
|
||||
rc = dn2id_add( be, &e->e_nname, e->e_id );
|
||||
if( rc != 0 ) {
|
||||
strncpy( text->bv_val, "dn2id add failed", text->bv_len );
|
||||
return NOID;
|
||||
}
|
||||
|
||||
ldbm_datum_init( key );
|
||||
ldbm_datum_init( data );
|
||||
|
||||
#ifndef WORDS_BIGENDIAN
|
||||
id = htonl( e->e_id );
|
||||
key.dptr = (char *) &id;
|
||||
#else
|
||||
key.dptr = (char *) &e->e_id;
|
||||
#endif
|
||||
key.dsize = sizeof(ID);
|
||||
|
||||
data.dptr = entry2str( e, &len );
|
||||
data.dsize = len + 1;
|
||||
|
||||
/* store it */
|
||||
rc = ldbm_cache_store( id2entry, key, data, LDBM_REPLACE );
|
||||
|
||||
if( rc != 0 ) {
|
||||
(void) dn2id_delete( be, &e->e_nname, e->e_id );
|
||||
strncpy( text->bv_val, "cache store failed", text->bv_len );
|
||||
return NOID;
|
||||
}
|
||||
|
||||
return e->e_id;
|
||||
}
|
||||
|
||||
int ldbm_tool_entry_reindex(
|
||||
BackendDB *be,
|
||||
ID id )
|
||||
{
|
||||
int rc;
|
||||
Entry *e;
|
||||
Operation op = {0};
|
||||
Opheader ohdr = {0};
|
||||
|
||||
Debug( LDAP_DEBUG_ARGS, "=> ldbm_tool_entry_reindex( %ld )\n",
|
||||
(long) id, 0, 0 );
|
||||
|
||||
|
||||
e = ldbm_tool_entry_get( be, id );
|
||||
|
||||
if( e == NULL ) {
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"ldbm_tool_entry_reindex:: could not locate id=%ld\n",
|
||||
(long) id, 0, 0 );
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* just (re)add them for now
|
||||
* assume that some other routine (not yet implemented)
|
||||
* will zap index databases
|
||||
*
|
||||
*/
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "=> ldbm_tool_entry_reindex( %ld, \"%s\" )\n",
|
||||
id, e->e_dn, 0 );
|
||||
|
||||
dn2id_add( be, &e->e_nname, e->e_id );
|
||||
|
||||
op.o_hdr = &ohdr;
|
||||
op.o_bd = be;
|
||||
op.o_tmpmemctx = NULL;
|
||||
op.o_tmpmfuncs = &ch_mfuncs;
|
||||
rc = index_entry_add( &op, e );
|
||||
|
||||
entry_free( e );
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int ldbm_tool_sync( BackendDB *be )
|
||||
{
|
||||
struct ldbminfo *li = (struct ldbminfo *) be->be_private;
|
||||
|
||||
assert( slapMode & SLAP_TOOL_MODE );
|
||||
|
||||
if ( li->li_nextid != NOID ) {
|
||||
if ( next_id_write( be, li->li_nextid ) ) {
|
||||
return( -1 );
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
Loading…
Reference in a new issue