summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVolker Lendecke <vl@samba.org>2008-03-18 13:20:10 +0100
committerKarolin Seeger <kseeger@samba.org>2008-03-18 13:49:46 +0100
commit16cbc22a99c0a302d248dc006ac0016042c1e3ec (patch)
tree6a1e98392cf2379eb4737cb7a6318cc5c7b844a2
parentc5356479c1953b15fee8097d5d3436204fc7a4ce (diff)
downloadsamba-16cbc22a99c0a302d248dc006ac0016042c1e3ec.tar.gz
samba-16cbc22a99c0a302d248dc006ac0016042c1e3ec.tar.xz
samba-16cbc22a99c0a302d248dc006ac0016042c1e3ec.zip
Fix bug 5334
I did not test with a zero length file :-) (This used to be commit 7d7a73944c2dcf078f7bc8de65d575f32f9aa851)
-rw-r--r--source3/include/async_req.h7
-rw-r--r--source3/lib/async_req.c30
-rw-r--r--source3/libsmb/clireadwrite.c8
3 files changed, 45 insertions, 0 deletions
diff --git a/source3/include/async_req.h b/source3/include/async_req.h
index 6df53602b26..fb463d5b9a1 100644
--- a/source3/include/async_req.h
+++ b/source3/include/async_req.h
@@ -75,6 +75,13 @@ void async_req_done(struct async_req *req);
void async_req_error(struct async_req *req, NTSTATUS status);
/*
+ * If a request is finished or ends in error even before it has the chance to
+ * trigger the event loop, post a status. This creates an immediate timed
+ * event to call the async function if there is any.
+ */
+bool async_post_status(struct async_req *req, NTSTATUS status);
+
+/*
* Convenience helper to easily check alloc failure within a callback.
*
* Call pattern would be
diff --git a/source3/lib/async_req.c b/source3/lib/async_req.c
index 01154ca4363..2e85d9a38d7 100644
--- a/source3/lib/async_req.c
+++ b/source3/lib/async_req.c
@@ -58,6 +58,36 @@ void async_req_error(struct async_req *req, NTSTATUS status)
}
}
+static void async_trigger(struct event_context *ev, struct timed_event *te,
+ const struct timeval *now, void *priv)
+{
+ struct async_req *req = talloc_get_type_abort(priv, struct async_req);
+
+ TALLOC_FREE(te);
+ if (NT_STATUS_IS_OK(req->status)) {
+ async_req_done(req);
+ }
+ else {
+ async_req_error(req, req->status);
+ }
+}
+
+bool async_post_status(struct async_req *req, NTSTATUS status)
+{
+ /*
+ * Used if a request is finished before it even started
+ */
+
+ req->status = status;
+
+ if (event_add_timed(req->event_ctx, req, timeval_zero(),
+ "async_trigger",
+ async_trigger, req) == NULL) {
+ return false;
+ }
+ return true;
+}
+
bool async_req_nomem(const void *p, struct async_req *req)
{
if (p != NULL) {
diff --git a/source3/libsmb/clireadwrite.c b/source3/libsmb/clireadwrite.c
index 9bd81706730..13c024a2642 100644
--- a/source3/libsmb/clireadwrite.c
+++ b/source3/libsmb/clireadwrite.c
@@ -262,6 +262,14 @@ struct async_req *cli_pull_send(TALLOC_CTX *mem_ctx, struct cli_state *cli,
state->pushed = 0;
state->top_req = 0;
+
+ if (size == 0) {
+ if (!async_post_status(result, NT_STATUS_OK)) {
+ goto failed;
+ }
+ return result;
+ }
+
state->chunk_size = cli_read_max_bufsize(cli);
state->num_reqs = MAX(window_size/state->chunk_size, 1);