mirror of
https://github.com/samba-team/samba.git
synced 2025-02-28 01:58:17 +03:00
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 <slow@samba.org> Reviewed-by: Stefan Metzmacher <metze@samba.org>
This commit is contained in:
parent
2ad11c6920
commit
74e018f476
@ -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);
|
||||
|
@ -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;
|
||||
/*
|
||||
* 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;
|
||||
|
||||
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 = &state->cc_copy.chunks[state->current_chunk];
|
||||
length = chunk->length;
|
||||
source_off = chunk->source_off;
|
||||
target_off = chunk->target_off;
|
||||
}
|
||||
|
||||
chunk = &state->cc_copy.chunks[state->current_chunk];
|
||||
|
||||
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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user