vfs_fruit: filter out AFP_AfpInfo streams with pending delete-on-close
authorRalph Boehme <slow@samba.org>
Thu, 7 Dec 2017 16:32:35 +0000 (17:32 +0100)
committerRalph Boehme <slow@samba.org>
Tue, 9 Jan 2018 11:53:32 +0000 (12:53 +0100)
This is in preperation of fixing the implementation of removing the
AFP_AfpInfo stream by zeroing the FinderInfo out.

We currently remove the stream blob from the underyling filesystem
backing store, but that results in certain operations to fail on any
still open file-handle.

The fix comes in the next commit which will convert to backing store
delete operation to a set delete-on-close on the stream.

This commit adds filtering on streams that have the delete-on-close
set. It is only needed for the fruit:metadata=stream case, as with
fruit:metadata=netatalk the filtering is already done in
fruit_streaminfo_meta_netatalk().

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

Signed-off-by: Ralph Boehme <slow@samba.org>
Reviewed-by: Jeremy Allison <jra@samba.org>
source3/modules/vfs_fruit.c

index d72ac7ef92cc3d19b7d8e113c30b2dbb847220c3..4b53136aef947fa67743f6640e6e8e264b4371df 100644 (file)
@@ -4940,7 +4940,16 @@ 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)) {
@@ -4960,7 +4969,68 @@ static NTSTATUS fruit_streaminfo_meta_stream(
                                                  pnum_streams, pstreams);
        }
 
-       return NT_STATUS_OK;
+       /*
+        * 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 = SMB_VFS_NEXT_STAT(handle, sname);
+       if (ret != 0) {
+               status = map_nt_error_from_unix(errno);
+               goto out;
+       }
+
+       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;
 }
 
 static NTSTATUS fruit_streaminfo_meta_netatalk(