[SCM] Samba Shared Repository - branch v3-5-test updated

Jeremy Allison jra at samba.org
Wed Nov 25 14:24:38 MST 2009


The branch, v3-5-test has been updated
       via  0047845... 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. (cherry picked from commit c96d487ae3c65c17b377bb316adac4b5775448f3)
       via  d99584e... Add RAW-CHKPATH test with case-sensitive share. Jeremy. (cherry picked from commit 108da2adaf77c152fd292bbdf5645923659a7c2c)
      from  27522fa... s3-registry: fix REG_MULTI_SZ handling in registry_push_value.

http://gitweb.samba.org/?p=samba.git;a=shortlog;h=v3-5-test


- Log -----------------------------------------------------------------
commit 00478458b56a0eea52e08605f9f1746abe22109f
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.
    (cherry picked from commit c96d487ae3c65c17b377bb316adac4b5775448f3)

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

    Add RAW-CHKPATH test with case-sensitive share.
    Jeremy.
    (cherry picked from commit 108da2adaf77c152fd292bbdf5645923659a7c2c)

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

Summary of changes:
 source3/script/tests/selftest.sh      |    3 +
 source3/script/tests/test_posix_s3.sh |    4 +
 source3/smbd/filename.c               |  147 +++++++++++++++++++++++---------
 3 files changed, 112 insertions(+), 42 deletions(-)


Changeset truncated at 500 lines:

diff --git a/source3/script/tests/selftest.sh b/source3/script/tests/selftest.sh
index 80e5042..c952ef2 100755
--- a/source3/script/tests/selftest.sh
+++ b/source3/script/tests/selftest.sh
@@ -266,6 +266,9 @@ cat >$SERVERCONFFILE<<EOF
 [hideunread]
 	copy = tmp
 	hide unreadable = yes
+[tmpcase]
+	copy = tmp
+	case sensitive = yes
 [hideunwrite]
 	copy = tmp
 	hide unwriteable files = yes
diff --git a/source3/script/tests/test_posix_s3.sh b/source3/script/tests/test_posix_s3.sh
index 11fe247..f2f137b 100755
--- a/source3/script/tests/test_posix_s3.sh
+++ b/source3/script/tests/test_posix_s3.sh
@@ -96,6 +96,10 @@ for t in $tests; do
     else
 	    testit "$name" $VALGRIND $SMBTORTURE4 $TORTURE4_OPTIONS $ADDARGS $unc -U"$username"%"$password" $t || failed=`expr $failed + 1`
     fi
+    if [ "$t" = "RAW-CHKPATH" ]; then
+	    echo "Testing with case sensitive"
+	    testit "$name" $VALGRIND $SMBTORTURE4 $TORTURE4_OPTIONS $ADDARGS "$unc"case -U"$username"%"$password" $t || failed=`expr $failed + 1`
+    fi
 done
 
 testok $0 $failed
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