summaryrefslogtreecommitdiff
path: root/source3/smbd/filename.c
diff options
context:
space:
mode:
authorJeremy Allison <jra@samba.org>2010-09-08 16:55:24 -0700
committerJeremy Allison <jra@samba.org>2010-09-08 16:55:24 -0700
commitfcac46a61245e6b05f88ed80ec4b554ffd55dc63 (patch)
tree52a6a7438aef1df156313dd643192b6031bad9c4 /source3/smbd/filename.c
parent4f0b190a3086db3789e4198f5409a2b5c1980bf9 (diff)
downloadsamba-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/smbd/filename.c')
-rw-r--r--source3/smbd/filename.c98
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.
*/