diff options
author | Jeremy Allison <jra@samba.org> | 2010-09-08 16:55:24 -0700 |
---|---|---|
committer | Jeremy Allison <jra@samba.org> | 2010-09-08 16:55:24 -0700 |
commit | fcac46a61245e6b05f88ed80ec4b554ffd55dc63 (patch) | |
tree | 52a6a7438aef1df156313dd643192b6031bad9c4 /source3 | |
parent | 4f0b190a3086db3789e4198f5409a2b5c1980bf9 (diff) | |
download | samba-fcac46a61245e6b05f88ed80ec4b554ffd55dc63.tar.gz samba-fcac46a61245e6b05f88ed80ec4b554ffd55dc63.tar.bz2 samba-fcac46a61245e6b05f88ed80ec4b554ffd55dc63.zip |
Optimization suggested by Metze. Without this patch,
FindFirst with 'path\to\some\dir\with\files\*'
triggers the following stat calls
path\to\some\dir\with\files\* => ENOENT
path\
path\to\
path\to\some\
path\to\some\dir\
path\to\some\dir\with\
path\to\some\dir\with\files\
path\to\some\dir\with\files\* => ENOENT
With this patch we get :
path\to\some\dir\with\files\* => ENOENT
path\to\some\dir\with\files = OK
Jeremy.
Diffstat (limited to 'source3')
-rw-r--r-- | source3/smbd/filename.c | 98 |
1 files changed, 97 insertions, 1 deletions
diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 8f9b8558c1..eadb977a72 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -382,10 +382,12 @@ NTSTATUS unix_convert(TALLOC_CTX *ctx, * or a missing intermediate component ? */ struct smb_filename parent_fname; + const char *last_component = NULL; + ZERO_STRUCT(parent_fname); if (!parent_dirname(ctx, smb_fname->base_name, &parent_fname.base_name, - NULL)) { + &last_component)) { status = NT_STATUS_NO_MEMORY; goto fail; } @@ -401,7 +403,40 @@ NTSTATUS unix_convert(TALLOC_CTX *ctx, status = NT_STATUS_OBJECT_PATH_NOT_FOUND; goto fail; } + } else if (ret == 0) { + /* + * stat() or lstat() of the parent dir + * succeeded. So start the walk + * at this point. + */ + status = check_for_dot_component(&parent_fname); + if (!NT_STATUS_IS_OK(status)) { + goto fail; + } + + /* + * If there was no parent component in + * smb_fname->base_name then + * don't do this optimization. + */ + if (smb_fname->base_name != last_component) { + /* + * Safe to use CONST_DISCARD + * here as last_component points + * into our smb_fname->base_name. + */ + start = CONST_DISCARD(char *, + last_component); + + DEBUG(5,("unix_convert optimize1: name " + "= %s, dirpath = %s, " + "start = %s\n", + smb_fname->base_name, + dirpath, + start)); + } } + /* * Missing last component is ok - new file. * Also deal with permission denied elsewhere. @@ -410,6 +445,61 @@ NTSTATUS unix_convert(TALLOC_CTX *ctx, goto done; } } + } else { + /* + * We have a wildcard in the pathname. + * + * Optimization for common case where the wildcard + * is in the last component and the client already + * sent the correct case. + */ + struct smb_filename parent_fname; + const char *last_component = NULL; + + ZERO_STRUCT(parent_fname); + if (!parent_dirname(ctx, smb_fname->base_name, + &parent_fname.base_name, + &last_component)) { + status = NT_STATUS_NO_MEMORY; + goto fail; + } + /* + * If there was no parent component in + * smb_fname->base_name then + * don't do this optimization. + */ + if ((smb_fname->base_name != last_component) && + !ms_has_wild(parent_fname.base_name)) { + /* + * Wildcard isn't in the parent, i.e. + * it must be in the last component. + */ + if (posix_pathnames) { + ret = SMB_VFS_LSTAT(conn, &parent_fname); + } else { + ret = SMB_VFS_STAT(conn, &parent_fname); + } + if (ret == 0) { + status = check_for_dot_component(&parent_fname); + if (!NT_STATUS_IS_OK(status)) { + goto fail; + } + + /* + * Safe to use CONST_DISCARD + * here as last_component points + * into our smb_fname->base_name. + */ + start = CONST_DISCARD(char *,last_component); + + DEBUG(5,("unix_convert optimize2: name " + "= %s, dirpath = %s, " + "start = %s\n", + smb_fname->base_name, + dirpath, + start)); + } + } } /* @@ -480,6 +570,12 @@ NTSTATUS unix_convert(TALLOC_CTX *ctx, goto fail; } + /* Skip the stat call if it's a wildcard end. */ + if (name_has_wildcard) { + DEBUG(5,("Wildcard %s\n",start)); + goto done; + } + /* * Check if the name exists up to this point. */ |