[SCM] Samba Shared Repository - branch master updated

Jeremy Allison jra at samba.org
Wed Nov 25 14:23:26 MST 2009


The branch, master has been updated
       via  c96d487... Make us pass RAW-CHKPATH with a case sensitive share. I know Volker will look at this closely so here's the explaination :-). Originally on a case-sensitive share we simply did a stat (or lstat) call and returned success of fail based on the result. However this failed to take account of incoming paths with a wildcard (which must always fail, and with different error messages depending on whether the wildcard is the last component or in the path). Also it failed to take account of a stat fail with ENOENT due to a missing component of the path as the last component (which is ok as it could be a new file)  or if the ENOENT was due to the missing component within the path (not the last component) - which must return the correct error. What this means is that with "case sensitive = yes" we do one more talloc call (to get the parent directory) and one more stat call (on the parent directory) in the case where the stat call fails. I think this is an acceptabl
 e overhead to enable case sensitive shares to return the correct error messages for applications. Volker please examine carefully :-). Jeremy.
      from  108da2a... Add RAW-CHKPATH test with case-sensitive share. Jeremy.

http://gitweb.samba.org/?p=samba.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit c96d487ae3c65c17b377bb316adac4b5775448f3
Author: Jeremy Allison <jra at samba.org>
Date:   Wed Nov 25 13:17:56 2009 -0800

    Make us pass RAW-CHKPATH with a case sensitive share.
    I know Volker will look at this closely so here's the explaination :-).
    Originally on a case-sensitive share we simply did a stat (or lstat)
    call and returned success of fail based on the result. However this
    failed to take account of incoming paths with a wildcard (which must
    always fail, and with different error messages depending on whether
    the wildcard is the last component or in the path). Also it failed
    to take account of a stat fail with ENOENT due to a missing component
    of the path as the last component (which is ok as it could be a new
    file)  or if the ENOENT was due to the missing component within
    the path (not the last component) - which must return the correct
    error. What this means is that with "case sensitive = yes" we do
    one more talloc call (to get the parent directory) and one more
    stat call (on the parent directory) in the case where the stat
    call fails. I think this is an acceptable overhead to enable
    case sensitive shares to return the correct error messages for
    applications. Volker please examine carefully :-).
    Jeremy.

-----------------------------------------------------------------------

Summary of changes:
 source3/smbd/filename.c |  147 +++++++++++++++++++++++++++++++++-------------
 1 files changed, 105 insertions(+), 42 deletions(-)


Changeset truncated at 500 lines:

diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c
index 16e3631..ab79dfd 100644
--- a/source3/smbd/filename.c
+++ b/source3/smbd/filename.c
@@ -80,6 +80,24 @@ static NTSTATUS determine_path_error(const char *name,
 	}
 }
 
+static NTSTATUS check_for_dot_component(const struct smb_filename *smb_fname)
+{
+	/* Ensure we catch all names with in "/."
+	   this is disallowed under Windows and
+	   in POSIX they've already been removed. */
+	const char *p = strstr(smb_fname->base_name, "/."); /*mb safe*/
+	if (p) {
+		if (p[2] == '/') {
+			/* Error code within a pathname. */
+			return NT_STATUS_OBJECT_PATH_NOT_FOUND;
+		} else if (p[2] == '\0') {
+			/* Error code at the end of a pathname. */
+			return NT_STATUS_OBJECT_NAME_INVALID;
+		}
+	}
+	return NT_STATUS_OK;
+}
+
 /****************************************************************************
 This routine is called to convert names from the dos namespace to unix
 namespace. It needs to handle any case conversions, mangling, format changes,
@@ -294,52 +312,103 @@ NTSTATUS unix_convert(TALLOC_CTX *ctx,
 	}
 
 	/*
-	 * stat the name - if it exists then we can add the stream back (if
-	 * there was one) and be done!
+	 * If we have a wildcard we must walk the path to
+	 * find where the error is, even if case sensitive
+	 * is true.
 	 */
 
-	if (posix_pathnames) {
-		ret = SMB_VFS_LSTAT(conn, smb_fname);
-	} else {
-		ret = SMB_VFS_STAT(conn, smb_fname);
+	name_has_wildcard = ms_has_wild(smb_fname->base_name);
+	if (name_has_wildcard && !allow_wcard_last_component) {
+		/* Wildcard not valid anywhere. */
+		status = NT_STATUS_OBJECT_NAME_INVALID;
+		goto fail;
 	}
 
-	if (ret == 0) {
-		/* Ensure we catch all names with in "/."
-		   this is disallowed under Windows. */
-		const char *p = strstr(smb_fname->base_name, "/."); /*mb safe*/
-		if (p) {
-			if (p[2] == '/') {
-				/* Error code within a pathname. */
-				status = NT_STATUS_OBJECT_PATH_NOT_FOUND;
-				goto fail;
-			} else if (p[2] == '\0') {
-				/* Error code at the end of a pathname. */
-				status = NT_STATUS_OBJECT_NAME_INVALID;
+	DEBUG(5,("unix_convert begin: name = %s, dirpath = %s, start = %s\n",
+		 smb_fname->base_name, dirpath, start));
+
+	if (!name_has_wildcard) {
+		/*
+		 * stat the name - if it exists then we can add the stream back (if
+		 * there was one) and be done!
+		 */
+
+		if (posix_pathnames) {
+			ret = SMB_VFS_LSTAT(conn, smb_fname);
+		} else {
+			ret = SMB_VFS_STAT(conn, smb_fname);
+		}
+
+		if (ret == 0) {
+			status = check_for_dot_component(smb_fname);
+			if (!NT_STATUS_IS_OK(status)) {
 				goto fail;
 			}
+			/* Add the path (not including the stream) to the cache. */
+			stat_cache_add(orig_path, smb_fname->base_name,
+				       conn->case_sensitive);
+			DEBUG(5,("conversion of base_name finished %s -> %s\n",
+				 orig_path, smb_fname->base_name));
+			goto done;
 		}
-		/* Add the path (not including the stream) to the cache. */
-		stat_cache_add(orig_path, smb_fname->base_name,
-			       conn->case_sensitive);
-		DEBUG(5,("conversion of base_name finished %s -> %s\n",
-			 orig_path, smb_fname->base_name));
-		goto done;
-	}
 
-	DEBUG(5,("unix_convert begin: name = %s, dirpath = %s, start = %s\n",
-		 smb_fname->base_name, dirpath, start));
+		/*
+		 * A special case - if we don't have any wildcards or mangling chars and are case
+		 * sensitive or the underlying filesystem is case insentive then searching
+		 * won't help.
+		 */
 
-	/*
-	 * A special case - if we don't have any mangling chars and are case
-	 * sensitive or the underlying filesystem is case insentive then searching
-	 * won't help.
-	 */
+		if ((conn->case_sensitive || !(conn->fs_capabilities &
+					FILE_CASE_SENSITIVE_SEARCH)) &&
+				!mangle_is_mangled(smb_fname->base_name, conn->params)) {
 
-	if ((conn->case_sensitive || !(conn->fs_capabilities &
-				       FILE_CASE_SENSITIVE_SEARCH)) &&
-	    !mangle_is_mangled(smb_fname->base_name, conn->params)) {
-		goto done;
+			status = check_for_dot_component(smb_fname);
+			if (!NT_STATUS_IS_OK(status)) {
+				goto fail;
+			}
+
+			/*
+			 * The stat failed. Could be ok as it could be
+ 			 * a new file.
+ 			 */
+
+			if (errno == ENOTDIR || errno == ELOOP) {
+				status = NT_STATUS_OBJECT_PATH_NOT_FOUND;
+				goto fail;
+			} else if (errno == ENOENT) {
+				/*
+				 * Was it a missing last component ?
+				 * or a missing intermediate component ?
+				 */
+				struct smb_filename parent_fname;
+				ZERO_STRUCT(parent_fname);
+				if (!parent_dirname(ctx, smb_fname->base_name,
+							&parent_fname.base_name,
+							NULL)) {
+					status = NT_STATUS_NO_MEMORY;
+					goto fail;
+				}
+				if (posix_pathnames) {
+					ret = SMB_VFS_LSTAT(conn, &parent_fname);
+				} else {
+					ret = SMB_VFS_STAT(conn, &parent_fname);
+				}
+				if (ret == -1) {
+					if (errno == ENOTDIR ||
+							errno == ENOENT ||
+							errno == ELOOP) {
+						status = NT_STATUS_OBJECT_PATH_NOT_FOUND;
+						goto fail;
+					}
+				}
+				/*
+				 * Missing last component is ok - new file.
+				 * Also deal with permission denied elsewhere.
+				 * Just drop out to done.
+				 */
+				goto done;
+			}
+		}
 	}
 
 	/*
@@ -404,12 +473,6 @@ NTSTATUS unix_convert(TALLOC_CTX *ctx,
 
 		name_has_wildcard = ms_has_wild(start);
 
-		/* Wildcard not valid anywhere. */
-		if (name_has_wildcard && !allow_wcard_last_component) {
-			status = NT_STATUS_OBJECT_NAME_INVALID;
-			goto fail;
-		}
-
 		/* Wildcards never valid within a pathname. */
 		if (name_has_wildcard && end) {
 			status = NT_STATUS_OBJECT_NAME_INVALID;


-- 
Samba Shared Repository


More information about the samba-cvs mailing list