2000-04-30 08:45:16 +04:00
/*
2002-01-30 09:08:46 +03:00
Unix SMB / CIFS implementation .
2000-04-30 15:25:09 +04:00
filename matching routine
2000-04-30 08:45:16 +04:00
Copyright ( C ) Andrew Tridgell 1992 - 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
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 . */
2000-04-30 15:25:09 +04:00
/*
This module was originally based on fnmatch . c copyright by the Free
Software Foundation . It bears little resemblence to that code now
*/
2000-04-30 08:45:16 +04:00
# if FNMATCH_TEST
# include <stdio.h>
# include <stdlib.h>
# else
# include "includes.h"
# endif
2001-04-17 09:41:07 +04:00
/*
bugger . we need a separate wildcard routine for older versions
of the protocol . This is not yet perfect , but its a lot
2001-07-04 11:15:53 +04:00
better than what we had */
static int ms_fnmatch_lanman_core ( const smb_ucs2_t * pattern ,
const smb_ucs2_t * string )
2001-04-17 09:41:07 +04:00
{
2001-07-04 11:15:53 +04:00
const smb_ucs2_t * p = pattern , * n = string ;
smb_ucs2_t c ;
2001-04-17 09:41:07 +04:00
2001-07-04 11:15:53 +04:00
if ( strcmp_wa ( p , " ? " ) = = 0 & & strcmp_wa ( n , " . " ) ) goto match ;
2001-04-17 09:41:07 +04:00
while ( ( c = * p + + ) ) {
switch ( c ) {
2001-07-04 11:15:53 +04:00
case UCS2_CHAR ( ' . ' ) :
2001-04-17 11:09:42 +04:00
if ( ! * n ) goto next ;
2001-07-04 11:15:53 +04:00
if ( * n ! = UCS2_CHAR ( ' . ' ) ) goto nomatch ;
2001-04-17 09:41:07 +04:00
n + + ;
break ;
2001-07-04 11:15:53 +04:00
case UCS2_CHAR ( ' ? ' ) :
2001-04-17 11:09:42 +04:00
if ( ! * n ) goto next ;
2001-07-04 11:15:53 +04:00
if ( ( * n = = UCS2_CHAR ( ' . ' ) & &
n [ 1 ] ! = UCS2_CHAR ( ' . ' ) ) | | ! * n )
goto next ;
2001-04-17 09:41:07 +04:00
n + + ;
break ;
2001-07-04 11:15:53 +04:00
case UCS2_CHAR ( ' > ' ) :
2001-04-17 11:09:42 +04:00
if ( ! * n ) goto next ;
2001-07-04 11:15:53 +04:00
if ( n [ 0 ] = = UCS2_CHAR ( ' . ' ) ) {
2001-04-17 09:41:07 +04:00
if ( ! n [ 1 ] & & ms_fnmatch_lanman_core ( p , n + 1 ) = = 0 ) goto match ;
if ( ms_fnmatch_lanman_core ( p , n ) = = 0 ) goto match ;
goto nomatch ;
}
n + + ;
break ;
2001-07-04 11:15:53 +04:00
case UCS2_CHAR ( ' * ' ) :
2001-04-17 11:09:42 +04:00
if ( ! * n ) goto next ;
2001-04-17 09:41:07 +04:00
if ( ! * p ) goto match ;
for ( ; * n ; n + + ) {
if ( ms_fnmatch_lanman_core ( p , n ) = = 0 ) goto match ;
}
break ;
2001-07-04 11:15:53 +04:00
case UCS2_CHAR ( ' < ' ) :
2001-04-17 09:41:07 +04:00
for ( ; * n ; n + + ) {
if ( ms_fnmatch_lanman_core ( p , n ) = = 0 ) goto match ;
2001-07-04 11:15:53 +04:00
if ( * n = = UCS2_CHAR ( ' . ' ) & &
! strchr_w ( n + 1 , UCS2_CHAR ( ' . ' ) ) ) {
2001-04-17 09:41:07 +04:00
n + + ;
break ;
}
}
break ;
2001-07-04 11:15:53 +04:00
case UCS2_CHAR ( ' " ' ) :
2001-04-17 09:41:07 +04:00
if ( * n = = 0 & & ms_fnmatch_lanman_core ( p , n ) = = 0 ) goto match ;
2001-07-04 11:15:53 +04:00
if ( * n ! = UCS2_CHAR ( ' . ' ) ) goto nomatch ;
2001-04-17 09:41:07 +04:00
n + + ;
break ;
default :
if ( c ! = * n ) goto nomatch ;
n + + ;
}
}
if ( ! * n ) goto match ;
nomatch :
/*
if ( verbose ) printf ( " NOMATCH pattern=[%s] string=[%s] \n " , pattern , string ) ;
*/
return - 1 ;
next :
if ( ms_fnmatch_lanman_core ( p , n ) = = 0 ) goto match ;
goto nomatch ;
match :
/*
if ( verbose ) printf ( " MATCH pattern=[%s] string=[%s] \n " , pattern , string ) ;
*/
return 0 ;
}
2001-07-04 11:15:53 +04:00
static int ms_fnmatch_lanman1 ( const smb_ucs2_t * pattern , const smb_ucs2_t * string )
2001-04-17 09:41:07 +04:00
{
2001-07-04 11:15:53 +04:00
if ( ! strpbrk_wa ( pattern , " ?*<> \" " ) ) {
smb_ucs2_t s [ ] = { UCS2_CHAR ( ' . ' ) , 0 } ;
if ( strcmp_wa ( string , " .. " ) = = 0 ) string = s ;
return strcasecmp_w ( pattern , string ) ;
2001-04-17 09:41:07 +04:00
}
2001-07-04 11:15:53 +04:00
if ( strcmp_wa ( string , " .. " ) = = 0 | | strcmp_wa ( string , " . " ) = = 0 ) {
smb_ucs2_t dot [ ] = { UCS2_CHAR ( ' . ' ) , 0 } ;
smb_ucs2_t dotdot [ ] = { UCS2_CHAR ( ' . ' ) , UCS2_CHAR ( ' . ' ) , 0 } ;
return ms_fnmatch_lanman_core ( pattern , dotdot ) & &
ms_fnmatch_lanman_core ( pattern , dot ) ;
2001-04-17 09:41:07 +04:00
}
return ms_fnmatch_lanman_core ( pattern , string ) ;
}
2000-04-30 08:45:16 +04:00
/* the following function was derived using the masktest utility -
after years of effort we finally have a perfect MS wildcard
2000-04-30 15:25:09 +04:00
matching routine !
NOTE : this matches only filenames with no directory component
2000-05-02 06:23:41 +04:00
Returns 0 on match , - 1 on fail .
2000-04-30 15:25:09 +04:00
*/
2001-08-20 09:15:26 +04:00
static int ms_fnmatch_w ( const smb_ucs2_t * pattern , const smb_ucs2_t * string , int protocol )
2000-04-30 08:45:16 +04:00
{
2001-07-04 11:15:53 +04:00
const smb_ucs2_t * p = pattern , * n = string ;
smb_ucs2_t c ;
2001-04-17 09:41:07 +04:00
2001-08-20 09:15:26 +04:00
if ( protocol < = PROTOCOL_LANMAN2 ) {
2001-04-17 09:41:07 +04:00
return ms_fnmatch_lanman1 ( pattern , string ) ;
}
2000-04-30 08:45:16 +04:00
while ( ( c = * p + + ) ) {
switch ( c ) {
2001-07-04 11:15:53 +04:00
case UCS2_CHAR ( ' ? ' ) :
2000-04-30 08:45:16 +04:00
if ( ! * n ) return - 1 ;
n + + ;
break ;
2001-07-04 11:15:53 +04:00
case UCS2_CHAR ( ' > ' ) :
if ( n [ 0 ] = = UCS2_CHAR ( ' . ' ) ) {
2001-08-20 09:15:26 +04:00
if ( ! n [ 1 ] & & ms_fnmatch_w ( p , n + 1 , protocol ) = = 0 ) return 0 ;
if ( ms_fnmatch_w ( p , n , protocol ) = = 0 ) return 0 ;
2000-04-30 08:45:16 +04:00
return - 1 ;
}
2001-08-20 09:15:26 +04:00
if ( ! * n ) return ms_fnmatch_w ( p , n , protocol ) ;
2000-04-30 08:45:16 +04:00
n + + ;
break ;
2001-07-04 11:15:53 +04:00
case UCS2_CHAR ( ' * ' ) :
2000-04-30 08:45:16 +04:00
for ( ; * n ; n + + ) {
2001-08-20 09:15:26 +04:00
if ( ms_fnmatch_w ( p , n , protocol ) = = 0 ) return 0 ;
2000-04-30 08:45:16 +04:00
}
break ;
2001-07-04 11:15:53 +04:00
case UCS2_CHAR ( ' < ' ) :
2000-04-30 08:45:16 +04:00
for ( ; * n ; n + + ) {
2001-08-20 09:15:26 +04:00
if ( ms_fnmatch_w ( p , n , protocol ) = = 0 ) return 0 ;
2001-07-04 11:15:53 +04:00
if ( * n = = UCS2_CHAR ( ' . ' ) & & ! strchr_wa ( n + 1 , ' . ' ) ) {
2000-04-30 08:45:16 +04:00
n + + ;
break ;
}
}
break ;
2001-07-04 11:15:53 +04:00
case UCS2_CHAR ( ' " ' ) :
2001-08-20 09:15:26 +04:00
if ( * n = = 0 & & ms_fnmatch_w ( p , n , protocol ) = = 0 ) return 0 ;
2001-07-04 11:15:53 +04:00
if ( * n ! = UCS2_CHAR ( ' . ' ) ) return - 1 ;
2000-04-30 08:45:16 +04:00
n + + ;
break ;
default :
if ( c ! = * n ) return - 1 ;
n + + ;
}
}
2000-04-30 15:25:09 +04:00
if ( ! * n ) return 0 ;
2000-04-30 08:45:16 +04:00
return - 1 ;
}
2001-08-20 09:15:26 +04:00
int ms_fnmatch ( const char * pattern , const char * string , int protocol )
2000-04-30 08:45:16 +04:00
{
2001-07-04 11:15:53 +04:00
wpstring p , s ;
2001-08-20 09:15:26 +04:00
int ret ;
2000-04-30 08:45:16 +04:00
2001-07-04 11:15:53 +04:00
pstrcpy_wa ( p , pattern ) ;
pstrcpy_wa ( s , string ) ;
2000-04-30 08:45:16 +04:00
2001-08-20 09:15:26 +04:00
ret = ms_fnmatch_w ( p , s , protocol ) ;
/* DEBUG(0,("ms_fnmatch(%s,%s) -> %d\n", pattern, string, ret)); */
return ret ;
}
/* a generic fnmatch function - uses for non-CIFS pattern matching */
int gen_fnmatch ( const char * pattern , const char * string )
{
return ms_fnmatch ( pattern , string , PROTOCOL_NT1 ) ;
2000-04-30 08:45:16 +04:00
}