smb2:ioctl: support for OS X AAPL copyfile style copy_chunk
authorRalph Boehme <slow@samba.org>
Wed, 22 Apr 2015 20:29:16 +0000 (22:29 +0200)
committerRalph Böhme <slow@samba.org>
Tue, 23 Jun 2015 09:45:23 +0000 (11:45 +0200)
Apple's special copy_chunk ioctl that requests a copy of the whole file
along with all attached metadata.

These copy_chunk requests have a chunk count of 0 that we translate to a
copy_chunk_send VFS call overloading the parameters src_off = dest_off =
num = 0.

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

Signed-off-by: Ralph Boehme <slow@samba.org>
Reviewed-by: Stefan Metzmacher <metze@samba.org>
source3/include/vfs.h
source3/smbd/smb2_ioctl_network_fs.c

index aa1a880e553fe6067ba0478a0669867552261162..081030c14ee71444b2534ef5b4b19c4396fd2ce8 100644 (file)
 /* Bump to version 33 - Samba 4.3 will ship with that. */
 /* Version 33 - change fallocate mode flags param from enum->uint32_t */
 /* Version 33 - Add snapshot create/delete calls */
+/* Version 33 - Add OS X SMB2 AAPL copyfile extension flag to fsp */
 
 #define SMB_VFS_INTERFACE_VERSION 33
 
@@ -257,6 +258,7 @@ typedef struct files_struct {
        bool is_sparse;
        bool backup_intent; /* Handle was successfully opened with backup intent
                                and opener has privilege to do so. */
+       bool aapl_copyfile_supported;
        struct smb_filename *fsp_name;
        uint32_t name_hash;             /* Jenkins hash of full pathname. */
        uint64_t mid;                   /* Mid of the operation that created us. */
index 36b8e899d281ee7185646b5546ef586bde812383..01798ac8f829cb478553879d831c53409092f4af 100644 (file)
@@ -91,6 +91,7 @@ struct fsctl_srv_copychunk_state {
                COPYCHUNK_OUT_LIMITS,
                COPYCHUNK_OUT_RSP,
        } out_data;
+       bool aapl_copyfile;
 };
 static void fsctl_srv_copychunk_vfs_done(struct tevent_req *subreq);
 
@@ -235,6 +236,38 @@ static struct tevent_req *fsctl_srv_copychunk_send(TALLOC_CTX *mem_ctx,
        /* any errors from here onwards should carry copychunk response data */
        state->out_data = COPYCHUNK_OUT_RSP;
 
+       if (cc_copy.chunk_count == 0) {
+               struct tevent_req *vfs_subreq;
+               /*
+                * Process as OS X copyfile request. This is currently
+                * the only copychunk request with a chunk count of 0
+                * we will process.
+                */
+               if (!state->src_fsp->aapl_copyfile_supported) {
+                       tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
+                       return tevent_req_post(req, ev);
+               }
+               if (!state->dst_fsp->aapl_copyfile_supported) {
+                       tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
+                       return tevent_req_post(req, ev);
+               }
+               state->aapl_copyfile = true;
+               vfs_subreq = SMB_VFS_COPY_CHUNK_SEND(dst_fsp->conn,
+                                                    state, ev,
+                                                    state->src_fsp,
+                                                    0,
+                                                    state->dst_fsp,
+                                                    0,
+                                                    0);
+               if (tevent_req_nomem(vfs_subreq, req)) {
+                       return tevent_req_post(req, ev);
+               }
+               tevent_req_set_callback(vfs_subreq,
+                                       fsctl_srv_copychunk_vfs_done, req);
+               state->dispatch_count++;
+               return req;
+       }
+
        for (i = 0; i < cc_copy.chunk_count; i++) {
                struct tevent_req *vfs_subreq;
                chunk = &cc_copy.chunks[i];
@@ -327,7 +360,11 @@ static NTSTATUS fsctl_srv_copychunk_recv(struct tevent_req *req,
                *pack_rsp = true;
                break;
        case COPYCHUNK_OUT_RSP:
-               cc_rsp->chunks_written = state->recv_count - state->bad_recv_count;
+               if (state->aapl_copyfile == true) {
+                       cc_rsp->chunks_written = 0;
+               } else {
+                       cc_rsp->chunks_written = state->recv_count - state->bad_recv_count;
+               }
                cc_rsp->chunk_bytes_written = 0;
                cc_rsp->total_bytes_written = state->total_written;
                *pack_rsp = true;