[PATCH] Another vfs_fruit patch I found in the attic

Ralph Böhme slow at samba.org
Fri Apr 7 09:35:51 UTC 2017


Hi!

Another patch for vfs_fruit taking us one step further on the way to behave like
a macOS SMB server exporting HFS+.

Please review & push if happy. Thanks!

Cheerio!
-slow
-------------- next part --------------
From 8c96c6c26a41dfa293d2dfa9ac9db3a00282cfb9 Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
Date: Tue, 7 Feb 2017 07:44:40 +0100
Subject: [PATCH 1/2] vfs_fruit: resource fork open request with
 flags=O_CREAT|O_RDONLY

When receiving an SMB create request with read-only access mode and
open_if disposition, we end of calling the open() function with
flags=O_CREAT|O_RDONLY for the ._ AppleDouble file.

If the file doesn't exist, ie there's currently no rsrc stream, we create
it but then we fail to write the AppleDouble header into the file due to
the O_RDONLY open mode, leaving a 0 byte size ._ file.

Running this create requests against macOS SMB server yields an
interesting result: it returns NT_STATUS_OBJECT_NAME_NOT_FOUND even
though create dispotion is open_if. Another instance where the macOS SMB
server just exposes FSA behaviour (ie HFS+) and we have to adapt to be
compatible.

Bug: https://bugzilla.samba.org/show_bug.cgi?id=12565

Signed-off-by: Ralph Boehme <slow at samba.org>
---
 source3/modules/vfs_fruit.c | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/source3/modules/vfs_fruit.c b/source3/modules/vfs_fruit.c
index 0b5558a..b747145 100644
--- a/source3/modules/vfs_fruit.c
+++ b/source3/modules/vfs_fruit.c
@@ -2970,6 +2970,20 @@ static int fruit_open_rsrc(vfs_handle_struct *handle,
 	SMB_VFS_HANDLE_GET_DATA(handle, config,
 				struct fruit_config_data, return -1);
 
+	if (((flags & O_ACCMODE) == O_RDONLY)
+	    && (flags & O_CREAT)
+	    && !VALID_STAT(fsp->fsp_name->st))
+	{
+		/*
+		 * This means the stream doesn't exist. macOS SMB server fails
+		 * this with NT_STATUS_OBJECT_NAME_NOT_FOUND, so must we. Cf bug
+		 * 12565 and the test for this combination in
+		 * test_rfork_create().
+		 */
+		errno = ENOENT;
+		return -1;
+	}
+
 	switch (config->rsrc) {
 	case FRUIT_RSRC_STREAM:
 		fd = SMB_VFS_NEXT_OPEN(handle, smb_fname, fsp, flags, mode);
-- 
2.9.3


From 1c85fcc6613b7799a74bab2643c858def80dc350 Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
Date: Tue, 7 Feb 2017 15:13:15 +0100
Subject: [PATCH 2/2] s4/torture: vfs_fruit: test for bug 12565

Bug: https://bugzilla.samba.org/show_bug.cgi?id=12565

Signed-off-by: Ralph Boehme <slow at samba.org>
---
 source4/torture/vfs/fruit.c | 67 ++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 66 insertions(+), 1 deletion(-)

diff --git a/source4/torture/vfs/fruit.c b/source4/torture/vfs/fruit.c
index 857e738..637963b 100644
--- a/source4/torture/vfs/fruit.c
+++ b/source4/torture/vfs/fruit.c
@@ -1814,6 +1814,71 @@ done:
 	return ret;
 }
 
+static bool test_rfork_create_ro(struct torture_context *tctx,
+				 struct smb2_tree *tree)
+{
+	TALLOC_CTX *mem_ctx = talloc_new(tctx);
+	const char *fname = BASEDIR "\\torture_rfork_create";
+	const char *rfork = BASEDIR "\\torture_rfork_create" AFPRESOURCE_STREAM;
+	NTSTATUS status;
+	struct smb2_handle testdirh;
+	bool ret = true;
+	struct smb2_create create;
+
+	smb2_util_unlink(tree, fname);
+	status = torture_smb2_testdir(tree, BASEDIR, &testdirh);
+	torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "torture_smb2_testdir\n");
+	smb2_util_close(tree, testdirh);
+
+	ret = torture_setup_file(mem_ctx, tree, fname, false);
+	if (ret == false) {
+		goto done;
+	}
+
+	torture_comment(tctx, "(%s) Try opening read-only with open_if create disposition, should return ENOENT\n",
+			__location__);
+
+	ZERO_STRUCT(create);
+	create.in.fname = rfork;
+	create.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
+	create.in.desired_access = SEC_FILE_READ_DATA | SEC_STD_READ_CONTROL;
+	create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
+	create.in.share_access = FILE_SHARE_READ | FILE_SHARE_DELETE;
+	status = smb2_create(tree, mem_ctx, &(create));
+	torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND,
+					   ret, done, "smb2_create failed\n");
+
+	torture_comment(tctx, "(%s) Now write something to the rsrc stream, then the same open should succeed\n",
+			__location__);
+
+	ret = write_stream(tree, __location__, tctx, mem_ctx,
+			   fname, AFPRESOURCE_STREAM_NAME,
+			   0, 3, "foo");
+	torture_assert_goto(tctx, ret == true, ret, done, "write_stream failed\n");
+
+	ret = check_stream(tree, __location__, tctx, mem_ctx,
+			   fname, AFPRESOURCE_STREAM,
+			   0, 3, 0, 3, "foo");
+	torture_assert_goto(tctx, ret == true, ret, done, "check_stream");
+
+	ZERO_STRUCT(create);
+	create.in.fname = rfork;
+	create.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
+	create.in.desired_access = SEC_FILE_READ_DATA | SEC_STD_READ_CONTROL;
+	create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
+	create.in.share_access = FILE_SHARE_READ | FILE_SHARE_DELETE;
+	status = smb2_create(tree, mem_ctx, &(create));
+	torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create failed\n");
+
+	smb2_util_close(tree, create.out.file.handle);
+
+done:
+	smb2_util_unlink(tree, fname);
+	smb2_deltree(tree, BASEDIR);
+	talloc_free(mem_ctx);
+	return ret;
+}
+
 static bool test_adouble_conversion(struct torture_context *tctx,
 				    struct smb2_tree *tree)
 {
@@ -4007,8 +4072,8 @@ struct torture_suite *torture_vfs_fruit(void)
 	torture_suite_add_1smb2_test(suite, "delete", test_delete_file_with_rfork);
 	torture_suite_add_1smb2_test(suite, "read open rsrc after rename", test_rename_and_read_rsrc);
 	torture_suite_add_1smb2_test(suite, "readdir_attr with names with illegal ntfs characters", test_readdir_attr_illegal_ntfs);
-
 	torture_suite_add_2ns_smb2_test(suite, "invalid AFP_AfpInfo", test_invalid_afpinfo);
+	torture_suite_add_1smb2_test(suite, "creating rsrc with read-only access", test_rfork_create_ro);
 
 	return suite;
 }
-- 
2.9.3



More information about the samba-technical mailing list