The Samba-Bugzilla – Attachment 14562 Details for
Bug 13646
File saving issues with vfs_fruit on samba >= 4.8.5
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Patch for 4.9 cherry-picked from master
bug13646-v49.patch (text/plain), 94.18 KB, created by
Ralph Böhme
on 2018-11-02 09:36:09 UTC
(
hide
)
Description:
Patch for 4.9 cherry-picked from master
Filename:
MIME Type:
Creator:
Ralph Böhme
Created:
2018-11-02 09:36:09 UTC
Size:
94.18 KB
patch
obsolete
>From 87c31ae9219055c359b161db4426e9a203f395ce Mon Sep 17 00:00:00 2001 >From: Ralph Boehme <slow@samba.org> >Date: Thu, 23 Aug 2018 12:07:20 +0200 >Subject: [PATCH 01/34] vfs_streams_xattr: fix open implementation > >Since a long time the modules's open function happily returned success >when opening a non existent stream without O_CREAT. > >This change fixes it to return -1 and errno=ENOATTR if > >o get_ea_value() returns NT_STATUS_NOT_FOUND (eg mapped from > getxattr() = -1, errno=ENOATTR) and > >o flags doesn't contain O_CREAT > >Bug: https://bugzilla.samba.org/show_bug.cgi?id=13646 > >Signed-off-by: Ralph Boehme <slow@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >(cherry picked from commit 9f58997d7a1ab0358963a45cb8bf291e7afa8068) >--- > source3/modules/vfs_streams_xattr.c | 64 +++++++++++++++++------------ > 1 file changed, 38 insertions(+), 26 deletions(-) > >diff --git a/source3/modules/vfs_streams_xattr.c b/source3/modules/vfs_streams_xattr.c >index 8714007cb8d..87c5589395a 100644 >--- a/source3/modules/vfs_streams_xattr.c >+++ b/source3/modules/vfs_streams_xattr.c >@@ -407,6 +407,7 @@ static int streams_xattr_open(vfs_handle_struct *handle, > char *xattr_name = NULL; > int pipe_fds[2]; > int fakefd = -1; >+ bool set_empty_xattr = false; > int ret; > > SMB_VFS_HANDLE_GET_DATA(handle, config, struct streams_xattr_config, >@@ -440,39 +441,37 @@ static int streams_xattr_open(vfs_handle_struct *handle, > goto fail; > } > >- /* >- * Return a valid fd, but ensure any attempt to use it returns an error >- * (EPIPE). >- */ >- ret = pipe(pipe_fds); >- if (ret != 0) { >- goto fail; >- } >- >- close(pipe_fds[1]); >- pipe_fds[1] = -1; >- fakefd = pipe_fds[0]; >- > status = get_ea_value(talloc_tos(), handle->conn, NULL, > smb_fname, xattr_name, &ea); > > DEBUG(10, ("get_ea_value returned %s\n", nt_errstr(status))); > >- if (!NT_STATUS_IS_OK(status) >- && !NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) { >- /* >- * The base file is not there. This is an error even if we got >- * O_CREAT, the higher levels should have created the base >- * file for us. >- */ >- DEBUG(10, ("streams_xattr_open: base file %s not around, " >- "returning ENOENT\n", smb_fname->base_name)); >- errno = ENOENT; >- goto fail; >+ if (!NT_STATUS_IS_OK(status)) { >+ if (!NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) { >+ /* >+ * The base file is not there. This is an error even if >+ * we got O_CREAT, the higher levels should have created >+ * the base file for us. >+ */ >+ DBG_DEBUG("streams_xattr_open: base file %s not around, " >+ "returning ENOENT\n", smb_fname->base_name); >+ errno = ENOENT; >+ goto fail; >+ } >+ >+ if (!(flags & O_CREAT)) { >+ errno = ENOATTR; >+ goto fail; >+ } >+ >+ set_empty_xattr = true; > } > >- if ((!NT_STATUS_IS_OK(status) && (flags & O_CREAT)) || >- (flags & O_TRUNC)) { >+ if (flags & O_TRUNC) { >+ set_empty_xattr = true; >+ } >+ >+ if (set_empty_xattr) { > /* > * The attribute does not exist or needs to be truncated > */ >@@ -495,6 +494,19 @@ static int streams_xattr_open(vfs_handle_struct *handle, > } > } > >+ /* >+ * Return a valid fd, but ensure any attempt to use it returns an error >+ * (EPIPE). >+ */ >+ ret = pipe(pipe_fds); >+ if (ret != 0) { >+ goto fail; >+ } >+ >+ close(pipe_fds[1]); >+ pipe_fds[1] = -1; >+ fakefd = pipe_fds[0]; >+ > sio = VFS_ADD_FSP_EXTENSION(handle, fsp, struct stream_io, NULL); > if (sio == NULL) { > errno = ENOMEM; >-- >2.17.2 > > >From 24a6618cad279ab32a0bb3acefaaf831a76785be Mon Sep 17 00:00:00 2001 >From: Ralph Boehme <slow@samba.org> >Date: Fri, 19 Oct 2018 22:21:10 +0200 >Subject: [PATCH 02/34] s4:torture/vfs/fruit: skip a few tests when running > against a macOS SMB server > >These tests are designed to test specific vfs_fruit functionality. > >Bug: https://bugzilla.samba.org/show_bug.cgi?id=13646 > >Signed-off-by: Ralph Boehme <slow@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >(cherry picked from commit 242f42ef79e51e35ab33331e2f2d7c9feaac36f8) >--- > source4/torture/vfs/fruit.c | 15 +++++++++++++++ > 1 file changed, 15 insertions(+) > >diff --git a/source4/torture/vfs/fruit.c b/source4/torture/vfs/fruit.c >index 2eaf698c4e0..b15958afe07 100644 >--- a/source4/torture/vfs/fruit.c >+++ b/source4/torture/vfs/fruit.c >@@ -2111,6 +2111,11 @@ static bool test_adouble_conversion(struct torture_context *tctx, > ":com.apple.metadata" "\xef\x80\xa2" "_kMDItemUserTags:$DATA", > ":foo" "\xef\x80\xa2" "bar:$DATA", /* "foo:bar:$DATA" */ > }; >+ bool is_osx = torture_setting_bool(tctx, "osx", false); >+ >+ if (is_osx) { >+ torture_skip(tctx, "Test only works with Samba\n"); >+ } > > smb2_deltree(tree, BASEDIR); > >@@ -2185,6 +2190,11 @@ static bool test_adouble_conversion_wo_xattr(struct torture_context *tctx, > union smb_search_data *d; > const char *data = "This resource fork intentionally left blank"; > size_t datalen = strlen(data); >+ bool is_osx = torture_setting_bool(tctx, "osx", false); >+ >+ if (is_osx) { >+ torture_skip(tctx, "Test only works with Samba\n"); >+ } > > smb2_deltree(tree, BASEDIR); > >@@ -4742,6 +4752,11 @@ static bool test_nfs_aces(struct torture_context *tctx, > struct security_descriptor *psd = NULL; > NTSTATUS status; > bool ret = true; >+ bool is_osx = torture_setting_bool(tctx, "osx", false); >+ >+ if (is_osx) { >+ torture_skip(tctx, "Test only works with Samba\n"); >+ } > > ret = enable_aapl(tctx, tree); > torture_assert(tctx, ret == true, "enable_aapl failed"); >-- >2.17.2 > > >From 0b040777796ac83268283b0bd068c4b51b3be812 Mon Sep 17 00:00:00 2001 >From: Ralph Boehme <slow@samba.org> >Date: Wed, 17 Oct 2018 10:51:45 +0200 >Subject: [PATCH 03/34] s4:torture/vfs/fruit: fix a few error checks in "delete > AFP_AfpInfo by writing all 0" > >Bug: https://bugzilla.samba.org/show_bug.cgi?id=13646 > >Signed-off-by: Ralph Boehme <slow@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >(cherry picked from commit 394d1fc9ac8373ea7419ea9514750422bd6e504d) >--- > source4/torture/vfs/fruit.c | 8 ++++---- > 1 file changed, 4 insertions(+), 4 deletions(-) > >diff --git a/source4/torture/vfs/fruit.c b/source4/torture/vfs/fruit.c >index b15958afe07..3039c4ecc5b 100644 >--- a/source4/torture/vfs/fruit.c >+++ b/source4/torture/vfs/fruit.c >@@ -3675,8 +3675,8 @@ static bool test_afpinfo_all0(struct torture_context *tctx, > create.in.fname = fname; > > status = smb2_create(tree, mem_ctx, &create); >- torture_assert_goto(tctx, ret == true, ret, done, >- "smb2_create failed\n"); >+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, >+ "smb2_create failed\n"); > baseh = create.out.file.handle; > > ZERO_STRUCT(create); >@@ -3686,8 +3686,8 @@ static bool test_afpinfo_all0(struct torture_context *tctx, > create.in.fname = sname; > > status = smb2_create(tree, mem_ctx, &create); >- torture_assert_goto(tctx, ret == true, ret, done, >- "smb2_create failed\n"); >+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, >+ "smb2_create failed\n"); > h1 = create.out.file.handle; > > status = smb2_util_write(tree, h1, infobuf, 0, AFP_INFO_SIZE); >-- >2.17.2 > > >From 877c5c4d450555d0b70d26ea0045e33dd90132d9 Mon Sep 17 00:00:00 2001 >From: Ralph Boehme <slow@samba.org> >Date: Thu, 11 Oct 2018 17:13:52 +0200 >Subject: [PATCH 04/34] s4:torture/vfs/fruit: set share_access to > NTCREATEX_SHARE_ACCESS_MASK in check_stream_list > >Avoid sharing conflicts with other opens on the basefile. > >Bug: https://bugzilla.samba.org/show_bug.cgi?id=13646 > >Signed-off-by: Ralph Boehme <slow@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >(cherry picked from commit 1d4e50649b02c7c2314aa04e08f9946e21b6b37d) >--- > source4/torture/vfs/fruit.c | 1 + > 1 file changed, 1 insertion(+) > >diff --git a/source4/torture/vfs/fruit.c b/source4/torture/vfs/fruit.c >index 3039c4ecc5b..d067a9c97e2 100644 >--- a/source4/torture/vfs/fruit.c >+++ b/source4/torture/vfs/fruit.c >@@ -3053,6 +3053,7 @@ static bool check_stream_list(struct smb2_tree *tree, > create.in.desired_access = SEC_FILE_ALL; > create.in.create_options = is_dir ? NTCREATEX_OPTIONS_DIRECTORY : 0; > create.in.file_attributes = is_dir ? FILE_ATTRIBUTE_DIRECTORY : FILE_ATTRIBUTE_NORMAL; >+ create.in.share_access = NTCREATEX_SHARE_ACCESS_MASK; > status = smb2_create(tree, tmp_ctx, &create); > torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create"); > h = create.out.file.handle; >-- >2.17.2 > > >From 2c5f40eede9993df99dba98da2934173cb470a28 Mon Sep 17 00:00:00 2001 >From: Ralph Boehme <slow@samba.org> >Date: Mon, 15 Oct 2018 15:31:21 +0200 >Subject: [PATCH 05/34] s4:torture/vfs/fruit: update test "SMB2/CREATE context > AAPL" to work against macOS > >Bug: https://bugzilla.samba.org/show_bug.cgi?id=13646 > >Signed-off-by: Ralph Boehme <slow@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >(cherry picked from commit dba9a4743fc42b57f03b6ace24753ce8091f629f) >--- > source4/torture/vfs/fruit.c | 6 +++++- > 1 file changed, 5 insertions(+), 1 deletion(-) > >diff --git a/source4/torture/vfs/fruit.c b/source4/torture/vfs/fruit.c >index d067a9c97e2..0e463a7e451 100644 >--- a/source4/torture/vfs/fruit.c >+++ b/source4/torture/vfs/fruit.c >@@ -2306,6 +2306,7 @@ static bool test_aapl(struct torture_context *tctx, > uint32_t aapl_reply_bitmap; > uint32_t aapl_server_caps; > uint32_t aapl_vol_caps; >+ uint32_t expected_vol_caps = 0; > char *model; > struct smb2_find f; > unsigned int count; >@@ -2424,8 +2425,11 @@ static bool test_aapl(struct torture_context *tctx, > goto done; > } > >+ if (is_osx_server) { >+ expected_vol_caps = 5; >+ } > aapl_vol_caps = BVAL(aapl->data.data, 24); >- if (aapl_vol_caps != 0) { >+ if (aapl_vol_caps != expected_vol_caps) { > /* this will fail on a case insensitive fs ... */ > torture_result(tctx, TORTURE_FAIL, > "(%s) unexpected vol_caps: %d", >-- >2.17.2 > > >From 012de21f27ac19cd1068eb6d78d6e31a6a3e3bb1 Mon Sep 17 00:00:00 2001 >From: Ralph Boehme <slow@samba.org> >Date: Mon, 15 Oct 2018 15:39:12 +0200 >Subject: [PATCH 06/34] s4:torture/vfs/fruit: update test "stream names" to > work with macOS > >o create the basefile before trying to create a stream on it, otherwise > this fails on macOS > >o write something to the stream, otherwise the stream is not listed as > macOS hides 0-byte sized streams > >Bug: https://bugzilla.samba.org/show_bug.cgi?id=13646 > >Signed-off-by: Ralph Boehme <slow@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >(cherry picked from commit 125498861abeeed5bde727ff98d88d9ce4af6c75) >--- > source4/torture/vfs/fruit.c | 8 ++++++++ > 1 file changed, 8 insertions(+) > >diff --git a/source4/torture/vfs/fruit.c b/source4/torture/vfs/fruit.c >index 0e463a7e451..681dde53d06 100644 >--- a/source4/torture/vfs/fruit.c >+++ b/source4/torture/vfs/fruit.c >@@ -3132,6 +3132,9 @@ static bool test_stream_names(struct torture_context *tctx, > CHECK_STATUS(status, NT_STATUS_OK); > smb2_util_close(tree, h); > >+ ret = torture_setup_file(mem_ctx, tree, fname, false); >+ torture_assert_goto(tctx, ret, ret, done, "torture_setup_file"); >+ > torture_comment(tctx, "(%s) testing stream names\n", __location__); > ZERO_STRUCT(create); > create.in.desired_access = SEC_FILE_WRITE_DATA; >@@ -3146,6 +3149,11 @@ static bool test_stream_names(struct torture_context *tctx, > > status = smb2_create(tree, mem_ctx, &create); > CHECK_STATUS(status, NT_STATUS_OK); >+ >+ status = smb2_util_write(tree, create.out.file.handle, "foo", 0, 3); >+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, >+ "smb2_util_write failed\n"); >+ > smb2_util_close(tree, create.out.file.handle); > > ret = check_stream_list(tree, tctx, fname, 2, streams, false); >-- >2.17.2 > > >From e3fbaa610d104ec24cf0671a73560c0b48eb350a Mon Sep 17 00:00:00 2001 >From: Ralph Boehme <slow@samba.org> >Date: Wed, 31 Oct 2018 15:49:45 +0100 >Subject: [PATCH 07/34] s4:torture/vfs/fruit: ensure a directory handle is > closed in all code paths > >Otherwise we get a sharing violation when running against Samba and >opening the directory a second time. > >Bug: https://bugzilla.samba.org/show_bug.cgi?id=13646 > >Signed-off-by: Ralph Boehme <slow@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >(cherry picked from commit f7551d8fb3599a6a71dd0570bad02bdc48324107) >--- > source4/torture/vfs/fruit.c | 11 ++++------- > 1 file changed, 4 insertions(+), 7 deletions(-) > >diff --git a/source4/torture/vfs/fruit.c b/source4/torture/vfs/fruit.c >index 681dde53d06..141faa1bc5b 100644 >--- a/source4/torture/vfs/fruit.c >+++ b/source4/torture/vfs/fruit.c >@@ -3232,15 +3232,12 @@ static bool test_rename_dir_openfile(struct torture_context *torture, > torture_assert_ntstatus_equal(torture, status, > NT_STATUS_ACCESS_DENIED, > "smb2_setinfo_file"); >- >- ZERO_STRUCT(cl.smb2); >- cl.smb2.level = RAW_CLOSE_SMB2; >- cl.smb2.in.file.handle = d1; >- status = smb2_close(tree, &(cl.smb2)); >- torture_assert_ntstatus_ok(torture, status, "smb2_close"); >- ZERO_STRUCT(d1); > } > >+ status = smb2_util_close(tree, d1); >+ torture_assert_ntstatus_ok(torture, status, "smb2_util_close\n"); >+ ZERO_STRUCT(d1); >+ > torture_comment(torture, "Enabling AAPL\n"); > > ret = enable_aapl(torture, tree); >-- >2.17.2 > > >From 0f324ea42ddbdcf37707a7bf84c6933901778ec4 Mon Sep 17 00:00:00 2001 >From: Ralph Boehme <slow@samba.org> >Date: Mon, 15 Oct 2018 16:24:19 +0200 >Subject: [PATCH 08/34] s4:torture/vfs/fruit: update test "read open rsrc after > rename" to work with macOS > >macOS SMB server seems to return NT_STATUS_SHARING_VIOLATION in this >case while Windows 2016 returns NT_STATUS_ACCESS_DENIED. > >Lets stick with the Windows error code for now in the Samba fileserver, >but let the test pass against macOS. > >Bug: https://bugzilla.samba.org/show_bug.cgi?id=13646 > >Signed-off-by: Ralph Boehme <slow@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >(cherry picked from commit 9cd9859dc10d425d29774d221ec9ad697192b466) >--- > source4/torture/vfs/fruit.c | 17 +++++++++++++++-- > 1 file changed, 15 insertions(+), 2 deletions(-) > >diff --git a/source4/torture/vfs/fruit.c b/source4/torture/vfs/fruit.c >index 141faa1bc5b..43c9dd11c77 100644 >--- a/source4/torture/vfs/fruit.c >+++ b/source4/torture/vfs/fruit.c >@@ -4179,6 +4179,8 @@ static bool test_rename_and_read_rsrc(struct torture_context *tctx, > const char *fname_renamed = "test_rename_openfile_renamed"; > const char *data = "1234567890"; > union smb_setfileinfo sinfo; >+ bool server_is_macos = torture_setting_bool(tctx, "osx", false); >+ NTSTATUS expected_status; > > ret = enable_aapl(tctx, tree); > torture_assert_goto(tctx, ret == true, ret, done, "enable_aapl failed"); >@@ -4229,14 +4231,25 @@ static bool test_rename_and_read_rsrc(struct torture_context *tctx, > sinfo.rename_information.in.root_fid = 0; > sinfo.rename_information.in.new_name = fname_renamed; > >+ if (server_is_macos) { >+ expected_status = NT_STATUS_SHARING_VIOLATION; >+ } else { >+ expected_status = NT_STATUS_ACCESS_DENIED; >+ } >+ > status = smb2_setinfo_file(tree, &sinfo); > torture_assert_ntstatus_equal_goto( >- tctx, status, NT_STATUS_ACCESS_DENIED, ret, done, >+ tctx, status, expected_status, ret, done, > "smb2_setinfo_file failed"); > >- smb2_util_close(tree, h1); > smb2_util_close(tree, h2); > >+ status = smb2_util_write(tree, h1, "foo", 0, 3); >+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, >+ "write failed\n"); >+ >+ smb2_util_close(tree, h1); >+ > done: > smb2_util_unlink(tree, fname); > smb2_util_unlink(tree, fname_renamed); >-- >2.17.2 > > >From 9a790a4c3c7c5c7197a9541a5b646fcdd2f6ea88 Mon Sep 17 00:00:00 2001 >From: Ralph Boehme <slow@samba.org> >Date: Tue, 9 Oct 2018 18:48:08 +0200 >Subject: [PATCH 09/34] s4:torture/vfs/fruit: expand existing test "setinfo > delete-on-close AFP_AfpInfo" a little bit > >Add a check that verifies a create on a stream gets >NT_STATUS_DELETE_PENDING after delete-on-close has been set. > >Bug: https://bugzilla.samba.org/show_bug.cgi?id=13646 > >Signed-off-by: Ralph Boehme <slow@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >(cherry picked from commit 0d9a80b6b2e3f51cad122ee0dc78c2f4dfdebcb5) >--- > source4/torture/vfs/fruit.c | 17 +++++++++++++++++ > 1 file changed, 17 insertions(+) > >diff --git a/source4/torture/vfs/fruit.c b/source4/torture/vfs/fruit.c >index 43c9dd11c77..52ccd693794 100644 >--- a/source4/torture/vfs/fruit.c >+++ b/source4/torture/vfs/fruit.c >@@ -3450,6 +3450,10 @@ static bool test_setinfo_delete_on_close(struct torture_context *tctx, > const char *sname = BASEDIR "\\file" AFPINFO_STREAM_NAME; > const char *type_creator = "SMB,OLE!"; > AfpInfo *info = NULL; >+ const char *streams[] = { >+ AFPINFO_STREAM, >+ "::$DATA" >+ }; > const char *streams_basic[] = { > "::$DATA" > }; >@@ -3491,6 +3495,19 @@ static bool test_setinfo_delete_on_close(struct torture_context *tctx, > status = smb2_setinfo_file(tree, &sfinfo); > torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "set delete-on-close failed"); > >+ ret = check_stream_list(tree, tctx, fname, 2, streams, false); >+ torture_assert_goto(tctx, ret == true, ret, done, "Bad streams"); >+ >+ ZERO_STRUCT(create); >+ create.in.create_disposition = NTCREATEX_DISP_OPEN; >+ create.in.desired_access = SEC_FILE_ALL; >+ create.in.fname = sname; >+ create.in.file_attributes = FILE_ATTRIBUTE_NORMAL; >+ create.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION; >+ status = smb2_create(tree, mem_ctx, &create); >+ torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_DELETE_PENDING, >+ ret, done, "Got unexpected AFP_AfpInfo stream"); >+ > smb2_util_close(tree, h1); > > ret = check_stream_list(tree, tctx, fname, 1, streams_basic, false); >-- >2.17.2 > > >From ba643030337040cd35f5192fca2c4fd80df83d37 Mon Sep 17 00:00:00 2001 >From: Ralph Boehme <slow@samba.org> >Date: Wed, 10 Oct 2018 12:47:07 +0200 >Subject: [PATCH 10/34] s4:torture/vfs/fruit: expand existing vfs_test "null > afpinfo" > >This adds a check that a read on a seperate handle also sees the >previously created AFP_AfpInfo stream. > >Bug: https://bugzilla.samba.org/show_bug.cgi?id=13646 > >Signed-off-by: Ralph Boehme <slow@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >(cherry picked from commit 6f428607e35055b9ce1a04a625d43740bf5c76b2) >--- > source4/torture/vfs/fruit.c | 16 ++++++++++++++++ > 1 file changed, 16 insertions(+) > >diff --git a/source4/torture/vfs/fruit.c b/source4/torture/vfs/fruit.c >index 52ccd693794..272a2a98782 100644 >--- a/source4/torture/vfs/fruit.c >+++ b/source4/torture/vfs/fruit.c >@@ -4091,6 +4091,8 @@ static bool test_null_afpinfo(struct torture_context *tctx, > AfpInfo *afpinfo = NULL; > char *afpinfo_buf = NULL; > const char *type_creator = "SMB,OLE!"; >+ struct smb2_handle handle2; >+ struct smb2_read r; > > torture_comment(tctx, "Checking create of AfpInfo stream\n"); > >@@ -4129,6 +4131,20 @@ static bool test_null_afpinfo(struct torture_context *tctx, > status = smb2_read_recv(req[1], tree, &read); > torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_read_recv failed"); > >+ status = torture_smb2_testfile_access(tree, sname, &handle2, >+ SEC_FILE_READ_DATA); >+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, >+ "torture_smb2_testfile failed\n"); >+ r = (struct smb2_read) { >+ .in.file.handle = handle2, >+ .in.length = AFP_INFO_SIZE, >+ }; >+ >+ status = smb2_read(tree, tree, &r); >+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, >+ "torture_smb2_testfile failed\n"); >+ smb2_util_close(tree, handle2); >+ > afpinfo = torture_afpinfo_new(mem_ctx); > torture_assert_goto(tctx, afpinfo != NULL, ret, done, "torture_afpinfo_new failed"); > >-- >2.17.2 > > >From b58b5f7a135f0c24247bcf9e7a1d951e9531eee4 Mon Sep 17 00:00:00 2001 >From: Ralph Boehme <slow@samba.org> >Date: Mon, 15 Oct 2018 15:17:08 +0200 >Subject: [PATCH 11/34] s4:torture/vfs/fruit: update test "creating rsrc with > read-only access" for newer macOS versions > >While this operation failed against older macOS versions, it passes >against versions 10.12 and newer. Update the test accordingly, a >subsequent commit will then update our implementation. > >Bug: https://bugzilla.samba.org/show_bug.cgi?id=13646 > >Signed-off-by: Ralph Boehme <slow@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >(cherry picked from commit c3cf09a0791ed4dfb7ca18d175396ac1aca5d2ed) >--- > selftest/knownfail.d/samba3.vfs.fruit | 3 +++ > source4/torture/vfs/fruit.c | 28 +-------------------------- > 2 files changed, 4 insertions(+), 27 deletions(-) > >diff --git a/selftest/knownfail.d/samba3.vfs.fruit b/selftest/knownfail.d/samba3.vfs.fruit >index 6307e2b3404..a2758ffeded 100644 >--- a/selftest/knownfail.d/samba3.vfs.fruit >+++ b/selftest/knownfail.d/samba3.vfs.fruit >@@ -1,2 +1,5 @@ > ^samba3.vfs.fruit streams_depot.OS X AppleDouble file conversion\(nt4_dc\) > ^samba3.vfs.fruit streams_depot.OS X AppleDouble file conversion without embedded xattr\(nt4_dc\) >+^samba3.vfs.fruit metadata_netatalk.creating rsrc with read-only access\(nt4_dc\) >+^samba3.vfs.fruit metadata_stream.creating rsrc with read-only access\(nt4_dc\) >+^samba3.vfs.fruit streams_depot.creating rsrc with read-only access\(nt4_dc\) >diff --git a/source4/torture/vfs/fruit.c b/source4/torture/vfs/fruit.c >index 272a2a98782..8dd34e39294 100644 >--- a/source4/torture/vfs/fruit.c >+++ b/source4/torture/vfs/fruit.c >@@ -2045,35 +2045,9 @@ static bool test_rfork_create_ro(struct torture_context *tctx, > } > > torture_comment(tctx, "(%s) Try opening read-only with " >- "open_if create disposition, should return ENOENT\n", >+ "open_if create disposition, should work\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; >-- >2.17.2 > > >From 28314a029b2246855ced6bc3b592c56e13ebe2cb Mon Sep 17 00:00:00 2001 >From: Ralph Boehme <slow@samba.org> >Date: Mon, 22 Oct 2018 12:32:09 +0200 >Subject: [PATCH 12/34] vfs_fruit: update handling of read-only creation of > resource fork > >macOS SMB server versions supports this since 10.12, so we adapt our >behaviour. > >Bug: https://bugzilla.samba.org/show_bug.cgi?id=13646 > >Signed-off-by: Ralph Boehme <slow@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >(cherry picked from commit 055ca448f1a2bd995291af1810c9ec94f90f32dd) >--- > selftest/knownfail.d/samba3.vfs.fruit | 3 --- > source3/modules/vfs_fruit.c | 23 +++-------------------- > 2 files changed, 3 insertions(+), 23 deletions(-) > >diff --git a/selftest/knownfail.d/samba3.vfs.fruit b/selftest/knownfail.d/samba3.vfs.fruit >index a2758ffeded..6307e2b3404 100644 >--- a/selftest/knownfail.d/samba3.vfs.fruit >+++ b/selftest/knownfail.d/samba3.vfs.fruit >@@ -1,5 +1,2 @@ > ^samba3.vfs.fruit streams_depot.OS X AppleDouble file conversion\(nt4_dc\) > ^samba3.vfs.fruit streams_depot.OS X AppleDouble file conversion without embedded xattr\(nt4_dc\) >-^samba3.vfs.fruit metadata_netatalk.creating rsrc with read-only access\(nt4_dc\) >-^samba3.vfs.fruit metadata_stream.creating rsrc with read-only access\(nt4_dc\) >-^samba3.vfs.fruit streams_depot.creating rsrc with read-only access\(nt4_dc\) >diff --git a/source3/modules/vfs_fruit.c b/source3/modules/vfs_fruit.c >index 5c986a7b3ea..b51eda1146b 100644 >--- a/source3/modules/vfs_fruit.c >+++ b/source3/modules/vfs_fruit.c >@@ -3575,12 +3575,9 @@ static int fruit_open_rsrc_adouble(vfs_handle_struct *handle, > goto exit; > } > >- /* Sanitize flags */ >- if (flags & O_WRONLY) { >- /* We always need read access for the metadata header too */ >- flags &= ~O_WRONLY; >- flags |= O_RDWR; >- } >+ /* We always need read/write access for the metadata header too */ >+ flags &= ~(O_RDONLY | O_WRONLY); >+ flags |= O_RDWR; > > hostfd = SMB_VFS_NEXT_OPEN(handle, smb_fname_base, fsp, > flags, mode); >@@ -3667,20 +3664,6 @@ 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.17.2 > > >From 50528b65206472241cf4d3f10cc598216be1467f Mon Sep 17 00:00:00 2001 >From: Ralph Boehme <slow@samba.org> >Date: Mon, 22 Oct 2018 12:43:16 +0200 >Subject: [PATCH 13/34] s4:torture/vfs/fruit: expand test "setinfo eof stream" > >o Adds checks verifying that after setting eof to 0 on a stream, a > subsequent open gets ENOENT, before and after closing the handle that > had been used to set eof to 0. > >o Verify that a write to a handle succeeds after that handle has been > used to set eof to 0 on a stream. > >Bug: https://bugzilla.samba.org/show_bug.cgi?id=13646 > >Signed-off-by: Ralph Boehme <slow@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >(cherry picked from commit b35d9e74028727da24f349242cb0bc62403a9b09) >--- > selftest/knownfail.d/samba3.vfs.fruit | 3 ++ > source4/torture/vfs/fruit.c | 61 +++++++++++++++++++++++++++ > 2 files changed, 64 insertions(+) > >diff --git a/selftest/knownfail.d/samba3.vfs.fruit b/selftest/knownfail.d/samba3.vfs.fruit >index 6307e2b3404..5ecba522d4a 100644 >--- a/selftest/knownfail.d/samba3.vfs.fruit >+++ b/selftest/knownfail.d/samba3.vfs.fruit >@@ -1,2 +1,5 @@ > ^samba3.vfs.fruit streams_depot.OS X AppleDouble file conversion\(nt4_dc\) > ^samba3.vfs.fruit streams_depot.OS X AppleDouble file conversion without embedded xattr\(nt4_dc\) >+^samba3.vfs.fruit metadata_netatalk.setinfo eof stream\(nt4_dc\) >+^samba3.vfs.fruit metadata_stream.setinfo eof stream\(nt4_dc\) >+^samba3.vfs.fruit streams_depot.setinfo eof stream\(nt4_dc\) >diff --git a/source4/torture/vfs/fruit.c b/source4/torture/vfs/fruit.c >index 8dd34e39294..ebe11bc44db 100644 >--- a/source4/torture/vfs/fruit.c >+++ b/source4/torture/vfs/fruit.c >@@ -4981,8 +4981,32 @@ static bool test_setinfo_stream_eof(struct torture_context *tctx, > torture_assert_ntstatus_ok_goto(tctx, status, ret, done, > "set eof 0 failed\n"); > >+ ZERO_STRUCT(create); >+ create.in.desired_access = SEC_FILE_READ_ATTRIBUTE; >+ create.in.share_access = NTCREATEX_SHARE_ACCESS_MASK; >+ create.in.file_attributes = FILE_ATTRIBUTE_NORMAL; >+ create.in.create_disposition = NTCREATEX_DISP_OPEN; >+ create.in.fname = sname; >+ >+ status = smb2_create(tree, tctx, &create); >+ torture_assert_ntstatus_equal_goto( >+ tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND, ret, done, >+ "Unexpected status\n"); >+ > smb2_util_close(tree, h1); > >+ ZERO_STRUCT(create); >+ create.in.desired_access = SEC_FILE_READ_ATTRIBUTE; >+ create.in.share_access = NTCREATEX_SHARE_ACCESS_MASK; >+ create.in.file_attributes = FILE_ATTRIBUTE_NORMAL; >+ create.in.create_disposition = NTCREATEX_DISP_OPEN; >+ create.in.fname = sname; >+ >+ status = smb2_create(tree, tctx, &create); >+ torture_assert_ntstatus_equal_goto( >+ tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND, ret, done, >+ "Unexpected status\n"); >+ > status = torture_smb2_testfile_access(tree, sname, &h1, > SEC_FILE_WRITE_DATA); > torture_assert_ntstatus_ok_goto(tctx, status, ret, done, >@@ -5061,6 +5085,18 @@ static bool test_setinfo_stream_eof(struct torture_context *tctx, > torture_assert_ntstatus_ok_goto(tctx, status, ret, done, > "set eof 0 failed\n"); > >+ ZERO_STRUCT(create); >+ create.in.desired_access = SEC_FILE_READ_ATTRIBUTE; >+ create.in.share_access = NTCREATEX_SHARE_ACCESS_MASK; >+ create.in.file_attributes = FILE_ATTRIBUTE_NORMAL; >+ create.in.create_disposition = NTCREATEX_DISP_OPEN; >+ create.in.fname = sname; >+ >+ status = smb2_create(tree, tctx, &create); >+ torture_assert_ntstatus_equal_goto( >+ tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND, ret, done, >+ "Unexpected status\n"); >+ > smb2_util_close(tree, h1); > > ZERO_STRUCT(create); >@@ -5120,6 +5156,31 @@ static bool test_setinfo_stream_eof(struct torture_context *tctx, > torture_assert_ntstatus_ok_goto(tctx, status, ret, done, > "torture_smb2_testfile failed\n"); > smb2_util_close(tree, h1); >+ >+ torture_comment(tctx, "Writing to stream after setting EOF to 0\n"); >+ status = torture_smb2_testfile_access(tree, sname, &h1, >+ SEC_FILE_WRITE_DATA); >+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, >+ "torture_smb2_testfile failed\n"); >+ >+ status = smb2_util_write(tree, h1, "1234567890", 0, 10); >+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, >+ "smb2_util_write failed\n"); >+ >+ ZERO_STRUCT(sfinfo); >+ sfinfo.generic.in.file.handle = h1; >+ sfinfo.generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION; >+ sfinfo.position_information.in.position = 0; >+ status = smb2_setinfo_file(tree, &sfinfo); >+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, >+ "set eof 0 failed\n"); >+ >+ status = smb2_util_write(tree, h1, "1234567890", 0, 10); >+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, >+ "smb2_util_write failed\n"); >+ >+ smb2_util_close(tree, h1); >+ > done: > smb2_util_unlink(tree, fname); > smb2_util_rmdir(tree, BASEDIR); >-- >2.17.2 > > >From c9c0587e5e0a3d08254610520245719336eff4d1 Mon Sep 17 00:00:00 2001 >From: Ralph Boehme <slow@samba.org> >Date: Sat, 20 Oct 2018 14:52:23 +0200 >Subject: [PATCH 14/34] s4:torture/vfs/fruit: write some data to a just created > teststream > >Doesn't currently make a difference, but this prepares for a later >change in vfs_fruit that will filter out empty streams (which is the >macOS behaviour). > >Bug: https://bugzilla.samba.org/show_bug.cgi?id=13646 > >Signed-off-by: Ralph Boehme <slow@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >(cherry picked from commit 3195ff9547824dd129e3fbcbbb8823fb10a0a5d4) >--- > source4/torture/vfs/fruit.c | 5 +++++ > 1 file changed, 5 insertions(+) > >diff --git a/source4/torture/vfs/fruit.c b/source4/torture/vfs/fruit.c >index ebe11bc44db..2742e568da4 100644 >--- a/source4/torture/vfs/fruit.c >+++ b/source4/torture/vfs/fruit.c >@@ -5282,6 +5282,11 @@ static bool test_stream_names_local(struct torture_context *tctx, > > status = smb2_create(tree, mem_ctx, &create); > CHECK_STATUS(status, NT_STATUS_OK); >+ >+ status = smb2_util_write(tree, create.out.file.handle, "foo", 0, 3); >+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, >+ "smb2_util_write failed\n"); >+ > smb2_util_close(tree, create.out.file.handle); > > ret = torture_setup_local_xattr(tctx, "localdir", BASEDIR "/stream_names.txt", >-- >2.17.2 > > >From 07af5d80b7bb0bc80f6907fe9aeb9d90fe0954f6 Mon Sep 17 00:00:00 2001 >From: Ralph Boehme <slow@samba.org> >Date: Sat, 20 Oct 2018 14:54:48 +0200 >Subject: [PATCH 15/34] vfs_fruit: don't unlink 0-byte size truncated streams > >This caused all sort of havoc with subsequent SMB request that acted on >the handle of the then deleted backend storage (file or blob, depending >on the used streams module). > >Bug: https://bugzilla.samba.org/show_bug.cgi?id=13646 > >Signed-off-by: Ralph Boehme <slow@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >(cherry picked from commit 287082d739362ad068df37076712927ccd7ca90c) >--- > source3/modules/vfs_fruit.c | 7 ------- > 1 file changed, 7 deletions(-) > >diff --git a/source3/modules/vfs_fruit.c b/source3/modules/vfs_fruit.c >index b51eda1146b..1446461a8a3 100644 >--- a/source3/modules/vfs_fruit.c >+++ b/source3/modules/vfs_fruit.c >@@ -5816,13 +5816,6 @@ static int fruit_ftruncate(struct vfs_handle_struct *handle, > (intmax_t)offset); > > if (fio == NULL) { >- if (offset == 0 && >- global_fruit_config.nego_aapl && >- is_ntfs_stream_smb_fname(fsp->fsp_name) && >- !is_ntfs_default_stream_smb_fname(fsp->fsp_name)) >- { >- return SMB_VFS_NEXT_UNLINK(handle, fsp->fsp_name); >- } > return SMB_VFS_NEXT_FTRUNCATE(handle, fsp, offset); > } > >-- >2.17.2 > > >From 331d5283a35f37dc7b675a4f7bc80aad2c34f5ec Mon Sep 17 00:00:00 2001 >From: Ralph Boehme <slow@samba.org> >Date: Mon, 22 Oct 2018 14:01:34 +0200 >Subject: [PATCH 16/34] s4:torture/vfs/fruit: enable AAPL extensions in a bunch > of tests > >These tests check for macOS SMB server specific behaviour. They work >currently against Samba without enabling AAPL because in vfs_fruit we're >currently don't check whether AAPL has been negotiated in one place. A >subsequent commit will change that and this commit prepares for that >change. > >Bug: https://bugzilla.samba.org/show_bug.cgi?id=13646 > >Signed-off-by: Ralph Boehme <slow@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >(cherry picked from commit 7485007bb0a69dc8237c78be90f4bae06aad49b2) >--- > source4/torture/vfs/fruit.c | 12 ++++++++++++ > 1 file changed, 12 insertions(+) > >diff --git a/source4/torture/vfs/fruit.c b/source4/torture/vfs/fruit.c >index 2742e568da4..0cd61a41479 100644 >--- a/source4/torture/vfs/fruit.c >+++ b/source4/torture/vfs/fruit.c >@@ -1810,6 +1810,9 @@ static bool test_rfork_truncate(struct torture_context *tctx, > struct smb2_handle fh1, fh2, fh3; > union smb_setfileinfo sinfo; > >+ ret = enable_aapl(tctx, tree); >+ torture_assert_goto(tctx, ret == true, ret, done, "enable_aapl failed"); >+ > smb2_util_unlink(tree, fname); > > status = torture_smb2_testdir(tree, BASEDIR, &testdirh); >@@ -1928,6 +1931,9 @@ static bool test_rfork_create(struct torture_context *tctx, > }; > union smb_fileinfo finfo; > >+ ret = enable_aapl(tctx, tree); >+ torture_assert_goto(tctx, ret == true, ret, done, "enable_aapl failed"); >+ > smb2_util_unlink(tree, fname); > > status = torture_smb2_testdir(tree, BASEDIR, &testdirh); >@@ -3935,6 +3941,9 @@ static bool test_setinfo_eof_resource(struct torture_context *tctx, > > torture_assert_goto(tctx, mem_ctx != NULL, ret, done, "talloc_new"); > >+ ret = enable_aapl(tctx, tree); >+ torture_assert_goto(tctx, ret == true, ret, done, "enable_aapl failed"); >+ > torture_comment(tctx, "Set AFP_AfpResource EOF to 1 and 0\n"); > > smb2_deltree(tree, BASEDIR); >@@ -4901,6 +4910,9 @@ static bool test_setinfo_stream_eof(struct torture_context *tctx, > torture_assert_goto(tctx, mem_ctx != NULL, ret, done, > "talloc_new failed\n"); > >+ ret = enable_aapl(tctx, tree); >+ torture_assert(tctx, ret == true, "enable_aapl failed"); >+ > torture_comment(tctx, "Test setting EOF on a stream\n"); > > smb2_deltree(tree, BASEDIR); >-- >2.17.2 > > >From 5dda86658b5b54c3dc25006ed0150d7e91e75567 Mon Sep 17 00:00:00 2001 >From: Ralph Boehme <slow@samba.org> >Date: Sat, 20 Oct 2018 15:28:06 +0200 >Subject: [PATCH 17/34] vfs_fruit: use check on global_fruit_config.nego_aapl > for macOS specific behaviour > >Ensure any non MS compliant protocol behaviour targetted at supporting >macOS clients are only effective if the client negotiated AAPL. > >Currently this only guards the resource fork which only macOS client are >going to use, but subsequent commits add more this at this place. > >Bug: https://bugzilla.samba.org/show_bug.cgi?id=13646 > >Signed-off-by: Ralph Boehme <slow@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >(cherry picked from commit 046456fca60b9fef38a0cdf5a116883fb1c7dffe) >--- > source3/modules/vfs_fruit.c | 3 ++- > 1 file changed, 2 insertions(+), 1 deletion(-) > >diff --git a/source3/modules/vfs_fruit.c b/source3/modules/vfs_fruit.c >index 1446461a8a3..62e741c4ae2 100644 >--- a/source3/modules/vfs_fruit.c >+++ b/source3/modules/vfs_fruit.c >@@ -5892,7 +5892,8 @@ static NTSTATUS fruit_create_file(vfs_handle_struct *handle, > * > * Cf the vfs_fruit torture tests in test_rfork_create(). > */ >- if (is_afpresource_stream(fsp->fsp_name) && >+ if (global_fruit_config.nego_aapl && >+ is_afpresource_stream(fsp->fsp_name) && > create_disposition == FILE_OPEN) > { > if (fsp->fsp_name->st.st_ex_size == 0) { >-- >2.17.2 > > >From 8807b544d5ef8652dfe05715c5e48e78708324eb Mon Sep 17 00:00:00 2001 >From: Ralph Boehme <slow@samba.org> >Date: Sat, 20 Oct 2018 14:53:50 +0200 >Subject: [PATCH 18/34] vfs_fruit: filter empty streams > >First step in achieving macOS compliant behaviour wrt to empty streams: >- hide empty streams in streaminfo >- prevent opens of empty streams > >This means that we may carry 0-byte sized streams in our streams >backend, but this shouldn't really hurt. > >The previous attempt of deleting the streams when an SMB setinfo eof to >0 request came in, turned out be a road into desaster. > >We could set delete-on-close on the stream, but that means we'd have to >check for it for every write on a stream and checking the >delete-on-close bits requires fetching the locking.tdb record, so this >is expensive and I'd like to avoid that overhead. > >Bug: https://bugzilla.samba.org/show_bug.cgi?id=13646 > >Signed-off-by: Ralph Boehme <slow@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >(cherry picked from commit ebfcf75e993b1a792db76b94aa898532e1c81eeb) >--- > selftest/knownfail.d/samba3.vfs.fruit | 3 -- > source3/modules/vfs_fruit.c | 44 +++++++++++++++++++++++---- > 2 files changed, 38 insertions(+), 9 deletions(-) > >diff --git a/selftest/knownfail.d/samba3.vfs.fruit b/selftest/knownfail.d/samba3.vfs.fruit >index 5ecba522d4a..6307e2b3404 100644 >--- a/selftest/knownfail.d/samba3.vfs.fruit >+++ b/selftest/knownfail.d/samba3.vfs.fruit >@@ -1,5 +1,2 @@ > ^samba3.vfs.fruit streams_depot.OS X AppleDouble file conversion\(nt4_dc\) > ^samba3.vfs.fruit streams_depot.OS X AppleDouble file conversion without embedded xattr\(nt4_dc\) >-^samba3.vfs.fruit metadata_netatalk.setinfo eof stream\(nt4_dc\) >-^samba3.vfs.fruit metadata_stream.setinfo eof stream\(nt4_dc\) >-^samba3.vfs.fruit streams_depot.setinfo eof stream\(nt4_dc\) >diff --git a/source3/modules/vfs_fruit.c b/source3/modules/vfs_fruit.c >index 62e741c4ae2..181038c9817 100644 >--- a/source3/modules/vfs_fruit.c >+++ b/source3/modules/vfs_fruit.c >@@ -5598,6 +5598,36 @@ static NTSTATUS fruit_streaminfo_rsrc(vfs_handle_struct *handle, > return status; > } > >+static void fruit_filter_empty_streams(unsigned int *pnum_streams, >+ struct stream_struct **pstreams) >+{ >+ unsigned num_streams = *pnum_streams; >+ struct stream_struct *streams = *pstreams; >+ unsigned i = 0; >+ >+ if (!global_fruit_config.nego_aapl) { >+ return; >+ } >+ >+ while (i < num_streams) { >+ struct smb_filename smb_fname = (struct smb_filename) { >+ .stream_name = streams[i].name, >+ }; >+ >+ if (is_ntfs_default_stream_smb_fname(&smb_fname) >+ || streams[i].size > 0) >+ { >+ i++; >+ continue; >+ } >+ >+ streams[i] = streams[num_streams - 1]; >+ num_streams--; >+ } >+ >+ *pnum_streams = num_streams; >+} >+ > static NTSTATUS fruit_streaminfo(vfs_handle_struct *handle, > struct files_struct *fsp, > const struct smb_filename *smb_fname, >@@ -5619,6 +5649,8 @@ static NTSTATUS fruit_streaminfo(vfs_handle_struct *handle, > return status; > } > >+ fruit_filter_empty_streams(pnum_streams, pstreams); >+ > status = fruit_streaminfo_meta(handle, fsp, smb_fname, > mem_ctx, pnum_streams, pstreams); > if (!NT_STATUS_IS_OK(status)) { >@@ -5893,13 +5925,13 @@ static NTSTATUS fruit_create_file(vfs_handle_struct *handle, > * Cf the vfs_fruit torture tests in test_rfork_create(). > */ > if (global_fruit_config.nego_aapl && >- is_afpresource_stream(fsp->fsp_name) && >- create_disposition == FILE_OPEN) >+ create_disposition == FILE_OPEN && >+ smb_fname->st.st_ex_size == 0 && >+ is_ntfs_stream_smb_fname(smb_fname) && >+ !(is_ntfs_default_stream_smb_fname(smb_fname))) > { >- if (fsp->fsp_name->st.st_ex_size == 0) { >- status = NT_STATUS_OBJECT_NAME_NOT_FOUND; >- goto fail; >- } >+ status = NT_STATUS_OBJECT_NAME_NOT_FOUND; >+ goto fail; > } > > if (is_ntfs_stream_smb_fname(smb_fname) >-- >2.17.2 > > >From ba922b2d596fb5920968b14d6fce7bfd38ce97e7 Mon Sep 17 00:00:00 2001 >From: Ralph Boehme <slow@samba.org> >Date: Wed, 10 Oct 2018 18:45:56 +0200 >Subject: [PATCH 19/34] s4:torture/util: add torture_smb2_open() > >This seems to be missing: a simple wrapper to just open a file without >fancy options. > >Bug: https://bugzilla.samba.org/show_bug.cgi?id=13646 > >Signed-off-by: Ralph Boehme <slow@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >(cherry picked from commit 64b28e4a94365092f46052712a38e6fcfbb9f20c) >--- > source4/torture/smb2/util.c | 30 ++++++++++++++++++++++++++++++ > 1 file changed, 30 insertions(+) > >diff --git a/source4/torture/smb2/util.c b/source4/torture/smb2/util.c >index 65090b0e8b7..ac8a0d5df77 100644 >--- a/source4/torture/smb2/util.c >+++ b/source4/torture/smb2/util.c >@@ -527,6 +527,36 @@ NTSTATUS torture_smb2_testfile(struct smb2_tree *tree, const char *fname, > SEC_RIGHTS_FILE_ALL); > } > >+/* >+ create and return a handle to a test file >+ with a specific access mask >+*/ >+NTSTATUS torture_smb2_open(struct smb2_tree *tree, >+ const char *fname, >+ uint32_t desired_access, >+ struct smb2_handle *handle) >+{ >+ struct smb2_create io; >+ NTSTATUS status; >+ >+ io = (struct smb2_create) { >+ .in.fname = fname, >+ .in.desired_access = desired_access, >+ .in.file_attributes = FILE_ATTRIBUTE_NORMAL, >+ .in.create_disposition = NTCREATEX_DISP_OPEN, >+ .in.share_access = NTCREATEX_SHARE_ACCESS_MASK, >+ }; >+ >+ status = smb2_create(tree, tree, &io); >+ if (!NT_STATUS_IS_OK(status)) { >+ return status; >+ } >+ >+ *handle = io.out.file.handle; >+ >+ return NT_STATUS_OK; >+} >+ > /* > create and return a handle to a test directory > with specific desired access >-- >2.17.2 > > >From 69345fbbcb21dd4e1960a8846d62689880b65434 Mon Sep 17 00:00:00 2001 >From: Ralph Boehme <slow@samba.org> >Date: Thu, 11 Oct 2018 17:14:50 +0200 >Subject: [PATCH 20/34] s4:torture/vfs/fruit: add check_stream_list_handle() > >Bug: https://bugzilla.samba.org/show_bug.cgi?id=13646 > >Signed-off-by: Ralph Boehme <slow@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >(cherry picked from commit aba502d440ae3478543d3be5c5bbcea39fb0a463) >--- > source4/torture/vfs/fruit.c | 62 +++++++++++++++++++++++++++++++++++++ > 1 file changed, 62 insertions(+) > >diff --git a/source4/torture/vfs/fruit.c b/source4/torture/vfs/fruit.c >index 0cd61a41479..24256e4c6bf 100644 >--- a/source4/torture/vfs/fruit.c >+++ b/source4/torture/vfs/fruit.c >@@ -3082,6 +3082,68 @@ static bool check_stream_list(struct smb2_tree *tree, > return ret; > } > >+#if 0 >+static bool check_stream_list_handle(struct smb2_tree *tree, >+ struct torture_context *tctx, >+ struct smb2_handle h, >+ int num_exp, >+ const char **exp, >+ bool is_dir) >+{ >+ bool ret = true; >+ union smb_fileinfo finfo; >+ NTSTATUS status; >+ int i; >+ TALLOC_CTX *tmp_ctx = talloc_new(tctx); >+ char **exp_sort; >+ struct stream_struct *stream_sort; >+ >+ torture_assert_goto(tctx, tmp_ctx != NULL, ret, done, >+ "talloc_new failed\n"); >+ >+ finfo = (union smb_fileinfo) { >+ .stream_info.level = RAW_FILEINFO_STREAM_INFORMATION, >+ .stream_info.in.file.handle = h, >+ }; >+ >+ status = smb2_getinfo_file(tree, tctx, &finfo); >+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, >+ "get stream info\n"); >+ >+ torture_assert_int_equal_goto(tctx, finfo.stream_info.out.num_streams, >+ num_exp, ret, done, "stream count\n"); >+ >+ if (num_exp == 0) { >+ TALLOC_FREE(tmp_ctx); >+ goto done; >+ } >+ >+ exp_sort = talloc_memdup(tmp_ctx, exp, num_exp * sizeof(*exp)); >+ torture_assert_goto(tctx, exp_sort != NULL, ret, done, __location__); >+ >+ TYPESAFE_QSORT(exp_sort, num_exp, qsort_string); >+ >+ stream_sort = talloc_memdup(tmp_ctx, finfo.stream_info.out.streams, >+ finfo.stream_info.out.num_streams * >+ sizeof(*stream_sort)); >+ torture_assert_goto(tctx, stream_sort != NULL, ret, done, __location__); >+ >+ TYPESAFE_QSORT(stream_sort, finfo.stream_info.out.num_streams, qsort_stream); >+ >+ for (i=0; i<num_exp; i++) { >+ torture_comment(tctx, "i[%d] exp[%s] got[%s]\n", >+ i, exp_sort[i], stream_sort[i].stream_name.s); >+ torture_assert_str_equal_goto(tctx, stream_sort[i].stream_name.s, >+ exp_sort[i], ret, done, >+ "stream name\n"); >+ } >+ >+done: >+ TALLOC_FREE(tmp_ctx); >+ return ret; >+} >+#endif >+ > /* > test stream names > */ >-- >2.17.2 > > >From b5695b050675b7848044a958a9787d1669d8cc3c Mon Sep 17 00:00:00 2001 >From: Ralph Boehme <slow@samba.org> >Date: Mon, 22 Oct 2018 16:21:21 +0200 >Subject: [PATCH 21/34] s4:torture/vfs/fruit: add test "empty_stream" > >One to rule them all: consistently test critical operations on all >streams relevant to macOS clients: the FinderInfo stream, the Resource >Fork stream and an arbitrary stream that macOS maps to xattrs when >written to on a macOS SMB server. > >Bug: https://bugzilla.samba.org/show_bug.cgi?id=13646 > >Signed-off-by: Ralph Boehme <slow@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >(cherry picked from commit 9d8751db64de75a0de442365b317c1b9ce194170) >--- > selftest/knownfail.d/samba3.vfs.fruit | 3 + > source4/torture/vfs/fruit.c | 613 +++++++++++++++++++++++++- > 2 files changed, 614 insertions(+), 2 deletions(-) > >diff --git a/selftest/knownfail.d/samba3.vfs.fruit b/selftest/knownfail.d/samba3.vfs.fruit >index 6307e2b3404..2d3c21caf91 100644 >--- a/selftest/knownfail.d/samba3.vfs.fruit >+++ b/selftest/knownfail.d/samba3.vfs.fruit >@@ -1,2 +1,5 @@ > ^samba3.vfs.fruit streams_depot.OS X AppleDouble file conversion\(nt4_dc\) > ^samba3.vfs.fruit streams_depot.OS X AppleDouble file conversion without embedded xattr\(nt4_dc\) >+^samba3.vfs.fruit metadata_netatalk.empty_stream\(nt4_dc\) >+^samba3.vfs.fruit metadata_stream.empty_stream\(nt4_dc\) >+^samba3.vfs.fruit streams_depot.empty_stream\(nt4_dc\) >diff --git a/source4/torture/vfs/fruit.c b/source4/torture/vfs/fruit.c >index 24256e4c6bf..6dd96853a38 100644 >--- a/source4/torture/vfs/fruit.c >+++ b/source4/torture/vfs/fruit.c >@@ -3082,7 +3082,6 @@ static bool check_stream_list(struct smb2_tree *tree, > return ret; > } > >-#if 0 > static bool check_stream_list_handle(struct smb2_tree *tree, > struct torture_context *tctx, > struct smb2_handle h, >@@ -3142,7 +3141,6 @@ static bool check_stream_list_handle(struct smb2_tree *tree, > TALLOC_FREE(tmp_ctx); > return ret; > } >-#endif > > /* > test stream names >@@ -5261,6 +5259,616 @@ static bool test_setinfo_stream_eof(struct torture_context *tctx, > return ret; > } > >+#define MAX_STREAMS 16 >+ >+struct tcase { >+ const char *name; >+ uint32_t access; >+ const char *write_data; >+ size_t write_size; >+ struct tcase_results { >+ size_t size; >+ NTSTATUS initial_status; >+ NTSTATUS final_status; >+ int num_streams_open_handle; >+ const char *streams_open_handle[MAX_STREAMS]; >+ int num_streams_closed_handle; >+ const char *streams_closed_handle[MAX_STREAMS]; >+ } create, write, overwrite, eof, doc; >+}; >+ >+typedef enum {T_CREATE, T_WRITE, T_OVERWRITE, T_EOF, T_DOC} subtcase_t; >+ >+static bool test_empty_stream_do_checks( >+ struct torture_context *tctx, >+ struct smb2_tree *tree, >+ struct smb2_tree *tree2, >+ struct tcase *tcase, >+ TALLOC_CTX *mem_ctx, >+ struct smb2_handle baseh, >+ struct smb2_handle streamh, >+ subtcase_t subcase) >+{ >+ bool ret = false; >+ NTSTATUS status; >+ struct smb2_handle h1; >+ union smb_fileinfo finfo; >+ struct tcase_results *tcase_results = NULL; >+ >+ switch (subcase) { >+ case T_CREATE: >+ tcase_results = &tcase->create; >+ break; >+ case T_OVERWRITE: >+ tcase_results = &tcase->overwrite; >+ break; >+ case T_WRITE: >+ tcase_results = &tcase->write; >+ break; >+ case T_EOF: >+ tcase_results = &tcase->eof; >+ break; >+ case T_DOC: >+ tcase_results = &tcase->doc; >+ break; >+ } >+ >+ finfo = (union smb_fileinfo) { >+ .generic.level = RAW_FILEINFO_STANDARD_INFORMATION, >+ .generic.in.file.handle = streamh, >+ }; >+ >+ /* >+ * Test: check size, same client >+ */ >+ >+ status = smb2_getinfo_file(tree, mem_ctx, &finfo); >+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, >+ "torture_smb2_testfile failed\n"); >+ >+ torture_assert_int_equal_goto(tctx, finfo.standard_info.out.size, >+ tcase_results->size, >+ ret, done, "Wrong size\n"); >+ >+ /* >+ * Test: open, same client >+ */ >+ >+ status = torture_smb2_open(tree, tcase->name, >+ SEC_FILE_READ_ATTRIBUTE, &h1); >+ torture_assert_ntstatus_equal_goto(tctx, status, >+ tcase_results->initial_status, >+ ret, done, >+ "smb2_create failed\n"); >+ if (NT_STATUS_IS_OK(status)) { >+ status = smb2_util_close(tree, h1); >+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, >+ "smb2_util_close failed\n"); >+ } >+ >+ /* >+ * Test: check streams, same client >+ */ >+ >+ ret = check_stream_list_handle(tree, tctx, baseh, >+ tcase_results->num_streams_open_handle, >+ tcase_results->streams_open_handle, >+ false); >+ torture_assert_goto(tctx, ret == true, ret, done, "Bad streams"); >+ >+ /* >+ * Test: open, different client >+ */ >+ >+ status = torture_smb2_open(tree2, tcase->name, >+ SEC_FILE_READ_ATTRIBUTE, &h1); >+ torture_assert_ntstatus_equal_goto(tctx, status, >+ tcase_results->initial_status, >+ ret, done, >+ "smb2_create failed\n"); >+ if (NT_STATUS_IS_OK(status)) { >+ finfo = (union smb_fileinfo) { >+ .generic.level = RAW_FILEINFO_STANDARD_INFORMATION, >+ .generic.in.file.handle = h1, >+ }; >+ >+ /* >+ * Test: check size, different client >+ */ >+ >+ status = smb2_getinfo_file(tree2, mem_ctx, &finfo); >+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, >+ "smb2_getinfo_file failed\n"); >+ >+ torture_assert_int_equal_goto(tctx, finfo.standard_info.out.size, >+ tcase_results->size, >+ ret, done, "Wrong size\n"); >+ >+ /* >+ * Test: check streams, different client >+ */ >+ >+ ret = check_stream_list(tree2, tctx, BASEDIR "\\file", >+ tcase_results->num_streams_open_handle, >+ tcase_results->streams_open_handle, >+ false); >+ torture_assert_goto(tctx, ret == true, ret, done, "Bad streams"); >+ >+ status = smb2_util_close(tree2, h1); >+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, >+ "smb2_util_close failed\n"); >+ } >+ >+ status = smb2_util_close(tree, streamh); >+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, >+ "smb2_util_close failed\n"); >+ >+ /* >+ * Test: open after close, same client >+ */ >+ >+ status = torture_smb2_open(tree, tcase->name, >+ SEC_FILE_READ_DATA, &h1); >+ torture_assert_ntstatus_equal_goto(tctx, status, >+ tcase_results->final_status, >+ ret, done, >+ "smb2_create failed\n"); >+ if (NT_STATUS_IS_OK(status)) { >+ status = smb2_util_close(tree, h1); >+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, >+ "smb2_util_close failed\n"); >+ } >+ >+ /* >+ * Test: open after close, different client >+ */ >+ >+ status = torture_smb2_open(tree2, tcase->name, >+ SEC_FILE_READ_DATA, &h1); >+ torture_assert_ntstatus_equal_goto(tctx, status, >+ tcase_results->final_status, >+ ret, done, >+ "smb2_create failed\n"); >+ if (NT_STATUS_IS_OK(status)) { >+ status = smb2_util_close(tree2, h1); >+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, >+ "smb2_util_close failed\n"); >+ } >+ >+ /* >+ * Test: check streams after close, same client >+ */ >+ >+ ret = check_stream_list_handle(tree, tctx, baseh, >+ tcase_results->num_streams_closed_handle, >+ tcase_results->streams_closed_handle, >+ false); >+ torture_assert_goto(tctx, ret == true, ret, done, "Bad streams"); >+ >+ ret = true; >+ >+done: >+ smb2_util_close(tree, streamh); >+ smb2_util_close(tree, baseh); >+ return ret; >+} >+ >+static bool test_empty_stream_do_one( >+ struct torture_context *tctx, >+ struct smb2_tree *tree, >+ struct smb2_tree *tree2, >+ struct tcase *tcase) >+{ >+ bool ret = false; >+ NTSTATUS status; >+ struct smb2_handle baseh; >+ struct smb2_handle streamh; >+ struct smb2_create create; >+ union smb_setfileinfo sfinfo; >+ TALLOC_CTX *mem_ctx = talloc_new(tctx); >+ >+ torture_comment(tctx, "Testing stream [%s]\n", tcase->name); >+ >+ torture_assert_goto(tctx, mem_ctx != NULL, ret, done, "talloc_new\n"); >+ >+ /* >+ * Subtest: create >+ */ >+ torture_comment(tctx, "Subtest: T_CREATE\n"); >+ >+ status = smb2_util_unlink(tree, BASEDIR "\\file"); >+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, >+ "smb2_util_unlink failed\n"); >+ >+ status = torture_smb2_testfile_access(tree, BASEDIR "\\file", >+ &baseh, SEC_FILE_ALL); >+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, >+ "torture_smb2_testfile_access failed\n"); >+ >+ status = torture_smb2_testfile_access(tree, tcase->name, &streamh, >+ tcase->access); >+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, >+ "torture_smb2_testfile_access failed\n"); >+ >+ ret = test_empty_stream_do_checks(tctx, tree, tree2, tcase, >+ mem_ctx, baseh, streamh, T_CREATE); >+ torture_assert_goto(tctx, ret, ret, done, "test failed\n"); >+ >+ if (!(tcase->access & SEC_FILE_WRITE_DATA)) { >+ /* >+ * All subsequent tests require write access >+ */ >+ ret = true; >+ goto done; >+ } >+ >+ /* >+ * Subtest: create and write >+ */ >+ torture_comment(tctx, "Subtest: T_WRITE\n"); >+ >+ status = smb2_util_unlink(tree, BASEDIR "\\file"); >+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, >+ "smb2_util_unlink failed\n"); >+ >+ status = torture_smb2_testfile_access(tree, BASEDIR "\\file", >+ &baseh, SEC_FILE_ALL); >+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, >+ "torture_smb2_testfile_access failed\n"); >+ >+ status = torture_smb2_testfile_access(tree, tcase->name, &streamh, >+ tcase->access); >+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, >+ "torture_smb2_testfile_access failed\n"); >+ >+ status = smb2_util_write(tree, streamh, tcase->write_data, 0, >+ tcase->write_size); >+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, >+ "torture_smb2_open failed\n"); >+ >+ ret = test_empty_stream_do_checks(tctx, tree, tree2, tcase, >+ mem_ctx, baseh, streamh, T_WRITE); >+ torture_assert_goto(tctx, ret, ret, done, "test failed\n"); >+ >+ /* >+ * Subtest: overwrite >+ */ >+ torture_comment(tctx, "Subtest: T_OVERWRITE\n"); >+ >+ status = smb2_util_unlink(tree, BASEDIR "\\file"); >+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, >+ "smb2_util_unlink failed\n"); >+ >+ status = torture_smb2_testfile_access(tree, BASEDIR "\\file", >+ &baseh, SEC_FILE_ALL); >+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, >+ "torture_smb2_testfile_access failed\n"); >+ >+ create = (struct smb2_create) { >+ .in.desired_access = SEC_FILE_ALL, >+ .in.share_access = NTCREATEX_SHARE_ACCESS_MASK, >+ .in.file_attributes = FILE_ATTRIBUTE_NORMAL, >+ .in.create_disposition = NTCREATEX_DISP_OVERWRITE_IF, >+ .in.fname = tcase->name, >+ }; >+ >+ status = smb2_create(tree, tctx, &create); >+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, >+ "torture_smb2_testfile failed\n"); >+ streamh = create.out.file.handle; >+ >+ ret = test_empty_stream_do_checks(tctx, tree, tree2, tcase, >+ mem_ctx, baseh, streamh, T_OVERWRITE); >+ torture_assert_goto(tctx, ret, ret, done, "test failed\n"); >+ >+ /* >+ * Subtest: setinfo EOF 0 >+ */ >+ torture_comment(tctx, "Subtest: T_EOF\n"); >+ >+ status = smb2_util_unlink(tree, BASEDIR "\\file"); >+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, >+ "smb2_util_unlink failed\n"); >+ >+ status = torture_smb2_testfile_access(tree, BASEDIR "\\file", >+ &baseh, SEC_FILE_ALL); >+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, >+ "torture_smb2_testfile_access failed\n"); >+ >+ status = torture_smb2_testfile_access(tree, tcase->name, &streamh, >+ tcase->access); >+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, >+ "torture_smb2_testfile_access failed\n"); >+ >+ status = smb2_util_write(tree, streamh, tcase->write_data, 0, >+ tcase->write_size); >+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, >+ "torture_smb2_open failed\n"); >+ >+ sfinfo = (union smb_setfileinfo) { >+ .end_of_file_info.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION, >+ .end_of_file_info.in.file.handle = streamh, >+ .end_of_file_info.in.size = 0, >+ }; >+ status = smb2_setinfo_file(tree, &sfinfo); >+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, >+ "set eof 0 failed\n"); >+ >+ ret = test_empty_stream_do_checks(tctx, tree, tree2, tcase, >+ mem_ctx, baseh, streamh, T_EOF); >+ torture_assert_goto(tctx, ret, ret, done, "test failed\n"); >+ >+ /* >+ * Subtest: delete-on-close >+ */ >+ torture_comment(tctx, "Subtest: T_DOC\n"); >+ >+ status = smb2_util_unlink(tree, BASEDIR "\\file"); >+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, >+ "smb2_util_unlink failed\n"); >+ >+ status = torture_smb2_testfile_access(tree, BASEDIR "\\file", >+ &baseh, SEC_FILE_ALL); >+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, >+ "torture_smb2_testfile_access failed\n"); >+ >+ status = torture_smb2_testfile_access(tree, tcase->name, &streamh, >+ tcase->access); >+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, >+ "torture_smb2_testfile_access failed\n"); >+ >+ status = smb2_util_write(tree, streamh, tcase->write_data, 0, >+ tcase->write_size); >+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, >+ "torture_smb2_open failed\n"); >+ >+ sfinfo = (union smb_setfileinfo) { >+ .disposition_info.level = RAW_SFILEINFO_DISPOSITION_INFORMATION, >+ .disposition_info.in.file.handle = streamh, >+ .disposition_info.in.delete_on_close = true, >+ }; >+ status = smb2_setinfo_file(tree, &sfinfo); >+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, >+ "set eof 0 failed\n"); >+ >+ ret = test_empty_stream_do_checks(tctx, tree, tree2, tcase, >+ mem_ctx, baseh, streamh, >+ T_DOC); >+ torture_assert_goto(tctx, ret, ret, done, "test failed\n"); >+ >+ ret = true; >+ >+done: >+ smb2_util_close(tree, baseh); >+ TALLOC_FREE(mem_ctx); >+ return ret; >+} >+ >+static bool test_empty_stream(struct torture_context *tctx, >+ struct smb2_tree *tree) >+{ >+ struct smb2_tree *tree2 = NULL; >+ struct tcase *tcase = NULL; >+ const char *fname = BASEDIR "\\file"; >+ struct smb2_handle h1; >+ bool ret = true; >+ NTSTATUS status; >+ AfpInfo ai = (AfpInfo) { >+ .afpi_Signature = AFP_Signature, >+ .afpi_Version = AFP_Version, >+ .afpi_BackupTime = AFP_BackupTime, >+ .afpi_FinderInfo = "FOO BAR ", >+ }; >+ char *ai_blob = torture_afpinfo_pack(tctx, &ai); >+ struct tcase tcase_afpinfo_ro = (struct tcase) { >+ .name = BASEDIR "\\file" AFPINFO_STREAM, >+ .access = SEC_FILE_READ_DATA|SEC_FILE_READ_ATTRIBUTE, >+ .create.size = 60, >+ .create.initial_status = NT_STATUS_OBJECT_NAME_NOT_FOUND, >+ .create.final_status = NT_STATUS_OBJECT_NAME_NOT_FOUND, >+ .create.num_streams_open_handle = 1, >+ .create.num_streams_closed_handle = 1, >+ .create.streams_open_handle = {"::$DATA"}, >+ .create.streams_closed_handle = {"::$DATA"}, >+ }; >+ struct tcase tcase_afpinfo_rw = (struct tcase) { >+ .name = BASEDIR "\\file" AFPINFO_STREAM, >+ .access = SEC_FILE_READ_DATA|SEC_FILE_READ_ATTRIBUTE|SEC_FILE_WRITE_DATA|SEC_STD_DELETE, >+ .write_data = ai_blob, >+ .write_size = AFP_INFO_SIZE, >+ .create.size = 60, >+ .create.initial_status = NT_STATUS_OBJECT_NAME_NOT_FOUND, >+ .create.final_status = NT_STATUS_OBJECT_NAME_NOT_FOUND, >+ .create.num_streams_open_handle = 1, >+ .create.num_streams_closed_handle = 1, >+ .create.streams_open_handle = {"::$DATA"}, >+ .create.streams_closed_handle = {"::$DATA"}, >+ .write.size = 60, >+ .write.initial_status = NT_STATUS_OK, >+ .write.final_status = NT_STATUS_OK, >+ .write.num_streams_open_handle = 2, >+ .write.num_streams_closed_handle = 2, >+ .write.streams_open_handle = {"::$DATA", AFPINFO_STREAM}, >+ .write.streams_closed_handle = {"::$DATA", AFPINFO_STREAM}, >+ .overwrite.size = 60, >+ .overwrite.initial_status = NT_STATUS_OBJECT_NAME_NOT_FOUND, >+ .overwrite.final_status = NT_STATUS_OBJECT_NAME_NOT_FOUND, >+ .overwrite.num_streams_open_handle = 1, >+ .overwrite.num_streams_closed_handle = 1, >+ .overwrite.streams_open_handle = {"::$DATA"}, >+ .overwrite.streams_closed_handle = {"::$DATA"}, >+ .eof.size = 60, >+ .eof.initial_status = NT_STATUS_OK, >+ .eof.final_status = NT_STATUS_OK, >+ .eof.num_streams_open_handle = 2, >+ .eof.num_streams_closed_handle = 2, >+ .eof.streams_open_handle = {"::$DATA", AFPINFO_STREAM}, >+ .eof.streams_closed_handle = {"::$DATA", AFPINFO_STREAM}, >+ .doc.size = 60, >+ .doc.initial_status = NT_STATUS_DELETE_PENDING, >+ .doc.final_status = NT_STATUS_OBJECT_NAME_NOT_FOUND, >+ .doc.num_streams_open_handle = 2, >+ .doc.num_streams_closed_handle = 1, >+ .doc.streams_open_handle = {"::$DATA", AFPINFO_STREAM}, >+ .doc.streams_closed_handle = {"::$DATA"}, >+ }; >+ >+ struct tcase tcase_afpresource_ro = (struct tcase) { >+ .name = BASEDIR "\\file" AFPRESOURCE_STREAM, >+ .access = SEC_FILE_READ_DATA|SEC_FILE_READ_ATTRIBUTE, >+ .create.size = 0, >+ .create.initial_status = NT_STATUS_OBJECT_NAME_NOT_FOUND, >+ .create.final_status = NT_STATUS_OBJECT_NAME_NOT_FOUND, >+ .create.num_streams_open_handle = 1, >+ .create.num_streams_closed_handle = 1, >+ .create.streams_open_handle = {"::$DATA"}, >+ .create.streams_closed_handle = {"::$DATA"}, >+ }; >+ struct tcase tcase_afpresource_rw = (struct tcase) { >+ .name = BASEDIR "\\file" AFPRESOURCE_STREAM, >+ .access = SEC_FILE_READ_DATA|SEC_FILE_READ_ATTRIBUTE|SEC_FILE_WRITE_DATA|SEC_STD_DELETE, >+ .write_data = "foo", >+ .write_size = 3, >+ .create.size = 0, >+ .create.initial_status = NT_STATUS_OBJECT_NAME_NOT_FOUND, >+ .create.final_status = NT_STATUS_OBJECT_NAME_NOT_FOUND, >+ .create.num_streams_open_handle = 1, >+ .create.num_streams_closed_handle = 1, >+ .create.streams_open_handle = {"::$DATA"}, >+ .create.streams_closed_handle = {"::$DATA"}, >+ .write.size = 3, >+ .write.initial_status = NT_STATUS_OK, >+ .write.final_status = NT_STATUS_OK, >+ .write.num_streams_open_handle = 2, >+ .write.num_streams_closed_handle = 2, >+ .write.streams_open_handle = {"::$DATA", AFPRESOURCE_STREAM}, >+ .write.streams_closed_handle = {"::$DATA", AFPRESOURCE_STREAM}, >+ .overwrite.size = 0, >+ .overwrite.initial_status = NT_STATUS_OBJECT_NAME_NOT_FOUND, >+ .overwrite.final_status = NT_STATUS_OBJECT_NAME_NOT_FOUND, >+ .overwrite.num_streams_open_handle = 1, >+ .overwrite.num_streams_closed_handle = 1, >+ .overwrite.streams_open_handle = {"::$DATA"}, >+ .overwrite.streams_closed_handle = {"::$DATA"}, >+ .eof.size = 0, >+ .eof.initial_status = NT_STATUS_OBJECT_NAME_NOT_FOUND, >+ .eof.final_status = NT_STATUS_OBJECT_NAME_NOT_FOUND, >+ .eof.num_streams_open_handle = 1, >+ .eof.num_streams_closed_handle = 1, >+ .eof.streams_open_handle = {"::$DATA"}, >+ .eof.streams_closed_handle = {"::$DATA"}, >+ .doc.size = 3, >+ .doc.initial_status = NT_STATUS_DELETE_PENDING, >+ .doc.final_status = NT_STATUS_OK, >+ .doc.num_streams_open_handle = 2, >+ .doc.num_streams_closed_handle = 2, >+ .doc.streams_open_handle = {"::$DATA", AFPRESOURCE_STREAM}, >+ .doc.streams_closed_handle = {"::$DATA", AFPRESOURCE_STREAM}, >+ }; >+ >+ struct tcase tcase_foo_ro = (struct tcase) { >+ .name = BASEDIR "\\file:foo", >+ .access = SEC_FILE_READ_DATA|SEC_FILE_READ_ATTRIBUTE, >+ .write_data = "foo", >+ .write_size = 3, >+ .create.size = 0, >+ .create.initial_status = NT_STATUS_OBJECT_NAME_NOT_FOUND, >+ .create.final_status = NT_STATUS_OBJECT_NAME_NOT_FOUND, >+ .create.num_streams_open_handle = 1, >+ .create.num_streams_closed_handle = 1, >+ .create.streams_open_handle = {"::$DATA"}, >+ .create.streams_closed_handle = {"::$DATA"}, >+ }; >+ >+ struct tcase tcase_foo_rw = (struct tcase) { >+ .name = BASEDIR "\\file:foo", >+ .access = SEC_FILE_READ_DATA|SEC_FILE_READ_ATTRIBUTE|SEC_FILE_WRITE_DATA|SEC_STD_DELETE, >+ .write_data = "foo", >+ .write_size = 3, >+ .create.size = 0, >+ .create.initial_status = NT_STATUS_OBJECT_NAME_NOT_FOUND, >+ .create.final_status = NT_STATUS_OBJECT_NAME_NOT_FOUND, >+ .create.num_streams_open_handle = 1, >+ .create.num_streams_closed_handle = 1, >+ .create.streams_open_handle = {"::$DATA"}, >+ .create.streams_closed_handle = {"::$DATA"}, >+ .write.size = 3, >+ .write.initial_status = NT_STATUS_OK, >+ .write.final_status = NT_STATUS_OK, >+ .write.num_streams_open_handle = 2, >+ .write.num_streams_closed_handle = 2, >+ .write.streams_open_handle = {"::$DATA", ":foo:$DATA"}, >+ .write.streams_closed_handle = {"::$DATA", ":foo:$DATA"}, >+ .overwrite.size = 0, >+ .overwrite.initial_status = NT_STATUS_OBJECT_NAME_NOT_FOUND, >+ .overwrite.final_status = NT_STATUS_OBJECT_NAME_NOT_FOUND, >+ .overwrite.num_streams_open_handle = 1, >+ .overwrite.num_streams_closed_handle = 1, >+ .overwrite.streams_open_handle = {"::$DATA"}, >+ .overwrite.streams_closed_handle = {"::$DATA"}, >+ .eof.size = 0, >+ .eof.initial_status = NT_STATUS_OBJECT_NAME_NOT_FOUND, >+ .eof.final_status = NT_STATUS_OBJECT_NAME_NOT_FOUND, >+ .eof.num_streams_open_handle = 1, >+ .eof.num_streams_closed_handle = 1, >+ .eof.streams_open_handle = {"::$DATA"}, >+ .eof.streams_closed_handle = {"::$DATA"}, >+ .doc.size = 3, >+ .doc.initial_status = NT_STATUS_DELETE_PENDING, >+ .doc.final_status = NT_STATUS_OBJECT_NAME_NOT_FOUND, >+ .doc.num_streams_open_handle = 2, >+ .doc.num_streams_closed_handle = 1, >+ .doc.streams_open_handle = {"::$DATA", ":foo:$DATA"}, >+ .doc.streams_closed_handle = {"::$DATA"}, >+ }; >+ >+ struct tcase tcases[] = { >+ tcase_afpinfo_ro, >+ tcase_afpinfo_rw, >+ tcase_afpresource_ro, >+ tcase_afpresource_rw, >+ tcase_foo_ro, >+ tcase_foo_rw, >+ {NULL} >+ }; >+ >+ ret = torture_smb2_connection(tctx, &tree2); >+ torture_assert_goto(tctx, ret == true, ret, done, >+ "torture_smb2_connection failed\n"); >+ >+ ret = enable_aapl(tctx, tree); >+ torture_assert(tctx, ret == true, "enable_aapl failed\n"); >+ >+ ret = enable_aapl(tctx, tree2); >+ torture_assert(tctx, ret == true, "enable_aapl failed\n"); >+ >+ smb2_deltree(tree, BASEDIR); >+ >+ status = torture_smb2_testdir(tree, BASEDIR, &h1); >+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, >+ "torture_smb2_testdir\n"); >+ smb2_util_close(tree, h1); >+ >+ for (tcase = &tcases[0]; tcase->name != NULL; tcase++) { >+ ret = torture_setup_file(tctx, tree, fname, false); >+ torture_assert_goto(tctx, ret == true, ret, done, >+ "torture_setup_file failed\n"); >+ >+ ret = test_empty_stream_do_one(tctx, tree, tree2, tcase); >+ torture_assert_goto(tctx, ret == true, ret, done, >+ "subtest failed\n"); >+ >+ status = smb2_util_unlink(tree, fname); >+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, >+ "smb2_util_unlink failed\n"); >+ } >+ >+done: >+ smb2_deltree(tree, BASEDIR); >+ TALLOC_FREE(tree2); >+ return ret; >+} >+ > /* > * Note: This test depends on "vfs objects = catia fruit streams_xattr". For > * some tests torture must be run on the host it tests and takes an additional >@@ -5304,6 +5912,7 @@ struct torture_suite *torture_vfs_fruit(TALLOC_CTX *ctx) > torture_suite_add_1smb2_test(suite, "OS X AppleDouble file conversion", test_adouble_conversion); > torture_suite_add_1smb2_test(suite, "NFS ACE entries", test_nfs_aces); > torture_suite_add_1smb2_test(suite, "OS X AppleDouble file conversion without embedded xattr", test_adouble_conversion_wo_xattr); >+ torture_suite_add_1smb2_test(suite, "empty_stream", test_empty_stream); > > return suite; > } >-- >2.17.2 > > >From 0a3d5953d0b24e9f74283556ad1bd8d554518ffd Mon Sep 17 00:00:00 2001 >From: Ralph Boehme <slow@samba.org> >Date: Wed, 17 Oct 2018 19:07:11 +0200 >Subject: [PATCH 22/34] vfs_fruit: add some debugging of dev/ino > >Aids in debugging dev/ino mismatch failures in open_file_ntcreate. > >Bug: https://bugzilla.samba.org/show_bug.cgi?id=13646 > >Signed-off-by: Ralph Boehme <slow@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >(cherry picked from commit 993c7c4e711612225bd07b8fa5544c4bfef88a9e) >--- > source3/modules/vfs_fruit.c | 13 +++++++++++-- > 1 file changed, 11 insertions(+), 2 deletions(-) > >diff --git a/source3/modules/vfs_fruit.c b/source3/modules/vfs_fruit.c >index 181038c9817..2acfce779e1 100644 >--- a/source3/modules/vfs_fruit.c >+++ b/source3/modules/vfs_fruit.c >@@ -2374,6 +2374,10 @@ static SMB_INO_T fruit_inode(const SMB_STRUCT_STAT *sbuf, const char *sname) > SMB_INO_T result; > char *upper_sname; > >+ DBG_DEBUG("fruit_inode called for %ju/%ju [%s]\n", >+ (uintmax_t)sbuf->st_ex_dev, >+ (uintmax_t)sbuf->st_ex_ino, sname); >+ > upper_sname = talloc_strdup_upper(talloc_tos(), sname); > SMB_ASSERT(upper_sname != NULL); > >@@ -2391,8 +2395,8 @@ static SMB_INO_T fruit_inode(const SMB_STRUCT_STAT *sbuf, const char *sname) > /* Hopefully all the variation is in the lower 4 (or 8) bytes! */ > memcpy(&result, hash, sizeof(result)); > >- DEBUG(10, ("fruit_inode \"%s\": ino=0x%llu\n", >- sname, (unsigned long long)result)); >+ DBG_DEBUG("fruit_inode \"%s\": ino=%ju\n", >+ sname, (uintmax_t)result); > > return result; > } >@@ -4815,6 +4819,11 @@ static int fruit_stat_base(vfs_handle_struct *handle, > rc = SMB_VFS_NEXT_LSTAT(handle, smb_fname); > } > smb_fname->stream_name = tmp_stream_name; >+ >+ DBG_DEBUG("fruit_stat_base [%s] dev [%ju] ino [%ju]\n", >+ smb_fname->base_name, >+ (uintmax_t)smb_fname->st.st_ex_dev, >+ (uintmax_t)smb_fname->st.st_ex_ino); > return rc; > } > >-- >2.17.2 > > >From 322b64bd695bb9453a95b4d126b3f7f084e57b5e Mon Sep 17 00:00:00 2001 >From: Ralph Boehme <slow@samba.org> >Date: Mon, 15 Oct 2018 18:38:33 +0200 >Subject: [PATCH 23/34] vfs_fruit: remove resource fork special casing > >Directly unlinking a file with open handles is not good, don't do it. > >Bug: https://bugzilla.samba.org/show_bug.cgi?id=13646 > >Signed-off-by: Ralph Boehme <slow@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >(cherry picked from commit a26032c3f68028b01fb6a7d38851409db1858161) >--- > source3/modules/vfs_fruit.c | 8 -------- > 1 file changed, 8 deletions(-) > >diff --git a/source3/modules/vfs_fruit.c b/source3/modules/vfs_fruit.c >index 2acfce779e1..df93c897c5e 100644 >--- a/source3/modules/vfs_fruit.c >+++ b/source3/modules/vfs_fruit.c >@@ -5736,10 +5736,6 @@ static int fruit_ftruncate_rsrc_xattr(struct vfs_handle_struct *handle, > struct files_struct *fsp, > off_t offset) > { >- if (offset == 0) { >- return SMB_VFS_FREMOVEXATTR(fsp, AFPRESOURCE_EA_NETATALK); >- } >- > #ifdef HAVE_ATTROPEN > return SMB_VFS_NEXT_FTRUNCATE(handle, fsp, offset); > #endif >@@ -5787,10 +5783,6 @@ static int fruit_ftruncate_rsrc_stream(struct vfs_handle_struct *handle, > struct files_struct *fsp, > off_t offset) > { >- if (offset == 0) { >- return SMB_VFS_NEXT_UNLINK(handle, fsp->fsp_name); >- } >- > return SMB_VFS_NEXT_FTRUNCATE(handle, fsp, offset); > } > >-- >2.17.2 > > >From e579ca47905c4acf9b3209c483b5e4f1d15cb9e3 Mon Sep 17 00:00:00 2001 >From: Ralph Boehme <slow@samba.org> >Date: Mon, 22 Oct 2018 16:56:46 +0200 >Subject: [PATCH 24/34] vfs_fruit: add fio->created > >fio->created tracks whether a create created a stream. > >Bug: https://bugzilla.samba.org/show_bug.cgi?id=13646 > >Signed-off-by: Ralph Boehme <slow@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >(cherry picked from commit 1e055a79541eb69eb2deeae897dde3665c5ffee2) >--- > source3/modules/vfs_fruit.c | 9 +++++++++ > 1 file changed, 9 insertions(+) > >diff --git a/source3/modules/vfs_fruit.c b/source3/modules/vfs_fruit.c >index df93c897c5e..5f8b2119fbb 100644 >--- a/source3/modules/vfs_fruit.c >+++ b/source3/modules/vfs_fruit.c >@@ -514,6 +514,9 @@ struct fio { > > /* Denote stream type, meta or rsrc */ > adouble_type_t type; >+ >+ /* Whether the create created the stream */ >+ bool created; > }; > > /* >@@ -5885,6 +5888,7 @@ static NTSTATUS fruit_create_file(vfs_handle_struct *handle, > NTSTATUS status; > struct fruit_config_data *config = NULL; > files_struct *fsp = NULL; >+ struct fio *fio = NULL; > > status = check_aapl(handle, req, in_context_blobs, out_context_blobs); > if (!NT_STATUS_IS_OK(status)) { >@@ -5935,6 +5939,11 @@ static NTSTATUS fruit_create_file(vfs_handle_struct *handle, > goto fail; > } > >+ fio = (struct fio *)VFS_FETCH_FSP_EXTENSION(handle, fsp); >+ if (fio != NULL && pinfo != NULL && *pinfo == FILE_WAS_CREATED) { >+ fio->created = true; >+ } >+ > if (is_ntfs_stream_smb_fname(smb_fname) > || fsp->is_directory) { > return status; >-- >2.17.2 > > >From ae10e473b8a54bca9632895ac057af02ec09229f Mon Sep 17 00:00:00 2001 >From: Ralph Boehme <slow@samba.org> >Date: Wed, 22 Aug 2018 15:22:57 +0200 >Subject: [PATCH 25/34] vfs_fruit: prepare struct fio for fake-fd and on-demand > opening > >Not used for now, that comes in the subsequent commits. > >Bug: https://bugzilla.samba.org/show_bug.cgi?id=13646 > >Signed-off-by: Ralph Boehme <slow@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >(cherry picked from commit 96320eccc9a63b793ff8d05842bce54f120286f9) >--- > source3/modules/vfs_fruit.c | 11 +++++++++++ > 1 file changed, 11 insertions(+) > >diff --git a/source3/modules/vfs_fruit.c b/source3/modules/vfs_fruit.c >index 5f8b2119fbb..dc5ff2ccd2c 100644 >--- a/source3/modules/vfs_fruit.c >+++ b/source3/modules/vfs_fruit.c >@@ -517,6 +517,17 @@ struct fio { > > /* Whether the create created the stream */ > bool created; >+ >+ /* >+ * AFP_AfpInfo stream created, but not written yet, thus still a fake >+ * pipe fd. This is set to true in fruit_open_meta if there was no >+ * exisiting stream but the caller requested O_CREAT. It is later set to >+ * false when we get a write on the stream that then does open and >+ * create the stream. >+ */ >+ bool fake_fd; >+ int flags; >+ int mode; > }; > > /* >-- >2.17.2 > > >From 91bcd8c926b1c49a5c253aa73318f996bc1b3b3d Mon Sep 17 00:00:00 2001 >From: Ralph Boehme <slow@samba.org> >Date: Wed, 22 Aug 2018 15:21:08 +0200 >Subject: [PATCH 26/34] vfs_fruit: prepare fruit_pwrite_meta() for on-demand > opening and writing > >This avoid creating files or blobs in our streams backend when a client >creates a stream but hasn't written anything yet. This is the only sane >way to implement the following semantics: > >* client 1: create stream "file:foo" > >* client 2: open stream "file:foo" > >The second operation of client 2 must fail with NT_STATUS_NOT_FOUND. > >Bug: https://bugzilla.samba.org/show_bug.cgi?id=13646 > >Signed-off-by: Ralph Boehme <slow@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >(cherry picked from commit 4a5c9a9e73230f640eb045a3c47af75b5be9f1d6) >--- > source3/modules/vfs_fruit.c | 34 ++++++++++++++++++++++++++++++++++ > 1 file changed, 34 insertions(+) > >diff --git a/source3/modules/vfs_fruit.c b/source3/modules/vfs_fruit.c >index dc5ff2ccd2c..09c820eb1ef 100644 >--- a/source3/modules/vfs_fruit.c >+++ b/source3/modules/vfs_fruit.c >@@ -4495,10 +4495,44 @@ static ssize_t fruit_pwrite_meta_stream(vfs_handle_struct *handle, > files_struct *fsp, const void *data, > size_t n, off_t offset) > { >+ struct fio *fio = (struct fio *)VFS_FETCH_FSP_EXTENSION(handle, fsp); > AfpInfo *ai = NULL; > size_t nwritten; >+ int ret; > bool ok; > >+ DBG_DEBUG("Path [%s] offset=%"PRIdMAX", size=%zd\n", >+ fsp_str_dbg(fsp), (intmax_t)offset, n); >+ >+ if (fio == NULL) { >+ return -1; >+ } >+ >+ if (fio->fake_fd) { >+ int fd; >+ >+ ret = SMB_VFS_NEXT_CLOSE(handle, fsp); >+ if (ret != 0) { >+ DBG_ERR("Close [%s] failed: %s\n", >+ fsp_str_dbg(fsp), strerror(errno)); >+ fsp->fh->fd = -1; >+ return -1; >+ } >+ >+ fd = SMB_VFS_NEXT_OPEN(handle, >+ fsp->fsp_name, >+ fsp, >+ fio->flags, >+ fio->mode); >+ if (fd == -1) { >+ DBG_ERR("On-demand create [%s] in write failed: %s\n", >+ fsp_str_dbg(fsp), strerror(errno)); >+ return -1; >+ } >+ fsp->fh->fd = fd; >+ fio->fake_fd = false; >+ } >+ > ai = afpinfo_unpack(talloc_tos(), data); > if (ai == NULL) { > return -1; >-- >2.17.2 > > >From cc3d80d8e46e7f8ab181812b975e050382fe491e Mon Sep 17 00:00:00 2001 >From: Ralph Boehme <slow@samba.org> >Date: Wed, 22 Aug 2018 15:22:08 +0200 >Subject: [PATCH 27/34] vfs_fruit: prepare fruit_pread_meta() for reading on > fake-fd > >If the read on the stream fails we may have hit a handle on a just >created stream (fio->created=true) with no data written yet. > >If that's the case return an empty initialized FinderInfo blob. > >Bug: https://bugzilla.samba.org/show_bug.cgi?id=13646 > >Signed-off-by: Ralph Boehme <slow@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >(cherry picked from commit d7d92710711f6e555ed45c1dda528cd6a83e1bf5) >--- > source3/modules/vfs_fruit.c | 22 ++++++++++++++++++++-- > 1 file changed, 20 insertions(+), 2 deletions(-) > >diff --git a/source3/modules/vfs_fruit.c b/source3/modules/vfs_fruit.c >index 09c820eb1ef..87f3cd1afeb 100644 >--- a/source3/modules/vfs_fruit.c >+++ b/source3/modules/vfs_fruit.c >@@ -4194,8 +4194,7 @@ static ssize_t fruit_pread_meta_stream(vfs_handle_struct *handle, > int ret; > > nread = SMB_VFS_NEXT_PREAD(handle, fsp, data, n, offset); >- >- if (nread == n) { >+ if (nread == -1 || nread == n) { > return nread; > } > >@@ -4299,6 +4298,25 @@ static ssize_t fruit_pread_meta(vfs_handle_struct *handle, > return -1; > } > >+ if (nread == -1 && fio->created) { >+ AfpInfo *ai = NULL; >+ char afpinfo_buf[AFP_INFO_SIZE]; >+ >+ ai = afpinfo_new(talloc_tos()); >+ if (ai == NULL) { >+ return -1; >+ } >+ >+ nread = afpinfo_pack(ai, afpinfo_buf); >+ TALLOC_FREE(ai); >+ if (nread != AFP_INFO_SIZE) { >+ return -1; >+ } >+ >+ memcpy(data, afpinfo_buf, to_return); >+ return to_return; >+ } >+ > return nread; > } > >-- >2.17.2 > > >From c29ae29bef8280a01820a62e72dbb34ebabbdcd6 Mon Sep 17 00:00:00 2001 >From: Ralph Boehme <slow@samba.org> >Date: Wed, 22 Aug 2018 16:49:23 +0200 >Subject: [PATCH 28/34] vfs_fruit: do ino calculation > >As we'll start returning fake fds in open shortly, we can't rely on the >next module to calculat correct inode numbers for streams and must take >over that responsibility. > >Bug: https://bugzilla.samba.org/show_bug.cgi?id=13646 > >Signed-off-by: Ralph Boehme <slow@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >(cherry picked from commit 80afafe398566fd622f431966808d08ba9ec6473) >--- > source3/modules/vfs_fruit.c | 50 +++++++++++++++++++++++++++++++++++-- > 1 file changed, 48 insertions(+), 2 deletions(-) > >diff --git a/source3/modules/vfs_fruit.c b/source3/modules/vfs_fruit.c >index 87f3cd1afeb..f5324968b7e 100644 >--- a/source3/modules/vfs_fruit.c >+++ b/source3/modules/vfs_fruit.c >@@ -4898,6 +4898,14 @@ static int fruit_stat_meta_stream(vfs_handle_struct *handle, > bool follow_links) > { > int ret; >+ ino_t ino; >+ >+ ret = fruit_stat_base(handle, smb_fname, false); >+ if (ret != 0) { >+ return -1; >+ } >+ >+ ino = fruit_inode(&smb_fname->st, smb_fname->stream_name); > > if (follow_links) { > ret = SMB_VFS_NEXT_STAT(handle, smb_fname); >@@ -4905,6 +4913,8 @@ static int fruit_stat_meta_stream(vfs_handle_struct *handle, > ret = SMB_VFS_NEXT_LSTAT(handle, smb_fname); > } > >+ smb_fname->st.st_ex_ino = ino; >+ > return ret; > } > >@@ -5158,7 +5168,41 @@ static int fruit_fstat_meta_stream(vfs_handle_struct *handle, > files_struct *fsp, > SMB_STRUCT_STAT *sbuf) > { >- return SMB_VFS_NEXT_FSTAT(handle, fsp, sbuf); >+ struct fio *fio = (struct fio *)VFS_FETCH_FSP_EXTENSION(handle, fsp); >+ ino_t ino; >+ int ret; >+ >+ if (fio == NULL) { >+ return -1; >+ } >+ >+ if (fio->fake_fd) { >+ ret = fruit_stat_base(handle, fsp->base_fsp->fsp_name, false); >+ if (ret != 0) { >+ return -1; >+ } >+ >+ *sbuf = fsp->base_fsp->fsp_name->st; >+ sbuf->st_ex_size = AFP_INFO_SIZE; >+ sbuf->st_ex_ino = fruit_inode(sbuf, fsp->fsp_name->stream_name); >+ return 0; >+ } >+ >+ ret = fruit_stat_base(handle, fsp->base_fsp->fsp_name, false); >+ if (ret != 0) { >+ return -1; >+ } >+ *sbuf = fsp->base_fsp->fsp_name->st; >+ >+ ino = fruit_inode(sbuf, fsp->fsp_name->stream_name); >+ >+ ret = SMB_VFS_NEXT_FSTAT(handle, fsp, sbuf); >+ if (ret != 0) { >+ return -1; >+ } >+ >+ sbuf->st_ex_ino = ino; >+ return 0; > } > > static int fruit_fstat_meta_netatalk(vfs_handle_struct *handle, >@@ -5393,12 +5437,14 @@ static NTSTATUS fruit_streaminfo_meta_stream( > goto out; > } > >- ret = SMB_VFS_NEXT_STAT(handle, sname); >+ ret = fruit_stat_base(handle, sname, false); > if (ret != 0) { > status = map_nt_error_from_unix(errno); > goto out; > } > >+ sname->st.st_ex_ino = fruit_inode(&sname->st, AFPINFO_STREAM); >+ > id = SMB_VFS_NEXT_FILE_ID_CREATE(handle, &sname->st); > > lck = get_existing_share_mode_lock(talloc_tos(), id); >-- >2.17.2 > > >From 87bd21fcfa8496933946fd0b69edde385f69a995 Mon Sep 17 00:00:00 2001 >From: Ralph Boehme <slow@samba.org> >Date: Wed, 17 Oct 2018 16:51:34 +0200 >Subject: [PATCH 29/34] vfs_fruit: let fruit handle all aio on the FinderInfo > metadata stream > >This will be required to support using fake fds for the FinderInfo >metadata stream. > >Bug: https://bugzilla.samba.org/show_bug.cgi?id=13646 > >Signed-off-by: Ralph Boehme <slow@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >(cherry picked from commit 6fd256afcd5fedc894036efbfba1fc6d2264fba9) >--- > source3/modules/vfs_fruit.c | 4 +--- > 1 file changed, 1 insertion(+), 3 deletions(-) > >diff --git a/source3/modules/vfs_fruit.c b/source3/modules/vfs_fruit.c >index f5324968b7e..b21e16a4a6f 100644 >--- a/source3/modules/vfs_fruit.c >+++ b/source3/modules/vfs_fruit.c >@@ -4416,9 +4416,7 @@ static bool fruit_must_handle_aio_stream(struct fio *fio) > return false; > }; > >- if ((fio->type == ADOUBLE_META) && >- (fio->config->meta == FRUIT_META_NETATALK)) >- { >+ if (fio->type == ADOUBLE_META) { > return true; > } > >-- >2.17.2 > > >From b0acc15842e28f2e71f983b26c3c02f8afe59bd0 Mon Sep 17 00:00:00 2001 >From: Ralph Boehme <slow@samba.org> >Date: Sat, 20 Oct 2018 23:46:43 +0200 >Subject: [PATCH 30/34] vfs_fruit: pass stream size to > delete_invalid_meta_stream() > >delete_invalid_meta_stream() is meant to guard against random data being >present in the FinderInfo stream. If the stream size is 0, it's likely a >freshly created stream where no data has been written to yet, so don't >delete it. > >Bug: https://bugzilla.samba.org/show_bug.cgi?id=13646 > >Signed-off-by: Ralph Boehme <slow@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >(cherry picked from commit 6e13dbddaec9f8118e11309297f85c3cdfd22e43) >--- > source3/modules/vfs_fruit.c | 15 ++++++++++++--- > 1 file changed, 12 insertions(+), 3 deletions(-) > >diff --git a/source3/modules/vfs_fruit.c b/source3/modules/vfs_fruit.c >index b21e16a4a6f..c4311eb3bf6 100644 >--- a/source3/modules/vfs_fruit.c >+++ b/source3/modules/vfs_fruit.c >@@ -5352,7 +5352,8 @@ static NTSTATUS delete_invalid_meta_stream( > const struct smb_filename *smb_fname, > TALLOC_CTX *mem_ctx, > unsigned int *pnum_streams, >- struct stream_struct **pstreams) >+ struct stream_struct **pstreams, >+ off_t size) > { > struct smb_filename *sname = NULL; > int ret; >@@ -5363,6 +5364,10 @@ static NTSTATUS delete_invalid_meta_stream( > return NT_STATUS_INTERNAL_ERROR; > } > >+ if (size == 0) { >+ return NT_STATUS_OK; >+ } >+ > sname = synthetic_smb_fname(talloc_tos(), > smb_fname->base_name, > AFPINFO_STREAM_NAME, >@@ -5416,8 +5421,12 @@ static NTSTATUS fruit_streaminfo_meta_stream( > DBG_ERR("Removing invalid AFPINFO_STREAM size [%jd] from [%s]\n", > (intmax_t)stream[i].size, smb_fname_str_dbg(smb_fname)); > >- return delete_invalid_meta_stream(handle, smb_fname, mem_ctx, >- pnum_streams, pstreams); >+ return delete_invalid_meta_stream(handle, >+ smb_fname, >+ mem_ctx, >+ pnum_streams, >+ pstreams, >+ stream[i].size); > } > > /* >-- >2.17.2 > > >From a4715c87cd8dfce3c63908bca83cd9cf37cd39d1 Mon Sep 17 00:00:00 2001 >From: Ralph Boehme <slow@samba.org> >Date: Sat, 20 Oct 2018 23:40:14 +0200 >Subject: [PATCH 31/34] vfs_fruit: let fruit_pwrite_meta_stream also ftruncate > empty FinderInfo > >fruit_streaminfo currently filters out the FinderInfo stream is >delete-on-close is set. We set it here internally, but the client may >also set it over SMB. Turns out that the macOS SMB server does NOT >filter out FinderInfo stream with delete-on-close set, so we must change >the way filtering is done in fruit_streaminfo. > >Filtering is now done based on the FinderInfo stream being 0-bytes large which >is why I'm adding the ftruncate here. > >No idea why the tests that check the filtering passed the commits >leading up to this one, but if you revert this commit after applying the >whole patchset, the "delete AFP_AfpInfo by writing all 0" test will fail. > >Bug: https://bugzilla.samba.org/show_bug.cgi?id=13646 > >Signed-off-by: Ralph Boehme <slow@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >(cherry picked from commit 480695cd723cc4949e0b39ddb83560efac393412) >--- > source3/modules/vfs_fruit.c | 30 ++++++++++++++++++------------ > 1 file changed, 18 insertions(+), 12 deletions(-) > >diff --git a/source3/modules/vfs_fruit.c b/source3/modules/vfs_fruit.c >index c4311eb3bf6..53bd4aec486 100644 >--- a/source3/modules/vfs_fruit.c >+++ b/source3/modules/vfs_fruit.c >@@ -4554,23 +4554,29 @@ static ssize_t fruit_pwrite_meta_stream(vfs_handle_struct *handle, > return -1; > } > >- nwritten = SMB_VFS_NEXT_PWRITE(handle, fsp, data, n, offset); >- if (nwritten != n) { >- return -1; >- } >- >- if (!ai_empty_finderinfo(ai)) { >- return n; >- } >+ if (ai_empty_finderinfo(ai)) { >+ ret = SMB_VFS_NEXT_FTRUNCATE(handle, fsp, 0); >+ if (ret != 0) { >+ DBG_ERR("SMB_VFS_NEXT_FTRUNCATE on [%s] failed\n", >+ fsp_str_dbg(fsp)); >+ return -1; >+ } > >- ok = set_delete_on_close( >+ ok = set_delete_on_close( > fsp, > true, > handle->conn->session_info->security_token, > handle->conn->session_info->unix_token); >- if (!ok) { >- DBG_ERR("set_delete_on_close on [%s] failed\n", >- fsp_str_dbg(fsp)); >+ if (!ok) { >+ DBG_ERR("set_delete_on_close on [%s] failed\n", >+ fsp_str_dbg(fsp)); >+ return -1; >+ } >+ return n; >+ } >+ >+ nwritten = SMB_VFS_NEXT_PWRITE(handle, fsp, data, n, offset); >+ if (nwritten != n) { > return -1; > } > >-- >2.17.2 > > >From 0a7a273676b57d19035643c19bf35746ad579d5b Mon Sep 17 00:00:00 2001 >From: Ralph Boehme <slow@samba.org> >Date: Sat, 20 Oct 2018 23:50:32 +0200 >Subject: [PATCH 32/34] vfs_fruit: don't check for delete-on-close on the > FinderInfo stream > >macOS SMB server doesn't filter out the FinderInfo stream if it has >delete-on-close set. > >Bug: https://bugzilla.samba.org/show_bug.cgi?id=13646 > >Signed-off-by: Ralph Boehme <slow@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >(cherry picked from commit d8c1bb52018289878b9397d513ebbae63933a05f) >--- > source3/modules/vfs_fruit.c | 73 +------------------------------------ > 1 file changed, 1 insertion(+), 72 deletions(-) > >diff --git a/source3/modules/vfs_fruit.c b/source3/modules/vfs_fruit.c >index 53bd4aec486..448d33418d0 100644 >--- a/source3/modules/vfs_fruit.c >+++ b/source3/modules/vfs_fruit.c >@@ -5402,16 +5402,7 @@ static NTSTATUS fruit_streaminfo_meta_stream( > { > struct stream_struct *stream = *pstreams; > unsigned int num_streams = *pnum_streams; >- struct smb_filename *sname = NULL; >- char *full_name = NULL; >- uint32_t name_hash; >- struct share_mode_lock *lck = NULL; >- struct file_id id = {0}; >- bool delete_on_close_set; > int i; >- int ret; >- NTSTATUS status; >- bool ok; > > for (i = 0; i < num_streams; i++) { > if (strequal_m(stream[i].name, AFPINFO_STREAM)) { >@@ -5435,70 +5426,8 @@ static NTSTATUS fruit_streaminfo_meta_stream( > stream[i].size); > } > >- /* >- * Now check if there's a delete-on-close pending on the stream. If so, >- * hide the stream. This behaviour was verified against a macOS 10.12 >- * SMB server. >- */ > >- sname = synthetic_smb_fname(talloc_tos(), >- smb_fname->base_name, >- AFPINFO_STREAM_NAME, >- NULL, 0); >- if (sname == NULL) { >- status = NT_STATUS_NO_MEMORY; >- goto out; >- } >- >- ret = fruit_stat_base(handle, sname, false); >- if (ret != 0) { >- status = map_nt_error_from_unix(errno); >- goto out; >- } >- >- sname->st.st_ex_ino = fruit_inode(&sname->st, AFPINFO_STREAM); >- >- id = SMB_VFS_NEXT_FILE_ID_CREATE(handle, &sname->st); >- >- lck = get_existing_share_mode_lock(talloc_tos(), id); >- if (lck == NULL) { >- status = NT_STATUS_OK; >- goto out; >- } >- >- full_name = talloc_asprintf(talloc_tos(), >- "%s%s", >- sname->base_name, >- AFPINFO_STREAM); >- if (full_name == NULL) { >- status = NT_STATUS_NO_MEMORY; >- goto out; >- } >- >- status = file_name_hash(handle->conn, full_name, &name_hash); >- if (!NT_STATUS_IS_OK(status)) { >- goto out; >- } >- >- delete_on_close_set = is_delete_on_close_set(lck, name_hash); >- if (delete_on_close_set) { >- ok = del_fruit_stream(mem_ctx, >- pnum_streams, >- pstreams, >- AFPINFO_STREAM); >- if (!ok) { >- status = NT_STATUS_INTERNAL_ERROR; >- goto out; >- } >- } >- >- status = NT_STATUS_OK; >- >-out: >- TALLOC_FREE(sname); >- TALLOC_FREE(lck); >- TALLOC_FREE(full_name); >- return status; >+ return NT_STATUS_OK; > } > > static NTSTATUS fruit_streaminfo_meta_netatalk( >-- >2.17.2 > > >From fbedf4d80d4aae661144680d549a1e9e56927358 Mon Sep 17 00:00:00 2001 >From: Ralph Boehme <slow@samba.org> >Date: Wed, 22 Aug 2018 15:25:26 +0200 >Subject: [PATCH 33/34] vfs_fruit: let fruit_open_meta() with O_CREAT return a > fake-fd > >This is the final step in implementing the needed macOS semantics on the >FinderInfo stream: as long as the client hasn't written a non-zero >FinderInfo blob to the stream, there mustn't be a visible filesystem >entry for other openers. > >Bug: https://bugzilla.samba.org/show_bug.cgi?id=13646 > >Signed-off-by: Ralph Boehme <slow@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> > >Autobuild-User(master): Jeremy Allison <jra@samba.org> >Autobuild-Date(master): Thu Nov 1 01:14:23 CET 2018 on sn-devel-144 > >(cherry picked from commit 1b2de44ea8114cf2025e8b8c843131e2f2dbed27) >--- > selftest/knownfail.d/samba3.vfs.fruit | 3 - > source3/modules/vfs_fruit.c | 165 +++++++++++--------------- > 2 files changed, 72 insertions(+), 96 deletions(-) > >diff --git a/selftest/knownfail.d/samba3.vfs.fruit b/selftest/knownfail.d/samba3.vfs.fruit >index 2d3c21caf91..6307e2b3404 100644 >--- a/selftest/knownfail.d/samba3.vfs.fruit >+++ b/selftest/knownfail.d/samba3.vfs.fruit >@@ -1,5 +1,2 @@ > ^samba3.vfs.fruit streams_depot.OS X AppleDouble file conversion\(nt4_dc\) > ^samba3.vfs.fruit streams_depot.OS X AppleDouble file conversion without embedded xattr\(nt4_dc\) >-^samba3.vfs.fruit metadata_netatalk.empty_stream\(nt4_dc\) >-^samba3.vfs.fruit metadata_stream.empty_stream\(nt4_dc\) >-^samba3.vfs.fruit streams_depot.empty_stream\(nt4_dc\) >diff --git a/source3/modules/vfs_fruit.c b/source3/modules/vfs_fruit.c >index 448d33418d0..14d7a797451 100644 >--- a/source3/modules/vfs_fruit.c >+++ b/source3/modules/vfs_fruit.c >@@ -3403,66 +3403,68 @@ static int fruit_connect(vfs_handle_struct *handle, > return rc; > } > >+static int fruit_fake_fd(void) >+{ >+ int pipe_fds[2]; >+ int fd; >+ int ret; >+ >+ /* >+ * Return a valid fd, but ensure any attempt to use it returns >+ * an error (EPIPE). Once we get a write on the handle, we open >+ * the real fd. >+ */ >+ ret = pipe(pipe_fds); >+ if (ret != 0) { >+ return -1; >+ } >+ fd = pipe_fds[0]; >+ close(pipe_fds[1]); >+ >+ return fd; >+} >+ > static int fruit_open_meta_stream(vfs_handle_struct *handle, > struct smb_filename *smb_fname, > files_struct *fsp, > int flags, > mode_t mode) > { >- AfpInfo *ai = NULL; >- char afpinfo_buf[AFP_INFO_SIZE]; >- ssize_t len, written; >- int hostfd = -1; >- int rc = -1; >+ struct fruit_config_data *config = NULL; >+ struct fio *fio = NULL; >+ int open_flags = flags & ~O_CREAT; >+ int fd; > >- hostfd = SMB_VFS_NEXT_OPEN(handle, smb_fname, fsp, flags, mode); >- if (hostfd == -1) { >- return -1; >- } >+ DBG_DEBUG("Path [%s]\n", smb_fname_str_dbg(smb_fname)); > >- if (!(flags & (O_CREAT | O_TRUNC))) { >- return hostfd; >- } >+ SMB_VFS_HANDLE_GET_DATA(handle, config, >+ struct fruit_config_data, return -1); > >- ai = afpinfo_new(talloc_tos()); >- if (ai == NULL) { >- rc = -1; >- goto fail; >- } >+ fio = VFS_ADD_FSP_EXTENSION(handle, fsp, struct fio, NULL); >+ fio->type = ADOUBLE_META; >+ fio->config = config; > >- len = afpinfo_pack(ai, afpinfo_buf); >- if (len != AFP_INFO_SIZE) { >- rc = -1; >- goto fail; >+ fd = SMB_VFS_NEXT_OPEN(handle, smb_fname, fsp, open_flags, mode); >+ if (fd != -1) { >+ return fd; > } > >- /* Set fd, needed in SMB_VFS_NEXT_PWRITE() */ >- fsp->fh->fd = hostfd; >- >- written = SMB_VFS_NEXT_PWRITE(handle, fsp, afpinfo_buf, >- AFP_INFO_SIZE, 0); >- fsp->fh->fd = -1; >- if (written != AFP_INFO_SIZE) { >- DBG_ERR("bad write [%zd/%d]\n", written, AFP_INFO_SIZE); >- rc = -1; >- goto fail; >+ if (!(flags & O_CREAT)) { >+ VFS_REMOVE_FSP_EXTENSION(handle, fsp); >+ return -1; > } > >- rc = 0; >+ fd = fruit_fake_fd(); >+ if (fd == -1) { >+ VFS_REMOVE_FSP_EXTENSION(handle, fsp); >+ return -1; >+ } > >-fail: >- DBG_DEBUG("rc=%d, fd=%d\n", rc, hostfd); >+ fio->fake_fd = true; >+ fio->flags = flags; >+ fio->mode = mode; > >- if (rc != 0) { >- int saved_errno = errno; >- if (hostfd >= 0) { >- fsp->fh->fd = hostfd; >- SMB_VFS_NEXT_CLOSE(handle, fsp); >- } >- hostfd = -1; >- errno = saved_errno; >- } >- return hostfd; >+ return fd; > } > > static int fruit_open_meta_netatalk(vfs_handle_struct *handle, >@@ -3471,56 +3473,42 @@ static int fruit_open_meta_netatalk(vfs_handle_struct *handle, > int flags, > mode_t mode) > { >- int rc; >- int fakefd = -1; >+ struct fruit_config_data *config = NULL; >+ struct fio *fio = NULL; > struct adouble *ad = NULL; >- int fds[2]; >+ bool meta_exists = false; >+ int fd; > > DBG_DEBUG("Path [%s]\n", smb_fname_str_dbg(smb_fname)); > >- /* >- * Return a valid fd, but ensure any attempt to use it returns an error >- * (EPIPE). All operations on the smb_fname or the fsp will use path >- * based syscalls. >- */ >- rc = pipe(fds); >- if (rc != 0) { >- goto exit; >+ ad = ad_get(talloc_tos(), handle, smb_fname, ADOUBLE_META); >+ if (ad != NULL) { >+ meta_exists = true; > } >- fakefd = fds[0]; >- close(fds[1]); >- >- if (flags & (O_CREAT | O_TRUNC)) { >- /* >- * The attribute does not exist or needs to be truncated, >- * create an AppleDouble EA >- */ >- ad = ad_init(fsp, handle, ADOUBLE_META); >- if (ad == NULL) { >- rc = -1; >- goto exit; >- } > >- rc = ad_set(ad, fsp->fsp_name); >- if (rc != 0) { >- rc = -1; >- goto exit; >- } >+ TALLOC_FREE(ad); > >- TALLOC_FREE(ad); >+ if (!meta_exists && !(flags & O_CREAT)) { >+ errno = ENOENT; >+ return -1; > } > >-exit: >- DEBUG(10, ("fruit_open meta rc=%d, fd=%d\n", rc, fakefd)); >- if (rc != 0) { >- int saved_errno = errno; >- if (fakefd >= 0) { >- close(fakefd); >- } >- fakefd = -1; >- errno = saved_errno; >+ fd = fruit_fake_fd(); >+ if (fd == -1) { >+ return -1; > } >- return fakefd; >+ >+ SMB_VFS_HANDLE_GET_DATA(handle, config, >+ struct fruit_config_data, return -1); >+ >+ fio = VFS_ADD_FSP_EXTENSION(handle, fsp, struct fio, NULL); >+ fio->type = ADOUBLE_META; >+ fio->config = config; >+ fio->fake_fd = true; >+ fio->flags = flags; >+ fio->mode = mode; >+ >+ return fd; > } > > static int fruit_open_meta(vfs_handle_struct *handle, >@@ -3529,7 +3517,6 @@ static int fruit_open_meta(vfs_handle_struct *handle, > { > int fd; > struct fruit_config_data *config = NULL; >- struct fio *fio = NULL; > > DBG_DEBUG("path [%s]\n", smb_fname_str_dbg(smb_fname)); > >@@ -3554,14 +3541,6 @@ static int fruit_open_meta(vfs_handle_struct *handle, > > DBG_DEBUG("path [%s] fd [%d]\n", smb_fname_str_dbg(smb_fname), fd); > >- if (fd == -1) { >- return -1; >- } >- >- fio = VFS_ADD_FSP_EXTENSION(handle, fsp, struct fio, NULL); >- fio->type = ADOUBLE_META; >- fio->config = config; >- > return fd; > } > >-- >2.17.2 > > >From 8c13e42f5df45922173f5ca991b57e56e95de459 Mon Sep 17 00:00:00 2001 >From: Volker Lendecke <vl@samba.org> >Date: Thu, 1 Nov 2018 12:09:14 +0100 >Subject: [PATCH 34/34] torture: Fix the clang build > >It's used uninitialized if an early torture_assert fails > >Bug: https://bugzilla.samba.org/show_bug.cgi?id=13646 > >Signed-off-by: Volker Lendecke <vl@samba.org> >Reviewed-by: Ralph Boehme <slow@samba.org> > >Autobuild-User(master): Volker Lendecke <vl@samba.org> >Autobuild-Date(master): Thu Nov 1 17:34:31 CET 2018 on sn-devel-144 > >(cherry picked from commit 9b28d47b0d86570be5a7c5628e460e01207afb00) >--- > source4/torture/vfs/fruit.c | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > >diff --git a/source4/torture/vfs/fruit.c b/source4/torture/vfs/fruit.c >index 6dd96853a38..6bdcae6c877 100644 >--- a/source4/torture/vfs/fruit.c >+++ b/source4/torture/vfs/fruit.c >@@ -5461,7 +5461,7 @@ static bool test_empty_stream_do_one( > { > bool ret = false; > NTSTATUS status; >- struct smb2_handle baseh; >+ struct smb2_handle baseh = {{0}}; > struct smb2_handle streamh; > struct smb2_create create; > union smb_setfileinfo sfinfo; >-- >2.17.2 >
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Raw
Flags:
jra
:
review+
Actions:
View
Attachments on
bug 13646
:
14514
|
14544
|
14545
|
14546
|
14556
|
14557
|
14558
|
14559
|
14561
| 14562