2008-06-14 20:37:40 -04:00
/*
2004-03-31 06:45:39 +00:00
ldb database library
2009-10-06 09:30:53 +02:00
Copyright ( C ) Andrew Tridgell 2004
Copyright ( C ) Stefan Metzmacher 2004
Copyright ( C ) Simo Sorce 2006 - 2008
2010-10-18 20:07:49 +02:00
Copyright ( C ) Matthias Dieter Wallnöfer 2009 - 2010
2004-03-31 06:45:39 +00:00
* * NOTE ! The following LGPL license applies to the ldb
* * library . This does NOT imply that all of Samba is released
* * under the LGPL
2008-06-14 20:37:40 -04:00
2004-03-31 06:45:39 +00:00
This library is free software ; you can redistribute it and / or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation ; either
2007-07-10 02:46:15 +00:00
version 3 of the License , or ( at your option ) any later version .
2004-03-31 06:45:39 +00:00
This library is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the GNU
Lesser General Public License for more details .
You should have received a copy of the GNU Lesser General Public
2007-07-10 03:42:26 +00:00
License along with this library ; if not , see < http : //www.gnu.org/licenses/>.
2004-03-31 06:45:39 +00:00
*/
/*
2006-03-03 17:44:03 +00:00
* Name : ldb_tdb
2004-03-31 06:45:39 +00:00
*
* Component : ldb tdb backend
*
* Description : core functions for tdb backend
*
* Author : Andrew Tridgell
2004-10-20 19:28:02 +00:00
* Author : Stefan Metzmacher
2006-03-03 17:44:03 +00:00
*
* Modifications :
*
2010-02-21 17:22:45 +11:00
* - description : make the module use asynchronous calls
2006-03-03 17:44:03 +00:00
* date : Feb 2006
* Author : Simo Sorce
2008-09-11 18:34:11 -04:00
*
* - description : make it possible to use event contexts
* date : Jan 2008
* Author : Simo Sorce
2009-10-06 09:30:53 +02:00
*
* - description : fix up memory leaks and small bugs
* date : Oct 2009
* Author : Matthias Dieter Wallnöfer
2004-03-31 06:45:39 +00:00
*/
2007-05-05 18:50:56 +00:00
# include "ldb_tdb.h"
2012-10-31 16:06:03 +11:00
# include "ldb_private.h"
2018-07-23 10:02:16 +12:00
# include "../ldb_key_value/ldb_kv.h"
2012-06-19 12:43:10 +09:30
# include <tdb.h>
2004-03-31 06:45:39 +00:00
2008-10-15 14:03:20 -04:00
/*
lock the database for read - use by ltdb_search and ltdb_sequence_number
*/
2017-01-10 23:19:55 +13:00
static int ltdb_lock_read ( struct ldb_module * module )
2008-10-15 14:03:20 -04:00
{
2009-01-29 18:39:30 -05:00
void * data = ldb_module_get_private ( module ) ;
2018-07-20 11:54:39 +12:00
struct ldb_kv_private * ldb_kv =
talloc_get_type ( data , struct ldb_kv_private ) ;
2017-09-14 14:04:51 +12:00
int tdb_ret = 0 ;
int ret ;
2018-05-04 14:35:14 +12:00
pid_t pid = getpid ( ) ;
2018-07-20 11:53:21 +12:00
if ( ldb_kv - > pid ! = pid ) {
2018-07-20 11:54:39 +12:00
ldb_asprintf_errstring ( ldb_module_get_ctx ( module ) ,
__location__
" : Reusing ldb opend by pid %d in "
" process %d \n " ,
ldb_kv - > pid ,
pid ) ;
2018-05-04 14:35:14 +12:00
return LDB_ERR_PROTOCOL_ERROR ;
}
2009-12-09 14:37:26 +11:00
2018-07-20 11:53:21 +12:00
if ( tdb_transaction_active ( ldb_kv - > tdb ) = = false & &
ldb_kv - > read_lock_count = = 0 ) {
tdb_ret = tdb_lockall_read ( ldb_kv - > tdb ) ;
2008-10-15 14:03:20 -04:00
}
2017-09-14 14:04:51 +12:00
if ( tdb_ret = = 0 ) {
2018-07-20 11:53:21 +12:00
ldb_kv - > read_lock_count + + ;
2017-09-14 14:04:51 +12:00
return LDB_SUCCESS ;
}
2018-07-20 11:53:21 +12:00
ret = ltdb_err_map ( tdb_error ( ldb_kv - > tdb ) ) ;
2017-09-14 14:04:51 +12:00
if ( ret = = LDB_SUCCESS ) {
ret = LDB_ERR_OPERATIONS_ERROR ;
2009-12-09 14:37:26 +11:00
}
2017-09-14 14:04:51 +12:00
ldb_debug_set ( ldb_module_get_ctx ( module ) ,
LDB_DEBUG_FATAL ,
" Failure during ltdb_lock_read(): %s -> %s " ,
2018-07-20 11:53:21 +12:00
tdb_errorstr ( ldb_kv - > tdb ) ,
2017-09-14 14:04:51 +12:00
ldb_strerror ( ret ) ) ;
2009-12-09 14:37:26 +11:00
return ret ;
2008-10-15 14:03:20 -04:00
}
/*
unlock the database after a ltdb_lock_read ( )
*/
2017-01-10 23:19:55 +13:00
static int ltdb_unlock_read ( struct ldb_module * module )
2008-10-15 14:03:20 -04:00
{
2009-01-29 18:39:30 -05:00
void * data = ldb_module_get_private ( module ) ;
2018-07-20 11:54:39 +12:00
struct ldb_kv_private * ldb_kv =
talloc_get_type ( data , struct ldb_kv_private ) ;
2018-05-04 14:35:14 +12:00
pid_t pid = getpid ( ) ;
2018-07-20 11:53:21 +12:00
if ( ldb_kv - > pid ! = pid ) {
2018-07-20 11:54:39 +12:00
ldb_asprintf_errstring ( ldb_module_get_ctx ( module ) ,
__location__
" : Reusing ldb opend by pid %d in "
" process %d \n " ,
ldb_kv - > pid ,
pid ) ;
2018-05-04 14:35:14 +12:00
return LDB_ERR_PROTOCOL_ERROR ;
}
2018-07-20 11:54:39 +12:00
if ( ! tdb_transaction_active ( ldb_kv - > tdb ) & &
ldb_kv - > read_lock_count = = 1 ) {
2018-07-20 11:53:21 +12:00
tdb_unlockall_read ( ldb_kv - > tdb ) ;
ldb_kv - > read_lock_count - - ;
2011-06-20 18:40:32 +09:30
return 0 ;
2008-10-15 14:03:20 -04:00
}
2018-07-20 11:53:21 +12:00
ldb_kv - > read_lock_count - - ;
2008-10-15 14:03:20 -04:00
return 0 ;
}
2018-07-20 11:53:21 +12:00
static int ltdb_store ( struct ldb_kv_private * ldb_kv ,
2018-07-20 07:25:32 +12:00
struct ldb_val ldb_key ,
struct ldb_val ldb_data ,
int flags )
2017-01-10 19:05:40 +13:00
{
2018-02-16 17:13:26 +13:00
TDB_DATA key = {
. dptr = ldb_key . data ,
. dsize = ldb_key . length
} ;
TDB_DATA data = {
. dptr = ldb_data . data ,
. dsize = ldb_data . length
} ;
2018-07-20 11:53:21 +12:00
bool transaction_active = tdb_transaction_active ( ldb_kv - > tdb ) ;
2018-03-15 11:36:33 +13:00
if ( transaction_active = = false ) {
return LDB_ERR_PROTOCOL_ERROR ;
}
2018-07-23 10:02:16 +12:00
return tdb_store ( ldb_kv - > tdb , key , data , flags ) ;
}
2017-08-11 11:33:17 +12:00
2018-07-23 10:02:16 +12:00
static int ltdb_error ( struct ldb_kv_private * ldb_kv )
{
return ltdb_err_map ( tdb_error ( ldb_kv - > tdb ) ) ;
}
2012-07-31 10:17:20 +10:00
2018-07-23 10:02:16 +12:00
static const char * ltdb_errorstr ( struct ldb_kv_private * ldb_kv )
{
return tdb_errorstr ( ldb_kv - > tdb ) ;
}
2007-09-18 06:36:07 +00:00
2018-07-23 10:02:16 +12:00
static int ltdb_delete ( struct ldb_kv_private * ldb_kv , struct ldb_val ldb_key )
{
TDB_DATA tdb_key = {
. dptr = ldb_key . data ,
. dsize = ldb_key . length
} ;
bool transaction_active = tdb_transaction_active ( ldb_kv - > tdb ) ;
if ( transaction_active = = false ) {
return LDB_ERR_PROTOCOL_ERROR ;
2009-11-18 21:56:24 +11:00
}
2018-07-23 10:02:16 +12:00
return tdb_delete ( ldb_kv - > tdb , tdb_key ) ;
2006-03-03 17:44:03 +00:00
}
2005-01-02 07:49:29 +00:00
2018-07-20 11:53:21 +12:00
static int ltdb_transaction_start ( struct ldb_kv_private * ldb_kv )
2017-01-10 21:44:11 +13:00
{
2018-05-04 14:35:14 +12:00
pid_t pid = getpid ( ) ;
2018-07-20 11:53:21 +12:00
if ( ldb_kv - > pid ! = pid ) {
2018-07-20 11:54:39 +12:00
ldb_asprintf_errstring ( ldb_module_get_ctx ( ldb_kv - > module ) ,
__location__
" : Reusing ldb opend by pid %d in "
" process %d \n " ,
ldb_kv - > pid ,
pid ) ;
2018-05-04 14:35:14 +12:00
return LDB_ERR_PROTOCOL_ERROR ;
}
2018-07-20 11:53:21 +12:00
return tdb_transaction_start ( ldb_kv - > tdb ) ;
2017-01-10 21:44:11 +13:00
}
2018-07-20 11:53:21 +12:00
static int ltdb_transaction_cancel ( struct ldb_kv_private * ldb_kv )
2017-01-10 21:44:11 +13:00
{
2018-05-04 14:35:14 +12:00
pid_t pid = getpid ( ) ;
2018-07-20 11:53:21 +12:00
if ( ldb_kv - > pid ! = pid ) {
2018-07-20 11:54:39 +12:00
ldb_asprintf_errstring ( ldb_module_get_ctx ( ldb_kv - > module ) ,
__location__
" : Reusing ldb opend by pid %d in "
" process %d \n " ,
ldb_kv - > pid ,
pid ) ;
2018-05-04 14:35:14 +12:00
return LDB_ERR_PROTOCOL_ERROR ;
}
2018-07-20 11:53:21 +12:00
return tdb_transaction_cancel ( ldb_kv - > tdb ) ;
2017-01-10 21:44:11 +13:00
}
2018-07-20 11:53:21 +12:00
static int ltdb_transaction_prepare_commit ( struct ldb_kv_private * ldb_kv )
2017-01-10 21:44:11 +13:00
{
2018-05-04 14:35:14 +12:00
pid_t pid = getpid ( ) ;
2018-07-20 11:53:21 +12:00
if ( ldb_kv - > pid ! = pid ) {
2018-07-20 11:54:39 +12:00
ldb_asprintf_errstring ( ldb_module_get_ctx ( ldb_kv - > module ) ,
__location__
" : Reusing ldb opend by pid %d in "
" process %d \n " ,
ldb_kv - > pid ,
pid ) ;
2018-05-04 14:35:14 +12:00
return LDB_ERR_PROTOCOL_ERROR ;
}
2018-07-20 11:53:21 +12:00
return tdb_transaction_prepare_commit ( ldb_kv - > tdb ) ;
2017-01-10 21:44:11 +13:00
}
2018-07-20 11:53:21 +12:00
static int ltdb_transaction_commit ( struct ldb_kv_private * ldb_kv )
2017-01-10 21:44:11 +13:00
{
2018-05-04 14:35:14 +12:00
pid_t pid = getpid ( ) ;
2018-07-20 11:53:21 +12:00
if ( ldb_kv - > pid ! = pid ) {
2018-07-20 11:54:39 +12:00
ldb_asprintf_errstring ( ldb_module_get_ctx ( ldb_kv - > module ) ,
__location__
" : Reusing ldb opend by pid %d in "
" process %d \n " ,
ldb_kv - > pid ,
pid ) ;
2018-05-04 14:35:14 +12:00
return LDB_ERR_PROTOCOL_ERROR ;
}
2018-07-20 11:53:21 +12:00
return tdb_transaction_commit ( ldb_kv - > tdb ) ;
2017-01-10 21:44:11 +13:00
}
2018-02-16 13:06:31 +13:00
struct kv_ctx {
ldb_kv_traverse_fn kv_traverse_fn ;
void * ctx ;
2018-07-20 11:53:21 +12:00
struct ldb_kv_private * ldb_kv ;
2018-02-19 12:37:20 +13:00
int ( * parser ) ( struct ldb_val key ,
struct ldb_val data ,
void * private_data ) ;
2018-02-16 13:06:31 +13:00
} ;
2018-07-20 07:25:32 +12:00
static int ltdb_traverse_fn_wrapper ( struct tdb_context * tdb ,
TDB_DATA tdb_key ,
TDB_DATA tdb_data ,
void * ctx )
2018-02-16 13:06:31 +13:00
{
struct kv_ctx * kv_ctx = ctx ;
struct ldb_val key = {
. length = tdb_key . dsize ,
. data = tdb_key . dptr ,
} ;
struct ldb_val data = {
. length = tdb_data . dsize ,
. data = tdb_data . dptr ,
} ;
2018-07-20 11:53:21 +12:00
return kv_ctx - > kv_traverse_fn ( kv_ctx - > ldb_kv , key , data , kv_ctx - > ctx ) ;
2018-02-16 13:06:31 +13:00
}
2018-07-20 11:53:21 +12:00
static int ltdb_traverse_fn ( struct ldb_kv_private * ldb_kv ,
2018-07-20 07:25:32 +12:00
ldb_kv_traverse_fn fn ,
void * ctx )
2018-02-16 13:06:31 +13:00
{
struct kv_ctx kv_ctx = {
2018-07-20 11:54:39 +12:00
. kv_traverse_fn = fn , . ctx = ctx , . ldb_kv = ldb_kv } ;
2018-07-20 11:53:21 +12:00
if ( tdb_transaction_active ( ldb_kv - > tdb ) ) {
2018-07-20 07:25:32 +12:00
return tdb_traverse (
2018-07-20 11:53:21 +12:00
ldb_kv - > tdb , ltdb_traverse_fn_wrapper , & kv_ctx ) ;
2018-02-16 13:06:31 +13:00
} else {
2018-07-20 07:25:32 +12:00
return tdb_traverse_read (
2018-07-20 11:53:21 +12:00
ldb_kv - > tdb , ltdb_traverse_fn_wrapper , & kv_ctx ) ;
2018-02-16 13:06:31 +13:00
}
}
2018-07-20 11:53:21 +12:00
static int ltdb_update_in_iterate ( struct ldb_kv_private * ldb_kv ,
2018-07-20 07:25:32 +12:00
struct ldb_val ldb_key ,
struct ldb_val ldb_key2 ,
struct ldb_val ldb_data ,
void * state )
2018-02-16 13:06:31 +13:00
{
int tdb_ret ;
struct ldb_context * ldb ;
2018-07-20 08:53:28 +12:00
struct ldb_kv_reindex_context * ctx =
( struct ldb_kv_reindex_context * ) state ;
2018-02-16 13:06:31 +13:00
struct ldb_module * module = ctx - > module ;
2018-02-16 17:13:26 +13:00
TDB_DATA key = {
. dptr = ldb_key . data ,
. dsize = ldb_key . length
} ;
TDB_DATA key2 = {
. dptr = ldb_key2 . data ,
. dsize = ldb_key2 . length
} ;
TDB_DATA data = {
. dptr = ldb_data . data ,
. dsize = ldb_data . length
} ;
2018-02-16 13:06:31 +13:00
ldb = ldb_module_get_ctx ( module ) ;
2018-07-20 11:53:21 +12:00
tdb_ret = tdb_delete ( ldb_kv - > tdb , key ) ;
2018-02-16 13:06:31 +13:00
if ( tdb_ret ! = 0 ) {
2018-07-20 11:54:39 +12:00
ldb_debug ( ldb ,
LDB_DEBUG_ERROR ,
2018-02-16 13:06:31 +13:00
" Failed to delete %*.*s "
" for rekey as %*.*s: %s " ,
2018-07-20 11:54:39 +12:00
( int ) key . dsize ,
( int ) key . dsize ,
2018-02-16 13:06:31 +13:00
( const char * ) key . dptr ,
2018-07-20 11:54:39 +12:00
( int ) key2 . dsize ,
( int ) key2 . dsize ,
2018-02-16 13:06:31 +13:00
( const char * ) key . dptr ,
2018-07-20 11:53:21 +12:00
tdb_errorstr ( ldb_kv - > tdb ) ) ;
ctx - > error = ltdb_err_map ( tdb_error ( ldb_kv - > tdb ) ) ;
2018-02-16 13:06:31 +13:00
return - 1 ;
}
2018-07-20 11:53:21 +12:00
tdb_ret = tdb_store ( ldb_kv - > tdb , key2 , data , 0 ) ;
2018-02-16 13:06:31 +13:00
if ( tdb_ret ! = 0 ) {
2018-07-20 11:54:39 +12:00
ldb_debug ( ldb ,
LDB_DEBUG_ERROR ,
2018-02-16 13:06:31 +13:00
" Failed to rekey %*.*s as %*.*s: %s " ,
2018-07-20 11:54:39 +12:00
( int ) key . dsize ,
( int ) key . dsize ,
2018-02-16 13:06:31 +13:00
( const char * ) key . dptr ,
2018-07-20 11:54:39 +12:00
( int ) key2 . dsize ,
( int ) key2 . dsize ,
2018-02-16 13:06:31 +13:00
( const char * ) key . dptr ,
2018-07-20 11:53:21 +12:00
tdb_errorstr ( ldb_kv - > tdb ) ) ;
ctx - > error = ltdb_err_map ( tdb_error ( ldb_kv - > tdb ) ) ;
2018-02-16 13:06:31 +13:00
return - 1 ;
}
return tdb_ret ;
}
2018-07-20 07:25:32 +12:00
static int ltdb_parse_record_wrapper ( TDB_DATA tdb_key ,
TDB_DATA tdb_data ,
void * ctx )
2018-02-19 12:37:20 +13:00
{
struct kv_ctx * kv_ctx = ctx ;
struct ldb_val key = {
. length = tdb_key . dsize ,
. data = tdb_key . dptr ,
} ;
struct ldb_val data = {
. length = tdb_data . dsize ,
. data = tdb_data . dptr ,
} ;
return kv_ctx - > parser ( key , data , kv_ctx - > ctx ) ;
}
2018-07-20 11:53:21 +12:00
static int ltdb_parse_record ( struct ldb_kv_private * ldb_kv ,
2018-07-20 07:25:32 +12:00
struct ldb_val ldb_key ,
int ( * parser ) ( struct ldb_val key ,
struct ldb_val data ,
void * private_data ) ,
void * ctx )
2017-01-10 20:43:38 +13:00
{
2018-07-20 11:54:39 +12:00
struct kv_ctx kv_ctx = { . parser = parser , . ctx = ctx , . ldb_kv = ldb_kv } ;
2018-02-19 12:37:20 +13:00
TDB_DATA key = {
. dptr = ldb_key . data ,
. dsize = ldb_key . length
} ;
2018-03-15 11:33:32 +13:00
int ret ;
2018-02-19 12:37:20 +13:00
2018-07-20 11:53:21 +12:00
if ( tdb_transaction_active ( ldb_kv - > tdb ) = = false & &
ldb_kv - > read_lock_count = = 0 ) {
2018-04-04 17:21:30 +12:00
return LDB_ERR_PROTOCOL_ERROR ;
}
2018-07-20 07:25:32 +12:00
ret = tdb_parse_record (
2018-07-20 11:53:21 +12:00
ldb_kv - > tdb , key , ltdb_parse_record_wrapper , & kv_ctx ) ;
2018-03-15 11:33:32 +13:00
if ( ret = = 0 ) {
return LDB_SUCCESS ;
}
2018-07-20 11:53:21 +12:00
return ltdb_err_map ( tdb_error ( ldb_kv - > tdb ) ) ;
2017-01-10 20:43:38 +13:00
}
2019-03-04 12:50:24 +13:00
static int ltdb_iterate_range ( struct ldb_kv_private * ldb_kv ,
struct ldb_val start_key ,
struct ldb_val end_key ,
ldb_kv_traverse_fn fn ,
void * ctx )
{
/*
* We do not implement this operation because we do not know how to
* iterate from one key to the next ( in a sorted fashion ) .
*
* We could mimic it potentially , but it would violate boundaries of
* knowledge ( data type representation ) .
*/
return LDB_ERR_OPERATIONS_ERROR ;
}
2018-07-20 11:53:21 +12:00
static const char * ltdb_name ( struct ldb_kv_private * ldb_kv )
2017-01-10 19:05:40 +13:00
{
2018-07-20 11:53:21 +12:00
return tdb_name ( ldb_kv - > tdb ) ;
2017-01-10 19:05:40 +13:00
}
2018-07-20 11:53:21 +12:00
static bool ltdb_changed ( struct ldb_kv_private * ldb_kv )
2017-01-10 23:23:22 +13:00
{
2018-07-20 11:53:21 +12:00
int seq = tdb_get_seqnum ( ldb_kv - > tdb ) ;
bool has_changed = ( seq ! = ldb_kv - > tdb_seqnum ) ;
2017-01-10 23:23:22 +13:00
2018-07-20 11:53:21 +12:00
ldb_kv - > tdb_seqnum = seq ;
2017-01-10 23:23:22 +13:00
2018-03-07 13:27:20 +13:00
return has_changed ;
2017-01-10 23:23:22 +13:00
}
2018-07-20 11:53:21 +12:00
static bool ltdb_transaction_active ( struct ldb_kv_private * ldb_kv )
2018-03-20 11:25:28 +13:00
{
2018-07-20 11:53:21 +12:00
return tdb_transaction_active ( ldb_kv - > tdb ) ;
2018-03-20 11:25:28 +13:00
}
2019-04-01 15:27:32 +13:00
/*
* Get an estimate of the number of records in a tdb database .
*
* This implementation will overestimate the number of records in a sparsely
* populated database . The size estimate is only used for allocating
* an in memory tdb to cache index records during a reindex , overestimating
* the contents is acceptable , and preferable to underestimating
*/
# define RECORD_SIZE 500
static size_t ltdb_get_size ( struct ldb_kv_private * ldb_kv )
{
size_t map_size = tdb_map_size ( ldb_kv - > tdb ) ;
size_t size = map_size / RECORD_SIZE ;
return size ;
}
2017-01-10 19:05:40 +13:00
static const struct kv_db_ops key_value_ops = {
2018-07-20 07:25:32 +12:00
. store = ltdb_store ,
. delete = ltdb_delete ,
. iterate = ltdb_traverse_fn ,
. update_in_iterate = ltdb_update_in_iterate ,
. fetch_and_parse = ltdb_parse_record ,
2019-03-04 12:50:24 +13:00
. iterate_range = ltdb_iterate_range ,
2018-07-20 07:25:32 +12:00
. lock_read = ltdb_lock_read ,
. unlock_read = ltdb_unlock_read ,
. begin_write = ltdb_transaction_start ,
. prepare_write = ltdb_transaction_prepare_commit ,
. finish_write = ltdb_transaction_commit ,
. abort_write = ltdb_transaction_cancel ,
. error = ltdb_error ,
. errorstr = ltdb_errorstr ,
. name = ltdb_name ,
. has_changed = ltdb_changed ,
. transaction_active = ltdb_transaction_active ,
2019-04-01 15:27:32 +13:00
. get_size = ltdb_get_size ,
2017-01-10 19:05:40 +13:00
} ;
2004-03-31 06:45:39 +00:00
/*
connect to the database
*/
2018-02-16 13:26:46 +13:00
int ltdb_connect ( struct ldb_context * ldb , const char * url ,
unsigned int flags , const char * options [ ] ,
struct ldb_module * * _module )
2004-03-31 06:45:39 +00:00
{
const char * path ;
int tdb_flags , open_flags ;
2018-07-20 11:53:21 +12:00
struct ldb_kv_private * ldb_kv ;
2004-05-06 04:40:15 +00:00
2017-05-12 02:28:02 +02:00
/*
* We hold locks , so we must use a private event context
* on each returned handle
*/
ldb_set_require_private_event_context ( ldb ) ;
2004-03-31 06:45:39 +00:00
/* parse the url */
2004-05-03 09:34:18 +00:00
if ( strchr ( url , ' : ' ) ) {
if ( strncmp ( url , " tdb:// " , 6 ) ! = 0 ) {
2008-06-14 20:37:40 -04:00
ldb_debug ( ldb , LDB_DEBUG_ERROR ,
" Invalid tdb URL '%s' " , url ) ;
2009-10-23 17:23:44 +02:00
return LDB_ERR_OPERATIONS_ERROR ;
2004-05-03 09:34:18 +00:00
}
path = url + 6 ;
} else {
path = url ;
2004-03-31 06:45:39 +00:00
}
2018-03-23 11:28:18 +13:00
tdb_flags = TDB_DEFAULT | TDB_SEQNUM | TDB_DISALLOW_NESTING ;
2004-03-31 06:45:39 +00:00
2005-09-22 04:16:46 +00:00
/* check for the 'nosync' option */
if ( flags & LDB_FLG_NOSYNC ) {
tdb_flags | = TDB_NOSYNC ;
}
2005-09-22 03:56:41 +00:00
2007-06-06 12:44:04 +00:00
/* and nommap option */
if ( flags & LDB_FLG_NOMMAP ) {
tdb_flags | = TDB_NOMMAP ;
}
2018-07-20 11:53:21 +12:00
ldb_kv = talloc_zero ( ldb , struct ldb_kv_private ) ;
if ( ! ldb_kv ) {
2017-09-18 10:43:32 +12:00
ldb_oom ( ldb ) ;
return LDB_ERR_OPERATIONS_ERROR ;
}
2004-03-31 06:45:39 +00:00
if ( flags & LDB_FLG_RDONLY ) {
2017-09-18 10:43:32 +12:00
/*
* This is weird , but because we can only have one tdb
* in this process , and the other one could be
* read - write , we can ' t use the tdb readonly . Plus a
* read only tdb prohibits the all - record lock .
*/
open_flags = O_RDWR ;
2018-07-20 11:53:21 +12:00
ldb_kv - > read_only = true ;
2017-09-18 10:43:32 +12:00
2017-02-24 15:34:33 +01:00
} else if ( flags & LDB_FLG_DONT_CREATE_DB ) {
2017-09-18 10:43:32 +12:00
/*
* This is used by ldbsearch to prevent creation of the database
* if the name is wrong
*/
2017-02-24 15:34:33 +01:00
open_flags = O_RDWR ;
2004-03-31 06:45:39 +00:00
} else {
2017-09-18 10:43:32 +12:00
/*
* This is the normal case
*/
2004-03-31 06:45:39 +00:00
open_flags = O_CREAT | O_RDWR ;
}
2018-07-20 11:53:21 +12:00
ldb_kv - > kv_ops = & key_value_ops ;
2017-01-11 11:36:48 +13:00
2018-05-07 12:59:49 +12:00
errno = 0 ;
2005-07-20 00:59:38 +00:00
/* note that we use quite a large default hash size */
2018-07-20 11:54:39 +12:00
ldb_kv - > tdb = ltdb_wrap_open ( ldb_kv ,
path ,
10000 ,
tdb_flags ,
open_flags ,
ldb_get_create_perms ( ldb ) ,
ldb ) ;
2018-07-20 11:53:21 +12:00
if ( ! ldb_kv - > tdb ) {
2011-10-18 11:30:52 +11:00
ldb_asprintf_errstring ( ldb ,
2014-02-05 14:52:28 +13:00
" Unable to open tdb '%s': %s " , path , strerror ( errno ) ) ;
2008-06-14 20:37:40 -04:00
ldb_debug ( ldb , LDB_DEBUG_ERROR ,
2014-02-05 14:52:28 +13:00
" Unable to open tdb '%s': %s " , path , strerror ( errno ) ) ;
2018-07-20 11:53:21 +12:00
talloc_free ( ldb_kv ) ;
2014-02-05 14:52:28 +13:00
if ( errno = = EACCES | | errno = = EPERM ) {
return LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS ;
}
2009-10-23 17:23:44 +02:00
return LDB_ERR_OPERATIONS_ERROR ;
2005-07-20 00:59:38 +00:00
}
2004-05-01 09:45:56 +00:00
2018-07-20 07:23:10 +12:00
return ldb_kv_init_store (
2018-07-20 11:53:21 +12:00
ldb_kv , " ldb_tdb backend " , ldb , options , _module ) ;
2004-03-31 06:45:39 +00:00
}