libsmb: Add async cli_qfileinfo_basic
authorVolker Lendecke <vl@samba.org>
Thu, 28 May 2020 16:24:17 +0000 (18:24 +0200)
committerJeremy Allison <jra@samba.org>
Thu, 4 Jun 2020 17:11:39 +0000 (17:11 +0000)
Signed-off-by: Volker Lendecke <vl@samba.org>
Reviewed-by: Jeremy Allison <jra@samba.org>
source3/libsmb/clirap.c
source3/libsmb/clirap.h

index 65d3afbcaac852ea2b5a83715db9318cd2b73d24..ad1f4fe618d93a53395efe789f614c4ef9ca4143 100644 (file)
@@ -1298,74 +1298,192 @@ NTSTATUS cli_qfilename(struct cli_state *cli, uint16_t fnum,
        return NT_STATUS_OK;
 }
 
-/****************************************************************************
- Send a qfileinfo call.
-****************************************************************************/
+struct cli_qfileinfo_basic_state {
+       uint32_t attr;
+       off_t size;
+       struct timespec create_time;
+       struct timespec access_time;
+       struct timespec write_time;
+       struct timespec change_time;
+       SMB_INO_T ino;
+};
 
-NTSTATUS cli_qfileinfo_basic(struct cli_state *cli, uint16_t fnum,
-                            uint32_t *pattr, off_t *size,
-                            struct timespec *create_time,
-                            struct timespec *access_time,
-                            struct timespec *write_time,
-                            struct timespec *change_time,
-                            SMB_INO_T *ino)
+static void cli_qfileinfo_basic_done(struct tevent_req *subreq);
+
+struct tevent_req *cli_qfileinfo_basic_send(
+       TALLOC_CTX *mem_ctx,
+       struct tevent_context *ev,
+       struct cli_state *cli,
+       uint16_t fnum)
 {
-       uint8_t *rdata;
-       uint32_t num_rdata;
-       NTSTATUS status;
+       struct tevent_req *req = NULL, *subreq = NULL;
+       struct cli_qfileinfo_basic_state *state = NULL;
 
-       if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
-               return cli_smb2_qfileinfo_basic(cli,
-                                               fnum,
-                                               pattr,
-                                               size,
-                                               create_time,
-                                               access_time,
-                                               write_time,
-                                               change_time,
-                                               ino);
+       req = tevent_req_create(
+               mem_ctx, &state, struct cli_qfileinfo_basic_state);
+       if (req == NULL) {
+               return NULL;
        }
 
        /* if its a win95 server then fail this - win95 totally screws it
           up */
        if (cli->win95) {
-               return NT_STATUS_NOT_SUPPORTED;
+               tevent_req_nterror(req, NT_STATUS_NOT_SUPPORTED);
+               return tevent_req_post(req, ev);
        }
 
-       status = cli_qfileinfo(talloc_tos(), cli, fnum,
-                              SMB_QUERY_FILE_ALL_INFO,
-                              68, CLI_BUFFER_SIZE,
-                              NULL,
-                              &rdata, &num_rdata);
-       if (!NT_STATUS_IS_OK(status)) {
+       subreq = cli_qfileinfo_send(
+               state,
+               ev,
+               cli,
+               fnum,
+               SMB_QUERY_FILE_ALL_INFO, /* level */
+               68,                      /* min_rdata */
+               CLI_BUFFER_SIZE);        /* max_rdata */
+       if (tevent_req_nomem(subreq, req)) {
+               return tevent_req_post(req, ev);
+       }
+       tevent_req_set_callback(subreq, cli_qfileinfo_basic_done, req);
+       return req;
+}
+
+static void cli_qfileinfo_basic_done(struct tevent_req *subreq)
+{
+       struct tevent_req *req = tevent_req_callback_data(
+               subreq, struct tevent_req);
+       struct cli_qfileinfo_basic_state *state = tevent_req_data(
+               req, struct cli_qfileinfo_basic_state);
+       uint8_t *rdata;
+       uint32_t num_rdata;
+       NTSTATUS status;
+
+       status = cli_qfileinfo_recv(
+               subreq, state, NULL, &rdata, &num_rdata);
+       TALLOC_FREE(subreq);
+       if (tevent_req_nterror(req, status)) {
+               return;
+       }
+
+       state->create_time = interpret_long_date((char *)rdata+0);
+       state->access_time = interpret_long_date((char *)rdata+8);
+       state->write_time = interpret_long_date((char *)rdata+16);
+       state->change_time = interpret_long_date((char *)rdata+24);
+       state->attr = PULL_LE_U32(rdata, 32);
+       state->size = PULL_LE_U64(rdata,48);
+       state->ino = PULL_LE_U32(rdata, 64);
+       TALLOC_FREE(rdata);
+
+       tevent_req_done(req);
+}
+
+NTSTATUS cli_qfileinfo_basic_recv(
+       struct tevent_req *req,
+       uint32_t *attr,
+       off_t *size,
+       struct timespec *create_time,
+       struct timespec *access_time,
+       struct timespec *write_time,
+       struct timespec *change_time,
+       SMB_INO_T *ino)
+{
+       struct cli_qfileinfo_basic_state *state = tevent_req_data(
+               req, struct cli_qfileinfo_basic_state);
+       NTSTATUS status;
+
+       if (tevent_req_is_nterror(req, &status)) {
                return status;
        }
 
-       if (create_time) {
-               *create_time = interpret_long_date((char *)rdata+0);
+       if (create_time != NULL) {
+               *create_time = state->create_time;
        }
-       if (access_time) {
-               *access_time = interpret_long_date((char *)rdata+8);
+       if (access_time != NULL) {
+               *access_time = state->access_time;
        }
-       if (write_time) {
-               *write_time = interpret_long_date((char *)rdata+16);
+       if (write_time != NULL) {
+               *write_time = state->write_time;
        }
-       if (change_time) {
-               *change_time = interpret_long_date((char *)rdata+24);
+       if (change_time != NULL) {
+               *change_time = state->change_time;
        }
-       if (pattr) {
-               *pattr = SVAL(rdata, 32);
+       if (attr != NULL) {
+               *attr = state->attr;
        }
-       if (size) {
-                *size = IVAL2_TO_SMB_BIG_UINT(rdata,48);
+       if (size != NULL) {
+                *size = state->size;
        }
        if (ino) {
-               *ino = IVAL(rdata, 64);
+               *ino = state->ino;
        }
 
-       TALLOC_FREE(rdata);
        return NT_STATUS_OK;
 }
+/****************************************************************************
+ Send a qfileinfo call.
+****************************************************************************/
+
+NTSTATUS cli_qfileinfo_basic(
+       struct cli_state *cli,
+       uint16_t fnum,
+       uint32_t *attr,
+       off_t *size,
+       struct timespec *create_time,
+       struct timespec *access_time,
+       struct timespec *write_time,
+       struct timespec *change_time,
+       SMB_INO_T *ino)
+{
+       TALLOC_CTX *frame = NULL;
+       struct tevent_context *ev = NULL;
+       struct tevent_req *req = NULL;
+       NTSTATUS status = NT_STATUS_NO_MEMORY;
+
+       if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
+               return cli_smb2_qfileinfo_basic(cli,
+                                               fnum,
+                                               attr,
+                                               size,
+                                               create_time,
+                                               access_time,
+                                               write_time,
+                                               change_time,
+                                               ino);
+       }
+
+       frame = talloc_stackframe();
+
+       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_qfileinfo_basic_send(frame, ev, cli, fnum);
+       if (req == NULL) {
+               goto fail;
+       }
+       if (!tevent_req_poll_ntstatus(req, ev, &status)) {
+               goto fail;
+       }
+
+       status = cli_qfileinfo_basic_recv(
+               req,
+               attr,
+               size,
+               create_time,
+               access_time,
+               write_time,
+               change_time,
+               ino);
+fail:
+       TALLOC_FREE(frame);
+       return status;
+}
 
 /****************************************************************************
  Send a qpathinfo BASIC_INFO call.
index 73388f2d268cf32c870f97b616743af4162e9b6e..9fd48fa09abbf8ff70ba87c42202b9e7ef3d9d70 100644 (file)
@@ -125,13 +125,30 @@ bool parse_streams_blob(TALLOC_CTX *mem_ctx, const uint8_t *rdata,
                                struct stream_struct **pstreams);
 NTSTATUS cli_qfilename(struct cli_state *cli, uint16_t fnum,
                       TALLOC_CTX *mem_ctx, char **name);
-NTSTATUS cli_qfileinfo_basic(struct cli_state *cli, uint16_t fnum,
-                            uint32_t *pattr, off_t *size,
-                            struct timespec *create_time,
-                            struct timespec *access_time,
-                            struct timespec *write_time,
-                            struct timespec *change_time,
-                            SMB_INO_T *ino);
+struct tevent_req *cli_qfileinfo_basic_send(
+       TALLOC_CTX *mem_ctx,
+       struct tevent_context *ev,
+       struct cli_state *cli,
+       uint16_t fnum);
+NTSTATUS cli_qfileinfo_basic_recv(
+       struct tevent_req *req,
+       uint32_t *attr,
+       off_t *size,
+       struct timespec *create_time,
+       struct timespec *access_time,
+       struct timespec *write_time,
+       struct timespec *change_time,
+       SMB_INO_T *ino);
+NTSTATUS cli_qfileinfo_basic(
+       struct cli_state *cli,
+       uint16_t fnum,
+       uint32_t *attr,
+       off_t *size,
+       struct timespec *create_time,
+       struct timespec *access_time,
+       struct timespec *write_time,
+       struct timespec *change_time,
+       SMB_INO_T *ino);
 struct tevent_req *cli_qpathinfo_basic_send(TALLOC_CTX *mem_ctx,
                                            struct tevent_context *ev,
                                            struct cli_state *cli,