r18547: Add in fixes to mangling dir code - ensure don't
authorJeremy Allison <jra@samba.org>
Fri, 15 Sep 2006 09:06:36 +0000 (09:06 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 16:51:48 +0000 (11:51 -0500)
look in the paths for wcard - always read directly
from incoming packet.
Jeremy.
(This used to be commit 3745a1af4ea9262fcda28931539fa6ab4c9060d1)

source3/smbd/dir.c
source3/smbd/trans2.c

index 96e0923dbd0b62c99c637199a294ba0677d465d2..1c77630ee724aff51892767ed4e60a0d6448a145 100644 (file)
@@ -61,6 +61,7 @@ struct dptr_struct {
        uint32 attr;
        char *path;
        BOOL has_wild; /* Set to true if the wcard entry has MS wildcard characters in it. */
+       BOOL did_stat; /* Optimisation for non-wcard searches. */
 };
 
 static struct bitmap *dptr_bmap;
@@ -535,6 +536,11 @@ long dptr_TellDir(struct dptr_struct *dptr)
        return TellDir(dptr->dir_hnd);
 }
 
+BOOL dptr_has_wild(struct dptr_struct *dptr)
+{
+       return dptr->has_wild;
+}
+
 /****************************************************************************
  Return the next visible file name, skipping veto'd and invisible files.
 ****************************************************************************/
@@ -557,8 +563,6 @@ static const char *dptr_normal_ReadDirName(struct dptr_struct *dptr, long *poffs
 
 const char *dptr_ReadDirName(struct dptr_struct *dptr, long *poffset, SMB_STRUCT_STAT *pst)
 {
-       pstring pathreal;
-
        SET_STAT_INVALID(*pst);
 
        if (dptr->has_wild) {
@@ -571,55 +575,62 @@ const char *dptr_ReadDirName(struct dptr_struct *dptr, long *poffset, SMB_STRUCT
                return NULL;
        }
 
-       /* We know the stored wcard contains no wildcard characters. See if we can match
-          with a stat call. If we can't, then set has_wild to true to
-          prevent us from doing this on every call. */
+       if (!dptr->did_stat) {
+               pstring pathreal;
 
-       /* First check if it should be visible. */
-       if (!is_visible_file(dptr->conn, dptr->path, dptr->wcard, pst, True)) {
-               dptr->has_wild = True;
-               return dptr_normal_ReadDirName(dptr, poffset, pst);
-       }
+               /* We know the stored wcard contains no wildcard characters. See if we can match
+                  with a stat call. If we can't, then set did_stat to true to
+                  ensure we only do this once and keep searching. */
 
-       if (VALID_STAT(*pst)) {
-               /* We need to set the underlying dir_hdn offset to -1 also as
-                  this function is usually called with the output from TellDir. */
-               dptr->dir_hnd->offset = *poffset = END_OF_DIRECTORY_OFFSET;
-               return dptr->wcard;
-       }
+               dptr->did_stat = True;
 
-       pstrcpy(pathreal,dptr->path);
-       pstrcat(pathreal,"/");
-       pstrcat(pathreal,dptr->wcard);
+               /* First check if it should be visible. */
+               if (!is_visible_file(dptr->conn, dptr->path, dptr->wcard, pst, True)) {
+                       /* This only returns False if the file was found, but
+                          is explicitly not visible. Set us to end of directory,
+                          but return NULL as we know we can't ever find it. */
+                       dptr->dir_hnd->offset = *poffset = END_OF_DIRECTORY_OFFSET;
+                       return NULL;
+               }
 
-       if (SMB_VFS_STAT(dptr->conn,pathreal,pst) == 0) {
-               /* We need to set the underlying dir_hdn offset to -1 also as
-                  this function is usually called with the output from TellDir. */
-               dptr->dir_hnd->offset = *poffset = END_OF_DIRECTORY_OFFSET;
-               return dptr->wcard;
-       } else {
-               /* If we get any other error than ENOENT or ENOTDIR
-                  then the file exists we just can't stat it. */
-               if (errno != ENOENT && errno != ENOTDIR) {
-                       /* We need to set the underlying dir_hdn offset to -1 also as
+               if (VALID_STAT(*pst)) {
+                       /* We need to set the underlying dir_hnd offset to -1 also as
                           this function is usually called with the output from TellDir. */
                        dptr->dir_hnd->offset = *poffset = END_OF_DIRECTORY_OFFSET;
                        return dptr->wcard;
                }
-       }
 
-       /* In case sensitive mode we don't search - we know if it doesn't exist 
-          with a stat we will fail. */
+               pstrcpy(pathreal,dptr->path);
+               pstrcat(pathreal,"/");
+               pstrcat(pathreal,dptr->wcard);
 
-       if (dptr->conn->case_sensitive) {
-               /* We need to set the underlying dir_hdn offset to -1 also as
-                  this function is usually called with the output from TellDir. */
-               dptr->dir_hnd->offset = *poffset = END_OF_DIRECTORY_OFFSET;
-               return NULL;
-       } else {
-               dptr->has_wild = True;
-               return dptr_normal_ReadDirName(dptr, poffset, pst);
+               if (SMB_VFS_STAT(dptr->conn,pathreal,pst) == 0) {
+                       /* We need to set the underlying dir_hnd offset to -1 also as
+                          this function is usually called with the output from TellDir. */
+                       dptr->dir_hnd->offset = *poffset = END_OF_DIRECTORY_OFFSET;
+                       return dptr->wcard;
+               } else {
+                       /* If we get any other error than ENOENT or ENOTDIR
+                          then the file exists we just can't stat it. */
+                       if (errno != ENOENT && errno != ENOTDIR) {
+                               /* We need to set the underlying dir_hdn offset to -1 also as
+                                  this function is usually called with the output from TellDir. */
+                               dptr->dir_hnd->offset = *poffset = END_OF_DIRECTORY_OFFSET;
+                               return dptr->wcard;
+                       }
+               }
+
+               /* In case sensitive mode we don't search - we know if it doesn't exist 
+                  with a stat we will fail. */
+
+               if (dptr->conn->case_sensitive) {
+                       /* We need to set the underlying dir_hnd offset to -1 also as
+                          this function is usually called with the output from TellDir. */
+                       dptr->dir_hnd->offset = *poffset = END_OF_DIRECTORY_OFFSET;
+                       return NULL;
+               }
        }
+       return dptr_normal_ReadDirName(dptr, poffset, pst);
 }
 
 /****************************************************************************
index f40dd5154bc8fb4e495baf067f1d1509f72c9c83..adbba92ee73158a7817f02361c195a0e5d2b4894 100644 (file)
@@ -957,16 +957,16 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, i
  Case can be significant or not.
 **********************************************************/
 
-static BOOL exact_match(char *str,char *mask, BOOL case_sig) 
+static BOOL exact_match(connection_struct *conn, char *str, char *mask)
 {
        if (mask[0] == '.' && mask[1] == 0)
                return False;
-       if (case_sig)   
+       if (conn->case_sensitive)
                return strcmp(str,mask)==0;
        if (StrCaseCmp(str,mask) != 0) {
                return False;
        }
-       if (ms_has_wild(str)) {
+       if (dptr_has_wild(conn->dirptr)) {
                return False;
        }
        return True;
@@ -1132,7 +1132,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn,
 
                pstrcpy(fname,dname);      
 
-               if(!(got_match = *got_exact_match = exact_match(fname, mask, conn->case_sensitive)))
+               if(!(got_match = *got_exact_match = exact_match(conn, fname, mask)))
                        got_match = mask_match(fname, mask, conn->case_sensitive);
 
                if(!got_match && check_mangled_names &&
@@ -1148,7 +1148,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn,
                        pstring newname;
                        pstrcpy( newname, fname);
                        mangle_map( newname, True, False, conn->params);
-                       if(!(got_match = *got_exact_match = exact_match(newname, mask, conn->case_sensitive)))
+                       if(!(got_match = *got_exact_match = exact_match(conn, newname, mask)))
                                got_match = mask_match(newname, mask, conn->case_sensitive);
                }