2002-08-18 18:04:00 +00:00
/*
Unix SMB / CIFS implementation .
VFS module tester
Copyright ( C ) Simo Sorce 2002
Copyright ( C ) Eric Lorimer 2002
2003-04-14 21:16:16 +00:00
Copyright ( C ) Jelmer Vernooij 2002 , 2003
2002-08-18 18:04:00 +00:00
Most of this code was ripped off of rpcclient .
Copyright ( C ) Tim Potter 2000 - 2001
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-09 19:25:36 +00:00
the Free Software Foundation ; either version 3 of the License , or
2002-08-18 18:04:00 +00: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 00:52:41 +00:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
2002-08-18 18:04:00 +00:00
*/
# include "includes.h"
2011-03-22 22:34:22 +01:00
# include "smbd/smbd.h"
2010-08-05 10:49:53 +02:00
# include "popt_common.h"
2002-08-18 18:04:00 +00:00
# include "vfstest.h"
2010-10-01 10:34:14 +02:00
# include "../libcli/smbreadline/smbreadline.h"
2002-08-18 18:04:00 +00:00
/* List to hold groups of commands */
static struct cmd_list {
struct cmd_list * prev , * next ;
struct cmd_set * cmd_set ;
} * cmd_list ;
/****************************************************************************
handle completion of commands for readline
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-09-30 17:13:37 +00:00
static char * * completion_fn ( const char * text , int start , int end )
2002-08-18 18:04:00 +00:00
{
# define MAX_COMPLETIONS 100
char * * matches ;
int i , count = 0 ;
struct cmd_list * commands = cmd_list ;
if ( start )
return NULL ;
/* make sure we have a list of valid commands */
if ( ! commands )
return NULL ;
2005-05-07 06:59:00 +00:00
matches = SMB_MALLOC_ARRAY ( char * , MAX_COMPLETIONS ) ;
2002-08-18 18:04:00 +00:00
if ( ! matches ) return NULL ;
2005-05-07 06:59:00 +00:00
matches [ count + + ] = SMB_STRDUP ( text ) ;
2002-08-18 18:04:00 +00:00
if ( ! matches [ 0 ] ) return NULL ;
while ( commands & & count < MAX_COMPLETIONS - 1 )
{
if ( ! commands - > cmd_set )
break ;
for ( i = 0 ; commands - > cmd_set [ i ] . name ; i + + )
{
if ( ( strncmp ( text , commands - > cmd_set [ i ] . name , strlen ( text ) ) = = 0 ) & &
commands - > cmd_set [ i ] . fn )
{
2005-05-07 06:59:00 +00:00
matches [ count ] = SMB_STRDUP ( commands - > cmd_set [ i ] . name ) ;
2002-08-18 18:04:00 +00:00
if ( ! matches [ count ] )
return NULL ;
count + + ;
}
}
commands = commands - > next ;
}
if ( count = = 2 ) {
SAFE_FREE ( matches [ 0 ] ) ;
2005-05-07 06:59:00 +00:00
matches [ 0 ] = SMB_STRDUP ( matches [ 1 ] ) ;
2002-08-18 18:04:00 +00:00
}
matches [ count ] = NULL ;
return matches ;
}
2007-12-04 16:56:18 -08:00
static char * next_command ( TALLOC_CTX * ctx , char * * cmdstr )
2002-08-18 18:04:00 +00:00
{
2007-12-04 16:56:18 -08:00
char * command ;
char * p ;
2002-08-18 18:04:00 +00:00
if ( ! cmdstr | | ! ( * cmdstr ) )
return NULL ;
2007-12-04 16:56:18 -08:00
2002-08-18 18:04:00 +00:00
p = strchr_m ( * cmdstr , ' ; ' ) ;
if ( p )
* p = ' \0 ' ;
2007-12-04 16:56:18 -08:00
command = talloc_strdup ( ctx , * cmdstr ) ;
2002-08-18 18:04:00 +00:00
* cmdstr = p ;
2007-12-04 16:56:18 -08:00
2002-08-18 18:04:00 +00:00
return command ;
}
2002-08-19 00:19:44 +00:00
/* Load specified configuration file */
static NTSTATUS cmd_conf ( struct vfs_state * vfs , TALLOC_CTX * mem_ctx ,
2003-05-11 23:34:18 +00:00
int argc , const char * * argv )
2002-08-19 00:19:44 +00:00
{
if ( argc ! = 2 ) {
printf ( " Usage: %s <smb.conf> \n " , argv [ 0 ] ) ;
return NT_STATUS_OK ;
}
2002-08-18 18:04:00 +00:00
2006-01-28 22:53:04 +00:00
if ( ! lp_load ( argv [ 1 ] , False , True , False , True ) ) {
2002-08-19 00:19:44 +00:00
printf ( " Error loading \" %s \" \n " , argv [ 1 ] ) ;
return NT_STATUS_OK ;
}
printf ( " \" %s \" successfully loaded \n " , argv [ 1 ] ) ;
return NT_STATUS_OK ;
}
2002-08-18 18:04:00 +00:00
/* Display help on commands */
static NTSTATUS cmd_help ( struct vfs_state * vfs , TALLOC_CTX * mem_ctx ,
2003-02-25 23:52:38 +00:00
int argc , const char * * argv )
2002-08-18 18:04:00 +00:00
{
struct cmd_list * tmp ;
struct cmd_set * tmp_set ;
/* Usage */
if ( argc > 2 ) {
printf ( " Usage: %s [command] \n " , argv [ 0 ] ) ;
return NT_STATUS_OK ;
}
/* Help on one command */
if ( argc = = 2 ) {
for ( tmp = cmd_list ; tmp ; tmp = tmp - > next ) {
tmp_set = tmp - > cmd_set ;
while ( tmp_set - > name ) {
if ( strequal ( argv [ 1 ] , tmp_set - > name ) ) {
if ( tmp_set - > usage & &
tmp_set - > usage [ 0 ] )
printf ( " %s \n " , tmp_set - > usage ) ;
else
printf ( " No help for %s \n " , tmp_set - > name ) ;
return NT_STATUS_OK ;
}
tmp_set + + ;
}
}
printf ( " No such command: %s \n " , argv [ 1 ] ) ;
return NT_STATUS_OK ;
}
/* List all commands */
for ( tmp = cmd_list ; tmp ; tmp = tmp - > next ) {
tmp_set = tmp - > cmd_set ;
while ( tmp_set - > name ) {
printf ( " %15s \t \t %s \n " , tmp_set - > name ,
tmp_set - > description ? tmp_set - > description :
" " ) ;
tmp_set + + ;
}
}
return NT_STATUS_OK ;
}
/* Change the debug level */
2003-05-11 23:34:18 +00:00
static NTSTATUS cmd_debuglevel ( struct vfs_state * vfs , TALLOC_CTX * mem_ctx , int argc , const char * * argv )
2002-08-18 18:04:00 +00:00
{
if ( argc > 2 ) {
printf ( " Usage: %s [debuglevel] \n " , argv [ 0 ] ) ;
return NT_STATUS_OK ;
}
if ( argc = = 2 ) {
2010-10-29 15:29:09 +11:00
lp_set_cmdline ( " log level " , argv [ 1 ] ) ;
2002-08-18 18:04:00 +00:00
}
printf ( " debuglevel is %d \n " , DEBUGLEVEL ) ;
return NT_STATUS_OK ;
}
2003-05-11 23:34:18 +00:00
static NTSTATUS cmd_freemem ( struct vfs_state * vfs , TALLOC_CTX * mem_ctx , int argc , const char * * argv )
2002-08-18 18:04:00 +00:00
{
/* Cleanup */
2002-08-29 11:17:14 +00:00
talloc_destroy ( mem_ctx ) ;
mem_ctx = NULL ;
2002-08-18 18:04:00 +00:00
vfs - > data = NULL ;
2002-08-20 17:58:09 +00:00
vfs - > data_size = 0 ;
return NT_STATUS_OK ;
2002-08-18 18:04:00 +00:00
}
2003-05-11 23:34:18 +00:00
static NTSTATUS cmd_quit ( struct vfs_state * vfs , TALLOC_CTX * mem_ctx , int argc , const char * * argv )
2002-08-18 18:04:00 +00:00
{
/* Cleanup */
2002-08-29 11:17:14 +00:00
talloc_destroy ( mem_ctx ) ;
2002-08-18 18:04:00 +00:00
exit ( 0 ) ;
return NT_STATUS_OK ; /* NOTREACHED */
}
static struct cmd_set vfstest_commands [ ] = {
{ " GENERAL OPTIONS " } ,
2002-08-19 00:19:44 +00:00
{ " conf " , cmd_conf , " Load smb configuration file " , " conf <smb.conf> " } ,
{ " help " , cmd_help , " Get help on commands " , " " } ,
{ " ? " , cmd_help , " Get help on commands " , " " } ,
{ " debuglevel " , cmd_debuglevel , " Set debug level " , " " } ,
{ " freemem " , cmd_freemem , " Free currently allocated buffers " , " " } ,
2002-08-18 18:04:00 +00:00
{ " exit " , cmd_quit , " Exit program " , " " } ,
{ " quit " , cmd_quit , " Exit program " , " " } ,
{ NULL }
} ;
static struct cmd_set separator_command [ ] = {
{ " --------------- " , NULL , " ---------------------- " } ,
{ NULL }
} ;
extern struct cmd_set vfs_commands [ ] ;
static struct cmd_set * vfstest_command_list [ ] = {
vfstest_commands ,
vfs_commands ,
NULL
} ;
static void add_command_set ( struct cmd_set * cmd_set )
{
struct cmd_list * entry ;
2005-05-07 06:59:00 +00:00
if ( ! ( entry = SMB_MALLOC_P ( struct cmd_list ) ) ) {
2002-08-18 18:04:00 +00:00
DEBUG ( 0 , ( " out of memory \n " ) ) ;
return ;
}
ZERO_STRUCTP ( entry ) ;
entry - > cmd_set = cmd_set ;
DLIST_ADD ( cmd_list , entry ) ;
}
static NTSTATUS do_cmd ( struct vfs_state * vfs , struct cmd_set * cmd_entry , char * cmd )
{
2003-06-04 12:51:21 +00:00
const char * p = cmd ;
char * * argv = NULL ;
2002-08-18 18:04:00 +00:00
NTSTATUS result = NT_STATUS_UNSUCCESSFUL ;
2007-12-04 16:56:18 -08:00
char * buf ;
TALLOC_CTX * mem_ctx = talloc_stackframe ( ) ;
2002-08-18 18:04:00 +00:00
int argc = 0 , i ;
/* Count number of arguments first time through the loop then
allocate memory and strdup them . */
again :
2007-12-04 16:56:18 -08:00
while ( next_token_talloc ( mem_ctx , & p , & buf , " " ) ) {
2002-08-18 18:04:00 +00:00
if ( argv ) {
2005-05-07 06:59:00 +00:00
argv [ argc ] = SMB_STRDUP ( buf ) ;
2002-08-18 18:04:00 +00:00
}
argc + + ;
}
2007-12-04 16:56:18 -08:00
if ( ! argv ) {
2002-08-18 18:04:00 +00:00
/* Create argument list */
2005-05-07 06:59:00 +00:00
argv = SMB_MALLOC_ARRAY ( char * , argc ) ;
2002-08-18 18:04:00 +00:00
memset ( argv , 0 , sizeof ( char * ) * argc ) ;
if ( ! argv ) {
fprintf ( stderr , " out of memory \n " ) ;
result = NT_STATUS_NO_MEMORY ;
goto done ;
}
2007-12-04 16:56:18 -08:00
2002-08-18 18:04:00 +00:00
p = cmd ;
argc = 0 ;
2007-12-04 16:56:18 -08:00
2002-08-18 18:04:00 +00:00
goto again ;
}
/* Call the function */
if ( cmd_entry - > fn ) {
/* Run command */
2003-05-11 23:34:18 +00:00
result = cmd_entry - > fn ( vfs , mem_ctx , argc , ( const char * * ) argv ) ;
2002-08-18 18:04:00 +00:00
} else {
fprintf ( stderr , " Invalid command \n " ) ;
goto done ;
}
done :
2007-12-04 16:56:18 -08:00
2002-08-18 18:04:00 +00:00
/* Cleanup */
if ( argv ) {
for ( i = 0 ; i < argc ; i + + )
SAFE_FREE ( argv [ i ] ) ;
2007-12-04 16:56:18 -08:00
2002-08-18 18:04:00 +00:00
SAFE_FREE ( argv ) ;
}
2007-12-04 16:56:18 -08:00
TALLOC_FREE ( mem_ctx ) ;
2002-08-18 18:04:00 +00:00
return result ;
}
/* Process a command entered at the prompt or as part of -c */
static NTSTATUS process_cmd ( struct vfs_state * vfs , char * cmd )
{
struct cmd_list * temp_list ;
2007-10-18 17:40:25 -07:00
bool found = False ;
2007-12-04 16:56:18 -08:00
char * buf ;
2003-06-04 12:51:21 +00:00
const char * p = cmd ;
2002-08-18 18:04:00 +00:00
NTSTATUS result = NT_STATUS_OK ;
2007-12-04 16:56:18 -08:00
TALLOC_CTX * mem_ctx = talloc_stackframe ( ) ;
2002-08-18 18:04:00 +00:00
int len = 0 ;
if ( cmd [ strlen ( cmd ) - 1 ] = = ' \n ' )
cmd [ strlen ( cmd ) - 1 ] = ' \0 ' ;
2007-12-04 16:56:18 -08:00
if ( ! next_token_talloc ( mem_ctx , & p , & buf , " " ) ) {
TALLOC_FREE ( mem_ctx ) ;
2002-08-18 18:04:00 +00:00
return NT_STATUS_OK ;
}
2007-12-04 16:56:18 -08:00
/* Strip the trailing \n if it exists */
2002-08-18 18:04:00 +00:00
len = strlen ( buf ) ;
if ( buf [ len - 1 ] = = ' \n ' )
buf [ len - 1 ] = ' \0 ' ;
/* Search for matching commands */
for ( temp_list = cmd_list ; temp_list ; temp_list = temp_list - > next ) {
struct cmd_set * temp_set = temp_list - > cmd_set ;
while ( temp_set - > name ) {
if ( strequal ( buf , temp_set - > name ) ) {
found = True ;
result = do_cmd ( vfs , temp_set , cmd ) ;
goto done ;
}
temp_set + + ;
}
}
done :
if ( ! found & & buf [ 0 ] ) {
printf ( " command not found: %s \n " , buf ) ;
2007-12-04 16:56:18 -08:00
TALLOC_FREE ( mem_ctx ) ;
2002-08-18 18:04:00 +00:00
return NT_STATUS_OK ;
}
if ( ! NT_STATUS_IS_OK ( result ) ) {
printf ( " result was %s \n " , nt_errstr ( result ) ) ;
}
2007-12-04 16:56:18 -08:00
TALLOC_FREE ( mem_ctx ) ;
2002-08-18 18:04:00 +00:00
return result ;
}
2002-08-21 02:34:49 +00:00
static void process_file ( struct vfs_state * pvfs , char * filename ) {
FILE * file ;
char command [ 3 * PATH_MAX ] ;
if ( * filename = = ' - ' ) {
file = stdin ;
} else {
file = fopen ( filename , " r " ) ;
if ( file = = NULL ) {
printf ( " vfstest: error reading file (%s)! " , filename ) ;
printf ( " errno n.%d: %s " , errno , strerror ( errno ) ) ;
exit ( - 1 ) ;
}
}
while ( fgets ( command , 3 * PATH_MAX , file ) ! = NULL ) {
process_cmd ( pvfs , command ) ;
}
2009-05-25 23:59:05 +07:00
if ( file ! = stdin ) {
fclose ( file ) ;
}
2002-08-21 02:34:49 +00:00
}
2003-01-03 08:28:12 +00:00
void exit_server ( const char * reason )
2002-08-18 18:04:00 +00:00
{
DEBUG ( 3 , ( " Server exit (%s) \n " , ( reason ? reason : " " ) ) ) ;
exit ( 0 ) ;
}
2006-04-11 06:35:36 +00:00
void exit_server_cleanly ( const char * const reason )
2006-04-04 00:27:50 +00:00
{
exit_server ( " normal exit " ) ;
}
2002-08-18 18:04:00 +00:00
int last_message = - 1 ;
/* Main function */
int main ( int argc , char * argv [ ] )
{
2003-04-14 21:16:16 +00:00
static char * cmdstr = NULL ;
2002-08-18 18:04:00 +00:00
struct cmd_set * * cmd_set ;
static struct vfs_state vfs ;
int i ;
2003-05-11 23:34:18 +00:00
static char * filename = NULL ;
2007-12-04 16:56:18 -08:00
TALLOC_CTX * frame = talloc_stackframe ( ) ;
2002-08-18 18:04:00 +00:00
/* make sure the vars that get altered (4th field) are in
a fixed location or certain compilers complain */
poptContext pc ;
struct poptOption long_options [ ] = {
2002-08-29 12:05:30 +00:00
POPT_AUTOHELP
{ " file " , ' f ' , POPT_ARG_STRING , & filename , 0 , } ,
{ " command " , ' c ' , POPT_ARG_STRING , & cmdstr , 0 , " Execute specified list of commands " } ,
2003-04-14 21:16:16 +00:00
POPT_COMMON_SAMBA
POPT_TABLEEND
2002-08-18 18:04:00 +00:00
} ;
2006-01-23 00:19:45 +00:00
load_case_tables ( ) ;
2002-08-18 18:04:00 +00:00
setlinebuf ( stdout ) ;
pc = poptGetContext ( " vfstest " , argc , ( const char * * ) argv ,
long_options , 0 ) ;
2003-04-14 21:16:16 +00:00
while ( poptGetNextOpt ( pc ) ! = - 1 ) ;
2002-08-18 18:04:00 +00:00
poptFreeContext ( pc ) ;
2010-12-09 22:41:58 +11:00
lp_load_initial_only ( get_dyn_CONFIGFILE ( ) ) ;
2002-08-21 02:34:49 +00:00
/* TODO: check output */
2011-12-13 14:16:21 +01:00
reload_services ( NULL , - 1 , False ) ;
2002-08-21 02:34:49 +00:00
2002-08-18 18:04:00 +00:00
/* the following functions are part of the Samba debugging
facilities . See lib / debug . c */
2010-10-29 14:19:32 +11:00
setup_logging ( " vfstest " , DEBUG_STDOUT ) ;
2002-08-18 18:04:00 +00:00
/* Load command lists */
cmd_set = vfstest_command_list ;
while ( * cmd_set ) {
add_command_set ( * cmd_set ) ;
add_command_set ( separator_command ) ;
cmd_set + + ;
}
/* some basic initialization stuff */
2003-05-11 23:34:18 +00:00
sec_init ( ) ;
2011-06-07 11:44:43 +10:00
vfs . conn = talloc_zero ( NULL , connection_struct ) ;
2011-06-07 11:38:41 +10:00
vfs . conn - > params = talloc ( vfs . conn , struct share_params ) ;
2002-08-18 18:04:00 +00:00
for ( i = 0 ; i < 1024 ; i + + )
vfs . files [ i ] = NULL ;
2002-08-21 02:34:49 +00:00
/* some advanced initiliazation stuff */
smbd_vfs_init ( vfs . conn ) ;
/* Do we have a file input? */
2003-04-14 21:16:16 +00:00
if ( filename & & filename [ 0 ] ) {
2002-08-21 02:34:49 +00:00
process_file ( & vfs , filename ) ;
return 0 ;
}
/* Do anything specified with -c */
2003-04-14 21:16:16 +00:00
if ( cmdstr & & cmdstr [ 0 ] ) {
2002-08-18 18:04:00 +00:00
char * cmd ;
char * p = cmdstr ;
2007-12-04 16:56:18 -08:00
while ( ( cmd = next_command ( frame , & p ) ) ! = NULL ) {
2002-08-18 18:04:00 +00:00
process_cmd ( & vfs , cmd ) ;
}
2007-12-04 16:56:18 -08:00
TALLOC_FREE ( cmd ) ;
2002-08-18 18:04:00 +00:00
return 0 ;
}
/* Loop around accepting commands */
while ( 1 ) {
2007-12-06 17:16:33 -08:00
char * line = NULL ;
2002-08-18 18:04:00 +00:00
2007-12-04 16:56:18 -08:00
line = smb_readline ( " vfstest $> " , NULL , completion_fn ) ;
2002-08-18 18:04:00 +00:00
2007-12-06 17:16:33 -08:00
if ( line = = NULL ) {
2002-08-18 18:04:00 +00:00
break ;
2007-12-06 17:16:33 -08:00
}
2002-08-18 18:04:00 +00:00
2007-12-06 17:16:33 -08:00
if ( line [ 0 ] ! = ' \n ' ) {
2002-08-18 18:04:00 +00:00
process_cmd ( & vfs , line ) ;
2007-12-06 17:16:33 -08:00
}
SAFE_FREE ( line ) ;
2002-08-18 18:04:00 +00:00
}
2007-12-04 16:56:18 -08:00
2009-05-27 11:15:44 +02:00
TALLOC_FREE ( vfs . conn ) ;
2007-12-04 16:56:18 -08:00
TALLOC_FREE ( frame ) ;
2002-08-18 18:04:00 +00:00
return 0 ;
}