mirror of
https://github.com/samba-team/samba.git
synced 2025-12-12 12:23:50 +03:00
- removed all our old wildcard matching code and replaced it with a
call to ms_fnmatch(). This also removes all the Win9X semantics stuff and a bunch of other associated cruft. - moved the stat cache code into statcache.c - fixed the uint16 alignment requirements of ascii_to_unistr() and unistr_to_ascii() - trans2 SMB_FIND_FILE_BOTH_DIRECTORY_INFO returns the short name as unicode always (at least thats what NT4 does) - fixed some errors in the in-memory tdb code. Still ugly, but doesn't crash as much
This commit is contained in:
@@ -165,7 +165,7 @@ SMBD_OBJ1 = smbd/server.o smbd/files.o smbd/chgpasswd.o smbd/connection.o \
|
|||||||
smbd/message.o smbd/nttrans.o smbd/pipes.o \
|
smbd/message.o smbd/nttrans.o smbd/pipes.o \
|
||||||
smbd/reply.o smbd/trans2.o smbd/uid.o \
|
smbd/reply.o smbd/trans2.o smbd/uid.o \
|
||||||
smbd/dosmode.o smbd/filename.o smbd/open.o smbd/close.o smbd/blocking.o \
|
smbd/dosmode.o smbd/filename.o smbd/open.o smbd/close.o smbd/blocking.o \
|
||||||
smbd/vfs.o smbd/vfs-wrap.o \
|
smbd/vfs.o smbd/vfs-wrap.o smbd/statcache.o \
|
||||||
lib/msrpc-client.o lib/msrpc_use.o \
|
lib/msrpc-client.o lib/msrpc_use.o \
|
||||||
rpc_parse/parse_creds.o \
|
rpc_parse/parse_creds.o \
|
||||||
smbd/process.o smbd/oplock.o smbd/service.o smbd/error.o \
|
smbd/process.o smbd/oplock.o smbd/service.o smbd/error.o \
|
||||||
|
|||||||
@@ -302,7 +302,7 @@ static BOOL do_this_one(file_info *finfo)
|
|||||||
if (finfo->mode & aDIR) return(True);
|
if (finfo->mode & aDIR) return(True);
|
||||||
|
|
||||||
if (*fileselection &&
|
if (*fileselection &&
|
||||||
!mask_match(finfo->name,fileselection,False,False)) {
|
!mask_match(finfo->name,fileselection,False)) {
|
||||||
DEBUG(3,("match_match %s failed\n", finfo->name));
|
DEBUG(3,("match_match %s failed\n", finfo->name));
|
||||||
return False;
|
return False;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -820,7 +820,7 @@ static void do_tar(file_info *finfo)
|
|||||||
#ifdef HAVE_REGEX_H
|
#ifdef HAVE_REGEX_H
|
||||||
(tar_re_search && !regexec(preg, exclaim, 0, NULL, 0))) {
|
(tar_re_search && !regexec(preg, exclaim, 0, NULL, 0))) {
|
||||||
#else
|
#else
|
||||||
(tar_re_search && mask_match(exclaim, cliplist[0], True, False))) {
|
(tar_re_search && mask_match(exclaim, cliplist[0], True))) {
|
||||||
#endif
|
#endif
|
||||||
DEBUG(3,("Skipping file %s\n", exclaim));
|
DEBUG(3,("Skipping file %s\n", exclaim));
|
||||||
return;
|
return;
|
||||||
@@ -1234,7 +1234,7 @@ static void do_tarput(void)
|
|||||||
#ifdef HAVE_REGEX_H
|
#ifdef HAVE_REGEX_H
|
||||||
|| (tar_re_search && !regexec(preg, finfo.name, 0, NULL, 0)));
|
|| (tar_re_search && !regexec(preg, finfo.name, 0, NULL, 0)));
|
||||||
#else
|
#else
|
||||||
|| (tar_re_search && mask_match(finfo.name, cliplist[0], True, False)));
|
|| (tar_re_search && mask_match(finfo.name, cliplist[0], True)));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
DEBUG(5, ("Skip = %i, cliplist=%s, file=%s\n", skip, (cliplist?cliplist[0]:NULL), finfo.name));
|
DEBUG(5, ("Skip = %i, cliplist=%s, file=%s\n", skip, (cliplist?cliplist[0]:NULL), finfo.name));
|
||||||
|
|||||||
@@ -140,6 +140,10 @@ void initialize_multibyte_vectors( int client_codepage);
|
|||||||
|
|
||||||
void mdfour(unsigned char *out, unsigned char *in, int n);
|
void mdfour(unsigned char *out, unsigned char *in, int n);
|
||||||
|
|
||||||
|
/*The following definitions come from lib/ms_fnmatch.c */
|
||||||
|
|
||||||
|
int ms_fnmatch(char *pattern, char *string);
|
||||||
|
|
||||||
/*The following definitions come from lib/msrpc-client.c */
|
/*The following definitions come from lib/msrpc-client.c */
|
||||||
|
|
||||||
BOOL receive_msrpc(int fd, prs_struct *data, unsigned int timeout);
|
BOOL receive_msrpc(int fd, prs_struct *data, unsigned int timeout);
|
||||||
@@ -305,14 +309,11 @@ int set_message(char *buf,int num_words,int num_bytes,BOOL zero);
|
|||||||
void dos_clean_name(char *s);
|
void dos_clean_name(char *s);
|
||||||
void unix_clean_name(char *s);
|
void unix_clean_name(char *s);
|
||||||
BOOL reduce_name(char *s,char *dir,BOOL widelinks);
|
BOOL reduce_name(char *s,char *dir,BOOL widelinks);
|
||||||
void expand_mask(char *Mask,BOOL doext);
|
|
||||||
void make_dir_struct(char *buf,char *mask,char *fname,SMB_OFF_T size,int mode,time_t date);
|
void make_dir_struct(char *buf,char *mask,char *fname,SMB_OFF_T size,int mode,time_t date);
|
||||||
void close_low_fds(void);
|
void close_low_fds(void);
|
||||||
int set_blocking(int fd, BOOL set);
|
int set_blocking(int fd, BOOL set);
|
||||||
SMB_OFF_T transfer_file(int infd,int outfd,SMB_OFF_T n,char *header,int headlen,int align);
|
SMB_OFF_T transfer_file(int infd,int outfd,SMB_OFF_T n,char *header,int headlen,int align);
|
||||||
void msleep(int t);
|
void msleep(int t);
|
||||||
BOOL unix_do_match(char *str, char *regexp, BOOL case_sig);
|
|
||||||
BOOL mask_match(char *str, char *regexp, BOOL case_sig, BOOL trans2);
|
|
||||||
void become_daemon(void);
|
void become_daemon(void);
|
||||||
BOOL yesno(char *p);
|
BOOL yesno(char *p);
|
||||||
int set_filelen(int fd, SMB_OFF_T len);
|
int set_filelen(int fd, SMB_OFF_T len);
|
||||||
@@ -355,6 +356,8 @@ void *memdup(void *p, size_t size);
|
|||||||
char *myhostname(void);
|
char *myhostname(void);
|
||||||
char *lock_path(char *name);
|
char *lock_path(char *name);
|
||||||
char *parent_dirname(const char *path);
|
char *parent_dirname(const char *path);
|
||||||
|
BOOL ms_has_wild(char *s);
|
||||||
|
BOOL mask_match(char *string, char *pattern, BOOL case_sensitive);
|
||||||
int _Insure_trap_error(int a1, int a2, int a3, int a4, int a5, int a6);
|
int _Insure_trap_error(int a1, int a2, int a3, int a4, int a5, int a6);
|
||||||
|
|
||||||
/*The following definitions come from lib/util_array.c */
|
/*The following definitions come from lib/util_array.c */
|
||||||
@@ -492,8 +495,8 @@ char *string_truncate(char *s, int length);
|
|||||||
/*The following definitions come from lib/util_unistr.c */
|
/*The following definitions come from lib/util_unistr.c */
|
||||||
|
|
||||||
int dos_PutUniCode(char *dst,const char *src, ssize_t len, BOOL null_terminate);
|
int dos_PutUniCode(char *dst,const char *src, ssize_t len, BOOL null_terminate);
|
||||||
void ascii_to_unistr(uint16 *dest, const char *src, int maxlen);
|
void ascii_to_unistr(char *dest, const char *src, int maxlen);
|
||||||
void unistr_to_ascii(char *dest, const uint16 *src, int len);
|
void unistr_to_ascii(char *dest, char *src, int len);
|
||||||
char *skip_unibuf(char *src, size_t len);
|
char *skip_unibuf(char *src, size_t len);
|
||||||
char *dos_unistrn2(uint16 *src, int len);
|
char *dos_unistrn2(uint16 *src, int len);
|
||||||
char *dos_unistr2(uint16 *src);
|
char *dos_unistr2(uint16 *src);
|
||||||
@@ -3059,11 +3062,9 @@ void sys_fsync_file(connection_struct *conn, files_struct *fsp);
|
|||||||
|
|
||||||
/*The following definitions come from smbd/filename.c */
|
/*The following definitions come from smbd/filename.c */
|
||||||
|
|
||||||
void print_stat_cache_statistics(void);
|
|
||||||
BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component,
|
BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component,
|
||||||
BOOL *bad_path, SMB_STRUCT_STAT *pst);
|
BOOL *bad_path, SMB_STRUCT_STAT *pst);
|
||||||
BOOL check_name(char *name,connection_struct *conn);
|
BOOL check_name(char *name,connection_struct *conn);
|
||||||
BOOL reset_stat_cache( void );
|
|
||||||
|
|
||||||
/*The following definitions come from smbd/files.c */
|
/*The following definitions come from smbd/files.c */
|
||||||
|
|
||||||
@@ -3316,9 +3317,16 @@ int sslutil_connect(int fd);
|
|||||||
int sslutil_disconnect(int fd);
|
int sslutil_disconnect(int fd);
|
||||||
int sslutil_negotiate_ssl(int fd, int msg_type);
|
int sslutil_negotiate_ssl(int fd, int msg_type);
|
||||||
|
|
||||||
|
/*The following definitions come from smbd/statcache.c */
|
||||||
|
|
||||||
|
void print_stat_cache_statistics(void);
|
||||||
|
void stat_cache_add( char *full_orig_name, char *orig_translated_path);
|
||||||
|
BOOL stat_cache_lookup(connection_struct *conn, char *name, char *dirpath,
|
||||||
|
char **start, SMB_STRUCT_STAT *pst);
|
||||||
|
BOOL reset_stat_cache( void );
|
||||||
|
|
||||||
/*The following definitions come from smbd/trans2.c */
|
/*The following definitions come from smbd/trans2.c */
|
||||||
|
|
||||||
void mask_convert( char *mask);
|
|
||||||
int reply_findclose(connection_struct *conn,
|
int reply_findclose(connection_struct *conn,
|
||||||
char *inbuf,char *outbuf,int length,int bufsize);
|
char *inbuf,char *outbuf,int length,int bufsize);
|
||||||
int reply_findnclose(connection_struct *conn,
|
int reply_findnclose(connection_struct *conn,
|
||||||
@@ -3475,6 +3483,9 @@ int tdb_writelock(TDB_CONTEXT *tdb);
|
|||||||
int tdb_writeunlock(TDB_CONTEXT *tdb);
|
int tdb_writeunlock(TDB_CONTEXT *tdb);
|
||||||
int tdb_lockchain(TDB_CONTEXT *tdb, TDB_DATA key);
|
int tdb_lockchain(TDB_CONTEXT *tdb, TDB_DATA key);
|
||||||
int tdb_unlockchain(TDB_CONTEXT *tdb, TDB_DATA key);
|
int tdb_unlockchain(TDB_CONTEXT *tdb, TDB_DATA key);
|
||||||
|
|
||||||
|
/*The following definitions come from tdb/tdbutil.c */
|
||||||
|
|
||||||
int tdb_get_int_byblob(TDB_CONTEXT *tdb, char *keyval, size_t len);
|
int tdb_get_int_byblob(TDB_CONTEXT *tdb, char *keyval, size_t len);
|
||||||
int tdb_get_int(TDB_CONTEXT *tdb, char *keystr);
|
int tdb_get_int(TDB_CONTEXT *tdb, char *keystr);
|
||||||
int tdb_store_int_byblob(TDB_CONTEXT *tdb, char *keystr, size_t len, int v);
|
int tdb_store_int_byblob(TDB_CONTEXT *tdb, char *keystr, size_t len, int v);
|
||||||
|
|||||||
@@ -176,14 +176,6 @@
|
|||||||
#define _smb_setlen(buf,len) buf[0] = 0; buf[1] = (len&0x10000)>>16; \
|
#define _smb_setlen(buf,len) buf[0] = 0; buf[1] = (len&0x10000)>>16; \
|
||||||
buf[2] = (len&0xFF00)>>8; buf[3] = len&0xFF;
|
buf[2] = (len&0xFF00)>>8; buf[3] = len&0xFF;
|
||||||
|
|
||||||
/*********************************************************
|
|
||||||
* Routine to check if a given string matches exactly.
|
|
||||||
* Case can be significant or not.
|
|
||||||
**********************************************************/
|
|
||||||
|
|
||||||
#define exact_match(str, regexp, case_sig) \
|
|
||||||
((case_sig?strcmp(str,regexp):strcasecmp(str,regexp)) == 0)
|
|
||||||
|
|
||||||
/*******************************************************************
|
/*******************************************************************
|
||||||
find the difference in milliseconds between two struct timeval
|
find the difference in milliseconds between two struct timeval
|
||||||
values
|
values
|
||||||
|
|||||||
@@ -90,9 +90,6 @@ pstring global_myname = "";
|
|||||||
fstring global_myworkgroup = "";
|
fstring global_myworkgroup = "";
|
||||||
char **my_netbios_names;
|
char **my_netbios_names;
|
||||||
|
|
||||||
static char *filename_dos(char *path,char *buf);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
find a suitable temporary directory. The result should be copied immediately
|
find a suitable temporary directory. The result should be copied immediately
|
||||||
@@ -543,85 +540,6 @@ BOOL reduce_name(char *s,char *dir,BOOL widelinks)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
expand some *s
|
|
||||||
****************************************************************************/
|
|
||||||
static void expand_one(char *Mask,int len)
|
|
||||||
{
|
|
||||||
char *p1;
|
|
||||||
while ((p1 = strchr(Mask,'*')) != NULL)
|
|
||||||
{
|
|
||||||
int lfill = (len+1) - strlen(Mask);
|
|
||||||
int l1= (p1 - Mask);
|
|
||||||
pstring tmp;
|
|
||||||
pstrcpy(tmp,Mask);
|
|
||||||
memset(tmp+l1,'?',lfill);
|
|
||||||
pstrcpy(tmp + l1 + lfill,Mask + l1 + 1);
|
|
||||||
pstrcpy(Mask,tmp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
expand a wildcard expression, replacing *s with ?s
|
|
||||||
****************************************************************************/
|
|
||||||
void expand_mask(char *Mask,BOOL doext)
|
|
||||||
{
|
|
||||||
pstring mbeg,mext;
|
|
||||||
pstring dirpart;
|
|
||||||
pstring filepart;
|
|
||||||
BOOL hasdot = False;
|
|
||||||
char *p1;
|
|
||||||
BOOL absolute = (*Mask == '\\');
|
|
||||||
|
|
||||||
*mbeg = *mext = *dirpart = *filepart = 0;
|
|
||||||
|
|
||||||
/* parse the directory and filename */
|
|
||||||
if (strchr(Mask,'\\'))
|
|
||||||
split_at_last_component(Mask,dirpart,'\\',NULL);
|
|
||||||
|
|
||||||
filename_dos(Mask,filepart);
|
|
||||||
|
|
||||||
pstrcpy(mbeg,filepart);
|
|
||||||
if ((p1 = strchr(mbeg,'.')) != NULL)
|
|
||||||
{
|
|
||||||
hasdot = True;
|
|
||||||
*p1 = 0;
|
|
||||||
p1++;
|
|
||||||
pstrcpy(mext,p1);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
pstrcpy(mext,"");
|
|
||||||
if (strlen(mbeg) > 8)
|
|
||||||
{
|
|
||||||
pstrcpy(mext,mbeg + 8);
|
|
||||||
mbeg[8] = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (*mbeg == 0)
|
|
||||||
pstrcpy(mbeg,"????????");
|
|
||||||
if ((*mext == 0) && doext && !hasdot)
|
|
||||||
pstrcpy(mext,"???");
|
|
||||||
|
|
||||||
if (strequal(mbeg,"*") && *mext==0)
|
|
||||||
pstrcpy(mext,"*");
|
|
||||||
|
|
||||||
/* expand *'s */
|
|
||||||
expand_one(mbeg,8);
|
|
||||||
if (*mext)
|
|
||||||
expand_one(mext,3);
|
|
||||||
|
|
||||||
pstrcpy(Mask,dirpart);
|
|
||||||
if (*dirpart || absolute) pstrcat(Mask,"\\");
|
|
||||||
pstrcat(Mask,mbeg);
|
|
||||||
pstrcat(Mask,".");
|
|
||||||
pstrcat(Mask,mext);
|
|
||||||
|
|
||||||
DEBUG(6,("Mask expanded to [%s]\n",Mask));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
make a dir struct
|
make a dir struct
|
||||||
@@ -818,502 +736,6 @@ void msleep(int t)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*********************************************************
|
|
||||||
* Recursive routine that is called by unix_mask_match.
|
|
||||||
* Does the actual matching. This is the 'original code'
|
|
||||||
* used by the unix matcher.
|
|
||||||
*********************************************************/
|
|
||||||
|
|
||||||
BOOL unix_do_match(char *str, char *regexp, BOOL case_sig)
|
|
||||||
{
|
|
||||||
char *p;
|
|
||||||
|
|
||||||
for( p = regexp; *p && *str; ) {
|
|
||||||
switch(*p) {
|
|
||||||
case '?':
|
|
||||||
str++; p++;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case '*':
|
|
||||||
/*
|
|
||||||
* Look for a character matching
|
|
||||||
* the one after the '*'.
|
|
||||||
*/
|
|
||||||
p++;
|
|
||||||
if(!*p)
|
|
||||||
return True; /* Automatic match */
|
|
||||||
while(*str) {
|
|
||||||
|
|
||||||
while(*str && (case_sig ? (*p != *str) : (toupper(*p)!=toupper(*str))))
|
|
||||||
str++;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Patch from weidel@multichart.de. In the case of the regexp
|
|
||||||
* '*XX*' we want to ensure there are at least 2 'X' characters
|
|
||||||
* in the filename after the '*' for a match to be made.
|
|
||||||
*/
|
|
||||||
|
|
||||||
{
|
|
||||||
int matchcount=0;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Eat all the characters that match, but count how many there were.
|
|
||||||
*/
|
|
||||||
|
|
||||||
while(*str && (case_sig ? (*p == *str) : (toupper(*p)==toupper(*str)))) {
|
|
||||||
str++;
|
|
||||||
matchcount++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Now check that if the regexp had n identical characters that
|
|
||||||
* matchcount had at least that many matches.
|
|
||||||
*/
|
|
||||||
|
|
||||||
while (( *(p+1) && (case_sig ? (*(p+1) == *p) : (toupper(*(p+1))==toupper(*p))))) {
|
|
||||||
p++;
|
|
||||||
matchcount--;
|
|
||||||
}
|
|
||||||
if ( matchcount <= 0 ) {
|
|
||||||
return False;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
str--; /* We've eaten the match char after the '*' */
|
|
||||||
if(unix_do_match(str,p,case_sig))
|
|
||||||
return True;
|
|
||||||
if(!*str)
|
|
||||||
return False;
|
|
||||||
else
|
|
||||||
str++;
|
|
||||||
}
|
|
||||||
return False;
|
|
||||||
|
|
||||||
default:
|
|
||||||
if(case_sig) {
|
|
||||||
if(*str != *p)
|
|
||||||
return False;
|
|
||||||
} else {
|
|
||||||
if(toupper(*str) != toupper(*p))
|
|
||||||
return False;
|
|
||||||
}
|
|
||||||
str++, p++;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!*p && !*str)
|
|
||||||
return True;
|
|
||||||
|
|
||||||
if (!*p && str[0] == '.' && str[1] == 0)
|
|
||||||
return(True);
|
|
||||||
|
|
||||||
if (!*str && *p == '?')
|
|
||||||
{
|
|
||||||
while (*p == '?') p++;
|
|
||||||
return(!*p);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!*str && (*p == '*' && p[1] == '\0'))
|
|
||||||
return True;
|
|
||||||
return False;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*********************************************************
|
|
||||||
* Routine to match a given string with a regexp - uses
|
|
||||||
* simplified regexp that takes * and ? only. Case can be
|
|
||||||
* significant or not.
|
|
||||||
* This is the 'original code' used by the unix matcher.
|
|
||||||
*********************************************************/
|
|
||||||
|
|
||||||
static BOOL unix_mask_match(char *str, char *regexp, BOOL case_sig)
|
|
||||||
{
|
|
||||||
char *p;
|
|
||||||
pstring p1, p2;
|
|
||||||
fstring ebase,sbase;
|
|
||||||
BOOL matched;
|
|
||||||
|
|
||||||
/* Make local copies of str and regexp */
|
|
||||||
StrnCpy(p1,regexp,sizeof(pstring)-1);
|
|
||||||
StrnCpy(p2,str,sizeof(pstring)-1);
|
|
||||||
|
|
||||||
/* Remove any *? and ** as they are meaningless */
|
|
||||||
for(p = p1; *p; p++)
|
|
||||||
while( *p == '*' && (p[1] == '?' ||p[1] == '*'))
|
|
||||||
(void)pstrcpy( &p[1], &p[2]);
|
|
||||||
|
|
||||||
if (strequal(p1,"*")) return(True);
|
|
||||||
|
|
||||||
DEBUG(8,("unix_mask_match str=<%s> regexp=<%s>, case_sig = %d\n", p2, p1, case_sig));
|
|
||||||
|
|
||||||
fstrcpy(ebase,p1);
|
|
||||||
fstrcpy(sbase,p2);
|
|
||||||
|
|
||||||
matched = unix_do_match(sbase,ebase,case_sig);
|
|
||||||
|
|
||||||
DEBUG(8,("unix_mask_match returning %d\n", matched));
|
|
||||||
|
|
||||||
return matched;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*********************************************************
|
|
||||||
* Recursive routine that is called by mask_match.
|
|
||||||
* Does the actual matching. Returns True if matched,
|
|
||||||
* False if failed. This is the 'new' NT style matcher.
|
|
||||||
* The win9x_semantics parameter is needed as Win9x matching
|
|
||||||
* is *actually different*. In Win9x, trailing '?' characters
|
|
||||||
* will only match the *exact* number of characters. Under
|
|
||||||
* DOS and NT they match any number. This makes no
|
|
||||||
* sense.....
|
|
||||||
*********************************************************/
|
|
||||||
|
|
||||||
static BOOL do_match(char *str, char *regexp, int case_sig, BOOL win9x_semantics)
|
|
||||||
{
|
|
||||||
char *p;
|
|
||||||
|
|
||||||
for( p = regexp; *p && *str; ) {
|
|
||||||
switch(*p) {
|
|
||||||
case '?':
|
|
||||||
str++; p++;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case '*':
|
|
||||||
/* Look for a character matching
|
|
||||||
the one after the '*' */
|
|
||||||
p++;
|
|
||||||
if(!*p)
|
|
||||||
return True; /* Automatic match */
|
|
||||||
while(*str) {
|
|
||||||
while(*str && (case_sig ? (*p != *str) : (toupper(*p)!=toupper(*str))))
|
|
||||||
str++;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Patch from weidel@multichart.de. In the case of the regexp
|
|
||||||
* '*XX*' we want to ensure there are at least 2 'X' characters
|
|
||||||
* in the filename after the '*' for a match to be made.
|
|
||||||
*/
|
|
||||||
|
|
||||||
{
|
|
||||||
int matchcount=0;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Eat all the characters that match, but count how many there were.
|
|
||||||
*/
|
|
||||||
|
|
||||||
while(*str && (case_sig ? (*p == *str) : (toupper(*p)==toupper(*str)))) {
|
|
||||||
str++;
|
|
||||||
matchcount++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Now check that if the regexp had n identical characters that
|
|
||||||
* matchcount had at least that many matches.
|
|
||||||
*/
|
|
||||||
|
|
||||||
while (( *(p+1) && (case_sig ? (*(p+1) == *p) : (toupper(*(p+1))==toupper(*p))))) {
|
|
||||||
p++;
|
|
||||||
matchcount--;
|
|
||||||
}
|
|
||||||
if ( matchcount <= 0 ) {
|
|
||||||
return False;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
str--; /* We've eaten the match char after the '*' */
|
|
||||||
if(do_match(str,p,case_sig,win9x_semantics)) {
|
|
||||||
return True;
|
|
||||||
}
|
|
||||||
if(!*str) {
|
|
||||||
return False;
|
|
||||||
} else {
|
|
||||||
str++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return False;
|
|
||||||
|
|
||||||
default:
|
|
||||||
if(case_sig) {
|
|
||||||
if(*str != *p) {
|
|
||||||
return False;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if(toupper(*str) != toupper(*p)) {
|
|
||||||
return False;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
str++, p++;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!*p && !*str)
|
|
||||||
return True;
|
|
||||||
|
|
||||||
if (!*p && str[0] == '.' && str[1] == 0) {
|
|
||||||
return(True);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!win9x_semantics) {
|
|
||||||
if (!*str && *p == '?') {
|
|
||||||
while (*p == '?')
|
|
||||||
p++;
|
|
||||||
return(!*p);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!*str && (*p == '*' && p[1] == '\0')) {
|
|
||||||
return True;
|
|
||||||
}
|
|
||||||
|
|
||||||
return False;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*********************************************************
|
|
||||||
* Routine to match a given string with a regexp - uses
|
|
||||||
* simplified regexp that takes * and ? only. Case can be
|
|
||||||
* significant or not.
|
|
||||||
* The 8.3 handling was rewritten by Ums Harald <Harald.Ums@pro-sieben.de>
|
|
||||||
* This is the new 'NT style' matcher.
|
|
||||||
*********************************************************/
|
|
||||||
|
|
||||||
BOOL mask_match(char *str, char *regexp, BOOL case_sig, BOOL trans2)
|
|
||||||
{
|
|
||||||
char *p;
|
|
||||||
pstring t_pattern, t_filename, te_pattern, te_filename;
|
|
||||||
fstring ebase,eext,sbase,sext;
|
|
||||||
BOOL matched = False;
|
|
||||||
BOOL win9x_semantics = (get_remote_arch() == RA_WIN95) && trans2;
|
|
||||||
|
|
||||||
/* special case - if it is exactly the same then it always matches! */
|
|
||||||
if(exact_match(str, regexp, case_sig))
|
|
||||||
return True;
|
|
||||||
|
|
||||||
/* Make local copies of str and regexp */
|
|
||||||
pstrcpy(t_pattern,regexp);
|
|
||||||
pstrcpy(t_filename,str);
|
|
||||||
|
|
||||||
if(trans2) {
|
|
||||||
|
|
||||||
/* a special case for 16 bit apps */
|
|
||||||
if (strequal(t_pattern,"????????.???"))
|
|
||||||
pstrcpy(t_pattern,"*");
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
/*
|
|
||||||
* Handle broken clients that send us old 8.3 format.
|
|
||||||
*/
|
|
||||||
pstring_sub(t_pattern,"????????","*");
|
|
||||||
pstring_sub(t_pattern,".???",".*");
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
/*
|
|
||||||
* Not sure if this is a good idea. JRA.
|
|
||||||
*/
|
|
||||||
if(trans2 && is_8_3(t_pattern,False) && is_8_3(t_filename,False))
|
|
||||||
trans2 = False;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
if (!strchr(t_filename,'.')) {
|
|
||||||
pstrcat(t_filename,".");
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Remove any *? and ** as they are meaningless */
|
|
||||||
for(p = t_pattern; *p; p++)
|
|
||||||
while( *p == '*' && (p[1] == '?' || p[1] == '*'))
|
|
||||||
(void)pstrcpy( &p[1], &p[2]);
|
|
||||||
|
|
||||||
if (strequal(t_pattern,"*"))
|
|
||||||
return(True);
|
|
||||||
|
|
||||||
DEBUG(8,("mask_match str=<%s> regexp=<%s>, case_sig = %d\n", t_filename, t_pattern, case_sig));
|
|
||||||
|
|
||||||
if(trans2) {
|
|
||||||
/*
|
|
||||||
* Match each component of the regexp, split up by '.'
|
|
||||||
* characters.
|
|
||||||
*/
|
|
||||||
char *fp, *rp, *cp2, *cp1;
|
|
||||||
BOOL last_wcard_was_star = False;
|
|
||||||
int num_path_components, num_regexp_components;
|
|
||||||
|
|
||||||
pstrcpy(te_pattern,t_pattern);
|
|
||||||
pstrcpy(te_filename,t_filename);
|
|
||||||
/*
|
|
||||||
* Remove multiple "*." patterns.
|
|
||||||
*/
|
|
||||||
pstring_sub(te_pattern, "*.*.", "*.");
|
|
||||||
num_regexp_components = count_chars(te_pattern, '.');
|
|
||||||
num_path_components = count_chars(te_filename, '.');
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Check for special 'hack' case of "DIR a*z". - needs to match a.b.c...z
|
|
||||||
*/
|
|
||||||
if(num_regexp_components == 0)
|
|
||||||
matched = do_match( te_filename, te_pattern, case_sig, win9x_semantics);
|
|
||||||
else {
|
|
||||||
for( cp1 = te_pattern, cp2 = te_filename; cp1;) {
|
|
||||||
fp = strchr(cp2, '.');
|
|
||||||
if(fp)
|
|
||||||
*fp = '\0';
|
|
||||||
rp = strchr(cp1, '.');
|
|
||||||
if(rp)
|
|
||||||
*rp = '\0';
|
|
||||||
|
|
||||||
if(cp1[0] && cp1[strlen(cp1)-1] == '*')
|
|
||||||
last_wcard_was_star = True;
|
|
||||||
else
|
|
||||||
last_wcard_was_star = False;
|
|
||||||
|
|
||||||
if(!do_match(cp2, cp1, case_sig, win9x_semantics))
|
|
||||||
break;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Ugly ! Special case for Win9x *only*. If filename is XXXX and pattern extension
|
|
||||||
* is '*' or all '?' then disallow match.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (win9x_semantics) {
|
|
||||||
if (*cp2 == '\0' && str_is_all(cp1, '?'))
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
cp1 = rp ? rp + 1 : NULL;
|
|
||||||
cp2 = fp ? fp + 1 : "";
|
|
||||||
|
|
||||||
if(last_wcard_was_star || ((cp1 != NULL) && (*cp1 == '*'))) {
|
|
||||||
/* Eat the extra path components. */
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for(i = 0; i < num_path_components - num_regexp_components; i++) {
|
|
||||||
fp = strchr(cp2, '.');
|
|
||||||
if(fp)
|
|
||||||
*fp = '\0';
|
|
||||||
|
|
||||||
if((cp1 != NULL) && do_match( cp2, cp1, case_sig, win9x_semantics)) {
|
|
||||||
cp2 = fp ? fp + 1 : "";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
cp2 = fp ? fp + 1 : "";
|
|
||||||
}
|
|
||||||
num_path_components -= i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(cp1 == NULL && ((*cp2 == '\0') || last_wcard_was_star))
|
|
||||||
matched = True;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
|
|
||||||
/* -------------------------------------------------
|
|
||||||
* Behaviour of Win95
|
|
||||||
* for 8.3 filenames and 8.3 Wildcards
|
|
||||||
* -------------------------------------------------
|
|
||||||
*/
|
|
||||||
if (strequal (t_filename, ".")) {
|
|
||||||
/*
|
|
||||||
* Patterns: *.* *. ?. ? ????????.??? are valid.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
if(strequal(t_pattern, "*.*") || strequal(t_pattern, "*.") ||
|
|
||||||
strequal(t_pattern, "????????.???") ||
|
|
||||||
strequal(t_pattern, "?.") || strequal(t_pattern, "?"))
|
|
||||||
matched = True;
|
|
||||||
} else if (strequal (t_filename, "..")) {
|
|
||||||
/*
|
|
||||||
* Patterns: *.* *. ?. ? *.? ????????.??? are valid.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
if(strequal(t_pattern, "*.*") || strequal(t_pattern, "*.") ||
|
|
||||||
strequal(t_pattern, "?.") || strequal(t_pattern, "?") ||
|
|
||||||
strequal(t_pattern, "????????.???") ||
|
|
||||||
strequal(t_pattern, "*.?") || strequal(t_pattern, "?.*"))
|
|
||||||
matched = True;
|
|
||||||
} else {
|
|
||||||
|
|
||||||
if ((p = strrchr (t_pattern, '.'))) {
|
|
||||||
/*
|
|
||||||
* Wildcard has a suffix.
|
|
||||||
*/
|
|
||||||
*p = 0;
|
|
||||||
fstrcpy (ebase, t_pattern);
|
|
||||||
if (p[1]) {
|
|
||||||
fstrcpy (eext, p + 1);
|
|
||||||
} else {
|
|
||||||
/* pattern ends in DOT: treat as if there is no DOT */
|
|
||||||
*eext = 0;
|
|
||||||
if (strequal (ebase, "*"))
|
|
||||||
return (True);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
/*
|
|
||||||
* No suffix for wildcard.
|
|
||||||
*/
|
|
||||||
fstrcpy (ebase, t_pattern);
|
|
||||||
eext[0] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
p = strrchr (t_filename, '.');
|
|
||||||
if (p && (p[1] == 0) ) {
|
|
||||||
/*
|
|
||||||
* Filename has an extension of '.' only.
|
|
||||||
*/
|
|
||||||
*p = 0; /* nuke dot at end of string */
|
|
||||||
p = 0; /* and treat it as if there is no extension */
|
|
||||||
}
|
|
||||||
|
|
||||||
if (p) {
|
|
||||||
/*
|
|
||||||
* Filename has an extension.
|
|
||||||
*/
|
|
||||||
*p = 0;
|
|
||||||
fstrcpy (sbase, t_filename);
|
|
||||||
fstrcpy (sext, p + 1);
|
|
||||||
if (*eext) {
|
|
||||||
matched = do_match(sbase, ebase, case_sig, False)
|
|
||||||
&& do_match(sext, eext, case_sig, False);
|
|
||||||
} else {
|
|
||||||
/* pattern has no extension */
|
|
||||||
/* Really: match complete filename with pattern ??? means exactly 3 chars */
|
|
||||||
matched = do_match(str, ebase, case_sig, False);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
/*
|
|
||||||
* Filename has no extension.
|
|
||||||
*/
|
|
||||||
fstrcpy (sbase, t_filename);
|
|
||||||
fstrcpy (sext, "");
|
|
||||||
if (*eext) {
|
|
||||||
/* pattern has extension */
|
|
||||||
matched = do_match(sbase, ebase, case_sig, False)
|
|
||||||
&& do_match(sext, eext, case_sig, False);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
matched = do_match(sbase, ebase, case_sig, False);
|
|
||||||
#ifdef EMULATE_WEIRD_W95_MATCHING
|
|
||||||
/*
|
|
||||||
* Even Microsoft has some problems
|
|
||||||
* Behaviour Win95 -> local disk
|
|
||||||
* is different from Win95 -> smb drive from Nt 4.0
|
|
||||||
* This branch would reflect the Win95 local disk behaviour
|
|
||||||
*/
|
|
||||||
if (!matched) {
|
|
||||||
/* a? matches aa and a in w95 */
|
|
||||||
fstrcat (sbase, ".");
|
|
||||||
matched = do_match(sbase, ebase, case_sig, False);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DEBUG(8,("mask_match returning %d\n", matched));
|
|
||||||
|
|
||||||
return matched;
|
|
||||||
}
|
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
become a daemon, discarding the controlling terminal
|
become a daemon, discarding the controlling terminal
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
@@ -1419,24 +841,6 @@ this is a version of setbuffer() for those machines that only have setvbuf
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
parse out a filename from a path name. Assumes dos style filenames.
|
|
||||||
****************************************************************************/
|
|
||||||
static char *filename_dos(char *path,char *buf)
|
|
||||||
{
|
|
||||||
char *p = strrchr(path,'\\');
|
|
||||||
|
|
||||||
if (!p)
|
|
||||||
pstrcpy(buf,path);
|
|
||||||
else
|
|
||||||
pstrcpy(buf,p+1);
|
|
||||||
|
|
||||||
return(buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
expand a pointer to be a particular size
|
expand a pointer to be a particular size
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
@@ -1961,12 +1365,7 @@ BOOL is_in_path(char *name, name_compare_entry *namelist)
|
|||||||
{
|
{
|
||||||
if(namelist->is_wild)
|
if(namelist->is_wild)
|
||||||
{
|
{
|
||||||
/*
|
if (mask_match(last_component, namelist->name, case_sensitive))
|
||||||
* Look for a wildcard match. Use the old
|
|
||||||
* 'unix style' mask match, rather than the
|
|
||||||
* new NT one.
|
|
||||||
*/
|
|
||||||
if (unix_mask_match(last_component, namelist->name, case_sensitive))
|
|
||||||
{
|
{
|
||||||
DEBUG(8,("is_in_path: mask match succeeded\n"));
|
DEBUG(8,("is_in_path: mask match succeeded\n"));
|
||||||
return True;
|
return True;
|
||||||
@@ -2067,8 +1466,7 @@ void set_namearray(name_compare_entry **ppname_array, char *namelist)
|
|||||||
if(name_end == NULL)
|
if(name_end == NULL)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
(*ppname_array)[i].is_wild = ((strchr( nameptr, '?')!=NULL) ||
|
(*ppname_array)[i].is_wild = ms_has_wild(nameptr);
|
||||||
(strchr( nameptr, '*')!=NULL));
|
|
||||||
if(((*ppname_array)[i].name = strdup(nameptr)) == NULL)
|
if(((*ppname_array)[i].name = strdup(nameptr)) == NULL)
|
||||||
{
|
{
|
||||||
DEBUG(0,("set_namearray: malloc fail (1)\n"));
|
DEBUG(0,("set_namearray: malloc fail (1)\n"));
|
||||||
@@ -2653,7 +2051,58 @@ char *parent_dirname(const char *path)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************
|
||||||
|
determine if a pattern contains any Microsoft wildcard characters
|
||||||
|
*******************************************************************/
|
||||||
|
BOOL ms_has_wild(char *s)
|
||||||
|
{
|
||||||
|
char c;
|
||||||
|
while ((c = *s++)) {
|
||||||
|
switch (c) {
|
||||||
|
case '*':
|
||||||
|
case '?':
|
||||||
|
case '<':
|
||||||
|
case '>':
|
||||||
|
case '"':
|
||||||
|
return True;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return False;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************
|
||||||
|
a wrapper that handles case sensitivity and the special handling
|
||||||
|
of the ".." name
|
||||||
|
|
||||||
|
case_sensitive is a boolean
|
||||||
|
*******************************************************************/
|
||||||
|
BOOL mask_match(char *string, char *pattern, BOOL case_sensitive)
|
||||||
|
{
|
||||||
|
fstring p2, s2;
|
||||||
|
if (strcmp(string,"..") == 0) string = ".";
|
||||||
|
if (strcmp(pattern,".") == 0) return False;
|
||||||
|
|
||||||
|
if (case_sensitive) {
|
||||||
|
return ms_fnmatch(pattern, string) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
fstrcpy(p2, pattern);
|
||||||
|
fstrcpy(s2, string);
|
||||||
|
strlower(p2);
|
||||||
|
strlower(s2);
|
||||||
|
return ms_fnmatch(p2, s2) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __INSURE__
|
#ifdef __INSURE__
|
||||||
|
|
||||||
|
/*******************************************************************
|
||||||
|
This routine is a trick to immediately catch errors when debugging
|
||||||
|
with insure. A xterm with a gdb is popped up when insure catches
|
||||||
|
a error. It is Linux specific.
|
||||||
|
********************************************************************/
|
||||||
int _Insure_trap_error(int a1, int a2, int a3, int a4, int a5, int a6)
|
int _Insure_trap_error(int a1, int a2, int a3, int a4, int a5, int a6)
|
||||||
{
|
{
|
||||||
static int (*fn)();
|
static int (*fn)();
|
||||||
|
|||||||
@@ -84,52 +84,45 @@ int dos_PutUniCode(char *dst,const char *src, ssize_t len, BOOL null_terminate)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*******************************************************************
|
/*******************************************************************
|
||||||
Put an ASCII string into a UNICODE array (uint16's).
|
Put an ASCII string into a UNICODE string.
|
||||||
|
|
||||||
Warning: doesn't do any codepage !!! BAD !!!
|
Warning: doesn't do any codepage !!! BAD !!!
|
||||||
|
|
||||||
Help ! Fix Me ! Fix Me !
|
Help ! Fix Me ! Fix Me !
|
||||||
********************************************************************/
|
********************************************************************/
|
||||||
|
|
||||||
void ascii_to_unistr(uint16 *dest, const char *src, int maxlen)
|
void ascii_to_unistr(char *dest, const char *src, int maxlen)
|
||||||
{
|
{
|
||||||
uint16 *destend = dest + maxlen;
|
char *destend = dest + maxlen;
|
||||||
register char c;
|
char c;
|
||||||
|
|
||||||
while (dest < destend)
|
while (dest < destend) {
|
||||||
{
|
|
||||||
c = *(src++);
|
c = *(src++);
|
||||||
if (c == 0)
|
if (c == 0) break;
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
*(dest++) = (uint16)c;
|
SSVAL(dest, 0, (uint16)c);
|
||||||
|
dest += 2;
|
||||||
}
|
}
|
||||||
|
SSVAL(dest, 0, 0);
|
||||||
*dest = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*******************************************************************
|
/*******************************************************************
|
||||||
Pull an ASCII string out of a UNICODE array (uint16's).
|
Pull an ASCII string out of a UNICODE array .
|
||||||
|
|
||||||
Warning: doesn't do any codepage !!! BAD !!!
|
Warning: doesn't do any codepage !!! BAD !!!
|
||||||
|
|
||||||
Help ! Fix Me ! Fix Me !
|
Help ! Fix Me ! Fix Me !
|
||||||
********************************************************************/
|
********************************************************************/
|
||||||
|
|
||||||
void unistr_to_ascii(char *dest, const uint16 *src, int len)
|
void unistr_to_ascii(char *dest, char *src, int len)
|
||||||
{
|
{
|
||||||
char *destend = dest + len;
|
char *destend = dest + len;
|
||||||
register uint16 c;
|
uint16 c;
|
||||||
|
|
||||||
while (dest < destend)
|
while (dest < destend) {
|
||||||
{
|
c = SVAL(src, 0);
|
||||||
c = *(src++);
|
src += 2;
|
||||||
if (c == 0)
|
if (c == 0) break;
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
*(dest++) = (char)c;
|
*(dest++) = (char)c;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -999,7 +999,7 @@ BOOL release_posix_lock(files_struct *fsp, SMB_BIG_UINT u_offset, SMB_BIG_UINT u
|
|||||||
ret = False;
|
ret = False;
|
||||||
}
|
}
|
||||||
|
|
||||||
talloc_destroy(ul_ctx);
|
talloc_destroy(ul_ctx);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@@ -1020,7 +1020,7 @@ static void delete_posix_lock_entries(files_struct *fsp)
|
|||||||
Debug function.
|
Debug function.
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
void dump_entry(struct posix_lock *pl)
|
static void dump_entry(struct posix_lock *pl)
|
||||||
{
|
{
|
||||||
DEBUG(10,("entry: start=%.0f, size=%.0f, type=%d, fd=%i\n",
|
DEBUG(10,("entry: start=%.0f, size=%.0f, type=%d, fd=%i\n",
|
||||||
(double)pl->start, (double)pl->size, (int)pl->lock_type, pl->fd ));
|
(double)pl->start, (double)pl->size, (int)pl->lock_type, pl->fd ));
|
||||||
|
|||||||
@@ -249,7 +249,7 @@ static int expect(int master, char *issue, char *expected)
|
|||||||
nread += len;
|
nread += len;
|
||||||
buffer[nread] = 0;
|
buffer[nread] = 0;
|
||||||
|
|
||||||
if ((match = unix_do_match(buffer, expected, False)))
|
if ((match = (ms_fnmatch(expected, buffer) == 0)))
|
||||||
timeout = 200;
|
timeout = 200;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -604,7 +604,7 @@ BOOL get_dir_entry(connection_struct *conn,char *mask,int dirtype,char *fname,
|
|||||||
|
|
||||||
if ((filename_is_mask = (strcmp(filename,mask) == 0)) ||
|
if ((filename_is_mask = (strcmp(filename,mask) == 0)) ||
|
||||||
(name_map_mangle(filename,True,False,SNUM(conn)) &&
|
(name_map_mangle(filename,True,False,SNUM(conn)) &&
|
||||||
mask_match(filename,mask,False,False)))
|
mask_match(filename,mask,False)))
|
||||||
{
|
{
|
||||||
if (isrootdir && (strequal(filename,"..") || strequal(filename,".")))
|
if (isrootdir && (strequal(filename,"..") || strequal(filename,".")))
|
||||||
continue;
|
continue;
|
||||||
|
|||||||
@@ -88,228 +88,6 @@ static BOOL mangled_equal(char *name1, char *name2)
|
|||||||
return(strequal(name1,tmpname));
|
return(strequal(name1,tmpname));
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
Stat cache code used in unix_convert.
|
|
||||||
*****************************************************************************/
|
|
||||||
|
|
||||||
static int global_stat_cache_lookups;
|
|
||||||
static int global_stat_cache_misses;
|
|
||||||
static int global_stat_cache_hits;
|
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
Stat cache statistics code.
|
|
||||||
*****************************************************************************/
|
|
||||||
|
|
||||||
void print_stat_cache_statistics(void)
|
|
||||||
{
|
|
||||||
double eff;
|
|
||||||
|
|
||||||
if(global_stat_cache_lookups == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
eff = (100.0* (double)global_stat_cache_hits)/(double)global_stat_cache_lookups;
|
|
||||||
|
|
||||||
DEBUG(0,("stat cache stats: lookups = %d, hits = %d, misses = %d, \
|
|
||||||
stat cache was %f%% effective.\n", global_stat_cache_lookups,
|
|
||||||
global_stat_cache_hits, global_stat_cache_misses, eff ));
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
int name_len;
|
|
||||||
char names[2]; /* This is extended via malloc... */
|
|
||||||
} stat_cache_entry;
|
|
||||||
|
|
||||||
#define INIT_STAT_CACHE_SIZE 512
|
|
||||||
static hash_table stat_cache;
|
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
Compare a pathname to a name in the stat cache - of a given length.
|
|
||||||
Note - this code always checks that the next character in the pathname
|
|
||||||
is either a '/' character, or a '\0' character - to ensure we only
|
|
||||||
match *full* pathname components. Note we don't need to handle case
|
|
||||||
here, if we're case insensitive the stat cache orig names are all upper
|
|
||||||
case.
|
|
||||||
*****************************************************************************/
|
|
||||||
|
|
||||||
#if 0 /* This function unused?? */
|
|
||||||
static BOOL stat_name_equal_len( char *stat_name, char *orig_name, int len)
|
|
||||||
{
|
|
||||||
BOOL matched = (memcmp( stat_name, orig_name, len) == 0);
|
|
||||||
if(orig_name[len] != '/' && orig_name[len] != '\0')
|
|
||||||
return False;
|
|
||||||
|
|
||||||
return matched;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
Add an entry into the stat cache.
|
|
||||||
*****************************************************************************/
|
|
||||||
|
|
||||||
static void stat_cache_add( char *full_orig_name, char *orig_translated_path)
|
|
||||||
{
|
|
||||||
stat_cache_entry *scp;
|
|
||||||
stat_cache_entry *found_scp;
|
|
||||||
pstring orig_name;
|
|
||||||
pstring translated_path;
|
|
||||||
int namelen;
|
|
||||||
hash_element *hash_elem;
|
|
||||||
|
|
||||||
if (!lp_stat_cache()) return;
|
|
||||||
|
|
||||||
namelen = strlen(orig_translated_path);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Don't cache trivial valid directory entries.
|
|
||||||
*/
|
|
||||||
if((*full_orig_name == '\0') || (strcmp(full_orig_name, ".") == 0) ||
|
|
||||||
(strcmp(full_orig_name, "..") == 0))
|
|
||||||
return;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If we are in case insentive mode, we need to
|
|
||||||
* store names that need no translation - else, it
|
|
||||||
* would be a waste.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if(case_sensitive && (strcmp(full_orig_name, orig_translated_path) == 0))
|
|
||||||
return;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Remove any trailing '/' characters from the
|
|
||||||
* translated path.
|
|
||||||
*/
|
|
||||||
|
|
||||||
pstrcpy(translated_path, orig_translated_path);
|
|
||||||
if(translated_path[namelen-1] == '/') {
|
|
||||||
translated_path[namelen-1] = '\0';
|
|
||||||
namelen--;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* We will only replace namelen characters
|
|
||||||
* of full_orig_name.
|
|
||||||
* StrnCpy always null terminates.
|
|
||||||
*/
|
|
||||||
|
|
||||||
StrnCpy(orig_name, full_orig_name, namelen);
|
|
||||||
if(!case_sensitive)
|
|
||||||
strupper( orig_name );
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Check this name doesn't exist in the cache before we
|
|
||||||
* add it.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if ((hash_elem = hash_lookup(&stat_cache, orig_name))) {
|
|
||||||
found_scp = (stat_cache_entry *)(hash_elem->value);
|
|
||||||
if (strcmp((found_scp->names+found_scp->name_len+1), translated_path) == 0) {
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
hash_remove(&stat_cache, hash_elem);
|
|
||||||
if((scp = (stat_cache_entry *)malloc(sizeof(stat_cache_entry)+2*namelen)) == NULL) {
|
|
||||||
DEBUG(0,("stat_cache_add: Out of memory !\n"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
pstrcpy(scp->names, orig_name);
|
|
||||||
pstrcpy((scp->names+namelen+1), translated_path);
|
|
||||||
scp->name_len = namelen;
|
|
||||||
hash_insert(&stat_cache, (char *)scp, orig_name);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
|
|
||||||
/*
|
|
||||||
* New entry.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if((scp = (stat_cache_entry *)malloc(sizeof(stat_cache_entry)+2*namelen)) == NULL) {
|
|
||||||
DEBUG(0,("stat_cache_add: Out of memory !\n"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
pstrcpy(scp->names, orig_name);
|
|
||||||
pstrcpy(scp->names+namelen+1, translated_path);
|
|
||||||
scp->name_len = namelen;
|
|
||||||
hash_insert(&stat_cache, (char *)scp, orig_name);
|
|
||||||
}
|
|
||||||
|
|
||||||
DEBUG(5,("stat_cache_add: Added entry %s -> %s\n", scp->names, (scp->names+scp->name_len+1)));
|
|
||||||
}
|
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
Look through the stat cache for an entry - promote it to the top if found.
|
|
||||||
Return True if we translated (and did a scuccessful stat on) the entire name.
|
|
||||||
*****************************************************************************/
|
|
||||||
|
|
||||||
static BOOL stat_cache_lookup(connection_struct *conn, char *name, char *dirpath,
|
|
||||||
char **start, SMB_STRUCT_STAT *pst)
|
|
||||||
{
|
|
||||||
stat_cache_entry *scp;
|
|
||||||
char *trans_name;
|
|
||||||
pstring chk_name;
|
|
||||||
int namelen;
|
|
||||||
hash_element *hash_elem;
|
|
||||||
char *sp;
|
|
||||||
|
|
||||||
if (!lp_stat_cache())
|
|
||||||
return False;
|
|
||||||
|
|
||||||
namelen = strlen(name);
|
|
||||||
|
|
||||||
*start = name;
|
|
||||||
global_stat_cache_lookups++;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Don't lookup trivial valid directory entries.
|
|
||||||
*/
|
|
||||||
if((*name == '\0') || (strcmp(name, ".") == 0) || (strcmp(name, "..") == 0)) {
|
|
||||||
global_stat_cache_misses++;
|
|
||||||
return False;
|
|
||||||
}
|
|
||||||
|
|
||||||
pstrcpy(chk_name, name);
|
|
||||||
if(!case_sensitive)
|
|
||||||
strupper( chk_name );
|
|
||||||
|
|
||||||
while (1) {
|
|
||||||
hash_elem = hash_lookup(&stat_cache, chk_name);
|
|
||||||
if(hash_elem == NULL) {
|
|
||||||
/*
|
|
||||||
* Didn't find it - remove last component for next try.
|
|
||||||
*/
|
|
||||||
sp = strrchr(chk_name, '/');
|
|
||||||
if (sp) {
|
|
||||||
*sp = '\0';
|
|
||||||
} else {
|
|
||||||
/*
|
|
||||||
* We reached the end of the name - no match.
|
|
||||||
*/
|
|
||||||
global_stat_cache_misses++;
|
|
||||||
return False;
|
|
||||||
}
|
|
||||||
if((*chk_name == '\0') || (strcmp(chk_name, ".") == 0)
|
|
||||||
|| (strcmp(chk_name, "..") == 0)) {
|
|
||||||
global_stat_cache_misses++;
|
|
||||||
return False;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
scp = (stat_cache_entry *)(hash_elem->value);
|
|
||||||
global_stat_cache_hits++;
|
|
||||||
trans_name = scp->names+scp->name_len+1;
|
|
||||||
if(conn->vfs_ops.stat(dos_to_unix(trans_name,False), pst) != 0) {
|
|
||||||
/* Discard this entry - it doesn't exist in the filesystem. */
|
|
||||||
hash_remove(&stat_cache, hash_elem);
|
|
||||||
return False;
|
|
||||||
}
|
|
||||||
memcpy(name, trans_name, scp->name_len);
|
|
||||||
*start = &name[scp->name_len];
|
|
||||||
if(**start == '/')
|
|
||||||
++*start;
|
|
||||||
StrnCpy( dirpath, trans_name, name - (*start));
|
|
||||||
return (namelen == scp->name_len);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
This routine is called to convert names from the dos namespace to unix
|
This routine is called to convert names from the dos namespace to unix
|
||||||
@@ -406,26 +184,6 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component,
|
|||||||
(!case_preserve || (is_8_3(name, False) && !short_case_preserve)))
|
(!case_preserve || (is_8_3(name, False) && !short_case_preserve)))
|
||||||
strnorm(name);
|
strnorm(name);
|
||||||
|
|
||||||
/*
|
|
||||||
* Check if it's a printer file.
|
|
||||||
*/
|
|
||||||
if (conn->printer) {
|
|
||||||
if ((! *name) || strchr(name,'/') || !is_8_3(name, True)) {
|
|
||||||
char *s;
|
|
||||||
fstring name2;
|
|
||||||
slprintf(name2,sizeof(name2)-1,"%.6s.XXXXXX",remote_machine);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Sanitise the name.
|
|
||||||
*/
|
|
||||||
|
|
||||||
for (s=name2 ; *s ; s++)
|
|
||||||
if (!issafe(*s)) *s = '_';
|
|
||||||
pstrcpy(name,(char *)smbd_mktemp(name2));
|
|
||||||
}
|
|
||||||
return(True);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If we trimmed down to a single '\0' character
|
* If we trimmed down to a single '\0' character
|
||||||
* then we will be using the "." directory.
|
* then we will be using the "." directory.
|
||||||
@@ -471,8 +229,7 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component,
|
|||||||
!lp_strip_dot() && !use_mangled_map)
|
!lp_strip_dot() && !use_mangled_map)
|
||||||
return(False);
|
return(False);
|
||||||
|
|
||||||
if(strchr(start,'?') || strchr(start,'*'))
|
name_has_wildcard = ms_has_wild(start);
|
||||||
name_has_wildcard = True;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* is_mangled() was changed to look at an entire pathname, not
|
* is_mangled() was changed to look at an entire pathname, not
|
||||||
@@ -549,7 +306,7 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component,
|
|||||||
* Try to find this part of the path in the directory.
|
* Try to find this part of the path in the directory.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (strchr(start,'?') || strchr(start,'*') ||
|
if (ms_has_wild(start) ||
|
||||||
!scan_directory(dirpath, start, conn, end?True:False)) {
|
!scan_directory(dirpath, start, conn, end?True:False)) {
|
||||||
if (end) {
|
if (end) {
|
||||||
/*
|
/*
|
||||||
@@ -752,15 +509,3 @@ static BOOL scan_directory(char *path, char *name,connection_struct *conn,BOOL d
|
|||||||
return(False);
|
return(False);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*************************************************************************** **
|
|
||||||
* Initializes or clears the stat cache.
|
|
||||||
*
|
|
||||||
* Input: none.
|
|
||||||
* Output: none.
|
|
||||||
*
|
|
||||||
* ************************************************************************** **
|
|
||||||
*/
|
|
||||||
BOOL reset_stat_cache( void )
|
|
||||||
{
|
|
||||||
return hash_table_init( &stat_cache, INIT_STAT_CACHE_SIZE, (compare_function)(strcmp));
|
|
||||||
} /* reset_stat_cache */
|
|
||||||
|
|||||||
@@ -1331,9 +1331,6 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Convert the formatted mask. (This code lives in trans2.c) */
|
|
||||||
mask_convert(mask);
|
|
||||||
|
|
||||||
{
|
{
|
||||||
int skip;
|
int skip;
|
||||||
p = mask;
|
p = mask;
|
||||||
@@ -1936,7 +1933,7 @@ int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
|
|||||||
if (!rc && is_mangled(mask))
|
if (!rc && is_mangled(mask))
|
||||||
check_mangled_cache( mask );
|
check_mangled_cache( mask );
|
||||||
|
|
||||||
has_wild = strchr(mask,'*') || strchr(mask,'?');
|
has_wild = ms_has_wild(mask);
|
||||||
|
|
||||||
if (!has_wild) {
|
if (!has_wild) {
|
||||||
pstrcat(directory,"/");
|
pstrcat(directory,"/");
|
||||||
@@ -1969,7 +1966,7 @@ int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
|
|||||||
pstring fname;
|
pstring fname;
|
||||||
pstrcpy(fname,dname);
|
pstrcpy(fname,dname);
|
||||||
|
|
||||||
if(!mask_match(fname, mask, case_sensitive, False)) continue;
|
if(!mask_match(fname, mask, case_sensitive)) continue;
|
||||||
|
|
||||||
error = ERRnoaccess;
|
error = ERRnoaccess;
|
||||||
slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
|
slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
|
||||||
@@ -3508,7 +3505,7 @@ int rename_internals(connection_struct *conn,
|
|||||||
if (!rc && is_mangled(mask))
|
if (!rc && is_mangled(mask))
|
||||||
check_mangled_cache( mask );
|
check_mangled_cache( mask );
|
||||||
|
|
||||||
has_wild = strchr(mask,'*') || strchr(mask,'?');
|
has_wild = ms_has_wild(mask);
|
||||||
|
|
||||||
if (!has_wild) {
|
if (!has_wild) {
|
||||||
/*
|
/*
|
||||||
@@ -3618,7 +3615,7 @@ int rename_internals(connection_struct *conn,
|
|||||||
|
|
||||||
pstrcpy(fname,dname);
|
pstrcpy(fname,dname);
|
||||||
|
|
||||||
if(!mask_match(fname, mask, case_sensitive, False))
|
if(!mask_match(fname, mask, case_sensitive))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
error = ERRnoaccess;
|
error = ERRnoaccess;
|
||||||
@@ -3847,7 +3844,7 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
|
|||||||
if (!rc && is_mangled(mask))
|
if (!rc && is_mangled(mask))
|
||||||
check_mangled_cache( mask );
|
check_mangled_cache( mask );
|
||||||
|
|
||||||
has_wild = strchr(mask,'*') || strchr(mask,'?');
|
has_wild = ms_has_wild(mask);
|
||||||
|
|
||||||
if (!has_wild) {
|
if (!has_wild) {
|
||||||
pstrcat(directory,"/");
|
pstrcat(directory,"/");
|
||||||
@@ -3878,7 +3875,7 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
|
|||||||
pstring fname;
|
pstring fname;
|
||||||
pstrcpy(fname,dname);
|
pstrcpy(fname,dname);
|
||||||
|
|
||||||
if(!mask_match(fname, mask, case_sensitive, False))
|
if(!mask_match(fname, mask, case_sensitive))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
error = ERRnoaccess;
|
error = ERRnoaccess;
|
||||||
|
|||||||
243
source/smbd/statcache.c
Normal file
243
source/smbd/statcache.c
Normal file
@@ -0,0 +1,243 @@
|
|||||||
|
/*
|
||||||
|
Unix SMB/Netbios implementation.
|
||||||
|
Version 3.0
|
||||||
|
stat cache code
|
||||||
|
Copyright (C) Andrew Tridgell 1992-2000
|
||||||
|
Copyright (C) Jeremy Allison 1999-200
|
||||||
|
|
||||||
|
|
||||||
|
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 02139, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "includes.h"
|
||||||
|
|
||||||
|
extern BOOL case_sensitive;
|
||||||
|
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
Stat cache code used in unix_convert.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
static int global_stat_cache_lookups;
|
||||||
|
static int global_stat_cache_misses;
|
||||||
|
static int global_stat_cache_hits;
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
Stat cache statistics code.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
void print_stat_cache_statistics(void)
|
||||||
|
{
|
||||||
|
double eff;
|
||||||
|
|
||||||
|
if(global_stat_cache_lookups == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
eff = (100.0* (double)global_stat_cache_hits)/(double)global_stat_cache_lookups;
|
||||||
|
|
||||||
|
DEBUG(0,("stat cache stats: lookups = %d, hits = %d, misses = %d, \
|
||||||
|
stat cache was %f%% effective.\n", global_stat_cache_lookups,
|
||||||
|
global_stat_cache_hits, global_stat_cache_misses, eff ));
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int name_len;
|
||||||
|
char names[2]; /* This is extended via malloc... */
|
||||||
|
} stat_cache_entry;
|
||||||
|
|
||||||
|
#define INIT_STAT_CACHE_SIZE 512
|
||||||
|
static hash_table stat_cache;
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
Add an entry into the stat cache.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
void stat_cache_add( char *full_orig_name, char *orig_translated_path)
|
||||||
|
{
|
||||||
|
stat_cache_entry *scp;
|
||||||
|
stat_cache_entry *found_scp;
|
||||||
|
pstring orig_name;
|
||||||
|
pstring translated_path;
|
||||||
|
int namelen;
|
||||||
|
hash_element *hash_elem;
|
||||||
|
|
||||||
|
if (!lp_stat_cache()) return;
|
||||||
|
|
||||||
|
namelen = strlen(orig_translated_path);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Don't cache trivial valid directory entries.
|
||||||
|
*/
|
||||||
|
if((*full_orig_name == '\0') || (strcmp(full_orig_name, ".") == 0) ||
|
||||||
|
(strcmp(full_orig_name, "..") == 0))
|
||||||
|
return;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If we are in case insentive mode, we need to
|
||||||
|
* store names that need no translation - else, it
|
||||||
|
* would be a waste.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if(case_sensitive && (strcmp(full_orig_name, orig_translated_path) == 0))
|
||||||
|
return;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Remove any trailing '/' characters from the
|
||||||
|
* translated path.
|
||||||
|
*/
|
||||||
|
|
||||||
|
pstrcpy(translated_path, orig_translated_path);
|
||||||
|
if(translated_path[namelen-1] == '/') {
|
||||||
|
translated_path[namelen-1] = '\0';
|
||||||
|
namelen--;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We will only replace namelen characters
|
||||||
|
* of full_orig_name.
|
||||||
|
* StrnCpy always null terminates.
|
||||||
|
*/
|
||||||
|
|
||||||
|
StrnCpy(orig_name, full_orig_name, namelen);
|
||||||
|
if(!case_sensitive)
|
||||||
|
strupper( orig_name );
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check this name doesn't exist in the cache before we
|
||||||
|
* add it.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if ((hash_elem = hash_lookup(&stat_cache, orig_name))) {
|
||||||
|
found_scp = (stat_cache_entry *)(hash_elem->value);
|
||||||
|
if (strcmp((found_scp->names+found_scp->name_len+1), translated_path) == 0) {
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
hash_remove(&stat_cache, hash_elem);
|
||||||
|
if((scp = (stat_cache_entry *)malloc(sizeof(stat_cache_entry)+2*namelen)) == NULL) {
|
||||||
|
DEBUG(0,("stat_cache_add: Out of memory !\n"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
pstrcpy(scp->names, orig_name);
|
||||||
|
pstrcpy((scp->names+namelen+1), translated_path);
|
||||||
|
scp->name_len = namelen;
|
||||||
|
hash_insert(&stat_cache, (char *)scp, orig_name);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* New entry.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if((scp = (stat_cache_entry *)malloc(sizeof(stat_cache_entry)+2*namelen)) == NULL) {
|
||||||
|
DEBUG(0,("stat_cache_add: Out of memory !\n"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
pstrcpy(scp->names, orig_name);
|
||||||
|
pstrcpy(scp->names+namelen+1, translated_path);
|
||||||
|
scp->name_len = namelen;
|
||||||
|
hash_insert(&stat_cache, (char *)scp, orig_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
DEBUG(5,("stat_cache_add: Added entry %s -> %s\n", scp->names, (scp->names+scp->name_len+1)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
Look through the stat cache for an entry - promote it to the top if found.
|
||||||
|
Return True if we translated (and did a scuccessful stat on) the entire name.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
BOOL stat_cache_lookup(connection_struct *conn, char *name, char *dirpath,
|
||||||
|
char **start, SMB_STRUCT_STAT *pst)
|
||||||
|
{
|
||||||
|
stat_cache_entry *scp;
|
||||||
|
char *trans_name;
|
||||||
|
pstring chk_name;
|
||||||
|
int namelen;
|
||||||
|
hash_element *hash_elem;
|
||||||
|
char *sp;
|
||||||
|
|
||||||
|
if (!lp_stat_cache())
|
||||||
|
return False;
|
||||||
|
|
||||||
|
namelen = strlen(name);
|
||||||
|
|
||||||
|
*start = name;
|
||||||
|
global_stat_cache_lookups++;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Don't lookup trivial valid directory entries.
|
||||||
|
*/
|
||||||
|
if((*name == '\0') || (strcmp(name, ".") == 0) || (strcmp(name, "..") == 0)) {
|
||||||
|
global_stat_cache_misses++;
|
||||||
|
return False;
|
||||||
|
}
|
||||||
|
|
||||||
|
pstrcpy(chk_name, name);
|
||||||
|
if(!case_sensitive)
|
||||||
|
strupper( chk_name );
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
hash_elem = hash_lookup(&stat_cache, chk_name);
|
||||||
|
if(hash_elem == NULL) {
|
||||||
|
/*
|
||||||
|
* Didn't find it - remove last component for next try.
|
||||||
|
*/
|
||||||
|
sp = strrchr(chk_name, '/');
|
||||||
|
if (sp) {
|
||||||
|
*sp = '\0';
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
* We reached the end of the name - no match.
|
||||||
|
*/
|
||||||
|
global_stat_cache_misses++;
|
||||||
|
return False;
|
||||||
|
}
|
||||||
|
if((*chk_name == '\0') || (strcmp(chk_name, ".") == 0)
|
||||||
|
|| (strcmp(chk_name, "..") == 0)) {
|
||||||
|
global_stat_cache_misses++;
|
||||||
|
return False;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
scp = (stat_cache_entry *)(hash_elem->value);
|
||||||
|
global_stat_cache_hits++;
|
||||||
|
trans_name = scp->names+scp->name_len+1;
|
||||||
|
if(conn->vfs_ops.stat(dos_to_unix(trans_name,False), pst) != 0) {
|
||||||
|
/* Discard this entry - it doesn't exist in the filesystem. */
|
||||||
|
hash_remove(&stat_cache, hash_elem);
|
||||||
|
return False;
|
||||||
|
}
|
||||||
|
memcpy(name, trans_name, scp->name_len);
|
||||||
|
*start = &name[scp->name_len];
|
||||||
|
if(**start == '/')
|
||||||
|
++*start;
|
||||||
|
StrnCpy( dirpath, trans_name, name - (*start));
|
||||||
|
return (namelen == scp->name_len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*************************************************************************** **
|
||||||
|
* Initializes or clears the stat cache.
|
||||||
|
*
|
||||||
|
* Input: none.
|
||||||
|
* Output: none.
|
||||||
|
*
|
||||||
|
* ************************************************************************** **
|
||||||
|
*/
|
||||||
|
BOOL reset_stat_cache( void )
|
||||||
|
{
|
||||||
|
return hash_table_init( &stat_cache, INIT_STAT_CACHE_SIZE, (compare_function)(strcmp));
|
||||||
|
} /* reset_stat_cache */
|
||||||
@@ -287,6 +287,19 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*********************************************************
|
||||||
|
* Routine to check if a given string matches exactly.
|
||||||
|
* as a special case a mask of "." does NOT match. That
|
||||||
|
* is required for correct wildcard semantics
|
||||||
|
* Case can be significant or not.
|
||||||
|
**********************************************************/
|
||||||
|
static BOOL exact_match(char *str,char *mask, BOOL case_sig)
|
||||||
|
{
|
||||||
|
if (mask[0] == '.' && mask[1] == 0) return False;
|
||||||
|
if (case_sig) return strcmp(str,mask)==0;
|
||||||
|
return strcasecmp(str,mask) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
get a level dependent lanman2 dir entry.
|
get a level dependent lanman2 dir entry.
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
@@ -360,7 +373,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn,
|
|||||||
pstrcpy(fname,dname);
|
pstrcpy(fname,dname);
|
||||||
|
|
||||||
if(!(got_match = *got_exact_match = exact_match(fname, mask, case_sensitive)))
|
if(!(got_match = *got_exact_match = exact_match(fname, mask, case_sensitive)))
|
||||||
got_match = mask_match(fname, mask, case_sensitive, True);
|
got_match = mask_match(fname, mask, case_sensitive);
|
||||||
|
|
||||||
if(!got_match && !is_8_3(fname, False)) {
|
if(!got_match && !is_8_3(fname, False)) {
|
||||||
|
|
||||||
@@ -375,7 +388,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn,
|
|||||||
pstrcpy( newname, fname);
|
pstrcpy( newname, fname);
|
||||||
name_map_mangle( newname, True, False, SNUM(conn));
|
name_map_mangle( newname, True, False, SNUM(conn));
|
||||||
if(!(got_match = *got_exact_match = exact_match(newname, mask, case_sensitive)))
|
if(!(got_match = *got_exact_match = exact_match(newname, mask, case_sensitive)))
|
||||||
got_match = mask_match(newname, mask, case_sensitive, True);
|
got_match = mask_match(newname, mask, case_sensitive);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(got_match)
|
if(got_match)
|
||||||
@@ -509,13 +522,20 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn,
|
|||||||
SIVAL(p,0,strlen(fname)); p += 4;
|
SIVAL(p,0,strlen(fname)); p += 4;
|
||||||
SIVAL(p,0,0); p += 4;
|
SIVAL(p,0,0); p += 4;
|
||||||
if (!was_8_3) {
|
if (!was_8_3) {
|
||||||
pstrcpy(p+2,fname);
|
/* NT4 always uses unicode here */
|
||||||
if (!name_map_mangle(p+2,True,True,SNUM(conn)))
|
fstring short_name, ushort_name;
|
||||||
(p+2)[12] = 0;
|
int slen;
|
||||||
} else
|
pstrcpy(short_name,fname);
|
||||||
*(p+2) = 0;
|
name_map_mangle(short_name,True,True,SNUM(conn));
|
||||||
strupper(p+2);
|
strupper(short_name);
|
||||||
SSVAL(p,0,strlen(p+2));
|
slen = strlen(short_name);
|
||||||
|
ascii_to_unistr(ushort_name, short_name, 24);
|
||||||
|
memcpy(p+2, ushort_name, 2*slen);
|
||||||
|
SSVAL(p, 0, 2*slen);
|
||||||
|
} else {
|
||||||
|
SSVAL(p,0,0);
|
||||||
|
*(p+2) = 0;
|
||||||
|
}
|
||||||
p += 2 + 24;
|
p += 2 + 24;
|
||||||
/* nameptr = p; */
|
/* nameptr = p; */
|
||||||
pstrcpy(p,fname); p += strlen(p);
|
pstrcpy(p,fname); p += strlen(p);
|
||||||
@@ -591,32 +611,6 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn,
|
|||||||
return(found);
|
return(found);
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
Convert the directory masks formated for the wire.
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
void mask_convert( char *mask)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* We know mask is a pstring.
|
|
||||||
*/
|
|
||||||
char *p = mask;
|
|
||||||
while (*p) {
|
|
||||||
if (*p == '<') {
|
|
||||||
pstring expnd;
|
|
||||||
if(p[1] != '"' && p[1] != '.') {
|
|
||||||
pstrcpy( expnd, p+1 );
|
|
||||||
*p++ = '*';
|
|
||||||
*p = '.';
|
|
||||||
safe_strcpy( p+1, expnd, sizeof(pstring) - (p - mask) - 2);
|
|
||||||
} else
|
|
||||||
*p = '*';
|
|
||||||
}
|
|
||||||
if (*p == '>') *p = '?';
|
|
||||||
if (*p == '"') *p = '.';
|
|
||||||
p++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
Reply to a TRANS2_FINDFIRST.
|
Reply to a TRANS2_FINDFIRST.
|
||||||
@@ -727,9 +721,6 @@ static int call_trans2findfirst(connection_struct *conn,
|
|||||||
if (dptr_num < 0)
|
if (dptr_num < 0)
|
||||||
return(UNIXERROR(ERRDOS,ERRbadfile));
|
return(UNIXERROR(ERRDOS,ERRbadfile));
|
||||||
|
|
||||||
/* Convert the formatted mask. */
|
|
||||||
mask_convert(mask);
|
|
||||||
|
|
||||||
/* Save the wildcard match and attribs we are using on this directory -
|
/* Save the wildcard match and attribs we are using on this directory -
|
||||||
needed as lanman2 assumes these are being saved between calls */
|
needed as lanman2 assumes these are being saved between calls */
|
||||||
|
|
||||||
|
|||||||
@@ -499,7 +499,7 @@ static int tdb_new_database(TDB_CONTEXT *tdb, int hash_size)
|
|||||||
header.version = TDB_VERSION;
|
header.version = TDB_VERSION;
|
||||||
header.hash_size = hash_size;
|
header.hash_size = hash_size;
|
||||||
lseek(tdb->fd, 0, SEEK_SET);
|
lseek(tdb->fd, 0, SEEK_SET);
|
||||||
ftruncate(tdb->fd, 0);
|
if (tdb->fd != -1) ftruncate(tdb->fd, 0);
|
||||||
|
|
||||||
if (tdb->fd != -1 && write(tdb->fd, &header, sizeof(header)) !=
|
if (tdb->fd != -1 && write(tdb->fd, &header, sizeof(header)) !=
|
||||||
sizeof(header)) {
|
sizeof(header)) {
|
||||||
@@ -1150,12 +1150,12 @@ TDB_CONTEXT *tdb_open(char *name, int hash_size, int tdb_flags,
|
|||||||
|
|
||||||
tdb.read_only = ((open_flags & O_ACCMODE) == O_RDONLY);
|
tdb.read_only = ((open_flags & O_ACCMODE) == O_RDONLY);
|
||||||
|
|
||||||
if (name != NULL) {
|
if (name == NULL) goto in_memory;
|
||||||
tdb.fd = open(name, open_flags, mode);
|
|
||||||
if (tdb.fd == -1) {
|
tdb.fd = open(name, open_flags, mode);
|
||||||
|
if (tdb.fd == -1) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/* ensure there is only one process initialising at once */
|
/* ensure there is only one process initialising at once */
|
||||||
tdb_brlock(&tdb, GLOBAL_LOCK, LOCK_SET, F_WRLCK, F_SETLKW);
|
tdb_brlock(&tdb, GLOBAL_LOCK, LOCK_SET, F_WRLCK, F_SETLKW);
|
||||||
@@ -1182,19 +1182,15 @@ TDB_CONTEXT *tdb_open(char *name, int hash_size, int tdb_flags,
|
|||||||
if (tdb_new_database(&tdb, hash_size) == -1) goto fail;
|
if (tdb_new_database(&tdb, hash_size) == -1) goto fail;
|
||||||
|
|
||||||
lseek(tdb.fd, 0, SEEK_SET);
|
lseek(tdb.fd, 0, SEEK_SET);
|
||||||
if (tdb.fd != -1 && read(tdb.fd, &tdb.header,
|
if (read(tdb.fd, &tdb.header, sizeof(tdb.header)) != sizeof(tdb.header))
|
||||||
sizeof(tdb.header)) !=
|
|
||||||
sizeof(tdb.header))
|
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tdb.fd != -1) {
|
fstat(tdb.fd, &st);
|
||||||
fstat(tdb.fd, &st);
|
|
||||||
|
|
||||||
/* map the database and fill in the return structure */
|
/* map the database and fill in the return structure */
|
||||||
tdb.name = (char *)strdup(name);
|
tdb.name = (char *)strdup(name);
|
||||||
tdb.map_size = st.st_size;
|
tdb.map_size = st.st_size;
|
||||||
}
|
|
||||||
|
|
||||||
tdb.locked = (int *)calloc(tdb.header.hash_size+1,
|
tdb.locked = (int *)calloc(tdb.header.hash_size+1,
|
||||||
sizeof(tdb.locked[0]));
|
sizeof(tdb.locked[0]));
|
||||||
@@ -1203,13 +1199,12 @@ TDB_CONTEXT *tdb_open(char *name, int hash_size, int tdb_flags,
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if HAVE_MMAP
|
#if HAVE_MMAP
|
||||||
if (tdb.fd != -1) {
|
tdb.map_ptr = (void *)mmap(NULL, st.st_size,
|
||||||
tdb.map_ptr = (void *)mmap(NULL, st.st_size,
|
tdb.read_only? PROT_READ : PROT_READ|PROT_WRITE,
|
||||||
tdb.read_only? PROT_READ : PROT_READ|PROT_WRITE,
|
MAP_SHARED | MAP_FILE, tdb.fd, 0);
|
||||||
MAP_SHARED | MAP_FILE, tdb.fd, 0);
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
in_memory:
|
||||||
ret = (TDB_CONTEXT *)malloc(sizeof(tdb));
|
ret = (TDB_CONTEXT *)malloc(sizeof(tdb));
|
||||||
if (!ret) goto fail;
|
if (!ret) goto fail;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user