From: Ralph Boehme Date: Sat, 20 Oct 2018 12:53:50 +0000 (+0200) Subject: vfs_fruit: filter empty streams X-Git-Tag: samba-4.8.8~56 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=280722734964afa847280851f6d493e2f987f060;p=thirdparty%2Fsamba.git 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 Reviewed-by: Jeremy Allison (cherry picked from commit ebfcf75e993b1a792db76b94aa898532e1c81eeb) --- 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 a36e131be30..9932249e315 100644 --- a/source3/modules/vfs_fruit.c +++ b/source3/modules/vfs_fruit.c @@ -5578,6 +5578,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, @@ -5599,6 +5629,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)) { @@ -5868,13 +5900,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)