diff options
author | Andrew Tridgell <tridge@samba.org> | 2000-04-30 11:04:28 +0000 |
---|---|---|
committer | Andrew Tridgell <tridge@samba.org> | 2000-04-30 11:04:28 +0000 |
commit | 700f72453ed8dfd356a5591b9447127b5066ac4b (patch) | |
tree | 46a30958a2f160cf389a9309355c3ebc39c584fd | |
parent | 71e7974f3f847759ba6f844ea7f482786cc5db02 (diff) | |
download | samba-700f72453ed8dfd356a5591b9447127b5066ac4b.tar.gz samba-700f72453ed8dfd356a5591b9447127b5066ac4b.tar.bz2 samba-700f72453ed8dfd356a5591b9447127b5066ac4b.zip |
- 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 used to be commit 03e9cea004bbba72161a5323cf3b4556c94aed8e)
-rw-r--r-- | source3/Makefile.in | 2 | ||||
-rw-r--r-- | source3/client/client.c | 2 | ||||
-rw-r--r-- | source3/client/clitar.c | 4 | ||||
-rw-r--r-- | source3/include/proto.h | 27 | ||||
-rw-r--r-- | source3/include/smb_macros.h | 8 | ||||
-rw-r--r-- | source3/lib/util.c | 657 | ||||
-rw-r--r-- | source3/lib/util_unistr.c | 39 | ||||
-rw-r--r-- | source3/locking/posix.c | 4 | ||||
-rw-r--r-- | source3/smbd/chgpasswd.c | 2 | ||||
-rw-r--r-- | source3/smbd/dir.c | 2 | ||||
-rw-r--r-- | source3/smbd/filename.c | 259 | ||||
-rw-r--r-- | source3/smbd/reply.c | 15 | ||||
-rw-r--r-- | source3/smbd/statcache.c | 243 | ||||
-rw-r--r-- | source3/smbd/trans2.c | 67 | ||||
-rw-r--r-- | source3/tdb/tdb.c | 35 |
15 files changed, 391 insertions, 975 deletions
diff --git a/source3/Makefile.in b/source3/Makefile.in index 1d551b5443..73b8e45400 100644 --- a/source3/Makefile.in +++ b/source3/Makefile.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/reply.o smbd/trans2.o smbd/uid.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 \ rpc_parse/parse_creds.o \ smbd/process.o smbd/oplock.o smbd/service.o smbd/error.o \ diff --git a/source3/client/client.c b/source3/client/client.c index 08dd8970fc..ade1436871 100644 --- a/source3/client/client.c +++ b/source3/client/client.c @@ -302,7 +302,7 @@ static BOOL do_this_one(file_info *finfo) if (finfo->mode & aDIR) return(True); if (*fileselection && - !mask_match(finfo->name,fileselection,False,False)) { + !mask_match(finfo->name,fileselection,False)) { DEBUG(3,("match_match %s failed\n", finfo->name)); return False; } diff --git a/source3/client/clitar.c b/source3/client/clitar.c index d71eff1c9e..efa4fa8815 100644 --- a/source3/client/clitar.c +++ b/source3/client/clitar.c @@ -820,7 +820,7 @@ static void do_tar(file_info *finfo) #ifdef HAVE_REGEX_H (tar_re_search && !regexec(preg, exclaim, 0, NULL, 0))) { #else - (tar_re_search && mask_match(exclaim, cliplist[0], True, False))) { + (tar_re_search && mask_match(exclaim, cliplist[0], True))) { #endif DEBUG(3,("Skipping file %s\n", exclaim)); return; @@ -1234,7 +1234,7 @@ static void do_tarput(void) #ifdef HAVE_REGEX_H || (tar_re_search && !regexec(preg, finfo.name, 0, NULL, 0))); #else - || (tar_re_search && mask_match(finfo.name, cliplist[0], True, False))); + || (tar_re_search && mask_match(finfo.name, cliplist[0], True))); #endif DEBUG(5, ("Skip = %i, cliplist=%s, file=%s\n", skip, (cliplist?cliplist[0]:NULL), finfo.name)); diff --git a/source3/include/proto.h b/source3/include/proto.h index dc12838e77..27d97ee4c7 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -140,6 +140,10 @@ void initialize_multibyte_vectors( int client_codepage); 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 */ 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 unix_clean_name(char *s); 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 close_low_fds(void); 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); 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); BOOL yesno(char *p); int set_filelen(int fd, SMB_OFF_T len); @@ -355,6 +356,8 @@ void *memdup(void *p, size_t size); char *myhostname(void); char *lock_path(char *name); 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); /*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 */ 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 unistr_to_ascii(char *dest, const uint16 *src, int len); +void ascii_to_unistr(char *dest, const char *src, int maxlen); +void unistr_to_ascii(char *dest, char *src, int len); char *skip_unibuf(char *src, size_t len); char *dos_unistrn2(uint16 *src, int len); 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 */ -void print_stat_cache_statistics(void); BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, BOOL *bad_path, SMB_STRUCT_STAT *pst); BOOL check_name(char *name,connection_struct *conn); -BOOL reset_stat_cache( void ); /*The following definitions come from smbd/files.c */ @@ -3316,9 +3317,16 @@ int sslutil_connect(int fd); int sslutil_disconnect(int fd); 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 */ -void mask_convert( char *mask); int reply_findclose(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize); int reply_findnclose(connection_struct *conn, @@ -3475,6 +3483,9 @@ int tdb_writelock(TDB_CONTEXT *tdb); int tdb_writeunlock(TDB_CONTEXT *tdb); int tdb_lockchain(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(TDB_CONTEXT *tdb, char *keystr); int tdb_store_int_byblob(TDB_CONTEXT *tdb, char *keystr, size_t len, int v); diff --git a/source3/include/smb_macros.h b/source3/include/smb_macros.h index e7d05189cd..267b061f65 100644 --- a/source3/include/smb_macros.h +++ b/source3/include/smb_macros.h @@ -176,14 +176,6 @@ #define _smb_setlen(buf,len) buf[0] = 0; buf[1] = (len&0x10000)>>16; \ 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 values diff --git a/source3/lib/util.c b/source3/lib/util.c index 7d9f6a5a50..955e1df080 100644 --- a/source3/lib/util.c +++ b/source3/lib/util.c @@ -90,9 +90,6 @@ pstring global_myname = ""; fstring global_myworkgroup = ""; char **my_netbios_names; -static char *filename_dos(char *path,char *buf); - - /**************************************************************************** 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 } -/**************************************************************************** -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 @@ -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 ****************************************************************************/ @@ -1419,24 +841,6 @@ this is a version of setbuffer() for those machines that only have setvbuf } #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 ****************************************************************************/ @@ -1961,12 +1365,7 @@ BOOL is_in_path(char *name, name_compare_entry *namelist) { if(namelist->is_wild) { - /* - * 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)) + if (mask_match(last_component, namelist->name, case_sensitive)) { DEBUG(8,("is_in_path: mask match succeeded\n")); return True; @@ -2067,8 +1466,7 @@ void set_namearray(name_compare_entry **ppname_array, char *namelist) if(name_end == NULL) break; - (*ppname_array)[i].is_wild = ((strchr( nameptr, '?')!=NULL) || - (strchr( nameptr, '*')!=NULL)); + (*ppname_array)[i].is_wild = ms_has_wild(nameptr); if(((*ppname_array)[i].name = strdup(nameptr)) == NULL) { 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__ + +/******************************************************************* +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) { static int (*fn)(); diff --git a/source3/lib/util_unistr.c b/source3/lib/util_unistr.c index 71ef32a1fd..0ca148ba94 100644 --- a/source3/lib/util_unistr.c +++ b/source3/lib/util_unistr.c @@ -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 !!! 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; - register char c; + char *destend = dest + maxlen; + char c; - while (dest < destend) - { + while (dest < destend) { c = *(src++); - if (c == 0) - { - break; - } + if (c == 0) break; - *(dest++) = (uint16)c; + SSVAL(dest, 0, (uint16)c); + dest += 2; } - - *dest = 0; + SSVAL(dest, 0, 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 !!! 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; - register uint16 c; + uint16 c; - while (dest < destend) - { - c = *(src++); - if (c == 0) - { - break; - } + while (dest < destend) { + c = SVAL(src, 0); + src += 2; + if (c == 0) break; *(dest++) = (char)c; } diff --git a/source3/locking/posix.c b/source3/locking/posix.c index 1117bed8da..7b4075d5d8 100644 --- a/source3/locking/posix.c +++ b/source3/locking/posix.c @@ -999,7 +999,7 @@ BOOL release_posix_lock(files_struct *fsp, SMB_BIG_UINT u_offset, SMB_BIG_UINT u ret = False; } - talloc_destroy(ul_ctx); + talloc_destroy(ul_ctx); return ret; } @@ -1020,7 +1020,7 @@ static void delete_posix_lock_entries(files_struct *fsp) 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", (double)pl->start, (double)pl->size, (int)pl->lock_type, pl->fd )); diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index df1f92f5ce..484523bd27 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -249,7 +249,7 @@ static int expect(int master, char *issue, char *expected) nread += len; buffer[nread] = 0; - if ((match = unix_do_match(buffer, expected, False))) + if ((match = (ms_fnmatch(expected, buffer) == 0))) timeout = 200; } diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index 55d5bf132c..bd4e2a44f9 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -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)) || (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,"."))) continue; diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 7afa9e9986..ed1a1c3f63 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -88,228 +88,6 @@ static BOOL mangled_equal(char *name1, char *name2) 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 @@ -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))) 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 * 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) return(False); - if(strchr(start,'?') || strchr(start,'*')) - name_has_wildcard = True; + name_has_wildcard = ms_has_wild(start); /* * 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. */ - if (strchr(start,'?') || strchr(start,'*') || + if (ms_has_wild(start) || !scan_directory(dirpath, start, conn, end?True:False)) { if (end) { /* @@ -752,15 +509,3 @@ static BOOL scan_directory(char *path, char *name,connection_struct *conn,BOOL d 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 */ diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 41c6dcb143..990a9aecb2 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -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; p = mask; @@ -1936,7 +1933,7 @@ int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size if (!rc && is_mangled(mask)) check_mangled_cache( mask ); - has_wild = strchr(mask,'*') || strchr(mask,'?'); + has_wild = ms_has_wild(mask); if (!has_wild) { pstrcat(directory,"/"); @@ -1969,7 +1966,7 @@ int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size pstring fname; pstrcpy(fname,dname); - if(!mask_match(fname, mask, case_sensitive, False)) continue; + if(!mask_match(fname, mask, case_sensitive)) continue; error = ERRnoaccess; slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname); @@ -3508,7 +3505,7 @@ int rename_internals(connection_struct *conn, if (!rc && is_mangled(mask)) check_mangled_cache( mask ); - has_wild = strchr(mask,'*') || strchr(mask,'?'); + has_wild = ms_has_wild(mask); if (!has_wild) { /* @@ -3618,7 +3615,7 @@ int rename_internals(connection_struct *conn, pstrcpy(fname,dname); - if(!mask_match(fname, mask, case_sensitive, False)) + if(!mask_match(fname, mask, case_sensitive)) continue; error = ERRnoaccess; @@ -3847,7 +3844,7 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, if (!rc && is_mangled(mask)) check_mangled_cache( mask ); - has_wild = strchr(mask,'*') || strchr(mask,'?'); + has_wild = ms_has_wild(mask); if (!has_wild) { pstrcat(directory,"/"); @@ -3878,7 +3875,7 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, pstring fname; pstrcpy(fname,dname); - if(!mask_match(fname, mask, case_sensitive, False)) + if(!mask_match(fname, mask, case_sensitive)) continue; error = ERRnoaccess; diff --git a/source3/smbd/statcache.c b/source3/smbd/statcache.c new file mode 100644 index 0000000000..ae5dbb1ef7 --- /dev/null +++ b/source3/smbd/statcache.c @@ -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 */ diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 4e502f767b..7ae24f9e38 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -287,6 +287,19 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, 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. ****************************************************************************/ @@ -360,7 +373,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, pstrcpy(fname,dname); 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)) { @@ -375,7 +388,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, pstrcpy( newname, fname); name_map_mangle( newname, True, False, SNUM(conn)); 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) @@ -509,13 +522,20 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, SIVAL(p,0,strlen(fname)); p += 4; SIVAL(p,0,0); p += 4; if (!was_8_3) { - pstrcpy(p+2,fname); - if (!name_map_mangle(p+2,True,True,SNUM(conn))) - (p+2)[12] = 0; - } else - *(p+2) = 0; - strupper(p+2); - SSVAL(p,0,strlen(p+2)); + /* NT4 always uses unicode here */ + fstring short_name, ushort_name; + int slen; + pstrcpy(short_name,fname); + name_map_mangle(short_name,True,True,SNUM(conn)); + strupper(short_name); + 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; /* nameptr = p; */ pstrcpy(p,fname); p += strlen(p); @@ -591,32 +611,6 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, 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. @@ -727,9 +721,6 @@ static int call_trans2findfirst(connection_struct *conn, if (dptr_num < 0) return(UNIXERROR(ERRDOS,ERRbadfile)); - /* Convert the formatted mask. */ - mask_convert(mask); - /* Save the wildcard match and attribs we are using on this directory - needed as lanman2 assumes these are being saved between calls */ diff --git a/source3/tdb/tdb.c b/source3/tdb/tdb.c index c8860e2191..a1483d42d2 100644 --- a/source3/tdb/tdb.c +++ b/source3/tdb/tdb.c @@ -499,7 +499,7 @@ static int tdb_new_database(TDB_CONTEXT *tdb, int hash_size) header.version = TDB_VERSION; header.hash_size = hash_size; 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)) != 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); - if (name != NULL) { - tdb.fd = open(name, open_flags, mode); - if (tdb.fd == -1) { + if (name == NULL) goto in_memory; + + tdb.fd = open(name, open_flags, mode); + if (tdb.fd == -1) { goto fail; - } - } + } /* ensure there is only one process initialising at once */ 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; lseek(tdb.fd, 0, SEEK_SET); - if (tdb.fd != -1 && read(tdb.fd, &tdb.header, - sizeof(tdb.header)) != - sizeof(tdb.header)) + if (read(tdb.fd, &tdb.header, sizeof(tdb.header)) != sizeof(tdb.header)) goto fail; } - if (tdb.fd != -1) { - fstat(tdb.fd, &st); + fstat(tdb.fd, &st); - /* map the database and fill in the return structure */ - tdb.name = (char *)strdup(name); - tdb.map_size = st.st_size; - } + /* map the database and fill in the return structure */ + tdb.name = (char *)strdup(name); + tdb.map_size = st.st_size; tdb.locked = (int *)calloc(tdb.header.hash_size+1, sizeof(tdb.locked[0])); @@ -1203,13 +1199,12 @@ TDB_CONTEXT *tdb_open(char *name, int hash_size, int tdb_flags, } #if HAVE_MMAP - if (tdb.fd != -1) { - tdb.map_ptr = (void *)mmap(NULL, st.st_size, - tdb.read_only? PROT_READ : PROT_READ|PROT_WRITE, - MAP_SHARED | MAP_FILE, tdb.fd, 0); - } + tdb.map_ptr = (void *)mmap(NULL, st.st_size, + tdb.read_only? PROT_READ : PROT_READ|PROT_WRITE, + MAP_SHARED | MAP_FILE, tdb.fd, 0); #endif + in_memory: ret = (TDB_CONTEXT *)malloc(sizeof(tdb)); if (!ret) goto fail; |