2001-12-04 13:21:15 +00:00
/*
2002-01-30 06:08:46 +00:00
Unix SMB / CIFS implementation .
2004-03-28 02:19:58 +00:00
trivial database library
2006-07-11 18:01:26 +00:00
Copyright ( C ) Andrew Tridgell 1999 - 2005
2000-12-06 00:05:15 +00:00
Copyright ( C ) Paul ` Rusty ' Russell 2000
2003-01-11 00:07:44 +00:00
Copyright ( C ) Jeremy Allison 2000 - 2003
1999-12-21 03:04:37 +00:00
2004-03-28 02:19:58 +00:00
* * NOTE ! The following LGPL license applies to the tdb
* * library . This does NOT imply that all of Samba is released
* * under the LGPL
1999-12-21 03:04:37 +00:00
2004-03-28 02:19:58 +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
version 2 of the License , or ( at your option ) any later version .
This library is distributed in the hope that it will be useful ,
1999-12-21 03:04:37 +00:00
but WITHOUT ANY WARRANTY ; without even the implied warranty of
2004-03-28 02:19:58 +00:00
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the GNU
Lesser General Public License for more details .
2006-07-11 18:01:26 +00:00
2004-03-28 02:19:58 +00:00
You should have received a copy of the GNU Lesser General Public
License along with this library ; if not , write to the Free Software
Foundation , Inc . , 59 Temple Place , Suite 330 , Boston , MA 02111 - 1307 USA
1999-12-21 03:04:37 +00:00
*/
2003-04-14 03:49:03 +00:00
2006-07-11 18:01:26 +00:00
# include "tdb_private.h"
2003-04-14 03:49:03 +00:00
2000-12-06 00:05:15 +00:00
TDB_DATA tdb_null ;
2006-07-11 18:01:26 +00:00
/*
increment the tdb sequence number if the tdb has been opened using
the TDB_SEQNUM flag
*/
static void tdb_increment_seqnum ( struct tdb_context * tdb )
2000-12-06 00:05:15 +00:00
{
2006-07-11 18:01:26 +00:00
tdb_off_t seqnum = 0 ;
if ( ! ( tdb - > flags & TDB_SEQNUM ) ) {
return ;
2002-04-07 22:02:09 +00:00
}
2000-12-06 00:05:15 +00:00
2006-10-20 09:55:47 +00:00
if ( tdb_brlock ( tdb , TDB_SEQNUM_OFS , F_WRLCK , F_SETLKW , 1 , 1 ) ! = 0 ) {
2001-08-02 20:17:40 +00:00
return ;
2001-05-30 05:40:52 +00:00
}
2000-12-06 00:05:15 +00:00
2006-07-11 18:01:26 +00:00
/* we ignore errors from this, as we have no sane way of
dealing with them .
2001-07-25 18:59:56 +00:00
*/
2006-07-11 18:01:26 +00:00
tdb_ofs_read ( tdb , TDB_SEQNUM_OFS , & seqnum ) ;
seqnum + + ;
tdb_ofs_write ( tdb , TDB_SEQNUM_OFS , & seqnum ) ;
1999-12-21 03:04:37 +00:00
2006-10-20 09:55:47 +00:00
tdb_brlock ( tdb , TDB_SEQNUM_OFS , F_UNLCK , F_SETLKW , 1 , 1 ) ;
1999-12-22 01:22:14 +00:00
}
1999-12-21 03:04:37 +00:00
2000-01-07 03:01:55 +00:00
/* Returns 0 on fail. On success, return offset of record, and fills
in rec */
2006-07-11 18:01:26 +00:00
static tdb_off_t tdb_find ( struct tdb_context * tdb , TDB_DATA key , u32 hash ,
2000-12-06 00:05:15 +00:00
struct list_struct * r )
1999-12-21 03:04:37 +00:00
{
2006-07-11 18:01:26 +00:00
tdb_off_t rec_ptr ;
2000-01-07 03:01:55 +00:00
1999-12-21 03:04:37 +00:00
/* read in the hash top */
2006-07-11 18:01:26 +00:00
if ( tdb_ofs_read ( tdb , TDB_HASH_TOP ( hash ) , & rec_ptr ) = = - 1 )
2001-08-02 20:17:40 +00:00
return 0 ;
1999-12-21 03:04:37 +00:00
/* keep looking until we find the right record */
while ( rec_ptr ) {
2006-07-11 18:01:26 +00:00
if ( tdb_rec_read ( tdb , rec_ptr , r ) = = - 1 )
2001-08-02 20:17:40 +00:00
return 0 ;
1999-12-21 03:04:37 +00:00
2000-12-06 00:05:15 +00:00
if ( ! TDB_DEAD ( r ) & & hash = = r - > full_hash & & key . dsize = = r - > key_len ) {
2000-01-07 03:01:55 +00:00
char * k ;
/* a very likely hit - read the key */
2000-12-06 00:05:15 +00:00
k = tdb_alloc_read ( tdb , rec_ptr + sizeof ( * r ) ,
r - > key_len ) ;
2001-08-02 20:17:40 +00:00
if ( ! k )
return 0 ;
1999-12-21 03:04:37 +00:00
2000-01-07 03:01:55 +00:00
if ( memcmp ( key . dptr , k , key . dsize ) = = 0 ) {
2002-01-02 23:28:55 +00:00
SAFE_FREE ( k ) ;
2000-01-07 03:01:55 +00:00
return rec_ptr ;
}
2002-01-02 23:28:55 +00:00
SAFE_FREE ( k ) ;
1999-12-21 03:04:37 +00:00
}
2000-12-06 00:05:15 +00:00
rec_ptr = r - > next ;
1999-12-21 03:04:37 +00:00
}
2000-12-06 00:05:15 +00:00
return TDB_ERRCODE ( TDB_ERR_NOEXIST , 0 ) ;
1999-12-21 03:04:37 +00:00
}
2000-12-06 00:05:15 +00:00
/* As tdb_find, but if you succeed, keep the lock */
2006-07-11 18:01:26 +00:00
tdb_off_t tdb_find_lock_hash ( struct tdb_context * tdb , TDB_DATA key , u32 hash , int locktype ,
struct list_struct * rec )
2000-12-06 00:05:15 +00:00
{
2003-09-06 19:59:12 +00:00
u32 rec_ptr ;
2000-12-06 00:05:15 +00:00
2001-08-02 20:17:40 +00:00
if ( tdb_lock ( tdb , BUCKET ( hash ) , locktype ) = = - 1 )
return 0 ;
2000-12-06 00:05:15 +00:00
if ( ! ( rec_ptr = tdb_find ( tdb , key , hash , rec ) ) )
tdb_unlock ( tdb , BUCKET ( hash ) , locktype ) ;
return rec_ptr ;
}
2000-01-08 08:16:02 +00:00
2000-01-07 03:01:55 +00:00
/* update an entry in place - this only works if the new data size
is < = the old data size and the key exists .
2003-01-11 00:07:44 +00:00
on failure return - 1.
2000-01-07 03:01:55 +00:00
*/
2006-07-11 18:01:26 +00:00
static int tdb_update_hash ( struct tdb_context * tdb , TDB_DATA key , u32 hash , TDB_DATA dbuf )
1999-12-21 03:04:37 +00:00
{
struct list_struct rec ;
2006-07-11 18:01:26 +00:00
tdb_off_t rec_ptr ;
1999-12-21 03:04:37 +00:00
2000-12-06 00:05:15 +00:00
/* find entry */
2003-09-06 19:59:12 +00:00
if ( ! ( rec_ptr = tdb_find ( tdb , key , hash , & rec ) ) )
2001-08-02 20:17:40 +00:00
return - 1 ;
1999-12-23 01:14:20 +00:00
2000-12-06 00:05:15 +00:00
/* must be long enough key, data and tailer */
2006-07-11 18:01:26 +00:00
if ( rec . rec_len < key . dsize + dbuf . dsize + sizeof ( tdb_off_t ) ) {
2001-07-31 00:03:24 +00:00
tdb - > ecode = TDB_SUCCESS ; /* Not really an error */
2003-01-11 00:07:44 +00:00
return - 1 ;
2001-07-31 00:03:24 +00:00
}
1999-12-21 03:04:37 +00:00
2006-07-11 18:01:26 +00:00
if ( tdb - > methods - > tdb_write ( tdb , rec_ptr + sizeof ( rec ) + rec . key_len ,
2000-01-07 03:01:55 +00:00
dbuf . dptr , dbuf . dsize ) = = - 1 )
2003-01-11 00:07:44 +00:00
return - 1 ;
1999-12-21 03:04:37 +00:00
2000-01-07 03:01:55 +00:00
if ( dbuf . dsize ! = rec . data_len ) {
/* update size */
rec . data_len = dbuf . dsize ;
2006-07-11 18:01:26 +00:00
return tdb_rec_write ( tdb , rec_ptr , & rec ) ;
2003-01-11 00:07:44 +00:00
}
return 0 ;
2000-01-07 03:01:55 +00:00
}
1999-12-21 03:04:37 +00:00
2000-01-07 03:01:55 +00:00
/* find an entry in the database given a key */
2002-09-26 21:02:47 +00:00
/* If an entry doesn't exist tdb_err will be set to
* TDB_ERR_NOEXIST . If a key has no data attached
2006-07-11 18:01:26 +00:00
* then the TDB_DATA will have zero length but
* a non - zero pointer
2002-09-26 21:02:47 +00:00
*/
2006-07-11 18:01:26 +00:00
TDB_DATA tdb_fetch ( struct tdb_context * tdb , TDB_DATA key )
2000-01-07 03:01:55 +00:00
{
2006-07-11 18:01:26 +00:00
tdb_off_t rec_ptr ;
2000-01-07 03:01:55 +00:00
struct list_struct rec ;
2000-12-06 00:05:15 +00:00
TDB_DATA ret ;
2003-09-06 19:59:12 +00:00
u32 hash ;
2000-02-16 22:57:57 +00:00
2000-01-07 03:01:55 +00:00
/* find which hash bucket it is in */
2004-08-24 22:48:49 +00:00
hash = tdb - > hash_fn ( & key ) ;
2003-09-06 19:59:12 +00:00
if ( ! ( rec_ptr = tdb_find_lock_hash ( tdb , key , hash , F_RDLCK , & rec ) ) )
2001-08-02 20:17:40 +00:00
return tdb_null ;
1999-12-21 03:04:37 +00:00
2006-07-11 18:01:26 +00:00
ret . dptr = tdb_alloc_read ( tdb , rec_ptr + sizeof ( rec ) + rec . key_len ,
rec . data_len ) ;
2000-12-06 00:05:15 +00:00
ret . dsize = rec . data_len ;
tdb_unlock ( tdb , BUCKET ( rec . full_hash ) , F_RDLCK ) ;
2000-01-07 03:01:55 +00:00
return ret ;
1999-12-21 03:04:37 +00:00
}
/* check if an entry in the database exists
note that 1 is returned if the key is found and 0 is returned if not found
this doesn ' t match the conventions in the rest of this module , but is
compatible with gdbm
*/
2006-07-11 18:01:26 +00:00
static int tdb_exists_hash ( struct tdb_context * tdb , TDB_DATA key , u32 hash )
1999-12-21 03:04:37 +00:00
{
struct list_struct rec ;
2000-01-07 03:01:55 +00:00
2003-09-06 19:59:12 +00:00
if ( tdb_find_lock_hash ( tdb , key , hash , F_RDLCK , & rec ) = = 0 )
2001-08-02 20:17:40 +00:00
return 0 ;
2000-12-06 00:05:15 +00:00
tdb_unlock ( tdb , BUCKET ( rec . full_hash ) , F_RDLCK ) ;
return 1 ;
}
1999-12-21 03:04:37 +00:00
2006-07-11 18:01:26 +00:00
int tdb_exists ( struct tdb_context * tdb , TDB_DATA key )
{
u32 hash = tdb - > hash_fn ( & key ) ;
return tdb_exists_hash ( tdb , key , hash ) ;
2000-01-07 03:01:55 +00:00
}
1999-12-21 03:04:37 +00:00
2000-12-06 00:05:15 +00:00
/* actually delete an entry in the database given the offset */
2006-07-11 18:01:26 +00:00
int tdb_do_delete ( struct tdb_context * tdb , tdb_off_t rec_ptr , struct list_struct * rec )
1999-12-21 03:04:37 +00:00
{
2006-07-11 18:01:26 +00:00
tdb_off_t last_ptr , i ;
2000-12-06 00:05:15 +00:00
struct list_struct lastrec ;
1999-12-21 03:04:37 +00:00
2006-07-11 18:01:26 +00:00
if ( tdb - > read_only | | tdb - > traverse_read ) return - 1 ;
2000-12-11 06:10:32 +00:00
2006-07-11 18:01:26 +00:00
if ( tdb_write_lock_record ( tdb , rec_ptr ) = = - 1 ) {
2000-12-06 00:05:15 +00:00
/* Someone traversing here: mark it as dead */
rec - > magic = TDB_DEAD_MAGIC ;
2006-07-11 18:01:26 +00:00
return tdb_rec_write ( tdb , rec_ptr , rec ) ;
2000-12-06 00:05:15 +00:00
}
2006-07-11 18:01:26 +00:00
if ( tdb_write_unlock_record ( tdb , rec_ptr ) ! = 0 )
2002-04-07 22:02:09 +00:00
return - 1 ;
2000-02-16 22:57:57 +00:00
2000-12-06 00:05:15 +00:00
/* find previous record in hash chain */
2006-07-11 18:01:26 +00:00
if ( tdb_ofs_read ( tdb , TDB_HASH_TOP ( rec - > full_hash ) , & i ) = = - 1 )
2001-08-02 20:17:40 +00:00
return - 1 ;
2000-12-06 00:05:15 +00:00
for ( last_ptr = 0 ; i ! = rec_ptr ; last_ptr = i , i = lastrec . next )
2006-07-11 18:01:26 +00:00
if ( tdb_rec_read ( tdb , i , & lastrec ) = = - 1 )
2001-08-02 20:17:40 +00:00
return - 1 ;
1999-12-23 01:14:20 +00:00
2000-12-06 00:05:15 +00:00
/* unlink it: next ptr is at start of record. */
2001-08-02 20:17:40 +00:00
if ( last_ptr = = 0 )
last_ptr = TDB_HASH_TOP ( rec - > full_hash ) ;
2006-07-11 18:01:26 +00:00
if ( tdb_ofs_write ( tdb , last_ptr , & rec - > next ) = = - 1 )
2001-08-02 20:17:40 +00:00
return - 1 ;
1999-12-21 03:04:37 +00:00
2000-12-06 00:05:15 +00:00
/* recover the space */
2001-08-02 20:17:40 +00:00
if ( tdb_free ( tdb , rec_ptr , rec ) = = - 1 )
return - 1 ;
2000-12-06 00:05:15 +00:00
return 0 ;
}
1999-12-21 03:04:37 +00:00
/* delete an entry in the database given a key */
2006-07-11 18:01:26 +00:00
static int tdb_delete_hash ( struct tdb_context * tdb , TDB_DATA key , u32 hash )
1999-12-21 03:04:37 +00:00
{
2006-07-11 18:01:26 +00:00
tdb_off_t rec_ptr ;
2000-12-06 00:05:15 +00:00
struct list_struct rec ;
int ret ;
1999-12-23 01:14:20 +00:00
2003-09-06 19:59:12 +00:00
if ( ! ( rec_ptr = tdb_find_lock_hash ( tdb , key , hash , F_WRLCK , & rec ) ) )
2001-08-02 20:17:40 +00:00
return - 1 ;
2006-07-11 18:01:26 +00:00
ret = tdb_do_delete ( tdb , rec_ptr , & rec ) ;
if ( ret = = 0 ) {
tdb_increment_seqnum ( tdb ) ;
}
2002-04-07 22:02:09 +00:00
if ( tdb_unlock ( tdb , BUCKET ( rec . full_hash ) , F_WRLCK ) ! = 0 )
2006-10-20 09:55:47 +00:00
TDB_LOG ( ( tdb , TDB_DEBUG_WARNING , " tdb_delete: WARNING tdb_unlock failed! \n " ) ) ;
2000-12-06 00:05:15 +00:00
return ret ;
1999-12-21 03:04:37 +00:00
}
2006-07-11 18:01:26 +00:00
int tdb_delete ( struct tdb_context * tdb , TDB_DATA key )
2003-09-06 19:59:12 +00:00
{
2004-08-24 22:48:49 +00:00
u32 hash = tdb - > hash_fn ( & key ) ;
2003-09-06 19:59:12 +00:00
return tdb_delete_hash ( tdb , key , hash ) ;
}
1999-12-21 03:04:37 +00:00
/* store an element in the database, replacing any existing element
with the same key
return 0 on success , - 1 on failure
*/
2006-07-11 18:01:26 +00:00
int tdb_store ( struct tdb_context * tdb , TDB_DATA key , TDB_DATA dbuf , int flag )
1999-12-21 03:04:37 +00:00
{
struct list_struct rec ;
2000-12-06 00:05:15 +00:00
u32 hash ;
2006-07-11 18:01:26 +00:00
tdb_off_t rec_ptr ;
2000-01-02 01:40:35 +00:00
char * p = NULL ;
2000-12-06 00:05:15 +00:00
int ret = 0 ;
2000-02-16 22:57:57 +00:00
2006-07-11 18:01:26 +00:00
if ( tdb - > read_only | | tdb - > traverse_read ) {
tdb - > ecode = TDB_ERR_RDONLY ;
return - 1 ;
}
1999-12-23 01:14:20 +00:00
/* find which hash bucket it is in */
2004-08-24 22:48:49 +00:00
hash = tdb - > hash_fn ( & key ) ;
2001-08-02 20:17:40 +00:00
if ( tdb_lock ( tdb , BUCKET ( hash ) , F_WRLCK ) = = - 1 )
return - 1 ;
2000-06-15 15:29:39 +00:00
2000-04-25 01:17:45 +00:00
/* check for it existing, on insert. */
2000-12-06 00:05:15 +00:00
if ( flag = = TDB_INSERT ) {
2003-09-06 19:59:12 +00:00
if ( tdb_exists_hash ( tdb , key , hash ) ) {
2000-12-06 00:05:15 +00:00
tdb - > ecode = TDB_ERR_EXISTS ;
goto fail ;
}
} else {
/* first try in-place update, on modify or replace. */
2003-09-06 19:59:12 +00:00
if ( tdb_update_hash ( tdb , key , hash , dbuf ) = = 0 )
2001-08-02 20:17:40 +00:00
goto out ;
2004-03-28 02:19:58 +00:00
if ( tdb - > ecode = = TDB_ERR_NOEXIST & &
flag = = TDB_MODIFY ) {
/* if the record doesn't exist and we are in TDB_MODIFY mode then
we should fail the store */
2000-12-06 00:05:15 +00:00
goto fail ;
2006-07-11 18:01:26 +00:00
}
2004-03-28 02:19:58 +00:00
}
2000-04-25 01:17:45 +00:00
/* reset the error code potentially set by the tdb_update() */
2000-12-06 00:05:15 +00:00
tdb - > ecode = TDB_SUCCESS ;
1999-12-24 08:45:02 +00:00
2000-12-06 00:05:15 +00:00
/* delete any existing record - if it doesn't exist we don't
care . Doing this first reduces fragmentation , and avoids
coalescing with ` allocated ' block before it ' s updated . */
2001-08-02 20:17:40 +00:00
if ( flag ! = TDB_INSERT )
2003-09-06 19:59:12 +00:00
tdb_delete_hash ( tdb , key , hash ) ;
1999-12-22 01:22:14 +00:00
2001-01-29 21:34:08 +00:00
/* Copy key+value *before* allocating free space in case malloc
fails and we are left with a dead spot in the tdb . */
if ( ! ( p = ( char * ) malloc ( key . dsize + dbuf . dsize ) ) ) {
tdb - > ecode = TDB_ERR_OOM ;
goto fail ;
}
memcpy ( p , key . dptr , key . dsize ) ;
2002-11-07 02:15:35 +00:00
if ( dbuf . dsize )
memcpy ( p + key . dsize , dbuf . dptr , dbuf . dsize ) ;
2001-01-29 21:34:08 +00:00
2004-03-28 02:19:58 +00:00
/* we have to allocate some space */
2000-12-13 06:33:53 +00:00
if ( ! ( rec_ptr = tdb_allocate ( tdb , key . dsize + dbuf . dsize , & rec ) ) )
goto fail ;
1999-12-21 03:04:37 +00:00
2000-12-13 06:33:53 +00:00
/* Read hash top into next ptr */
2006-07-11 18:01:26 +00:00
if ( tdb_ofs_read ( tdb , TDB_HASH_TOP ( hash ) , & rec . next ) = = - 1 )
2001-08-02 20:17:40 +00:00
goto fail ;
1999-12-21 03:04:37 +00:00
rec . key_len = key . dsize ;
rec . data_len = dbuf . dsize ;
rec . full_hash = hash ;
1999-12-22 01:22:14 +00:00
rec . magic = TDB_MAGIC ;
1999-12-21 03:04:37 +00:00
2000-12-06 00:05:15 +00:00
/* write out and point the top of the hash chain at it */
2006-07-11 18:01:26 +00:00
if ( tdb_rec_write ( tdb , rec_ptr , & rec ) = = - 1
| | tdb - > methods - > tdb_write ( tdb , rec_ptr + sizeof ( rec ) , p , key . dsize + dbuf . dsize ) = = - 1
| | tdb_ofs_write ( tdb , TDB_HASH_TOP ( hash ) , & rec_ptr ) = = - 1 ) {
2001-01-29 21:34:08 +00:00
/* Need to tdb_unallocate() here */
2002-04-07 22:02:09 +00:00
goto fail ;
2000-12-06 00:05:15 +00:00
}
2006-07-11 18:01:26 +00:00
tdb_increment_seqnum ( tdb ) ;
2000-12-06 00:05:15 +00:00
out :
2002-01-02 23:28:55 +00:00
SAFE_FREE ( p ) ;
2000-12-06 00:05:15 +00:00
tdb_unlock ( tdb , BUCKET ( hash ) , F_WRLCK ) ;
return ret ;
2002-04-07 22:02:09 +00:00
fail :
ret = - 1 ;
goto out ;
1999-12-21 03:04:37 +00:00
}
2003-01-11 00:07:44 +00:00
/* Append to an entry. Create if not exist. */
2006-07-11 18:01:26 +00:00
int tdb_append ( struct tdb_context * tdb , TDB_DATA key , TDB_DATA new_dbuf )
2003-01-11 00:07:44 +00:00
{
u32 hash ;
2006-07-11 18:01:26 +00:00
TDB_DATA dbuf ;
int ret = - 1 ;
2003-01-11 00:07:44 +00:00
/* find which hash bucket it is in */
2004-08-24 22:48:49 +00:00
hash = tdb - > hash_fn ( & key ) ;
2003-01-11 00:07:44 +00:00
if ( tdb_lock ( tdb , BUCKET ( hash ) , F_WRLCK ) = = - 1 )
return - 1 ;
2006-07-11 18:01:26 +00:00
dbuf = tdb_fetch ( tdb , key ) ;
2003-01-11 00:07:44 +00:00
2006-07-11 18:01:26 +00:00
if ( dbuf . dptr = = NULL ) {
2006-07-30 10:42:11 +00:00
dbuf . dptr = ( char * ) malloc ( new_dbuf . dsize ) ;
2006-07-11 18:01:26 +00:00
} else {
2006-07-30 10:42:11 +00:00
dbuf . dptr = ( char * ) realloc ( dbuf . dptr ,
dbuf . dsize + new_dbuf . dsize ) ;
2003-01-11 00:07:44 +00:00
}
2006-07-11 18:01:26 +00:00
if ( dbuf . dptr = = NULL ) {
2003-01-11 00:07:44 +00:00
tdb - > ecode = TDB_ERR_OOM ;
2006-07-11 18:01:26 +00:00
goto failed ;
2004-02-19 01:55:24 +00:00
}
2006-07-11 18:01:26 +00:00
memcpy ( dbuf . dptr + dbuf . dsize , new_dbuf . dptr , new_dbuf . dsize ) ;
dbuf . dsize + = new_dbuf . dsize ;
1999-12-21 03:04:37 +00:00
2006-07-11 18:01:26 +00:00
ret = tdb_store ( tdb , key , dbuf , 0 ) ;
2001-12-04 13:21:15 +00:00
2006-07-11 18:01:26 +00:00
failed :
tdb_unlock ( tdb , BUCKET ( hash ) , F_WRLCK ) ;
SAFE_FREE ( dbuf . dptr ) ;
2000-12-06 00:05:15 +00:00
return ret ;
1999-12-21 03:04:37 +00:00
}
2002-04-07 22:02:09 +00:00
2006-07-11 18:01:26 +00:00
/*
return the name of the current tdb file
useful for external logging functions
*/
const char * tdb_name ( struct tdb_context * tdb )
2000-12-06 00:05:15 +00:00
{
2006-07-11 18:01:26 +00:00
return tdb - > name ;
2000-12-02 01:04:11 +00:00
}
2001-05-28 13:29:06 +00:00
2006-07-11 18:01:26 +00:00
/*
return the underlying file descriptor being used by tdb , or - 1
useful for external routines that want to check the device / inode
of the fd
*/
int tdb_fd ( struct tdb_context * tdb )
2002-11-09 03:36:47 +00:00
{
2006-07-11 18:01:26 +00:00
return tdb - > fd ;
2002-11-09 03:36:47 +00:00
}
2006-07-11 18:01:26 +00:00
/*
return the current logging function
useful for external tdb routines that wish to log tdb errors
*/
tdb_log_func tdb_log_fn ( struct tdb_context * tdb )
2002-11-09 03:36:47 +00:00
{
2006-10-20 09:55:47 +00:00
return tdb - > log . log_fn ;
2002-11-09 03:36:47 +00:00
}
2001-05-28 13:29:06 +00:00
2006-07-11 18:01:26 +00:00
/*
get the tdb sequence number . Only makes sense if the writers opened
with TDB_SEQNUM set . Note that this sequence number will wrap quite
quickly , so it should only be used for a ' has something changed '
test , not for code that relies on the count of the number of changes
made . If you want a counter then use a tdb record .
The aim of this sequence number is to allow for a very lightweight
test of a possible tdb change .
*/
int tdb_get_seqnum ( struct tdb_context * tdb )
2001-09-19 05:43:15 +00:00
{
2006-07-11 18:01:26 +00:00
tdb_off_t seqnum = 0 ;
2001-09-19 05:43:15 +00:00
2006-07-11 18:01:26 +00:00
tdb_ofs_read ( tdb , TDB_SEQNUM_OFS , & seqnum ) ;
return seqnum ;
2001-09-19 05:43:15 +00:00
}
2006-07-11 18:01:26 +00:00
int tdb_hash_size ( struct tdb_context * tdb )
2001-09-19 05:43:15 +00:00
{
2006-07-11 18:01:26 +00:00
return tdb - > header . hash_size ;
2001-09-19 05:43:15 +00:00
}
2006-10-20 09:55:47 +00:00
size_t tdb_map_size ( struct tdb_context * tdb )
{
return tdb - > map_size ;
}
int tdb_get_flags ( struct tdb_context * tdb )
{
return tdb - > flags ;
}