summaryrefslogtreecommitdiff
path: root/source3/libsmb
diff options
context:
space:
mode:
authorJeremy Allison <jra@samba.org>2009-05-20 18:31:36 -0700
committerJeremy Allison <jra@samba.org>2009-05-20 18:31:36 -0700
commit000da55dd930d151db14ee8eed58e82806522692 (patch)
treed04850e454a6f01749ad60d767927e6afaf64fff /source3/libsmb
parentc1a21d085d758284fe6997a05396f225da683352 (diff)
downloadsamba-000da55dd930d151db14ee8eed58e82806522692.tar.gz
samba-000da55dd930d151db14ee8eed58e82806522692.tar.bz2
samba-000da55dd930d151db14ee8eed58e82806522692.zip
Make cli_posix_open() and cli_posix_mkdir() async.
Jeremy.
Diffstat (limited to 'source3/libsmb')
-rw-r--r--source3/libsmb/clifile.c273
1 files changed, 217 insertions, 56 deletions
diff --git a/source3/libsmb/clifile.c b/source3/libsmb/clifile.c
index 3c13383669..2c80f1dd1a 100644
--- a/source3/libsmb/clifile.c
+++ b/source3/libsmb/clifile.c
@@ -3311,87 +3311,248 @@ static uint32_t open_flags_to_wire(int flags)
Open a file - POSIX semantics. Returns fnum. Doesn't request oplock.
****************************************************************************/
-static int cli_posix_open_internal(struct cli_state *cli, const char *fname, int flags, mode_t mode, bool is_dir)
+struct posix_open_state {
+ uint16_t setup;
+ uint8_t *param;
+ uint8_t data[18];
+ uint16_t fnum; /* Out */
+};
+
+static void cli_posix_open_internal_done(struct tevent_req *subreq)
{
- unsigned int data_len = 0;
- unsigned int param_len = 0;
- uint16_t setup = TRANSACT2_SETPATHINFO;
- char *param;
- char data[18];
- char *rparam=NULL, *rdata=NULL;
- char *p;
- uint16_t fnum = (uint16_t)-1;
+ struct tevent_req *req = tevent_req_callback_data(
+ subreq, struct tevent_req);
+ struct posix_open_state *state = tevent_req_data(req, struct posix_open_state);
+ NTSTATUS status;
+ uint8_t *data;
+ uint32_t num_data;
+
+ status = cli_trans_recv(subreq, state, NULL, NULL, NULL, NULL, &data, &num_data);
+ TALLOC_FREE(subreq);
+ if (!NT_STATUS_IS_OK(status)) {
+ tevent_req_nterror(req, status);
+ return;
+ }
+ if (num_data < 12) {
+ tevent_req_nterror(req, status);
+ return;
+ }
+ state->fnum = SVAL(data,2);
+ tevent_req_done(req);
+}
+
+static struct tevent_req *cli_posix_open_internal_send(TALLOC_CTX *mem_ctx,
+ struct event_context *ev,
+ struct cli_state *cli,
+ const char *fname,
+ int flags,
+ mode_t mode,
+ bool is_dir)
+{
+ struct tevent_req *req = NULL, *subreq = NULL;
+ struct posix_open_state *state = NULL;
uint32_t wire_flags = open_flags_to_wire(flags);
- size_t srclen = 2*(strlen(fname)+1);
- param = SMB_MALLOC_ARRAY(char, 6+srclen+2);
- if (!param) {
- return false;
+ req = tevent_req_create(mem_ctx, &state, struct posix_open_state);
+ if (req == NULL) {
+ return NULL;
}
- memset(param, '\0', 6);
- SSVAL(param,0, SMB_POSIX_PATH_OPEN);
- p = &param[6];
- p += clistr_push(cli, p, fname, srclen, STR_TERMINATE);
- param_len = PTR_DIFF(p, param);
+ /* Setup setup word. */
+ SSVAL(&state->setup, 0, TRANSACT2_SETPATHINFO);
- if (is_dir) {
- wire_flags &= ~(SMB_O_RDONLY|SMB_O_RDWR|SMB_O_WRONLY);
- wire_flags |= SMB_O_DIRECTORY;
+ /* Setup param array. */
+ state->param = talloc_array(state, uint8_t, 6);
+ if (tevent_req_nomem(state->param, req)) {
+ return tevent_req_post(req, ev);
}
+ memset(state->param, '\0', 6);
+ SSVAL(state->param, 0, SMB_POSIX_PATH_OPEN);
- p = data;
- SIVAL(p,0,0); /* No oplock. */
- SIVAL(p,4,wire_flags);
- SIVAL(p,8,unix_perms_to_wire(mode));
- SIVAL(p,12,0); /* Top bits of perms currently undefined. */
- SSVAL(p,16,SMB_NO_INFO_LEVEL_RETURNED); /* No info level returned. */
+ state->param = trans2_bytes_push_str(state->param, cli_ucs2(cli), fname,
+ strlen(fname)+1, NULL);
- data_len = 18;
+ if (tevent_req_nomem(state->param, req)) {
+ return tevent_req_post(req, ev);
+ }
- if (!cli_send_trans(cli, SMBtrans2,
- NULL, /* name */
- -1, 0, /* fid, flags */
- &setup, 1, 0, /* setup, length, max */
- param, param_len, 0, /* param, length, max */
- (char *)&data, data_len, cli->max_xmit /* data, length, max */
- )) {
- SAFE_FREE(param);
- return -1;
+ /* Setup data words. */
+ if (is_dir) {
+ wire_flags &= ~(SMB_O_RDONLY|SMB_O_RDWR|SMB_O_WRONLY);
+ wire_flags |= SMB_O_DIRECTORY;
}
- SAFE_FREE(param);
+ SIVAL(state->data,0,0); /* No oplock. */
+ SIVAL(state->data,4,wire_flags);
+ SIVAL(state->data,8,unix_perms_to_wire(mode));
+ SIVAL(state->data,12,0); /* Top bits of perms currently undefined. */
+ SSVAL(state->data,16,SMB_NO_INFO_LEVEL_RETURNED); /* No info level returned. */
- if (!cli_receive_trans(cli, SMBtrans2,
- &rparam, &param_len,
- &rdata, &data_len)) {
- return -1;
+ subreq = cli_trans_send(state, /* mem ctx. */
+ ev, /* event ctx. */
+ cli, /* cli_state. */
+ SMBtrans2, /* cmd. */
+ NULL, /* pipe name. */
+ -1, /* fid. */
+ 0, /* function. */
+ 0, /* flags. */
+ &state->setup, /* setup. */
+ 1, /* num setup uint16_t words. */
+ 0, /* max returned setup. */
+ state->param, /* param. */
+ talloc_get_size(state->param),/* num param. */
+ 2, /* max returned param. */
+ state->data, /* data. */
+ 18, /* num data. */
+ 12); /* max returned data. */
+
+ if (tevent_req_nomem(subreq, req)) {
+ return tevent_req_post(req, ev);
}
+ tevent_req_set_callback(subreq, cli_posix_open_internal_done, req);
+ return req;
+}
- fnum = SVAL(rdata,2);
+struct tevent_req *cli_posix_open_send(TALLOC_CTX *mem_ctx,
+ struct event_context *ev,
+ struct cli_state *cli,
+ const char *fname,
+ int flags,
+ mode_t mode)
+{
+ return cli_posix_open_internal_send(mem_ctx, ev,
+ cli, fname, flags, mode, false);
+}
- SAFE_FREE(rdata);
- SAFE_FREE(rparam);
+NTSTATUS cli_posix_open_recv(struct tevent_req *req, uint16_t *pfnum)
+{
+ struct posix_open_state *state = tevent_req_data(req, struct posix_open_state);
+ NTSTATUS status;
- return fnum;
+ if (tevent_req_is_nterror(req, &status)) {
+ return status;
+ }
+ *pfnum = state->fnum;
+ return NT_STATUS_OK;
}
/****************************************************************************
- open - POSIX semantics.
+ Open - POSIX semantics. Doesn't request oplock.
****************************************************************************/
-int cli_posix_open(struct cli_state *cli, const char *fname, int flags, mode_t mode)
+NTSTATUS cli_posix_open(struct cli_state *cli, const char *fname,
+ int flags, mode_t mode, uint16_t *pfnum)
{
- return cli_posix_open_internal(cli, fname, flags, mode, False);
+
+ TALLOC_CTX *frame = talloc_stackframe();
+ struct event_context *ev = NULL;
+ struct tevent_req *req = NULL;
+ NTSTATUS status = NT_STATUS_OK;
+
+ if (cli_has_async_calls(cli)) {
+ /*
+ * Can't use sync call while an async call is in flight
+ */
+ status = NT_STATUS_INVALID_PARAMETER;
+ goto fail;
+ }
+
+ ev = event_context_init(frame);
+ if (ev == NULL) {
+ status = NT_STATUS_NO_MEMORY;
+ goto fail;
+ }
+
+ req = cli_posix_open_send(frame,
+ ev,
+ cli,
+ fname,
+ flags,
+ mode);
+ if (req == NULL) {
+ status = NT_STATUS_NO_MEMORY;
+ goto fail;
+ }
+
+ if (!tevent_req_poll(req, ev)) {
+ status = map_nt_error_from_unix(errno);
+ goto fail;
+ }
+
+ status = cli_posix_open_recv(req, pfnum);
+
+ fail:
+ TALLOC_FREE(frame);
+ if (!NT_STATUS_IS_OK(status)) {
+ cli_set_error(cli, status);
+ }
+ return status;
}
-/****************************************************************************
- mkdir - POSIX semantics.
-****************************************************************************/
+struct tevent_req *cli_posix_mkdir_send(TALLOC_CTX *mem_ctx,
+ struct event_context *ev,
+ struct cli_state *cli,
+ const char *fname,
+ mode_t mode)
+{
+ return cli_posix_open_internal_send(mem_ctx, ev,
+ cli, fname, O_CREAT, mode, true);
+}
-int cli_posix_mkdir(struct cli_state *cli, const char *fname, mode_t mode)
+NTSTATUS cli_posix_mkdir_recv(struct tevent_req *req)
{
- return (cli_posix_open_internal(cli, fname, O_CREAT, mode, True) == -1) ? -1 : 0;
+ NTSTATUS status;
+
+ if (tevent_req_is_nterror(req, &status)) {
+ return status;
+ }
+ return NT_STATUS_OK;
+}
+
+NTSTATUS cli_posix_mkdir(struct cli_state *cli, const char *fname, mode_t mode)
+{
+ TALLOC_CTX *frame = talloc_stackframe();
+ struct event_context *ev = NULL;
+ struct tevent_req *req = NULL;
+ NTSTATUS status = NT_STATUS_OK;
+
+ if (cli_has_async_calls(cli)) {
+ /*
+ * Can't use sync call while an async call is in flight
+ */
+ status = NT_STATUS_INVALID_PARAMETER;
+ goto fail;
+ }
+
+ ev = event_context_init(frame);
+ if (ev == NULL) {
+ status = NT_STATUS_NO_MEMORY;
+ goto fail;
+ }
+
+ req = cli_posix_mkdir_send(frame,
+ ev,
+ cli,
+ fname,
+ mode);
+ if (req == NULL) {
+ status = NT_STATUS_NO_MEMORY;
+ goto fail;
+ }
+
+ if (!tevent_req_poll(req, ev)) {
+ status = map_nt_error_from_unix(errno);
+ goto fail;
+ }
+
+ status = cli_posix_mkdir_recv(req);
+
+ fail:
+ TALLOC_FREE(frame);
+ if (!NT_STATUS_IS_OK(status)) {
+ cli_set_error(cli, status);
+ }
+ return status;
}
/****************************************************************************
@@ -3489,7 +3650,7 @@ struct tevent_req *cli_posix_unlink_send(TALLOC_CTX *mem_ctx,
return cli_posix_unlink_internal_send(mem_ctx, ev, cli, fname, false);
}
-NTSTATUS cli_posix_unlink_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx)
+NTSTATUS cli_posix_unlink_recv(struct tevent_req *req)
{
NTSTATUS status;
@@ -3538,7 +3699,7 @@ NTSTATUS cli_posix_unlink(struct cli_state *cli, const char *fname)
goto fail;
}
- status = cli_posix_unlink_recv(req, frame);
+ status = cli_posix_unlink_recv(req);
fail:
TALLOC_FREE(frame);