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

Jule Anger janger at samba.org
Wed Jan 12 12:44:01 UTC 2022


The branch, v4-15-test has been updated
       via  680f68a072c s3:modules: VFS CAP symlinkat always fails
       via  76e7fdb70c6 s3:modules: Fix the horrible vfs_crossrename module
       via  4a6e8bc5e29 s3: smbclient: In do_host_query(), if we need SMB1, ensure we select NT1 as the client max protocol" before continuing.
       via  4907ecaaf4e s3: selftest: Add two tests that show we try and send an SMB1 request over an SMB2 connection to list servers if "-mSMB3" is selected.
       via  a43ad2777e3 s3: includes: Make the comments describing itime consistent. Always use "invented" time.
       via  85941fe0cd1 s3: lib: In create_clock_itime(), use timespec_current() -> clock_gettime(CLOCK_REALTIME..).
       via  b48e5c61aaf s3: smbd: Create and use a common function for generating a fileid - create_clock_itime().
       via  263aeea95d8 lib: util: Add a function nt_time_to_unix_timespec_raw().
       via  032df88d61d tests: Add 2 tests for unique fileid's with top bit set (generated from itime) for files and directories.
      from  96cd0ab567e VERSION: Bump version up to Samba 4.15.4...

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


- Log -----------------------------------------------------------------
commit 680f68a072cfb7b3a0eb22498e6ee6997340adaf
Author: Pavel Filipenský <pfilipen at redhat.com>
Date:   Fri Jan 7 13:55:38 2022 +0100

    s3:modules: VFS CAP symlinkat always fails
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=14941
    
    Found by covscan.
    
    Since capnew is initialized by NULL, checking it too early makes the
    rest of the function a dead code.
    
    Pair-programmed-with: Andreas Schneider <asn at samba.org>
    
    Signed-off-by: Pavel Filipenský <pfilipen at redhat.com>
    Signed-off-by: Andreas Schneider <asn at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>
    (cherry picked from commit 41ebb7f68c5b21492f503afc4cb341a97654a43d)
    
    Autobuild-User(v4-15-test): Jule Anger <janger at samba.org>
    Autobuild-Date(v4-15-test): Wed Jan 12 12:43:05 UTC 2022 on sn-devel-184

commit 76e7fdb70c6ebf5ec4aad4c7a65cc485ac0c06c2
Author: Pavel Filipenský <pfilipen at redhat.com>
Date:   Fri Jan 7 13:16:26 2022 +0100

    s3:modules: Fix the horrible vfs_crossrename module
    
    It really has to be removed! ;-)
    
    Found by covscan. The code always leaves here as the dst variable
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=14940
    
    Pair-programmed-with: Andreas Schneider <asn at samba.org>
    
    Signed-off-by: Pavel Filipenský <pfilipen at redhat.com>
    Signed-off-by: Andreas Schneider <asn at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>
    (cherry picked from commit 4d7ed39fd8fa18f90756f215c8b0fc5d293e955e)

commit 4a6e8bc5e29cc13e10e1c59a7968edd6eb5bda62
Author: Jeremy Allison <jra at samba.org>
Date:   Mon Jan 3 16:52:25 2022 -0800

    s3: smbclient: In do_host_query(), if we need SMB1, ensure we select NT1 as the client max protocol" before continuing.
    
    Remove knownfail: selftest/knownfail.d/list_servers
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=14939
    
    Signed-off-by: Jeremy Allison <jra at samba.org>
    Reviewed-by: Noel Power <noel.power at suse.com>
    
    Autobuild-User(master): Noel Power <npower at samba.org>
    Autobuild-Date(master): Thu Jan  6 11:50:32 UTC 2022 on sn-devel-184
    
    (cherry picked from commit 099c62a654da2623653218c771dd8fabdc7cc091)

commit 4907ecaaf4e28b4a4d6bafbed83925494eff601e
Author: Jeremy Allison <jra at samba.org>
Date:   Mon Jan 3 16:48:17 2022 -0800

    s3: selftest: Add two tests that show we try and send an SMB1 request over an SMB2 connection to list servers if "-mSMB3" is selected.
    
    Add knownfail: knownfail.d/list_servers
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=14939
    
    Signed-off-by: Jeremy Allison <jra at samba.org>
    Reviewed-by: Noel Power <npower at samba.org>
    (cherry picked from commit 0d9d1546a7bad6e0fac58e146a75e4eb1ce78c11)

commit a43ad2777e3e7997faab2a8a37d168a4db559815
Author: Jones Syue <jonessyue at qnap.com>
Date:   Mon Jan 10 09:29:44 2022 -0800

    s3: includes: Make the comments describing itime consistent. Always use "invented" time.
    
    It gets confusing if we call it "imaginary" or "instantiation"
    in different places.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=14928
    
    Signed-off-by: Jones Syue <jonessyue at qnap.com>
    Reviewed-by: Jeremy Allison <jra at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>
    
    Autobuild-User(master): Jeremy Allison <jra at samba.org>
    Autobuild-Date(master): Mon Jan 10 18:42:02 UTC 2022 on sn-devel-184
    
    (cherry picked from commit 745af26a1a6531b2e906aa7c1c0355cbab658441)

commit 85941fe0cd10a01aa82d2a5a977e25c636a6b84a
Author: Jeremy Allison <jra at samba.org>
Date:   Mon Jan 10 09:01:09 2022 -0800

    s3: lib: In create_clock_itime(), use timespec_current() -> clock_gettime(CLOCK_REALTIME..).
    
    CLOCK_MONOTONIC (which we previously used) is reset
    when the system is rebooted.
    
    CLOCK_REALTIME is a "wall clock" time. It's still affected by NTP
    changes (for Linux we should probably use CLOCK_TAI instead
    but that is Linux-specific). For most systems CLOCK_REALTIME
    will be good enough.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=14928
    
    Signed-off-by: Jeremy Allison <jra at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>
    (cherry picked from commit 920611f0bc98229ac4a5ee127af7f99216075341)

commit b48e5c61aaf9c81c38f5873c22724cfc911c66ca
Author: Jeremy Allison <jra at samba.org>
Date:   Wed Jan 5 11:40:46 2022 -0800

    s3: smbd: Create and use a common function for generating a fileid - create_clock_itime().
    
    This first gets the clock_gettime_mono() value, converts to an NTTIME (as
    this is what is stored in the dos attribute EA), then mixes in 8 bits of
    randomness shifted up by 55 bits to cope with poor resolution clocks to
    avoid duplicate inodes.
    
    Using 8 bits of randomness on top of an NTTIME gives us around 114
    years headroom. We can now guarentee returning a itime-based
    fileid in a normal share (storing dos attributes in an EA).
    
    Remove knownfail.d/fileid-unique
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=14928
    
    Signed-off-by: Jeremy Allison <jra at samba.org>
    Reviewed-by: Christof Schmitt <cs at samba.org>
    
    Autobuild-User(master): Jeremy Allison <jra at samba.org>
    Autobuild-Date(master): Sat Jan  8 06:35:22 UTC 2022 on sn-devel-184
    
    (cherry picked from commit 23fbf0bad0332a0ae0d4dc3c8f6df6e7ec46b88b)

commit 263aeea95d8df206250ee40ab2a539169618eb1f
Author: Jeremy Allison <jra at samba.org>
Date:   Thu Jan 6 13:58:20 2022 -0800

    lib: util: Add a function nt_time_to_unix_timespec_raw().
    
    Not yet used. Does no checks on the converted values.
    
    A later cleanup will allow us to move nt_time_to_unix_timespec()
    and nt_time_to_full_timespec() to use common code.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=14928
    
    Signed-off-by: Jeremy Allison <jra at samba.org>
    Reviewed-by: Christof Schmitt <cs at samba.org>
    (cherry picked from commit 29d69c22a0d945193ce3dac27e1083dbc5c53f03)

commit 032df88d61d569b60f311c7447521759ac7c0735
Author: Jeremy Allison <jra at samba.org>
Date:   Thu Jan 6 15:11:20 2022 -0800

    tests: Add 2 tests for unique fileid's with top bit set (generated from itime) for files and directories.
    
    smb2.fileid_unique.fileid_unique
    smb2.fileid_unique.fileid_unique-dir
    
    Create 100 files or directories as fast as we can
    against a "normal" share, then read info on them
    and ensure (a) top bit is set (generated from itime)
    and (b) uniqueness across all generated objects
    (checks poor timestamp resolution doesn't create
    duplicate fileids).
    
    This shows that even on ext4, this is enough to
    cause duplicate fileids to be returned.
    
    Add knownfail.d/fileid-unique
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=14928
    
    Signed-off-by: Jeremy Allison <jra at samba.org>
    Reviewed-by: Christof Schmitt <cs at samba.org>
    (cherry picked from commit 30fea0d31117c1a899cd333a9b8a62ba765dbb02)

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

Summary of changes:
 lib/util/time.c                                    |  30 +++
 lib/util/time.h                                    |   2 +
 source3/client/client.c                            |   1 +
 source3/include/includes.h                         |   4 +-
 source3/include/proto.h                            |   1 +
 source3/lib/system.c                               |  52 ++++++
 source3/modules/vfs_cap.c                          |   2 +-
 source3/modules/vfs_crossrename.c                  |   2 +-
 .../script/tests/test_smbclient_list_servers.sh    |  45 +++++
 source3/selftest/tests.py                          |  20 ++
 source3/smbd/open.c                                |   6 +-
 source4/selftest/tests.py                          |   1 +
 source4/torture/smb2/create.c                      | 205 +++++++++++++++++++++
 source4/torture/smb2/smb2.c                        |   1 +
 14 files changed, 365 insertions(+), 7 deletions(-)
 create mode 100755 source3/script/tests/test_smbclient_list_servers.sh


Changeset truncated at 500 lines:

diff --git a/lib/util/time.c b/lib/util/time.c
index cec91c14791..5839e80a15b 100644
--- a/lib/util/time.c
+++ b/lib/util/time.c
@@ -867,6 +867,36 @@ _PUBLIC_ int get_time_zone(time_t t)
 	return tm_diff(&tm_utc,tm);
 }
 
+/*
+ * Raw convert an NTTIME to a unix timespec.
+ */
+
+struct timespec nt_time_to_unix_timespec_raw(
+			NTTIME nt)
+{
+	int64_t d;
+	struct timespec ret;
+
+	d = (int64_t)nt;
+	/* d is now in 100ns units, since jan 1st 1601".
+	   Save off the ns fraction. */
+
+	/*
+	 * Take the last seven decimal digits and multiply by 100.
+	 * to convert from 100ns units to 1ns units.
+	 */
+        ret.tv_nsec = (long) ((d % (1000 * 1000 * 10)) * 100);
+
+	/* Convert to seconds */
+	d /= 1000*1000*10;
+
+	/* Now adjust by 369 years to make the secs since 1970 */
+	d -= TIME_FIXUP_CONSTANT_INT;
+
+	ret.tv_sec = (time_t)d;
+	return ret;
+}
+
 struct timespec nt_time_to_unix_timespec(NTTIME nt)
 {
 	int64_t d;
diff --git a/lib/util/time.h b/lib/util/time.h
index 72347b39b99..bdb67de5431 100644
--- a/lib/util/time.h
+++ b/lib/util/time.h
@@ -343,6 +343,8 @@ bool nt_time_equal(NTTIME *t1, NTTIME *t2);
 
 void interpret_dos_date(uint32_t date,int *year,int *month,int *day,int *hour,int *minute,int *second);
 
+struct timespec nt_time_to_unix_timespec_raw(NTTIME nt);
+
 struct timespec nt_time_to_unix_timespec(NTTIME nt);
 
 time_t convert_timespec_to_time_t(struct timespec ts);
diff --git a/source3/client/client.c b/source3/client/client.c
index 98425048f4b..a8e11044b39 100644
--- a/source3/client/client.c
+++ b/source3/client/client.c
@@ -6169,6 +6169,7 @@ static int do_host_query(const char *query_host)
 
 		cli_shutdown(cli);
 		d_printf("Reconnecting with SMB1 for workgroup listing.\n");
+		lp_set_cmdline("client max protocol", "NT1");
 		status = cli_cm_open(talloc_tos(), NULL,
 				     query_host,
 				     "IPC$",
diff --git a/source3/include/includes.h b/source3/include/includes.h
index 6fc2ee25d95..c3d3d351e41 100644
--- a/source3/include/includes.h
+++ b/source3/include/includes.h
@@ -205,10 +205,10 @@ struct stat_ex {
 	struct timespec st_ex_ctime;
 	struct timespec st_ex_btime; /* birthtime */
 	/*
-	 * Immutable original birth time aka instantiation time. Set when a file
+	 * Immutable original birth time aka invented time. Set when a file
 	 * is created, never changes thereafter. May not be set by the client.
 	 */
-	struct timespec st_ex_itime; /* instantiation time */
+	struct timespec st_ex_itime; /* invented time */
 
 	blksize_t	st_ex_blksize;
 	blkcnt_t	st_ex_blocks;
diff --git a/source3/include/proto.h b/source3/include/proto.h
index a96c2c8d110..20d026f83b3 100644
--- a/source3/include/proto.h
+++ b/source3/include/proto.h
@@ -175,6 +175,7 @@ void update_stat_ex_create_time(struct stat_ex *dst, struct timespec create_time
 void update_stat_ex_file_id(struct stat_ex *dst, uint64_t file_id);
 void update_stat_ex_from_saved_stat(struct stat_ex *dst,
 				    const struct stat_ex *src);
+void create_clock_itime(struct stat_ex *dst);
 int sys_stat(const char *fname, SMB_STRUCT_STAT *sbuf,
 	     bool fake_dir_create_times);
 int sys_fstat(int fd, SMB_STRUCT_STAT *sbuf,
diff --git a/source3/lib/system.c b/source3/lib/system.c
index a14fc51ca63..83dc79101c9 100644
--- a/source3/lib/system.c
+++ b/source3/lib/system.c
@@ -310,6 +310,58 @@ void init_stat_ex_from_stat (struct stat_ex *dst,
 	dst->st_ex_iflags |= ST_EX_IFLAG_CALCULATED_FILE_ID;
 }
 
+/*******************************************************************
+ Create a clock-derived itime (invented) time. Used to generate
+ the fileid.
+********************************************************************/
+
+void create_clock_itime(struct stat_ex *dst)
+{
+	NTTIME tval;
+	struct timespec itime;
+	uint64_t mixin;
+	uint8_t rval;
+
+	/* Start with the system clock. */
+	itime = timespec_current();
+
+	/* Convert to NTTIME. */
+	tval = unix_timespec_to_nt_time(itime);
+
+	/*
+	 * In case the system clock is poor granularity
+	 * (happens on VM or docker images) then mix in
+	 * 8 bits of randomness.
+	 */
+	generate_random_buffer((unsigned char *)&rval, 1);
+	mixin = rval;
+
+	/*
+	 * Shift up by 55 bits. This gives us approx 114 years
+	 * of headroom.
+	 */
+	mixin <<= 55;
+
+	/* And OR into the nttime. */
+	tval |= mixin;
+
+	/*
+	 * Convert to a unix timespec, ignoring any
+	 * constraints on seconds being higher than
+	 * TIME_T_MAX or lower than TIME_T_MIN. These
+	 * are only needed to allow unix display time functions
+	 * to work correctly, and this is being used to
+	 * generate a fileid. All we care about is the
+	 * NTTIME being valid across all NTTIME ranges
+	 * (which we carefully ensured above).
+	 */
+
+	itime = nt_time_to_unix_timespec_raw(tval);
+
+	/* And set as a generated itime. */
+	update_stat_ex_itime(dst, itime);
+}
+
 /*******************************************************************
 A stat() wrapper.
 ********************************************************************/
diff --git a/source3/modules/vfs_cap.c b/source3/modules/vfs_cap.c
index 4a47b26c7b9..43c8edb8932 100644
--- a/source3/modules/vfs_cap.c
+++ b/source3/modules/vfs_cap.c
@@ -448,7 +448,7 @@ static int cap_symlinkat(vfs_handle_struct *handle,
 	int saved_errno = 0;
 	int ret;
 
-	if (!capold || !capnew) {
+	if (capold == NULL) {
 		errno = ENOMEM;
 		return -1;
 	}
diff --git a/source3/modules/vfs_crossrename.c b/source3/modules/vfs_crossrename.c
index 52b8af9d3f6..930eec02739 100644
--- a/source3/modules/vfs_crossrename.c
+++ b/source3/modules/vfs_crossrename.c
@@ -82,7 +82,7 @@ static NTSTATUS copy_reg(vfs_handle_struct *handle,
 	full_fname_src = full_path_from_dirfsp_atname(talloc_tos(),
 						      srcfsp,
 						      source);
-	if (full_fname_dst == NULL) {
+	if (full_fname_src == NULL) {
 		status = NT_STATUS_NO_MEMORY;
 		goto out;
 	}
diff --git a/source3/script/tests/test_smbclient_list_servers.sh b/source3/script/tests/test_smbclient_list_servers.sh
new file mode 100755
index 00000000000..884a5a25b9a
--- /dev/null
+++ b/source3/script/tests/test_smbclient_list_servers.sh
@@ -0,0 +1,45 @@
+#!/bin/sh
+#
+# Ensure we don't get an error smb1cli_req_writev_submit: called for dialect[SMB3_11]
+# when listing servers via -L.
+# BUG: https://bugzilla.samba.org/show_bug.cgi?id=14939
+
+if [ $# -lt 5 ]; then
+cat <<EOF
+Usage: test_smbclient_list_servers.sh SERVER SERVER_IP USERNAME PASSWORD SMBCLIENT
+EOF
+exit 1;
+fi
+
+SERVER="$1"
+SERVER_IP="$2"
+USERNAME="$3"
+PASSWORD="$4"
+SMBCLIENT="$5"
+shift 5
+ADDARGS="$@"
+
+incdir=$(dirname "$0")/../../../testprogs/blackbox
+. "$incdir/subunit.sh"
+
+failed=0
+
+test_smbclient_list_servers()
+{
+    cmd='CLI_FORCE_INTERACTIVE=yes $SMBCLIENT -L //$SERVER -U$USERNAME%$PASSWORD -I $SERVER_IP -p139 "$ADDARGS" </dev/null 2>&1'
+    eval echo "$cmd"
+    out=$(eval "$cmd")
+
+    echo "$out" | grep 'smb1cli_req_writev_submit:'
+    ret=$?
+    if [ $ret -eq 0 ] ; then
+       echo "$out"
+       echo 'failed - should not get: smb1cli_req_writev_submit: error.'
+       return 1
+    fi
+
+    return 0
+}
+
+testit "smb1_list_servers" test_smbclient_list_servers || failed=$((failed+1))
+testok "$0" "$failed"
diff --git a/source3/selftest/tests.py b/source3/selftest/tests.py
index 32f02396004..0654d8b0495 100755
--- a/source3/selftest/tests.py
+++ b/source3/selftest/tests.py
@@ -560,6 +560,24 @@ for env in ["fileserver"]:
     plantestsuite("samba3.blackbox.test_dangle_rmdir", env,
                   [os.path.join(samba3srcdir, "script/tests/test_delete_veto_files_only_rmdir.sh"),
                   '$SERVER', '$SERVER_IP', '$USERNAME', '$PASSWORD', '$LOCAL_PATH/veto', smbclient3])
+    plantestsuite("samba3.blackbox.test_list_servers.NT1",
+                  env + "_smb1_done",
+                  [os.path.join(samba3srcdir, "script/tests/test_smbclient_list_servers.sh"),
+                  '$SERVER',
+                  '$SERVER_IP',
+                  '$USERNAME',
+                  '$PASSWORD',
+                  smbclient3,
+                  "-mSMB3"])
+    plantestsuite("samba3.blackbox.test_list_servers.SMB2",
+                  env,
+                  [os.path.join(samba3srcdir, "script/tests/test_smbclient_list_servers.sh"),
+                  '$SERVER',
+                  '$SERVER_IP',
+                  '$USERNAME',
+                  '$PASSWORD',
+                  smbclient3,
+                  "-mSMB3"])
 
     #
     # tar command tests
@@ -935,6 +953,8 @@ for t in tests:
         plansmbtorture4testsuite(t, "ad_dc", '//$SERVER/tmp -U$USERNAME%$PASSWORD')
     elif t == "smb2.fileid":
         plansmbtorture4testsuite(t, "nt4_dc", '//$SERVER_IP/vfs_fruit_xattr -U$USERNAME%$PASSWORD')
+    elif t == "smb2.fileid_unique":
+        plansmbtorture4testsuite(t, "fileserver", '//$SERVER_IP/tmp -U$USERNAME%$PASSWORD')
     elif t == "smb2.acls_non_canonical":
         plansmbtorture4testsuite(t, "nt4_dc", '//$SERVER_IP/acls_non_canonical -U$USERNAME%$PASSWORD')
     elif t == "rpc.wkssvc":
diff --git a/source3/smbd/open.c b/source3/smbd/open.c
index 968dd8ecb00..5ed2c035318 100644
--- a/source3/smbd/open.c
+++ b/source3/smbd/open.c
@@ -4132,13 +4132,13 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn,
 	 * If we created a file and it's not a stream, this is the point where
 	 * we set the itime (aka invented time) that get's stored in the DOS
 	 * attribute xattr. The value is going to be either what the filesystem
-	 * provided or a copy of the creation date.
+	 * provided or a generated itime value.
 	 *
 	 * Either way, we turn the itime into a File-ID, unless the filesystem
 	 * provided one (unlikely).
 	 */
 	if (info == FILE_WAS_CREATED && !is_named_stream(smb_fname)) {
-		smb_fname->st.st_ex_iflags &= ~ST_EX_IFLAG_CALCULATED_ITIME;
+		create_clock_itime(&smb_fname->st);
 
 		if (lp_store_dos_attributes(SNUM(conn)) &&
 		    smb_fname->st.st_ex_iflags & ST_EX_IFLAG_CALCULATED_FILE_ID)
@@ -4320,7 +4320,7 @@ static NTSTATUS mkdir_internal(connection_struct *conn,
 		return NT_STATUS_NOT_A_DIRECTORY;
 	}
 
-	smb_dname->st.st_ex_iflags &= ~ST_EX_IFLAG_CALCULATED_ITIME;
+	create_clock_itime(&smb_dname->st);
 
 	if (lp_store_dos_attributes(SNUM(conn))) {
 		if (smb_dname->st.st_ex_iflags & ST_EX_IFLAG_CALCULATED_FILE_ID)
diff --git a/source4/selftest/tests.py b/source4/selftest/tests.py
index a16b2879bd2..61cbca43132 100755
--- a/source4/selftest/tests.py
+++ b/source4/selftest/tests.py
@@ -369,6 +369,7 @@ smb2_s3only = [
     "smb2.durable-v2-delay",
     "smb2.aio_delay",
     "smb2.fileid",
+    "smb2.fileid_unique",
     "smb2.timestamps",
 ]
 smb2 = [x for x in smbtorture4_testsuites("smb2.") if x not in smb2_s3only]
diff --git a/source4/torture/smb2/create.c b/source4/torture/smb2/create.c
index aba3f69a28a..41a6ed6e4e4 100644
--- a/source4/torture/smb2/create.c
+++ b/source4/torture/smb2/create.c
@@ -2707,6 +2707,191 @@ done:
 	return ret;
 }
 
+static bool test_fileid_unique_object(
+			struct torture_context *tctx,
+			struct smb2_tree *tree,
+			unsigned int num_objs,
+			bool create_dirs)
+{
+	TALLOC_CTX *mem_ctx = talloc_new(tctx);
+	char *fname = NULL;
+	struct smb2_handle testdirh;
+	struct smb2_handle h1;
+	struct smb2_create create;
+	unsigned int i;
+	uint64_t fileid_array[num_objs];
+	NTSTATUS status;
+	bool ret = true;
+
+	smb2_deltree(tree, DNAME);
+
+	status = torture_smb2_testdir(tree, DNAME, &testdirh);
+	torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+					"test_fileid_unique failed\n");
+	smb2_util_close(tree, testdirh);
+
+	/* Create num_obj files as rapidly as we can. */
+	for (i = 0; i < num_objs; i++) {
+		fname = talloc_asprintf(mem_ctx,
+					"%s\\testfile.%u",
+					DNAME,
+					i);
+		torture_assert_goto(tctx,
+				fname != NULL,
+				ret,
+				done,
+				"talloc failed\n");
+
+		create = (struct smb2_create) {
+			.in.desired_access = SEC_FILE_READ_ATTRIBUTE,
+			.in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
+			.in.file_attributes = FILE_ATTRIBUTE_NORMAL,
+			.in.create_disposition = NTCREATEX_DISP_CREATE,
+			.in.fname = fname,
+		};
+
+		if (create_dirs) {
+			create.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
+			create.in.create_options = FILE_DIRECTORY_FILE;
+		}
+
+		status = smb2_create(tree, tctx, &create);
+		if (!NT_STATUS_IS_OK(status)) {
+			torture_fail(tctx,
+				talloc_asprintf(tctx,
+					"test file %s could not be created\n",
+					fname));
+			TALLOC_FREE(fname);
+			ret = false;
+			goto done;
+		}
+
+		h1 = create.out.file.handle;
+		smb2_util_close(tree, h1);
+		TALLOC_FREE(fname);
+	}
+
+	/*
+	 * Get the file ids.
+	 */
+	for (i = 0; i < num_objs; i++) {
+		union smb_fileinfo finfo;
+
+		fname = talloc_asprintf(mem_ctx,
+					"%s\\testfile.%u",
+					DNAME,
+					i);
+		torture_assert_goto(tctx,
+				fname != NULL,
+				ret,
+				done,
+				"talloc failed\n");
+
+		create = (struct smb2_create) {
+			.in.desired_access = SEC_FILE_READ_ATTRIBUTE,
+			.in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
+			.in.file_attributes = FILE_ATTRIBUTE_NORMAL,
+			.in.create_disposition = NTCREATEX_DISP_OPEN,
+			.in.fname = fname,
+		};
+
+		if (create_dirs) {
+			create.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
+			create.in.create_options = FILE_DIRECTORY_FILE;
+		}
+
+		status = smb2_create(tree, tctx, &create);
+		if (!NT_STATUS_IS_OK(status)) {
+			torture_fail(tctx,
+				talloc_asprintf(tctx,
+					"test file %s could not "
+					"be opened: %s\n",
+					fname,
+					nt_errstr(status)));
+			TALLOC_FREE(fname);
+			ret = false;
+			goto done;
+		}
+
+		h1 = create.out.file.handle;
+
+		finfo = (union smb_fileinfo) {
+			.generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION,
+			.generic.in.file.handle = h1,
+		};
+
+		status = smb2_getinfo_file(tree, tctx, &finfo);
+		if (!NT_STATUS_IS_OK(status)) {
+			torture_fail(tctx,
+				talloc_asprintf(tctx,
+					"failed to get fileid for "
+					"test file %s: %s\n",
+					fname,
+					nt_errstr(status)));
+			TALLOC_FREE(fname);
+			ret = false;
+			goto done;
+		}
+		smb2_util_close(tree, h1);
+		/*
+		 * Samba created files on a "normal" share
+		 * using itime should have the top bit of the fileid set.
+		 */
+		fileid_array[i] = finfo.all_info2.out.file_id;
+
+		if ((fileid_array[i] & 0x8000000000000000) == 0) {
+			torture_fail(tctx,
+				talloc_asprintf(tctx,
+					"test file %s fileid 0x%lx top "
+					"bit not set\n",
+					fname,
+					fileid_array[i]));
+			TALLOC_FREE(fname);
+			ret = false;
+			goto done;
+		}
+		TALLOC_FREE(fname);
+	}
+
+	/* All returned fileids must be unique. 100 is small so brute force. */
+	for (i = 0; i < num_objs - 1; i++) {
+		unsigned int j;
+		for (j = i + 1; j < num_objs; j++) {
+			if (fileid_array[i] == fileid_array[j]) {
+				torture_fail(tctx,
+					talloc_asprintf(tctx,
+						"fileid %u == fileid %u (0x%lu)\n",
+						i,
+						j,
+						fileid_array[i]));
+				ret = false;
+				goto done;
+			}
+		}
+	}
+
+done:
+
+	smb2_util_close(tree, testdirh);
+	smb2_deltree(tree, DNAME);
+	talloc_free(mem_ctx);
+	return ret;
+}
+
+static bool test_fileid_unique(
+			struct torture_context *tctx,
+			struct smb2_tree *tree)
+{
+	return test_fileid_unique_object(tctx, tree, 100, false);
+}
+


-- 
Samba Shared Repository



More information about the samba-cvs mailing list