summaryrefslogtreecommitdiff
path: root/source3/smbd/dir.c
diff options
context:
space:
mode:
Diffstat (limited to 'source3/smbd/dir.c')
-rw-r--r--source3/smbd/dir.c91
1 files changed, 51 insertions, 40 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);
}
/****************************************************************************