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 ;
}
2024-03-13 18:19:48 +03:00
status = g_lock_lock ( ctx ,
key ,
G_LOCK_WRITE ,
tevent_timeval_set ( timeout / 1000 ,
timeout % 1000 ) ,
NULL ,
NULL ) ;
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
}
2019-10-25 14:35:39 +03:00
static void net_g_lock_dump_fn ( struct server_id exclusive ,
size_t num_shared ,
2022-08-18 18:52:33 +03:00
const struct server_id * shared ,
2019-10-25 14:35:39 +03:00
const uint8_t * data ,
size_t datalen ,
void * private_data )
2009-10-25 18:12:12 +03:00
{
2019-10-25 14:35:39 +03:00
struct server_id_buf idbuf ;
if ( exclusive . pid ! = 0 ) {
d_printf ( " %s: WRITE \n " ,
server_id_str_buf ( exclusive , & idbuf ) ) ;
} else {
size_t i ;
for ( i = 0 ; i < num_shared ; i + + ) {
d_printf ( " %s: READ \n " ,
server_id_str_buf ( shared [ i ] , & idbuf ) ) ;
}
2017-05-18 16:27:46 +03:00
}
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 ;
}
2020-04-28 13:18:40 +03:00
static int net_g_lock_dumpall_fn ( TDB_DATA key , void * private_data )
{
struct g_lock_ctx * g_ctx = talloc_get_type_abort (
private_data , struct g_lock_ctx ) ;
dump_data_file ( key . dptr , key . dsize , true , stdout ) ;
g_lock_dump ( g_ctx , key , net_g_lock_dump_fn , NULL ) ;
printf ( " \n " ) ;
return 0 ;
}
static int net_g_lock_dumpall (
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 ;
}
2024-10-12 17:36:21 +03:00
ret = g_lock_locks_read ( g_ctx , net_g_lock_dumpall_fn , g_ctx ) ;
2020-04-28 13:18:40 +03:00
done :
TALLOC_FREE ( g_ctx ) ;
TALLOC_FREE ( msg ) ;
TALLOC_FREE ( ev ) ;
return ret < 0 ? - 1 : 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
{
2020-04-28 13:08:14 +03:00
dump_data_file ( key . dptr , key . dsize , true , stdout ) ;
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 ;
}
2024-10-12 17:36:21 +03:00
ret = g_lock_locks_read ( g_ctx , net_g_lock_locks_fn , NULL ) ;
2009-10-25 18:12:12 +03:00
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 " )
} ,
2020-04-28 13:18:40 +03:00
{
" dumpall " ,
net_g_lock_dumpall ,
NET_TRANSPORT_LOCAL ,
N_ ( " Dump all g_lock locking tables " ) ,
N_ ( " net g_lock dumpall \n " )
} ,
2009-10-25 18:12:12 +03:00
{ NULL , NULL , 0 , NULL , NULL }
} ;
return net_run_function ( c , argc , argv , " net g_lock " , func ) ;
}