2009-10-25 18:12:12 +03:00
/*
* Samba Unix / Linux SMB client library
* Interface to the g_lock facility
* Copyright ( C ) Volker Lendecke 2009
*
* 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"
# include "net.h"
2017-01-01 23:00:55 +03:00
# include "lib/util/server_id.h"
2009-10-25 18:12:12 +03:00
# include "g_lock.h"
2011-03-24 17:31:06 +03:00
# include "messages.h"
2017-12-03 22:47:02 +03:00
# include "lib/util/util_tdb.h"
2009-10-25 18:12:12 +03:00
static bool net_g_lock_init ( TALLOC_CTX * mem_ctx ,
struct tevent_context * * pev ,
struct messaging_context * * pmsg ,
struct g_lock_ctx * * pg_ctx )
{
struct tevent_context * ev = NULL ;
struct messaging_context * msg = NULL ;
struct g_lock_ctx * g_ctx = NULL ;
2013-02-18 12:11:52 +04:00
ev = samba_tevent_context_init ( mem_ctx ) ;
2009-10-25 18:12:12 +03:00
if ( ev = = NULL ) {
d_fprintf ( stderr , " ERROR: could not init event context \n " ) ;
goto fail ;
}
2011-12-12 17:55:54 +04:00
msg = messaging_init ( mem_ctx , ev ) ;
2009-10-25 18:12:12 +03:00
if ( msg = = NULL ) {
d_fprintf ( stderr , " ERROR: could not init messaging context \n " ) ;
goto fail ;
}
2010-03-12 14:12:25 +03:00
g_ctx = g_lock_ctx_init ( mem_ctx , msg ) ;
2009-10-25 18:12:12 +03:00
if ( g_ctx = = NULL ) {
d_fprintf ( stderr , " ERROR: could not init g_lock context \n " ) ;
goto fail ;
}
* pev = ev ;
* pmsg = msg ;
* pg_ctx = g_ctx ;
return true ;
fail :
TALLOC_FREE ( g_ctx ) ;
TALLOC_FREE ( msg ) ;
TALLOC_FREE ( ev ) ;
return false ;
}
static int net_g_lock_do ( struct net_context * c , int argc , const char * * argv )
{
2019-10-10 14:38:17 +03:00
struct g_lock_ctx * ctx = NULL ;
TDB_DATA key = { 0 } ;
const char * cmd = NULL ;
2010-03-12 16:22:54 +03:00
int timeout ;
2009-10-25 18:12:12 +03:00
NTSTATUS status ;
2019-10-10 14:38:17 +03:00
int result = - 1 ;
2009-10-25 18:12:12 +03:00
if ( argc ! = 3 ) {
d_printf ( " Usage: net g_lock do <lockname> <timeout> "
" <command> \n " ) ;
return - 1 ;
}
2019-10-10 14:38:17 +03:00
key = string_term_tdb_data ( argv [ 0 ] ) ;
2009-10-25 18:12:12 +03:00
timeout = atoi ( argv [ 1 ] ) ;
cmd = argv [ 2 ] ;
2019-10-10 14:38:17 +03:00
ctx = g_lock_ctx_init ( c , c - > msg_ctx ) ;
if ( ctx = = NULL ) {
d_fprintf ( stderr , _ ( " g_lock_ctx_init failed \n " ) ) ;
return - 1 ;
}
status = g_lock_lock (
ctx ,
key ,
G_LOCK_WRITE ,
timeval_set ( timeout / 1000 , timeout % 1000 ) ) ;
2009-10-25 18:12:12 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2019-10-10 14:38:17 +03:00
d_fprintf ( stderr ,
_ ( " g_lock_lock failed: %s \n " ) ,
2009-10-25 18:12:12 +03:00
nt_errstr ( status ) ) ;
goto done ;
}
2019-10-10 14:38:17 +03:00
result = system ( cmd ) ;
g_lock_unlock ( ctx , key ) ;
if ( result = = - 1 ) {
2009-10-25 18:12:12 +03:00
d_fprintf ( stderr , " ERROR: system() returned %s \n " ,
strerror ( errno ) ) ;
goto done ;
}
2019-10-10 14:38:17 +03:00
d_fprintf ( stderr , " command returned %d \n " , result ) ;
2009-10-25 18:12:12 +03:00
done :
2019-10-10 14:38:17 +03:00
TALLOC_FREE ( ctx ) ;
return result ;
2009-10-25 18:12:12 +03:00
}
2017-05-18 16:27:46 +03:00
static void net_g_lock_dump_fn ( const struct g_lock_rec * locks ,
size_t num_locks ,
const uint8_t * data ,
size_t datalen ,
void * private_data )
2009-10-25 18:12:12 +03:00
{
2017-05-18 16:27:46 +03:00
size_t i ;
for ( i = 0 ; i < num_locks ; i + + ) {
const struct g_lock_rec * l = & locks [ i ] ;
struct server_id_buf idbuf ;
d_printf ( " %s: %s \n " , server_id_str_buf ( l - > pid , & idbuf ) ,
( l - > lock_type & 1 ) ? " WRITE " : " READ " ) ;
}
2017-06-08 13:51:19 +03:00
dump_data_file ( data , datalen , true , stdout ) ;
2009-10-25 18:12:12 +03:00
}
static int net_g_lock_dump ( struct net_context * c , int argc , const char * * argv )
{
struct tevent_context * ev = NULL ;
struct messaging_context * msg = NULL ;
struct g_lock_ctx * g_ctx = NULL ;
int ret = - 1 ;
if ( argc ! = 1 ) {
d_printf ( " Usage: net g_lock dump <lockname> \n " ) ;
return - 1 ;
}
if ( ! net_g_lock_init ( talloc_tos ( ) , & ev , & msg , & g_ctx ) ) {
goto done ;
}
2017-12-03 22:47:02 +03:00
( void ) g_lock_dump ( g_ctx , string_term_tdb_data ( argv [ 0 ] ) ,
net_g_lock_dump_fn , NULL ) ;
2009-10-25 18:12:12 +03:00
ret = 0 ;
done :
TALLOC_FREE ( g_ctx ) ;
TALLOC_FREE ( msg ) ;
TALLOC_FREE ( ev ) ;
return ret ;
}
2017-12-03 22:47:02 +03:00
static int net_g_lock_locks_fn ( TDB_DATA key , void * private_data )
2009-10-25 18:12:12 +03:00
{
2017-12-03 22:47:02 +03:00
if ( ( key . dsize = = 0 ) | | ( key . dptr [ key . dsize - 1 ] ! = 0 ) ) {
DEBUG ( 1 , ( " invalid key in g_lock.tdb, ignoring \n " ) ) ;
return 0 ;
}
d_printf ( " %s \n " , ( const char * ) key . dptr ) ;
2009-10-25 18:12:12 +03:00
return 0 ;
}
static int net_g_lock_locks ( struct net_context * c , int argc , const char * * argv )
{
struct tevent_context * ev = NULL ;
struct messaging_context * msg = NULL ;
struct g_lock_ctx * g_ctx = NULL ;
int ret = - 1 ;
if ( argc ! = 0 ) {
d_printf ( " Usage: net g_lock locks \n " ) ;
return - 1 ;
}
if ( ! net_g_lock_init ( talloc_tos ( ) , & ev , & msg , & g_ctx ) ) {
goto done ;
}
ret = g_lock_locks ( g_ctx , net_g_lock_locks_fn , NULL ) ;
done :
TALLOC_FREE ( g_ctx ) ;
TALLOC_FREE ( msg ) ;
TALLOC_FREE ( ev ) ;
2011-06-20 13:10:31 +04:00
return ret < 0 ? - 1 : ret ;
2009-10-25 18:12:12 +03:00
}
int net_g_lock ( struct net_context * c , int argc , const char * * argv )
{
struct functable func [ ] = {
{
" do " ,
net_g_lock_do ,
NET_TRANSPORT_LOCAL ,
N_ ( " Execute a shell command under a lock " ) ,
N_ ( " net g_lock do <lock name> <timeout> <command> \n " )
} ,
{
" locks " ,
net_g_lock_locks ,
NET_TRANSPORT_LOCAL ,
N_ ( " List all locknames " ) ,
N_ ( " net g_lock locks \n " )
} ,
{
" dump " ,
net_g_lock_dump ,
NET_TRANSPORT_LOCAL ,
N_ ( " Dump a g_lock locking table " ) ,
N_ ( " net g_lock dump <lock name> \n " )
} ,
{ NULL , NULL , 0 , NULL , NULL }
} ;
return net_run_function ( c , argc , argv , " net g_lock " , func ) ;
}