- removed all our old wildcard matching code and replaced it with a
authorAndrew Tridgell <tridge@samba.org>
Sun, 30 Apr 2000 11:04:28 +0000 (11:04 +0000)
committerAndrew Tridgell <tridge@samba.org>
Sun, 30 Apr 2000 11:04:28 +0000 (11:04 +0000)
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)

15 files changed:
source3/Makefile.in
source3/client/client.c
source3/client/clitar.c
source3/include/proto.h
source3/include/smb_macros.h
source3/lib/util.c
source3/lib/util_unistr.c
source3/locking/posix.c
source3/smbd/chgpasswd.c
source3/smbd/dir.c
source3/smbd/filename.c
source3/smbd/reply.c
source3/smbd/statcache.c [new file with mode: 0644]
source3/smbd/trans2.c
source3/tdb/tdb.c

index 1d551b5443982127f1ff1a397d9d207cfa88d98f..73b8e454004a86a3b0830a4dadde1cb4f9eb6565 100644 (file)
@@ -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 \
index 08dd8970fcf0a1c15aa0c971048c8bc19511ce4a..ade1436871ca073e4f9f4cac26f958baa22e8ecf 100644 (file)
@@ -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;
        }
index d71eff1c9e2017ea3d1d910042a4263d39e62c45..efa4fa8815edccc705f24a9294d73659e454a384 100644 (file)
@@ -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));
index dc12838e7708cc70499b15d275ab90f16ec54075..27d97ee4c76b361ff20c8fa83ec84a300fd2153d 100644 (file)
@@ -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);
index e7d05189cdcfa7f202819fa1ed7aab7d9afbadef..267b061f656dff101c2e038b081c61351ae0f20a 100644 (file)
 #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
index 7d9f6a5a50fa33b26be47ff3350194d38af3f528..955e1df080a2220860a32316018ce3ee7364f51e 100644 (file)
@@ -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)();
index 71ef32a1fd98d48e74eaa0ddef05a7ca93345725..0ca148ba949f9e060097cc7aa7868cb8d80c2db3 100644 (file)
@@ -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;
        }
index 1117bed8daadf435ee44b4293118088828e5c3b0..7b4075d5d8e2c93e94235c6fbd9b1857fe39d528 100644 (file)
@@ -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 ));
index df1f92f5ced6b6a6932af0de8e12a4042b07a9f4..484523bd2726457c0d363f9e1816dd8a18d68f40 100644 (file)
@@ -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;
                }
 
index 55d5bf132cf954b84f2ed3d00bbe70a334cc5362..bd4e2a44f9c1c71d3219a3286d9eacc6a4272259 100644 (file)
@@ -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;
index 7afa9e99865fad43cd74d13fd5191078f2aa6c16..ed1a1c3f63f4e7eb20b95b076c4fab01024c9b03 100644 (file)
@@ -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  */
index 41c6dcb143a96b6c1908616c5292c8891e2635ad..990a9aecb2fc3801fcc25f6eb23243e516eb7472 100644 (file)
@@ -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 (file)
index 0000000..ae5dbb1
--- /dev/null
@@ -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  */
index 4e502f767bdc13086479965e8ecdcb57895cfbae..7ae24f9e3899043d13a5d48e8c50999b7583fd6b 100644 (file)
@@ -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 */
 
index c8860e219101a79e07bee4d7786cfb3cc3ef9659..a1483d42d21a017466111d14820a051c7013ee03 100644 (file)
@@ -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;