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

Karolin Seeger kseeger at samba.org
Wed Sep 18 13:52:05 UTC 2019


The branch, v4-11-test has been updated
       via  d702f662901 s3/4: libsmbclient test. Test using smbc_telldir/smbc_lseekdir with smbc_readdir/smbc_readdirplus/smbc_getdents.
       via  411eb45f2c9 s3: libsmbclient: Fix smbc_lseekdir() to work with smbc_readdirplus().
       via  a70eee31213 s3: libsmbclient: Ensure SMBC_getdents_ctx() also updates the readdirplus pointers.
       via  0fbd2c08b54 s3: libsmbclient: Ensure SMBC_readdirplus_ctx() also updates the readdir pointers.
       via  a0342e92f3a s3: libsmbclient: Ensure SMBC_readdir_ctx() also updates the readdirplus pointers.
      from  872e03c2dc8 VERSION: Bump version up to 4.11.1...

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


- Log -----------------------------------------------------------------
commit d702f66290159d72c8f3c5d08ec9e9f23772611f
Author: Jeremy Allison <jra at samba.org>
Date:   Mon Aug 26 11:22:35 2019 -0700

    s3/4: libsmbclient test. Test using smbc_telldir/smbc_lseekdir with smbc_readdir/smbc_readdirplus/smbc_getdents.
    
    Ensure that for file access you can mix any of these
    three access methods for directory entries and the
    returned names/structs stay in sync across telldir/seekdir
    changes.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=14094
    
    Signed-off-by: Jeremy Allison <jra at samba.org>
    Reviewed-by: Ralph Böhme <slow at samba.org>
    
    Autobuild-User(master): Jeremy Allison <jra at samba.org>
    Autobuild-Date(master): Tue Sep  3 17:31:29 UTC 2019 on sn-devel-184
    
    (cherry picked from commit 3355601fe8541994cc41f5ed800aab9b6a2294f4)
    
    Autobuild-User(v4-11-test): Karolin Seeger <kseeger at samba.org>
    Autobuild-Date(v4-11-test): Wed Sep 18 13:51:56 UTC 2019 on sn-devel-184

commit 411eb45f2c9b9019d8a54c3c7092a3c0fc515e15
Author: Jeremy Allison <jra at samba.org>
Date:   Mon Aug 26 10:18:28 2019 -0700

    s3: libsmbclient: Fix smbc_lseekdir() to work with smbc_readdirplus().
    
    If returning files the dir_list and the dirplus_list have exactly the same
    entries, we just need to keep the next pointers in sync on seek.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=14094
    
    Signed-off-by: Jeremy Allison <jra at samba.org>
    Reviewed-by: Ralph Böhme <slow at samba.org>
    (cherry picked from commit 0d9b1645499ce12a79a137d3482434aa5d2eb47c)

commit a70eee31213189d9cf0e4b40d14e2c301ef4f2c8
Author: Jeremy Allison <jra at samba.org>
Date:   Mon Aug 26 10:07:32 2019 -0700

    s3: libsmbclient: Ensure SMBC_getdents_ctx() also updates the readdirplus pointers.
    
    If we are returning file entries, we
    have a duplicate list in dirplus.
    
    Update dirplus_next also so readdir and
    readdirplus are kept in sync.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=14094
    
    Signed-off-by: Jeremy Allison <jra at samba.org>
    Reviewed-by: Ralph Böhme <slow at samba.org>
    (cherry picked from commit 754cec7756b2ddb1cfcc3984265f01cb366beb76)

commit 0fbd2c08b548bd2588de960a5475ed5fc2de9bf7
Author: Jeremy Allison <jra at samba.org>
Date:   Mon Aug 26 10:02:47 2019 -0700

    s3: libsmbclient: Ensure SMBC_readdirplus_ctx() also updates the readdir pointers.
    
    If we are returning file entries, we
    have a duplicate list in dir_list.
    
    Update dir_next also so readdir and
    readdirplus are kept in sync.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=14094
    
    Signed-off-by: Jeremy Allison <jra at samba.org>
    Reviewed-by: Ralph Böhme <slow at samba.org>
    (cherry picked from commit 3d82b7d11cd7b78adc6b3642e64e3a8f251de869)

commit a0342e92f3a25fbf15ab0f3ad3f05e597726be81
Author: Jeremy Allison <jra at samba.org>
Date:   Mon Aug 26 09:54:06 2019 -0700

    s3: libsmbclient: Ensure SMBC_readdir_ctx() also updates the readdirplus pointers.
    
    If we are returning file entries, we
    have a duplicate list in dirplus.
    
    Update dirplus_next also so readdir and
    readdirplus are kept in sync.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=14094
    
    Signed-off-by: Jeremy Allison <jra at samba.org>
    Reviewed-by: Ralph Böhme <slow at samba.org>
    (cherry picked from commit 4bca8e097f5a909c628daa4dbfa932ddc1725ebc)

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

Summary of changes:
 source3/libsmb/libsmb_dir.c                 | 102 ++++++---
 source3/selftest/tests.py                   |   3 +-
 source4/torture/libsmbclient/libsmbclient.c | 340 ++++++++++++++++++++++++++++
 3 files changed, 418 insertions(+), 27 deletions(-)


Changeset truncated at 500 lines:

diff --git a/source3/libsmb/libsmb_dir.c b/source3/libsmb/libsmb_dir.c
index 886aa626509..df606c4adfe 100644
--- a/source3/libsmb/libsmb_dir.c
+++ b/source3/libsmb/libsmb_dir.c
@@ -1174,6 +1174,17 @@ SMBC_readdir_ctx(SMBCCTX *context,
 
         dir->dir_next = dir->dir_next->next;
 
+	/*
+	 * If we are returning file entries, we
+	 * have a duplicate list in dirplus.
+	 *
+	 * Update dirplus_next also so readdir and
+	 * readdirplus are kept in sync.
+	 */
+	if (dir->dirplus_list != NULL) {
+		dir->dirplus_next = dir->dirplus_next->next;
+	}
+
 	TALLOC_FREE(frame);
         return dirp;
 }
@@ -1220,6 +1231,17 @@ SMBC_readdirplus_ctx(SMBCCTX *context,
 	}
 	dir->dirplus_next = dir->dirplus_next->next;
 
+	/*
+	 * If we are returning file entries, we
+	 * have a duplicate list in dir_list
+	 *
+	 * Update dir_next also so readdir and
+	 * readdirplus are kept in sync.
+	 */
+	if (dir->dir_list) {
+		dir->dir_next = dir->dir_next->next;
+	}
+
 	TALLOC_FREE(frame);
 	return smb_finfo;
 }
@@ -1336,6 +1358,17 @@ SMBC_getdents_ctx(SMBCCTX *context,
 		}
 
 		dir->dir_next = dirlist = dirlist -> next;
+
+		/*
+		 * If we are returning file entries, we
+		 * have a duplicate list in dirplus.
+		 *
+		 * Update dirplus_next also so readdir and
+		 * readdirplus are kept in sync.
+		 */
+		if (dir->dirplus_list != NULL) {
+			dir->dirplus_next = dir->dirplus_next->next;
+		}
 	}
 
 	TALLOC_FREE(frame);
@@ -1639,35 +1672,43 @@ SMBC_telldir_ctx(SMBCCTX *context,
 
 /*
  * A routine to run down the list and see if the entry is OK
+ * Modifies the dir list and the dirplus list (if it exists)
+ * to point at the correct next entry on success.
  */
 
-static struct smbc_dir_list *
-check_dir_ent(struct smbc_dir_list *list,
-              struct smbc_dirent *dirent)
+static bool update_dir_ents(SMBCFILE *dir, struct smbc_dirent *dirent)
 {
+	struct smbc_dir_list *tmp_dir = dir->dir_list;
+	struct smbc_dirplus_list *tmp_dirplus = dir->dirplus_list;
 
-	/* Run down the list looking for what we want */
-
-	if (dirent) {
-
-		struct smbc_dir_list *tmp = list;
-
-		while (tmp) {
-
-			if (tmp->dirent == dirent)
-				return tmp;
-
-			tmp = tmp->next;
+	/*
+	 * Run down the list looking for what we want.
+	 * If we're enumerating files both dir_list
+	 * and dirplus_list contain the same entry
+	 * list, as they were seeded from the same
+	 * cli_list callback.
+	 *
+	 * If we're enumerating servers then
+	 * dirplus_list will be NULL, so don't
+	 * update in that case.
+	 */
 
+	while (tmp_dir != NULL) {
+		if (tmp_dir->dirent == dirent) {
+			dir->dir_next = tmp_dir;
+			if (tmp_dirplus != NULL) {
+				dir->dirplus_next = tmp_dirplus;
+			}
+			return true;
+		}
+		tmp_dir = tmp_dir->next;
+		if (tmp_dirplus != NULL) {
+			tmp_dirplus = tmp_dirplus->next;
 		}
-
 	}
-
-	return NULL;  /* Not found, or an error */
-
+	return false;
 }
 
-
 /*
  * Routine to seek on a directory
  */
@@ -1679,8 +1720,8 @@ SMBC_lseekdir_ctx(SMBCCTX *context,
 {
 	long int l_offset = offset;  /* Handle problems of size */
 	struct smbc_dirent *dirent = (struct smbc_dirent *)l_offset;
-	struct smbc_dir_list *list_ent = (struct smbc_dir_list *)NULL;
 	TALLOC_CTX *frame = talloc_stackframe();
+	bool ok;
 
 	if (!context || !context->internal->initialized) {
 
@@ -1703,6 +1744,10 @@ SMBC_lseekdir_ctx(SMBCCTX *context,
 	if (dirent == NULL) {  /* Seek to the begining of the list */
 
 		dir->dir_next = dir->dir_list;
+
+		/* Do the same for dirplus. */
+		dir->dirplus_next = dir->dirplus_list;
+
 		TALLOC_FREE(frame);
 		return 0;
 
@@ -1710,21 +1755,26 @@ SMBC_lseekdir_ctx(SMBCCTX *context,
 
         if (offset == -1) {     /* Seek to the end of the list */
                 dir->dir_next = NULL;
+
+		/* Do the same for dirplus. */
+		dir->dirplus_next = NULL;
+
 		TALLOC_FREE(frame);
                 return 0;
         }
 
-	/* Now, run down the list and make sure that the entry is OK       */
-	/* This may need to be changed if we change the format of the list */
+        /*
+         * Run down the list and make sure that the entry is OK.
+         * Update the position of both dir and dirplus lists.
+         */
 
-	if ((list_ent = check_dir_ent(dir->dir_list, dirent)) == NULL) {
+	ok = update_dir_ents(dir, dirent);
+	if (!ok) {
 		errno = EINVAL;   /* Bad entry */
 		TALLOC_FREE(frame);
 		return -1;
 	}
 
-	dir->dir_next = list_ent;
-
 	TALLOC_FREE(frame);
 	return 0;
 }
diff --git a/source3/selftest/tests.py b/source3/selftest/tests.py
index 20f2eea7661..5b5a1978988 100755
--- a/source3/selftest/tests.py
+++ b/source3/selftest/tests.py
@@ -495,7 +495,8 @@ nbt = ["nbt.dgram"]
 libsmbclient = ["libsmbclient.version", "libsmbclient.initialize",
                 "libsmbclient.configuration", "libsmbclient.setConfiguration",
                 "libsmbclient.options", "libsmbclient.opendir",
-                "libsmbclient.list_shares", "libsmbclient.readdirplus"]
+                "libsmbclient.list_shares", "libsmbclient.readdirplus",
+		"libsmbclient.readdirplus_seek"]
 
 vfs = [
     "vfs.fruit",
diff --git a/source4/torture/libsmbclient/libsmbclient.c b/source4/torture/libsmbclient/libsmbclient.c
index f9154e8a19c..b74d87aabed 100644
--- a/source4/torture/libsmbclient/libsmbclient.c
+++ b/source4/torture/libsmbclient/libsmbclient.c
@@ -18,6 +18,7 @@
 */
 
 #include "includes.h"
+#include "system/dir.h"
 #include "torture/smbtorture.h"
 #include "auth/credentials/credentials.h"
 #include "lib/cmdline/popt_common.h"
@@ -375,6 +376,343 @@ static bool torture_libsmbclient_readdirplus(struct torture_context *tctx)
 	return true;
 }
 
+static bool torture_libsmbclient_readdirplus_seek(struct torture_context *tctx)
+{
+	SMBCCTX *ctx;
+	int ret = -1;
+	int dhandle = -1;
+	int fhandle = -1;
+	const char *dname = NULL;
+	const char *full_filename[100] = {0};
+	const char *filename[100] = {0};
+	const struct libsmb_file_info *direntries[102] = {0};
+	unsigned int i = 0;
+	const char *smburl = torture_setting_string(tctx, "smburl", NULL);
+	bool success = false;
+	off_t telldir_50 = (off_t)-1;
+	off_t telldir_20 = (off_t)-1;
+	size_t getdentries_size = 0;
+	struct smbc_dirent *getdentries = NULL;
+	struct smbc_dirent *dirent_20 = NULL;
+	const struct libsmb_file_info *direntries_20 = NULL;
+
+	if (smburl == NULL) {
+		torture_fail(tctx,
+			"option --option=torture:smburl="
+			"smb://user:password@server/share missing\n");
+	}
+
+	DEBUG(0,("torture_libsmbclient_readdirplus_seek start\n"));
+
+	torture_assert(tctx, torture_libsmbclient_init_context(tctx, &ctx), "");
+	smbc_set_context(ctx);
+
+	dname = talloc_asprintf(tctx,
+				"%s/rd_seek",
+				smburl);
+	if (dname == NULL) {
+		torture_fail_goto(tctx,
+			done,
+			"talloc fail\n");
+	}
+
+	/* Ensure the files don't exist. */
+	for (i = 0; i < 100; i++) {
+		filename[i] = talloc_asprintf(tctx,
+				"test_readdirplus_%u.txt",
+				i);
+		if (filename[i] == NULL) {
+			torture_fail_goto(tctx,
+				done,
+				"talloc fail\n");
+		}
+		full_filename[i] = talloc_asprintf(tctx,
+				"%s/%s",
+				dname,
+				filename[i]);
+		if (full_filename[i] == NULL) {
+			torture_fail_goto(tctx,
+				done,
+				"talloc fail\n");
+		}
+		(void)smbc_unlink(full_filename[i]);
+	}
+	/* Ensure the directory doesn't exist. */
+	(void)smbc_rmdir(dname);
+
+	/* Create containing directory. */
+	ret = smbc_mkdir(dname, 0777);
+	if (ret != 0) {
+		torture_fail_goto(tctx,
+			done,
+			talloc_asprintf(tctx,
+				"failed to create directory '%s': %s",
+				dname,
+				strerror(errno)));
+	}
+
+	DEBUG(0,("torture_libsmbclient_readdirplus_seek create\n"));
+
+	/* Create them. */
+	for (i = 0; i < 100; i++) {
+		fhandle = smbc_creat(full_filename[i], 0666);
+		if (fhandle < 0) {
+			torture_fail_goto(tctx,
+				done,
+				talloc_asprintf(tctx,
+					"failed to create file '%s': %s",
+					full_filename[i],
+					strerror(errno)));
+		}
+		ret = smbc_close(fhandle);
+		torture_assert_int_equal_goto(tctx,
+			ret,
+			0,
+			success,
+			done,
+			talloc_asprintf(tctx,
+				"failed to close handle for '%s'",
+				full_filename[i]));
+	}
+
+	DEBUG(0,("torture_libsmbclient_readdirplus_seek enum\n"));
+
+	/* Now enumerate the directory. */
+	dhandle = smbc_opendir(dname);
+	if (dhandle < 0) {
+		torture_fail_goto(tctx,
+			done,
+			talloc_asprintf(tctx,
+				"failed to obtain "
+				"directory handle for '%s' : %s",
+				dname,
+				strerror(errno)));
+	}
+
+	/* Read all the files. 100 we created plus . and .. */
+	for (i = 0; i < 102; i++) {
+		bool found = false;
+		unsigned int j;
+
+		direntries[i] = smbc_readdirplus(dhandle);
+		if (direntries[i] == NULL) {
+			break;
+		}
+
+		/* Store at offset 50. */
+		if (i == 50) {
+			telldir_50 = smbc_telldir(dhandle);
+			if (telldir_50 == (off_t)-1) {
+				torture_fail_goto(tctx,
+					done,
+					talloc_asprintf(tctx,
+						"telldir failed file %s\n",
+						direntries[i]->name));
+			}
+		}
+
+		if (ISDOT(direntries[i]->name)) {
+			continue;
+		}
+		if (ISDOTDOT(direntries[i]->name)) {
+			continue;
+		}
+
+		/* Ensure all our files exist. */
+		for (j = 0; j < 100; j++) {
+			if (strcmp(direntries[i]->name,
+				filename[j]) == 0) {
+				found = true;
+			}
+		}
+		if (!found) {
+			torture_fail_goto(tctx,
+				done,
+				talloc_asprintf(tctx,
+					"failed to find file %s\n",
+					direntries[i]->name));
+		}
+	}
+
+	/*
+	 * We're seeking on in-memory lists here, so
+	 * whilst the handle is open we really should
+	 * get the same files back in the same order.
+	 */
+
+	ret = smbc_lseekdir(dhandle, telldir_50);
+	torture_assert_int_equal_goto(tctx,
+		ret,
+		0,
+		success,
+		done,
+		talloc_asprintf(tctx,
+			"failed to seek (50) directory handle for '%s'",
+			dname));
+
+	DEBUG(0,("torture_libsmbclient_readdirplus_seek seek\n"));
+
+	for (i = 51; i < 102; i++) {
+		const struct libsmb_file_info *entry =
+				smbc_readdirplus(dhandle);
+		if (entry != direntries[i]) {
+			torture_fail_goto(tctx,
+				done,
+				talloc_asprintf(tctx,
+					"after seek - failed to find "
+					"file %s - got %s\n",
+					direntries[i]->name,
+					entry->name));
+		}
+	}
+
+	/* Seek back to the start. */
+	ret = smbc_lseekdir(dhandle, 0);
+	torture_assert_int_equal_goto(tctx,
+		ret,
+		0,
+		success,
+		done,
+		talloc_asprintf(tctx,
+			"failed to seek directory handle to start for '%s'",
+			dname));
+
+	/*
+	 * Mix getdents/readdir/readdirplus with lseek to ensure
+	 * we get the same result.
+	 */
+
+	/* Allocate the space for 20 entries.
+	 * Tricky as we need to allocate 20 struct smbc_dirent's + space
+	 * for the name lengths.
+	 */
+	getdentries_size = 20 * (sizeof(struct smbc_dirent) +
+				strlen("test_readdirplus_1000.txt") + 1);
+
+	getdentries = (struct smbc_dirent *)talloc_array_size(tctx,
+						getdentries_size,
+						1);
+
+	ret = smbc_getdents(dhandle, getdentries, getdentries_size);
+	torture_assert_goto(tctx,
+		(ret != -1),
+		success,
+		done,
+		talloc_asprintf(tctx,
+			"smbd_getdents(1) for '%s' failed\n",
+			dname));
+
+	telldir_20 = smbc_telldir(dhandle);
+	if (telldir_20 == (off_t)-1) {
+		torture_fail_goto(tctx,
+			done,
+			talloc_asprintf(tctx,
+				"telldir (20) failed\n"));
+	}
+	/* Read another 20. */
+	ret = smbc_getdents(dhandle, getdentries, getdentries_size);
+	torture_assert_goto(tctx,
+		(ret != -1),
+		success,
+		done,
+		talloc_asprintf(tctx,
+			"smbd_getdents(2) for '%s' failed\n",
+			dname));
+
+	/* Seek back to 20. */
+	ret = smbc_lseekdir(dhandle, telldir_20);
+	torture_assert_int_equal_goto(tctx,
+		ret,
+		0,
+		success,
+		done,
+		talloc_asprintf(tctx,
+			"failed to seek (20) directory handle for '%s'",
+			dname));
+
+	/* Read with readdir. */
+	dirent_20 = smbc_readdir(dhandle);
+	if (dirent_20 == NULL) {
+		torture_fail_goto(tctx,
+			done,
+			talloc_asprintf(tctx,
+				"smbc_readdir (20) failed\n"));
+	}
+
+	/* Ensure the getdents and readdir names are the same. */
+	ret = strcmp(dirent_20->name, getdentries[0].name);
+	if (ret != 0) {
+		torture_fail_goto(tctx,
+			done,
+			talloc_asprintf(tctx,
+				"after seek (20) readdir name missmatch "
+				"file %s - got %s\n",
+				dirent_20->name,
+				getdentries[0].name));
+	}
+
+	/* Seek back to 20. */
+	ret = smbc_lseekdir(dhandle, telldir_20);
+	torture_assert_int_equal_goto(tctx,
+		ret,
+		0,
+		success,
+		done,
+		talloc_asprintf(tctx,
+			"failed to seek (20) directory handle for '%s'",
+			dname));
+	/* Read with readdirplus. */
+	direntries_20 = smbc_readdirplus(dhandle);
+	if (direntries_20 == NULL) {
+		torture_fail_goto(tctx,
+			done,
+			talloc_asprintf(tctx,
+				"smbc_readdirplus (20) failed\n"));
+	}
+
+	/* Ensure the readdirplus and readdir names are the same. */


-- 
Samba Shared Repository



More information about the samba-cvs mailing list