s3:libsmb: add cli_smb2_delete_on_close*()
authorStefan Metzmacher <metze@samba.org>
Tue, 20 Jun 2017 06:35:13 +0000 (08:35 +0200)
committerStefan Metzmacher <metze@samba.org>
Thu, 22 Jun 2017 11:07:40 +0000 (13:07 +0200)
Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Jeremy Allison <jra@samba.org>
source3/libsmb/cli_smb2_fnum.c
source3/libsmb/cli_smb2_fnum.h

index 351fccf..954f3fe 100644 (file)
@@ -485,6 +485,133 @@ NTSTATUS cli_smb2_close_fnum(struct cli_state *cli, uint16_t fnum)
        return status;
 }
 
+struct cli_smb2_delete_on_close_state {
+       struct cli_state *cli;
+       uint16_t fnum;
+       struct smb2_hnd *ph;
+       uint8_t data[1];
+       DATA_BLOB inbuf;
+};
+
+static void cli_smb2_delete_on_close_done(struct tevent_req *subreq);
+
+struct tevent_req *cli_smb2_delete_on_close_send(TALLOC_CTX *mem_ctx,
+                                       struct tevent_context *ev,
+                                       struct cli_state *cli,
+                                       uint16_t fnum,
+                                       bool flag)
+{
+       struct tevent_req *req = NULL;
+       struct cli_smb2_delete_on_close_state *state = NULL;
+       struct tevent_req *subreq = NULL;
+       uint8_t in_info_type;
+       uint8_t in_file_info_class;
+       NTSTATUS status;
+
+       req = tevent_req_create(mem_ctx, &state,
+                               struct cli_smb2_delete_on_close_state);
+       if (req == NULL) {
+               return NULL;
+       }
+       state->cli = cli;
+       state->fnum = fnum;
+
+       if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_SMB2_02) {
+               tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
+               return tevent_req_post(req, ev);
+       }
+
+       status = map_fnum_to_smb2_handle(cli, fnum, &state->ph);
+       if (tevent_req_nterror(req, status)) {
+               return tevent_req_post(req, ev);
+       }
+
+       /*
+        * setinfo on the handle with info_type SMB2_SETINFO_FILE (1),
+        * level 13 (SMB_FILE_DISPOSITION_INFORMATION - 1000).
+        */
+       in_info_type = 1;
+       in_file_info_class = SMB_FILE_DISPOSITION_INFORMATION - 1000;
+       /* Setup data array. */
+       SCVAL(&state->data[0], 0, flag ? 1 : 0);
+       state->inbuf.data = &state->data[0];
+       state->inbuf.length = 1;
+
+       subreq = smb2cli_set_info_send(state, ev,
+                                      cli->conn,
+                                      cli->timeout,
+                                      cli->smb2.session,
+                                      cli->smb2.tcon,
+                                      in_info_type,
+                                      in_file_info_class,
+                                      &state->inbuf, /* in_input_buffer */
+                                      0, /* in_additional_info */
+                                      state->ph->fid_persistent,
+                                      state->ph->fid_volatile);
+       if (tevent_req_nomem(subreq, req)) {
+               return tevent_req_post(req, ev);
+       }
+       tevent_req_set_callback(subreq,
+                               cli_smb2_delete_on_close_done,
+                               req);
+       return req;
+}
+
+static void cli_smb2_delete_on_close_done(struct tevent_req *subreq)
+{
+       NTSTATUS status = smb2cli_set_info_recv(subreq);
+       tevent_req_simple_finish_ntstatus(subreq, status);
+}
+
+NTSTATUS cli_smb2_delete_on_close_recv(struct tevent_req *req)
+{
+       struct cli_smb2_delete_on_close_state *state =
+               tevent_req_data(req,
+               struct cli_smb2_delete_on_close_state);
+       NTSTATUS status;
+
+       if (tevent_req_is_nterror(req, &status)) {
+               state->cli->raw_status = status;
+               tevent_req_received(req);
+               return status;
+       }
+
+       state->cli->raw_status = NT_STATUS_OK;
+       tevent_req_received(req);
+       return NT_STATUS_OK;
+}
+
+NTSTATUS cli_smb2_delete_on_close(struct cli_state *cli, uint16_t fnum, bool flag)
+{
+       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_delete_on_close_send(frame, ev, cli, fnum, flag);
+       if (req == NULL) {
+               goto fail;
+       }
+       if (!tevent_req_poll_ntstatus(req, ev, &status)) {
+               goto fail;
+       }
+       status = cli_smb2_delete_on_close_recv(req);
+ fail:
+       TALLOC_FREE(frame);
+       return status;
+}
+
 /***************************************************************
  Small wrapper that allows SMB2 to create a directory
  Synchronous only.
index 43e0471..190ec59 100644 (file)
@@ -54,6 +54,13 @@ struct tevent_req *cli_smb2_close_fnum_send(TALLOC_CTX *mem_ctx,
                                            uint16_t fnum);
 NTSTATUS cli_smb2_close_fnum_recv(struct tevent_req *req);
 NTSTATUS cli_smb2_close_fnum(struct cli_state *cli, uint16_t fnum);
+struct tevent_req *cli_smb2_delete_on_close_send(TALLOC_CTX *mem_ctx,
+                                       struct tevent_context *ev,
+                                       struct cli_state *cli,
+                                       uint16_t fnum,
+                                       bool flag);
+NTSTATUS cli_smb2_delete_on_close_recv(struct tevent_req *req);
+NTSTATUS cli_smb2_delete_on_close(struct cli_state *cli, uint16_t fnum, bool flag);
 NTSTATUS cli_smb2_mkdir(struct cli_state *cli, const char *dirname);
 NTSTATUS cli_smb2_rmdir(struct cli_state *cli, const char *dirname);
 NTSTATUS cli_smb2_unlink(struct cli_state *cli,const char *fname);