1
0
mirror of https://github.com/samba-team/samba.git synced 2025-03-20 22:50:26 +03:00

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)
This commit is contained in:
Ralph Boehme 2018-10-20 14:53:50 +02:00 committed by Karolin Seeger
parent b0657faba4
commit 2807227349
2 changed files with 38 additions and 9 deletions

View File

@ -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\)

View File

@ -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)