summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source3/include/proto.h13
-rw-r--r--source3/libsmb/clifile.c148
2 files changed, 111 insertions, 50 deletions
diff --git a/source3/include/proto.h b/source3/include/proto.h
index 557e5f2c71..514ee68e7a 100644
--- a/source3/include/proto.h
+++ b/source3/include/proto.h
@@ -2513,10 +2513,15 @@ NTSTATUS cli_ntcreate(struct cli_state *cli,
int cli_nt_create(struct cli_state *cli, const char *fname, uint32 DesiredAccess);
uint8_t *smb_bytes_push_str(uint8_t *buf, bool ucs2, const char *str,
size_t str_len, size_t *pconverted_size);
-struct async_req *cli_open_send(TALLOC_CTX *mem_ctx, struct event_context *ev,
- struct cli_state *cli,
- const char *fname, int flags, int share_mode);
-NTSTATUS cli_open_recv(struct async_req *req, int *fnum);
+struct tevent_req *cli_open_create(TALLOC_CTX *mem_ctx,
+ struct event_context *ev,
+ struct cli_state *cli, const char *fname,
+ int flags, int share_mode,
+ struct tevent_req **psmbreq);
+struct tevent_req *cli_open_send(TALLOC_CTX *mem_ctx, struct event_context *ev,
+ struct cli_state *cli, const char *fname,
+ int flags, int share_mode);
+NTSTATUS cli_open_recv(struct tevent_req *req, int *fnum);
int cli_open(struct cli_state *cli, const char *fname, int flags, int share_mode);
struct tevent_req *cli_close_create(TALLOC_CTX *mem_ctx,
struct event_context *ev,
diff --git a/source3/libsmb/clifile.c b/source3/libsmb/clifile.c
index c492f2b01f..4293828214 100644
--- a/source3/libsmb/clifile.c
+++ b/source3/libsmb/clifile.c
@@ -998,17 +998,33 @@ uint8_t *smb_bytes_push_str(uint8_t *buf, bool ucs2,
WARNING: if you open with O_WRONLY then getattrE won't work!
****************************************************************************/
-struct async_req *cli_open_send(TALLOC_CTX *mem_ctx, struct event_context *ev,
- struct cli_state *cli,
- const char *fname, int flags, int share_mode)
+struct cli_open_state {
+ uint16_t vwv[15];
+ int fnum;
+ struct iovec bytes;
+};
+
+static void cli_open_done(struct tevent_req *subreq);
+
+struct tevent_req *cli_open_create(TALLOC_CTX *mem_ctx,
+ struct event_context *ev,
+ struct cli_state *cli, const char *fname,
+ int flags, int share_mode,
+ struct tevent_req **psmbreq)
{
- unsigned openfn = 0;
- unsigned accessmode = 0;
- uint8_t additional_flags = 0;
+ struct tevent_req *req, *subreq;
+ struct cli_open_state *state;
+ unsigned openfn;
+ unsigned accessmode;
+ uint8_t additional_flags;
uint8_t *bytes;
- uint16_t vwv[15];
- struct async_req *result;
+ req = tevent_req_create(mem_ctx, &state, struct cli_open_state);
+ if (req == NULL) {
+ return NULL;
+ }
+
+ openfn = 0;
if (flags & O_CREAT) {
openfn |= (1<<4);
}
@@ -1037,63 +1053,96 @@ struct async_req *cli_open_send(TALLOC_CTX *mem_ctx, struct event_context *ev,
accessmode = 0xFF;
}
- SCVAL(vwv + 0, 0, 0xFF);
- SCVAL(vwv + 0, 1, 0);
- SSVAL(vwv + 1, 0, 0);
- SSVAL(vwv + 2, 0, 0); /* no additional info */
- SSVAL(vwv + 3, 0, accessmode);
- SSVAL(vwv + 4, 0, aSYSTEM | aHIDDEN);
- SSVAL(vwv + 5, 0, 0);
- SIVAL(vwv + 6, 0, 0);
- SSVAL(vwv + 8, 0, openfn);
- SIVAL(vwv + 9, 0, 0);
- SIVAL(vwv + 11, 0, 0);
- SIVAL(vwv + 13, 0, 0);
+ SCVAL(state->vwv + 0, 0, 0xFF);
+ SCVAL(state->vwv + 0, 1, 0);
+ SSVAL(state->vwv + 1, 0, 0);
+ SSVAL(state->vwv + 2, 0, 0); /* no additional info */
+ SSVAL(state->vwv + 3, 0, accessmode);
+ SSVAL(state->vwv + 4, 0, aSYSTEM | aHIDDEN);
+ SSVAL(state->vwv + 5, 0, 0);
+ SIVAL(state->vwv + 6, 0, 0);
+ SSVAL(state->vwv + 8, 0, openfn);
+ SIVAL(state->vwv + 9, 0, 0);
+ SIVAL(state->vwv + 11, 0, 0);
+ SIVAL(state->vwv + 13, 0, 0);
+
+ additional_flags = 0;
if (cli->use_oplocks) {
/* if using oplocks then ask for a batch oplock via
core and extended methods */
additional_flags =
FLAG_REQUEST_OPLOCK|FLAG_REQUEST_BATCH_OPLOCK;
- SSVAL(vwv+2, 0, SVAL(vwv+2, 0) | 6);
+ SSVAL(state->vwv+2, 0, SVAL(state->vwv+2, 0) | 6);
}
- bytes = talloc_array(talloc_tos(), uint8_t, 0);
+ bytes = talloc_array(state, uint8_t, 0);
bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), fname,
strlen(fname)+1, NULL);
- if (bytes == NULL) {
+
+ if (tevent_req_nomem(bytes, req)) {
+ return tevent_req_post(req, ev);
+ }
+
+ state->bytes.iov_base = bytes;
+ state->bytes.iov_len = talloc_get_size(bytes);
+
+ subreq = cli_smb_req_create(state, ev, cli, SMBopenX, additional_flags,
+ 15, state->vwv, 1, &state->bytes);
+ if (subreq == NULL) {
+ TALLOC_FREE(req);
return NULL;
}
+ tevent_req_set_callback(subreq, cli_open_done, req);
+ *psmbreq = subreq;
+ return req;
+}
- result = cli_request_send(mem_ctx, ev, cli, SMBopenX, additional_flags,
- 15, vwv, 0, talloc_get_size(bytes), bytes);
- TALLOC_FREE(bytes);
- return result;
+struct tevent_req *cli_open_send(TALLOC_CTX *mem_ctx, struct event_context *ev,
+ struct cli_state *cli, const char *fname,
+ int flags, int share_mode)
+{
+ struct tevent_req *req, *subreq;
+
+ req = cli_open_create(mem_ctx, ev, cli, fname, flags, share_mode,
+ &subreq);
+ if ((req == NULL) || !cli_smb_req_send(subreq)) {
+ TALLOC_FREE(req);
+ return NULL;
+ }
+ return req;
}
-NTSTATUS cli_open_recv(struct async_req *req, int *fnum)
+static void cli_open_done(struct tevent_req *subreq)
{
+ struct tevent_req *req = tevent_req_callback_data(
+ subreq, struct tevent_req);
+ struct cli_open_state *state = tevent_req_data(
+ req, struct cli_open_state);
uint8_t wct;
uint16_t *vwv;
- uint16_t num_bytes;
- uint8_t *bytes;
NTSTATUS status;
- if (async_req_is_nterror(req, &status)) {
- return status;
- }
-
- status = cli_pull_reply(req, &wct, &vwv, &num_bytes, &bytes);
+ status = cli_smb_recv(subreq, 3, &wct, &vwv, NULL, NULL);
if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
-
- if (wct < 3) {
- return NT_STATUS_INVALID_NETWORK_RESPONSE;
+ TALLOC_FREE(subreq);
+ tevent_req_nterror(req, status);
+ return;
}
+ state->fnum = SVAL(vwv+2, 0);
+ tevent_req_done(req);
+}
- *fnum = SVAL(vwv+2, 0);
+NTSTATUS cli_open_recv(struct tevent_req *req, int *fnum)
+{
+ struct cli_open_state *state = tevent_req_data(
+ req, struct cli_open_state);
+ NTSTATUS status;
+ if (tevent_req_is_nterror(req, &status)) {
+ return status;
+ }
+ *fnum = state->fnum;
return NT_STATUS_OK;
}
@@ -1102,34 +1151,41 @@ int cli_open(struct cli_state *cli, const char *fname, int flags,
{
TALLOC_CTX *frame = talloc_stackframe();
struct event_context *ev;
- struct async_req *req;
+ struct tevent_req *req;
+ NTSTATUS status = NT_STATUS_OK;
int result = -1;
- if (cli->fd_event != NULL) {
+ if (cli_has_async_calls(cli)) {
/*
* Can't use sync call while an async call is in flight
*/
- cli_set_error(cli, NT_STATUS_INVALID_PARAMETER);
+ status = NT_STATUS_INVALID_PARAMETER;
goto fail;
}
ev = event_context_init(frame);
if (ev == NULL) {
+ status = NT_STATUS_NO_MEMORY;
goto fail;
}
req = cli_open_send(frame, ev, cli, fname, flags, share_mode);
if (req == NULL) {
+ status = NT_STATUS_NO_MEMORY;
goto fail;
}
- while (req->state < ASYNC_REQ_DONE) {
- event_loop_once(ev);
+ if (!tevent_req_poll(req, ev)) {
+ status = map_nt_error_from_unix(errno);
+ goto fail;
}
cli_open_recv(req, &result);
fail:
TALLOC_FREE(frame);
+ if (!NT_STATUS_IS_OK(status)) {
+ cli_set_error(cli, status);
+ }
return result;
}