2009-05-15 03:48:55 +04:00
/*
Samba Unix / Linux CIFS implementation
low level TDB / CTDB tool using the dbwrap interface
Copyright ( C ) 2009 Michael Adam < obnox @ samba . org >
2011-10-14 14:22:16 +04:00
Copyright ( C ) 2011 Bjoern Baumbach < bb @ sernet . de >
2009-05-15 03:48:55 +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
the Free Software Foundation ; either version 3 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 , see < http : //www.gnu.org/licenses/>.
*/
# include "includes.h"
2011-02-26 01:20:06 +03:00
# include "system/filesys.h"
2011-09-20 06:32:25 +04:00
# include "popt_common.h"
2011-07-07 19:42:08 +04:00
# include "dbwrap/dbwrap.h"
2011-07-06 18:40:21 +04:00
# include "dbwrap/dbwrap_open.h"
2011-03-24 17:31:06 +03:00
# include "messages.h"
2011-10-14 14:22:16 +04:00
# include "util_tdb.h"
2009-05-15 03:48:55 +04:00
2012-01-25 00:04:00 +04:00
enum dbwrap_op { OP_FETCH , OP_STORE , OP_DELETE , OP_ERASE , OP_LISTKEYS } ;
2009-05-15 03:48:55 +04:00
2012-01-25 00:04:40 +04:00
enum dbwrap_type { TYPE_INT32 , TYPE_UINT32 , TYPE_STRING , TYPE_HEX } ;
2009-05-15 03:48:55 +04:00
static int dbwrap_tool_fetch_int32 ( struct db_context * db ,
const char * keyname ,
2011-10-14 14:22:16 +04:00
const char * data )
2009-05-15 03:48:55 +04:00
{
int32_t value ;
2011-10-06 22:34:55 +04:00
NTSTATUS status ;
2009-05-15 03:48:55 +04:00
2011-10-06 22:34:55 +04:00
status = dbwrap_fetch_int32 ( db , keyname , & value ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
d_printf ( " Error fetching int32 from key '%s': %s \n " ,
keyname , nt_errstr ( status ) ) ;
return - 1 ;
}
2009-05-15 03:48:55 +04:00
d_printf ( " %d \n " , value ) ;
return 0 ;
}
static int dbwrap_tool_fetch_uint32 ( struct db_context * db ,
const char * keyname ,
2011-10-14 14:22:16 +04:00
const char * data )
2009-05-15 03:48:55 +04:00
{
uint32_t value ;
2011-10-06 23:07:27 +04:00
NTSTATUS ret ;
2009-05-15 03:48:55 +04:00
ret = dbwrap_fetch_uint32 ( db , keyname , & value ) ;
2011-10-06 23:07:27 +04:00
if ( NT_STATUS_IS_OK ( ret ) ) {
2009-05-15 03:48:55 +04:00
d_printf ( " %u \n " , value ) ;
return 0 ;
} else {
2011-10-06 23:07:27 +04:00
d_fprintf ( stderr , " ERROR: could not fetch uint32 key '%s': "
" %s \n " , nt_errstr ( ret ) , keyname ) ;
2009-05-15 03:48:55 +04:00
return - 1 ;
}
}
2011-10-17 18:08:38 +04:00
static int dbwrap_tool_fetch_string ( struct db_context * db ,
const char * keyname ,
const char * data )
{
TDB_DATA tdbdata ;
NTSTATUS status ;
TALLOC_CTX * tmp_ctx = talloc_stackframe ( ) ;
int ret ;
status = dbwrap_fetch_bystring ( db , tmp_ctx , keyname , & tdbdata ) ;
if ( NT_STATUS_IS_OK ( status ) ) {
2011-10-19 12:54:53 +04:00
d_printf ( " %-*.*s \n " , ( int ) tdbdata . dsize , ( int ) tdbdata . dsize ,
2011-10-17 18:08:38 +04:00
tdbdata . dptr ) ;
ret = 0 ;
} else {
d_fprintf ( stderr , " ERROR: could not fetch string key '%s': "
" %s \n " , nt_errstr ( status ) , keyname ) ;
ret = - 1 ;
}
talloc_free ( tmp_ctx ) ;
return ret ;
}
static int dbwrap_tool_fetch_hex ( struct db_context * db ,
const char * keyname ,
const char * data )
{
TDB_DATA tdbdata ;
DATA_BLOB datablob ;
NTSTATUS status ;
TALLOC_CTX * tmp_ctx = talloc_stackframe ( ) ;
char * hex_string ;
int ret ;
status = dbwrap_fetch_bystring ( db , tmp_ctx , keyname , & tdbdata ) ;
if ( NT_STATUS_IS_OK ( status ) ) {
datablob . data = tdbdata . dptr ;
datablob . length = tdbdata . dsize ;
hex_string = data_blob_hex_string_upper ( tmp_ctx , & datablob ) ;
if ( hex_string = = NULL ) {
d_fprintf ( stderr , " ERROR: could not get hex string "
" from data blob \n " ) ;
ret = - 1 ;
} else {
d_printf ( " %s \n " , hex_string ) ;
ret = 0 ;
}
} else {
d_fprintf ( stderr , " ERROR: could not fetch hex key '%s': "
" %s \n " , nt_errstr ( status ) , keyname ) ;
ret = - 1 ;
}
talloc_free ( tmp_ctx ) ;
return ret ;
}
2009-05-15 03:48:55 +04:00
static int dbwrap_tool_store_int32 ( struct db_context * db ,
const char * keyname ,
2011-10-14 14:22:16 +04:00
const char * data )
2009-05-15 03:48:55 +04:00
{
NTSTATUS status ;
2011-10-14 14:22:16 +04:00
int32_t value = ( int32_t ) strtol ( data , NULL , 10 ) ;
2009-05-15 03:48:55 +04:00
status = dbwrap_trans_store_int32 ( db , keyname , value ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
d_fprintf ( stderr , " ERROR: could not store int32 key '%s': %s \n " ,
keyname , nt_errstr ( status ) ) ;
return - 1 ;
}
return 0 ;
}
static int dbwrap_tool_store_uint32 ( struct db_context * db ,
const char * keyname ,
2011-10-14 14:22:16 +04:00
const char * data )
2009-05-15 03:48:55 +04:00
{
NTSTATUS status ;
2011-10-14 14:22:16 +04:00
uint32_t value = ( uint32_t ) strtol ( data , NULL , 10 ) ;
2009-05-15 03:48:55 +04:00
status = dbwrap_trans_store_uint32 ( db , keyname , value ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
d_fprintf ( stderr ,
" ERROR: could not store uint32 key '%s': %s \n " ,
keyname , nt_errstr ( status ) ) ;
return - 1 ;
}
return 0 ;
}
2011-10-14 14:22:16 +04:00
static int dbwrap_tool_store_string ( struct db_context * db ,
const char * keyname ,
const char * data )
{
NTSTATUS status ;
status = dbwrap_trans_store_bystring ( db , keyname ,
string_term_tdb_data ( data ) , TDB_REPLACE ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
d_fprintf ( stderr ,
" ERROR: could not store string key '%s': %s \n " ,
keyname , nt_errstr ( status ) ) ;
return - 1 ;
}
return 0 ;
}
2011-10-17 18:05:52 +04:00
static int dbwrap_tool_store_hex ( struct db_context * db ,
const char * keyname ,
const char * data )
{
NTSTATUS status ;
DATA_BLOB datablob ;
TDB_DATA tdbdata ;
TALLOC_CTX * tmp_ctx = talloc_stackframe ( ) ;
datablob = strhex_to_data_blob ( tmp_ctx , data ) ;
if ( strlen ( data ) > 0 & & datablob . length = = 0 ) {
d_fprintf ( stderr ,
" ERROR: could not convert hex string to data blob \n "
" Not a valid hex string? \n " ) ;
talloc_free ( tmp_ctx ) ;
return - 1 ;
}
tdbdata . dptr = ( unsigned char * ) datablob . data ;
tdbdata . dsize = datablob . length ;
status = dbwrap_trans_store_bystring ( db , keyname ,
tdbdata ,
TDB_REPLACE ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
d_fprintf ( stderr ,
" ERROR: could not store string key '%s': %s \n " ,
keyname , nt_errstr ( status ) ) ;
talloc_free ( tmp_ctx ) ;
return - 1 ;
}
talloc_free ( tmp_ctx ) ;
return 0 ;
}
2009-05-15 03:48:55 +04:00
static int dbwrap_tool_delete ( struct db_context * db ,
const char * keyname ,
2011-10-14 14:22:16 +04:00
const char * data )
2009-05-15 03:48:55 +04:00
{
NTSTATUS status ;
status = dbwrap_trans_delete_bystring ( db , keyname ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
d_fprintf ( stderr , " ERROR deleting record %s : %s \n " ,
keyname , nt_errstr ( status ) ) ;
return - 1 ;
}
return 0 ;
}
2009-05-26 01:27:28 +04:00
static int delete_fn ( struct db_record * rec , void * priv )
{
2011-08-17 13:42:45 +04:00
dbwrap_record_delete ( rec ) ;
2009-05-26 01:27:28 +04:00
return 0 ;
}
/**
* dbwrap_tool_erase : erase the whole data base
* the keyname argument is not used .
*/
static int dbwrap_tool_erase ( struct db_context * db ,
const char * keyname ,
2011-10-14 14:22:16 +04:00
const char * data )
2009-05-26 01:27:28 +04:00
{
2011-08-17 13:42:45 +04:00
NTSTATUS status ;
2009-05-26 01:27:28 +04:00
2011-08-17 13:42:45 +04:00
status = dbwrap_traverse ( db , delete_fn , NULL , NULL ) ;
2009-05-26 01:27:28 +04:00
2011-08-17 13:42:45 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2009-05-26 01:27:28 +04:00
d_fprintf ( stderr , " ERROR erasing the database \n " ) ;
return - 1 ;
}
return 0 ;
}
2009-05-26 02:47:15 +04:00
static int listkey_fn ( struct db_record * rec , void * private_data )
{
2011-08-17 13:42:45 +04:00
int length = dbwrap_record_get_key ( rec ) . dsize ;
unsigned char * p = ( unsigned char * ) dbwrap_record_get_key ( rec ) . dptr ;
2009-05-26 02:47:15 +04:00
while ( length - - ) {
if ( isprint ( * p ) & & ! strchr ( " \" \\ " , * p ) ) {
d_printf ( " %c " , * p ) ;
} else {
d_printf ( " \\ %02X " , * p ) ;
}
p + + ;
}
d_printf ( " \n " ) ;
return 0 ;
}
static int dbwrap_tool_listkeys ( struct db_context * db ,
const char * keyname ,
2011-10-14 14:22:16 +04:00
const char * data )
2009-05-26 02:47:15 +04:00
{
2011-08-17 13:42:45 +04:00
NTSTATUS status ;
2009-05-26 02:47:15 +04:00
2011-08-17 13:42:45 +04:00
status = dbwrap_traverse_read ( db , listkey_fn , NULL , NULL ) ;
2009-05-26 02:47:15 +04:00
2011-08-17 13:42:45 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2009-05-26 02:47:15 +04:00
d_fprintf ( stderr , " ERROR listing db keys \n " ) ;
return - 1 ;
}
return 0 ;
}
2009-05-15 03:48:55 +04:00
struct dbwrap_op_dispatch_table {
2012-01-25 00:04:00 +04:00
enum dbwrap_op op ;
2012-01-25 00:04:40 +04:00
enum dbwrap_type type ;
2009-05-15 03:48:55 +04:00
int ( * cmd ) ( struct db_context * db ,
const char * keyname ,
2011-10-14 14:22:16 +04:00
const char * data ) ;
2009-05-15 03:48:55 +04:00
} ;
struct dbwrap_op_dispatch_table dispatch_table [ ] = {
{ OP_FETCH , TYPE_INT32 , dbwrap_tool_fetch_int32 } ,
{ OP_FETCH , TYPE_UINT32 , dbwrap_tool_fetch_uint32 } ,
2011-10-17 18:08:38 +04:00
{ OP_FETCH , TYPE_STRING , dbwrap_tool_fetch_string } ,
{ OP_FETCH , TYPE_HEX , dbwrap_tool_fetch_hex } ,
2009-05-15 03:48:55 +04:00
{ OP_STORE , TYPE_INT32 , dbwrap_tool_store_int32 } ,
{ OP_STORE , TYPE_UINT32 , dbwrap_tool_store_uint32 } ,
2011-10-14 14:22:16 +04:00
{ OP_STORE , TYPE_STRING , dbwrap_tool_store_string } ,
2011-10-17 18:05:52 +04:00
{ OP_STORE , TYPE_HEX , dbwrap_tool_store_hex } ,
2009-05-15 03:48:55 +04:00
{ OP_DELETE , TYPE_INT32 , dbwrap_tool_delete } ,
2009-05-26 01:27:28 +04:00
{ OP_ERASE , TYPE_INT32 , dbwrap_tool_erase } ,
2009-05-26 02:47:15 +04:00
{ OP_LISTKEYS , TYPE_INT32 , dbwrap_tool_listkeys } ,
2009-05-15 03:48:55 +04:00
{ 0 , 0 , NULL } ,
} ;
int main ( int argc , const char * * argv )
{
struct tevent_context * evt_ctx ;
struct messaging_context * msg_ctx ;
struct db_context * db ;
uint16_t count ;
const char * dbname ;
const char * opname ;
2012-01-25 00:04:00 +04:00
enum dbwrap_op op ;
2009-05-26 01:27:28 +04:00
const char * keyname = " " ;
2009-05-15 03:48:55 +04:00
const char * keytype = " int32 " ;
2012-01-25 00:04:40 +04:00
enum dbwrap_type type ;
2009-05-15 03:48:55 +04:00
const char * valuestr = " 0 " ;
TALLOC_CTX * mem_ctx = talloc_stackframe ( ) ;
int ret = 1 ;
2011-09-20 06:32:25 +04:00
struct poptOption popt_options [ ] = {
POPT_AUTOHELP
POPT_COMMON_SAMBA
POPT_TABLEEND
} ;
int opt ;
const char * * extra_argv ;
int extra_argc = 0 ;
poptContext pc ;
2009-05-15 03:48:55 +04:00
load_case_tables ( ) ;
2010-10-29 08:06:36 +04:00
lp_set_cmdline ( " log level " , " 0 " ) ;
2010-10-29 07:19:32 +04:00
setup_logging ( argv [ 0 ] , DEBUG_STDERR ) ;
2011-09-20 06:32:25 +04:00
pc = poptGetContext ( argv [ 0 ] , argc , argv , popt_options , POPT_CONTEXT_KEEP_FIRST ) ;
while ( ( opt = poptGetNextOpt ( pc ) ) ! = - 1 ) {
switch ( opt ) {
default :
fprintf ( stderr , " Invalid option %s: %s \n " ,
poptBadOption ( pc , 0 ) , poptStrerror ( opt ) ) ;
goto done ;
}
}
/* setup the remaining options for the main program to use */
extra_argv = poptGetArgs ( pc ) ;
if ( extra_argv ) {
extra_argv + + ;
while ( extra_argv [ extra_argc ] ) extra_argc + + ;
}
2011-07-28 12:15:41 +04:00
lp_load_global ( get_dyn_CONFIGFILE ( ) ) ;
2009-05-15 03:48:55 +04:00
2011-09-20 06:32:25 +04:00
if ( ( extra_argc < 2 ) | | ( extra_argc > 5 ) ) {
2009-05-15 03:48:55 +04:00
d_fprintf ( stderr ,
2009-05-26 01:27:28 +04:00
" USAGE: %s <database> <op> [<key> [<type> [<value>]]] \n "
2009-05-26 02:47:15 +04:00
" ops: fetch, store, delete, erase, listkeys \n "
2011-10-17 18:05:52 +04:00
" types: int32, uint32, string, hex \n " ,
2009-05-15 03:48:55 +04:00
argv [ 0 ] ) ;
goto done ;
}
2011-09-20 06:32:25 +04:00
dbname = extra_argv [ 0 ] ;
opname = extra_argv [ 1 ] ;
2009-05-15 03:48:55 +04:00
if ( strcmp ( opname , " store " ) = = 0 ) {
2011-09-20 06:32:25 +04:00
if ( extra_argc ! = 5 ) {
2009-05-15 03:48:55 +04:00
d_fprintf ( stderr , " ERROR: operation 'store' requires "
" value argument \n " ) ;
goto done ;
}
2011-09-20 06:32:25 +04:00
valuestr = extra_argv [ 4 ] ;
keytype = extra_argv [ 3 ] ;
keyname = extra_argv [ 2 ] ;
2009-05-15 03:48:55 +04:00
op = OP_STORE ;
} else if ( strcmp ( opname , " fetch " ) = = 0 ) {
2011-09-20 06:32:25 +04:00
if ( extra_argc ! = 4 ) {
2009-05-15 03:48:55 +04:00
d_fprintf ( stderr , " ERROR: operation 'fetch' requires "
" type but not value argument \n " ) ;
goto done ;
}
op = OP_FETCH ;
2011-09-20 06:32:25 +04:00
keytype = extra_argv [ 3 ] ;
keyname = extra_argv [ 2 ] ;
2009-05-15 03:48:55 +04:00
} else if ( strcmp ( opname , " delete " ) = = 0 ) {
2011-09-20 06:32:25 +04:00
if ( extra_argc ! = 3 ) {
2009-05-15 03:48:55 +04:00
d_fprintf ( stderr , " ERROR: operation 'delete' does "
" not allow type nor value argument \n " ) ;
goto done ;
}
2011-09-20 06:32:25 +04:00
keyname = extra_argv [ 2 ] ;
2009-05-15 03:48:55 +04:00
op = OP_DELETE ;
2009-05-26 01:27:28 +04:00
} else if ( strcmp ( opname , " erase " ) = = 0 ) {
2011-09-20 06:32:25 +04:00
if ( extra_argc ! = 2 ) {
2009-05-26 01:27:28 +04:00
d_fprintf ( stderr , " ERROR: operation 'erase' does "
" not take a key argument \n " ) ;
goto done ;
}
op = OP_ERASE ;
2009-05-26 02:47:15 +04:00
} else if ( strcmp ( opname , " listkeys " ) = = 0 ) {
2011-09-20 06:32:25 +04:00
if ( extra_argc ! = 2 ) {
2009-05-26 02:47:15 +04:00
d_fprintf ( stderr , " ERROR: operation 'listkeys' does "
" not take a key argument \n " ) ;
goto done ;
}
op = OP_LISTKEYS ;
2009-05-15 03:48:55 +04:00
} else {
d_fprintf ( stderr ,
" ERROR: invalid op '%s' specified \n "
" supported ops: fetch, store, delete \n " ,
opname ) ;
goto done ;
}
if ( strcmp ( keytype , " int32 " ) = = 0 ) {
type = TYPE_INT32 ;
} else if ( strcmp ( keytype , " uint32 " ) = = 0 ) {
type = TYPE_UINT32 ;
2011-10-14 14:22:16 +04:00
} else if ( strcmp ( keytype , " string " ) = = 0 ) {
type = TYPE_STRING ;
2011-10-17 18:05:52 +04:00
} else if ( strcmp ( keytype , " hex " ) = = 0 ) {
type = TYPE_HEX ;
2009-05-15 03:48:55 +04:00
} else {
d_fprintf ( stderr , " ERROR: invalid type '%s' specified. \n "
2011-10-17 18:05:52 +04:00
" supported types: int32, uint32, "
" string, hex \n " ,
2009-05-15 03:48:55 +04:00
keytype ) ;
goto done ;
}
evt_ctx = tevent_context_init ( mem_ctx ) ;
if ( evt_ctx = = NULL ) {
d_fprintf ( stderr , " ERROR: could not init event context \n " ) ;
goto done ;
}
2011-12-12 17:55:54 +04:00
msg_ctx = messaging_init ( mem_ctx , evt_ctx ) ;
2009-05-15 03:48:55 +04:00
if ( msg_ctx = = NULL ) {
d_fprintf ( stderr , " ERROR: could not init messaging context \n " ) ;
goto done ;
}
2012-01-06 20:19:54 +04:00
db = db_open ( mem_ctx , dbname , 0 , TDB_DEFAULT , O_RDWR | O_CREAT , 0644 ,
DBWRAP_LOCK_ORDER_1 ) ;
2009-05-15 03:48:55 +04:00
if ( db = = NULL ) {
d_fprintf ( stderr , " ERROR: could not open dbname \n " ) ;
goto done ;
}
for ( count = 0 ; dispatch_table [ count ] . cmd ! = NULL ; count + + ) {
if ( ( op = = dispatch_table [ count ] . op ) & &
( type = = dispatch_table [ count ] . type ) )
{
2011-10-14 14:22:16 +04:00
ret = dispatch_table [ count ] . cmd ( db , keyname , valuestr ) ;
2009-05-15 03:48:55 +04:00
break ;
}
}
done :
TALLOC_FREE ( mem_ctx ) ;
return ret ;
}