From: David Disseldorp Date: Tue, 15 Jan 2013 16:23:11 +0000 (+0100) Subject: smb2_ioctl: track copychunk response output state X-Git-Url: http://git.samba.org/?a=commitdiff_plain;h=bf07c33dac37442b8f5b49e68653f8ef629ff679;p=obnox%2Fsamba%2Fsamba-obnox.git smb2_ioctl: track copychunk response output state Treat the response data independent to the status. Reviewed by: Jeremy Allison --- diff --git a/source3/smbd/smb2_ioctl_network_fs.c b/source3/smbd/smb2_ioctl_network_fs.c index 125aaaee380..8341f2b327d 100644 --- a/source3/smbd/smb2_ioctl_network_fs.c +++ b/source3/smbd/smb2_ioctl_network_fs.c @@ -163,6 +163,11 @@ struct fsctl_srv_copychunk_state { struct lock_struct *wlocks; struct lock_struct *rlocks; uint32_t num_locks; + enum { + COPYCHUNK_OUT_EMPTY = 0, + COPYCHUNK_OUT_LIMITS, + COPYCHUNK_OUT_RSP, + } out_data; }; static void fsctl_srv_copychunk_vfs_done(struct tevent_req *subreq); @@ -236,9 +241,13 @@ static struct tevent_req *fsctl_srv_copychunk_send(TALLOC_CTX *mem_ctx, state->status = copychunk_check_limits(&cc_copy); if (tevent_req_nterror(req, state->status)) { DEBUG(3, ("copy chunk req exceeds limits\n")); + state->out_data = COPYCHUNK_OUT_LIMITS; return tevent_req_post(req, ev); } + /* any errors from here onwards should carry copychunk response data */ + state->out_data = COPYCHUNK_OUT_RSP; + state->status = copychunk_lock_all(state, &cc_copy, state->src_fsp, @@ -338,22 +347,32 @@ static void fsctl_srv_copychunk_vfs_done(struct tevent_req *subreq) } static NTSTATUS fsctl_srv_copychunk_recv(struct tevent_req *req, - struct srv_copychunk_rsp *cc_rsp) + struct srv_copychunk_rsp *cc_rsp, + bool *pack_rsp) { struct fsctl_srv_copychunk_state *state = tevent_req_data(req, struct fsctl_srv_copychunk_state); NTSTATUS status; - if (NT_STATUS_EQUAL(state->status, NT_STATUS_INVALID_PARAMETER)) { + switch (state->out_data) { + case COPYCHUNK_OUT_EMPTY: + *pack_rsp = false; + break; + case COPYCHUNK_OUT_LIMITS: /* 2.2.32.1 - send back our maximum transfer size limits */ copychunk_pack_limits(cc_rsp); - tevent_req_received(req); - return NT_STATUS_INVALID_PARAMETER; + *pack_rsp = true; + break; + case COPYCHUNK_OUT_RSP: + 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; + break; + default: /* not reached */ + assert(1); + break; } - - 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; status = state->status; tevent_req_received(req); @@ -575,17 +594,20 @@ static void smb2_ioctl_network_fs_copychunk_done(struct tevent_req *subreq) struct smbd_smb2_ioctl_state); struct srv_copychunk_rsp cc_rsp; NTSTATUS status; - enum ndr_err_code ndr_ret; + bool pack_rsp = false; ZERO_STRUCT(cc_rsp); - status = fsctl_srv_copychunk_recv(subreq, &cc_rsp); + status = fsctl_srv_copychunk_recv(subreq, &cc_rsp, &pack_rsp); TALLOC_FREE(subreq); - ndr_ret = ndr_push_struct_blob(&ioctl_state->out_output, - ioctl_state, - &cc_rsp, - (ndr_push_flags_fn_t)ndr_push_srv_copychunk_rsp); - if (ndr_ret != NDR_ERR_SUCCESS) { - status = NT_STATUS_INTERNAL_ERROR; + if (pack_rsp == true) { + enum ndr_err_code ndr_ret; + ndr_ret = ndr_push_struct_blob(&ioctl_state->out_output, + ioctl_state, + &cc_rsp, + (ndr_push_flags_fn_t)ndr_push_srv_copychunk_rsp); + if (ndr_ret != NDR_ERR_SUCCESS) { + status = NT_STATUS_INTERNAL_ERROR; + } } if (!tevent_req_nterror(req, status)) {