diff options
-rw-r--r-- | source3/smbd/dir.c | 91 | ||||
-rw-r--r-- | source3/smbd/trans2.c | 10 |
2 files changed, 56 insertions, 45 deletions
diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index 96e0923dbd..1c77630ee7 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -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); } /**************************************************************************** diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index f40dd5154b..adbba92ee7 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -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); } |