1999-12-21 06:05:38 +03:00
# define NBDEBUG 0
/*
2002-01-30 09:08:46 +03:00
Unix SMB / CIFS implementation .
1999-12-21 06:05:38 +03:00
SMB torture tester
Copyright ( C ) Andrew Tridgell 1997 - 1998
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 23:25:36 +04:00
the Free Software Foundation ; either version 3 of the License , or
1999-12-21 06:05:38 +03: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 04:52:41 +04:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
1999-12-21 06:05:38 +03:00
*/
# include "includes.h"
2009-11-24 13:43:56 +03:00
# include "torture/proto.h"
2010-10-12 08:27:50 +04:00
# include "../libcli/security/security.h"
2011-05-06 13:47:43 +04:00
# include "libsmb/libsmb.h"
2011-02-24 12:46:55 +03:00
# include "libsmb/clirap.h"
1999-12-21 06:05:38 +03:00
# define MAX_FILES 1000
static char buf [ 70000 ] ;
extern int line_count ;
2002-02-05 04:31:47 +03:00
extern int nbio_id ;
static int nprocs ;
2009-11-24 12:41:40 +03:00
static struct timeval nb_start ;
1999-12-21 06:05:38 +03:00
static struct {
int fd ;
int handle ;
} ftable [ MAX_FILES ] ;
2006-08-01 16:45:12 +04:00
static struct children {
2002-02-05 04:31:47 +03:00
double bytes_in , bytes_out ;
int line ;
2002-02-05 06:55:20 +03:00
int done ;
2002-02-05 04:31:47 +03:00
} * children ;
double nbio_total ( void )
{
int i ;
double total = 0 ;
for ( i = 0 ; i < nprocs ; i + + ) {
total + = children [ i ] . bytes_out + children [ i ] . bytes_in ;
}
return total ;
}
2003-12-02 14:36:02 +03:00
void nb_alarm ( int ignore )
2002-02-05 04:31:47 +03:00
{
int i ;
2002-02-05 06:55:20 +03:00
int lines = 0 , num_clients = 0 ;
2002-02-05 04:31:47 +03:00
if ( nbio_id ! = - 1 ) return ;
for ( i = 0 ; i < nprocs ; i + + ) {
lines + = children [ i ] . line ;
2002-02-05 06:55:20 +03:00
if ( ! children [ i ] . done ) num_clients + + ;
2002-02-05 04:31:47 +03:00
}
2009-11-24 12:41:40 +03:00
printf ( " %4d %8d %.2f MB/sec \r " ,
num_clients , lines / nprocs ,
1.0e-6 * nbio_total ( ) / timeval_elapsed ( & nb_start ) ) ;
2002-02-05 04:31:47 +03:00
signal ( SIGALRM , nb_alarm ) ;
alarm ( 1 ) ;
}
void nbio_shmem ( int n )
{
nprocs = n ;
2012-07-25 10:33:31 +04:00
children = ( struct children * ) anonymous_shared_allocate ( sizeof ( * children ) * nprocs ) ;
2002-02-05 04:31:47 +03:00
if ( ! children ) {
printf ( " Failed to setup shared memory! \n " ) ;
exit ( 1 ) ;
}
}
2003-12-02 14:36:02 +03:00
#if 0
2002-07-15 14:35:28 +04:00
static int ne_find_handle ( int handle )
{
int i ;
children [ nbio_id ] . line = line_count ;
for ( i = 0 ; i < MAX_FILES ; i + + ) {
if ( ftable [ i ] . handle = = handle ) return i ;
}
return - 1 ;
}
2003-12-02 14:36:02 +03:00
# endif
2002-07-15 14:35:28 +04:00
2002-02-05 04:31:47 +03:00
static int find_handle ( int handle )
{
int i ;
children [ nbio_id ] . line = line_count ;
for ( i = 0 ; i < MAX_FILES ; i + + ) {
if ( ftable [ i ] . handle = = handle ) return i ;
}
2002-03-05 22:51:05 +03:00
printf ( " (%d) ERROR: handle %d was not found \n " ,
2002-02-05 04:31:47 +03:00
line_count , handle ) ;
exit ( 1 ) ;
2002-04-05 02:56:39 +04:00
return - 1 ; /* Not reached */
2002-02-05 04:31:47 +03:00
}
1999-12-21 06:05:38 +03:00
static struct cli_state * c ;
static void sigsegv ( int sig )
{
char line [ 200 ] ;
printf ( " segv at line %d \n " , line_count ) ;
slprintf ( line , sizeof ( line ) , " /usr/X11R6/bin/xterm -e gdb /proc/%d/exe %d " ,
2000-01-14 11:33:20 +03:00
( int ) getpid ( ) , ( int ) getpid ( ) ) ;
2009-01-02 22:38:24 +03:00
if ( system ( line ) = = - 1 ) {
printf ( " system() failed \n " ) ;
}
1999-12-21 06:05:38 +03:00
exit ( 1 ) ;
}
void nb_setup ( struct cli_state * cli )
{
signal ( SIGSEGV , sigsegv ) ;
c = cli ;
2009-11-24 12:41:40 +03:00
nb_start = timeval_current ( ) ;
2002-02-05 06:55:20 +03:00
children [ nbio_id ] . done = 0 ;
1999-12-21 06:05:38 +03:00
}
2003-04-23 12:12:34 +04:00
void nb_unlink ( const char * fname )
1999-12-21 06:05:38 +03:00
{
2011-02-07 13:27:02 +03:00
NTSTATUS status ;
status = cli_unlink ( c , fname , FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
1999-12-21 06:05:38 +03:00
# if NBDEBUG
printf ( " (%d) unlink %s failed (%s) \n " ,
2011-02-07 13:27:02 +03:00
line_count , fname , nt_errstr ( status ) ) ;
1999-12-21 06:05:38 +03:00
# endif
}
}
2002-02-05 04:31:47 +03:00
2003-04-23 12:12:34 +04:00
void nb_createx ( const char * fname ,
2002-02-05 04:31:47 +03:00
unsigned create_options , unsigned create_disposition , int handle )
1999-12-21 06:05:38 +03:00
{
2009-05-01 02:26:43 +04:00
uint16_t fd = ( uint16_t ) - 1 ;
int i ;
NTSTATUS status ;
2015-05-09 06:10:12 +03:00
uint32_t desired_access ;
2002-03-05 22:51:05 +03:00
if ( create_options & FILE_DIRECTORY_FILE ) {
desired_access = FILE_READ_DATA ;
} else {
desired_access = FILE_READ_DATA | FILE_WRITE_DATA ;
}
1999-12-21 06:05:38 +03:00
2009-05-01 02:26:43 +04:00
status = cli_ntcreate ( c , fname , 0 ,
2002-03-05 22:51:05 +03:00
desired_access ,
0x0 ,
2002-02-05 04:31:47 +03:00
FILE_SHARE_READ | FILE_SHARE_WRITE ,
create_disposition ,
2014-05-09 07:55:57 +04:00
create_options , 0 , & fd , NULL ) ;
2009-05-01 02:26:43 +04:00
if ( ! NT_STATUS_IS_OK ( status ) & & handle ! = - 1 ) {
printf ( " ERROR: cli_ntcreate failed for %s - %s \n " ,
2011-02-07 13:27:02 +03:00
fname , nt_errstr ( status ) ) ;
2002-02-05 04:31:47 +03:00
exit ( 1 ) ;
1999-12-21 06:05:38 +03:00
}
2009-05-01 02:26:43 +04:00
if ( NT_STATUS_IS_OK ( status ) & & handle = = - 1 ) {
printf ( " ERROR: cli_ntcreate succeeded for %s \n " , fname ) ;
2002-02-05 04:31:47 +03:00
exit ( 1 ) ;
1999-12-21 06:05:38 +03:00
}
2009-05-01 02:26:43 +04:00
if ( fd = = ( uint16_t ) - 1 ) return ;
2002-02-05 04:31:47 +03:00
1999-12-21 06:05:38 +03:00
for ( i = 0 ; i < MAX_FILES ; i + + ) {
if ( ftable [ i ] . handle = = 0 ) break ;
}
if ( i = = MAX_FILES ) {
2002-02-05 04:31:47 +03:00
printf ( " (%d) file table full for %s \n " , line_count ,
fname ) ;
1999-12-21 06:05:38 +03:00
exit ( 1 ) ;
}
ftable [ i ] . handle = handle ;
ftable [ i ] . fd = fd ;
}
2002-02-05 04:31:47 +03:00
void nb_writex ( int handle , int offset , int size , int ret_size )
1999-12-21 06:05:38 +03:00
{
int i ;
2011-04-02 13:46:30 +04:00
NTSTATUS status ;
1999-12-21 06:05:38 +03:00
if ( buf [ 0 ] = = 0 ) memset ( buf , 1 , sizeof ( buf ) ) ;
2002-02-05 04:31:47 +03:00
i = find_handle ( handle ) ;
2011-04-02 13:46:30 +04:00
status = cli_writeall ( c , ftable [ i ] . fd , 0 , ( uint8_t * ) buf , offset , size ,
NULL ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
printf ( " (%d) ERROR: write failed on handle %d, fd %d "
" error %s \n " , line_count , handle , ftable [ i ] . fd ,
nt_errstr ( status ) ) ;
2002-02-05 04:31:47 +03:00
exit ( 1 ) ;
1999-12-21 06:05:38 +03:00
}
2002-02-05 04:31:47 +03:00
children [ nbio_id ] . bytes_out + = ret_size ;
1999-12-21 06:05:38 +03:00
}
2002-02-05 04:31:47 +03:00
void nb_readx ( int handle , int offset , int size , int ret_size )
1999-12-21 06:05:38 +03:00
{
2011-07-22 16:01:12 +04:00
int i ;
NTSTATUS status ;
size_t nread ;
1999-12-21 06:05:38 +03:00
2002-02-05 04:31:47 +03:00
i = find_handle ( handle ) ;
2011-07-22 16:01:12 +04:00
status = cli_read ( c , ftable [ i ] . fd , buf , offset , size , & nread ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
printf ( " (%d) ERROR: read failed on handle %d ofs=%d size=%d "
" fd %d nterror %s \n " ,
line_count , handle , offset , size ,
ftable [ i ] . fd , nt_errstr ( status ) ) ;
exit ( 1 ) ;
} else if ( nread ! = ret_size ) {
printf ( " (%d) ERROR: read failed on handle %d ofs=%d size=%d "
" nread=%lu ret_size=%d fd %d \n " ,
line_count , handle , offset , size , ( unsigned long ) nread ,
ret_size , ftable [ i ] . fd ) ;
2002-02-05 04:31:47 +03:00
exit ( 1 ) ;
1999-12-21 06:05:38 +03:00
}
2002-02-05 04:31:47 +03:00
children [ nbio_id ] . bytes_in + = ret_size ;
1999-12-21 06:05:38 +03:00
}
void nb_close ( int handle )
{
int i ;
2002-02-05 04:31:47 +03:00
i = find_handle ( handle ) ;
2009-05-01 03:57:42 +04:00
if ( ! NT_STATUS_IS_OK ( cli_close ( c , ftable [ i ] . fd ) ) ) {
2002-02-05 04:31:47 +03:00
printf ( " (%d) close failed on handle %d \n " , line_count , handle ) ;
exit ( 1 ) ;
1999-12-21 06:05:38 +03:00
}
ftable [ i ] . handle = 0 ;
}
2003-04-23 12:12:34 +04:00
void nb_rmdir ( const char * fname )
1999-12-21 06:05:38 +03:00
{
2011-02-07 13:27:02 +03:00
NTSTATUS status ;
status = cli_rmdir ( c , fname ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2002-02-05 04:31:47 +03:00
printf ( " ERROR: rmdir %s failed (%s) \n " ,
2011-02-07 13:27:02 +03:00
fname , nt_errstr ( status ) ) ;
2002-02-05 04:31:47 +03:00
exit ( 1 ) ;
1999-12-21 06:05:38 +03:00
}
}
2005-06-25 00:25:18 +04:00
void nb_rename ( const char * oldname , const char * newname )
1999-12-21 06:05:38 +03:00
{
2011-02-07 13:27:02 +03:00
NTSTATUS status ;
2017-03-22 00:13:07 +03:00
status = cli_rename ( c , oldname , newname , false ) ;
2011-02-07 13:27:02 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2002-02-05 04:31:47 +03:00
printf ( " ERROR: rename %s %s failed (%s) \n " ,
2011-02-07 13:27:02 +03:00
oldname , newname , nt_errstr ( status ) ) ;
2002-02-05 04:31:47 +03:00
exit ( 1 ) ;
1999-12-21 06:05:38 +03:00
}
}
2003-04-23 12:12:34 +04:00
void nb_qpathinfo ( const char * fname )
2002-02-05 04:31:47 +03:00
{
2010-07-25 15:19:34 +04:00
cli_qpathinfo1 ( c , fname , NULL , NULL , NULL , NULL , NULL ) ;
2002-02-05 04:31:47 +03:00
}
void nb_qfileinfo ( int fnum )
{
int i ;
i = find_handle ( fnum ) ;
2010-10-23 11:28:47 +04:00
cli_qfileinfo_basic ( c , ftable [ i ] . fd , NULL , NULL , NULL , NULL , NULL ,
NULL , NULL ) ;
2002-02-05 04:31:47 +03:00
}
void nb_qfsinfo ( int level )
1999-12-21 06:05:38 +03:00
{
2014-06-05 01:12:38 +04:00
uint64_t bsize , total , avail ;
2002-02-05 04:31:47 +03:00
/* this is not the right call - we need cli_qfsinfo() */
2016-01-06 01:08:25 +03:00
cli_disk_size ( c , " " , & bsize , & total , & avail ) ;
2002-02-05 04:31:47 +03:00
}
1999-12-21 06:05:38 +03:00
2020-10-19 11:09:23 +03:00
static NTSTATUS find_fn ( struct file_info * finfo , const char * name ,
2010-07-27 12:59:55 +04:00
void * state )
2002-02-05 04:31:47 +03:00
{
/* noop */
2010-10-29 22:56:51 +04:00
return NT_STATUS_OK ;
2002-02-05 04:31:47 +03:00
}
1999-12-21 06:05:38 +03:00
2003-04-23 12:12:34 +04:00
void nb_findfirst ( const char * mask )
2002-02-05 04:31:47 +03:00
{
cli_list ( c , mask , 0 , find_fn , NULL ) ;
}
void nb_flush ( int fnum )
{
int i ;
i = find_handle ( fnum ) ;
2013-12-04 17:02:00 +04:00
cli_flush ( NULL , c , i ) ;
2002-02-05 04:31:47 +03:00
}
static int total_deleted ;
2020-10-19 11:09:23 +03:00
static NTSTATUS delete_fn ( struct file_info * finfo ,
2010-07-27 12:59:55 +04:00
const char * name , void * state )
2002-02-05 04:31:47 +03:00
{
2010-10-29 22:56:51 +04:00
NTSTATUS status ;
2002-02-05 04:31:47 +03:00
char * s , * n ;
2010-11-17 22:54:41 +03:00
if ( finfo - > name [ 0 ] = = ' . ' ) {
return NT_STATUS_OK ;
}
2002-02-05 04:31:47 +03:00
2005-05-07 10:59:00 +04:00
n = SMB_STRDUP ( name ) ;
2002-02-05 04:31:47 +03:00
n [ strlen ( n ) - 1 ] = 0 ;
2009-01-02 22:38:24 +03:00
if ( asprintf ( & s , " %s%s " , n , finfo - > name ) = = - 1 ) {
2013-12-04 17:01:56 +04:00
free ( n ) ;
2009-01-02 22:38:24 +03:00
printf ( " asprintf failed \n " ) ;
2010-10-29 22:56:51 +04:00
return NT_STATUS_NO_MEMORY ;
2009-01-02 22:38:24 +03:00
}
2020-06-03 20:41:27 +03:00
if ( finfo - > attr & FILE_ATTRIBUTE_DIRECTORY ) {
2002-02-05 06:55:20 +03:00
char * s2 ;
2009-01-02 22:38:24 +03:00
if ( asprintf ( & s2 , " %s \\ * " , s ) = = - 1 ) {
printf ( " asprintf failed \n " ) ;
2013-12-04 17:01:56 +04:00
free ( s ) ;
free ( n ) ;
2010-10-29 22:56:51 +04:00
return NT_STATUS_NO_MEMORY ;
}
2011-04-29 05:57:02 +04:00
status = cli_list ( c , s2 , FILE_ATTRIBUTE_DIRECTORY , delete_fn , NULL ) ;
2013-12-04 17:01:56 +04:00
free ( s2 ) ;
2010-10-29 22:56:51 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2013-12-04 17:01:56 +04:00
free ( s ) ;
2010-10-29 22:56:51 +04:00
free ( n ) ;
return status ;
2009-01-02 22:38:24 +03:00
}
2002-02-05 06:55:20 +03:00
nb_rmdir ( s ) ;
2002-02-05 04:31:47 +03:00
} else {
total_deleted + + ;
nb_unlink ( s ) ;
1999-12-21 06:05:38 +03:00
}
2002-02-05 04:31:47 +03:00
free ( s ) ;
free ( n ) ;
2010-10-29 22:56:51 +04:00
return NT_STATUS_OK ;
1999-12-21 06:05:38 +03:00
}
2003-04-23 12:12:34 +04:00
void nb_deltree ( const char * dname )
1999-12-21 06:05:38 +03:00
{
2002-02-05 04:31:47 +03:00
char * mask ;
2009-01-02 22:38:24 +03:00
if ( asprintf ( & mask , " %s \\ * " , dname ) = = - 1 ) {
printf ( " asprintf failed \n " ) ;
return ;
}
2002-02-05 04:31:47 +03:00
total_deleted = 0 ;
2011-04-29 05:57:02 +04:00
cli_list ( c , mask , FILE_ATTRIBUTE_DIRECTORY , delete_fn , NULL ) ;
2002-02-05 04:31:47 +03:00
free ( mask ) ;
2002-02-05 06:02:14 +03:00
cli_rmdir ( c , dname ) ;
2002-02-05 04:31:47 +03:00
if ( total_deleted ) printf ( " WARNING: Cleaned up %d files \n " , total_deleted ) ;
1999-12-21 06:05:38 +03:00
}
2002-02-05 06:55:20 +03:00
void nb_cleanup ( void )
{
cli_rmdir ( c , " clients " ) ;
children [ nbio_id ] . done = 1 ;
}