ldbm.c

来自「OpenLdap是LDAP的开源项目」· C语言 代码 · 共 1,212 行 · 第 1/2 页

C
1,212
字号
/* ldbm.c - ldap dbm compatibility routines *//* $OpenLDAP: pkg/ldap/servers/slapd/back-ldbm/ldbm.c,v 1.4.2.6 2007/08/06 12:32:51 ando Exp $ *//* This work is part of OpenLDAP Software <http://www.openldap.org/>. * * Copyright 1998-2007 The OpenLDAP Foundation. * Portions Copyright 1998-2003 Kurt D. Zeilenga. * Portions Copyright 1998-2001 Net Boolean Incorporated. * 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>. *//* ACKNOWLEDGEMENTS: * This work was originally developed by the University of Michigan * (as part of U-MICH LDAP).  Additional significant contributors * include: *   Gary Williams *   Howard Chu *   Juan Gomez *   Kurt D. Zeilenga *   Kurt Spanier *   Mark Whitehouse *   Randy Kundee */#include "portable.h"#ifdef SLAPD_LDBM#include <stdio.h>#include <ac/stdlib.h>#include <ac/string.h>#include <ac/errno.h>#include "ldbm.h"#include "ldap_pvt_thread.h"voidldbm_datum_free( LDBM ldbm, Datum data ){	if ( data.dptr ) {		free( data.dptr );		memset( &data, '\0', sizeof( Datum ));		data.dptr = NULL;	}}Datumldbm_datum_dup( LDBM ldbm, Datum data ){	Datum	dup;	ldbm_datum_init( dup );	if ( data.dsize == 0 ) {		dup.dsize = 0;		dup.dptr = NULL;		return( dup );	}	dup.dsize = data.dsize;	if ( (dup.dptr = (char *) malloc( data.dsize )) != NULL ) {		AC_MEMCPY( dup.dptr, data.dptr, data.dsize );	}	return( dup );}static int ldbm_initialized = 0;#if defined( USE_BERKELEY_CDB )	/* not currently supported */#define LDBM_RWLOCK_INIT  ((void) 0)#define LDBM_RWLOCK_DESTROY ((void) 0)#define LDBM_WLOCK		((void) 0)#define LDBM_WUNLOCK	((void) 0)#define LDBM_RLOCK		((void) 0)#define LDBM_RUNLOCK	((void) 0)#elif defined( HAVE_BERKELEY_DB_THREAD )static ldap_pvt_thread_rdwr_t ldbm_big_rdwr;#define LDBM_RWLOCK_INIT (ldap_pvt_thread_rdwr_init( &ldbm_big_rdwr ))#define LDBM_RWLOCK_DESTROY (ldap_pvt_thread_rdwr_destroy( &ldbm_big_rdwr ))#define LDBM_WLOCK		(ldap_pvt_thread_rdwr_wlock(&ldbm_big_rdwr))#define LDBM_WUNLOCK	(ldap_pvt_thread_rdwr_wunlock(&ldbm_big_rdwr))#define LDBM_RLOCK		(ldap_pvt_thread_rdwr_rlock(&ldbm_big_rdwr))#define LDBM_RUNLOCK	(ldap_pvt_thread_rdwr_runlock(&ldbm_big_rdwr))#elsestatic ldap_pvt_thread_mutex_t ldbm_big_mutex;#define LDBM_RWLOCK_INIT (ldap_pvt_thread_mutex_init( &ldbm_big_mutex ))#define LDBM_RWLOCK_DESTROY (ldap_pvt_thread_mutex_destroy( &ldbm_big_mutex ))#define LDBM_WLOCK		(ldap_pvt_thread_mutex_lock(&ldbm_big_mutex))#define LDBM_WUNLOCK	(ldap_pvt_thread_mutex_unlock(&ldbm_big_mutex))#define LDBM_RLOCK		LDBM_WLOCK#define LDBM_RUNLOCK	LDBM_WUNLOCK#endif#if !defined( HAVE_BERKELEY_DB ) || (DB_VERSION_MAJOR < 3)	/*  a dbEnv for BERKELEYv2  */DB_ENV *ldbm_Env = NULL;	/* real or fake, depending on db and version */#endif/* Let's make the version comparisons a little easier... */#undef DB_VERSION_X#ifdef HAVE_BERKELEY_DB#define	DB_VERSION_X	((DB_VERSION_MAJOR<<16)|(DB_VERSION_MINOR<<8)|DB_VERSION_PATCH)#endif/******************************************************************* *                                                                 * *  Create some special functions to initialize Berkeley DB for    * *  versions greater than 2.                                       * *                                                                 * *******************************************************************/#if defined( HAVE_BERKELEY_DB ) && (DB_VERSION_MAJOR >= 2)void *ldbm_malloc( size_t size ){	/* likely should use ber_mem* routines */	return( calloc( 1, size ) );}#ifdef LDAP_SYSLOG#include <ac/syslog.h>#endifstatic void#if DB_VERSION_X < 0x040300ldbm_db_errcall( const char *prefix, char *message )#elseldbm_db_errcall( const DB_ENV *env, const char *prefix, const char *message )#endif{#ifdef LDAP_SYSLOG	syslog( LOG_INFO, "ldbm: %s %s", prefix, message );#endif}int ldbm_initialize( const char* home ){#if DB_VERSION_MAJOR < 3	int	err;	u_int32_t	envFlags;#endif	if(ldbm_initialized++) return 1;	{		char *version;#ifdef HAVE_EBCDIC		char v2[1024];#endif		int major, minor, patch;		version = db_version( &major, &minor, &patch );#ifdef HAVE_EBCDIC		strcpy( v2, version );		__etoa( v2 );		version = v2;#endif		if( major != DB_VERSION_MAJOR ||			minor < DB_VERSION_MINOR )		{#ifdef LDAP_SYSLOG			syslog( LOG_INFO,				"ldbm_initialize(): version mismatch\nexpected: %s\ngot: %s\n",				DB_VERSION_STRING, version );#endif			return 1;		}	}#if DB_VERSION_MAJOR < 3	ldbm_Env = calloc( 1, sizeof( DB_ENV ));	if( ldbm_Env == NULL ) return 1;	ldbm_Env->db_errcall	= ldbm_db_errcall;	ldbm_Env->db_errpfx		= "==>";	envFlags = DB_CREATE | DB_USE_ENVIRON;	/* add optional flags */#ifdef DB_PRIVATE	envFlags |= DB_PRIVATE;#endif#ifdef HAVE_BERKELEY_DB_THREAD	envFlags |= DB_THREAD; #endif	err = db_appinit( home, NULL, ldbm_Env, envFlags );	if ( err ) {#ifdef LDAP_SYSLOG		syslog( LOG_INFO, "ldbm_initialize(): "			"FATAL error (%d) in db_appinit()\n", err );#endif	 	return( 1 );	}#endif	LDBM_RWLOCK_INIT;	return 0;}int ldbm_shutdown( void ){	if( !ldbm_initialized ) return 1;#if DB_VERSION_MAJOR < 3	db_appexit( ldbm_Env );#endif	LDBM_RWLOCK_DESTROY;	return 0;}#else  /* some DB other than Berkeley V2 or greater */int ldbm_initialize( const char * home ){	if(ldbm_initialized++) return 1;	LDBM_RWLOCK_INIT;	return 0;}int ldbm_shutdown( void ){	if( !ldbm_initialized ) return 1;	LDBM_RWLOCK_DESTROY;	return 0;}#endif /* HAVE_BERKELEY_DB */#if defined( HAVE_BERKELEY_DB ) && (DB_VERSION_MAJOR >= 3)DB_ENV *ldbm_initialize_env(const char *home, int dbcachesize, int *envdirok){	DB_ENV *env = NULL;    	int     err;	u_int32_t	envFlags;#ifdef HAVE_EBCDIC	char n2[2048];#endif	err = db_env_create( &env, 0 );	if ( err ) {#ifdef LDAP_SYSLOG		syslog( LOG_INFO, "ldbm_initialize_env(): "			"FATAL error in db_env_create() : %s (%d)\n",			db_strerror( err ), err );#endif		return NULL;	}#if DB_VERSION_X >= 0x030300	/* This interface appeared in 3.3 */	env->set_alloc( env, ldbm_malloc, NULL, NULL );#endif	env->set_errcall( env, ldbm_db_errcall );	env->set_errpfx( env, "==>" );	if (dbcachesize) {		env->set_cachesize( env, 0, dbcachesize, 0 );	}	envFlags = DB_CREATE | DB_INIT_MPOOL | DB_USE_ENVIRON;#ifdef DB_PRIVATE	envFlags |= DB_PRIVATE;#endif#ifdef DB_MPOOL_PRIVATE	envFlags |= DB_MPOOL_PRIVATE;#endif#ifdef HAVE_BERKELEY_DB_THREAD	envFlags |= DB_THREAD;#endif#ifdef HAVE_EBCDIC	strncpy(n2, home, sizeof(n2)-1);	n2[sizeof(n2)-1] = '\0';	__atoe(n2);	home = n2;#endif#if DB_VERSION_X >= 0x030100	err = (env->open)( env, home, envFlags, 0 );#else	/* 3.0.x requires an extra argument */	err = (env->open)( env, home, NULL, envFlags, 0 );#endif	if ( err != 0 ) {#ifdef LDAP_SYSLOG		syslog(	LOG_INFO, "ldbm_initialize_env(): "			"FATAL error in dbEnv->open() : %s (%d)\n",			db_strerror( err ), err );#endif		env->close( env, 0 );		return NULL;	}	*envdirok = 1;	return env;}void ldbm_shutdown_env(DB_ENV *env){	env->close( env, 0 );}#elseDB_ENV *ldbm_initialize_env(const char *home, int dbcachesize, int *envdirok){	return ldbm_Env;}void ldbm_shutdown_env(DB_ENV *env){}#endif#if defined( LDBM_USE_DBHASH ) || defined( LDBM_USE_DBBTREE )/***************************************************************** *                                                               * * use berkeley db hash or btree package                         * *                                                               * *****************************************************************/LDBMldbm_open( DB_ENV *env, char *name, int rw, int mode, int dbcachesize ){	LDBM		ret = NULL;#ifdef HAVE_EBCDIC	char n2[2048];#endif#if DB_VERSION_MAJOR >= 3	int err;	LDBM_WLOCK;	err = db_create( &ret, env, 0 );	if ( err != 0 ) {		(void)ret->close(ret, 0);		LDBM_WUNLOCK;		return NULL;	}#if DB_VERSION_X < 0x030300	ret->set_malloc( ret, ldbm_malloc );#endif	ret->set_pagesize( ret, DEFAULT_DB_PAGE_SIZE );	/* likely should use ber_mem* routines */#ifdef HAVE_EBCDIC	strncpy(n2, name, sizeof(n2)-1);	n2[sizeof(n2)-1] = '\0';	__atoe(n2);	name = n2;#endif#if DB_VERSION_X >= 0x040111	err = (ret->open)( ret, NULL, name, NULL, DB_TYPE, rw, mode);#else	err = (ret->open)( ret, name, NULL, DB_TYPE, rw, mode);#endif	if ( err != 0 ) {		int tmp = errno;		(void)ret->close(ret, 0);		errno = tmp;		LDBM_WUNLOCK;		return NULL;	}	LDBM_WUNLOCK; #elif DB_VERSION_MAJOR >= 2	DB_INFO dbinfo;	memset( &dbinfo, '\0', sizeof( dbinfo ));#if	DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR == 4	/*	 * BerkeleyDB 2.4 do not allow db_cachesize	 * to be specified if an DB_ENV is.	 */#else	/* set db_cachesize of MPOOL is NOT being used. */	if (( ldbm_Env == NULL ) || ( ldbm_Env->mp_info == NULL )) {		dbinfo.db_cachesize = dbcachesize;	}#endif	dbinfo.db_pagesize	= DEFAULT_DB_PAGE_SIZE;	dbinfo.db_malloc	= ldbm_malloc;	LDBM_WLOCK;	(void) db_open( name, DB_TYPE, rw, mode, ldbm_Env, &dbinfo, &ret );	LDBM_WUNLOCK;#else	void		*info;	BTREEINFO	binfo;	HASHINFO	hinfo;	if ( DB_TYPE == DB_HASH ) {		memset( (char *) &hinfo, '\0', sizeof(hinfo) );		hinfo.cachesize = dbcachesize;		info = &hinfo;	} else if ( DB_TYPE == DB_BTREE ) {		memset( (char *) &binfo, '\0', sizeof(binfo) );		binfo.cachesize = dbcachesize;		info = &binfo;	} else {		info = NULL;	}	LDBM_WLOCK;	ret = dbopen( name, rw, mode, DB_TYPE, info );	LDBM_WUNLOCK;#endif	return ret;}voidldbm_close( LDBM ldbm ){	LDBM_WLOCK;#if DB_VERSION_MAJOR >= 2	ldbm->close( ldbm, 0 );#else	ldbm->close( ldbm );#endif	LDBM_WUNLOCK;}voidldbm_sync( LDBM ldbm ){	LDBM_WLOCK;	(*ldbm->sync)( ldbm, 0 );	LDBM_WUNLOCK;}Datumldbm_fetch( LDBM ldbm, Datum key ){	Datum	data;	int	rc;	LDBM_RLOCK;#if DB_VERSION_MAJOR >= 2	ldbm_datum_init( data );	data.flags = DB_DBT_MALLOC;	if ( (rc = ldbm->get( ldbm, NULL, &key, &data, 0 )) != 0 ) {		ldbm_datum_free( ldbm, data );		data.dptr = NULL;		data.dsize = 0;	}#else	if ( (rc = ldbm->get( ldbm, &key, &data, 0 )) == 0 ) {		/* Berkeley DB 1.85 don't malloc the data for us */		/* duplicate it for to ensure reentrancy */		data = ldbm_datum_dup( ldbm, data );	} else {		data.dptr = NULL;		data.dsize = 0;	}#endif	LDBM_RUNLOCK;	return( data );}intldbm_store( LDBM ldbm, Datum key, Datum data, int flags ){	int	rc;	LDBM_WLOCK;#if DB_VERSION_MAJOR >= 2	rc = ldbm->put( ldbm, NULL, &key, &data, flags & ~LDBM_SYNC );	rc = (-1) * rc;#else	rc = ldbm->put( ldbm, &key, &data, flags & ~LDBM_SYNC );#endif	if ( flags & LDBM_SYNC )		ldbm->sync( ldbm, 0 );	LDBM_WUNLOCK;	return( rc );}intldbm_delete( LDBM ldbm, Datum key ){	int	rc;	LDBM_WLOCK;#if DB_VERSION_MAJOR >= 2	rc = ldbm->del( ldbm, NULL, &key, 0 );	rc = (-1) * rc;#else	rc = ldbm->del( ldbm, &key, 0 );#endif	ldbm->sync( ldbm, 0 );	LDBM_WUNLOCK;	return( rc );}Datumldbm_firstkey( LDBM ldbm, LDBMCursor **dbch ){	Datum	key, data;	int	rc;#if DB_VERSION_MAJOR >= 2	LDBMCursor  *dbci;	ldbm_datum_init( key );	ldbm_datum_init( data );	key.flags = data.flags = DB_DBT_MALLOC;	LDBM_RLOCK;	/* acquire a cursor for the DB */# if DB_VERSION_X >= 0x020600	rc = ldbm->cursor( ldbm, NULL, &dbci, 0 );# else	rc = ldbm->cursor( ldbm, NULL, &dbci );# endif	if( rc ) {		key.dptr = NULL;	} else {		*dbch = dbci;		if ( dbci->c_get( dbci, &key, &data, DB_NEXT ) == 0 ) {			ldbm_datum_free( ldbm, data );		} else {			key.dptr = NULL;			key.dsize = 0;		}	}	LDBM_RUNLOCK;#else	LDBM_RLOCK;	rc = ldbm->seq( ldbm, &key, &data, R_FIRST );	if ( rc == 0 ) {		key = ldbm_datum_dup( ldbm, key );	} else {		key.dptr = NULL;		key.dsize = 0;	}	LDBM_RUNLOCK;#endif	return( key );}Datumldbm_nextkey( LDBM ldbm, Datum key, LDBMCursor *dbcp ){	int	rc;	Datum	data;	LDBM_RLOCK;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?