From 74e018f476608429caa1c3594102485ccc17afce Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Fri, 9 Jun 2017 16:50:05 +0200 Subject: [PATCH] s3/smbd: redesign macOS copyfile copy-chunk The copy-chunk request chunk_count can be 0 and Windows server just returns success saying number of copied chunks is 0. macOS client overload this after negotiating AAPL via their SMB2 extensions, meaning it's a so called copyfile request (copy whole file and all streams). We previously checked this at the SMB layer, with this patch we just send this down the VFS, if vfs_fruit is loaded it implements the macOS copyile semantics, otherwise we get Windows behavour.. No change in behaviour. Signed-off-by: Ralph Boehme Reviewed-by: Stefan Metzmacher --- source3/modules/vfs_default.c | 6 +++ source3/smbd/smb2_ioctl_network_fs.c | 76 +++++++++++++++--------------------- 2 files changed, 37 insertions(+), 45 deletions(-) diff --git a/source3/modules/vfs_default.c b/source3/modules/vfs_default.c index 291f39b60f2..9b86a905203 100644 --- a/source3/modules/vfs_default.c +++ b/source3/modules/vfs_default.c @@ -1746,6 +1746,12 @@ static struct tevent_req *vfswrap_offload_write_send( .remaining = to_copy, .flags = flags, }; + + if (to_copy == 0) { + tevent_req_done(req); + return tevent_req_post(req, ev); + } + state->buf = talloc_array(state, uint8_t, num); if (tevent_req_nomem(state->buf, req)) { return tevent_req_post(req, ev); diff --git a/source3/smbd/smb2_ioctl_network_fs.c b/source3/smbd/smb2_ioctl_network_fs.c index 98355e2d988..b528ff2346d 100644 --- a/source3/smbd/smb2_ioctl_network_fs.c +++ b/source3/smbd/smb2_ioctl_network_fs.c @@ -248,54 +248,35 @@ static NTSTATUS fsctl_srv_copychunk_loop(struct tevent_req *req) struct fsctl_srv_copychunk_state *state = tevent_req_data( req, struct fsctl_srv_copychunk_state); struct tevent_req *subreq = NULL; - struct srv_copychunk *chunk = NULL; + uint32_t length = 0; + off_t source_off = 0; + off_t target_off = 0; - if (state->cc_copy.chunk_count == 0) { - /* - * 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 || - !state->dst_fsp->aapl_copyfile_supported) - { - /* - * This must not produce an error but just return a - * chunk count of 0 in the response. - */ - tevent_req_done(req); - tevent_req_post(req, state->ev); - return NT_STATUS_OK; - } - state->aapl_copyfile = true; - - subreq = SMB_VFS_OFFLOAD_WRITE_SEND(state->dst_fsp->conn, - state, - state->ev, - state->src_fsp, - 0, - state->dst_fsp, - 0, - 0, - 0); - if (subreq == NULL) { - return NT_STATUS_NO_MEMORY; - } - tevent_req_set_callback(subreq, - fsctl_srv_copychunk_vfs_done, req); - return NT_STATUS_OK; - } + /* + * chunk_count can be 0 which must either just do nothing returning + * success saying number of copied chunks is 0 (verified against + * Windows). + * + * Or it can be a special macOS copyfile request, so we send this into + * the VFS, vfs_fruit if loaded implements the macOS copyile semantics. + */ + if (state->cc_copy.chunk_count > 0) { + struct srv_copychunk *chunk = NULL; - chunk = &state->cc_copy.chunks[state->current_chunk]; + chunk = &state->cc_copy.chunks[state->current_chunk]; + length = chunk->length; + source_off = chunk->source_off; + target_off = chunk->target_off; + } subreq = SMB_VFS_OFFLOAD_WRITE_SEND(state->dst_fsp->conn, state, state->ev, state->src_fsp, - chunk->source_off, + source_off, state->dst_fsp, - chunk->target_off, - chunk->length, + target_off, + length, 0); if (tevent_req_nomem(subreq, req)) { return NT_STATUS_NO_MEMORY; @@ -331,6 +312,15 @@ static void fsctl_srv_copychunk_vfs_done(struct tevent_req *subreq) (unsigned int)state->cc_copy.chunk_count); state->total_written += chunk_nwritten; + if (state->cc_copy.chunk_count == 0) { + /* + * This must not produce an error but just return a chunk count + * of 0 in the response. + */ + tevent_req_done(req); + return; + } + state->current_chunk++; if (state->current_chunk == state->cc_copy.chunk_count) { tevent_req_done(req); @@ -361,11 +351,7 @@ static NTSTATUS fsctl_srv_copychunk_recv(struct tevent_req *req, *pack_rsp = true; break; case COPYCHUNK_OUT_RSP: - if (state->aapl_copyfile == true) { - cc_rsp->chunks_written = 0; - } else { - cc_rsp->chunks_written = state->current_chunk; - } + cc_rsp->chunks_written = state->current_chunk; cc_rsp->chunk_bytes_written = 0; cc_rsp->total_bytes_written = state->total_written; *pack_rsp = true; -- 2.11.4.GIT