The branch, master has been updated via 88d82b44c32 libsmb: Make cli_notify_send cancellable via 4c984f3f50c libsmb: Make cli_notify_send/recv smb2-aware via d4a8bed8551 libsmb: Introduce cli_smb2_notify_send/recv via 499d97b38c4 libcli: Make smb2cli_notify_send cancellable via 9c9ccf23498 libsmb: Make cli_trans_send cancellable via bb843be3bfe libsmb: Make cli_trans a normal subreq function from 24b1aa9da2e logger: use color automatically for a tty
https://git.samba.org/?p=samba.git;a=shortlog;h=master - Log ----------------------------------------------------------------- commit 88d82b44c326cfb3ab1cf1f7288eada2566ab4bc Author: Volker Lendecke <v...@samba.org> Date: Fri Nov 16 21:11:57 2018 +0100 libsmb: Make cli_notify_send cancellable Signed-off-by: Volker Lendecke <v...@samba.org> Reviewed-by: Jeremy Allison <j...@samba.org> Autobuild-User(master): Volker Lendecke <v...@samba.org> Autobuild-Date(master): Wed Nov 21 20:50:13 CET 2018 on sn-devel-144 commit 4c984f3f50c74a9f9fc35583ac00576faab1d0c5 Author: Volker Lendecke <v...@samba.org> Date: Fri Nov 16 13:53:01 2018 +0100 libsmb: Make cli_notify_send/recv smb2-aware smb2-awareness only existed in the sync wrapper Signed-off-by: Volker Lendecke <v...@samba.org> Reviewed-by: Jeremy Allison <j...@samba.org> commit d4a8bed85512b6d80e2a256f0343b4f59e3f63ad Author: Volker Lendecke <v...@samba.org> Date: Fri Nov 16 13:47:00 2018 +0100 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 <v...@samba.org> Reviewed-by: Jeremy Allison <j...@samba.org> commit 499d97b38c4477751d2dd38e9882bc7a5c7a8337 Author: Volker Lendecke <v...@samba.org> Date: Fri Nov 16 19:01:57 2018 +0100 libcli: Make smb2cli_notify_send cancellable Signed-off-by: Volker Lendecke <v...@samba.org> Reviewed-by: Jeremy Allison <j...@samba.org> commit 9c9ccf234989a28e0f3d8f46fa7bce070e44c5a4 Author: Volker Lendecke <v...@samba.org> Date: Fri Nov 16 21:03:45 2018 +0100 libsmb: Make cli_trans_send cancellable Required to cancel SMB1 notify Signed-off-by: Volker Lendecke <v...@samba.org> Reviewed-by: Jeremy Allison <j...@samba.org> commit bb843be3bfe4a9e15f345edb8acb290d63b28781 Author: Volker Lendecke <v...@samba.org> Date: Fri Nov 16 21:01:19 2018 +0100 libsmb: Make cli_trans a normal subreq function A lot of "state" variables, but still I don't think the additional complexity is justified by saving a few lines. Make this a completely regular tevent_req "req/subreq" function. Signed-off-by: Volker Lendecke <v...@samba.org> Reviewed-by: Jeremy Allison <j...@samba.org> ----------------------------------------------------------------------- Summary of changes: libcli/smb/smb2cli_notify.c | 31 ++++-- source3/libsmb/cli_smb2_fnum.c | 207 ++++++++++++++++++++++++++++---------- source3/libsmb/cli_smb2_fnum.h | 12 +++ source3/libsmb/clifile.c | 75 ++++++++++++-- source3/libsmb/clitrans.c | 221 +++++++++++++++++++++++------------------ 5 files changed, 383 insertions(+), 163 deletions(-) Changeset truncated at 500 lines: diff --git a/libcli/smb/smb2cli_notify.c b/libcli/smb/smb2cli_notify.c index 1a2a2793a32..9026a6b1c30 100644 --- a/libcli/smb/smb2cli_notify.c +++ b/libcli/smb/smb2cli_notify.c @@ -32,10 +32,12 @@ struct smb2cli_notify_state { uint32_t data_length; struct tevent_req *subreq; + struct tevent_req *timeout_subreq; }; static void smb2cli_notify_done(struct tevent_req *subreq); static void smb2cli_notify_timedout(struct tevent_req *subreq); +static bool smb2cli_notify_cancel(struct tevent_req *req); struct tevent_req *smb2cli_notify_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, @@ -49,7 +51,7 @@ struct tevent_req *smb2cli_notify_send(TALLOC_CTX *mem_ctx, uint32_t completion_filter, bool recursive) { - struct tevent_req *req, *subreq; + struct tevent_req *req; struct smb2cli_notify_state *state; uint8_t *fixed; uint16_t watch_tree; @@ -83,16 +85,33 @@ struct tevent_req *smb2cli_notify_send(TALLOC_CTX *mem_ctx, } tevent_req_set_callback(state->subreq, smb2cli_notify_done, req); - subreq = tevent_wakeup_send(state, ev, - timeval_current_ofs_msec(timeout_msec)); - if (tevent_req_nomem(subreq, req)) { - return tevent_req_post(req, ev); + if (timeout_msec != 0) { + state->timeout_subreq = tevent_wakeup_send( + state, ev, timeval_current_ofs_msec(timeout_msec)); + if (tevent_req_nomem(state->timeout_subreq, req)) { + return tevent_req_post(req, ev); + } + tevent_req_set_callback( + state->timeout_subreq, smb2cli_notify_timedout, req); } - tevent_req_set_callback(subreq, smb2cli_notify_timedout, req); + + tevent_req_set_cancel_fn(req, smb2cli_notify_cancel); return req; } +static bool smb2cli_notify_cancel(struct tevent_req *req) +{ + struct smb2cli_notify_state *state = tevent_req_data( + req, struct smb2cli_notify_state); + bool ok; + + TALLOC_FREE(state->timeout_subreq); + + ok = tevent_req_cancel(state->subreq); + return ok; +} + static void smb2cli_notify_timedout(struct tevent_req *subreq) { struct tevent_req *req = tevent_req_callback_data( 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, diff --git a/source3/libsmb/clifile.c b/source3/libsmb/clifile.c index 5f6e98ce460..b50926307a5 100644 --- a/source3/libsmb/clifile.c +++ b/source3/libsmb/clifile.c @@ -5491,12 +5491,15 @@ NTSTATUS cli_posix_rmdir(struct cli_state *cli, const char *fname) ****************************************************************************/ struct cli_notify_state { + struct tevent_req *subreq; uint8_t setup[8]; uint32_t num_changes; struct notify_change *changes; }; static void cli_notify_done(struct tevent_req *subreq); +static void cli_notify_done_smb2(struct tevent_req *subreq); +static bool cli_notify_cancel(struct tevent_req *req); struct tevent_req *cli_notify_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, @@ -5504,7 +5507,7 @@ struct tevent_req *cli_notify_send(TALLOC_CTX *mem_ctx, uint32_t buffer_size, uint32_t completion_filter, bool recursive) { - struct tevent_req *req, *subreq; + struct tevent_req *req; struct cli_notify_state *state; unsigned old_timeout; @@ -5513,6 +5516,31 @@ struct tevent_req *cli_notify_send(TALLOC_CTX *mem_ctx, return NULL; } + if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) { + /* + * Notifies should not time out + */ + old_timeout = cli_set_timeout(cli, 0); + + state->subreq = cli_smb2_notify_send( + state, + ev, + cli, + fnum, + buffer_size, + completion_filter, + recursive); + + cli_set_timeout(cli, old_timeout); + + if (tevent_req_nomem(state->subreq, req)) { + return tevent_req_post(req, ev); + } + tevent_req_set_callback( + state->subreq, cli_notify_done_smb2, req); + goto done; + } + SIVAL(state->setup, 0, completion_filter); SSVAL(state->setup, 4, fnum); SSVAL(state->setup, 6, recursive); @@ -5522,7 +5550,7 @@ struct tevent_req *cli_notify_send(TALLOC_CTX *mem_ctx, */ old_timeout = cli_set_timeout(cli, 0); - subreq = cli_trans_send( + state->subreq = cli_trans_send( state, /* mem ctx. */ ev, /* event ctx. */ cli, /* cli_state. */ @@ -5544,13 +5572,25 @@ struct tevent_req *cli_notify_send(TALLOC_CTX *mem_ctx, cli_set_timeout(cli, old_timeout); - if (tevent_req_nomem(subreq, req)) { + if (tevent_req_nomem(state->subreq, req)) { return tevent_req_post(req, ev); } - tevent_req_set_callback(subreq, cli_notify_done, req); + tevent_req_set_callback(state->subreq, cli_notify_done, req); +done: + tevent_req_set_cancel_fn(req, cli_notify_cancel); return req; } +static bool cli_notify_cancel(struct tevent_req *req) +{ + struct cli_notify_state *state = tevent_req_data( + req, struct cli_notify_state); + bool ok; + + ok = tevent_req_cancel(state->subreq); + return ok; +} + static void cli_notify_done(struct tevent_req *subreq) { struct tevent_req *req = tevent_req_callback_data( @@ -5565,6 +5605,7 @@ static void cli_notify_done(struct tevent_req *subreq) status = cli_trans_recv(subreq, talloc_tos(), &flags2, NULL, 0, NULL, ¶ms, 0, &num_params, NULL, 0, NULL); TALLOC_FREE(subreq); + state->subreq = NULL; if (tevent_req_nterror(req, status)) { DEBUG(10, ("cli_trans_recv returned %s\n", nt_errstr(status))); return; @@ -5622,6 +5663,26 @@ static void cli_notify_done(struct tevent_req *subreq) tevent_req_done(req); } +static void cli_notify_done_smb2(struct tevent_req *subreq) +{ + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); + struct cli_notify_state *state = tevent_req_data( + req, struct cli_notify_state); + NTSTATUS status; + + status = cli_smb2_notify_recv( + subreq, + state, + &state->changes, + &state->num_changes); + TALLOC_FREE(subreq); + if (tevent_req_nterror(req, status)) { + return; + } + tevent_req_done(req); +} + NTSTATUS cli_notify_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx, uint32_t *pnum_changes, struct notify_change **pchanges) @@ -5649,12 +5710,6 @@ NTSTATUS cli_notify(struct cli_state *cli, uint16_t fnum, uint32_t buffer_size, struct tevent_req *req; NTSTATUS status = NT_STATUS_NO_MEMORY; - if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) { - return cli_smb2_notify(cli, fnum, buffer_size, - completion_filter, recursive, - mem_ctx, pchanges, pnum_changes); - } - frame = talloc_stackframe(); if (smbXcli_conn_has_async_calls(cli->conn)) { diff --git a/source3/libsmb/clitrans.c b/source3/libsmb/clitrans.c index a96d8bf4769..e5b4c4a4618 100644 --- a/source3/libsmb/clitrans.c +++ b/source3/libsmb/clitrans.c @@ -25,28 +25,18 @@ struct cli_trans_state { struct cli_state *cli; - struct tevent_req *req; -- Samba Shared Repository