2003-08-13 05:53:07 +04:00
/*
Unix SMB / CIFS implementation .
2005-09-16 07:52:42 +04:00
2003-08-13 05:53:07 +04:00
tdb utility functions
2005-09-16 07:52:42 +04:00
2006-10-21 03:32:23 +04:00
Copyright ( C ) Andrew Tridgell 1992 - 2006
2003-08-13 05:53:07 +04:00
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
2007-07-10 06:07:03 +04:00
the Free Software Foundation ; either version 3 of the License , or
2003-08-13 05:53:07 +04:00
( at your option ) any later version .
This program 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 General Public License for more details .
You should have received a copy of the GNU General Public License
2007-07-10 06:07:03 +04:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
2003-08-13 05:53:07 +04:00
*/
# include "includes.h"
2008-09-16 17:16:31 +04:00
# include "../tdb/include/tdb.h"
2008-10-11 23:31:42 +04:00
# include "../lib/util/util_tdb.h"
2003-08-13 05:53:07 +04:00
/* these are little tdb utility functions that are meant to make
dealing with a tdb database a little less cumbersome in Samba */
/***************************************************************
Make a TDB_DATA and keep the const warning in one place
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-10-12 18:53:17 +04:00
TDB_DATA make_tdb_data ( const uint8_t * dptr , size_t dsize )
2003-08-13 05:53:07 +04:00
{
TDB_DATA ret ;
2008-10-12 18:53:17 +04:00
ret . dptr = discard_const_p ( uint8_t , dptr ) ;
2003-08-13 05:53:07 +04:00
ret . dsize = dsize ;
return ret ;
}
2008-10-12 18:53:17 +04:00
TDB_DATA string_tdb_data ( const char * string )
{
2008-10-12 19:34:43 +04:00
return make_tdb_data ( ( const uint8_t * ) string , string ? strlen ( string ) : 0 ) ;
2008-10-12 18:53:17 +04:00
}
TDB_DATA string_term_tdb_data ( const char * string )
{
2008-10-12 19:34:43 +04:00
return make_tdb_data ( ( const uint8_t * ) string , string ? strlen ( string ) + 1 : 0 ) ;
2008-10-12 18:53:17 +04:00
}
2003-08-13 05:53:07 +04:00
/****************************************************************************
2005-03-13 05:20:51 +03:00
Lock a chain by string . Return - 1 if lock failed .
2003-08-13 05:53:07 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-09-16 07:52:42 +04:00
int tdb_lock_bystring ( struct tdb_context * tdb , const char * keyval )
2003-08-13 05:53:07 +04:00
{
2008-10-12 18:53:17 +04:00
TDB_DATA key = string_term_tdb_data ( keyval ) ;
2003-08-13 05:53:07 +04:00
2005-03-13 04:40:45 +03:00
return tdb_chainlock ( tdb , key ) ;
2003-08-13 05:53:07 +04:00
}
/****************************************************************************
Unlock a chain by string .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-09-16 07:52:42 +04:00
void tdb_unlock_bystring ( struct tdb_context * tdb , const char * keyval )
2003-08-13 05:53:07 +04:00
{
2008-10-12 18:53:17 +04:00
TDB_DATA key = string_term_tdb_data ( keyval ) ;
2003-08-13 05:53:07 +04:00
tdb_chainunlock ( tdb , key ) ;
}
/****************************************************************************
2005-03-13 05:20:51 +03:00
Read lock a chain by string . Return - 1 if lock failed .
2003-08-13 05:53:07 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-09-16 07:52:42 +04:00
int tdb_read_lock_bystring ( struct tdb_context * tdb , const char * keyval )
2003-08-13 05:53:07 +04:00
{
2008-10-12 18:53:17 +04:00
TDB_DATA key = string_term_tdb_data ( keyval ) ;
2003-08-13 05:53:07 +04:00
2005-03-13 04:40:45 +03:00
return tdb_chainlock_read ( tdb , key ) ;
2003-08-13 05:53:07 +04:00
}
/****************************************************************************
Read unlock a chain by string .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-09-16 07:52:42 +04:00
void tdb_read_unlock_bystring ( struct tdb_context * tdb , const char * keyval )
2003-08-13 05:53:07 +04:00
{
2008-10-12 18:53:17 +04:00
TDB_DATA key = string_term_tdb_data ( keyval ) ;
2003-08-13 05:53:07 +04:00
tdb_chainunlock_read ( tdb , key ) ;
}
/****************************************************************************
2004-05-25 20:24:13 +04:00
Fetch a int32_t value by a arbitrary blob key , return - 1 if not found .
Output is int32_t in native byte order .
2003-08-13 05:53:07 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-10-12 18:53:17 +04:00
int32_t tdb_fetch_int32_byblob ( struct tdb_context * tdb , TDB_DATA key )
2003-08-13 05:53:07 +04:00
{
TDB_DATA data ;
2004-05-25 20:24:13 +04:00
int32_t ret ;
2003-08-13 05:53:07 +04:00
data = tdb_fetch ( tdb , key ) ;
2004-05-25 20:50:09 +04:00
if ( ! data . dptr | | data . dsize ! = sizeof ( int32_t ) ) {
2003-08-13 05:53:07 +04:00
SAFE_FREE ( data . dptr ) ;
return - 1 ;
}
ret = IVAL ( data . dptr , 0 ) ;
SAFE_FREE ( data . dptr ) ;
return ret ;
}
/****************************************************************************
2004-05-25 20:24:13 +04:00
Fetch a int32_t value by string key , return - 1 if not found .
Output is int32_t in native byte order .
2003-08-13 05:53:07 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-09-16 07:52:42 +04:00
int32_t tdb_fetch_int32 ( struct tdb_context * tdb , const char * keystr )
2003-08-13 05:53:07 +04:00
{
2008-10-12 18:53:17 +04:00
return tdb_fetch_int32_byblob ( tdb , string_term_tdb_data ( keystr ) ) ;
2003-08-13 05:53:07 +04:00
}
/****************************************************************************
2004-05-25 20:24:13 +04:00
Store a int32_t value by an arbitary blob key , return 0 on success , - 1 on failure .
Input is int32_t in native byte order . Output in tdb is in little - endian .
2003-08-13 05:53:07 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-10-12 18:53:17 +04:00
int tdb_store_int32_byblob ( struct tdb_context * tdb , TDB_DATA key , int32_t v )
2003-08-13 05:53:07 +04:00
{
TDB_DATA data ;
2004-05-25 20:24:13 +04:00
int32_t v_store ;
2003-08-13 05:53:07 +04:00
SIVAL ( & v_store , 0 , v ) ;
2007-09-08 17:27:14 +04:00
data . dptr = ( unsigned char * ) & v_store ;
2004-05-25 20:50:09 +04:00
data . dsize = sizeof ( int32_t ) ;
2003-08-13 05:53:07 +04:00
return tdb_store ( tdb , key , data , TDB_REPLACE ) ;
}
/****************************************************************************
2004-05-25 20:24:13 +04:00
Store a int32_t value by string key , return 0 on success , - 1 on failure .
Input is int32_t in native byte order . Output in tdb is in little - endian .
2003-08-13 05:53:07 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-09-16 07:52:42 +04:00
int tdb_store_int32 ( struct tdb_context * tdb , const char * keystr , int32_t v )
2003-08-13 05:53:07 +04:00
{
2008-10-12 18:53:17 +04:00
return tdb_store_int32_byblob ( tdb , string_term_tdb_data ( keystr ) , v ) ;
2003-08-13 05:53:07 +04:00
}
/****************************************************************************
2009-05-12 04:29:16 +04:00
Fetch a uint32_t value by a arbitrary blob key , return false if not found .
2004-05-25 20:24:13 +04:00
Output is uint32_t in native byte order .
2003-08-13 05:53:07 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-10-12 18:53:17 +04:00
bool tdb_fetch_uint32_byblob ( struct tdb_context * tdb , TDB_DATA key , uint32_t * value )
2003-08-13 05:53:07 +04:00
{
TDB_DATA data ;
data = tdb_fetch ( tdb , key ) ;
2004-05-25 20:50:09 +04:00
if ( ! data . dptr | | data . dsize ! = sizeof ( uint32_t ) ) {
2003-08-13 05:53:07 +04:00
SAFE_FREE ( data . dptr ) ;
2007-08-27 21:21:16 +04:00
return false ;
2003-08-13 05:53:07 +04:00
}
* value = IVAL ( data . dptr , 0 ) ;
SAFE_FREE ( data . dptr ) ;
2007-08-27 21:21:16 +04:00
return true ;
2003-08-13 05:53:07 +04:00
}
/****************************************************************************
2009-05-12 04:29:16 +04:00
Fetch a uint32_t value by string key , return false if not found .
2004-05-25 20:24:13 +04:00
Output is uint32_t in native byte order .
2003-08-13 05:53:07 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-08-27 21:21:16 +04:00
bool tdb_fetch_uint32 ( struct tdb_context * tdb , const char * keystr , uint32_t * value )
2003-08-13 05:53:07 +04:00
{
2008-10-12 18:53:17 +04:00
return tdb_fetch_uint32_byblob ( tdb , string_term_tdb_data ( keystr ) , value ) ;
2003-08-13 05:53:07 +04:00
}
/****************************************************************************
2004-05-25 20:24:13 +04:00
Store a uint32_t value by an arbitary blob key , return 0 on success , - 1 on failure .
Input is uint32_t in native byte order . Output in tdb is in little - endian .
2003-08-13 05:53:07 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-10-12 18:53:17 +04:00
bool tdb_store_uint32_byblob ( struct tdb_context * tdb , TDB_DATA key , uint32_t value )
2003-08-13 05:53:07 +04:00
{
TDB_DATA data ;
2004-05-25 20:24:13 +04:00
uint32_t v_store ;
2007-08-27 21:21:16 +04:00
bool ret = true ;
2003-08-13 05:53:07 +04:00
SIVAL ( & v_store , 0 , value ) ;
2007-09-08 17:27:14 +04:00
data . dptr = ( unsigned char * ) & v_store ;
2004-05-25 20:50:09 +04:00
data . dsize = sizeof ( uint32_t ) ;
2003-08-13 05:53:07 +04:00
if ( tdb_store ( tdb , key , data , TDB_REPLACE ) = = - 1 )
2007-08-27 21:21:16 +04:00
ret = false ;
2003-08-13 05:53:07 +04:00
return ret ;
}
/****************************************************************************
2004-05-25 20:24:13 +04:00
Store a uint32_t value by string key , return 0 on success , - 1 on failure .
Input is uint32_t in native byte order . Output in tdb is in little - endian .
2003-08-13 05:53:07 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-08-27 21:21:16 +04:00
bool tdb_store_uint32 ( struct tdb_context * tdb , const char * keystr , uint32_t value )
2003-08-13 05:53:07 +04:00
{
2008-10-12 18:53:17 +04:00
return tdb_store_uint32_byblob ( tdb , string_term_tdb_data ( keystr ) , value ) ;
2003-08-13 05:53:07 +04:00
}
/****************************************************************************
Store a buffer by a null terminated string key . Return 0 on success , - 1
on failure .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-09-16 07:52:42 +04:00
int tdb_store_bystring ( struct tdb_context * tdb , const char * keystr , TDB_DATA data , int flags )
2003-08-13 05:53:07 +04:00
{
2008-10-12 18:53:17 +04:00
TDB_DATA key = string_term_tdb_data ( keystr ) ;
2003-08-13 05:53:07 +04:00
return tdb_store ( tdb , key , data , flags ) ;
}
/****************************************************************************
Fetch a buffer using a null terminated string key . Don ' t forget to call
free ( ) on the result dptr .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-09-16 07:52:42 +04:00
TDB_DATA tdb_fetch_bystring ( struct tdb_context * tdb , const char * keystr )
2003-08-13 05:53:07 +04:00
{
2008-10-12 18:53:17 +04:00
TDB_DATA key = string_term_tdb_data ( keystr ) ;
2003-08-13 05:53:07 +04:00
return tdb_fetch ( tdb , key ) ;
}
/****************************************************************************
Delete an entry using a null terminated string key .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-09-16 07:52:42 +04:00
int tdb_delete_bystring ( struct tdb_context * tdb , const char * keystr )
2003-08-13 05:53:07 +04:00
{
2008-10-12 18:53:17 +04:00
TDB_DATA key = string_term_tdb_data ( keystr ) ;
2003-08-13 05:53:07 +04:00
return tdb_delete ( tdb , key ) ;
}
/****************************************************************************
Atomic integer change . Returns old value . To create , set initial value in * oldval .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-09-16 07:52:42 +04:00
int32_t tdb_change_int32_atomic ( struct tdb_context * tdb , const char * keystr , int32_t * oldval , int32_t change_val )
2003-08-13 05:53:07 +04:00
{
2004-05-25 20:24:13 +04:00
int32_t val ;
int32_t ret = - 1 ;
2003-08-13 05:53:07 +04:00
2005-03-13 05:20:51 +03:00
if ( tdb_lock_bystring ( tdb , keystr ) = = - 1 )
2003-08-13 05:53:07 +04:00
return - 1 ;
if ( ( val = tdb_fetch_int32 ( tdb , keystr ) ) = = - 1 ) {
/* The lookup failed */
if ( tdb_error ( tdb ) ! = TDB_ERR_NOEXIST ) {
2003-12-10 06:02:12 +03:00
/* but not because it didn't exist */
2003-08-13 05:53:07 +04:00
goto err_out ;
}
/* Start with 'old' value */
val = * oldval ;
} else {
/* It worked, set return value (oldval) to tdb data */
* oldval = val ;
}
/* Increment value for storage and return next time */
val + = change_val ;
if ( tdb_store_int32 ( tdb , keystr , val ) = = - 1 )
goto err_out ;
ret = 0 ;
err_out :
tdb_unlock_bystring ( tdb , keystr ) ;
return ret ;
}
/****************************************************************************
Atomic unsigned integer change . Returns old value . To create , set initial value in * oldval .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-08-27 21:21:16 +04:00
bool tdb_change_uint32_atomic ( struct tdb_context * tdb , const char * keystr , uint32_t * oldval , uint32_t change_val )
2003-08-13 05:53:07 +04:00
{
2004-05-25 20:24:13 +04:00
uint32_t val ;
2007-08-27 21:21:16 +04:00
bool ret = false ;
2003-08-13 05:53:07 +04:00
2005-03-13 05:20:51 +03:00
if ( tdb_lock_bystring ( tdb , keystr ) = = - 1 )
2007-08-27 21:21:16 +04:00
return false ;
2003-08-13 05:53:07 +04:00
if ( ! tdb_fetch_uint32 ( tdb , keystr , & val ) ) {
/* It failed */
if ( tdb_error ( tdb ) ! = TDB_ERR_NOEXIST ) {
2003-12-10 06:02:12 +03:00
/* and not because it didn't exist */
2003-08-13 05:53:07 +04:00
goto err_out ;
}
/* Start with 'old' value */
val = * oldval ;
} else {
/* it worked, set return value (oldval) to tdb data */
* oldval = val ;
}
/* get a new value to store */
val + = change_val ;
if ( ! tdb_store_uint32 ( tdb , keystr , val ) )
goto err_out ;
2007-08-27 21:21:16 +04:00
ret = true ;
2003-08-13 05:53:07 +04:00
err_out :
tdb_unlock_bystring ( tdb , keystr ) ;
return ret ;
}
2005-09-16 07:52:42 +04:00
/****************************************************************************
Allow tdb_delete to be used as a tdb_traversal_fn .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
int tdb_traverse_delete_fn ( struct tdb_context * the_tdb , TDB_DATA key , TDB_DATA dbuf ,
void * state )
{
return tdb_delete ( the_tdb , key ) ;
}