[SCM] Samba Shared Repository - branch master updated
Jeremy Allison
jra at samba.org
Thu Mar 31 18:48:01 UTC 2022
The branch, master has been updated
via 9fa67ba8eeb vfs_shadow_copy2: implement readdir()
via ba9c5ba8ec5 CI: add a test listing a snapshotted directory
via f734e960eb7 CI: avoid smb2.twrp being run by plansmbtorture4testsuite() directly
from 06bfac2125d s3: smbd: Preserve the fsp->fsp_name->st buf across a MSG_SMB_FILE_RENAME message.
https://git.samba.org/?p=samba.git;a=shortlog;h=master
- Log -----------------------------------------------------------------
commit 9fa67ba8eeb6249d4b91b894e80eb1985c845314
Author: Ralph Boehme <slow at samba.org>
Date: Thu Mar 24 16:25:22 2022 +0100
vfs_shadow_copy2: implement readdir()
RN: shadow_copy2 fails listing snapshotted dirs with shadow:fixinodes
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15035
Signed-off-by: Ralph Boehme <slow at samba.org>
Reviewed-by: Jeremy Allison <jra at samba.org>
Autobuild-User(master): Jeremy Allison <jra at samba.org>
Autobuild-Date(master): Thu Mar 31 18:47:42 UTC 2022 on sn-devel-184
commit ba9c5ba8ec54e72d68e3f753a5350afe0fb50a7c
Author: Ralph Boehme <slow at samba.org>
Date: Thu Mar 24 17:31:00 2022 +0100
CI: add a test listing a snapshotted directory
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15035
Signed-off-by: Ralph Boehme <slow at samba.org>
Reviewed-by: Jeremy Allison <jra at samba.org>
commit f734e960eb7ad98808ad8757de51c51d3db86a2b
Author: Ralph Boehme <slow at samba.org>
Date: Mon Mar 28 20:05:26 2022 +0200
CI: avoid smb2.twrp being run by plansmbtorture4testsuite() directly
This should only be run by a blackbox test.
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15035
Signed-off-by: Ralph Boehme <slow at samba.org>
Reviewed-by: Jeremy Allison <jra at samba.org>
-----------------------------------------------------------------------
Summary of changes:
source3/modules/vfs_shadow_copy2.c | 91 ++++++++++++
source3/script/tests/test_shadow_copy_torture.sh | 21 +++
source3/selftest/tests.py | 3 +
source4/selftest/tests.py | 1 +
source4/torture/smb2/create.c | 168 +++++++++++++++++++++++
5 files changed, 284 insertions(+)
Changeset truncated at 500 lines:
diff --git a/source3/modules/vfs_shadow_copy2.c b/source3/modules/vfs_shadow_copy2.c
index 8e92cc71e18..dfdc6735dfb 100644
--- a/source3/modules/vfs_shadow_copy2.c
+++ b/source3/modules/vfs_shadow_copy2.c
@@ -3331,6 +3331,96 @@ static int shadow_copy2_connect(struct vfs_handle_struct *handle,
return 0;
}
+static struct dirent *shadow_copy2_readdir(vfs_handle_struct *handle,
+ struct files_struct *dirfsp,
+ DIR *dirp,
+ SMB_STRUCT_STAT *sbuf)
+{
+ struct shadow_copy2_private *priv = NULL;
+ struct dirent *ent = NULL;
+ struct smb_filename atname;
+ struct smb_filename *full_fname = NULL;
+ time_t timestamp = 0;
+ char *stripped = NULL;
+ char *conv = NULL;
+ char *abspath = NULL;
+ bool converted = false;
+
+ SMB_VFS_HANDLE_GET_DATA(handle, priv, struct shadow_copy2_private,
+ return NULL);
+
+ ent = SMB_VFS_NEXT_READDIR(handle, dirfsp, dirp, sbuf);
+ if (ent == NULL) {
+ return NULL;
+ }
+ if (sbuf == NULL) {
+ return ent;
+ }
+ if (ISDOT(dirfsp->fsp_name->base_name) && ISDOTDOT(ent->d_name)) {
+ return ent;
+ }
+
+ atname = (struct smb_filename) {
+ .base_name = ent->d_name,
+ .twrp = dirfsp->fsp_name->twrp,
+ .flags = dirfsp->fsp_name->flags,
+ };
+
+ full_fname = full_path_from_dirfsp_atname(talloc_tos(),
+ dirfsp,
+ &atname);
+ if (full_fname == NULL) {
+ return NULL;
+ }
+
+ if (!shadow_copy2_strip_snapshot_converted(talloc_tos(),
+ handle,
+ full_fname,
+ ×tamp,
+ &stripped,
+ &converted)) {
+ TALLOC_FREE(full_fname);
+ return NULL;
+ }
+
+ if (timestamp == 0 && !converted) {
+ /* Not a snapshot path, no need for convert_sbuf() */
+ TALLOC_FREE(stripped);
+ TALLOC_FREE(full_fname);
+ return ent;
+ }
+
+ if (timestamp == 0) {
+ abspath = make_path_absolute(talloc_tos(),
+ priv,
+ full_fname->base_name);
+ TALLOC_FREE(full_fname);
+ if (abspath == NULL) {
+ return NULL;
+ }
+ } else {
+ conv = shadow_copy2_convert(talloc_tos(),
+ handle,
+ stripped,
+ timestamp);
+ TALLOC_FREE(stripped);
+ if (conv == NULL) {
+ return NULL;
+ }
+
+ abspath = make_path_absolute(talloc_tos(), priv, conv);
+ TALLOC_FREE(conv);
+ if (abspath == NULL) {
+ return NULL;
+ }
+ }
+
+ convert_sbuf(handle, abspath, sbuf);
+
+ TALLOC_FREE(abspath);
+ return ent;
+}
+
static struct vfs_fn_pointers vfs_shadow_copy2_fns = {
.connect_fn = shadow_copy2_connect,
.disk_free_fn = shadow_copy2_disk_free,
@@ -3362,6 +3452,7 @@ static struct vfs_fn_pointers vfs_shadow_copy2_fns = {
.pwrite_recv_fn = shadow_copy2_pwrite_recv,
.connectpath_fn = shadow_copy2_connectpath,
.parent_pathname_fn = shadow_copy2_parent_pathname,
+ .readdir_fn = shadow_copy2_readdir,
};
static_decl_vfs;
diff --git a/source3/script/tests/test_shadow_copy_torture.sh b/source3/script/tests/test_shadow_copy_torture.sh
index 4ae2f9f707f..8f9d1be6927 100755
--- a/source3/script/tests/test_shadow_copy_torture.sh
+++ b/source3/script/tests/test_shadow_copy_torture.sh
@@ -191,6 +191,25 @@ test_hiddenfile()
return 0
}
+test_shadow_copy_listdir_fix_inodes()
+{
+ local msg
+
+ msg=$1
+
+ #delete snapshots from previous tests
+ find $WORKDIR -name ".snapshots" -exec rm -rf {} \; 1>/dev/null 2>&1
+ build_snapshots
+
+ testit "$msg" \
+ $SMBTORTURE \
+ -U$USERNAME%$PASSWORD \
+ "//$SERVER/shadow_write" \
+ --option="torture:twrp_snapshot=$SNAPSHOT" \
+ smb2.twrp.listdir || \
+ failed=`expr $failed + 1`
+}
+
build_files $WORKDIR
# test open for writing and write behaviour of snapshoted files
@@ -204,4 +223,6 @@ testit "fix inodes with hardlink" test_shadow_copy_fix_inodes || failed=`expr $f
testit "Test reading DOS attribute" test_hiddenfile || failed=`expr $failed + 1`
+test_shadow_copy_listdir_fix_inodes "fix inodes when listing directory"
+
exit $failed
diff --git a/source3/selftest/tests.py b/source3/selftest/tests.py
index cae09571fe1..71a0143604e 100755
--- a/source3/selftest/tests.py
+++ b/source3/selftest/tests.py
@@ -1019,6 +1019,9 @@ for t in tests:
"//$SERVER_IP/async_dosmode_shadow_copy2 -U$USERNAME%$PASSWORD")
elif t == "smb2.rename":
plansmbtorture4testsuite(t, "fileserver", '//$SERVER_IP/tmp -U$USERNAME%$PASSWORD')
+ elif t == "smb2.twrp":
+ # This is being driven by samba3.blackbox.shadow_copy_torture
+ pass
elif t == "rpc.wkssvc":
plansmbtorture4testsuite(t, "ad_member", '//$SERVER/tmp -U$DC_USERNAME%$DC_PASSWORD')
elif t == "rpc.srvsvc":
diff --git a/source4/selftest/tests.py b/source4/selftest/tests.py
index 726b6d8fc1f..944bf110e09 100755
--- a/source4/selftest/tests.py
+++ b/source4/selftest/tests.py
@@ -380,6 +380,7 @@ smb2_s3only = [
"smb2.fileid_unique",
"smb2.timestamps",
"smb2.async_dosmode",
+ "smb2.twrp",
]
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 4327fea9cc7..433fbe085f0 100644
--- a/source4/torture/smb2/create.c
+++ b/source4/torture/smb2/create.c
@@ -1965,6 +1965,173 @@ done:
return ret;
}
+static bool test_twrp_listdir(struct torture_context *tctx,
+ struct smb2_tree *tree)
+{
+ struct smb2_create create;
+ struct smb2_handle h = {{0}};
+ struct smb2_find find;
+ unsigned int count;
+ union smb_search_data *d;
+ char *p = NULL;
+ struct tm tm;
+ time_t t;
+ uint64_t nttime;
+ const char *snapshot = NULL;
+ uint64_t normal_fileid;
+ uint64_t snapshot_fileid;
+ NTSTATUS status;
+ bool ret = true;
+
+ snapshot = torture_setting_string(tctx, "twrp_snapshot", NULL);
+ if (snapshot == NULL) {
+ torture_fail(tctx, "missing 'twrp_snapshot' option\n");
+ }
+
+ torture_comment(tctx, "Testing File-Ids of directory listing "
+ "with timewarp (%s)\n",
+ snapshot);
+
+ setenv("TZ", "GMT", 1);
+
+ /* strptime does not set tm.tm_isdst but mktime assumes DST is in
+ * effect if it is greather than 1. */
+ ZERO_STRUCT(tm);
+
+ p = strptime(snapshot, "@GMT-%Y.%m.%d-%H.%M.%S", &tm);
+ torture_assert_goto(tctx, p != NULL, ret, done, "strptime\n");
+ torture_assert_goto(tctx, *p == '\0', ret, done, "strptime\n");
+
+ t = mktime(&tm);
+ unix_to_nt_time(&nttime, t);
+
+ /*
+ * 1: Query the file's File-Id
+ */
+ create = (struct smb2_create) {
+ .in.desired_access = SEC_FILE_READ_DATA,
+ .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
+ .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
+ .in.create_disposition = NTCREATEX_DISP_OPEN,
+ .in.fname = "subdir/hardlink",
+ .in.query_on_disk_id = true,
+ };
+
+ status = smb2_create(tree, tctx, &create);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "test file could not be created\n");
+ smb2_util_close(tree, create.out.file.handle);
+ normal_fileid = BVAL(&create.out.on_disk_id, 0);
+
+ /*
+ * 2: check directory listing of the file returns same File-Id
+ */
+
+ create = (struct smb2_create) {
+ .in.desired_access = SEC_DIR_LIST,
+ .in.file_attributes = FILE_ATTRIBUTE_DIRECTORY,
+ .in.create_disposition = NTCREATEX_DISP_OPEN,
+ .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
+ .in.fname = "subdir",
+ .in.create_options = NTCREATEX_OPTIONS_DIRECTORY,
+ };
+
+ status = smb2_create(tree, tctx, &create);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_create\n");
+ h = create.out.file.handle;
+
+ find = (struct smb2_find) {
+ .in.file.handle = h,
+ .in.pattern = "*",
+ .in.max_response_size = 0x1000,
+ .in.level = SMB2_FIND_ID_BOTH_DIRECTORY_INFO,
+ };
+
+ status = smb2_find_level(tree, tree, &find, &count, &d);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_find_level failed\n");
+
+ smb2_util_close(tree, h);
+
+ torture_assert_int_equal_goto(tctx, count, 3, ret, done, "Bad count\n");
+ torture_assert_str_equal_goto(tctx,
+ d[2].id_both_directory_info.name.s,
+ "hardlink",
+ ret, done, "bad name");
+ torture_assert_u64_equal_goto(tctx,
+ d[2].id_both_directory_info.file_id,
+ normal_fileid,
+ ret, done, "bad fileid\n");
+
+ /*
+ * 3: Query File-Id of snapshot of the file and check the File-Id is
+ * different compared to the basefile
+ */
+
+ create = (struct smb2_create) {
+ .in.desired_access = SEC_FILE_READ_DATA,
+ .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
+ .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
+ .in.create_disposition = NTCREATEX_DISP_OPEN,
+ .in.fname = "subdir/hardlink",
+ .in.query_on_disk_id = true,
+ .in.timewarp = nttime,
+ };
+
+ status = smb2_create(tree, tctx, &create);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "test file could not be created\n");
+ smb2_util_close(tree, create.out.file.handle);
+
+ snapshot_fileid = BVAL(&create.out.on_disk_id, 0);
+
+ /*
+ * 4: List directory of the snapshot and check the File-Id returned here
+ * is the same as in 3.
+ */
+
+ create = (struct smb2_create) {
+ .in.desired_access = SEC_DIR_LIST,
+ .in.file_attributes = FILE_ATTRIBUTE_DIRECTORY,
+ .in.create_disposition = NTCREATEX_DISP_OPEN,
+ .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
+ .in.fname = "subdir",
+ .in.create_options = NTCREATEX_OPTIONS_DIRECTORY,
+ .in.timewarp = nttime,
+ };
+
+ status = smb2_create(tree, tctx, &create);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_create\n");
+ h = create.out.file.handle;
+
+ find = (struct smb2_find) {
+ .in.file.handle = h,
+ .in.pattern = "*",
+ .in.max_response_size = 0x1000,
+ .in.level = SMB2_FIND_ID_BOTH_DIRECTORY_INFO,
+ };
+
+ status = smb2_find_level(tree, tree, &find, &count, &d);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "smb2_find_level failed\n");
+ smb2_util_close(tree, h);
+
+ torture_assert_int_equal_goto(tctx, count, 3, ret, done, "Bad count\n");
+ torture_assert_str_equal_goto(tctx,
+ d[2].id_both_directory_info.name.s,
+ "hardlink",
+ ret, done, "bad name");
+ torture_assert_u64_equal_goto(tctx,
+ snapshot_fileid,
+ d[2].id_both_directory_info.file_id,
+ ret, done, "bad fileid\n");
+
+done:
+ return ret;
+}
+
static bool test_fileid(struct torture_context *tctx,
struct smb2_tree *tree)
{
@@ -2988,6 +3155,7 @@ struct torture_suite *torture_smb2_twrp_init(TALLOC_CTX *ctx)
torture_suite_add_1smb2_test(suite, "write", test_twrp_write);
torture_suite_add_1smb2_test(suite, "stream", test_twrp_stream);
torture_suite_add_1smb2_test(suite, "openroot", test_twrp_openroot);
+ torture_suite_add_1smb2_test(suite, "listdir", test_twrp_listdir);
suite->description = talloc_strdup(suite, "SMB2-TWRP tests");
--
Samba Shared Repository
More information about the samba-cvs
mailing list