diff options
author | Volker Lendecke <vl@samba.org> | 2018-11-16 13:47:00 +0100 |
---|---|---|
committer | Volker Lendecke <vl@samba.org> | 2018-11-21 16:53:42 +0100 |
commit | d4a8bed85512b6d80e2a256f0343b4f59e3f63ad (patch) | |
tree | 7a4bf64f3f7e2c6108a59752ef351356d252964f /source3 | |
parent | 499d97b38c4477751d2dd38e9882bc7a5c7a8337 (diff) | |
download | samba-d4a8bed85512b6d80e2a256f0343b4f59e3f63ad.tar.gz |
libsmb: Introduce cli_smb2_notify_send/recv
This only existed as a sync wrapper where the underlying function could do
send/recv already.
Signed-off-by: Volker Lendecke <vl@samba.org>
Reviewed-by: Jeremy Allison <jra@samba.org>
Diffstat (limited to 'source3')
-rw-r--r-- | source3/libsmb/cli_smb2_fnum.c | 207 | ||||
-rw-r--r-- | source3/libsmb/cli_smb2_fnum.h | 12 |
2 files changed, 167 insertions, 52 deletions
diff --git a/source3/libsmb/cli_smb2_fnum.c b/source3/libsmb/cli_smb2_fnum.c index 3cf16b325dd..35edec88809 100644 --- a/source3/libsmb/cli_smb2_fnum.c +++ b/source3/libsmb/cli_smb2_fnum.c @@ -4196,52 +4196,95 @@ NTSTATUS cli_smb2_ftruncate(struct cli_state *cli, return status; } -NTSTATUS cli_smb2_notify(struct cli_state *cli, uint16_t fnum, - uint32_t buffer_size, uint32_t completion_filter, - bool recursive, TALLOC_CTX *mem_ctx, - struct notify_change **pchanges, - uint32_t *pnum_changes) +struct cli_smb2_notify_state { + struct tevent_req *subreq; + struct notify_change *changes; + size_t num_changes; +}; + +static void cli_smb2_notify_done(struct tevent_req *subreq); +static bool cli_smb2_notify_cancel(struct tevent_req *req); + +struct tevent_req *cli_smb2_notify_send( + TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct cli_state *cli, + uint16_t fnum, + uint32_t buffer_size, + uint32_t completion_filter, + bool recursive) { - NTSTATUS status; + struct tevent_req *req = NULL; + struct cli_smb2_notify_state *state = NULL; struct smb2_hnd *ph = NULL; - TALLOC_CTX *frame = talloc_stackframe(); - uint8_t *base; - uint32_t len, ofs; - struct notify_change *changes = NULL; - size_t num_changes = 0; + NTSTATUS status; - if (smbXcli_conn_has_async_calls(cli->conn)) { - /* - * Can't use sync call while an async call is in flight - */ - status = NT_STATUS_INVALID_PARAMETER; - goto fail; + req = tevent_req_create(mem_ctx, &state, + struct cli_smb2_notify_state); + if (req == NULL) { + return NULL; } if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_SMB2_02) { - status = NT_STATUS_INVALID_PARAMETER; - goto fail; + tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER); + return tevent_req_post(req, ev); } status = map_fnum_to_smb2_handle(cli, fnum, &ph); - if (!NT_STATUS_IS_OK(status)) { - goto fail; + if (tevent_req_nterror(req, status)) { + return tevent_req_post(req, ev); } - status = smb2cli_notify(cli->conn, cli->timeout, - cli->smb2.session, cli->smb2.tcon, - buffer_size, - ph->fid_persistent, ph->fid_volatile, - completion_filter, recursive, - frame, &base, &len); + state->subreq = smb2cli_notify_send( + state, + ev, + cli->conn, + cli->timeout, + cli->smb2.session, + cli->smb2.tcon, + buffer_size, + ph->fid_persistent, + ph->fid_volatile, + completion_filter, + recursive); + if (tevent_req_nomem(state->subreq, req)) { + return tevent_req_post(req, ev); + } + tevent_req_set_callback(state->subreq, cli_smb2_notify_done, req); + tevent_req_set_cancel_fn(req, cli_smb2_notify_cancel); + return req; +} + +static bool cli_smb2_notify_cancel(struct tevent_req *req) +{ + struct cli_smb2_notify_state *state = tevent_req_data( + req, struct cli_smb2_notify_state); + bool ok; + + ok = tevent_req_cancel(state->subreq); + return ok; +} + +static void cli_smb2_notify_done(struct tevent_req *subreq) +{ + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); + struct cli_smb2_notify_state *state = tevent_req_data( + req, struct cli_smb2_notify_state); + uint8_t *base; + uint32_t len; + uint32_t ofs; + NTSTATUS status; + + status = smb2cli_notify_recv(subreq, state, &base, &len); + TALLOC_FREE(subreq); if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) { - len = 0; - status = NT_STATUS_OK; + tevent_req_done(req); + return; } - - if (!NT_STATUS_IS_OK(status)) { - goto fail; + if (tevent_req_nterror(req, status)) { + return; } ofs = 0; @@ -4254,30 +4297,39 @@ NTSTATUS cli_smb2_notify(struct cli_state *cli, uint16_t fnum, size_t namelen; bool ok; - tmp = talloc_realloc(frame, changes, struct notify_change, - num_changes + 1); - if (tmp == NULL) { - status = NT_STATUS_NO_MEMORY; - goto fail; + tmp = talloc_realloc( + state, + state->changes, + struct notify_change, + state->num_changes + 1); + if (tevent_req_nomem(tmp, req)) { + return; } - changes = tmp; - c = &changes[num_changes]; - num_changes += 1; + state->changes = tmp; + c = &state->changes[state->num_changes]; + state->num_changes += 1; if (smb_buffer_oob(len, ofs, next_ofs) || smb_buffer_oob(len, ofs+12, file_name_length)) { - status = NT_STATUS_INVALID_NETWORK_RESPONSE; - goto fail; + tevent_req_nterror( + req, NT_STATUS_INVALID_NETWORK_RESPONSE); + return; } c->action = IVAL(base, ofs+4); - ok = convert_string_talloc(changes, CH_UTF16LE, CH_UNIX, - base + ofs + 12, file_name_length, - &c->name, &namelen); + ok = convert_string_talloc( + state->changes, + CH_UTF16LE, + CH_UNIX, + base + ofs + 12, + file_name_length, + &c->name, + &namelen); if (!ok) { - status = NT_STATUS_INVALID_NETWORK_RESPONSE; - goto fail; + tevent_req_nterror( + req, NT_STATUS_INVALID_NETWORK_RESPONSE); + return; } if (next_ofs == 0) { @@ -4286,13 +4338,64 @@ NTSTATUS cli_smb2_notify(struct cli_state *cli, uint16_t fnum, ofs += next_ofs; } - *pchanges = talloc_move(mem_ctx, &changes); - *pnum_changes = num_changes; - status = NT_STATUS_OK; + tevent_req_done(req); +} -fail: - cli->raw_status = status; +NTSTATUS cli_smb2_notify_recv(struct tevent_req *req, + TALLOC_CTX *mem_ctx, + struct notify_change **pchanges, + uint32_t *pnum_changes) +{ + struct cli_smb2_notify_state *state = tevent_req_data( + req, struct cli_smb2_notify_state); + NTSTATUS status; + if (tevent_req_is_nterror(req, &status)) { + return status; + } + *pchanges = talloc_move(mem_ctx, &state->changes); + *pnum_changes = state->num_changes; + return NT_STATUS_OK; +} + +NTSTATUS cli_smb2_notify(struct cli_state *cli, uint16_t fnum, + uint32_t buffer_size, uint32_t completion_filter, + bool recursive, TALLOC_CTX *mem_ctx, + struct notify_change **pchanges, + uint32_t *pnum_changes) +{ + TALLOC_CTX *frame = talloc_stackframe(); + struct tevent_context *ev; + struct tevent_req *req; + NTSTATUS status = NT_STATUS_NO_MEMORY; + + if (smbXcli_conn_has_async_calls(cli->conn)) { + /* + * Can't use sync call while an async call is in flight + */ + status = NT_STATUS_INVALID_PARAMETER; + goto fail; + } + ev = samba_tevent_context_init(frame); + if (ev == NULL) { + goto fail; + } + req = cli_smb2_notify_send( + frame, + ev, + cli, + fnum, + buffer_size, + completion_filter, + recursive); + if (req == NULL) { + goto fail; + } + if (!tevent_req_poll_ntstatus(req, ev, &status)) { + goto fail; + } + status = cli_smb2_notify_recv(req, mem_ctx, pchanges, pnum_changes); +fail: TALLOC_FREE(frame); return status; } diff --git a/source3/libsmb/cli_smb2_fnum.h b/source3/libsmb/cli_smb2_fnum.h index 0ceddd0b9ab..4fce5fce1c3 100644 --- a/source3/libsmb/cli_smb2_fnum.h +++ b/source3/libsmb/cli_smb2_fnum.h @@ -237,6 +237,18 @@ NTSTATUS cli_smb2_shadow_copy_data(TALLOC_CTX *mem_ctx, NTSTATUS cli_smb2_ftruncate(struct cli_state *cli, uint16_t fnum, uint64_t newsize); +struct tevent_req *cli_smb2_notify_send( + TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct cli_state *cli, + uint16_t fnum, + uint32_t buffer_size, + uint32_t completion_filter, + bool recursive); +NTSTATUS cli_smb2_notify_recv(struct tevent_req *req, + TALLOC_CTX *mem_ctx, + struct notify_change **pchanges, + uint32_t *pnum_changes); NTSTATUS cli_smb2_notify(struct cli_state *cli, uint16_t fnum, uint32_t buffer_size, uint32_t completion_filter, bool recursive, TALLOC_CTX *mem_ctx, |