summaryrefslogtreecommitdiff
path: root/source3
diff options
context:
space:
mode:
authorVolker Lendecke <vl@samba.org>2018-11-16 13:47:00 +0100
committerVolker Lendecke <vl@samba.org>2018-11-21 16:53:42 +0100
commitd4a8bed85512b6d80e2a256f0343b4f59e3f63ad (patch)
tree7a4bf64f3f7e2c6108a59752ef351356d252964f /source3
parent499d97b38c4477751d2dd38e9882bc7a5c7a8337 (diff)
downloadsamba-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.c207
-rw-r--r--source3/libsmb/cli_smb2_fnum.h12
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,