[SCM] Samba Shared Repository - branch v4-13-test updated

Karolin Seeger kseeger at samba.org
Thu Nov 26 09:44:03 UTC 2020


The branch, v4-13-test has been updated
       via  441bf80265f smbclient: Fix recursive mget
       via  67364d982d9 test3: Add a test showing that smbclient recursive mget is broken
       via  b4be2f994d1 smbclient: Slightly simplify do_mget()
       via  ddb0d43f0ae smbclient: Remove the "abort_mget" variable
      from  8c82d0fd49b vfs_shadow_copy2: Preserve all open flags assuming ROFS

https://git.samba.org/?p=samba.git;a=shortlog;h=v4-13-test


- Log -----------------------------------------------------------------
commit 441bf80265f41ab6384c2b209943d36c3c441b37
Author: Volker Lendecke <vl at samba.org>
Date:   Mon Sep 28 15:03:41 2020 +0200

    smbclient: Fix recursive mget
    
    Make do_mget rely on do_list() already doing the recursion in a
    breadth-first manner. The previous code called do_list() from within
    its callback. Unfortunately the recent simplifications of do_list()
    broke this, leading to recursive mget to segfault. Instead of figuring
    out how this worked before the simplifications in do_list() (I did
    spend a few hours on this) and fixing it, I chose to restructure
    do_mget() to not recursively call do_list() anymore but instead rely
    on do_list() to do the recursion. Saves quite a few lines of code and
    complexity.
    
    Bug: https://bugzilla.samba.org/show_bug.cgi?id=14517
    Signed-off-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>
    
    Autobuild-User(master): Jeremy Allison <jra at samba.org>
    Autobuild-Date(master): Wed Sep 30 17:23:45 UTC 2020 on sn-devel-184
    
    (cherry picked from commit 9f24b5098f796f364a3f403ad4e9ae28b3c0935a)
    
    Autobuild-User(v4-13-test): Karolin Seeger <kseeger at samba.org>
    Autobuild-Date(v4-13-test): Thu Nov 26 09:43:32 UTC 2020 on sn-devel-184

commit 67364d982d911f80604145b95904d075b13bb036
Author: Volker Lendecke <vl at samba.org>
Date:   Mon Sep 28 16:29:27 2020 +0200

    test3: Add a test showing that smbclient recursive mget is broken
    
    Bug: https://bugzilla.samba.org/show_bug.cgi?id=14517
    Signed-off-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>
    (cherry picked from commit 254a5b034e5a081c9d3f28717a4b54d2af0180fc)

commit b4be2f994d1776a6ed6507d17bb9a1b5a378a29d
Author: Volker Lendecke <vl at samba.org>
Date:   Mon Sep 28 14:21:24 2020 +0200

    smbclient: Slightly simplify do_mget()
    
    Put the prompt query into a separate if-statement, move the "quest"
    variable closer to its use
    
    Bug: https://bugzilla.samba.org/show_bug.cgi?id=14517
    Signed-off-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>
    (cherry picked from commit 71bc4d4b8d94458ac2e40d659f06110d434fd5c9)

commit ddb0d43f0ae064fc6cc4c9a466eb98e002b520fd
Author: Volker Lendecke <vl at samba.org>
Date:   Mon Sep 28 14:11:13 2020 +0200

    smbclient: Remove the "abort_mget" variable
    
    This was never set to true anywhere in the code
    
    Bug: https://bugzilla.samba.org/show_bug.cgi?id=14517
    Signed-off-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>
    (cherry picked from commit 8fa451d2b052223a11b24ffc2a956b80d03aaa7c)

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

Summary of changes:
 source3/client/client.c                     | 152 ++++++++--------------------
 source3/script/tests/test_smbclient_mget.sh |  39 +++++++
 source3/selftest/tests.py                   |  10 ++
 3 files changed, 93 insertions(+), 108 deletions(-)
 create mode 100755 source3/script/tests/test_smbclient_mget.sh


Changeset truncated at 500 lines:

diff --git a/source3/client/client.c b/source3/client/client.c
index f65293849d0..8c7ceb644aa 100644
--- a/source3/client/client.c
+++ b/source3/client/client.c
@@ -87,8 +87,6 @@ static char dest_ss_str[INET6_ADDRSTRLEN];
 
 #define SEPARATORS " \t\n\r"
 
-static bool abort_mget = true;
-
 /* timing globals */
 uint64_t get_total_size = 0;
 unsigned int get_total_time_ms = 0;
@@ -1203,12 +1201,10 @@ static NTSTATUS do_mget(struct cli_state *cli_state, struct file_info *finfo,
 		    const char *dir)
 {
 	TALLOC_CTX *ctx = talloc_tos();
-	NTSTATUS status = NT_STATUS_OK;
-	char *rname = NULL;
-	char *quest = NULL;
-	char *saved_curdir = NULL;
-	char *mget_mask = NULL;
-	char *new_cd = NULL;
+	const char *client_cwd = NULL;
+	size_t client_cwd_len;
+	char *path = NULL;
+	char *local_path = NULL;
 
 	if (!finfo->name) {
 		return NT_STATUS_OK;
@@ -1217,121 +1213,63 @@ static NTSTATUS do_mget(struct cli_state *cli_state, struct file_info *finfo,
 	if (strequal(finfo->name,".") || strequal(finfo->name,".."))
 		return NT_STATUS_OK;
 
-	if (abort_mget)	{
-		d_printf("mget aborted\n");
-		return NT_STATUS_UNSUCCESSFUL;
-	}
-
-	if (finfo->attr & FILE_ATTRIBUTE_DIRECTORY) {
-		if (asprintf(&quest,
-			 "Get directory %s? ",finfo->name) < 0) {
-			return NT_STATUS_NO_MEMORY;
-		}
-	} else {
-		if (asprintf(&quest,
-			 "Get file %s? ",finfo->name) < 0) {
-			return NT_STATUS_NO_MEMORY;
-		}
-	}
-
-	if (prompt && !yesno(quest)) {
-		SAFE_FREE(quest);
+	if ((finfo->attr & FILE_ATTRIBUTE_DIRECTORY) && !recurse) {
 		return NT_STATUS_OK;
 	}
-	SAFE_FREE(quest);
 
-	if (!(finfo->attr & FILE_ATTRIBUTE_DIRECTORY)) {
-		rname = talloc_asprintf(ctx,
-				"%s%s",
-				client_get_cur_dir(),
-				finfo->name);
-		if (!rname) {
+	if (prompt) {
+		const char *object = (finfo->attr & FILE_ATTRIBUTE_DIRECTORY) ?
+			"directory" : "file";
+		char *quest = NULL;
+		bool ok;
+
+		quest = talloc_asprintf(
+			ctx, "Get %s %s? ", object, finfo->name);
+		if (quest == NULL) {
 			return NT_STATUS_NO_MEMORY;
 		}
-		rname = client_clean_name(ctx, rname);
-		if (rname == NULL) {
-			return NT_STATUS_NO_MEMORY;
+
+		ok = yesno(quest);
+		TALLOC_FREE(quest);
+		if (!ok) {
+			return NT_STATUS_OK;
 		}
-		do_get(rname, finfo->name, false);
-		TALLOC_FREE(rname);
-		return NT_STATUS_OK;
 	}
 
-	/* handle directories */
-	saved_curdir = talloc_strdup(ctx, client_get_cur_dir());
-	if (!saved_curdir) {
+	path = talloc_asprintf(
+		ctx, "%s%c%s", dir, CLI_DIRSEP_CHAR, finfo->name);
+	if (path == NULL) {
 		return NT_STATUS_NO_MEMORY;
 	}
-
-	new_cd = talloc_asprintf(ctx,
-				"%s%s%s",
-				client_get_cur_dir(),
-				finfo->name,
-				CLI_DIRSEP_STR);
-	if (!new_cd) {
+	path = client_clean_name(ctx, path);
+	if (path == NULL) {
 		return NT_STATUS_NO_MEMORY;
 	}
-	new_cd = client_clean_name(ctx, new_cd);
-	if (new_cd == NULL) {
-		return NT_STATUS_NO_MEMORY;
-	}
-	client_set_cur_dir(new_cd);
-
-	string_replace(finfo->name,'\\','/');
-	if (lowercase) {
-		if (!strlower_m(finfo->name)) {
-			return NT_STATUS_INVALID_PARAMETER;
-		}
-	}
 
-	if (!directory_exist(finfo->name) &&
-	    mkdir(finfo->name,0777) != 0) {
-		d_printf("failed to create directory %s\n",finfo->name);
-		client_set_cur_dir(saved_curdir);
-		return map_nt_error_from_unix(errno);
-	}
-
-	if (chdir(finfo->name) != 0) {
-		d_printf("failed to chdir to directory %s\n",finfo->name);
-		client_set_cur_dir(saved_curdir);
-		return map_nt_error_from_unix(errno);
-	}
-
-	mget_mask = talloc_asprintf(ctx,
-			"%s*",
-			client_get_cur_dir());
+	/*
+	 * Skip the path prefix if we've done a remote "cd" when
+	 * creating the local path
+	 */
+	client_cwd = client_get_cur_dir();
+	client_cwd_len = strlen(client_cwd);
 
-	if (!mget_mask) {
+	local_path = talloc_strdup(ctx, path + client_cwd_len);
+	if (local_path == NULL) {
+		TALLOC_FREE(path);
 		return NT_STATUS_NO_MEMORY;
 	}
+	string_replace(local_path, CLI_DIRSEP_CHAR, '/');
 
-	mget_mask = client_clean_name(ctx, mget_mask);
-	if (mget_mask == NULL) {
-		return NT_STATUS_NO_MEMORY;
-	}
-	status = do_list(mget_mask,
-			 (FILE_ATTRIBUTE_SYSTEM
-			  | FILE_ATTRIBUTE_HIDDEN
-			  | FILE_ATTRIBUTE_DIRECTORY),
-			 do_mget, false, true);
-	if (!NT_STATUS_IS_OK(status)
-	 && !NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
-		/*
-		 * Ignore access denied errors to ensure all permitted files are
-		 * pulled down.
-		 */
-		return status;
-	}
+	if (finfo->attr & FILE_ATTRIBUTE_DIRECTORY) {
+		int ret = mkdir(local_path, 0777);
 
-	if (chdir("..") == -1) {
-		d_printf("do_mget: failed to chdir to .. (error %s)\n",
-			strerror(errno) );
-		return map_nt_error_from_unix(errno);
+		if ((ret == -1) && (errno != EEXIST)) {
+			return map_nt_error_from_unix(errno);
+		}
+	} else {
+		do_get(path, local_path, false);
 	}
-	client_set_cur_dir(saved_curdir);
-	TALLOC_FREE(mget_mask);
-	TALLOC_FREE(saved_curdir);
-	TALLOC_FREE(new_cd);
+
 	return NT_STATUS_OK;
 }
 
@@ -1419,8 +1357,6 @@ static int cmd_mget(void)
 		attribute |= FILE_ATTRIBUTE_DIRECTORY;
 	}
 
-	abort_mget = false;
-
 	while (next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
 
 		mget_mask = talloc_strdup(ctx, client_get_cur_dir());
@@ -1440,7 +1376,7 @@ static int cmd_mget(void)
 		if (mget_mask == NULL) {
 			return 1;
 		}
-		status = do_list(mget_mask, attribute, do_mget, false, true);
+		status = do_list(mget_mask, attribute, do_mget, recurse, true);
 		if (!NT_STATUS_IS_OK(status)) {
 			return 1;
 		}
@@ -1462,7 +1398,7 @@ static int cmd_mget(void)
 		if (mget_mask == NULL) {
 			return 1;
 		}
-		status = do_list(mget_mask, attribute, do_mget, false, true);
+		status = do_list(mget_mask, attribute, do_mget, recurse, true);
 		if (!NT_STATUS_IS_OK(status)) {
 			return 1;
 		}
diff --git a/source3/script/tests/test_smbclient_mget.sh b/source3/script/tests/test_smbclient_mget.sh
new file mode 100755
index 00000000000..45f62f15d4d
--- /dev/null
+++ b/source3/script/tests/test_smbclient_mget.sh
@@ -0,0 +1,39 @@
+#!/bin/sh
+
+if [ $# -lt 6 ]; then
+cat <<EOF
+Usage: $0 smbclient3 server share user password directory
+EOF
+exit 1;
+fi
+
+incdir=`dirname $0`/../../../testprogs/blackbox
+. $incdir/subunit.sh
+
+failed=0
+
+SMBCLIENT3="$1"; shift
+SERVER="$1"; shift
+SHARE="$1"; shift
+USERNAME="$1"; shift
+PASSWORD="$1"; shift
+DIRECTORY="$1"; shift
+
+# Can't use "testit" here -- it somehow breaks the -c command passed
+# to smbclient into two, spoiling the "mget"
+
+name="smbclient mget"
+subunit_start_test "$name"
+output=$("$SMBCLIENT3" //"$SERVER"/"$SHARE" \
+         -U"$USERNAME"%"$PASSWORD" -c "recurse;prompt;mget $DIRECTORY")
+status=$?
+if [ x$status = x0 ]; then
+    subunit_pass_test "$name"
+else
+    echo "$output" | subunit_fail_test "$name"
+fi
+
+testit "rm foo" rm "$DIRECTORY"/foo || failed=`expr $failed + 1`
+testit "rmdir $DIRECTORY" rmdir "$DIRECTORY" || failed=`expr $failed + 1`
+
+testok $0 $failed
diff --git a/source3/selftest/tests.py b/source3/selftest/tests.py
index d05de6bd08c..f9202f3f93a 100755
--- a/source3/selftest/tests.py
+++ b/source3/selftest/tests.py
@@ -1098,6 +1098,16 @@ for env in ["ad_member_idmap_rid:local", "maptoguest:local"]:
 
 plantestsuite("samba3.blackbox.itime", "ad_dc", [os.path.join(samba3srcdir, "script/tests/test_itime.sh"), '$SERVER', '$USERNAME', '$PASSWORD', '$LOCAL_PATH', smbclient3, 'xattr'])
 
+plantestsuite("samba3.blackbox.smbclient-mget",
+              "fileserver",
+              [os.path.join(samba3srcdir, "script/tests/test_smbclient_mget.sh"),
+               smbclient3,
+               "$SERVER",
+               "tmp",
+               "$USERNAME",
+               "$PASSWORD",
+               "valid_users"])
+
 t = "readdir-timestamp"
 plantestsuite(
     "samba3.smbtorture_s3.plain.%s" % t,


-- 
Samba Shared Repository



More information about the samba-cvs mailing list