2008-01-16 12:09:48 +03:00
/*
Unix SMB / CIFS implementation .
Utility functions for the dbwrap API
Copyright ( C ) Volker Lendecke 2007
2009-07-15 18:59:07 +04:00
Copyright ( C ) Michael Adam 2009
2008-01-16 12:09:48 +03: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
the Free Software Foundation ; either version 2 of the License , or
( 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
along with this program ; if not , write to the Free Software
Foundation , Inc . , 675 Mass Ave , Cambridge , MA 0213 9 , USA .
*/
# include "includes.h"
int32_t dbwrap_fetch_int32 ( struct db_context * db , const char * keystr )
{
TDB_DATA dbuf ;
int32 ret ;
if ( db - > fetch ( db , NULL , string_term_tdb_data ( keystr ) , & dbuf ) ! = 0 ) {
return - 1 ;
}
if ( ( dbuf . dptr = = NULL ) | | ( dbuf . dsize ! = sizeof ( int32_t ) ) ) {
TALLOC_FREE ( dbuf . dptr ) ;
return - 1 ;
}
ret = IVAL ( dbuf . dptr , 0 ) ;
TALLOC_FREE ( dbuf . dptr ) ;
return ret ;
}
int dbwrap_store_int32 ( struct db_context * db , const char * keystr , int32_t v )
{
struct db_record * rec ;
int32 v_store ;
NTSTATUS status ;
rec = db - > fetch_locked ( db , NULL , string_term_tdb_data ( keystr ) ) ;
if ( rec = = NULL ) {
return - 1 ;
}
SIVAL ( & v_store , 0 , v ) ;
2008-03-28 11:42:37 +03:00
status = rec - > store ( rec , make_tdb_data ( ( const uint8 * ) & v_store ,
sizeof ( v_store ) ) ,
TDB_REPLACE ) ;
TALLOC_FREE ( rec ) ;
return NT_STATUS_IS_OK ( status ) ? 0 : - 1 ;
}
bool dbwrap_fetch_uint32 ( struct db_context * db , const char * keystr ,
uint32_t * val )
{
TDB_DATA dbuf ;
if ( db - > fetch ( db , NULL , string_term_tdb_data ( keystr ) , & dbuf ) ! = 0 ) {
return false ;
}
if ( ( dbuf . dptr = = NULL ) | | ( dbuf . dsize ! = sizeof ( uint32_t ) ) ) {
TALLOC_FREE ( dbuf . dptr ) ;
return false ;
}
* val = IVAL ( dbuf . dptr , 0 ) ;
TALLOC_FREE ( dbuf . dptr ) ;
return true ;
}
2008-12-17 19:16:50 +03:00
int dbwrap_store_uint32 ( struct db_context * db , const char * keystr , uint32_t v )
2008-03-28 11:42:37 +03:00
{
struct db_record * rec ;
uint32 v_store ;
NTSTATUS status ;
rec = db - > fetch_locked ( db , NULL , string_term_tdb_data ( keystr ) ) ;
if ( rec = = NULL ) {
2008-12-17 19:16:50 +03:00
return - 1 ;
2008-03-28 11:42:37 +03:00
}
SIVAL ( & v_store , 0 , v ) ;
2008-01-16 12:09:48 +03:00
status = rec - > store ( rec , make_tdb_data ( ( const uint8 * ) & v_store ,
sizeof ( v_store ) ) ,
TDB_REPLACE ) ;
TALLOC_FREE ( rec ) ;
return NT_STATUS_IS_OK ( status ) ? 0 : - 1 ;
}
2008-08-06 01:13:06 +04:00
/**
* Atomic unsigned integer change ( addition ) :
*
* if value does not exist yet in the db , use * oldval as initial old value .
* return old value in * oldval .
* store * oldval + change_val to db .
*/
2009-07-29 16:32:31 +04:00
struct dbwrap_change_uint32_atomic_context {
const char * keystr ;
uint32_t * oldval ;
uint32_t change_val ;
} ;
static NTSTATUS dbwrap_change_uint32_atomic_action ( struct db_context * db ,
void * private_data )
2008-01-16 12:09:48 +03:00
{
struct db_record * rec ;
uint32 val = - 1 ;
TDB_DATA data ;
2009-07-29 16:16:11 +04:00
NTSTATUS ret ;
2009-07-29 16:32:31 +04:00
struct dbwrap_change_uint32_atomic_context * state ;
2008-01-16 12:09:48 +03:00
2009-07-29 16:32:31 +04:00
state = ( struct dbwrap_change_uint32_atomic_context * ) private_data ;
rec = db - > fetch_locked ( db , NULL , string_term_tdb_data ( state - > keystr ) ) ;
2009-07-29 16:25:29 +04:00
if ( ! rec ) {
2009-07-29 16:16:11 +04:00
return NT_STATUS_UNSUCCESSFUL ;
2008-01-16 12:09:48 +03:00
}
2008-08-06 00:38:44 +04:00
if ( rec - > value . dptr = = NULL ) {
2009-07-29 16:32:31 +04:00
val = * ( state - > oldval ) ;
2008-08-06 00:38:44 +04:00
} else if ( rec - > value . dsize = = sizeof ( val ) ) {
2008-01-16 12:09:48 +03:00
val = IVAL ( rec - > value . dptr , 0 ) ;
2009-07-29 16:32:31 +04:00
* ( state - > oldval ) = val ;
2008-08-06 00:38:44 +04:00
} else {
2009-07-29 16:22:37 +04:00
ret = NT_STATUS_UNSUCCESSFUL ;
goto done ;
2008-01-16 12:09:48 +03:00
}
2009-07-29 16:32:31 +04:00
val + = state - > change_val ;
2008-01-16 12:09:48 +03:00
data . dsize = sizeof ( val ) ;
data . dptr = ( uint8 * ) & val ;
2009-07-29 16:16:11 +04:00
ret = rec - > store ( rec , data , TDB_REPLACE ) ;
2008-01-16 12:09:48 +03:00
2009-07-29 16:22:37 +04:00
done :
2008-01-16 12:09:48 +03:00
TALLOC_FREE ( rec ) ;
2009-07-29 16:16:11 +04:00
return ret ;
2008-01-16 12:09:48 +03:00
}
2009-07-29 16:32:31 +04:00
NTSTATUS dbwrap_change_uint32_atomic ( struct db_context * db , const char * keystr ,
uint32_t * oldval , uint32_t change_val )
{
NTSTATUS ret ;
struct dbwrap_change_uint32_atomic_context state ;
state . keystr = keystr ;
state . oldval = oldval ;
state . change_val = change_val ;
ret = dbwrap_change_uint32_atomic_action ( db , & state ) ;
return ret ;
}
2009-07-29 16:37:39 +04:00
NTSTATUS dbwrap_trans_change_uint32_atomic ( struct db_context * db ,
const char * keystr ,
uint32_t * oldval ,
uint32_t change_val )
{
NTSTATUS ret ;
struct dbwrap_change_uint32_atomic_context state ;
state . keystr = keystr ;
state . oldval = oldval ;
state . change_val = change_val ;
ret = dbwrap_trans_do ( db , dbwrap_change_uint32_atomic_action , & state ) ;
return ret ;
}
2008-08-06 01:38:56 +04:00
/**
* Atomic integer change ( addition ) :
*
* if value does not exist yet in the db , use * oldval as initial old value .
* return old value in * oldval .
* store * oldval + change_val to db .
*/
2009-07-29 17:12:39 +04:00
struct dbwrap_change_int32_atomic_context {
const char * keystr ;
int32_t * oldval ;
int32_t change_val ;
} ;
static NTSTATUS dbwrap_change_int32_atomic_action ( struct db_context * db ,
void * private_data )
2008-03-09 13:15:10 +03:00
{
struct db_record * rec ;
2009-07-29 17:08:06 +04:00
int32_t val = - 1 ;
2008-03-09 13:15:10 +03:00
TDB_DATA data ;
2009-07-29 16:21:03 +04:00
NTSTATUS ret ;
2009-07-29 17:12:39 +04:00
struct dbwrap_change_int32_atomic_context * state ;
2008-03-09 13:15:10 +03:00
2009-07-29 17:12:39 +04:00
state = ( struct dbwrap_change_int32_atomic_context * ) private_data ;
rec = db - > fetch_locked ( db , NULL , string_term_tdb_data ( state - > keystr ) ) ;
2009-07-29 16:26:26 +04:00
if ( ! rec ) {
2009-07-29 16:21:03 +04:00
return NT_STATUS_UNSUCCESSFUL ;
2008-03-09 13:15:10 +03:00
}
2008-08-06 01:14:05 +04:00
if ( rec - > value . dptr = = NULL ) {
2009-07-29 17:12:39 +04:00
val = * ( state - > oldval ) ;
2008-08-06 01:14:05 +04:00
} else if ( rec - > value . dsize = = sizeof ( val ) ) {
2008-03-09 13:15:10 +03:00
val = IVAL ( rec - > value . dptr , 0 ) ;
2009-07-29 17:12:39 +04:00
* ( state - > oldval ) = val ;
2008-08-06 01:14:05 +04:00
} else {
2009-07-29 16:23:26 +04:00
ret = NT_STATUS_UNSUCCESSFUL ;
goto done ;
2008-03-09 13:15:10 +03:00
}
2009-07-29 17:12:39 +04:00
val + = state - > change_val ;
2008-03-09 13:15:10 +03:00
data . dsize = sizeof ( val ) ;
data . dptr = ( uint8 * ) & val ;
2009-07-29 16:21:03 +04:00
ret = rec - > store ( rec , data , TDB_REPLACE ) ;
2008-03-09 13:15:10 +03:00
2009-07-29 16:23:26 +04:00
done :
2008-03-09 13:15:10 +03:00
TALLOC_FREE ( rec ) ;
2009-07-29 16:21:03 +04:00
return ret ;
2008-03-09 13:15:10 +03:00
}
2008-03-10 15:27:27 +03:00
2009-07-29 17:12:39 +04:00
NTSTATUS dbwrap_change_int32_atomic ( struct db_context * db , const char * keystr ,
int32_t * oldval , int32_t change_val )
{
NTSTATUS ret ;
struct dbwrap_change_int32_atomic_context state ;
state . keystr = keystr ;
state . oldval = oldval ;
state . change_val = change_val ;
ret = dbwrap_change_int32_atomic_action ( db , & state ) ;
return ret ;
}
2009-07-29 17:14:57 +04:00
NTSTATUS dbwrap_trans_change_int32_atomic ( struct db_context * db ,
const char * keystr ,
int32_t * oldval ,
int32_t change_val )
{
NTSTATUS ret ;
struct dbwrap_change_int32_atomic_context state ;
state . keystr = keystr ;
state . oldval = oldval ;
state . change_val = change_val ;
ret = dbwrap_trans_do ( db , dbwrap_change_int32_atomic_action , & state ) ;
return ret ;
}
2009-07-21 14:35:48 +04:00
struct dbwrap_store_context {
TDB_DATA * key ;
TDB_DATA * dbuf ;
int flag ;
} ;
static NTSTATUS dbwrap_store_action ( struct db_context * db , void * private_data )
2008-03-10 15:27:27 +03:00
{
2008-03-30 15:11:22 +04:00
struct db_record * rec = NULL ;
2008-03-10 15:27:27 +03:00
NTSTATUS status ;
2009-07-21 14:35:48 +04:00
struct dbwrap_store_context * store_ctx ;
2008-03-10 15:27:27 +03:00
2009-07-21 14:35:48 +04:00
store_ctx = ( struct dbwrap_store_context * ) private_data ;
2008-03-10 15:27:27 +03:00
2009-07-21 14:35:48 +04:00
rec = db - > fetch_locked ( db , talloc_tos ( ) , * ( store_ctx - > key ) ) ;
2008-03-10 15:27:27 +03:00
if ( rec = = NULL ) {
DEBUG ( 5 , ( " fetch_locked failed \n " ) ) ;
2009-07-21 14:35:48 +04:00
return NT_STATUS_NO_MEMORY ;
2008-03-10 15:27:27 +03:00
}
2009-07-21 14:35:48 +04:00
status = rec - > store ( rec , * ( store_ctx - > dbuf ) , store_ctx - > flag ) ;
2008-03-10 15:27:27 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 5 , ( " store returned %s \n " , nt_errstr ( status ) ) ) ;
}
TALLOC_FREE ( rec ) ;
2009-07-21 14:35:48 +04:00
return status ;
}
2008-03-10 15:27:27 +03:00
2009-07-21 14:35:48 +04:00
NTSTATUS dbwrap_trans_store ( struct db_context * db , TDB_DATA key , TDB_DATA dbuf ,
int flag )
{
NTSTATUS status ;
struct dbwrap_store_context store_ctx ;
2008-03-10 15:27:27 +03:00
2009-07-21 14:35:48 +04:00
store_ctx . key = & key ;
store_ctx . dbuf = & dbuf ;
store_ctx . flag = flag ;
2008-03-10 15:27:27 +03:00
2009-07-21 14:35:48 +04:00
status = dbwrap_trans_do ( db , dbwrap_store_action , & store_ctx ) ;
2008-03-30 15:11:22 +04:00
2008-03-28 13:53:00 +03:00
return status ;
2008-03-10 15:27:27 +03:00
}
2009-07-21 14:26:14 +04:00
static NTSTATUS dbwrap_delete_action ( struct db_context * db , void * private_data )
2008-03-10 15:27:27 +03:00
{
NTSTATUS status ;
2009-07-21 14:26:14 +04:00
struct db_record * rec ;
TDB_DATA * key = ( TDB_DATA * ) private_data ;
2008-03-10 15:27:27 +03:00
2009-07-21 14:26:14 +04:00
rec = db - > fetch_locked ( db , talloc_tos ( ) , * key ) ;
2008-03-10 15:27:27 +03:00
if ( rec = = NULL ) {
DEBUG ( 5 , ( " fetch_locked failed \n " ) ) ;
2009-07-21 14:26:14 +04:00
return NT_STATUS_NO_MEMORY ;
2008-03-10 15:27:27 +03:00
}
status = rec - > delete_rec ( rec ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 5 , ( " delete_rec returned %s \n " , nt_errstr ( status ) ) ) ;
}
2009-07-21 14:26:14 +04:00
talloc_free ( rec ) ;
return status ;
}
2008-03-10 15:27:27 +03:00
2009-07-21 14:26:14 +04:00
NTSTATUS dbwrap_trans_delete ( struct db_context * db , TDB_DATA key )
{
NTSTATUS status ;
2008-03-10 15:27:27 +03:00
2009-07-21 14:26:14 +04:00
status = dbwrap_trans_do ( db , dbwrap_delete_action , & key ) ;
2008-04-08 01:36:29 +04:00
2008-03-28 13:57:54 +03:00
return status ;
2008-03-10 15:27:27 +03:00
}
2008-03-27 17:59:58 +03:00
2008-03-28 13:53:00 +03:00
NTSTATUS dbwrap_trans_store_int32 ( struct db_context * db , const char * keystr ,
int32_t v )
2008-03-27 17:59:58 +03:00
{
int32 v_store ;
SIVAL ( & v_store , 0 , v ) ;
2008-03-28 13:53:00 +03:00
return dbwrap_trans_store ( db , string_term_tdb_data ( keystr ) ,
make_tdb_data ( ( const uint8 * ) & v_store ,
2008-03-27 17:59:58 +03:00
sizeof ( v_store ) ) ,
2008-03-28 13:53:00 +03:00
TDB_REPLACE ) ;
2008-03-27 17:59:58 +03:00
}
2008-03-28 14:02:28 +03:00
2008-03-28 22:03:30 +03:00
NTSTATUS dbwrap_trans_store_uint32 ( struct db_context * db , const char * keystr ,
uint32_t v )
{
uint32 v_store ;
SIVAL ( & v_store , 0 , v ) ;
return dbwrap_trans_store ( db , string_term_tdb_data ( keystr ) ,
make_tdb_data ( ( const uint8 * ) & v_store ,
sizeof ( v_store ) ) ,
TDB_REPLACE ) ;
}
2008-03-28 14:02:28 +03:00
NTSTATUS dbwrap_trans_store_bystring ( struct db_context * db , const char * key ,
TDB_DATA data , int flags )
{
return dbwrap_trans_store ( db , string_term_tdb_data ( key ) , data , flags ) ;
}
NTSTATUS dbwrap_trans_delete_bystring ( struct db_context * db , const char * key )
{
return dbwrap_trans_delete ( db , string_term_tdb_data ( key ) ) ;
}
2009-07-15 16:00:42 +04:00
/**
* Wrap db action ( s ) into a transaction .
*/
NTSTATUS dbwrap_trans_do ( struct db_context * db ,
NTSTATUS ( * action ) ( struct db_context * , void * ) ,
void * private_data )
{
int res ;
NTSTATUS status ;
res = db - > transaction_start ( db ) ;
if ( res ! = 0 ) {
DEBUG ( 5 , ( " transaction_start failed \n " ) ) ;
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
}
status = action ( db , private_data ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
if ( db - > transaction_cancel ( db ) ! = 0 ) {
smb_panic ( " Cancelling transaction failed " ) ;
}
return status ;
}
res = db - > transaction_commit ( db ) ;
if ( res = = 0 ) {
return NT_STATUS_OK ;
}
DEBUG ( 2 , ( " transaction_commit failed \n " ) ) ;
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
}
2009-07-08 18:02:19 +04:00
NTSTATUS dbwrap_delete_bystring_upper ( struct db_context * db , const char * key )
{
char * key_upper ;
NTSTATUS status ;
key_upper = talloc_strdup_upper ( talloc_tos ( ) , key ) ;
if ( key_upper = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
status = dbwrap_delete_bystring ( db , key_upper ) ;
talloc_free ( key_upper ) ;
return status ;
}
2009-07-08 18:08:41 +04:00
NTSTATUS dbwrap_store_bystring_upper ( struct db_context * db , const char * key ,
TDB_DATA data , int flags )
{
char * key_upper ;
NTSTATUS status ;
key_upper = talloc_strdup_upper ( talloc_tos ( ) , key ) ;
if ( key_upper = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
status = dbwrap_store_bystring ( db , key_upper , data , flags ) ;
talloc_free ( key_upper ) ;
return status ;
}
2009-07-08 18:13:07 +04:00
TDB_DATA dbwrap_fetch_bystring_upper ( struct db_context * db , TALLOC_CTX * mem_ctx ,
const char * key )
{
char * key_upper ;
TDB_DATA result ;
key_upper = talloc_strdup_upper ( talloc_tos ( ) , key ) ;
if ( key_upper = = NULL ) {
return make_tdb_data ( NULL , 0 ) ;
}
result = dbwrap_fetch_bystring ( db , mem_ctx , key_upper ) ;
talloc_free ( key_upper ) ;
return result ;
}