2003-08-13 05:53:07 +04:00
/*
Unix SMB / CIFS implementation .
mask_match tester
Copyright ( C ) Andrew Tridgell 1999
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 2 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 , write to the Free Software
Foundation , Inc . , 675 Mass Ave , Cambridge , MA 0213 9 , USA .
*/
# include "includes.h"
2004-11-03 03:17:12 +03:00
# include "dynconfig.h"
2004-11-30 08:37:57 +03:00
# include "clilist.h"
2004-11-01 04:03:22 +03:00
# include "libcli/raw/libcliraw.h"
2004-11-02 03:24:21 +03:00
# include "system/time.h"
2003-08-13 05:53:07 +04:00
static fstring password ;
static fstring username ;
static BOOL showall = False ;
static BOOL old_list = False ;
static const char * maskchars = " <> \" ?*abc. " ;
static const char * filechars = " abcdefghijklm. " ;
static int verbose ;
static int die_on_error ;
static int NumLoops = 0 ;
2004-10-02 05:42:41 +04:00
static int max_length = 20 ;
2003-08-13 05:53:07 +04:00
2004-08-04 17:23:35 +04:00
static BOOL reg_match_one ( struct smbcli_state * cli , const char * pattern , const char * file )
2003-08-13 05:53:07 +04:00
{
/* oh what a weird world this is */
if ( old_list & & strcmp ( pattern , " *.* " ) = = 0 ) return True ;
if ( strcmp ( pattern , " . " ) = = 0 ) return False ;
if ( strcmp ( file , " .. " ) = = 0 ) file = " . " ;
return ms_fnmatch ( pattern , file , cli - > transport - > negotiate . protocol ) = = 0 ;
}
2004-08-04 17:23:35 +04:00
static char * reg_test ( struct smbcli_state * cli , char * pattern , char * long_name , char * short_name )
2003-08-13 05:53:07 +04:00
{
static fstring ret ;
fstrcpy ( ret , " --- " ) ;
pattern = 1 + strrchr_m ( pattern , ' \\ ' ) ;
if ( reg_match_one ( cli , pattern , " . " ) ) ret [ 0 ] = ' + ' ;
if ( reg_match_one ( cli , pattern , " .. " ) ) ret [ 1 ] = ' + ' ;
if ( reg_match_one ( cli , pattern , long_name ) | |
( * short_name & & reg_match_one ( cli , pattern , short_name ) ) ) ret [ 2 ] = ' + ' ;
return ret ;
}
/*****************************************************
return a connection to a server
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2004-08-04 17:23:35 +04:00
static struct smbcli_state * connect_one ( char * share )
2003-08-13 05:53:07 +04:00
{
2004-08-04 17:23:35 +04:00
struct smbcli_state * c ;
2003-08-13 05:53:07 +04:00
fstring server ;
uint_t flags = 0 ;
NTSTATUS status ;
fstrcpy ( server , share + 2 ) ;
share = strchr_m ( server , ' \\ ' ) ;
if ( ! share ) return NULL ;
* share = 0 ;
share + + ;
2004-09-28 09:44:59 +04:00
status = smbcli_full_connection ( NULL , & c , " masktest " ,
2003-08-13 05:53:07 +04:00
server , NULL ,
share , " ????? " ,
username , lp_workgroup ( ) ,
password , flags , NULL ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return NULL ;
}
return c ;
}
static char * resultp ;
static struct {
pstring long_name ;
pstring short_name ;
} last_hit ;
static BOOL f_info_hit ;
2004-11-30 08:37:57 +03:00
static void listfn ( struct clilist_file_info * f , const char * s , void * state )
2003-08-13 05:53:07 +04:00
{
if ( strcmp ( f - > name , " . " ) = = 0 ) {
resultp [ 0 ] = ' + ' ;
} else if ( strcmp ( f - > name , " .. " ) = = 0 ) {
resultp [ 1 ] = ' + ' ;
} else {
resultp [ 2 ] = ' + ' ;
}
pstrcpy ( last_hit . long_name , f - > name ) ;
pstrcpy ( last_hit . short_name , f - > short_name ) ;
f_info_hit = True ;
}
2004-08-04 17:23:35 +04:00
static void get_real_name ( struct smbcli_state * cli ,
2003-08-13 05:53:07 +04:00
pstring long_name , fstring short_name )
{
const char * mask ;
2004-08-10 00:51:16 +04:00
if ( cli - > transport - > negotiate . protocol < = PROTOCOL_LANMAN1 ) {
2003-08-13 05:53:07 +04:00
mask = " \\ masktest \\ *.* " ;
} else {
mask = " \\ masktest \\ * " ;
}
f_info_hit = False ;
2004-08-04 17:23:35 +04:00
smbcli_list_new ( cli - > tree , mask ,
2004-10-02 16:30:02 +04:00
FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_DIRECTORY ,
RAW_SEARCH_BOTH_DIRECTORY_INFO ,
listfn , NULL ) ;
2003-08-13 05:53:07 +04:00
if ( f_info_hit ) {
fstrcpy ( short_name , last_hit . short_name ) ;
strlower ( short_name ) ;
pstrcpy ( long_name , last_hit . long_name ) ;
strlower ( long_name ) ;
}
if ( * short_name = = 0 ) {
fstrcpy ( short_name , long_name ) ;
}
}
2004-08-04 17:23:35 +04:00
static void testpair ( struct smbcli_state * cli , char * mask , char * file )
2003-08-13 05:53:07 +04:00
{
int fnum ;
fstring res1 ;
char * res2 ;
static int count ;
fstring short_name ;
pstring long_name ;
count + + ;
fstrcpy ( res1 , " --- " ) ;
2004-08-04 17:23:35 +04:00
fnum = smbcli_open ( cli - > tree , file , O_CREAT | O_TRUNC | O_RDWR , 0 ) ;
2003-08-13 05:53:07 +04:00
if ( fnum = = - 1 ) {
DEBUG ( 0 , ( " Can't create %s \n " , file ) ) ;
return ;
}
2004-08-04 17:23:35 +04:00
smbcli_close ( cli - > tree , fnum ) ;
2003-08-13 05:53:07 +04:00
resultp = res1 ;
fstrcpy ( short_name , " " ) ;
get_real_name ( cli , long_name , short_name ) ;
fstrcpy ( res1 , " --- " ) ;
2004-10-08 12:13:00 +04:00
smbcli_list_new ( cli - > tree , mask ,
FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_DIRECTORY ,
RAW_SEARCH_BOTH_DIRECTORY_INFO ,
listfn , NULL ) ;
2003-08-13 05:53:07 +04:00
res2 = reg_test ( cli , mask , long_name , short_name ) ;
if ( showall | | strcmp ( res1 , res2 ) ) {
d_printf ( " %s %s %d mask=[%s] file=[%s] rfile=[%s/%s] \n " ,
res1 , res2 , count , mask , file , long_name , short_name ) ;
if ( die_on_error ) exit ( 1 ) ;
}
2004-08-04 17:23:35 +04:00
smbcli_unlink ( cli - > tree , file ) ;
2003-08-13 05:53:07 +04:00
if ( count % 100 = = 0 ) DEBUG ( 0 , ( " %d \n " , count ) ) ;
}
static void test_mask ( int argc , char * argv [ ] ,
2004-08-04 17:23:35 +04:00
struct smbcli_state * cli )
2003-08-13 05:53:07 +04:00
{
pstring mask , file ;
int l1 , l2 , i , l ;
int mc_len = strlen ( maskchars ) ;
int fc_len = strlen ( filechars ) ;
2004-08-04 17:23:35 +04:00
smbcli_mkdir ( cli - > tree , " \\ masktest " ) ;
2003-08-13 05:53:07 +04:00
2004-08-04 17:23:35 +04:00
smbcli_unlink ( cli - > tree , " \\ masktest \\ * " ) ;
2003-08-13 05:53:07 +04:00
if ( argc > = 2 ) {
while ( argc > = 2 ) {
pstrcpy ( mask , " \\ masktest \\ " ) ;
pstrcpy ( file , " \\ masktest \\ " ) ;
pstrcat ( mask , argv [ 0 ] ) ;
pstrcat ( file , argv [ 1 ] ) ;
testpair ( cli , mask , file ) ;
argv + = 2 ;
argc - = 2 ;
}
goto finished ;
}
while ( 1 ) {
2004-10-02 05:42:41 +04:00
l1 = 1 + random ( ) % max_length ;
l2 = 1 + random ( ) % max_length ;
2003-08-13 05:53:07 +04:00
pstrcpy ( mask , " \\ masktest \\ " ) ;
pstrcpy ( file , " \\ masktest \\ " ) ;
l = strlen ( mask ) ;
for ( i = 0 ; i < l1 ; i + + ) {
mask [ i + l ] = maskchars [ random ( ) % mc_len ] ;
}
mask [ l + l1 ] = 0 ;
for ( i = 0 ; i < l2 ; i + + ) {
file [ i + l ] = filechars [ random ( ) % fc_len ] ;
}
file [ l + l2 ] = 0 ;
if ( strcmp ( file + l , " . " ) = = 0 | |
strcmp ( file + l , " .. " ) = = 0 | |
strcmp ( mask + l , " .. " ) = = 0 ) continue ;
if ( strspn ( file + l , " . " ) = = strlen ( file + l ) ) continue ;
testpair ( cli , mask , file ) ;
if ( NumLoops & & ( - - NumLoops = = 0 ) )
break ;
}
finished :
2004-08-04 17:23:35 +04:00
smbcli_rmdir ( cli - > tree , " \\ masktest " ) ;
2003-08-13 05:53:07 +04:00
}
static void usage ( void )
{
printf (
" Usage: \n \
masktest / / server / share [ options . . ] \ n \
options : \ n \
- d debuglevel \ n \
- n numloops \ n \
- W workgroup \ n \
- U user % % pass \ n \
- s seed \ n \
2004-10-02 05:42:41 +04:00
- l max test length \ n \
2003-08-13 05:53:07 +04:00
- M max protocol \ n \
- f filechars ( default % s ) \ n \
- m maskchars ( default % s ) \ n \
- v verbose mode \ n \
- E die on error \ n \
- a show all tests \ n \
\ n \
This program tests wildcard matching between two servers . It generates \ n \
random pairs of filenames / masks and tests that they match in the same \ n \
way on the servers and internally \ n \
" ,
filechars , maskchars ) ;
}
/****************************************************************************
main program
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
int main ( int argc , char * argv [ ] )
{
char * share ;
2004-08-04 17:23:35 +04:00
struct smbcli_state * cli ;
2003-08-13 05:53:07 +04:00
int opt ;
char * p ;
int seed ;
setlinebuf ( stdout ) ;
setup_logging ( " masktest " , DEBUG_STDOUT ) ;
lp_set_cmdline ( " log level " , " 0 " ) ;
if ( argc < 2 | | argv [ 1 ] [ 0 ] = = ' - ' ) {
usage ( ) ;
exit ( 1 ) ;
}
share = argv [ 1 ] ;
all_string_sub ( share , " / " , " \\ " , 0 ) ;
2003-08-15 22:33:43 +04:00
setup_logging ( argv [ 0 ] , DEBUG_STDOUT ) ;
2003-08-13 05:53:07 +04:00
argc - = 1 ;
argv + = 1 ;
lp_load ( dyn_CONFIGFILE , True , False , False ) ;
load_interfaces ( ) ;
if ( getenv ( " USER " ) ) {
fstrcpy ( username , getenv ( " USER " ) ) ;
}
seed = time ( NULL ) ;
2004-10-08 12:13:00 +04:00
init_iconv ( ) ;
2004-10-02 05:42:41 +04:00
while ( ( opt = getopt ( argc , argv , " n:d:U:s:hm:f:aoW:M:vEl: " ) ) ! = EOF ) {
2003-08-13 05:53:07 +04:00
switch ( opt ) {
case ' n ' :
NumLoops = atoi ( optarg ) ;
break ;
case ' d ' :
DEBUGLEVEL = atoi ( optarg ) ;
break ;
case ' E ' :
die_on_error = 1 ;
break ;
case ' v ' :
verbose + + ;
break ;
case ' M ' :
2004-08-10 00:51:16 +04:00
lp_set_cmdline ( " max protocol " , optarg ) ;
2003-08-13 05:53:07 +04:00
break ;
case ' U ' :
fstrcpy ( username , optarg ) ;
p = strchr_m ( username , ' % ' ) ;
if ( p ) {
* p = 0 ;
fstrcpy ( password , p + 1 ) ;
}
break ;
case ' s ' :
seed = atoi ( optarg ) ;
break ;
case ' h ' :
usage ( ) ;
exit ( 1 ) ;
case ' m ' :
maskchars = optarg ;
break ;
2004-10-02 05:42:41 +04:00
case ' l ' :
max_length = atoi ( optarg ) ;
break ;
2003-08-13 05:53:07 +04:00
case ' f ' :
filechars = optarg ;
break ;
case ' a ' :
showall = 1 ;
break ;
case ' o ' :
old_list = True ;
break ;
default :
printf ( " Unknown option %c (%d) \n " , ( char ) opt , opt ) ;
exit ( 1 ) ;
}
}
2004-11-09 12:26:47 +03:00
masktest_init_subsystems ;
2003-08-13 05:53:07 +04:00
argc - = optind ;
argv + = optind ;
cli = connect_one ( share ) ;
if ( ! cli ) {
DEBUG ( 0 , ( " Failed to connect to %s \n " , share ) ) ;
exit ( 1 ) ;
}
/* need to init seed after connect as clientgen uses random numbers */
2004-08-10 00:51:16 +04:00
DEBUG ( 0 , ( " seed=%d format --- --- (server, correct) \n " , seed ) ) ;
2003-08-13 05:53:07 +04:00
srandom ( seed ) ;
test_mask ( argc , argv , cli ) ;
return ( 0 ) ;
}