The Samba-Bugzilla – Attachment 4830 Details for
Bug 6606
cli_read_andx_done() not handling short reads
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Patch for 3.4
0001-s3-Fix-bug-6606.patch (text/plain), 8.29 KB, created by
Volker Lendecke
on 2009-10-12 04:25:36 UTC
(
hide
)
Description:
Patch for 3.4
Filename:
MIME Type:
Creator:
Volker Lendecke
Created:
2009-10-12 04:25:36 UTC
Size:
8.29 KB
patch
obsolete
>From aaa2caa638b4a5709f4651a9c49625ba8a7e1c50 Mon Sep 17 00:00:00 2001 >From: Volker Lendecke <vl@samba.org> >Date: Sat, 10 Oct 2009 11:15:42 +0200 >Subject: [PATCH] s3: Fix bug 6606 > >This is a port of 1f34ffa0caae5 and 24309bdb2efc to 3.4. >--- > source3/libsmb/clireadwrite.c | 189 +++++++++++++++++++++++++++++++++++------ > 1 files changed, 164 insertions(+), 25 deletions(-) > >diff --git a/source3/libsmb/clireadwrite.c b/source3/libsmb/clireadwrite.c >index b1064ba..e6c7fb4 100644 >--- a/source3/libsmb/clireadwrite.c >+++ b/source3/libsmb/clireadwrite.c >@@ -195,6 +195,135 @@ NTSTATUS cli_read_andx_recv(struct async_req *req, ssize_t *received, > return NT_STATUS_OK; > } > >+struct cli_readall_state { >+ struct tevent_context *ev; >+ struct cli_state *cli; >+ uint16_t fnum; >+ off_t start_offset; >+ size_t size; >+ size_t received; >+ uint8_t *buf; >+}; >+ >+static void cli_readall_done(struct async_req *subreq); >+ >+static struct async_req *cli_readall_send(TALLOC_CTX *mem_ctx, >+ struct event_context *ev, >+ struct cli_state *cli, >+ uint16_t fnum, >+ off_t offset, size_t size) >+{ >+ struct async_req *req, *subreq; >+ struct cli_readall_state *state; >+ >+ if (!async_req_setup(mem_ctx, &req, &state, >+ struct cli_readall_state)) { >+ return NULL; >+ } >+ state->ev = ev; >+ state->cli = cli; >+ state->fnum = fnum; >+ state->start_offset = offset; >+ state->size = size; >+ state->received = 0; >+ state->buf = NULL; >+ >+ subreq = cli_read_andx_send(state, ev, cli, fnum, offset, size); >+ if (async_req_nomem(subreq, req)) { >+ TALLOC_FREE(req); >+ return NULL; >+ } >+ subreq->async.fn = cli_readall_done; >+ subreq->async.priv = req; >+ return req; >+} >+ >+static void cli_readall_done(struct async_req *subreq) >+{ >+ struct async_req *req = talloc_get_type_abort( >+ subreq->async.priv, struct async_req); >+ struct cli_readall_state *state = talloc_get_type_abort( >+ req->private_data, struct cli_readall_state); >+ ssize_t received; >+ uint8_t *buf; >+ NTSTATUS status; >+ >+ status = cli_read_andx_recv(subreq, &received, &buf); >+ if (!NT_STATUS_IS_OK(status)) { >+ async_req_nterror(req, status); >+ return; >+ } >+ >+ if (received == 0) { >+ /* EOF */ >+ async_req_done(req); >+ return; >+ } >+ >+ if ((state->received == 0) && (received == state->size)) { >+ /* Ideal case: Got it all in one run */ >+ state->buf = buf; >+ state->received += received; >+ async_req_done(req); >+ return; >+ } >+ >+ /* >+ * We got a short read, issue a read for the >+ * rest. Unfortunately we have to allocate the buffer >+ * ourselves now, as our caller expects to receive a single >+ * buffer. cli_read_andx does it from the buffer received from >+ * the net, but with a short read we have to put it together >+ * from several reads. >+ */ >+ >+ if (state->buf == NULL) { >+ state->buf = talloc_array(state, uint8_t, state->size); >+ if (async_req_nomem(state->buf, req)) { >+ return; >+ } >+ } >+ memcpy(state->buf + state->received, buf, received); >+ state->received += received; >+ >+ TALLOC_FREE(subreq); >+ >+ if (state->received >= state->size) { >+ async_req_done(req); >+ return; >+ } >+ >+ subreq = cli_read_andx_send(state, state->ev, state->cli, state->fnum, >+ state->start_offset + state->received, >+ state->size - state->received); >+ if (async_req_nomem(subreq, req)) { >+ return; >+ } >+ subreq->async.fn = cli_readall_done; >+ subreq->async.priv = req; >+} >+ >+static NTSTATUS cli_readall_recv(struct async_req *req, ssize_t *received, >+ uint8_t **rcvbuf) >+{ >+ struct cli_readall_state *state = talloc_get_type_abort( >+ req->private_data, struct cli_readall_state); >+ NTSTATUS status; >+ >+ if (async_req_is_nterror(req, &status)) { >+ return status; >+ } >+ *received = state->received; >+ *rcvbuf = state->buf; >+ return NT_STATUS_OK; >+} >+ >+struct cli_pull_subreq { >+ struct async_req *req; >+ ssize_t received; >+ uint8_t *buf; >+}; >+ > /* > * Parallel read support. > * >@@ -221,7 +350,7 @@ struct cli_pull_state { > * Outstanding requests > */ > int num_reqs; >- struct async_req **reqs; >+ struct cli_pull_subreq *reqs; > > /* > * For how many bytes did we send requests already? >@@ -308,7 +437,7 @@ struct async_req *cli_pull_send(TALLOC_CTX *mem_ctx, > state->num_reqs = MAX(window_size/state->chunk_size, 1); > state->num_reqs = MIN(state->num_reqs, cli->max_mux); > >- state->reqs = TALLOC_ZERO_ARRAY(state, struct async_req *, >+ state->reqs = TALLOC_ZERO_ARRAY(state, struct cli_pull_subreq, > state->num_reqs); > if (state->reqs == NULL) { > goto failed; >@@ -317,6 +446,7 @@ struct async_req *cli_pull_send(TALLOC_CTX *mem_ctx, > state->requested = 0; > > for (i=0; i<state->num_reqs; i++) { >+ struct cli_pull_subreq *subreq = &state->reqs[i]; > SMB_OFF_T size_left; > size_t request_thistime; > >@@ -328,17 +458,17 @@ struct async_req *cli_pull_send(TALLOC_CTX *mem_ctx, > size_left = size - state->requested; > request_thistime = MIN(size_left, state->chunk_size); > >- state->reqs[i] = cli_read_andx_send( >+ subreq->req = cli_readall_send( > state->reqs, ev, cli, fnum, > state->start_offset + state->requested, > request_thistime); > >- if (state->reqs[i] == NULL) { >+ if (subreq->req == NULL) { > goto failed; > } > >- state->reqs[i]->async.fn = cli_pull_read_done; >- state->reqs[i]->async.priv = result; >+ subreq->req->async.fn = cli_pull_read_done; >+ subreq->req->async.priv = result; > > state->requested += request_thistime; > } >@@ -360,12 +490,24 @@ static void cli_pull_read_done(struct async_req *read_req) > read_req->async.priv, struct async_req); > struct cli_pull_state *state = talloc_get_type_abort( > pull_req->private_data, struct cli_pull_state); >- struct cli_request *read_state = talloc_get_type_abort( >- read_req->private_data, struct cli_request); >+ struct cli_pull_subreq *pull_subreq = NULL; > NTSTATUS status; >+ int i; >+ >+ for (i = 0; i < state->num_reqs; i++) { >+ pull_subreq = &state->reqs[i]; >+ if (read_req == pull_subreq->req) { >+ break; >+ } >+ } >+ if (i == state->num_reqs) { >+ /* Huh -- received something we did not send?? */ >+ async_req_nterror(pull_req, NT_STATUS_INTERNAL_ERROR); >+ return; >+ } > >- status = cli_read_andx_recv(read_req, &read_state->data.read.received, >- &read_state->data.read.rcvbuf); >+ status = cli_readall_recv(read_req, &pull_subreq->received, >+ &pull_subreq->buf); > if (!NT_STATUS_IS_OK(status)) { > async_req_nterror(state->req, status); > return; >@@ -380,36 +522,33 @@ static void cli_pull_read_done(struct async_req *read_req) > * requests. > */ > >- while (state->reqs[state->top_req] != NULL) { >- struct cli_request *top_read; >+ while (state->reqs[state->top_req].req != NULL) { >+ struct cli_pull_subreq *top_read; > > DEBUG(11, ("cli_pull_read_done: top_req = %d\n", > state->top_req)); > >- if (state->reqs[state->top_req]->state < ASYNC_REQ_DONE) { >+ top_read = &state->reqs[state->top_req]; >+ >+ if (state->reqs[state->top_req].req->state < ASYNC_REQ_DONE) { > DEBUG(11, ("cli_pull_read_done: top request not yet " > "done\n")); > return; > } > >- top_read = talloc_get_type_abort( >- state->reqs[state->top_req]->private_data, >- struct cli_request); >- > DEBUG(10, ("cli_pull_read_done: Pushing %d bytes, %d already " >- "pushed\n", (int)top_read->data.read.received, >+ "pushed\n", (int)top_read->received, > (int)state->pushed)); > >- status = state->sink((char *)top_read->data.read.rcvbuf, >- top_read->data.read.received, >- state->priv); >+ status = state->sink((char *)top_read->buf, >+ top_read->received, state->priv); > if (!NT_STATUS_IS_OK(status)) { > async_req_nterror(state->req, status); > return; > } >- state->pushed += top_read->data.read.received; >+ state->pushed += top_read->received; > >- TALLOC_FREE(state->reqs[state->top_req]); >+ TALLOC_FREE(state->reqs[state->top_req].req); > > if (state->requested < state->size) { > struct async_req *new_req; >@@ -426,7 +565,7 @@ static void cli_pull_read_done(struct async_req *read_req) > + state->requested), > state->top_req)); > >- new_req = cli_read_andx_send( >+ new_req = cli_readall_send( > state->reqs, state->ev, state->cli, > state->fnum, > state->start_offset + state->requested, >@@ -439,7 +578,7 @@ static void cli_pull_read_done(struct async_req *read_req) > new_req->async.fn = cli_pull_read_done; > new_req->async.priv = pull_req; > >- state->reqs[state->top_req] = new_req; >+ state->reqs[state->top_req].req = new_req; > state->requested += request_thistime; > } > >-- >1.6.0.4 >
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Raw
Actions:
View
Attachments on
bug 6606
:
4720
|
4722
|
4724
| 4830