s3/libsmb: Use smbXcli_conn_nt_smbs_supported instead of SMB1 specific test
[obnox/samba/samba-obnox.git] / source3 / libsmb / clilist.c
index 280f876ba74f90d2d0ce670b633f14a1bd99adff..41f84db5149142d9b6b1128291e2f9d639cdd3c6 100644 (file)
 */
 
 #include "includes.h"
+#include "libsmb/libsmb.h"
+#include "../lib/util/tevent_ntstatus.h"
 #include "async_smb.h"
+#include "trans2.h"
+#include "../libcli/smb/smbXcli_base.h"
 
 /****************************************************************************
  Calculate a safe next_entry_offset.
@@ -74,16 +78,18 @@ static size_t interpret_long_filename(TALLOC_CTX *ctx,
                                return pdata_end - base;
                        }
                        finfo->ctime_ts = convert_time_t_to_timespec(
-                               make_unix_date2(p+4, cli->serverzone));
+                               make_unix_date2(p+4, smb1cli_conn_server_time_zone(cli->conn)));
                        finfo->atime_ts = convert_time_t_to_timespec(
-                               make_unix_date2(p+8, cli->serverzone));
+                               make_unix_date2(p+8, smb1cli_conn_server_time_zone(cli->conn)));
                        finfo->mtime_ts = convert_time_t_to_timespec(
-                               make_unix_date2(p+12, cli->serverzone));
+                               make_unix_date2(p+12, smb1cli_conn_server_time_zone(cli->conn)));
                        finfo->size = IVAL(p,16);
                        finfo->mode = CVAL(p,24);
                        len = CVAL(p, 26);
                        p += 27;
-                       p += align_string(base_ptr, p, 0);
+                       if (recv_flags2 & FLAGS2_UNICODE_STRINGS) {
+                               p += ucs2_align(base_ptr, p, STR_UNICODE);
+                       }
 
                        /* We can safely use len here (which is required by OS/2)
                         * and the NAS-BASIC server instead of +2 or +1 as the
@@ -123,11 +129,11 @@ static size_t interpret_long_filename(TALLOC_CTX *ctx,
                                return pdata_end - base;
                        }
                        finfo->ctime_ts = convert_time_t_to_timespec(
-                               make_unix_date2(p+4, cli->serverzone));
+                               make_unix_date2(p+4, smb1cli_conn_server_time_zone(cli->conn)));
                        finfo->atime_ts = convert_time_t_to_timespec(
-                               make_unix_date2(p+8, cli->serverzone));
+                               make_unix_date2(p+8, smb1cli_conn_server_time_zone(cli->conn)));
                        finfo->mtime_ts = convert_time_t_to_timespec(
-                               make_unix_date2(p+12, cli->serverzone));
+                               make_unix_date2(p+12, smb1cli_conn_server_time_zone(cli->conn)));
                        finfo->size = IVAL(p,16);
                        finfo->mode = CVAL(p,24);
                        len = CVAL(p, 30);
@@ -186,13 +192,15 @@ static size_t interpret_long_filename(TALLOC_CTX *ctx,
                                return pdata_end - base;
                        }
                        p += 2;
-                       {
-                               /* stupid NT bugs. grr */
-                               int flags = 0;
-                               if (p[1] == 0 && namelen > 1) flags |= STR_UNICODE;
-                               clistr_pull(base_ptr, finfo->short_name, p,
-                                           sizeof(finfo->short_name),
-                                           slen, flags);
+                       ret = clistr_pull_talloc(ctx,
+                                               base_ptr,
+                                               recv_flags2,
+                                               &finfo->short_name,
+                                               p,
+                                               slen,
+                                               STR_UNICODE);
+                       if (ret == (size_t)-1) {
+                               return pdata_end - base;
                        }
                        p += 24; /* short name? */
                        if (p + namelen < p || p + namelen > pdata_end) {
@@ -243,14 +251,14 @@ static bool interpret_short_filename(TALLOC_CTX *ctx,
        finfo->mode = CVAL(p,21);
 
        /* this date is converted to GMT by make_unix_date */
-       finfo->ctime_ts.tv_sec = make_unix_date(p+22, cli->serverzone);
+       finfo->ctime_ts.tv_sec = make_unix_date(p+22, smb1cli_conn_server_time_zone(cli->conn));
        finfo->ctime_ts.tv_nsec = 0;
        finfo->mtime_ts.tv_sec = finfo->atime_ts.tv_sec = finfo->ctime_ts.tv_sec;
        finfo->mtime_ts.tv_nsec = finfo->atime_ts.tv_nsec = 0;
        finfo->size = IVAL(p,26);
        ret = clistr_pull_talloc(ctx,
-                       cli->inbuf,
-                       SVAL(cli->inbuf, smb_flg2),
+                       NULL,
+                       0,
                        &finfo->name,
                        p+30,
                        12,
@@ -260,9 +268,10 @@ static bool interpret_short_filename(TALLOC_CTX *ctx,
        }
 
        if (finfo->name) {
-               strlcpy(finfo->short_name,
-                       finfo->name,
-                       sizeof(finfo->short_name));
+               finfo->short_name = talloc_strdup(ctx, finfo->name);
+               if (finfo->short_name == NULL) {
+                       return false;
+               }
        }
        return true;
 }
@@ -292,6 +301,7 @@ static struct tevent_req *cli_list_old_send(TALLOC_CTX *mem_ctx,
        struct cli_list_old_state *state;
        uint8_t *bytes;
        static const uint16_t zero = 0;
+       uint32_t usable_space;
 
        req = tevent_req_create(mem_ctx, &state, struct cli_list_old_state);
        if (req == NULL) {
@@ -305,7 +315,8 @@ static struct tevent_req *cli_list_old_send(TALLOC_CTX *mem_ctx,
        if (tevent_req_nomem(state->mask, req)) {
                return tevent_req_post(req, ev);
        }
-       state->num_asked = (cli->max_xmit - 100) / DIR_STRUCT_SIZE;
+       usable_space = cli_state_available_size(cli, 100);
+       state->num_asked = usable_space / DIR_STRUCT_SIZE;
 
        SSVAL(state->vwv + 0, 0, state->num_asked);
        SSVAL(state->vwv + 1, 0, state->attribute);
@@ -315,10 +326,10 @@ static struct tevent_req *cli_list_old_send(TALLOC_CTX *mem_ctx,
                return tevent_req_post(req, ev);
        }
        bytes[0] = 4;
-       bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), mask,
+       bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), mask,
                                   strlen(mask)+1, NULL);
 
-       bytes = smb_bytes_push_bytes(bytes, 5, (uint8_t *)&zero, 2);
+       bytes = smb_bytes_push_bytes(bytes, 5, (const uint8_t *)&zero, 2);
        if (tevent_req_nomem(bytes, req)) {
                return tevent_req_post(req, ev);
        }
@@ -384,7 +395,7 @@ static void cli_list_old_done(struct tevent_req *subreq)
 
                dirlist_len = talloc_get_size(state->dirlist);
 
-               tmp = TALLOC_REALLOC_ARRAY(
+               tmp = talloc_realloc(
                        state, state->dirlist, uint8_t,
                        dirlist_len + received * DIR_STRUCT_SIZE);
                if (tevent_req_nomem(tmp, req)) {
@@ -419,7 +430,7 @@ static void cli_list_old_done(struct tevent_req *subreq)
                return;
        }
        bytes[0] = 4;
-       bytes = smb_bytes_push_str(bytes, cli_ucs2(state->cli), "",
+       bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(state->cli->conn), "",
                                   1, NULL);
        bytes = smb_bytes_push_bytes(bytes, 5, state->search_status,
                                     sizeof(state->search_status));
@@ -449,7 +460,7 @@ static NTSTATUS cli_list_old_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
 
        num_received = talloc_array_length(state->dirlist) / DIR_STRUCT_SIZE;
 
-       finfo = TALLOC_ARRAY(mem_ctx, struct file_info, num_received);
+       finfo = talloc_array(mem_ctx, struct file_info, num_received);
        if (finfo == NULL) {
                return NT_STATUS_NO_MEMORY;
        }
@@ -469,24 +480,24 @@ static NTSTATUS cli_list_old_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
 
 NTSTATUS cli_list_old(struct cli_state *cli, const char *mask,
                      uint16 attribute,
-                     void (*fn)(const char *, struct file_info *,
+                     NTSTATUS (*fn)(const char *, struct file_info *,
                                 const char *, void *), void *state)
 {
        TALLOC_CTX *frame = talloc_stackframe();
-       struct event_context *ev;
+       struct tevent_context *ev;
        struct tevent_req *req;
        NTSTATUS status = NT_STATUS_NO_MEMORY;
        struct file_info *finfo;
        size_t i, num_finfo;
 
-       if (cli_has_async_calls(cli)) {
+       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 = event_context_init(frame);
+       ev = samba_tevent_context_init(frame);
        if (ev == NULL) {
                goto fail;
        }
@@ -504,13 +515,13 @@ NTSTATUS cli_list_old(struct cli_state *cli, const char *mask,
        }
        num_finfo = talloc_array_length(finfo);
        for (i=0; i<num_finfo; i++) {
-               fn(cli->dfs_mountpoint, &finfo[i], mask, state);
+               status = fn(cli->dfs_mountpoint, &finfo[i], mask, state);
+               if (!NT_STATUS_IS_OK(status)) {
+                       goto fail;
+               }
        }
  fail:
        TALLOC_FREE(frame);
-       if (!NT_STATUS_IS_OK(status)) {
-               cli_set_error(cli, status);
-       }
        return status;
 }
 
@@ -546,8 +557,7 @@ static struct tevent_req *cli_list_trans_send(TALLOC_CTX *mem_ctx,
 {
        struct tevent_req *req, *subreq;
        struct cli_list_trans_state *state;
-       size_t nlen, param_len;
-       char *p;
+       size_t param_len;
 
        req = tevent_req_create(mem_ctx, &state,
                                struct cli_list_trans_state);
@@ -567,10 +577,9 @@ static struct tevent_req *cli_list_trans_send(TALLOC_CTX *mem_ctx,
 
        state->max_matches = 1366; /* Match W2k */
 
-       state->setup[0] = TRANSACT2_FINDFIRST;
+       SSVAL(&state->setup[0], 0, TRANSACT2_FINDFIRST);
 
-       nlen = 2*(strlen(mask)+1);
-       state->param = TALLOC_ARRAY(state, uint8_t, 12+nlen+2);
+       state->param = talloc_array(state, uint8_t, 12);
        if (tevent_req_nomem(state->param, req)) {
                return tevent_req_post(req, ev);
        }
@@ -579,20 +588,24 @@ static struct tevent_req *cli_list_trans_send(TALLOC_CTX *mem_ctx,
        SSVAL(state->param, 2, state->max_matches);
        SSVAL(state->param, 4,
              FLAG_TRANS2_FIND_REQUIRE_RESUME
-             |FLAG_TRANS2_FIND_CLOSE_IF_END);
+             |FLAG_TRANS2_FIND_CLOSE_IF_END
+             |(cli->backup_intent ? FLAG_TRANS2_FIND_BACKUP_INTENT : 0));
        SSVAL(state->param, 6, state->info_level);
        SIVAL(state->param, 8, 0);
 
-       p = ((char *)state->param)+12;
-       p += clistr_push(state->cli, p, state->mask, nlen,
-                        STR_TERMINATE);
-       param_len = PTR_DIFF(p, state->param);
+       state->param = trans2_bytes_push_str(state->param, smbXcli_conn_use_unicode(cli->conn),
+                                            state->mask, strlen(state->mask)+1,
+                                            NULL);
+       if (tevent_req_nomem(state->param, req)) {
+               return tevent_req_post(req, ev);
+       }
+       param_len = talloc_get_size(state->param);
 
        subreq = cli_trans_send(state, state->ev, state->cli,
                                SMBtrans2, NULL, -1, 0, 0,
                                state->setup, 1, 0,
                                state->param, param_len, 10,
-                               NULL, 0, cli->max_xmit);
+                               NULL, 0, CLI_BUFFER_SIZE);
        if (tevent_req_nomem(subreq, req)) {
                return tevent_req_post(req, ev);
        }
@@ -623,7 +636,7 @@ static void cli_list_trans_done(struct tevent_req *subreq)
        int i;
        DATA_BLOB last_name_raw;
        struct file_info *finfo = NULL;
-       size_t nlen, param_len;
+       size_t param_len;
 
        min_param = (state->first ? 6 : 4);
 
@@ -651,7 +664,7 @@ static void cli_list_trans_done(struct tevent_req *subreq)
 
        old_num_finfo = talloc_array_length(state->finfo);
 
-       tmp = TALLOC_REALLOC_ARRAY(state, state->finfo, struct file_info,
+       tmp = talloc_realloc(state, state->finfo, struct file_info,
                                   old_num_finfo + ff_searchcount);
        if (tevent_req_nomem(tmp, req)) {
                return;
@@ -708,7 +721,7 @@ static void cli_list_trans_done(struct tevent_req *subreq)
        /*
         * Shrink state->finfo to the real length we received
         */
-       tmp = TALLOC_REALLOC_ARRAY(state, state->finfo, struct file_info,
+       tmp = talloc_realloc(state, state->finfo, struct file_info,
                                   old_num_finfo + i);
        if (tevent_req_nomem(tmp, req)) {
                return;
@@ -729,12 +742,9 @@ static void cli_list_trans_done(struct tevent_req *subreq)
                return;
        }
 
-       state->setup[0] = TRANSACT2_FINDNEXT;
+       SSVAL(&state->setup[0], 0, TRANSACT2_FINDNEXT);
 
-       nlen = 2*(strlen(state->mask) + 1);
-
-       param = TALLOC_REALLOC_ARRAY(state, state->param, uint8_t,
-                                    12 + nlen + last_name_raw.length + 2);
+       param = talloc_realloc(state, state->param, uint8_t, 12);
        if (tevent_req_nomem(param, req)) {
                return;
        }
@@ -754,24 +764,33 @@ static void cli_list_trans_done(struct tevent_req *subreq)
         * continue instead. JRA
         */
        SSVAL(param, 10, (FLAG_TRANS2_FIND_REQUIRE_RESUME
-                         |FLAG_TRANS2_FIND_CLOSE_IF_END));
-       p = ((char *)param)+12;
+                         |FLAG_TRANS2_FIND_CLOSE_IF_END
+                         |(state->cli->backup_intent ? FLAG_TRANS2_FIND_BACKUP_INTENT : 0)));
        if (last_name_raw.length) {
-               memcpy(p, last_name_raw.data, last_name_raw.length);
-               p += last_name_raw.length;
+               state->param = trans2_bytes_push_bytes(state->param,
+                                                      last_name_raw.data,
+                                                      last_name_raw.length);
+               if (tevent_req_nomem(state->param, req)) {
+                       return;
+               }
                data_blob_free(&last_name_raw);
        } else {
-               p += clistr_push(state->cli, p, state->mask, nlen,
-                                STR_TERMINATE);
+               state->param = trans2_bytes_push_str(state->param,
+                                                    smbXcli_conn_use_unicode(state->cli->conn),
+                                                    state->mask,
+                                                    strlen(state->mask)+1,
+                                                    NULL);
+               if (tevent_req_nomem(state->param, req)) {
+                       return;
+               }
        }
-
-       param_len = PTR_DIFF(p, param);
+       param_len = talloc_get_size(state->param);
 
        subreq = cli_trans_send(state, state->ev, state->cli,
                                SMBtrans2, NULL, -1, 0, 0,
                                state->setup, 1, 0,
                                state->param, param_len, 10,
-                               NULL, 0, state->cli->max_xmit);
+                               NULL, 0, CLI_BUFFER_SIZE);
        if (tevent_req_nomem(subreq, req)) {
                return;
        }
@@ -795,25 +814,25 @@ static NTSTATUS cli_list_trans_recv(struct tevent_req *req,
 
 NTSTATUS cli_list_trans(struct cli_state *cli, const char *mask,
                        uint16_t attribute, int info_level,
-                       void (*fn)(const char *mnt, struct file_info *finfo,
+                       NTSTATUS (*fn)(const char *mnt, struct file_info *finfo,
                                   const char *mask, void *private_data),
                        void *private_data)
 {
        TALLOC_CTX *frame = talloc_stackframe();
-       struct event_context *ev;
+       struct tevent_context *ev;
        struct tevent_req *req;
        int i, num_finfo;
        struct file_info *finfo = NULL;
        NTSTATUS status = NT_STATUS_NO_MEMORY;
 
-       if (cli_has_async_calls(cli)) {
+       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 = event_context_init(frame);
+       ev = samba_tevent_context_init(frame);
        if (ev == NULL) {
                goto fail;
        }
@@ -830,13 +849,13 @@ NTSTATUS cli_list_trans(struct cli_state *cli, const char *mask,
        }
        num_finfo = talloc_array_length(finfo);
        for (i=0; i<num_finfo; i++) {
-               fn(cli->dfs_mountpoint, &finfo[i], mask, private_data);
+               status = fn(cli->dfs_mountpoint, &finfo[i], mask, private_data);
+               if (!NT_STATUS_IS_OK(status)) {
+                       goto fail;
+               }
        }
  fail:
        TALLOC_FREE(frame);
-       if (!NT_STATUS_IS_OK(status)) {
-               cli_set_error(cli, status);
-       }
        return status;
 }
 
@@ -863,7 +882,7 @@ struct tevent_req *cli_list_send(TALLOC_CTX *mem_ctx,
                return NULL;
        }
 
-       if (cli->protocol <= PROTOCOL_LANMAN1) {
+       if (smbXcli_conn_protocol(cli->conn) <= PROTOCOL_LANMAN1) {
                subreq = cli_list_old_send(state, ev, cli, mask, attribute);
                state->recv_fn = cli_list_old_recv;
        } else {
@@ -911,30 +930,30 @@ NTSTATUS cli_list_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
 }
 
 NTSTATUS cli_list(struct cli_state *cli, const char *mask, uint16 attribute,
-                 void (*fn)(const char *, struct file_info *, const char *,
+                 NTSTATUS (*fn)(const char *, struct file_info *, const char *,
                             void *), void *state)
 {
        TALLOC_CTX *frame = talloc_stackframe();
-       struct event_context *ev;
+       struct tevent_context *ev;
        struct tevent_req *req;
        NTSTATUS status = NT_STATUS_NO_MEMORY;
        struct file_info *finfo;
        size_t i, num_finfo;
        uint16_t info_level;
 
-       if (cli_has_async_calls(cli)) {
+       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 = event_context_init(frame);
+       ev = samba_tevent_context_init(frame);
        if (ev == NULL) {
                goto fail;
        }
 
-       info_level = (cli->capabilities & CAP_NT_SMBS)
+       info_level = smbXcli_conn_nt_smbs_supported(cli->conn)
                ? SMB_FIND_FILE_BOTH_DIRECTORY_INFO : SMB_FIND_INFO_STANDARD;
 
        req = cli_list_send(frame, ev, cli, mask, attribute, info_level);
@@ -952,12 +971,12 @@ NTSTATUS cli_list(struct cli_state *cli, const char *mask, uint16 attribute,
        }
 
        for (i=0; i<num_finfo; i++) {
-               fn(cli->dfs_mountpoint, &finfo[i], mask, state);
+               status = fn(cli->dfs_mountpoint, &finfo[i], mask, state);
+               if (!NT_STATUS_IS_OK(status)) {
+                       goto fail;
+               }
        }
  fail:
        TALLOC_FREE(frame);
-       if (!NT_STATUS_IS_OK(status)) {
-               cli_set_error(cli, status);
-       }
        return status;
 }