LCOV - code coverage report
Current view: top level - source3/libsmb - clifile.c (source / functions) Hit Total Coverage
Test: coverage report for v4-17-test 1498b464 Lines: 1221 3028 40.3 %
Date: 2024-06-13 04:01:37 Functions: 114 230 49.6 %

          Line data    Source code
       1             : /* 
       2             :    Unix SMB/CIFS implementation.
       3             :    client file operations
       4             :    Copyright (C) Andrew Tridgell 1994-1998
       5             :    Copyright (C) Jeremy Allison 2001-2009
       6             : 
       7             :    This program is free software; you can redistribute it and/or modify
       8             :    it under the terms of the GNU General Public License as published by
       9             :    the Free Software Foundation; either version 3 of the License, or
      10             :    (at your option) any later version.
      11             : 
      12             :    This program is distributed in the hope that it will be useful,
      13             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      14             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      15             :    GNU General Public License for more details.
      16             : 
      17             :    You should have received a copy of the GNU General Public License
      18             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      19             : */
      20             : 
      21             : #include "includes.h"
      22             : #include "system/filesys.h"
      23             : #include "libsmb/libsmb.h"
      24             : #include "../lib/util/tevent_ntstatus.h"
      25             : #include "async_smb.h"
      26             : #include "libsmb/clirap.h"
      27             : #include "trans2.h"
      28             : #include "ntioctl.h"
      29             : #include "libcli/security/security.h"
      30             : #include "../libcli/smb/smbXcli_base.h"
      31             : 
      32             : struct cli_setpathinfo_state {
      33             :         uint16_t setup;
      34             :         uint8_t *param;
      35             : };
      36             : 
      37             : static void cli_setpathinfo_done(struct tevent_req *subreq);
      38             : 
      39           4 : struct tevent_req *cli_setpathinfo_send(TALLOC_CTX *mem_ctx,
      40             :                                         struct tevent_context *ev,
      41             :                                         struct cli_state *cli,
      42             :                                         uint16_t level,
      43             :                                         const char *path,
      44             :                                         uint8_t *data,
      45             :                                         size_t data_len)
      46             : {
      47             :         struct tevent_req *req, *subreq;
      48             :         struct cli_setpathinfo_state *state;
      49           4 :         uint16_t additional_flags2 = 0;
      50             : 
      51           4 :         req = tevent_req_create(mem_ctx, &state,
      52             :                                 struct cli_setpathinfo_state);
      53           4 :         if (req == NULL) {
      54           0 :                 return NULL;
      55             :         }
      56             : 
      57             :         /* Setup setup word. */
      58           4 :         SSVAL(&state->setup, 0, TRANSACT2_SETPATHINFO);
      59             : 
      60             :         /* Setup param array. */
      61           4 :         state->param = talloc_zero_array(state, uint8_t, 6);
      62           4 :         if (tevent_req_nomem(state->param, req)) {
      63           0 :                 return tevent_req_post(req, ev);
      64             :         }
      65           4 :         SSVAL(state->param, 0, level);
      66             : 
      67          12 :         state->param = trans2_bytes_push_str(
      68          12 :                 state->param, smbXcli_conn_use_unicode(cli->conn), path, strlen(path)+1, NULL);
      69           4 :         if (tevent_req_nomem(state->param, req)) {
      70           0 :                 return tevent_req_post(req, ev);
      71             :         }
      72             : 
      73           4 :         if (clistr_is_previous_version_path(path, NULL, NULL, NULL) &&
      74           0 :                         !INFO_LEVEL_IS_UNIX(level)) {
      75           0 :                 additional_flags2 = FLAGS2_REPARSE_PATH;
      76             :         }
      77             : 
      78          16 :         subreq = cli_trans_send(
      79             :                 state,                  /* mem ctx. */
      80             :                 ev,                     /* event ctx. */
      81             :                 cli,                    /* cli_state. */
      82             :                 additional_flags2,      /* additional_flags2 */
      83             :                 SMBtrans2,              /* cmd. */
      84             :                 NULL,                   /* pipe name. */
      85             :                 -1,                     /* fid. */
      86             :                 0,                      /* function. */
      87             :                 0,                      /* flags. */
      88           4 :                 &state->setup,           /* setup. */
      89             :                 1,                      /* num setup uint16_t words. */
      90             :                 0,                      /* max returned setup. */
      91           4 :                 state->param,                /* param. */
      92           4 :                 talloc_get_size(state->param),       /* num param. */
      93             :                 2,                      /* max returned param. */
      94             :                 data,                   /* data. */
      95             :                 data_len,               /* num data. */
      96             :                 0);                     /* max returned data. */
      97             : 
      98           4 :         if (tevent_req_nomem(subreq, req)) {
      99           0 :                 return tevent_req_post(req, ev);
     100             :         }
     101           4 :         tevent_req_set_callback(subreq, cli_setpathinfo_done, req);
     102           4 :         return req;
     103             : }
     104             : 
     105           4 : static void cli_setpathinfo_done(struct tevent_req *subreq)
     106             : {
     107           4 :         NTSTATUS status = cli_trans_recv(subreq, NULL, NULL, NULL, 0, NULL,
     108             :                                          NULL, 0, NULL, NULL, 0, NULL);
     109           4 :         tevent_req_simple_finish_ntstatus(subreq, status);
     110           4 : }
     111             : 
     112           4 : NTSTATUS cli_setpathinfo_recv(struct tevent_req *req)
     113             : {
     114           4 :         return tevent_req_simple_recv_ntstatus(req);
     115             : }
     116             : 
     117           4 : NTSTATUS cli_setpathinfo(struct cli_state *cli,
     118             :                          uint16_t level,
     119             :                          const char *path,
     120             :                          uint8_t *data,
     121             :                          size_t data_len)
     122             : {
     123           4 :         TALLOC_CTX *frame = talloc_stackframe();
     124             :         struct tevent_context *ev;
     125             :         struct tevent_req *req;
     126           4 :         NTSTATUS status = NT_STATUS_NO_MEMORY;
     127             : 
     128           4 :         if (smbXcli_conn_has_async_calls(cli->conn)) {
     129             :                 /*
     130             :                  * Can't use sync call while an async call is in flight
     131             :                  */
     132           0 :                 status = NT_STATUS_INVALID_PARAMETER;
     133           0 :                 goto fail;
     134             :         }
     135           4 :         ev = samba_tevent_context_init(frame);
     136           4 :         if (ev == NULL) {
     137           0 :                 goto fail;
     138             :         }
     139           4 :         req = cli_setpathinfo_send(ev, ev, cli, level, path, data, data_len);
     140           4 :         if (req == NULL) {
     141           0 :                 goto fail;
     142             :         }
     143           4 :         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
     144           0 :                 goto fail;
     145             :         }
     146           4 :         status = cli_setpathinfo_recv(req);
     147           4 :  fail:
     148           4 :         TALLOC_FREE(frame);
     149           4 :         return status;
     150             : }
     151             : 
     152             : struct cli_setfileinfo_state {
     153             :         uint16_t setup;
     154             :         uint8_t param[6];
     155             : };
     156             : 
     157             : static void cli_setfileinfo_done(struct tevent_req *subreq);
     158             : 
     159          10 : struct tevent_req *cli_setfileinfo_send(
     160             :         TALLOC_CTX *mem_ctx,
     161             :         struct tevent_context *ev,
     162             :         struct cli_state *cli,
     163             :         uint16_t fnum,
     164             :         uint16_t level,
     165             :         uint8_t *data,
     166             :         size_t data_len)
     167             : {
     168          10 :         struct tevent_req *req = NULL, *subreq = NULL;
     169          10 :         struct cli_setfileinfo_state *state = NULL;
     170             : 
     171          10 :         req = tevent_req_create(mem_ctx, &state, struct cli_setfileinfo_state);
     172          10 :         if (req == NULL) {
     173           0 :                 return NULL;
     174             :         }
     175          10 :         PUSH_LE_U16(&state->setup, 0, TRANSACT2_SETFILEINFO);
     176             : 
     177          10 :         PUSH_LE_U16(state->param, 0, fnum);
     178          10 :         PUSH_LE_U16(state->param, 2, level);
     179             : 
     180          20 :         subreq = cli_trans_send(state,          /* mem ctx. */
     181             :                                 ev,             /* event ctx. */
     182             :                                 cli,            /* cli_state. */
     183             :                                 0,              /* additional_flags2 */
     184             :                                 SMBtrans2,      /* cmd. */
     185             :                                 NULL,           /* pipe name. */
     186             :                                 -1,             /* fid. */
     187             :                                 0,              /* function. */
     188             :                                 0,              /* flags. */
     189          10 :                                 &state->setup,   /* setup. */
     190             :                                 1,              /* num setup uint16_t words. */
     191             :                                 0,              /* max returned setup. */
     192          10 :                                 state->param,        /* param. */
     193             :                                 6,              /* num param. */
     194             :                                 2,              /* max returned param. */
     195             :                                 data,           /* data. */
     196             :                                 data_len,       /* num data. */
     197             :                                 0);             /* max returned data. */
     198             : 
     199          10 :         if (tevent_req_nomem(subreq, req)) {
     200           0 :                 return tevent_req_post(req, ev);
     201             :         }
     202          10 :         tevent_req_set_callback(subreq, cli_setfileinfo_done, req);
     203          10 :         return req;
     204             : }
     205             : 
     206          10 : static void cli_setfileinfo_done(struct tevent_req *subreq)
     207             : {
     208          10 :         NTSTATUS status = cli_trans_recv(
     209             :                 subreq,         /* req */
     210             :                 NULL,           /* mem_ctx */
     211             :                 NULL,           /* recv_flags2 */
     212             :                 NULL,           /* setup */
     213             :                 0,              /* min_setup */
     214             :                 NULL,           /* num_setup */
     215             :                 NULL,           /* param */
     216             :                 0,              /* min_param */
     217             :                 NULL,           /* num_param */
     218             :                 NULL,           /* data */
     219             :                 0,              /* min_data */
     220             :                 NULL);          /* num_data */
     221          10 :         tevent_req_simple_finish_ntstatus(subreq, status);
     222          10 : }
     223             : 
     224          10 : NTSTATUS cli_setfileinfo_recv(struct tevent_req *req)
     225             : {
     226          10 :         return tevent_req_simple_recv_ntstatus(req);
     227             : }
     228             : 
     229             : /****************************************************************************
     230             :  Hard/Symlink a file (UNIX extensions).
     231             :  Creates new name (sym)linked to link_target.
     232             : ****************************************************************************/
     233             : 
     234             : struct cli_posix_link_internal_state {
     235             :         uint8_t *data;
     236             : };
     237             : 
     238             : static void cli_posix_link_internal_done(struct tevent_req *subreq);
     239             : 
     240           0 : static struct tevent_req *cli_posix_link_internal_send(TALLOC_CTX *mem_ctx,
     241             :                                         struct tevent_context *ev,
     242             :                                         struct cli_state *cli,
     243             :                                         uint16_t level,
     244             :                                         const char *link_target,
     245             :                                         const char *newname)
     246             : {
     247           0 :         struct tevent_req *req = NULL, *subreq = NULL;
     248           0 :         struct cli_posix_link_internal_state *state = NULL;
     249             : 
     250           0 :         req = tevent_req_create(mem_ctx, &state,
     251             :                                 struct cli_posix_link_internal_state);
     252           0 :         if (req == NULL) {
     253           0 :                 return NULL;
     254             :         }
     255             : 
     256             :         /* Setup data array. */
     257           0 :         state->data = talloc_array(state, uint8_t, 0);
     258           0 :         if (tevent_req_nomem(state->data, req)) {
     259           0 :                 return tevent_req_post(req, ev);
     260             :         }
     261           0 :         state->data = trans2_bytes_push_str(
     262           0 :                 state->data, smbXcli_conn_use_unicode(cli->conn),
     263           0 :                 link_target, strlen(link_target)+1, NULL);
     264             : 
     265           0 :         subreq = cli_setpathinfo_send(
     266             :                 state, ev, cli, level, newname,
     267           0 :                 state->data, talloc_get_size(state->data));
     268           0 :         if (tevent_req_nomem(subreq, req)) {
     269           0 :                 return tevent_req_post(req, ev);
     270             :         }
     271           0 :         tevent_req_set_callback(subreq, cli_posix_link_internal_done, req);
     272           0 :         return req;
     273             : }
     274             : 
     275           0 : static void cli_posix_link_internal_done(struct tevent_req *subreq)
     276             : {
     277           0 :         NTSTATUS status = cli_setpathinfo_recv(subreq);
     278           0 :         tevent_req_simple_finish_ntstatus(subreq, status);
     279           0 : }
     280             : 
     281           0 : static NTSTATUS cli_posix_link_internal_recv(struct tevent_req *req)
     282             : {
     283           0 :         return tevent_req_simple_recv_ntstatus(req);
     284             : }
     285             : 
     286             : /****************************************************************************
     287             :  Symlink a file (UNIX extensions).
     288             : ****************************************************************************/
     289             : 
     290             : struct cli_posix_symlink_state {
     291             :         uint8_t dummy;
     292             : };
     293             : 
     294             : static void cli_posix_symlink_done(struct tevent_req *subreq);
     295             : 
     296           0 : struct tevent_req *cli_posix_symlink_send(TALLOC_CTX *mem_ctx,
     297             :                                         struct tevent_context *ev,
     298             :                                         struct cli_state *cli,
     299             :                                         const char *link_target,
     300             :                                         const char *newname)
     301             : {
     302           0 :         struct tevent_req *req = NULL, *subreq = NULL;
     303           0 :         struct cli_posix_symlink_state *state = NULL;
     304             : 
     305           0 :         req = tevent_req_create(
     306             :                 mem_ctx, &state, struct cli_posix_symlink_state);
     307           0 :         if (req == NULL) {
     308           0 :                 return NULL;
     309             :         }
     310             : 
     311           0 :         subreq = cli_posix_link_internal_send(
     312             :                 mem_ctx, ev, cli, SMB_SET_FILE_UNIX_LINK, link_target, newname);
     313           0 :         if (tevent_req_nomem(subreq, req)) {
     314           0 :                 return tevent_req_post(req, ev);
     315             :         }
     316           0 :         tevent_req_set_callback(subreq, cli_posix_symlink_done, req);
     317           0 :         return req;
     318             : }
     319             : 
     320           0 : static void cli_posix_symlink_done(struct tevent_req *subreq)
     321             : {
     322           0 :         NTSTATUS status = cli_posix_link_internal_recv(subreq);
     323           0 :         tevent_req_simple_finish_ntstatus(subreq, status);
     324           0 : }
     325             : 
     326           0 : NTSTATUS cli_posix_symlink_recv(struct tevent_req *req)
     327             : {
     328           0 :         return tevent_req_simple_recv_ntstatus(req);
     329             : }
     330             : 
     331           0 : NTSTATUS cli_posix_symlink(struct cli_state *cli,
     332             :                         const char *link_target,
     333             :                         const char *newname)
     334             : {
     335           0 :         TALLOC_CTX *frame = talloc_stackframe();
     336           0 :         struct tevent_context *ev = NULL;
     337           0 :         struct tevent_req *req = NULL;
     338           0 :         NTSTATUS status = NT_STATUS_OK;
     339             : 
     340           0 :         if (smbXcli_conn_has_async_calls(cli->conn)) {
     341             :                 /*
     342             :                  * Can't use sync call while an async call is in flight
     343             :                  */
     344           0 :                 status = NT_STATUS_INVALID_PARAMETER;
     345           0 :                 goto fail;
     346             :         }
     347             : 
     348           0 :         ev = samba_tevent_context_init(frame);
     349           0 :         if (ev == NULL) {
     350           0 :                 status = NT_STATUS_NO_MEMORY;
     351           0 :                 goto fail;
     352             :         }
     353             : 
     354           0 :         req = cli_posix_symlink_send(frame,
     355             :                                 ev,
     356             :                                 cli,
     357             :                                 link_target,
     358             :                                 newname);
     359           0 :         if (req == NULL) {
     360           0 :                 status = NT_STATUS_NO_MEMORY;
     361           0 :                 goto fail;
     362             :         }
     363             : 
     364           0 :         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
     365           0 :                 goto fail;
     366             :         }
     367             : 
     368           0 :         status = cli_posix_symlink_recv(req);
     369             : 
     370           0 :  fail:
     371           0 :         TALLOC_FREE(frame);
     372           0 :         return status;
     373             : }
     374             : 
     375             : /****************************************************************************
     376             :  Read a POSIX symlink.
     377             : ****************************************************************************/
     378             : 
     379             : struct cli_posix_readlink_state {
     380             :         struct cli_state *cli;
     381             :         char *converted;
     382             : };
     383             : 
     384             : static void cli_posix_readlink_done(struct tevent_req *subreq);
     385             : 
     386           0 : struct tevent_req *cli_posix_readlink_send(TALLOC_CTX *mem_ctx,
     387             :                                         struct tevent_context *ev,
     388             :                                         struct cli_state *cli,
     389             :                                         const char *fname)
     390             : {
     391           0 :         struct tevent_req *req = NULL, *subreq = NULL;
     392           0 :         struct cli_posix_readlink_state *state = NULL;
     393             : 
     394           0 :         req = tevent_req_create(
     395             :                 mem_ctx, &state, struct cli_posix_readlink_state);
     396           0 :         if (req == NULL) {
     397           0 :                 return NULL;
     398             :         }
     399           0 :         state->cli = cli;
     400             : 
     401           0 :         subreq = cli_qpathinfo_send(
     402             :                 state,
     403             :                 ev,
     404             :                 cli,
     405             :                 fname,
     406             :                 SMB_QUERY_FILE_UNIX_LINK,
     407             :                 1,
     408             :                 UINT16_MAX);
     409           0 :         if (tevent_req_nomem(subreq, req)) {
     410           0 :                 return tevent_req_post(req, ev);
     411             :         }
     412           0 :         tevent_req_set_callback(subreq, cli_posix_readlink_done, req);
     413           0 :         return req;
     414             : }
     415             : 
     416           0 : static void cli_posix_readlink_done(struct tevent_req *subreq)
     417             : {
     418           0 :         struct tevent_req *req = tevent_req_callback_data(
     419             :                 subreq, struct tevent_req);
     420           0 :         struct cli_posix_readlink_state *state = tevent_req_data(
     421             :                 req, struct cli_posix_readlink_state);
     422             :         NTSTATUS status;
     423           0 :         uint8_t *data = NULL;
     424           0 :         uint32_t num_data = 0;
     425             :         charset_t charset;
     426             :         size_t converted_size;
     427             :         bool ok;
     428             : 
     429           0 :         status = cli_qpathinfo_recv(subreq, state, &data, &num_data);
     430           0 :         TALLOC_FREE(subreq);
     431           0 :         if (tevent_req_nterror(req, status)) {
     432           0 :                 return;
     433             :         }
     434             :         /*
     435             :          * num_data is > 1, we've given 1 as minimum to cli_qpathinfo_send
     436             :          */
     437           0 :         if (data == NULL || data[num_data-1] != '\0') {
     438           0 :                 tevent_req_nterror(req, NT_STATUS_DATA_ERROR);
     439           0 :                 return;
     440             :         }
     441             : 
     442           0 :         charset = smbXcli_conn_use_unicode(state->cli->conn) ?
     443           0 :                 CH_UTF16LE : CH_DOS;
     444             : 
     445             :         /* The returned data is a pushed string, not raw data. */
     446           0 :         ok = convert_string_talloc(
     447             :                 state,
     448             :                 charset,
     449             :                 CH_UNIX,
     450             :                 data,
     451             :                 num_data,
     452           0 :                 &state->converted,
     453             :                 &converted_size);
     454           0 :         if (!ok) {
     455           0 :                 tevent_req_oom(req);
     456           0 :                 return;
     457             :         }
     458           0 :         tevent_req_done(req);
     459             : }
     460             : 
     461           0 : NTSTATUS cli_posix_readlink_recv(
     462             :         struct tevent_req *req, TALLOC_CTX *mem_ctx, char **target)
     463             : {
     464           0 :         struct cli_posix_readlink_state *state = tevent_req_data(
     465             :                 req, struct cli_posix_readlink_state);
     466             :         NTSTATUS status;
     467             : 
     468           0 :         if (tevent_req_is_nterror(req, &status)) {
     469           0 :                 return status;
     470             :         }
     471           0 :         *target = talloc_move(mem_ctx, &state->converted);
     472           0 :         return NT_STATUS_OK;
     473             : }
     474             : 
     475           0 : NTSTATUS cli_posix_readlink(
     476             :         struct cli_state *cli,
     477             :         const char *fname,
     478             :         TALLOC_CTX *mem_ctx,
     479             :         char **target)
     480             : {
     481           0 :         TALLOC_CTX *frame = talloc_stackframe();
     482           0 :         struct tevent_context *ev = NULL;
     483           0 :         struct tevent_req *req = NULL;
     484           0 :         NTSTATUS status = NT_STATUS_OK;
     485             : 
     486           0 :         if (smbXcli_conn_has_async_calls(cli->conn)) {
     487             :                 /*
     488             :                  * Can't use sync call while an async call is in flight
     489             :                  */
     490           0 :                 status = NT_STATUS_INVALID_PARAMETER;
     491           0 :                 goto fail;
     492             :         }
     493             : 
     494           0 :         ev = samba_tevent_context_init(frame);
     495           0 :         if (ev == NULL) {
     496           0 :                 status = NT_STATUS_NO_MEMORY;
     497           0 :                 goto fail;
     498             :         }
     499             : 
     500           0 :         req = cli_posix_readlink_send(frame, ev, cli, fname);
     501           0 :         if (req == NULL) {
     502           0 :                 status = NT_STATUS_NO_MEMORY;
     503           0 :                 goto fail;
     504             :         }
     505             : 
     506           0 :         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
     507           0 :                 goto fail;
     508             :         }
     509             : 
     510           0 :         status = cli_posix_readlink_recv(req, mem_ctx, target);
     511             : 
     512           0 :  fail:
     513           0 :         TALLOC_FREE(frame);
     514           0 :         return status;
     515             : }
     516             : 
     517             : /****************************************************************************
     518             :  Hard link a file (UNIX extensions).
     519             : ****************************************************************************/
     520             : 
     521             : struct cli_posix_hardlink_state {
     522             :         uint8_t dummy;
     523             : };
     524             : 
     525             : static void cli_posix_hardlink_done(struct tevent_req *subreq);
     526             : 
     527           0 : struct tevent_req *cli_posix_hardlink_send(TALLOC_CTX *mem_ctx,
     528             :                                         struct tevent_context *ev,
     529             :                                         struct cli_state *cli,
     530             :                                         const char *oldname,
     531             :                                         const char *newname)
     532             : {
     533           0 :         struct tevent_req *req = NULL, *subreq = NULL;
     534           0 :         struct cli_posix_hardlink_state *state = NULL;
     535             : 
     536           0 :         req = tevent_req_create(
     537             :                 mem_ctx, &state, struct cli_posix_hardlink_state);
     538           0 :         if (req == NULL) {
     539           0 :                 return NULL;
     540             :         }
     541             : 
     542           0 :         subreq = cli_posix_link_internal_send(
     543             :                 state, ev, cli, SMB_SET_FILE_UNIX_HLINK, oldname, newname);
     544           0 :         if (tevent_req_nomem(subreq, req)) {
     545           0 :                 return tevent_req_post(req, ev);
     546             :         }
     547           0 :         tevent_req_set_callback(subreq, cli_posix_hardlink_done, req);
     548           0 :         return req;
     549             : }
     550             : 
     551           0 : static void cli_posix_hardlink_done(struct tevent_req *subreq)
     552             : {
     553           0 :         NTSTATUS status = cli_posix_link_internal_recv(subreq);
     554           0 :         tevent_req_simple_finish_ntstatus(subreq, status);
     555           0 : }
     556             : 
     557           0 : NTSTATUS cli_posix_hardlink_recv(struct tevent_req *req)
     558             : {
     559           0 :         return tevent_req_simple_recv_ntstatus(req);
     560             : }
     561             : 
     562           0 : NTSTATUS cli_posix_hardlink(struct cli_state *cli,
     563             :                         const char *oldname,
     564             :                         const char *newname)
     565             : {
     566           0 :         TALLOC_CTX *frame = talloc_stackframe();
     567           0 :         struct tevent_context *ev = NULL;
     568           0 :         struct tevent_req *req = NULL;
     569           0 :         NTSTATUS status = NT_STATUS_OK;
     570             : 
     571           0 :         if (smbXcli_conn_has_async_calls(cli->conn)) {
     572             :                 /*
     573             :                  * Can't use sync call while an async call is in flight
     574             :                  */
     575           0 :                 status = NT_STATUS_INVALID_PARAMETER;
     576           0 :                 goto fail;
     577             :         }
     578             : 
     579           0 :         ev = samba_tevent_context_init(frame);
     580           0 :         if (ev == NULL) {
     581           0 :                 status = NT_STATUS_NO_MEMORY;
     582           0 :                 goto fail;
     583             :         }
     584             : 
     585           0 :         req = cli_posix_hardlink_send(frame,
     586             :                                 ev,
     587             :                                 cli,
     588             :                                 oldname,
     589             :                                 newname);
     590           0 :         if (req == NULL) {
     591           0 :                 status = NT_STATUS_NO_MEMORY;
     592           0 :                 goto fail;
     593             :         }
     594             : 
     595           0 :         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
     596           0 :                 goto fail;
     597             :         }
     598             : 
     599           0 :         status = cli_posix_hardlink_recv(req);
     600             : 
     601           0 :  fail:
     602           0 :         TALLOC_FREE(frame);
     603           0 :         return status;
     604             : }
     605             : 
     606             : /****************************************************************************
     607             :  Do a POSIX getacl - pathname based ACL get (UNIX extensions).
     608             : ****************************************************************************/
     609             : 
     610             : struct getacl_state {
     611             :         uint32_t num_data;
     612             :         uint8_t *data;
     613             : };
     614             : 
     615             : static void cli_posix_getacl_done(struct tevent_req *subreq);
     616             : 
     617           0 : struct tevent_req *cli_posix_getacl_send(TALLOC_CTX *mem_ctx,
     618             :                                         struct tevent_context *ev,
     619             :                                         struct cli_state *cli,
     620             :                                         const char *fname)
     621             : {
     622           0 :         struct tevent_req *req = NULL, *subreq = NULL;
     623           0 :         struct getacl_state *state = NULL;
     624             : 
     625           0 :         req = tevent_req_create(mem_ctx, &state, struct getacl_state);
     626           0 :         if (req == NULL) {
     627           0 :                 return NULL;
     628             :         }
     629           0 :         subreq = cli_qpathinfo_send(state, ev, cli, fname, SMB_QUERY_POSIX_ACL,
     630             :                                     0, CLI_BUFFER_SIZE);
     631           0 :         if (tevent_req_nomem(subreq, req)) {
     632           0 :                 return tevent_req_post(req, ev);
     633             :         }
     634           0 :         tevent_req_set_callback(subreq, cli_posix_getacl_done, req);
     635           0 :         return req;
     636             : }
     637             : 
     638           0 : static void cli_posix_getacl_done(struct tevent_req *subreq)
     639             : {
     640           0 :         struct tevent_req *req = tevent_req_callback_data(
     641             :                 subreq, struct tevent_req);
     642           0 :         struct getacl_state *state = tevent_req_data(
     643             :                 req, struct getacl_state);
     644             :         NTSTATUS status;
     645             : 
     646           0 :         status = cli_qpathinfo_recv(subreq, state, &state->data,
     647             :                                     &state->num_data);
     648           0 :         TALLOC_FREE(subreq);
     649           0 :         if (tevent_req_nterror(req, status)) {
     650           0 :                 return;
     651             :         }
     652           0 :         tevent_req_done(req);
     653             : }
     654             : 
     655           0 : NTSTATUS cli_posix_getacl_recv(struct tevent_req *req,
     656             :                                 TALLOC_CTX *mem_ctx,
     657             :                                 size_t *prb_size,
     658             :                                 char **retbuf)
     659             : {
     660           0 :         struct getacl_state *state = tevent_req_data(req, struct getacl_state);
     661             :         NTSTATUS status;
     662             : 
     663           0 :         if (tevent_req_is_nterror(req, &status)) {
     664           0 :                 return status;
     665             :         }
     666           0 :         *prb_size = (size_t)state->num_data;
     667           0 :         *retbuf = (char *)talloc_move(mem_ctx, &state->data);
     668           0 :         return NT_STATUS_OK;
     669             : }
     670             : 
     671           0 : NTSTATUS cli_posix_getacl(struct cli_state *cli,
     672             :                         const char *fname,
     673             :                         TALLOC_CTX *mem_ctx,
     674             :                         size_t *prb_size,
     675             :                         char **retbuf)
     676             : {
     677           0 :         TALLOC_CTX *frame = talloc_stackframe();
     678           0 :         struct tevent_context *ev = NULL;
     679           0 :         struct tevent_req *req = NULL;
     680           0 :         NTSTATUS status = NT_STATUS_OK;
     681             : 
     682           0 :         if (smbXcli_conn_has_async_calls(cli->conn)) {
     683             :                 /*
     684             :                  * Can't use sync call while an async call is in flight
     685             :                  */
     686           0 :                 status = NT_STATUS_INVALID_PARAMETER;
     687           0 :                 goto fail;
     688             :         }
     689             : 
     690           0 :         ev = samba_tevent_context_init(frame);
     691           0 :         if (ev == NULL) {
     692           0 :                 status = NT_STATUS_NO_MEMORY;
     693           0 :                 goto fail;
     694             :         }
     695             : 
     696           0 :         req = cli_posix_getacl_send(frame,
     697             :                                 ev,
     698             :                                 cli,
     699             :                                 fname);
     700           0 :         if (req == NULL) {
     701           0 :                 status = NT_STATUS_NO_MEMORY;
     702           0 :                 goto fail;
     703             :         }
     704             : 
     705           0 :         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
     706           0 :                 goto fail;
     707             :         }
     708             : 
     709           0 :         status = cli_posix_getacl_recv(req, mem_ctx, prb_size, retbuf);
     710             : 
     711           0 :  fail:
     712           0 :         TALLOC_FREE(frame);
     713           0 :         return status;
     714             : }
     715             : 
     716             : /****************************************************************************
     717             :  Do a POSIX setacl - pathname based ACL set (UNIX extensions).
     718             : ****************************************************************************/
     719             : 
     720             : struct setacl_state {
     721             :         uint8_t *data;
     722             : };
     723             : 
     724             : static void cli_posix_setacl_done(struct tevent_req *subreq);
     725             : 
     726           0 : struct tevent_req *cli_posix_setacl_send(TALLOC_CTX *mem_ctx,
     727             :                                         struct tevent_context *ev,
     728             :                                         struct cli_state *cli,
     729             :                                         const char *fname,
     730             :                                         const void *data,
     731             :                                         size_t num_data)
     732             : {
     733           0 :         struct tevent_req *req = NULL, *subreq = NULL;
     734           0 :         struct setacl_state *state = NULL;
     735             : 
     736           0 :         req = tevent_req_create(mem_ctx, &state, struct setacl_state);
     737           0 :         if (req == NULL) {
     738           0 :                 return NULL;
     739             :         }
     740           0 :         state->data = talloc_memdup(state, data, num_data);
     741           0 :         if (tevent_req_nomem(state->data, req)) {
     742           0 :                 return tevent_req_post(req, ev);
     743             :         }
     744             : 
     745           0 :         subreq = cli_setpathinfo_send(state,
     746             :                                 ev,
     747             :                                 cli,
     748             :                                 SMB_SET_POSIX_ACL,
     749             :                                 fname,
     750           0 :                                 state->data,
     751             :                                 num_data);
     752           0 :         if (tevent_req_nomem(subreq, req)) {
     753           0 :                 return tevent_req_post(req, ev);
     754             :         }
     755           0 :         tevent_req_set_callback(subreq, cli_posix_setacl_done, req);
     756           0 :         return req;
     757             : }
     758             : 
     759           0 : static void cli_posix_setacl_done(struct tevent_req *subreq)
     760             : {
     761           0 :         NTSTATUS status = cli_setpathinfo_recv(subreq);
     762           0 :         tevent_req_simple_finish_ntstatus(subreq, status);
     763           0 : }
     764             : 
     765           0 : NTSTATUS cli_posix_setacl_recv(struct tevent_req *req)
     766             : {
     767           0 :         return tevent_req_simple_recv_ntstatus(req);
     768             : }
     769             : 
     770           0 : NTSTATUS cli_posix_setacl(struct cli_state *cli,
     771             :                         const char *fname,
     772             :                         const void *acl_buf,
     773             :                         size_t acl_buf_size)
     774             : {
     775           0 :         TALLOC_CTX *frame = talloc_stackframe();
     776           0 :         struct tevent_context *ev = NULL;
     777           0 :         struct tevent_req *req = NULL;
     778           0 :         NTSTATUS status = NT_STATUS_OK;
     779             : 
     780           0 :         if (smbXcli_conn_has_async_calls(cli->conn)) {
     781             :                 /*
     782             :                  * Can't use sync call while an async call is in flight
     783             :                  */
     784           0 :                 status = NT_STATUS_INVALID_PARAMETER;
     785           0 :                 goto fail;
     786             :         }
     787             : 
     788           0 :         ev = samba_tevent_context_init(frame);
     789           0 :         if (ev == NULL) {
     790           0 :                 status = NT_STATUS_NO_MEMORY;
     791           0 :                 goto fail;
     792             :         }
     793             : 
     794           0 :         req = cli_posix_setacl_send(frame,
     795             :                                 ev,
     796             :                                 cli,
     797             :                                 fname,
     798             :                                 acl_buf,
     799             :                                 acl_buf_size);
     800           0 :         if (req == NULL) {
     801           0 :                 status = NT_STATUS_NO_MEMORY;
     802           0 :                 goto fail;
     803             :         }
     804             : 
     805           0 :         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
     806           0 :                 goto fail;
     807             :         }
     808             : 
     809           0 :         status = cli_posix_setacl_recv(req);
     810             : 
     811           0 :  fail:
     812           0 :         TALLOC_FREE(frame);
     813           0 :         return status;
     814             : }
     815             : 
     816             : /****************************************************************************
     817             :  Stat a file (UNIX extensions).
     818             : ****************************************************************************/
     819             : 
     820             : struct stat_state {
     821             :         SMB_STRUCT_STAT *sbuf;
     822             : };
     823             : 
     824             : static void cli_posix_stat_done(struct tevent_req *subreq);
     825             : 
     826           0 : struct tevent_req *cli_posix_stat_send(TALLOC_CTX *mem_ctx,
     827             :                                        struct tevent_context *ev,
     828             :                                        struct cli_state *cli,
     829             :                                        const char *fname,
     830             :                                        SMB_STRUCT_STAT *sbuf)
     831             : {
     832           0 :         struct tevent_req *req = NULL, *subreq = NULL;
     833           0 :         struct stat_state *state = NULL;
     834             : 
     835           0 :         req = tevent_req_create(mem_ctx, &state, struct stat_state);
     836           0 :         if (req == NULL) {
     837           0 :                 return NULL;
     838             :         }
     839           0 :         state->sbuf = sbuf;
     840             : 
     841           0 :         subreq = cli_qpathinfo_send(state, ev, cli, fname,
     842             :                                     SMB_QUERY_FILE_UNIX_BASIC, 100, 100);
     843           0 :         if (tevent_req_nomem(subreq, req)) {
     844           0 :                 return tevent_req_post(req, ev);
     845             :         }
     846           0 :         tevent_req_set_callback(subreq, cli_posix_stat_done, req);
     847           0 :         return req;
     848             : }
     849             : 
     850           0 : static void cli_posix_stat_done(struct tevent_req *subreq)
     851             : {
     852           0 :         struct tevent_req *req = tevent_req_callback_data(
     853             :                                 subreq, struct tevent_req);
     854           0 :         struct stat_state *state = tevent_req_data(req, struct stat_state);
     855           0 :         SMB_STRUCT_STAT *sbuf = state->sbuf;
     856             :         uint8_t *data;
     857           0 :         uint32_t num_data = 0;
     858             :         NTSTATUS status;
     859             : 
     860           0 :         status = cli_qpathinfo_recv(subreq, state, &data, &num_data);
     861           0 :         TALLOC_FREE(subreq);
     862           0 :         if (tevent_req_nterror(req, status)) {
     863           0 :                 return;
     864             :         }
     865             : 
     866           0 :         if (num_data != 100) {
     867             :                 /*
     868             :                  * Paranoia, cli_qpathinfo should have guaranteed
     869             :                  * this, but you never know...
     870             :                  */
     871           0 :                 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
     872           0 :                 return;
     873             :         }
     874             : 
     875           0 :         *sbuf = (SMB_STRUCT_STAT) { 0 };
     876             : 
     877             :         /* total size, in bytes */
     878           0 :         sbuf->st_ex_size = IVAL2_TO_SMB_BIG_UINT(data, 0);
     879             : 
     880             :         /* number of blocks allocated */
     881           0 :         sbuf->st_ex_blocks = IVAL2_TO_SMB_BIG_UINT(data,8);
     882             : #if defined (HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
     883           0 :         sbuf->st_ex_blocks /= STAT_ST_BLOCKSIZE;
     884             : #else
     885             :         /* assume 512 byte blocks */
     886             :         sbuf->st_ex_blocks /= 512;
     887             : #endif
     888             :         /* time of last change */
     889           0 :         sbuf->st_ex_ctime = interpret_long_date((char *)(data + 16));
     890             : 
     891             :         /* time of last access */
     892           0 :         sbuf->st_ex_atime = interpret_long_date((char *)(data + 24));
     893             : 
     894             :         /* time of last modification */
     895           0 :         sbuf->st_ex_mtime = interpret_long_date((char *)(data + 32));
     896             : 
     897           0 :         sbuf->st_ex_uid = (uid_t) IVAL(data, 40); /* user ID of owner */
     898           0 :         sbuf->st_ex_gid = (gid_t) IVAL(data, 48); /* group ID of owner */
     899           0 :         sbuf->st_ex_mode = unix_filetype_from_wire(IVAL(data, 56));
     900             : 
     901             : #if defined(HAVE_MAKEDEV)
     902             :         {
     903           0 :                 uint32_t dev_major = IVAL(data,60);
     904           0 :                 uint32_t dev_minor = IVAL(data,68);
     905           0 :                 sbuf->st_ex_rdev = makedev(dev_major, dev_minor);
     906             :         }
     907             : #endif
     908             :         /* inode */
     909           0 :         sbuf->st_ex_ino = (SMB_INO_T)IVAL2_TO_SMB_BIG_UINT(data, 76);
     910             : 
     911             :         /* protection */
     912           0 :         sbuf->st_ex_mode |= wire_perms_to_unix(IVAL(data, 84));
     913             : 
     914             :         /* number of hard links */
     915           0 :         sbuf->st_ex_nlink = BIG_UINT(data, 92);
     916             : 
     917           0 :         tevent_req_done(req);
     918             : }
     919             : 
     920           0 : NTSTATUS cli_posix_stat_recv(struct tevent_req *req)
     921             : {
     922           0 :         return tevent_req_simple_recv_ntstatus(req);
     923             : }
     924             : 
     925           0 : NTSTATUS cli_posix_stat(struct cli_state *cli,
     926             :                         const char *fname,
     927             :                         SMB_STRUCT_STAT *sbuf)
     928             : {
     929           0 :         TALLOC_CTX *frame = talloc_stackframe();
     930           0 :         struct tevent_context *ev = NULL;
     931           0 :         struct tevent_req *req = NULL;
     932           0 :         NTSTATUS status = NT_STATUS_OK;
     933             : 
     934           0 :         if (smbXcli_conn_has_async_calls(cli->conn)) {
     935             :                 /*
     936             :                  * Can't use sync call while an async call is in flight
     937             :                  */
     938           0 :                 status = NT_STATUS_INVALID_PARAMETER;
     939           0 :                 goto fail;
     940             :         }
     941             : 
     942           0 :         ev = samba_tevent_context_init(frame);
     943           0 :         if (ev == NULL) {
     944           0 :                 status = NT_STATUS_NO_MEMORY;
     945           0 :                 goto fail;
     946             :         }
     947             : 
     948           0 :         req = cli_posix_stat_send(frame, ev, cli, fname, sbuf);
     949           0 :         if (req == NULL) {
     950           0 :                 status = NT_STATUS_NO_MEMORY;
     951           0 :                 goto fail;
     952             :         }
     953             : 
     954           0 :         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
     955           0 :                 goto fail;
     956             :         }
     957             : 
     958           0 :         status = cli_posix_stat_recv(req);
     959             : 
     960           0 :  fail:
     961           0 :         TALLOC_FREE(frame);
     962           0 :         return status;
     963             : }
     964             : 
     965             : /****************************************************************************
     966             :  Chmod or chown a file internal (UNIX extensions).
     967             : ****************************************************************************/
     968             : 
     969             : struct cli_posix_chown_chmod_internal_state {
     970             :         uint8_t data[100];
     971             : };
     972             : 
     973             : static void cli_posix_chown_chmod_internal_done(struct tevent_req *subreq);
     974             : 
     975           0 : static struct tevent_req *cli_posix_chown_chmod_internal_send(TALLOC_CTX *mem_ctx,
     976             :                                         struct tevent_context *ev,
     977             :                                         struct cli_state *cli,
     978             :                                         const char *fname,
     979             :                                         uint32_t mode,
     980             :                                         uint32_t uid,
     981             :                                         uint32_t gid)
     982             : {
     983           0 :         struct tevent_req *req = NULL, *subreq = NULL;
     984           0 :         struct cli_posix_chown_chmod_internal_state *state = NULL;
     985             : 
     986           0 :         req = tevent_req_create(mem_ctx, &state,
     987             :                                 struct cli_posix_chown_chmod_internal_state);
     988           0 :         if (req == NULL) {
     989           0 :                 return NULL;
     990             :         }
     991             : 
     992           0 :         memset(state->data, 0xff, 40); /* Set all sizes/times to no change. */
     993           0 :         memset(&state->data[40], '\0', 60);
     994           0 :         SIVAL(state->data,40,uid);
     995           0 :         SIVAL(state->data,48,gid);
     996           0 :         SIVAL(state->data,84,mode);
     997             : 
     998           0 :         subreq = cli_setpathinfo_send(state, ev, cli, SMB_SET_FILE_UNIX_BASIC,
     999           0 :                                       fname, state->data, sizeof(state->data));
    1000           0 :         if (tevent_req_nomem(subreq, req)) {
    1001           0 :                 return tevent_req_post(req, ev);
    1002             :         }
    1003           0 :         tevent_req_set_callback(subreq, cli_posix_chown_chmod_internal_done,
    1004             :                                 req);
    1005           0 :         return req;
    1006             : }
    1007             : 
    1008           0 : static void cli_posix_chown_chmod_internal_done(struct tevent_req *subreq)
    1009             : {
    1010           0 :         NTSTATUS status = cli_setpathinfo_recv(subreq);
    1011           0 :         tevent_req_simple_finish_ntstatus(subreq, status);
    1012           0 : }
    1013             : 
    1014           0 : static NTSTATUS cli_posix_chown_chmod_internal_recv(struct tevent_req *req)
    1015             : {
    1016           0 :         return tevent_req_simple_recv_ntstatus(req);
    1017             : }
    1018             : 
    1019             : /****************************************************************************
    1020             :  chmod a file (UNIX extensions).
    1021             : ****************************************************************************/
    1022             : 
    1023             : struct cli_posix_chmod_state {
    1024             :         uint8_t dummy;
    1025             : };
    1026             : 
    1027             : static void cli_posix_chmod_done(struct tevent_req *subreq);
    1028             : 
    1029           0 : struct tevent_req *cli_posix_chmod_send(TALLOC_CTX *mem_ctx,
    1030             :                                         struct tevent_context *ev,
    1031             :                                         struct cli_state *cli,
    1032             :                                         const char *fname,
    1033             :                                         mode_t mode)
    1034             : {
    1035           0 :         struct tevent_req *req = NULL, *subreq = NULL;
    1036           0 :         struct cli_posix_chmod_state *state = NULL;
    1037             : 
    1038           0 :         req = tevent_req_create(mem_ctx, &state, struct cli_posix_chmod_state);
    1039           0 :         if (req == NULL) {
    1040           0 :                 return NULL;
    1041             :         }
    1042             : 
    1043           0 :         subreq = cli_posix_chown_chmod_internal_send(
    1044             :                 state,
    1045             :                 ev,
    1046             :                 cli,
    1047             :                 fname,
    1048             :                 unix_perms_to_wire(mode),
    1049             :                 SMB_UID_NO_CHANGE,
    1050             :                 SMB_GID_NO_CHANGE);
    1051           0 :         if (tevent_req_nomem(subreq, req)) {
    1052           0 :                 return tevent_req_post(req, ev);
    1053             :         }
    1054           0 :         tevent_req_set_callback(subreq, cli_posix_chmod_done, req);
    1055           0 :         return req;
    1056             : }
    1057             : 
    1058           0 : static void cli_posix_chmod_done(struct tevent_req *subreq)
    1059             : {
    1060           0 :         NTSTATUS status = cli_posix_chown_chmod_internal_recv(subreq);
    1061           0 :         tevent_req_simple_finish_ntstatus(subreq, status);
    1062           0 : }
    1063             : 
    1064           0 : NTSTATUS cli_posix_chmod_recv(struct tevent_req *req)
    1065             : {
    1066           0 :         return tevent_req_simple_recv_ntstatus(req);
    1067             : }
    1068             : 
    1069           0 : NTSTATUS cli_posix_chmod(struct cli_state *cli, const char *fname, mode_t mode)
    1070             : {
    1071           0 :         TALLOC_CTX *frame = talloc_stackframe();
    1072           0 :         struct tevent_context *ev = NULL;
    1073           0 :         struct tevent_req *req = NULL;
    1074           0 :         NTSTATUS status = NT_STATUS_OK;
    1075             : 
    1076           0 :         if (smbXcli_conn_has_async_calls(cli->conn)) {
    1077             :                 /*
    1078             :                  * Can't use sync call while an async call is in flight
    1079             :                  */
    1080           0 :                 status = NT_STATUS_INVALID_PARAMETER;
    1081           0 :                 goto fail;
    1082             :         }
    1083             : 
    1084           0 :         ev = samba_tevent_context_init(frame);
    1085           0 :         if (ev == NULL) {
    1086           0 :                 status = NT_STATUS_NO_MEMORY;
    1087           0 :                 goto fail;
    1088             :         }
    1089             : 
    1090           0 :         req = cli_posix_chmod_send(frame,
    1091             :                                 ev,
    1092             :                                 cli,
    1093             :                                 fname,
    1094             :                                 mode);
    1095           0 :         if (req == NULL) {
    1096           0 :                 status = NT_STATUS_NO_MEMORY;
    1097           0 :                 goto fail;
    1098             :         }
    1099             : 
    1100           0 :         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
    1101           0 :                 goto fail;
    1102             :         }
    1103             : 
    1104           0 :         status = cli_posix_chmod_recv(req);
    1105             : 
    1106           0 :  fail:
    1107           0 :         TALLOC_FREE(frame);
    1108           0 :         return status;
    1109             : }
    1110             : 
    1111             : /****************************************************************************
    1112             :  chown a file (UNIX extensions).
    1113             : ****************************************************************************/
    1114             : 
    1115             : struct cli_posix_chown_state {
    1116             :         uint8_t dummy;
    1117             : };
    1118             : 
    1119             : static void cli_posix_chown_done(struct tevent_req *subreq);
    1120             : 
    1121           0 : struct tevent_req *cli_posix_chown_send(TALLOC_CTX *mem_ctx,
    1122             :                                         struct tevent_context *ev,
    1123             :                                         struct cli_state *cli,
    1124             :                                         const char *fname,
    1125             :                                         uid_t uid,
    1126             :                                         gid_t gid)
    1127             : {
    1128           0 :         struct tevent_req *req = NULL, *subreq = NULL;
    1129           0 :         struct cli_posix_chown_state *state = NULL;
    1130             : 
    1131           0 :         req = tevent_req_create(
    1132             :                 mem_ctx, &state, struct cli_posix_chown_state);
    1133           0 :         if (req == NULL) {
    1134           0 :                 return NULL;
    1135             :         }
    1136             : 
    1137           0 :         subreq = cli_posix_chown_chmod_internal_send(
    1138             :                 state,
    1139             :                 ev,
    1140             :                 cli,
    1141             :                 fname,
    1142             :                 SMB_MODE_NO_CHANGE,
    1143             :                 (uint32_t)uid,
    1144             :                 (uint32_t)gid);
    1145           0 :         if (tevent_req_nomem(subreq, req)) {
    1146           0 :                 return tevent_req_post(req, ev);
    1147             :         }
    1148           0 :         tevent_req_set_callback(subreq, cli_posix_chown_done, req);
    1149           0 :         return req;
    1150             : }
    1151             : 
    1152           0 : static void cli_posix_chown_done(struct tevent_req *subreq)
    1153             : {
    1154           0 :         NTSTATUS status = cli_posix_chown_chmod_internal_recv(subreq);
    1155           0 :         tevent_req_simple_finish_ntstatus(subreq, status);
    1156           0 : }
    1157             : 
    1158           0 : NTSTATUS cli_posix_chown_recv(struct tevent_req *req)
    1159             : {
    1160           0 :         return tevent_req_simple_recv_ntstatus(req);
    1161             : }
    1162             : 
    1163           0 : NTSTATUS cli_posix_chown(struct cli_state *cli,
    1164             :                         const char *fname,
    1165             :                         uid_t uid,
    1166             :                         gid_t gid)
    1167             : {
    1168           0 :         TALLOC_CTX *frame = talloc_stackframe();
    1169           0 :         struct tevent_context *ev = NULL;
    1170           0 :         struct tevent_req *req = NULL;
    1171           0 :         NTSTATUS status = NT_STATUS_OK;
    1172             : 
    1173           0 :         if (smbXcli_conn_has_async_calls(cli->conn)) {
    1174             :                 /*
    1175             :                  * Can't use sync call while an async call is in flight
    1176             :                  */
    1177           0 :                 status = NT_STATUS_INVALID_PARAMETER;
    1178           0 :                 goto fail;
    1179             :         }
    1180             : 
    1181           0 :         ev = samba_tevent_context_init(frame);
    1182           0 :         if (ev == NULL) {
    1183           0 :                 status = NT_STATUS_NO_MEMORY;
    1184           0 :                 goto fail;
    1185             :         }
    1186             : 
    1187           0 :         req = cli_posix_chown_send(frame,
    1188             :                                 ev,
    1189             :                                 cli,
    1190             :                                 fname,
    1191             :                                 uid,
    1192             :                                 gid);
    1193           0 :         if (req == NULL) {
    1194           0 :                 status = NT_STATUS_NO_MEMORY;
    1195           0 :                 goto fail;
    1196             :         }
    1197             : 
    1198           0 :         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
    1199           0 :                 goto fail;
    1200             :         }
    1201             : 
    1202           0 :         status = cli_posix_chown_recv(req);
    1203             : 
    1204           0 :  fail:
    1205           0 :         TALLOC_FREE(frame);
    1206           0 :         return status;
    1207             : }
    1208             : 
    1209             : /****************************************************************************
    1210             :  Rename a file.
    1211             : ****************************************************************************/
    1212             : 
    1213             : struct cli_smb1_rename_state {
    1214             :         uint8_t *data;
    1215             : };
    1216             : 
    1217             : static void cli_smb1_rename_done(struct tevent_req *subreq);
    1218             : 
    1219           0 : static struct tevent_req *cli_smb1_rename_send(TALLOC_CTX *mem_ctx,
    1220             :                                                struct tevent_context *ev,
    1221             :                                                struct cli_state *cli,
    1222             :                                                const char *fname_src,
    1223             :                                                const char *fname_dst,
    1224             :                                                bool replace)
    1225             : {
    1226             :         NTSTATUS status;
    1227           0 :         struct tevent_req *req = NULL, *subreq = NULL;
    1228           0 :         struct cli_smb1_rename_state *state = NULL;
    1229           0 :         smb_ucs2_t *converted_str = NULL;
    1230           0 :         size_t converted_size_bytes = 0;
    1231             : 
    1232           0 :         req = tevent_req_create(mem_ctx, &state, struct cli_smb1_rename_state);
    1233           0 :         if (req == NULL) {
    1234           0 :                 return NULL;
    1235             :         }
    1236             : 
    1237             :         /*
    1238             :          * Strip a MSDFS path from fname_dst if we were given one.
    1239             :          */
    1240           0 :         status = cli_dfs_target_check(state,
    1241             :                                 cli,
    1242             :                                 fname_src,
    1243             :                                 fname_dst,
    1244             :                                 &fname_dst);
    1245           0 :         if (!NT_STATUS_IS_OK(status)) {
    1246           0 :                 goto fail;
    1247             :         }
    1248             : 
    1249           0 :         if (!push_ucs2_talloc(talloc_tos(), &converted_str, fname_dst,
    1250             :                               &converted_size_bytes)) {
    1251           0 :                 status = NT_STATUS_INVALID_PARAMETER;
    1252           0 :                 goto fail;
    1253             :         }
    1254             : 
    1255             :         /* W2K8 insists the dest name is not null
    1256             :            terminated. Remove the last 2 zero bytes
    1257             :            and reduce the name length. */
    1258             : 
    1259           0 :         if (converted_size_bytes < 2) {
    1260           0 :                 status = NT_STATUS_INVALID_PARAMETER;
    1261           0 :                 goto fail;
    1262             :         }
    1263           0 :         converted_size_bytes -= 2;
    1264             : 
    1265           0 :         state->data =
    1266           0 :             talloc_zero_array(state, uint8_t, 12 + converted_size_bytes);
    1267           0 :         if (state->data == NULL) {
    1268           0 :                 status = NT_STATUS_NO_MEMORY;
    1269           0 :                 goto fail;
    1270             :         }
    1271             : 
    1272           0 :         if (replace) {
    1273           0 :                 SCVAL(state->data, 0, 1);
    1274             :         }
    1275             : 
    1276           0 :         SIVAL(state->data, 8, converted_size_bytes);
    1277           0 :         memcpy(state->data + 12, converted_str, converted_size_bytes);
    1278             : 
    1279           0 :         TALLOC_FREE(converted_str);
    1280             : 
    1281           0 :         subreq = cli_setpathinfo_send(
    1282           0 :             state, ev, cli, SMB_FILE_RENAME_INFORMATION, fname_src, state->data,
    1283           0 :             talloc_get_size(state->data));
    1284           0 :         if (tevent_req_nomem(subreq, req)) {
    1285           0 :                 status = NT_STATUS_NO_MEMORY;
    1286           0 :                 goto fail;
    1287             :         }
    1288           0 :         tevent_req_set_callback(subreq, cli_smb1_rename_done, req);
    1289           0 :         return req;
    1290             : 
    1291           0 : fail:
    1292           0 :         TALLOC_FREE(converted_str);
    1293           0 :         tevent_req_nterror(req, status);
    1294           0 :         return tevent_req_post(req, ev);
    1295             : }
    1296             : 
    1297           0 : static void cli_smb1_rename_done(struct tevent_req *subreq)
    1298             : {
    1299           0 :         NTSTATUS status = cli_setpathinfo_recv(subreq);
    1300           0 :         tevent_req_simple_finish_ntstatus(subreq, status);
    1301           0 : }
    1302             : 
    1303           0 : static NTSTATUS cli_smb1_rename_recv(struct tevent_req *req)
    1304             : {
    1305           0 :         return tevent_req_simple_recv_ntstatus(req);
    1306             : }
    1307             : 
    1308             : static void cli_cifs_rename_done(struct tevent_req *subreq);
    1309             : 
    1310             : struct cli_cifs_rename_state {
    1311             :         uint16_t vwv[1];
    1312             : };
    1313             : 
    1314           5 : static struct tevent_req *cli_cifs_rename_send(TALLOC_CTX *mem_ctx,
    1315             :                                                struct tevent_context *ev,
    1316             :                                                struct cli_state *cli,
    1317             :                                                const char *fname_src,
    1318             :                                                const char *fname_dst,
    1319             :                                                bool replace)
    1320             : {
    1321           5 :         struct tevent_req *req = NULL, *subreq = NULL;
    1322           5 :         struct cli_cifs_rename_state *state = NULL;
    1323           5 :         uint8_t additional_flags = 0;
    1324           5 :         uint16_t additional_flags2 = 0;
    1325           5 :         uint8_t *bytes = NULL;
    1326             :         NTSTATUS status;
    1327             : 
    1328           5 :         req = tevent_req_create(mem_ctx, &state, struct cli_cifs_rename_state);
    1329           5 :         if (req == NULL) {
    1330           0 :                 return NULL;
    1331             :         }
    1332             : 
    1333           5 :         if (replace) {
    1334             :                 /*
    1335             :                  * CIFS doesn't support replace
    1336             :                  */
    1337           0 :                 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
    1338           0 :                 return tevent_req_post(req, ev);
    1339             :         }
    1340             : 
    1341             :         /*
    1342             :          * Strip a MSDFS path from fname_dst if we were given one.
    1343             :          */
    1344           5 :         status = cli_dfs_target_check(state,
    1345             :                                 cli,
    1346             :                                 fname_src,
    1347             :                                 fname_dst,
    1348             :                                 &fname_dst);
    1349           5 :         if (tevent_req_nterror(req, status)) {
    1350           0 :                 return tevent_req_post(req, ev);
    1351             :         }
    1352             : 
    1353           5 :         SSVAL(state->vwv+0, 0, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_DIRECTORY);
    1354             : 
    1355           5 :         bytes = talloc_array(state, uint8_t, 1);
    1356           5 :         if (tevent_req_nomem(bytes, req)) {
    1357           0 :                 return tevent_req_post(req, ev);
    1358             :         }
    1359           5 :         bytes[0] = 4;
    1360           5 :         bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), fname_src,
    1361           5 :                                    strlen(fname_src)+1, NULL);
    1362           5 :         if (tevent_req_nomem(bytes, req)) {
    1363           0 :                 return tevent_req_post(req, ev);
    1364             :         }
    1365             : 
    1366           5 :         if (clistr_is_previous_version_path(fname_src, NULL, NULL, NULL)) {
    1367           0 :                 additional_flags2 = FLAGS2_REPARSE_PATH;
    1368             :         }
    1369             : 
    1370           5 :         bytes = talloc_realloc(state, bytes, uint8_t,
    1371             :                         talloc_get_size(bytes)+1);
    1372           5 :         if (tevent_req_nomem(bytes, req)) {
    1373           0 :                 return tevent_req_post(req, ev);
    1374             :         }
    1375             : 
    1376           5 :         bytes[talloc_get_size(bytes)-1] = 4;
    1377           5 :         bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), fname_dst,
    1378           5 :                                    strlen(fname_dst)+1, NULL);
    1379           5 :         if (tevent_req_nomem(bytes, req)) {
    1380           0 :                 return tevent_req_post(req, ev);
    1381             :         }
    1382             : 
    1383          10 :         subreq = cli_smb_send(state, ev, cli, SMBmv, additional_flags,
    1384             :                         additional_flags2,
    1385          10 :                         1, state->vwv, talloc_get_size(bytes), bytes);
    1386           5 :         if (tevent_req_nomem(subreq, req)) {
    1387           0 :                 return tevent_req_post(req, ev);
    1388             :         }
    1389           5 :         tevent_req_set_callback(subreq, cli_cifs_rename_done, req);
    1390           5 :         return req;
    1391             : }
    1392             : 
    1393           5 : static void cli_cifs_rename_done(struct tevent_req *subreq)
    1394             : {
    1395           5 :         NTSTATUS status = cli_smb_recv(
    1396             :                 subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
    1397           5 :         tevent_req_simple_finish_ntstatus(subreq, status);
    1398           5 : }
    1399             : 
    1400           5 : static NTSTATUS cli_cifs_rename_recv(struct tevent_req *req)
    1401             : {
    1402           5 :         return tevent_req_simple_recv_ntstatus(req);
    1403             : }
    1404             : 
    1405             : struct cli_rename_state {
    1406             :         uint8_t dummy;
    1407             : };
    1408             : 
    1409             : static void cli_rename_done1(struct tevent_req *subreq);
    1410             : static void cli_rename_done_cifs(struct tevent_req *subreq);
    1411             : static void cli_rename_done2(struct tevent_req *subreq);
    1412             : 
    1413          26 : struct tevent_req *cli_rename_send(TALLOC_CTX *mem_ctx,
    1414             :                                    struct tevent_context *ev,
    1415             :                                    struct cli_state *cli,
    1416             :                                    const char *fname_src,
    1417             :                                    const char *fname_dst,
    1418             :                                    bool replace)
    1419             : {
    1420          26 :         struct tevent_req *req = NULL, *subreq = NULL;
    1421          26 :         struct cli_rename_state *state = NULL;
    1422             : 
    1423          26 :         req = tevent_req_create(mem_ctx, &state, struct cli_rename_state);
    1424          26 :         if (req == NULL) {
    1425           0 :                 return NULL;
    1426             :         }
    1427             : 
    1428          26 :         if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
    1429          21 :                 subreq = cli_smb2_rename_send(
    1430             :                         state, ev, cli, fname_src, fname_dst, replace);
    1431          21 :                 if (tevent_req_nomem(subreq, req)) {
    1432           0 :                         return tevent_req_post(req, ev);
    1433             :                 }
    1434          21 :                 tevent_req_set_callback(subreq, cli_rename_done2, req);
    1435          21 :                 return req;
    1436             :         }
    1437             : 
    1438           5 :         if (replace && smbXcli_conn_support_passthrough(cli->conn)) {
    1439           0 :                 subreq = cli_smb1_rename_send(
    1440             :                         state, ev, cli, fname_src, fname_dst, replace);
    1441           0 :                 if (tevent_req_nomem(subreq, req)) {
    1442           0 :                         return tevent_req_post(req, ev);
    1443             :                 }
    1444           0 :                 tevent_req_set_callback(subreq, cli_rename_done1, req);
    1445           0 :                 return req;
    1446             :         }
    1447             : 
    1448           5 :         subreq = cli_cifs_rename_send(
    1449             :                 state, ev, cli, fname_src,fname_dst, replace);
    1450           5 :         if (tevent_req_nomem(subreq, req)) {
    1451           0 :                 return tevent_req_post(req, ev);
    1452             :         }
    1453           5 :         tevent_req_set_callback(subreq, cli_rename_done_cifs, req);
    1454           5 :         return req;
    1455             : }
    1456             : 
    1457           0 : static void cli_rename_done1(struct tevent_req *subreq)
    1458             : {
    1459           0 :         NTSTATUS status = cli_smb1_rename_recv(subreq);
    1460           0 :         tevent_req_simple_finish_ntstatus(subreq, status);
    1461           0 : }
    1462             : 
    1463           5 : static void cli_rename_done_cifs(struct tevent_req *subreq)
    1464             : {
    1465           5 :         NTSTATUS status = cli_cifs_rename_recv(subreq);
    1466           5 :         tevent_req_simple_finish_ntstatus(subreq, status);
    1467           5 : }
    1468             : 
    1469          21 : static void cli_rename_done2(struct tevent_req *subreq)
    1470             : {
    1471          21 :         NTSTATUS status = cli_smb2_rename_recv(subreq);
    1472          21 :         tevent_req_simple_finish_ntstatus(subreq, status);
    1473          21 : }
    1474             : 
    1475          26 : NTSTATUS cli_rename_recv(struct tevent_req *req)
    1476             : {
    1477          26 :         return tevent_req_simple_recv_ntstatus(req);
    1478             : }
    1479             : 
    1480          26 : NTSTATUS cli_rename(struct cli_state *cli,
    1481             :                     const char *fname_src,
    1482             :                     const char *fname_dst,
    1483             :                     bool replace)
    1484             : {
    1485          26 :         TALLOC_CTX *frame = NULL;
    1486             :         struct tevent_context *ev;
    1487             :         struct tevent_req *req;
    1488          26 :         NTSTATUS status = NT_STATUS_OK;
    1489             : 
    1490          26 :         frame = talloc_stackframe();
    1491             : 
    1492          26 :         if (smbXcli_conn_has_async_calls(cli->conn)) {
    1493             :                 /*
    1494             :                  * Can't use sync call while an async call is in flight
    1495             :                  */
    1496           0 :                 status = NT_STATUS_INVALID_PARAMETER;
    1497           0 :                 goto fail;
    1498             :         }
    1499             : 
    1500          26 :         ev = samba_tevent_context_init(frame);
    1501          26 :         if (ev == NULL) {
    1502           0 :                 status = NT_STATUS_NO_MEMORY;
    1503           0 :                 goto fail;
    1504             :         }
    1505             : 
    1506          26 :         req = cli_rename_send(frame, ev, cli, fname_src, fname_dst, replace);
    1507          26 :         if (req == NULL) {
    1508           0 :                 status = NT_STATUS_NO_MEMORY;
    1509           0 :                 goto fail;
    1510             :         }
    1511             : 
    1512          26 :         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
    1513           0 :                 goto fail;
    1514             :         }
    1515             : 
    1516          26 :         status = cli_rename_recv(req);
    1517          26 :         cli->raw_status = status; /* cli_smb2_rename_recv doesn't set this */
    1518             : 
    1519          26 :  fail:
    1520          26 :         TALLOC_FREE(frame);
    1521          26 :         return status;
    1522             : }
    1523             : 
    1524             : /****************************************************************************
    1525             :  NT Rename a file.
    1526             : ****************************************************************************/
    1527             : 
    1528             : static void cli_ntrename_internal_done(struct tevent_req *subreq);
    1529             : 
    1530             : struct cli_ntrename_internal_state {
    1531             :         uint16_t vwv[4];
    1532             : };
    1533             : 
    1534           1 : static struct tevent_req *cli_ntrename_internal_send(TALLOC_CTX *mem_ctx,
    1535             :                                 struct tevent_context *ev,
    1536             :                                 struct cli_state *cli,
    1537             :                                 const char *fname_src,
    1538             :                                 const char *fname_dst,
    1539             :                                 uint16_t rename_flag)
    1540             : {
    1541           1 :         struct tevent_req *req = NULL, *subreq = NULL;
    1542           1 :         struct cli_ntrename_internal_state *state = NULL;
    1543           1 :         uint8_t additional_flags = 0;
    1544           1 :         uint16_t additional_flags2 = 0;
    1545           1 :         uint8_t *bytes = NULL;
    1546             :         NTSTATUS status;
    1547             : 
    1548           1 :         req = tevent_req_create(mem_ctx, &state,
    1549             :                                 struct cli_ntrename_internal_state);
    1550           1 :         if (req == NULL) {
    1551           0 :                 return NULL;
    1552             :         }
    1553             : 
    1554             :         /*
    1555             :          * Strip a MSDFS path from fname_dst if we were given one.
    1556             :          */
    1557           1 :         status = cli_dfs_target_check(state,
    1558             :                                 cli,
    1559             :                                 fname_src,
    1560             :                                 fname_dst,
    1561             :                                 &fname_dst);
    1562           1 :         if (tevent_req_nterror(req, status)) {
    1563           0 :                 return tevent_req_post(req, ev);
    1564             :         }
    1565             : 
    1566           1 :         SSVAL(state->vwv+0, 0 ,FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_DIRECTORY);
    1567           1 :         SSVAL(state->vwv+1, 0, rename_flag);
    1568             : 
    1569           1 :         bytes = talloc_array(state, uint8_t, 1);
    1570           1 :         if (tevent_req_nomem(bytes, req)) {
    1571           0 :                 return tevent_req_post(req, ev);
    1572             :         }
    1573           1 :         bytes[0] = 4;
    1574           1 :         bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), fname_src,
    1575           1 :                                    strlen(fname_src)+1, NULL);
    1576           1 :         if (tevent_req_nomem(bytes, req)) {
    1577           0 :                 return tevent_req_post(req, ev);
    1578             :         }
    1579             : 
    1580           1 :         if (clistr_is_previous_version_path(fname_src, NULL, NULL, NULL)) {
    1581           0 :                 additional_flags2 = FLAGS2_REPARSE_PATH;
    1582             :         }
    1583             : 
    1584           1 :         bytes = talloc_realloc(state, bytes, uint8_t,
    1585             :                         talloc_get_size(bytes)+1);
    1586           1 :         if (tevent_req_nomem(bytes, req)) {
    1587           0 :                 return tevent_req_post(req, ev);
    1588             :         }
    1589             : 
    1590           1 :         bytes[talloc_get_size(bytes)-1] = 4;
    1591           1 :         bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), fname_dst,
    1592           1 :                                    strlen(fname_dst)+1, NULL);
    1593           1 :         if (tevent_req_nomem(bytes, req)) {
    1594           0 :                 return tevent_req_post(req, ev);
    1595             :         }
    1596             : 
    1597           2 :         subreq = cli_smb_send(state, ev, cli, SMBntrename, additional_flags,
    1598             :                         additional_flags2,
    1599           2 :                         4, state->vwv, talloc_get_size(bytes), bytes);
    1600           1 :         if (tevent_req_nomem(subreq, req)) {
    1601           0 :                 return tevent_req_post(req, ev);
    1602             :         }
    1603           1 :         tevent_req_set_callback(subreq, cli_ntrename_internal_done, req);
    1604           1 :         return req;
    1605             : }
    1606             : 
    1607           1 : static void cli_ntrename_internal_done(struct tevent_req *subreq)
    1608             : {
    1609           1 :         NTSTATUS status = cli_smb_recv(
    1610             :                 subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
    1611           1 :         tevent_req_simple_finish_ntstatus(subreq, status);
    1612           1 : }
    1613             : 
    1614           1 : static NTSTATUS cli_ntrename_internal_recv(struct tevent_req *req)
    1615             : {
    1616           1 :         return tevent_req_simple_recv_ntstatus(req);
    1617             : }
    1618             : 
    1619           0 : struct tevent_req *cli_ntrename_send(TALLOC_CTX *mem_ctx,
    1620             :                                 struct tevent_context *ev,
    1621             :                                 struct cli_state *cli,
    1622             :                                 const char *fname_src,
    1623             :                                 const char *fname_dst)
    1624             : {
    1625           0 :         return cli_ntrename_internal_send(mem_ctx,
    1626             :                                           ev,
    1627             :                                           cli,
    1628             :                                           fname_src,
    1629             :                                           fname_dst,
    1630             :                                           RENAME_FLAG_RENAME);
    1631             : }
    1632             : 
    1633           0 : NTSTATUS cli_ntrename_recv(struct tevent_req *req)
    1634             : {
    1635           0 :         return cli_ntrename_internal_recv(req);
    1636             : }
    1637             : 
    1638           0 : NTSTATUS cli_ntrename(struct cli_state *cli, const char *fname_src, const char *fname_dst)
    1639             : {
    1640           0 :         TALLOC_CTX *frame = talloc_stackframe();
    1641             :         struct tevent_context *ev;
    1642             :         struct tevent_req *req;
    1643           0 :         NTSTATUS status = NT_STATUS_OK;
    1644             : 
    1645           0 :         if (smbXcli_conn_has_async_calls(cli->conn)) {
    1646             :                 /*
    1647             :                  * Can't use sync call while an async call is in flight
    1648             :                  */
    1649           0 :                 status = NT_STATUS_INVALID_PARAMETER;
    1650           0 :                 goto fail;
    1651             :         }
    1652             : 
    1653           0 :         ev = samba_tevent_context_init(frame);
    1654           0 :         if (ev == NULL) {
    1655           0 :                 status = NT_STATUS_NO_MEMORY;
    1656           0 :                 goto fail;
    1657             :         }
    1658             : 
    1659           0 :         req = cli_ntrename_send(frame, ev, cli, fname_src, fname_dst);
    1660           0 :         if (req == NULL) {
    1661           0 :                 status = NT_STATUS_NO_MEMORY;
    1662           0 :                 goto fail;
    1663             :         }
    1664             : 
    1665           0 :         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
    1666           0 :                 goto fail;
    1667             :         }
    1668             : 
    1669           0 :         status = cli_ntrename_recv(req);
    1670             : 
    1671           0 :  fail:
    1672           0 :         TALLOC_FREE(frame);
    1673           0 :         return status;
    1674             : }
    1675             : 
    1676             : /****************************************************************************
    1677             :  NT hardlink a file.
    1678             : ****************************************************************************/
    1679             : 
    1680           1 : static struct tevent_req *cli_nt_hardlink_send(TALLOC_CTX *mem_ctx,
    1681             :                                 struct tevent_context *ev,
    1682             :                                 struct cli_state *cli,
    1683             :                                 const char *fname_src,
    1684             :                                 const char *fname_dst)
    1685             : {
    1686           1 :         return cli_ntrename_internal_send(mem_ctx,
    1687             :                                           ev,
    1688             :                                           cli,
    1689             :                                           fname_src,
    1690             :                                           fname_dst,
    1691             :                                           RENAME_FLAG_HARD_LINK);
    1692             : }
    1693             : 
    1694           1 : static NTSTATUS cli_nt_hardlink_recv(struct tevent_req *req)
    1695             : {
    1696           1 :         return cli_ntrename_internal_recv(req);
    1697             : }
    1698             : 
    1699             : struct cli_smb2_hardlink_state {
    1700             :         struct tevent_context *ev;
    1701             :         struct cli_state *cli;
    1702             :         uint16_t fnum_src;
    1703             :         const char *fname_dst;
    1704             :         bool overwrite;
    1705             :         NTSTATUS status;
    1706             : };
    1707             : 
    1708             : static void cli_smb2_hardlink_opened(struct tevent_req *subreq);
    1709             : static void cli_smb2_hardlink_info_set(struct tevent_req *subreq);
    1710             : static void cli_smb2_hardlink_closed(struct tevent_req *subreq);
    1711             : 
    1712           4 : static struct tevent_req *cli_smb2_hardlink_send(
    1713             :         TALLOC_CTX *mem_ctx,
    1714             :         struct tevent_context *ev,
    1715             :         struct cli_state *cli,
    1716             :         const char *fname_src,
    1717             :         const char *fname_dst,
    1718             :         bool overwrite,
    1719             :         struct smb2_create_blobs *in_cblobs)
    1720             : {
    1721           4 :         struct tevent_req *req = NULL, *subreq = NULL;
    1722           4 :         struct cli_smb2_hardlink_state *state = NULL;
    1723             :         NTSTATUS status;
    1724             : 
    1725           4 :         req = tevent_req_create(
    1726             :                 mem_ctx, &state, struct cli_smb2_hardlink_state);
    1727           4 :         if (req == NULL) {
    1728           0 :                 return NULL;
    1729             :         }
    1730             : 
    1731             :         /*
    1732             :          * Strip a MSDFS path from fname_dst if we were given one.
    1733             :          */
    1734           4 :         status = cli_dfs_target_check(state,
    1735             :                                 cli,
    1736             :                                 fname_src,
    1737             :                                 fname_dst,
    1738             :                                 &fname_dst);
    1739           4 :         if (tevent_req_nterror(req, status)) {
    1740           0 :                 return tevent_req_post(req, ev);
    1741             :         }
    1742             : 
    1743           4 :         state->ev = ev;
    1744           4 :         state->cli = cli;
    1745           4 :         state->fname_dst = fname_dst;
    1746           4 :         state->overwrite = overwrite;
    1747             : 
    1748           4 :         subreq = cli_smb2_create_fnum_send(
    1749             :                 state,
    1750             :                 ev,
    1751             :                 cli,
    1752             :                 fname_src,
    1753             :                 0,                      /* create_flags */
    1754             :                 SMB2_IMPERSONATION_IMPERSONATION,
    1755             :                 FILE_WRITE_ATTRIBUTES,
    1756             :                 0,                      /* file attributes */
    1757             :                 FILE_SHARE_READ|
    1758             :                 FILE_SHARE_WRITE|
    1759             :                 FILE_SHARE_DELETE,       /* share_access */
    1760             :                 FILE_OPEN,               /* create_disposition */
    1761             :                 FILE_NON_DIRECTORY_FILE, /* no hardlinks on directories */
    1762             :                 in_cblobs);
    1763           4 :         if (tevent_req_nomem(subreq, req)) {
    1764           0 :                 return tevent_req_post(req, ev);
    1765             :         }
    1766           4 :         tevent_req_set_callback(subreq, cli_smb2_hardlink_opened, req);
    1767           4 :         return req;
    1768             : }
    1769             : 
    1770           4 : static void cli_smb2_hardlink_opened(struct tevent_req *subreq)
    1771             : {
    1772           4 :         struct tevent_req *req = tevent_req_callback_data(
    1773             :                 subreq, struct tevent_req);
    1774           4 :         struct cli_smb2_hardlink_state *state = tevent_req_data(
    1775             :                 req, struct cli_smb2_hardlink_state);
    1776             :         NTSTATUS status;
    1777             :         smb_ucs2_t *ucs2_dst;
    1778             :         size_t ucs2_len;
    1779             :         DATA_BLOB inbuf;
    1780             :         bool ok;
    1781             : 
    1782           4 :         status = cli_smb2_create_fnum_recv(
    1783             :                 subreq, &state->fnum_src, NULL, NULL, NULL);
    1784           4 :         TALLOC_FREE(subreq);
    1785           4 :         if (tevent_req_nterror(req, status)) {
    1786           0 :                 return;
    1787             :         }
    1788             : 
    1789           4 :         ok = push_ucs2_talloc(state, &ucs2_dst, state->fname_dst, &ucs2_len);
    1790           4 :         if (!ok || (ucs2_len < 2)) {
    1791           0 :                 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
    1792           0 :                 return;
    1793             :         }
    1794             :         /* Don't 0-terminate the name */
    1795           4 :         ucs2_len -= 2;
    1796             : 
    1797           4 :         inbuf = data_blob_talloc_zero(state, ucs2_len + 20);
    1798           4 :         if (tevent_req_nomem(inbuf.data, req)) {
    1799           0 :                 return;
    1800             :         }
    1801             : 
    1802           4 :         if (state->overwrite) {
    1803           0 :                 SCVAL(inbuf.data, 0, 1);
    1804             :         }
    1805           4 :         SIVAL(inbuf.data, 16, ucs2_len);
    1806           4 :         memcpy(inbuf.data + 20, ucs2_dst, ucs2_len);
    1807           4 :         TALLOC_FREE(ucs2_dst);
    1808             : 
    1809           4 :         subreq = cli_smb2_set_info_fnum_send(
    1810             :                 state,
    1811             :                 state->ev,
    1812             :                 state->cli,
    1813           4 :                 state->fnum_src,
    1814             :                 1,              /* in_info_type */
    1815             :                 SMB_FILE_LINK_INFORMATION - 1000, /* in_file_info_class */
    1816             :                 &inbuf,
    1817             :                 0);             /* in_additional_info */
    1818           4 :         if (tevent_req_nomem(subreq, req)) {
    1819           0 :                 return;
    1820             :         }
    1821           4 :         tevent_req_set_callback(subreq, cli_smb2_hardlink_info_set, req);
    1822             : }
    1823             : 
    1824           4 : static void cli_smb2_hardlink_info_set(struct tevent_req *subreq)
    1825             : {
    1826           4 :         struct tevent_req *req = tevent_req_callback_data(
    1827             :                 subreq, struct tevent_req);
    1828           4 :         struct cli_smb2_hardlink_state *state = tevent_req_data(
    1829             :                 req, struct cli_smb2_hardlink_state);
    1830             : 
    1831           4 :         state->status = cli_smb2_set_info_fnum_recv(subreq);
    1832           4 :         TALLOC_FREE(subreq);
    1833             : 
    1834             :         /* ignore error here, we need to close the file */
    1835             : 
    1836           4 :         subreq = cli_smb2_close_fnum_send(
    1837           4 :                 state, state->ev, state->cli, state->fnum_src);
    1838           4 :         if (tevent_req_nomem(subreq, req)) {
    1839           0 :                 return;
    1840             :         }
    1841           4 :         tevent_req_set_callback(subreq, cli_smb2_hardlink_closed, req);
    1842             : }
    1843             : 
    1844           4 : static void cli_smb2_hardlink_closed(struct tevent_req *subreq)
    1845             : {
    1846           4 :         NTSTATUS status = cli_smb2_close_fnum_recv(subreq);
    1847           4 :         tevent_req_simple_finish_ntstatus(subreq, status);
    1848           4 : }
    1849             : 
    1850           4 : static NTSTATUS cli_smb2_hardlink_recv(struct tevent_req *req)
    1851             : {
    1852           4 :         struct cli_smb2_hardlink_state *state = tevent_req_data(
    1853             :                 req, struct cli_smb2_hardlink_state);
    1854             :         NTSTATUS status;
    1855             : 
    1856           4 :         if (tevent_req_is_nterror(req, &status)) {
    1857           0 :                 return status;
    1858             :         }
    1859           4 :         return state->status;
    1860             : }
    1861             : 
    1862             : struct cli_hardlink_state {
    1863             :         uint8_t dummy;
    1864             : };
    1865             : 
    1866             : static void cli_hardlink_done(struct tevent_req *subreq);
    1867             : static void cli_hardlink_done2(struct tevent_req *subreq);
    1868             : 
    1869           5 : struct tevent_req *cli_hardlink_send(
    1870             :         TALLOC_CTX *mem_ctx,
    1871             :         struct tevent_context *ev,
    1872             :         struct cli_state *cli,
    1873             :         const char *fname_src,
    1874             :         const char *fname_dst)
    1875             : {
    1876           5 :         struct tevent_req *req = NULL, *subreq = NULL;
    1877             :         struct cli_hardlink_state *state;
    1878             : 
    1879           5 :         req = tevent_req_create(mem_ctx, &state, struct cli_hardlink_state);
    1880           5 :         if (req == NULL) {
    1881           0 :                 return NULL;
    1882             :         }
    1883             : 
    1884           5 :         if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
    1885           4 :                 subreq = cli_smb2_hardlink_send(
    1886             :                         state, ev, cli, fname_src, fname_dst, false, NULL);
    1887           4 :                 if (tevent_req_nomem(subreq, req)) {
    1888           0 :                         return tevent_req_post(req, ev);
    1889             :                 }
    1890           4 :                 tevent_req_set_callback(subreq, cli_hardlink_done2, req);
    1891           4 :                 return req;
    1892             :         }
    1893             : 
    1894           1 :         subreq = cli_nt_hardlink_send(state, ev, cli, fname_src, fname_dst);
    1895           1 :         if (tevent_req_nomem(subreq, req)) {
    1896           0 :                 return tevent_req_post(req, ev);
    1897             :         }
    1898           1 :         tevent_req_set_callback(subreq, cli_hardlink_done, req);
    1899           1 :         return req;
    1900             : }
    1901             : 
    1902           1 : static void cli_hardlink_done(struct tevent_req *subreq)
    1903             : {
    1904           1 :         NTSTATUS status = cli_nt_hardlink_recv(subreq);
    1905           1 :         tevent_req_simple_finish_ntstatus(subreq, status);
    1906           1 : }
    1907             : 
    1908           4 : static void cli_hardlink_done2(struct tevent_req *subreq)
    1909             : {
    1910           4 :         NTSTATUS status = cli_smb2_hardlink_recv(subreq);
    1911           4 :         tevent_req_simple_finish_ntstatus(subreq, status);
    1912           4 : }
    1913             : 
    1914           5 : NTSTATUS cli_hardlink_recv(struct tevent_req *req)
    1915             : {
    1916           5 :         return tevent_req_simple_recv_ntstatus(req);
    1917             : }
    1918             : 
    1919           5 : NTSTATUS cli_hardlink(
    1920             :         struct cli_state *cli, const char *fname_src, const char *fname_dst)
    1921             : {
    1922           5 :         TALLOC_CTX *frame = talloc_stackframe();
    1923           5 :         struct tevent_context *ev = NULL;
    1924           5 :         struct tevent_req *req = NULL;
    1925           5 :         NTSTATUS status = NT_STATUS_NO_MEMORY;
    1926             : 
    1927           5 :         if (smbXcli_conn_has_async_calls(cli->conn)) {
    1928           0 :                 status = NT_STATUS_INVALID_PARAMETER;
    1929           0 :                 goto fail;
    1930             :         }
    1931           5 :         ev = samba_tevent_context_init(frame);
    1932           5 :         if (ev == NULL) {
    1933           0 :                 goto fail;
    1934             :         }
    1935           5 :         req = cli_hardlink_send(frame, ev, cli, fname_src, fname_dst);
    1936           5 :         if (req == NULL) {
    1937           0 :                 goto fail;
    1938             :         }
    1939           5 :         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
    1940           0 :                 goto fail;
    1941             :         }
    1942           5 :         status = cli_hardlink_recv(req);
    1943           5 :  fail:
    1944           5 :         TALLOC_FREE(frame);
    1945           5 :         return status;
    1946             : }
    1947             : 
    1948             : /****************************************************************************
    1949             :  Delete a file.
    1950             : ****************************************************************************/
    1951             : 
    1952             : static void cli_unlink_done(struct tevent_req *subreq);
    1953             : static void cli_unlink_done2(struct tevent_req *subreq);
    1954             : 
    1955             : struct cli_unlink_state {
    1956             :         uint16_t vwv[1];
    1957             : };
    1958             : 
    1959         729 : struct tevent_req *cli_unlink_send(TALLOC_CTX *mem_ctx,
    1960             :                                 struct tevent_context *ev,
    1961             :                                 struct cli_state *cli,
    1962             :                                 const char *fname,
    1963             :                                 uint32_t mayhave_attrs)
    1964             : {
    1965         729 :         struct tevent_req *req = NULL, *subreq = NULL;
    1966         729 :         struct cli_unlink_state *state = NULL;
    1967         729 :         uint8_t additional_flags = 0;
    1968         729 :         uint16_t additional_flags2 = 0;
    1969         729 :         uint8_t *bytes = NULL;
    1970             : 
    1971         729 :         req = tevent_req_create(mem_ctx, &state, struct cli_unlink_state);
    1972         729 :         if (req == NULL) {
    1973           0 :                 return NULL;
    1974             :         }
    1975             : 
    1976         729 :         if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
    1977         530 :                 subreq = cli_smb2_unlink_send(state, ev, cli, fname, NULL);
    1978         530 :                 if (tevent_req_nomem(subreq, req)) {
    1979           0 :                         return tevent_req_post(req, ev);
    1980             :                 }
    1981         530 :                 tevent_req_set_callback(subreq, cli_unlink_done2, req);
    1982         530 :                 return req;
    1983             :         }
    1984             : 
    1985         199 :         if (mayhave_attrs & 0xFFFF0000) {
    1986             :                 /*
    1987             :                  * Don't allow attributes greater than
    1988             :                  * 16-bits for a 16-bit protocol value.
    1989             :                  */
    1990           1 :                 if (tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER)) {
    1991           1 :                         return tevent_req_post(req, ev);
    1992             :                 }
    1993             :         }
    1994             : 
    1995         198 :         SSVAL(state->vwv+0, 0, mayhave_attrs);
    1996             : 
    1997         198 :         bytes = talloc_array(state, uint8_t, 1);
    1998         198 :         if (tevent_req_nomem(bytes, req)) {
    1999           0 :                 return tevent_req_post(req, ev);
    2000             :         }
    2001         198 :         bytes[0] = 4;
    2002         198 :         bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), fname,
    2003         198 :                                    strlen(fname)+1, NULL);
    2004             : 
    2005         198 :         if (tevent_req_nomem(bytes, req)) {
    2006           0 :                 return tevent_req_post(req, ev);
    2007             :         }
    2008             : 
    2009         198 :         if (clistr_is_previous_version_path(fname, NULL, NULL, NULL)) {
    2010           0 :                 additional_flags2 = FLAGS2_REPARSE_PATH;
    2011             :         }
    2012             : 
    2013         396 :         subreq = cli_smb_send(state, ev, cli, SMBunlink, additional_flags,
    2014             :                                 additional_flags2,
    2015         396 :                                 1, state->vwv, talloc_get_size(bytes), bytes);
    2016         198 :         if (tevent_req_nomem(subreq, req)) {
    2017           0 :                 return tevent_req_post(req, ev);
    2018             :         }
    2019         198 :         tevent_req_set_callback(subreq, cli_unlink_done, req);
    2020         198 :         return req;
    2021             : }
    2022             : 
    2023         198 : static void cli_unlink_done(struct tevent_req *subreq)
    2024             : {
    2025         198 :         NTSTATUS status = cli_smb_recv(
    2026             :                 subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
    2027         198 :         tevent_req_simple_finish_ntstatus(subreq, status);
    2028         198 : }
    2029             : 
    2030         530 : static void cli_unlink_done2(struct tevent_req *subreq)
    2031             : {
    2032         530 :         NTSTATUS status = cli_smb2_unlink_recv(subreq);
    2033         530 :         tevent_req_simple_finish_ntstatus(subreq, status);
    2034         530 : }
    2035             : 
    2036         729 : NTSTATUS cli_unlink_recv(struct tevent_req *req)
    2037             : {
    2038         729 :         return tevent_req_simple_recv_ntstatus(req);
    2039             : }
    2040             : 
    2041         264 : NTSTATUS cli_unlink(struct cli_state *cli, const char *fname, uint32_t mayhave_attrs)
    2042             : {
    2043         264 :         TALLOC_CTX *frame = NULL;
    2044             :         struct tevent_context *ev;
    2045             :         struct tevent_req *req;
    2046         264 :         NTSTATUS status = NT_STATUS_OK;
    2047             : 
    2048         264 :         frame = talloc_stackframe();
    2049             : 
    2050         264 :         if (smbXcli_conn_has_async_calls(cli->conn)) {
    2051             :                 /*
    2052             :                  * Can't use sync call while an async call is in flight
    2053             :                  */
    2054           0 :                 status = NT_STATUS_INVALID_PARAMETER;
    2055           0 :                 goto fail;
    2056             :         }
    2057             : 
    2058         264 :         ev = samba_tevent_context_init(frame);
    2059         264 :         if (ev == NULL) {
    2060           0 :                 status = NT_STATUS_NO_MEMORY;
    2061           0 :                 goto fail;
    2062             :         }
    2063             : 
    2064         264 :         req = cli_unlink_send(frame, ev, cli, fname, mayhave_attrs);
    2065         264 :         if (req == NULL) {
    2066           0 :                 status = NT_STATUS_NO_MEMORY;
    2067           0 :                 goto fail;
    2068             :         }
    2069             : 
    2070         264 :         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
    2071           0 :                 goto fail;
    2072             :         }
    2073             : 
    2074         264 :         status = cli_unlink_recv(req);
    2075         264 :         cli->raw_status = status; /* cli_smb2_unlink_recv doesn't set this */
    2076             : 
    2077         264 :  fail:
    2078         264 :         TALLOC_FREE(frame);
    2079         264 :         return status;
    2080             : }
    2081             : 
    2082             : /****************************************************************************
    2083             :  Create a directory.
    2084             : ****************************************************************************/
    2085             : 
    2086             : static void cli_mkdir_done(struct tevent_req *subreq);
    2087             : static void cli_mkdir_done2(struct tevent_req *subreq);
    2088             : 
    2089             : struct cli_mkdir_state {
    2090             :         int dummy;
    2091             : };
    2092             : 
    2093        1009 : struct tevent_req *cli_mkdir_send(TALLOC_CTX *mem_ctx,
    2094             :                                   struct tevent_context *ev,
    2095             :                                   struct cli_state *cli,
    2096             :                                   const char *dname)
    2097             : {
    2098        1009 :         struct tevent_req *req = NULL, *subreq = NULL;
    2099        1009 :         struct cli_mkdir_state *state = NULL;
    2100        1009 :         uint8_t additional_flags = 0;
    2101        1009 :         uint16_t additional_flags2 = 0;
    2102        1009 :         uint8_t *bytes = NULL;
    2103             : 
    2104        1009 :         req = tevent_req_create(mem_ctx, &state, struct cli_mkdir_state);
    2105        1009 :         if (req == NULL) {
    2106           0 :                 return NULL;
    2107             :         }
    2108             : 
    2109        1009 :         if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
    2110        1005 :                 subreq = cli_smb2_mkdir_send(state, ev, cli, dname);
    2111        1005 :                 if (tevent_req_nomem(subreq, req)) {
    2112           0 :                         return tevent_req_post(req, ev);
    2113             :                 }
    2114        1005 :                 tevent_req_set_callback(subreq, cli_mkdir_done2, req);
    2115        1005 :                 return req;
    2116             :         }
    2117             : 
    2118           4 :         bytes = talloc_array(state, uint8_t, 1);
    2119           4 :         if (tevent_req_nomem(bytes, req)) {
    2120           0 :                 return tevent_req_post(req, ev);
    2121             :         }
    2122           4 :         bytes[0] = 4;
    2123           4 :         bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), dname,
    2124           4 :                                    strlen(dname)+1, NULL);
    2125             : 
    2126           4 :         if (tevent_req_nomem(bytes, req)) {
    2127           0 :                 return tevent_req_post(req, ev);
    2128             :         }
    2129             : 
    2130           4 :         if (clistr_is_previous_version_path(dname, NULL, NULL, NULL)) {
    2131           0 :                 additional_flags2 = FLAGS2_REPARSE_PATH;
    2132             :         }
    2133             : 
    2134           4 :         subreq = cli_smb_send(state, ev, cli, SMBmkdir, additional_flags,
    2135             :                         additional_flags2,
    2136           4 :                         0, NULL, talloc_get_size(bytes), bytes);
    2137           4 :         if (tevent_req_nomem(subreq, req)) {
    2138           0 :                 return tevent_req_post(req, ev);
    2139             :         }
    2140           4 :         tevent_req_set_callback(subreq, cli_mkdir_done, req);
    2141           4 :         return req;
    2142             : }
    2143             : 
    2144           4 : static void cli_mkdir_done(struct tevent_req *subreq)
    2145             : {
    2146           4 :         struct tevent_req *req = tevent_req_callback_data(
    2147             :                 subreq, struct tevent_req);
    2148             :         NTSTATUS status;
    2149             : 
    2150           4 :         status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
    2151           4 :         TALLOC_FREE(subreq);
    2152           4 :         if (tevent_req_nterror(req, status)) {
    2153           0 :                 return;
    2154             :         }
    2155           4 :         tevent_req_done(req);
    2156             : }
    2157             : 
    2158        1005 : static void cli_mkdir_done2(struct tevent_req *subreq)
    2159             : {
    2160        1005 :         NTSTATUS status = cli_smb2_mkdir_recv(subreq);
    2161        1005 :         tevent_req_simple_finish_ntstatus(subreq, status);
    2162        1005 : }
    2163             : 
    2164        1009 : NTSTATUS cli_mkdir_recv(struct tevent_req *req)
    2165             : {
    2166        1009 :         return tevent_req_simple_recv_ntstatus(req);
    2167             : }
    2168             : 
    2169          97 : NTSTATUS cli_mkdir(struct cli_state *cli, const char *dname)
    2170             : {
    2171          97 :         TALLOC_CTX *frame = NULL;
    2172             :         struct tevent_context *ev;
    2173             :         struct tevent_req *req;
    2174          97 :         NTSTATUS status = NT_STATUS_OK;
    2175             : 
    2176          97 :         frame = talloc_stackframe();
    2177             : 
    2178          97 :         if (smbXcli_conn_has_async_calls(cli->conn)) {
    2179             :                 /*
    2180             :                  * Can't use sync call while an async call is in flight
    2181             :                  */
    2182           0 :                 status = NT_STATUS_INVALID_PARAMETER;
    2183           0 :                 goto fail;
    2184             :         }
    2185             : 
    2186          97 :         ev = samba_tevent_context_init(frame);
    2187          97 :         if (ev == NULL) {
    2188           0 :                 status = NT_STATUS_NO_MEMORY;
    2189           0 :                 goto fail;
    2190             :         }
    2191             : 
    2192          97 :         req = cli_mkdir_send(frame, ev, cli, dname);
    2193          97 :         if (req == NULL) {
    2194           0 :                 status = NT_STATUS_NO_MEMORY;
    2195           0 :                 goto fail;
    2196             :         }
    2197             : 
    2198          97 :         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
    2199           0 :                 goto fail;
    2200             :         }
    2201             : 
    2202          97 :         status = cli_mkdir_recv(req);
    2203          97 :         cli->raw_status = status; /* cli_smb2_mkdir_recv doesn't set this */
    2204             : 
    2205          97 :  fail:
    2206          97 :         TALLOC_FREE(frame);
    2207          97 :         return status;
    2208             : }
    2209             : 
    2210             : /****************************************************************************
    2211             :  Remove a directory.
    2212             : ****************************************************************************/
    2213             : 
    2214             : static void cli_rmdir_done(struct tevent_req *subreq);
    2215             : static void cli_rmdir_done2(struct tevent_req *subreq);
    2216             : 
    2217             : struct cli_rmdir_state {
    2218             :         int dummy;
    2219             : };
    2220             : 
    2221        1056 : struct tevent_req *cli_rmdir_send(TALLOC_CTX *mem_ctx,
    2222             :                                   struct tevent_context *ev,
    2223             :                                   struct cli_state *cli,
    2224             :                                   const char *dname)
    2225             : {
    2226        1056 :         struct tevent_req *req = NULL, *subreq = NULL;
    2227        1056 :         struct cli_rmdir_state *state = NULL;
    2228        1056 :         uint8_t additional_flags = 0;
    2229        1056 :         uint16_t additional_flags2 = 0;
    2230        1056 :         uint8_t *bytes = NULL;
    2231             : 
    2232        1056 :         req = tevent_req_create(mem_ctx, &state, struct cli_rmdir_state);
    2233        1056 :         if (req == NULL) {
    2234           0 :                 return NULL;
    2235             :         }
    2236             : 
    2237        1056 :         if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
    2238        1051 :                 subreq = cli_smb2_rmdir_send(state, ev, cli, dname, NULL);
    2239        1051 :                 if (tevent_req_nomem(subreq, req)) {
    2240           0 :                         return tevent_req_post(req, ev);
    2241             :                 }
    2242        1051 :                 tevent_req_set_callback(subreq, cli_rmdir_done2, req);
    2243        1051 :                 return req;
    2244             :         }
    2245             : 
    2246           5 :         bytes = talloc_array(state, uint8_t, 1);
    2247           5 :         if (tevent_req_nomem(bytes, req)) {
    2248           0 :                 return tevent_req_post(req, ev);
    2249             :         }
    2250           5 :         bytes[0] = 4;
    2251           5 :         bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), dname,
    2252           5 :                                    strlen(dname)+1, NULL);
    2253             : 
    2254           5 :         if (tevent_req_nomem(bytes, req)) {
    2255           0 :                 return tevent_req_post(req, ev);
    2256             :         }
    2257             : 
    2258           5 :         if (clistr_is_previous_version_path(dname, NULL, NULL, NULL)) {
    2259           0 :                 additional_flags2 = FLAGS2_REPARSE_PATH;
    2260             :         }
    2261             : 
    2262           5 :         subreq = cli_smb_send(state, ev, cli, SMBrmdir, additional_flags,
    2263             :                         additional_flags2,
    2264           5 :                         0, NULL, talloc_get_size(bytes), bytes);
    2265           5 :         if (tevent_req_nomem(subreq, req)) {
    2266           0 :                 return tevent_req_post(req, ev);
    2267             :         }
    2268           5 :         tevent_req_set_callback(subreq, cli_rmdir_done, req);
    2269           5 :         return req;
    2270             : }
    2271             : 
    2272           5 : static void cli_rmdir_done(struct tevent_req *subreq)
    2273             : {
    2274           5 :         NTSTATUS status = cli_smb_recv(
    2275             :                 subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
    2276           5 :         tevent_req_simple_finish_ntstatus(subreq, status);
    2277           5 : }
    2278             : 
    2279        1051 : static void cli_rmdir_done2(struct tevent_req *subreq)
    2280             : {
    2281        1051 :         NTSTATUS status = cli_smb2_rmdir_recv(subreq);
    2282        1051 :         tevent_req_simple_finish_ntstatus(subreq, status);
    2283        1051 : }
    2284             : 
    2285        1056 : NTSTATUS cli_rmdir_recv(struct tevent_req *req)
    2286             : {
    2287        1056 :         return tevent_req_simple_recv_ntstatus(req);
    2288             : }
    2289             : 
    2290          87 : NTSTATUS cli_rmdir(struct cli_state *cli, const char *dname)
    2291             : {
    2292          87 :         TALLOC_CTX *frame = NULL;
    2293             :         struct tevent_context *ev;
    2294             :         struct tevent_req *req;
    2295          87 :         NTSTATUS status = NT_STATUS_OK;
    2296             : 
    2297          87 :         frame = talloc_stackframe();
    2298             : 
    2299          87 :         if (smbXcli_conn_has_async_calls(cli->conn)) {
    2300             :                 /*
    2301             :                  * Can't use sync call while an async call is in flight
    2302             :                  */
    2303           0 :                 status = NT_STATUS_INVALID_PARAMETER;
    2304           0 :                 goto fail;
    2305             :         }
    2306             : 
    2307          87 :         ev = samba_tevent_context_init(frame);
    2308          87 :         if (ev == NULL) {
    2309           0 :                 status = NT_STATUS_NO_MEMORY;
    2310           0 :                 goto fail;
    2311             :         }
    2312             : 
    2313          87 :         req = cli_rmdir_send(frame, ev, cli, dname);
    2314          87 :         if (req == NULL) {
    2315           0 :                 status = NT_STATUS_NO_MEMORY;
    2316           0 :                 goto fail;
    2317             :         }
    2318             : 
    2319          87 :         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
    2320           0 :                 goto fail;
    2321             :         }
    2322             : 
    2323          87 :         status = cli_rmdir_recv(req);
    2324          87 :         cli->raw_status = status; /* cli_smb2_rmdir_recv doesn't set this */
    2325             : 
    2326          87 :  fail:
    2327          87 :         TALLOC_FREE(frame);
    2328          87 :         return status;
    2329             : }
    2330             : 
    2331             : /****************************************************************************
    2332             :  Set or clear the delete on close flag.
    2333             : ****************************************************************************/
    2334             : 
    2335             : struct doc_state {
    2336             :         uint8_t data[1];
    2337             : };
    2338             : 
    2339             : static void cli_nt_delete_on_close_smb1_done(struct tevent_req *subreq);
    2340             : static void cli_nt_delete_on_close_smb2_done(struct tevent_req *subreq);
    2341             : 
    2342          14 : struct tevent_req *cli_nt_delete_on_close_send(TALLOC_CTX *mem_ctx,
    2343             :                                         struct tevent_context *ev,
    2344             :                                         struct cli_state *cli,
    2345             :                                         uint16_t fnum,
    2346             :                                         bool flag)
    2347             : {
    2348          14 :         struct tevent_req *req = NULL, *subreq = NULL;
    2349          14 :         struct doc_state *state = NULL;
    2350             : 
    2351          14 :         req = tevent_req_create(mem_ctx, &state, struct doc_state);
    2352          14 :         if (req == NULL) {
    2353           0 :                 return NULL;
    2354             :         }
    2355             : 
    2356          14 :         if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
    2357           4 :                 subreq = cli_smb2_delete_on_close_send(state, ev, cli,
    2358             :                                                        fnum, flag);
    2359           4 :                 if (tevent_req_nomem(subreq, req)) {
    2360           0 :                         return tevent_req_post(req, ev);
    2361             :                 }
    2362           4 :                 tevent_req_set_callback(subreq,
    2363             :                                         cli_nt_delete_on_close_smb2_done,
    2364             :                                         req);
    2365           4 :                 return req;
    2366             :         }
    2367             : 
    2368             :         /* Setup data array. */
    2369          10 :         SCVAL(&state->data[0], 0, flag ? 1 : 0);
    2370             : 
    2371          10 :         subreq = cli_setfileinfo_send(
    2372             :                 state,
    2373             :                 ev,
    2374             :                 cli,
    2375             :                 fnum,
    2376             :                 SMB_SET_FILE_DISPOSITION_INFO,
    2377          10 :                 state->data,
    2378             :                 sizeof(state->data));
    2379             : 
    2380          10 :         if (tevent_req_nomem(subreq, req)) {
    2381           0 :                 return tevent_req_post(req, ev);
    2382             :         }
    2383          10 :         tevent_req_set_callback(subreq,
    2384             :                                 cli_nt_delete_on_close_smb1_done,
    2385             :                                 req);
    2386          10 :         return req;
    2387             : }
    2388             : 
    2389          10 : static void cli_nt_delete_on_close_smb1_done(struct tevent_req *subreq)
    2390             : {
    2391          10 :         NTSTATUS status = cli_setfileinfo_recv(subreq);
    2392          10 :         tevent_req_simple_finish_ntstatus(subreq, status);
    2393          10 : }
    2394             : 
    2395           4 : static void cli_nt_delete_on_close_smb2_done(struct tevent_req *subreq)
    2396             : {
    2397           4 :         NTSTATUS status = cli_smb2_delete_on_close_recv(subreq);
    2398           4 :         tevent_req_simple_finish_ntstatus(subreq, status);
    2399           4 : }
    2400             : 
    2401          14 : NTSTATUS cli_nt_delete_on_close_recv(struct tevent_req *req)
    2402             : {
    2403          14 :         return tevent_req_simple_recv_ntstatus(req);
    2404             : }
    2405             : 
    2406          10 : NTSTATUS cli_nt_delete_on_close(struct cli_state *cli, uint16_t fnum, bool flag)
    2407             : {
    2408          10 :         TALLOC_CTX *frame = talloc_stackframe();
    2409          10 :         struct tevent_context *ev = NULL;
    2410          10 :         struct tevent_req *req = NULL;
    2411          10 :         NTSTATUS status = NT_STATUS_OK;
    2412             : 
    2413          10 :         if (smbXcli_conn_has_async_calls(cli->conn)) {
    2414             :                 /*
    2415             :                  * Can't use sync call while an async call is in flight
    2416             :                  */
    2417           0 :                 status = NT_STATUS_INVALID_PARAMETER;
    2418           0 :                 goto fail;
    2419             :         }
    2420             : 
    2421          10 :         ev = samba_tevent_context_init(frame);
    2422          10 :         if (ev == NULL) {
    2423           0 :                 status = NT_STATUS_NO_MEMORY;
    2424           0 :                 goto fail;
    2425             :         }
    2426             : 
    2427          10 :         req = cli_nt_delete_on_close_send(frame,
    2428             :                                 ev,
    2429             :                                 cli,
    2430             :                                 fnum,
    2431             :                                 flag);
    2432          10 :         if (req == NULL) {
    2433           0 :                 status = NT_STATUS_NO_MEMORY;
    2434           0 :                 goto fail;
    2435             :         }
    2436             : 
    2437          10 :         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
    2438           0 :                 goto fail;
    2439             :         }
    2440             : 
    2441          10 :         status = cli_nt_delete_on_close_recv(req);
    2442             : 
    2443          10 :  fail:
    2444          10 :         TALLOC_FREE(frame);
    2445          10 :         return status;
    2446             : }
    2447             : 
    2448             : struct cli_ntcreate1_state {
    2449             :         uint16_t vwv[24];
    2450             :         uint16_t fnum;
    2451             :         struct smb_create_returns cr;
    2452             :         struct tevent_req *subreq;
    2453             : };
    2454             : 
    2455             : static void cli_ntcreate1_done(struct tevent_req *subreq);
    2456             : static bool cli_ntcreate1_cancel(struct tevent_req *req);
    2457             : 
    2458          65 : static struct tevent_req *cli_ntcreate1_send(TALLOC_CTX *mem_ctx,
    2459             :                                              struct tevent_context *ev,
    2460             :                                              struct cli_state *cli,
    2461             :                                              const char *fname,
    2462             :                                              uint32_t CreatFlags,
    2463             :                                              uint32_t DesiredAccess,
    2464             :                                              uint32_t FileAttributes,
    2465             :                                              uint32_t ShareAccess,
    2466             :                                              uint32_t CreateDisposition,
    2467             :                                              uint32_t CreateOptions,
    2468             :                                              uint32_t ImpersonationLevel,
    2469             :                                              uint8_t SecurityFlags)
    2470             : {
    2471             :         struct tevent_req *req, *subreq;
    2472             :         struct cli_ntcreate1_state *state;
    2473             :         uint16_t *vwv;
    2474             :         uint8_t *bytes;
    2475             :         size_t converted_len;
    2476          65 :         uint16_t additional_flags2 = 0;
    2477             : 
    2478          65 :         req = tevent_req_create(mem_ctx, &state, struct cli_ntcreate1_state);
    2479          65 :         if (req == NULL) {
    2480           0 :                 return NULL;
    2481             :         }
    2482             : 
    2483          65 :         vwv = state->vwv;
    2484             : 
    2485          65 :         SCVAL(vwv+0, 0, 0xFF);
    2486          65 :         SCVAL(vwv+0, 1, 0);
    2487          65 :         SSVAL(vwv+1, 0, 0);
    2488          65 :         SCVAL(vwv+2, 0, 0);
    2489             : 
    2490          65 :         if (cli->use_oplocks) {
    2491           0 :                 CreatFlags |= (REQUEST_OPLOCK|REQUEST_BATCH_OPLOCK);
    2492             :         }
    2493          65 :         SIVAL(vwv+3, 1, CreatFlags);
    2494          65 :         SIVAL(vwv+5, 1, 0x0);   /* RootDirectoryFid */
    2495          65 :         SIVAL(vwv+7, 1, DesiredAccess);
    2496          65 :         SIVAL(vwv+9, 1, 0x0);   /* AllocationSize */
    2497          65 :         SIVAL(vwv+11, 1, 0x0);  /* AllocationSize */
    2498          65 :         SIVAL(vwv+13, 1, FileAttributes);
    2499          65 :         SIVAL(vwv+15, 1, ShareAccess);
    2500          65 :         SIVAL(vwv+17, 1, CreateDisposition);
    2501          65 :         SIVAL(vwv+19, 1, CreateOptions |
    2502             :                 (cli->backup_intent ? FILE_OPEN_FOR_BACKUP_INTENT : 0));
    2503          65 :         SIVAL(vwv+21, 1, ImpersonationLevel);
    2504          65 :         SCVAL(vwv+23, 1, SecurityFlags);
    2505             : 
    2506          65 :         bytes = talloc_array(state, uint8_t, 0);
    2507          65 :         bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
    2508          65 :                                    fname, strlen(fname)+1,
    2509             :                                    &converted_len);
    2510             : 
    2511          65 :         if (clistr_is_previous_version_path(fname, NULL, NULL, NULL)) {
    2512           0 :                 additional_flags2 = FLAGS2_REPARSE_PATH;
    2513             :         }
    2514             : 
    2515             :         /* sigh. this copes with broken netapp filer behaviour */
    2516          65 :         bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "", 1, NULL);
    2517             : 
    2518          65 :         if (tevent_req_nomem(bytes, req)) {
    2519           0 :                 return tevent_req_post(req, ev);
    2520             :         }
    2521             : 
    2522          65 :         SSVAL(vwv+2, 1, converted_len);
    2523             : 
    2524          65 :         subreq = cli_smb_send(state, ev, cli, SMBntcreateX, 0,
    2525             :                         additional_flags2, 24, vwv,
    2526          65 :                         talloc_get_size(bytes), bytes);
    2527          65 :         if (tevent_req_nomem(subreq, req)) {
    2528           0 :                 return tevent_req_post(req, ev);
    2529             :         }
    2530          65 :         tevent_req_set_callback(subreq, cli_ntcreate1_done, req);
    2531             : 
    2532          65 :         state->subreq = subreq;
    2533          65 :         tevent_req_set_cancel_fn(req, cli_ntcreate1_cancel);
    2534             : 
    2535          65 :         return req;
    2536             : }
    2537             : 
    2538          65 : static void cli_ntcreate1_done(struct tevent_req *subreq)
    2539             : {
    2540          65 :         struct tevent_req *req = tevent_req_callback_data(
    2541             :                 subreq, struct tevent_req);
    2542          65 :         struct cli_ntcreate1_state *state = tevent_req_data(
    2543             :                 req, struct cli_ntcreate1_state);
    2544             :         uint8_t wct;
    2545             :         uint16_t *vwv;
    2546             :         uint32_t num_bytes;
    2547             :         uint8_t *bytes;
    2548             :         NTSTATUS status;
    2549             : 
    2550          65 :         status = cli_smb_recv(subreq, state, NULL, 34, &wct, &vwv,
    2551             :                               &num_bytes, &bytes);
    2552          65 :         TALLOC_FREE(subreq);
    2553          65 :         if (tevent_req_nterror(req, status)) {
    2554          11 :                 return;
    2555             :         }
    2556          54 :         state->cr.oplock_level = CVAL(vwv+2, 0);
    2557          54 :         state->fnum = SVAL(vwv+2, 1);
    2558          54 :         state->cr.create_action = IVAL(vwv+3, 1);
    2559          54 :         state->cr.creation_time = BVAL(vwv+5, 1);
    2560          54 :         state->cr.last_access_time = BVAL(vwv+9, 1);
    2561          54 :         state->cr.last_write_time = BVAL(vwv+13, 1);
    2562          54 :         state->cr.change_time   = BVAL(vwv+17, 1);
    2563          54 :         state->cr.file_attributes = IVAL(vwv+21, 1);
    2564          54 :         state->cr.allocation_size = BVAL(vwv+23, 1);
    2565          54 :         state->cr.end_of_file   = BVAL(vwv+27, 1);
    2566             : 
    2567          54 :         tevent_req_done(req);
    2568             : }
    2569             : 
    2570           0 : static bool cli_ntcreate1_cancel(struct tevent_req *req)
    2571             : {
    2572           0 :         struct cli_ntcreate1_state *state = tevent_req_data(
    2573             :                 req, struct cli_ntcreate1_state);
    2574           0 :         return tevent_req_cancel(state->subreq);
    2575             : }
    2576             : 
    2577          65 : static NTSTATUS cli_ntcreate1_recv(struct tevent_req *req,
    2578             :                                    uint16_t *pfnum,
    2579             :                                    struct smb_create_returns *cr)
    2580             : {
    2581          65 :         struct cli_ntcreate1_state *state = tevent_req_data(
    2582             :                 req, struct cli_ntcreate1_state);
    2583             :         NTSTATUS status;
    2584             : 
    2585          65 :         if (tevent_req_is_nterror(req, &status)) {
    2586          11 :                 return status;
    2587             :         }
    2588          54 :         *pfnum = state->fnum;
    2589          54 :         if (cr != NULL) {
    2590          54 :                 *cr = state->cr;
    2591             :         }
    2592          54 :         return NT_STATUS_OK;
    2593             : }
    2594             : 
    2595             : struct cli_ntcreate_state {
    2596             :         struct smb_create_returns cr;
    2597             :         uint16_t fnum;
    2598             :         struct tevent_req *subreq;
    2599             : };
    2600             : 
    2601             : static void cli_ntcreate_done_nt1(struct tevent_req *subreq);
    2602             : static void cli_ntcreate_done_smb2(struct tevent_req *subreq);
    2603             : static bool cli_ntcreate_cancel(struct tevent_req *req);
    2604             : 
    2605        4812 : struct tevent_req *cli_ntcreate_send(TALLOC_CTX *mem_ctx,
    2606             :                                      struct tevent_context *ev,
    2607             :                                      struct cli_state *cli,
    2608             :                                      const char *fname,
    2609             :                                      uint32_t create_flags,
    2610             :                                      uint32_t desired_access,
    2611             :                                      uint32_t file_attributes,
    2612             :                                      uint32_t share_access,
    2613             :                                      uint32_t create_disposition,
    2614             :                                      uint32_t create_options,
    2615             :                                      uint32_t impersonation_level,
    2616             :                                      uint8_t security_flags)
    2617             : {
    2618             :         struct tevent_req *req, *subreq;
    2619             :         struct cli_ntcreate_state *state;
    2620             : 
    2621        4812 :         req = tevent_req_create(mem_ctx, &state, struct cli_ntcreate_state);
    2622        4812 :         if (req == NULL) {
    2623           0 :                 return NULL;
    2624             :         }
    2625             : 
    2626        4812 :         if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
    2627        4747 :                 if (cli->use_oplocks) {
    2628           0 :                         create_flags |= REQUEST_OPLOCK|REQUEST_BATCH_OPLOCK;
    2629             :                 }
    2630             : 
    2631        4747 :                 subreq = cli_smb2_create_fnum_send(
    2632             :                         state,
    2633             :                         ev,
    2634             :                         cli,
    2635             :                         fname,
    2636             :                         create_flags,
    2637             :                         impersonation_level,
    2638             :                         desired_access,
    2639             :                         file_attributes,
    2640             :                         share_access,
    2641             :                         create_disposition,
    2642             :                         create_options,
    2643             :                         NULL);
    2644        4747 :                 if (tevent_req_nomem(subreq, req)) {
    2645           0 :                         return tevent_req_post(req, ev);
    2646             :                 }
    2647        4747 :                 tevent_req_set_callback(subreq, cli_ntcreate_done_smb2, req);
    2648             :         } else {
    2649          65 :                 subreq = cli_ntcreate1_send(
    2650             :                         state, ev, cli, fname, create_flags, desired_access,
    2651             :                         file_attributes, share_access, create_disposition,
    2652             :                         create_options, impersonation_level, security_flags);
    2653          65 :                 if (tevent_req_nomem(subreq, req)) {
    2654           0 :                         return tevent_req_post(req, ev);
    2655             :                 }
    2656          65 :                 tevent_req_set_callback(subreq, cli_ntcreate_done_nt1, req);
    2657             :         }
    2658             : 
    2659        4812 :         state->subreq = subreq;
    2660        4812 :         tevent_req_set_cancel_fn(req, cli_ntcreate_cancel);
    2661             : 
    2662        4812 :         return req;
    2663             : }
    2664             : 
    2665          65 : static void cli_ntcreate_done_nt1(struct tevent_req *subreq)
    2666             : {
    2667          65 :         struct tevent_req *req = tevent_req_callback_data(
    2668             :                 subreq, struct tevent_req);
    2669          65 :         struct cli_ntcreate_state *state = tevent_req_data(
    2670             :                 req, struct cli_ntcreate_state);
    2671             :         NTSTATUS status;
    2672             : 
    2673          65 :         status = cli_ntcreate1_recv(subreq, &state->fnum, &state->cr);
    2674          65 :         TALLOC_FREE(subreq);
    2675          65 :         if (tevent_req_nterror(req, status)) {
    2676          11 :                 return;
    2677             :         }
    2678          54 :         tevent_req_done(req);
    2679             : }
    2680             : 
    2681        4747 : static void cli_ntcreate_done_smb2(struct tevent_req *subreq)
    2682             : {
    2683        4747 :         struct tevent_req *req = tevent_req_callback_data(
    2684             :                 subreq, struct tevent_req);
    2685        4747 :         struct cli_ntcreate_state *state = tevent_req_data(
    2686             :                 req, struct cli_ntcreate_state);
    2687             :         NTSTATUS status;
    2688             : 
    2689        4747 :         status = cli_smb2_create_fnum_recv(
    2690             :                 subreq,
    2691             :                 &state->fnum,
    2692             :                 &state->cr,
    2693             :                 NULL,
    2694             :                 NULL);
    2695        4747 :         TALLOC_FREE(subreq);
    2696        4747 :         if (tevent_req_nterror(req, status)) {
    2697         874 :                 return;
    2698             :         }
    2699        3873 :         tevent_req_done(req);
    2700             : }
    2701             : 
    2702           0 : static bool cli_ntcreate_cancel(struct tevent_req *req)
    2703             : {
    2704           0 :         struct cli_ntcreate_state *state = tevent_req_data(
    2705             :                 req, struct cli_ntcreate_state);
    2706           0 :         return tevent_req_cancel(state->subreq);
    2707             : }
    2708             : 
    2709        4812 : NTSTATUS cli_ntcreate_recv(struct tevent_req *req, uint16_t *fnum,
    2710             :                            struct smb_create_returns *cr)
    2711             : {
    2712        4812 :         struct cli_ntcreate_state *state = tevent_req_data(
    2713             :                 req, struct cli_ntcreate_state);
    2714             :         NTSTATUS status;
    2715             : 
    2716        4812 :         if (tevent_req_is_nterror(req, &status)) {
    2717         885 :                 return status;
    2718             :         }
    2719        3927 :         if (fnum != NULL) {
    2720        3927 :                 *fnum = state->fnum;
    2721             :         }
    2722        3927 :         if (cr != NULL) {
    2723          94 :                 *cr = state->cr;
    2724             :         }
    2725        3927 :         return NT_STATUS_OK;
    2726             : }
    2727             : 
    2728         217 : NTSTATUS cli_ntcreate(struct cli_state *cli,
    2729             :                       const char *fname,
    2730             :                       uint32_t CreatFlags,
    2731             :                       uint32_t DesiredAccess,
    2732             :                       uint32_t FileAttributes,
    2733             :                       uint32_t ShareAccess,
    2734             :                       uint32_t CreateDisposition,
    2735             :                       uint32_t CreateOptions,
    2736             :                       uint8_t SecurityFlags,
    2737             :                       uint16_t *pfid,
    2738             :                       struct smb_create_returns *cr)
    2739             : {
    2740         217 :         TALLOC_CTX *frame = talloc_stackframe();
    2741             :         struct tevent_context *ev;
    2742             :         struct tevent_req *req;
    2743         217 :         uint32_t ImpersonationLevel = SMB2_IMPERSONATION_IMPERSONATION;
    2744         217 :         NTSTATUS status = NT_STATUS_NO_MEMORY;
    2745             : 
    2746         217 :         if (smbXcli_conn_has_async_calls(cli->conn)) {
    2747             :                 /*
    2748             :                  * Can't use sync call while an async call is in flight
    2749             :                  */
    2750           0 :                 status = NT_STATUS_INVALID_PARAMETER;
    2751           0 :                 goto fail;
    2752             :         }
    2753             : 
    2754         217 :         ev = samba_tevent_context_init(frame);
    2755         217 :         if (ev == NULL) {
    2756           0 :                 goto fail;
    2757             :         }
    2758             : 
    2759         217 :         req = cli_ntcreate_send(frame, ev, cli, fname, CreatFlags,
    2760             :                                 DesiredAccess, FileAttributes, ShareAccess,
    2761             :                                 CreateDisposition, CreateOptions,
    2762             :                                 ImpersonationLevel, SecurityFlags);
    2763         217 :         if (req == NULL) {
    2764           0 :                 goto fail;
    2765             :         }
    2766             : 
    2767         217 :         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
    2768           0 :                 goto fail;
    2769             :         }
    2770             : 
    2771         217 :         status = cli_ntcreate_recv(req, pfid, cr);
    2772         217 :  fail:
    2773         217 :         TALLOC_FREE(frame);
    2774         217 :         return status;
    2775             : }
    2776             : 
    2777             : struct cli_nttrans_create_state {
    2778             :         uint16_t fnum;
    2779             :         struct smb_create_returns cr;
    2780             : };
    2781             : 
    2782             : static void cli_nttrans_create_done(struct tevent_req *subreq);
    2783             : 
    2784           0 : struct tevent_req *cli_nttrans_create_send(TALLOC_CTX *mem_ctx,
    2785             :                                            struct tevent_context *ev,
    2786             :                                            struct cli_state *cli,
    2787             :                                            const char *fname,
    2788             :                                            uint32_t CreatFlags,
    2789             :                                            uint32_t DesiredAccess,
    2790             :                                            uint32_t FileAttributes,
    2791             :                                            uint32_t ShareAccess,
    2792             :                                            uint32_t CreateDisposition,
    2793             :                                            uint32_t CreateOptions,
    2794             :                                            uint8_t SecurityFlags,
    2795             :                                            struct security_descriptor *secdesc,
    2796             :                                            struct ea_struct *eas,
    2797             :                                            int num_eas)
    2798             : {
    2799             :         struct tevent_req *req, *subreq;
    2800             :         struct cli_nttrans_create_state *state;
    2801             :         uint8_t *param;
    2802             :         uint8_t *secdesc_buf;
    2803             :         size_t secdesc_len;
    2804             :         NTSTATUS status;
    2805             :         size_t converted_len;
    2806           0 :         uint16_t additional_flags2 = 0;
    2807             : 
    2808           0 :         req = tevent_req_create(mem_ctx,
    2809             :                                 &state, struct cli_nttrans_create_state);
    2810           0 :         if (req == NULL) {
    2811           0 :                 return NULL;
    2812             :         }
    2813             : 
    2814           0 :         if (secdesc != NULL) {
    2815           0 :                 status = marshall_sec_desc(talloc_tos(), secdesc,
    2816             :                                            &secdesc_buf, &secdesc_len);
    2817           0 :                 if (tevent_req_nterror(req, status)) {
    2818           0 :                         DEBUG(10, ("marshall_sec_desc failed: %s\n",
    2819             :                                    nt_errstr(status)));
    2820           0 :                         return tevent_req_post(req, ev);
    2821             :                 }
    2822             :         } else {
    2823           0 :                 secdesc_buf = NULL;
    2824           0 :                 secdesc_len = 0;
    2825             :         }
    2826             : 
    2827           0 :         if (num_eas != 0) {
    2828             :                 /*
    2829             :                  * TODO ;-)
    2830             :                  */
    2831           0 :                 tevent_req_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
    2832           0 :                 return tevent_req_post(req, ev);
    2833             :         }
    2834             : 
    2835           0 :         param = talloc_array(state, uint8_t, 53);
    2836           0 :         if (tevent_req_nomem(param, req)) {
    2837           0 :                 return tevent_req_post(req, ev);
    2838             :         }
    2839             : 
    2840           0 :         param = trans2_bytes_push_str(param, smbXcli_conn_use_unicode(cli->conn),
    2841             :                                       fname, strlen(fname),
    2842             :                                       &converted_len);
    2843           0 :         if (tevent_req_nomem(param, req)) {
    2844           0 :                 return tevent_req_post(req, ev);
    2845             :         }
    2846             : 
    2847           0 :         if (clistr_is_previous_version_path(fname, NULL, NULL, NULL)) {
    2848           0 :                 additional_flags2 = FLAGS2_REPARSE_PATH;
    2849             :         }
    2850             : 
    2851           0 :         SIVAL(param, 0, CreatFlags);
    2852           0 :         SIVAL(param, 4, 0x0);   /* RootDirectoryFid */
    2853           0 :         SIVAL(param, 8, DesiredAccess);
    2854           0 :         SIVAL(param, 12, 0x0);  /* AllocationSize */
    2855           0 :         SIVAL(param, 16, 0x0);  /* AllocationSize */
    2856           0 :         SIVAL(param, 20, FileAttributes);
    2857           0 :         SIVAL(param, 24, ShareAccess);
    2858           0 :         SIVAL(param, 28, CreateDisposition);
    2859           0 :         SIVAL(param, 32, CreateOptions |
    2860             :                 (cli->backup_intent ? FILE_OPEN_FOR_BACKUP_INTENT : 0));
    2861           0 :         SIVAL(param, 36, secdesc_len);
    2862           0 :         SIVAL(param, 40, 0);     /* EA length*/
    2863           0 :         SIVAL(param, 44, converted_len);
    2864           0 :         SIVAL(param, 48, 0x02); /* ImpersonationLevel */
    2865           0 :         SCVAL(param, 52, SecurityFlags);
    2866             : 
    2867           0 :         subreq = cli_trans_send(state, ev, cli,
    2868             :                                 additional_flags2, /* additional_flags2 */
    2869             :                                 SMBnttrans,
    2870             :                                 NULL, -1, /* name, fid */
    2871             :                                 NT_TRANSACT_CREATE, 0,
    2872             :                                 NULL, 0, 0, /* setup */
    2873           0 :                                 param, talloc_get_size(param), 128, /* param */
    2874             :                                 secdesc_buf, secdesc_len, 0); /* data */
    2875           0 :         if (tevent_req_nomem(subreq, req)) {
    2876           0 :                 return tevent_req_post(req, ev);
    2877             :         }
    2878           0 :         tevent_req_set_callback(subreq, cli_nttrans_create_done, req);
    2879           0 :         return req;
    2880             : }
    2881             : 
    2882           0 : static void cli_nttrans_create_done(struct tevent_req *subreq)
    2883             : {
    2884           0 :         struct tevent_req *req = tevent_req_callback_data(
    2885             :                 subreq, struct tevent_req);
    2886           0 :         struct cli_nttrans_create_state *state = tevent_req_data(
    2887             :                 req, struct cli_nttrans_create_state);
    2888             :         uint8_t *param;
    2889             :         uint32_t num_param;
    2890             :         NTSTATUS status;
    2891             : 
    2892           0 :         status = cli_trans_recv(subreq, talloc_tos(), NULL,
    2893             :                                 NULL, 0, NULL, /* rsetup */
    2894             :                                 &param, 69, &num_param,
    2895             :                                 NULL, 0, NULL);
    2896           0 :         if (tevent_req_nterror(req, status)) {
    2897           0 :                 return;
    2898             :         }
    2899           0 :         state->cr.oplock_level = CVAL(param, 0);
    2900           0 :         state->fnum = SVAL(param, 2);
    2901           0 :         state->cr.create_action = IVAL(param, 4);
    2902           0 :         state->cr.creation_time = BVAL(param, 12);
    2903           0 :         state->cr.last_access_time = BVAL(param, 20);
    2904           0 :         state->cr.last_write_time = BVAL(param, 28);
    2905           0 :         state->cr.change_time   = BVAL(param, 36);
    2906           0 :         state->cr.file_attributes = IVAL(param, 44);
    2907           0 :         state->cr.allocation_size = BVAL(param, 48);
    2908           0 :         state->cr.end_of_file   = BVAL(param, 56);
    2909             : 
    2910           0 :         TALLOC_FREE(param);
    2911           0 :         tevent_req_done(req);
    2912             : }
    2913             : 
    2914           0 : NTSTATUS cli_nttrans_create_recv(struct tevent_req *req,
    2915             :                         uint16_t *fnum,
    2916             :                         struct smb_create_returns *cr)
    2917             : {
    2918           0 :         struct cli_nttrans_create_state *state = tevent_req_data(
    2919             :                 req, struct cli_nttrans_create_state);
    2920             :         NTSTATUS status;
    2921             : 
    2922           0 :         if (tevent_req_is_nterror(req, &status)) {
    2923           0 :                 return status;
    2924             :         }
    2925           0 :         *fnum = state->fnum;
    2926           0 :         if (cr != NULL) {
    2927           0 :                 *cr = state->cr;
    2928             :         }
    2929           0 :         return NT_STATUS_OK;
    2930             : }
    2931             : 
    2932           0 : NTSTATUS cli_nttrans_create(struct cli_state *cli,
    2933             :                             const char *fname,
    2934             :                             uint32_t CreatFlags,
    2935             :                             uint32_t DesiredAccess,
    2936             :                             uint32_t FileAttributes,
    2937             :                             uint32_t ShareAccess,
    2938             :                             uint32_t CreateDisposition,
    2939             :                             uint32_t CreateOptions,
    2940             :                             uint8_t SecurityFlags,
    2941             :                             struct security_descriptor *secdesc,
    2942             :                             struct ea_struct *eas,
    2943             :                             int num_eas,
    2944             :                             uint16_t *pfid,
    2945             :                             struct smb_create_returns *cr)
    2946             : {
    2947           0 :         TALLOC_CTX *frame = talloc_stackframe();
    2948             :         struct tevent_context *ev;
    2949             :         struct tevent_req *req;
    2950           0 :         NTSTATUS status = NT_STATUS_NO_MEMORY;
    2951             : 
    2952           0 :         if (smbXcli_conn_has_async_calls(cli->conn)) {
    2953             :                 /*
    2954             :                  * Can't use sync call while an async call is in flight
    2955             :                  */
    2956           0 :                 status = NT_STATUS_INVALID_PARAMETER;
    2957           0 :                 goto fail;
    2958             :         }
    2959           0 :         ev = samba_tevent_context_init(frame);
    2960           0 :         if (ev == NULL) {
    2961           0 :                 goto fail;
    2962             :         }
    2963           0 :         req = cli_nttrans_create_send(frame, ev, cli, fname, CreatFlags,
    2964             :                                       DesiredAccess, FileAttributes,
    2965             :                                       ShareAccess, CreateDisposition,
    2966             :                                       CreateOptions, SecurityFlags,
    2967             :                                       secdesc, eas, num_eas);
    2968           0 :         if (req == NULL) {
    2969           0 :                 goto fail;
    2970             :         }
    2971           0 :         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
    2972           0 :                 goto fail;
    2973             :         }
    2974           0 :         status = cli_nttrans_create_recv(req, pfid, cr);
    2975           0 :  fail:
    2976           0 :         TALLOC_FREE(frame);
    2977           0 :         return status;
    2978             : }
    2979             : 
    2980             : /****************************************************************************
    2981             :  Open a file
    2982             :  WARNING: if you open with O_WRONLY then getattrE won't work!
    2983             : ****************************************************************************/
    2984             : 
    2985             : struct cli_openx_state {
    2986             :         const char *fname;
    2987             :         uint16_t vwv[15];
    2988             :         uint16_t fnum;
    2989             :         struct iovec bytes;
    2990             : };
    2991             : 
    2992             : static void cli_openx_done(struct tevent_req *subreq);
    2993             : 
    2994         174 : struct tevent_req *cli_openx_create(TALLOC_CTX *mem_ctx,
    2995             :                                    struct tevent_context *ev,
    2996             :                                    struct cli_state *cli, const char *fname,
    2997             :                                    int flags, int share_mode,
    2998             :                                    struct tevent_req **psmbreq)
    2999             : {
    3000             :         struct tevent_req *req, *subreq;
    3001             :         struct cli_openx_state *state;
    3002             :         unsigned openfn;
    3003             :         unsigned accessmode;
    3004             :         uint8_t additional_flags;
    3005         174 :         uint16_t additional_flags2 = 0;
    3006             :         uint8_t *bytes;
    3007             : 
    3008         174 :         req = tevent_req_create(mem_ctx, &state, struct cli_openx_state);
    3009         174 :         if (req == NULL) {
    3010           0 :                 return NULL;
    3011             :         }
    3012             : 
    3013         174 :         openfn = 0;
    3014         174 :         if (flags & O_CREAT) {
    3015         143 :                 openfn |= (1<<4);
    3016             :         }
    3017         174 :         if (!(flags & O_EXCL)) {
    3018         150 :                 if (flags & O_TRUNC)
    3019           7 :                         openfn |= (1<<1);
    3020             :                 else
    3021         143 :                         openfn |= (1<<0);
    3022             :         }
    3023             : 
    3024         174 :         accessmode = (share_mode<<4);
    3025             : 
    3026         174 :         if ((flags & O_ACCMODE) == O_RDWR) {
    3027         164 :                 accessmode |= 2;
    3028          10 :         } else if ((flags & O_ACCMODE) == O_WRONLY) {
    3029           0 :                 accessmode |= 1;
    3030             :         }
    3031             : 
    3032             : #if defined(O_SYNC)
    3033         174 :         if ((flags & O_SYNC) == O_SYNC) {
    3034           0 :                 accessmode |= (1<<14);
    3035             :         }
    3036             : #endif /* O_SYNC */
    3037             : 
    3038         174 :         if (share_mode == DENY_FCB) {
    3039           0 :                 accessmode = 0xFF;
    3040             :         }
    3041             : 
    3042         174 :         SCVAL(state->vwv + 0, 0, 0xFF);
    3043         174 :         SCVAL(state->vwv + 0, 1, 0);
    3044         174 :         SSVAL(state->vwv + 1, 0, 0);
    3045         174 :         SSVAL(state->vwv + 2, 0, 0);  /* no additional info */
    3046         174 :         SSVAL(state->vwv + 3, 0, accessmode);
    3047         174 :         SSVAL(state->vwv + 4, 0, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
    3048         174 :         SSVAL(state->vwv + 5, 0, 0);
    3049         174 :         SIVAL(state->vwv + 6, 0, 0);
    3050         174 :         SSVAL(state->vwv + 8, 0, openfn);
    3051         174 :         SIVAL(state->vwv + 9, 0, 0);
    3052         174 :         SIVAL(state->vwv + 11, 0, 0);
    3053         174 :         SIVAL(state->vwv + 13, 0, 0);
    3054             : 
    3055         174 :         additional_flags = 0;
    3056             : 
    3057         174 :         if (cli->use_oplocks) {
    3058             :                 /* if using oplocks then ask for a batch oplock via
    3059             :                    core and extended methods */
    3060           3 :                 additional_flags =
    3061             :                         FLAG_REQUEST_OPLOCK|FLAG_REQUEST_BATCH_OPLOCK;
    3062           3 :                 SSVAL(state->vwv+2, 0, SVAL(state->vwv+2, 0) | 6);
    3063             :         }
    3064             : 
    3065         174 :         bytes = talloc_array(state, uint8_t, 0);
    3066         174 :         bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), fname,
    3067         174 :                                    strlen(fname)+1, NULL);
    3068             : 
    3069         174 :         if (tevent_req_nomem(bytes, req)) {
    3070           0 :                 return tevent_req_post(req, ev);
    3071             :         }
    3072             : 
    3073         174 :         if (clistr_is_previous_version_path(fname, NULL, NULL, NULL)) {
    3074           0 :                 additional_flags2 = FLAGS2_REPARSE_PATH;
    3075             :         }
    3076             : 
    3077         174 :         state->bytes.iov_base = (void *)bytes;
    3078         174 :         state->bytes.iov_len = talloc_get_size(bytes);
    3079             : 
    3080         348 :         subreq = cli_smb_req_create(state, ev, cli, SMBopenX, additional_flags,
    3081         348 :                         additional_flags2, 15, state->vwv, 1, &state->bytes);
    3082         174 :         if (subreq == NULL) {
    3083           0 :                 TALLOC_FREE(req);
    3084           0 :                 return NULL;
    3085             :         }
    3086         174 :         tevent_req_set_callback(subreq, cli_openx_done, req);
    3087         174 :         *psmbreq = subreq;
    3088         174 :         return req;
    3089             : }
    3090             : 
    3091         172 : struct tevent_req *cli_openx_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev,
    3092             :                                  struct cli_state *cli, const char *fname,
    3093             :                                  int flags, int share_mode)
    3094             : {
    3095             :         struct tevent_req *req, *subreq;
    3096             :         NTSTATUS status;
    3097             : 
    3098         172 :         req = cli_openx_create(mem_ctx, ev, cli, fname, flags, share_mode,
    3099             :                               &subreq);
    3100         172 :         if (req == NULL) {
    3101           0 :                 return NULL;
    3102             :         }
    3103             : 
    3104         172 :         status = smb1cli_req_chain_submit(&subreq, 1);
    3105         172 :         if (tevent_req_nterror(req, status)) {
    3106           0 :                 return tevent_req_post(req, ev);
    3107             :         }
    3108         172 :         return req;
    3109             : }
    3110             : 
    3111         174 : static void cli_openx_done(struct tevent_req *subreq)
    3112             : {
    3113         174 :         struct tevent_req *req = tevent_req_callback_data(
    3114             :                 subreq, struct tevent_req);
    3115         174 :         struct cli_openx_state *state = tevent_req_data(
    3116             :                 req, struct cli_openx_state);
    3117             :         uint8_t wct;
    3118             :         uint16_t *vwv;
    3119             :         NTSTATUS status;
    3120             : 
    3121         174 :         status = cli_smb_recv(subreq, state, NULL, 3, &wct, &vwv, NULL,
    3122             :                               NULL);
    3123         174 :         TALLOC_FREE(subreq);
    3124         174 :         if (tevent_req_nterror(req, status)) {
    3125           9 :                 return;
    3126             :         }
    3127         165 :         state->fnum = SVAL(vwv+2, 0);
    3128         165 :         tevent_req_done(req);
    3129             : }
    3130             : 
    3131         174 : NTSTATUS cli_openx_recv(struct tevent_req *req, uint16_t *pfnum)
    3132             : {
    3133         174 :         struct cli_openx_state *state = tevent_req_data(
    3134             :                 req, struct cli_openx_state);
    3135             :         NTSTATUS status;
    3136             : 
    3137         174 :         if (tevent_req_is_nterror(req, &status)) {
    3138           9 :                 return status;
    3139             :         }
    3140         165 :         *pfnum = state->fnum;
    3141         165 :         return NT_STATUS_OK;
    3142             : }
    3143             : 
    3144         171 : NTSTATUS cli_openx(struct cli_state *cli, const char *fname, int flags,
    3145             :              int share_mode, uint16_t *pfnum)
    3146             : {
    3147         171 :         TALLOC_CTX *frame = talloc_stackframe();
    3148             :         struct tevent_context *ev;
    3149             :         struct tevent_req *req;
    3150         171 :         NTSTATUS status = NT_STATUS_NO_MEMORY;
    3151             : 
    3152         171 :         if (smbXcli_conn_has_async_calls(cli->conn)) {
    3153             :                 /*
    3154             :                  * Can't use sync call while an async call is in flight
    3155             :                  */
    3156           0 :                 status = NT_STATUS_INVALID_PARAMETER;
    3157           0 :                 goto fail;
    3158             :         }
    3159             : 
    3160         171 :         ev = samba_tevent_context_init(frame);
    3161         171 :         if (ev == NULL) {
    3162           0 :                 goto fail;
    3163             :         }
    3164             : 
    3165         171 :         req = cli_openx_send(frame, ev, cli, fname, flags, share_mode);
    3166         171 :         if (req == NULL) {
    3167           0 :                 goto fail;
    3168             :         }
    3169             : 
    3170         171 :         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
    3171           0 :                 goto fail;
    3172             :         }
    3173             : 
    3174         171 :         status = cli_openx_recv(req, pfnum);
    3175         171 :  fail:
    3176         171 :         TALLOC_FREE(frame);
    3177         171 :         return status;
    3178             : }
    3179             : /****************************************************************************
    3180             :  Synchronous wrapper function that does an NtCreateX open by preference
    3181             :  and falls back to openX if this fails.
    3182             : ****************************************************************************/
    3183             : 
    3184         110 : NTSTATUS cli_open(struct cli_state *cli, const char *fname, int flags,
    3185             :                         int share_mode_in, uint16_t *pfnum)
    3186             : {
    3187             :         NTSTATUS status;
    3188         110 :         unsigned int openfn = 0;
    3189         110 :         unsigned int dos_deny = 0;
    3190             :         uint32_t access_mask, share_mode, create_disposition, create_options;
    3191         110 :         struct smb_create_returns cr = {0};
    3192             : 
    3193             :         /* Do the initial mapping into OpenX parameters. */
    3194         110 :         if (flags & O_CREAT) {
    3195          89 :                 openfn |= (1<<4);
    3196             :         }
    3197         110 :         if (!(flags & O_EXCL)) {
    3198         110 :                 if (flags & O_TRUNC)
    3199          89 :                         openfn |= (1<<1);
    3200             :                 else
    3201          21 :                         openfn |= (1<<0);
    3202             :         }
    3203             : 
    3204         110 :         dos_deny = (share_mode_in<<4);
    3205             : 
    3206         110 :         if ((flags & O_ACCMODE) == O_RDWR) {
    3207          89 :                 dos_deny |= 2;
    3208          21 :         } else if ((flags & O_ACCMODE) == O_WRONLY) {
    3209           0 :                 dos_deny |= 1;
    3210             :         }
    3211             : 
    3212             : #if defined(O_SYNC)
    3213         110 :         if ((flags & O_SYNC) == O_SYNC) {
    3214           0 :                 dos_deny |= (1<<14);
    3215             :         }
    3216             : #endif /* O_SYNC */
    3217             : 
    3218         110 :         if (share_mode_in == DENY_FCB) {
    3219           0 :                 dos_deny = 0xFF;
    3220             :         }
    3221             : 
    3222         110 :         if (!map_open_params_to_ntcreate(fname, dos_deny,
    3223             :                                         openfn, &access_mask,
    3224             :                                         &share_mode, &create_disposition,
    3225             :                                         &create_options, NULL)) {
    3226           0 :                 goto try_openx;
    3227             :         }
    3228             : 
    3229         110 :         status = cli_ntcreate(cli,
    3230             :                                 fname,
    3231             :                                 0,
    3232             :                                 access_mask,
    3233             :                                 0,
    3234             :                                 share_mode,
    3235             :                                 create_disposition,
    3236             :                                 create_options,
    3237             :                                 0,
    3238             :                                 pfnum,
    3239             :                                 &cr);
    3240             : 
    3241             :         /* Try and cope will all varients of "we don't do this call"
    3242             :            and fall back to openX. */
    3243             : 
    3244         166 :         if (NT_STATUS_EQUAL(status,NT_STATUS_NOT_IMPLEMENTED) ||
    3245         166 :                         NT_STATUS_EQUAL(status,NT_STATUS_INVALID_INFO_CLASS) ||
    3246         166 :                         NT_STATUS_EQUAL(status,NT_STATUS_PROCEDURE_NOT_FOUND) ||
    3247         166 :                         NT_STATUS_EQUAL(status,NT_STATUS_INVALID_LEVEL) ||
    3248         166 :                         NT_STATUS_EQUAL(status,NT_STATUS_INVALID_PARAMETER) ||
    3249         166 :                         NT_STATUS_EQUAL(status,NT_STATUS_INVALID_DEVICE_REQUEST) ||
    3250         166 :                         NT_STATUS_EQUAL(status,NT_STATUS_INVALID_DEVICE_STATE) ||
    3251         166 :                         NT_STATUS_EQUAL(status,NT_STATUS_CTL_FILE_NOT_SUPPORTED) ||
    3252         110 :                         NT_STATUS_EQUAL(status,NT_STATUS_UNSUCCESSFUL)) {
    3253           0 :                 goto try_openx;
    3254             :         }
    3255             : 
    3256         158 :         if (NT_STATUS_IS_OK(status) &&
    3257         142 :             (create_options & FILE_NON_DIRECTORY_FILE) &&
    3258          94 :             (cr.file_attributes & FILE_ATTRIBUTE_DIRECTORY))
    3259             :         {
    3260             :                 /*
    3261             :                  * Some (broken) servers return a valid handle
    3262             :                  * for directories even if FILE_NON_DIRECTORY_FILE
    3263             :                  * is set. Just close the handle and set the
    3264             :                  * error explicitly to NT_STATUS_FILE_IS_A_DIRECTORY.
    3265             :                  */
    3266           0 :                 status = cli_close(cli, *pfnum);
    3267           0 :                 if (!NT_STATUS_IS_OK(status)) {
    3268           0 :                         return status;
    3269             :                 }
    3270           0 :                 status = NT_STATUS_FILE_IS_A_DIRECTORY;
    3271             :                 /* Set this so libsmbclient can retrieve it. */
    3272           0 :                 cli->raw_status = status;
    3273             :         }
    3274             : 
    3275         110 :         return status;
    3276             : 
    3277           0 :   try_openx:
    3278             : 
    3279           0 :         return cli_openx(cli, fname, flags, share_mode_in, pfnum);
    3280             : }
    3281             : 
    3282             : /****************************************************************************
    3283             :  Close a file.
    3284             : ****************************************************************************/
    3285             : 
    3286             : struct cli_smb1_close_state {
    3287             :         uint16_t vwv[3];
    3288             : };
    3289             : 
    3290             : static void cli_smb1_close_done(struct tevent_req *subreq);
    3291             : 
    3292         210 : struct tevent_req *cli_smb1_close_create(TALLOC_CTX *mem_ctx,
    3293             :                                 struct tevent_context *ev,
    3294             :                                 struct cli_state *cli,
    3295             :                                 uint16_t fnum,
    3296             :                                 struct tevent_req **psubreq)
    3297             : {
    3298             :         struct tevent_req *req, *subreq;
    3299             :         struct cli_smb1_close_state *state;
    3300             : 
    3301         210 :         req = tevent_req_create(mem_ctx, &state, struct cli_smb1_close_state);
    3302         210 :         if (req == NULL) {
    3303           0 :                 return NULL;
    3304             :         }
    3305             : 
    3306         210 :         SSVAL(state->vwv+0, 0, fnum);
    3307         210 :         SIVALS(state->vwv+1, 0, -1);
    3308             : 
    3309         210 :         subreq = cli_smb_req_create(state, ev, cli, SMBclose, 0, 0,
    3310         210 :                                 3, state->vwv, 0, NULL);
    3311         210 :         if (subreq == NULL) {
    3312           0 :                 TALLOC_FREE(req);
    3313           0 :                 return NULL;
    3314             :         }
    3315         210 :         tevent_req_set_callback(subreq, cli_smb1_close_done, req);
    3316         210 :         *psubreq = subreq;
    3317         210 :         return req;
    3318             : }
    3319             : 
    3320         210 : static void cli_smb1_close_done(struct tevent_req *subreq)
    3321             : {
    3322         210 :         struct tevent_req *req = tevent_req_callback_data(
    3323             :                 subreq, struct tevent_req);
    3324             :         NTSTATUS status;
    3325             : 
    3326         210 :         status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
    3327         210 :         TALLOC_FREE(subreq);
    3328         210 :         if (tevent_req_nterror(req, status)) {
    3329           5 :                 return;
    3330             :         }
    3331         205 :         tevent_req_done(req);
    3332             : }
    3333             : 
    3334             : struct cli_close_state {
    3335             :         int dummy;
    3336             : };
    3337             : 
    3338             : static void cli_close_done(struct tevent_req *subreq);
    3339             : 
    3340        4081 : struct tevent_req *cli_close_send(TALLOC_CTX *mem_ctx,
    3341             :                                 struct tevent_context *ev,
    3342             :                                 struct cli_state *cli,
    3343             :                                 uint16_t fnum)
    3344             : {
    3345             :         struct tevent_req *req, *subreq;
    3346             :         struct cli_close_state *state;
    3347             :         NTSTATUS status;
    3348             : 
    3349        4081 :         req = tevent_req_create(mem_ctx, &state, struct cli_close_state);
    3350        4081 :         if (req == NULL) {
    3351           0 :                 return NULL;
    3352             :         }
    3353             : 
    3354        4081 :         if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
    3355        3873 :                 subreq = cli_smb2_close_fnum_send(state,
    3356             :                                                 ev,
    3357             :                                                 cli,
    3358             :                                                 fnum);
    3359        3873 :                 if (tevent_req_nomem(subreq, req)) {
    3360           0 :                         return tevent_req_post(req, ev);
    3361             :                 }
    3362             :         } else {
    3363         208 :                 struct tevent_req *ch_req = NULL;
    3364         208 :                 subreq = cli_smb1_close_create(state, ev, cli, fnum, &ch_req);
    3365         208 :                 if (tevent_req_nomem(subreq, req)) {
    3366           0 :                         return tevent_req_post(req, ev);
    3367             :                 }
    3368         208 :                 status = smb1cli_req_chain_submit(&ch_req, 1);
    3369         208 :                 if (tevent_req_nterror(req, status)) {
    3370           0 :                         return tevent_req_post(req, ev);
    3371             :                 }
    3372             :         }
    3373             : 
    3374        4081 :         tevent_req_set_callback(subreq, cli_close_done, req);
    3375        4081 :         return req;
    3376             : }
    3377             : 
    3378        4081 : static void cli_close_done(struct tevent_req *subreq)
    3379             : {
    3380        4081 :         struct tevent_req *req = tevent_req_callback_data(
    3381             :                 subreq, struct tevent_req);
    3382        4081 :         NTSTATUS status = NT_STATUS_OK;
    3383        4081 :         bool err = tevent_req_is_nterror(subreq, &status);
    3384             : 
    3385        4081 :         TALLOC_FREE(subreq);
    3386        4081 :         if (err) {
    3387           5 :                 tevent_req_nterror(req, status);
    3388           5 :                 return;
    3389             :         }
    3390        4076 :         tevent_req_done(req);
    3391             : }
    3392             : 
    3393        4083 : NTSTATUS cli_close_recv(struct tevent_req *req)
    3394             : {
    3395        4083 :         return tevent_req_simple_recv_ntstatus(req);
    3396             : }
    3397             : 
    3398         341 : NTSTATUS cli_close(struct cli_state *cli, uint16_t fnum)
    3399             : {
    3400         341 :         TALLOC_CTX *frame = NULL;
    3401             :         struct tevent_context *ev;
    3402             :         struct tevent_req *req;
    3403         341 :         NTSTATUS status = NT_STATUS_OK;
    3404             : 
    3405         341 :         frame = talloc_stackframe();
    3406             : 
    3407         341 :         if (smbXcli_conn_has_async_calls(cli->conn)) {
    3408             :                 /*
    3409             :                  * Can't use sync call while an async call is in flight
    3410             :                  */
    3411           0 :                 status = NT_STATUS_INVALID_PARAMETER;
    3412           0 :                 goto fail;
    3413             :         }
    3414             : 
    3415         341 :         ev = samba_tevent_context_init(frame);
    3416         341 :         if (ev == NULL) {
    3417           0 :                 status = NT_STATUS_NO_MEMORY;
    3418           0 :                 goto fail;
    3419             :         }
    3420             : 
    3421         341 :         req = cli_close_send(frame, ev, cli, fnum);
    3422         341 :         if (req == NULL) {
    3423           0 :                 status = NT_STATUS_NO_MEMORY;
    3424           0 :                 goto fail;
    3425             :         }
    3426             : 
    3427         341 :         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
    3428           0 :                 goto fail;
    3429             :         }
    3430             : 
    3431         341 :         status = cli_close_recv(req);
    3432         341 :  fail:
    3433         341 :         TALLOC_FREE(frame);
    3434         341 :         return status;
    3435             : }
    3436             : 
    3437             : /****************************************************************************
    3438             :  Truncate a file to a specified size
    3439             : ****************************************************************************/
    3440             : 
    3441             : struct ftrunc_state {
    3442             :         uint8_t data[8];
    3443             : };
    3444             : 
    3445           0 : static void cli_ftruncate_done(struct tevent_req *subreq)
    3446             : {
    3447           0 :         NTSTATUS status = cli_setfileinfo_recv(subreq);
    3448           0 :         tevent_req_simple_finish_ntstatus(subreq, status);
    3449           0 : }
    3450             : 
    3451           0 : struct tevent_req *cli_ftruncate_send(TALLOC_CTX *mem_ctx,
    3452             :                                         struct tevent_context *ev,
    3453             :                                         struct cli_state *cli,
    3454             :                                         uint16_t fnum,
    3455             :                                         uint64_t size)
    3456             : {
    3457           0 :         struct tevent_req *req = NULL, *subreq = NULL;
    3458           0 :         struct ftrunc_state *state = NULL;
    3459             : 
    3460           0 :         req = tevent_req_create(mem_ctx, &state, struct ftrunc_state);
    3461           0 :         if (req == NULL) {
    3462           0 :                 return NULL;
    3463             :         }
    3464             : 
    3465             :         /* Setup data array. */
    3466           0 :         SBVAL(state->data, 0, size);
    3467             : 
    3468           0 :         subreq = cli_setfileinfo_send(
    3469             :                 state,
    3470             :                 ev,
    3471             :                 cli,
    3472             :                 fnum,
    3473             :                 SMB_SET_FILE_END_OF_FILE_INFO,
    3474           0 :                 state->data,
    3475             :                 sizeof(state->data));
    3476             : 
    3477           0 :         if (tevent_req_nomem(subreq, req)) {
    3478           0 :                 return tevent_req_post(req, ev);
    3479             :         }
    3480           0 :         tevent_req_set_callback(subreq, cli_ftruncate_done, req);
    3481           0 :         return req;
    3482             : }
    3483             : 
    3484           0 : NTSTATUS cli_ftruncate_recv(struct tevent_req *req)
    3485             : {
    3486           0 :         return tevent_req_simple_recv_ntstatus(req);
    3487             : }
    3488             : 
    3489          10 : NTSTATUS cli_ftruncate(struct cli_state *cli, uint16_t fnum, uint64_t size)
    3490             : {
    3491          10 :         TALLOC_CTX *frame = NULL;
    3492          10 :         struct tevent_context *ev = NULL;
    3493          10 :         struct tevent_req *req = NULL;
    3494          10 :         NTSTATUS status = NT_STATUS_OK;
    3495             : 
    3496          10 :         if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
    3497          10 :                 return cli_smb2_ftruncate(cli, fnum, size);
    3498             :         }
    3499             : 
    3500           0 :         frame = talloc_stackframe();
    3501             : 
    3502           0 :         if (smbXcli_conn_has_async_calls(cli->conn)) {
    3503             :                 /*
    3504             :                  * Can't use sync call while an async call is in flight
    3505             :                  */
    3506           0 :                 status = NT_STATUS_INVALID_PARAMETER;
    3507           0 :                 goto fail;
    3508             :         }
    3509             : 
    3510           0 :         ev = samba_tevent_context_init(frame);
    3511           0 :         if (ev == NULL) {
    3512           0 :                 status = NT_STATUS_NO_MEMORY;
    3513           0 :                 goto fail;
    3514             :         }
    3515             : 
    3516           0 :         req = cli_ftruncate_send(frame,
    3517             :                                 ev,
    3518             :                                 cli,
    3519             :                                 fnum,
    3520             :                                 size);
    3521           0 :         if (req == NULL) {
    3522           0 :                 status = NT_STATUS_NO_MEMORY;
    3523           0 :                 goto fail;
    3524             :         }
    3525             : 
    3526           0 :         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
    3527           0 :                 goto fail;
    3528             :         }
    3529             : 
    3530           0 :         status = cli_ftruncate_recv(req);
    3531             : 
    3532           0 :  fail:
    3533           0 :         TALLOC_FREE(frame);
    3534           0 :         return status;
    3535             : }
    3536             : 
    3537        1790 : static uint8_t *cli_lockingx_put_locks(
    3538             :         uint8_t *buf,
    3539             :         bool large,
    3540             :         uint16_t num_locks,
    3541             :         const struct smb1_lock_element *locks)
    3542             : {
    3543             :         uint16_t i;
    3544             : 
    3545        2683 :         for (i=0; i<num_locks; i++) {
    3546         893 :                 const struct smb1_lock_element *e = &locks[i];
    3547         893 :                 if (large) {
    3548           0 :                         SSVAL(buf, 0, e->pid);
    3549           0 :                         SSVAL(buf, 2, 0);
    3550           0 :                         SOFF_T_R(buf, 4, e->offset);
    3551           0 :                         SOFF_T_R(buf, 12, e->length);
    3552           0 :                         buf += 20;
    3553             :                 } else {
    3554         893 :                         SSVAL(buf, 0, e->pid);
    3555         893 :                         SIVAL(buf, 2, e->offset);
    3556         893 :                         SIVAL(buf, 6, e->length);
    3557         893 :                         buf += 10;
    3558             :                 }
    3559             :         }
    3560        1790 :         return buf;
    3561             : }
    3562             : 
    3563             : struct cli_lockingx_state {
    3564             :         uint16_t vwv[8];
    3565             :         struct iovec bytes;
    3566             :         struct tevent_req *subreq;
    3567             : };
    3568             : 
    3569             : static void cli_lockingx_done(struct tevent_req *subreq);
    3570             : static bool cli_lockingx_cancel(struct tevent_req *req);
    3571             : 
    3572         895 : struct tevent_req *cli_lockingx_create(
    3573             :         TALLOC_CTX *mem_ctx,
    3574             :         struct tevent_context *ev,
    3575             :         struct cli_state *cli,
    3576             :         uint16_t fnum,
    3577             :         uint8_t typeoflock,
    3578             :         uint8_t newoplocklevel,
    3579             :         int32_t timeout,
    3580             :         uint16_t num_unlocks,
    3581             :         const struct smb1_lock_element *unlocks,
    3582             :         uint16_t num_locks,
    3583             :         const struct smb1_lock_element *locks,
    3584             :         struct tevent_req **psmbreq)
    3585             : {
    3586         895 :         struct tevent_req *req = NULL, *subreq = NULL;
    3587         895 :         struct cli_lockingx_state *state = NULL;
    3588             :         uint16_t *vwv;
    3589             :         uint8_t *p;
    3590         895 :         const bool large = (typeoflock & LOCKING_ANDX_LARGE_FILES);
    3591         895 :         const size_t element_len = large ? 20 : 10;
    3592             : 
    3593             :         /* uint16->size_t, no overflow */
    3594         895 :         const size_t num_elements = (size_t)num_locks + (size_t)num_unlocks;
    3595             : 
    3596             :         /* at most 20*2*65535 = 2621400, no overflow */
    3597         895 :         const size_t num_bytes = num_elements * element_len;
    3598             : 
    3599         895 :         req = tevent_req_create(mem_ctx, &state, struct cli_lockingx_state);
    3600         895 :         if (req == NULL) {
    3601           0 :                 return NULL;
    3602             :         }
    3603         895 :         vwv = state->vwv;
    3604             : 
    3605         895 :         SCVAL(vwv + 0, 0, 0xFF);
    3606         895 :         SCVAL(vwv + 0, 1, 0);
    3607         895 :         SSVAL(vwv + 1, 0, 0);
    3608         895 :         SSVAL(vwv + 2, 0, fnum);
    3609         895 :         SCVAL(vwv + 3, 0, typeoflock);
    3610         895 :         SCVAL(vwv + 3, 1, newoplocklevel);
    3611         895 :         SIVALS(vwv + 4, 0, timeout);
    3612         895 :         SSVAL(vwv + 6, 0, num_unlocks);
    3613         895 :         SSVAL(vwv + 7, 0, num_locks);
    3614             : 
    3615         895 :         state->bytes.iov_len = num_bytes;
    3616         895 :         state->bytes.iov_base = talloc_array(state, uint8_t, num_bytes);
    3617         895 :         if (tevent_req_nomem(state->bytes.iov_base, req)) {
    3618           0 :                 return tevent_req_post(req, ev);
    3619             :         }
    3620             : 
    3621        1790 :         p = cli_lockingx_put_locks(
    3622         895 :                 state->bytes.iov_base, large, num_unlocks, unlocks);
    3623         895 :         cli_lockingx_put_locks(p, large, num_locks, locks);
    3624             : 
    3625         895 :         subreq = cli_smb_req_create(
    3626         895 :                 state, ev, cli, SMBlockingX, 0, 0, 8, vwv, 1, &state->bytes);
    3627         895 :         if (tevent_req_nomem(subreq, req)) {
    3628           0 :                 return tevent_req_post(req, ev);
    3629             :         }
    3630         895 :         tevent_req_set_callback(subreq, cli_lockingx_done, req);
    3631         895 :         *psmbreq = subreq;
    3632         895 :         return req;
    3633             : }
    3634             : 
    3635         893 : struct tevent_req *cli_lockingx_send(
    3636             :         TALLOC_CTX *mem_ctx,
    3637             :         struct tevent_context *ev,
    3638             :         struct cli_state *cli,
    3639             :         uint16_t fnum,
    3640             :         uint8_t typeoflock,
    3641             :         uint8_t newoplocklevel,
    3642             :         int32_t timeout,
    3643             :         uint16_t num_unlocks,
    3644             :         const struct smb1_lock_element *unlocks,
    3645             :         uint16_t num_locks,
    3646             :         const struct smb1_lock_element *locks)
    3647             : {
    3648         893 :         struct tevent_req *req = NULL, *subreq = NULL;
    3649         893 :         struct cli_lockingx_state *state = NULL;
    3650             :         NTSTATUS status;
    3651             : 
    3652         893 :         req = cli_lockingx_create(
    3653             :                 mem_ctx,
    3654             :                 ev,
    3655             :                 cli,
    3656             :                 fnum,
    3657             :                 typeoflock,
    3658             :                 newoplocklevel,
    3659             :                 timeout,
    3660             :                 num_unlocks,
    3661             :                 unlocks,
    3662             :                 num_locks,
    3663             :                 locks,
    3664             :                 &subreq);
    3665         893 :         if (req == NULL) {
    3666           0 :                 return NULL;
    3667             :         }
    3668         893 :         state = tevent_req_data(req, struct cli_lockingx_state);
    3669         893 :         state->subreq = subreq;
    3670             : 
    3671         893 :         status = smb1cli_req_chain_submit(&subreq, 1);
    3672         893 :         if (tevent_req_nterror(req, status)) {
    3673           0 :                 return tevent_req_post(req, ev);
    3674             :         }
    3675         893 :         tevent_req_set_cancel_fn(req, cli_lockingx_cancel);
    3676         893 :         return req;
    3677             : }
    3678             : 
    3679         895 : static void cli_lockingx_done(struct tevent_req *subreq)
    3680             : {
    3681         895 :         NTSTATUS status = cli_smb_recv(
    3682             :                 subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
    3683         895 :         tevent_req_simple_finish_ntstatus(subreq, status);
    3684         895 : }
    3685             : 
    3686           1 : static bool cli_lockingx_cancel(struct tevent_req *req)
    3687             : {
    3688           1 :         struct cli_lockingx_state *state = tevent_req_data(
    3689             :                 req, struct cli_lockingx_state);
    3690           1 :         if (state->subreq == NULL) {
    3691           0 :                 return false;
    3692             :         }
    3693           1 :         return tevent_req_cancel(state->subreq);
    3694             : }
    3695             : 
    3696         895 : NTSTATUS cli_lockingx_recv(struct tevent_req *req)
    3697             : {
    3698         895 :         return tevent_req_simple_recv_ntstatus(req);
    3699             : }
    3700             : 
    3701         669 : NTSTATUS cli_lockingx(
    3702             :         struct cli_state *cli,
    3703             :         uint16_t fnum,
    3704             :         uint8_t typeoflock,
    3705             :         uint8_t newoplocklevel,
    3706             :         int32_t timeout,
    3707             :         uint16_t num_unlocks,
    3708             :         const struct smb1_lock_element *unlocks,
    3709             :         uint16_t num_locks,
    3710             :         const struct smb1_lock_element *locks)
    3711             : {
    3712         669 :         TALLOC_CTX *frame = talloc_stackframe();
    3713         669 :         struct tevent_context *ev = NULL;
    3714         669 :         struct tevent_req *req = NULL;
    3715         669 :         NTSTATUS status = NT_STATUS_NO_MEMORY;
    3716         669 :         unsigned int set_timeout = 0;
    3717         669 :         unsigned int saved_timeout = 0;
    3718             : 
    3719         669 :         if (smbXcli_conn_has_async_calls(cli->conn)) {
    3720           0 :                 return NT_STATUS_INVALID_PARAMETER;
    3721             :         }
    3722         669 :         ev = samba_tevent_context_init(frame);
    3723         669 :         if (ev == NULL) {
    3724           0 :                 goto fail;
    3725             :         }
    3726             : 
    3727         669 :         if (timeout != 0) {
    3728           1 :                 if (timeout == -1) {
    3729           0 :                         set_timeout = 0x7FFFFFFF;
    3730             :                 } else {
    3731           1 :                         set_timeout = timeout + 2*1000;
    3732             :                 }
    3733           1 :                 saved_timeout = cli_set_timeout(cli, set_timeout);
    3734             :         }
    3735             : 
    3736         669 :         req = cli_lockingx_send(
    3737             :                 frame,
    3738             :                 ev,
    3739             :                 cli,
    3740             :                 fnum,
    3741             :                 typeoflock,
    3742             :                 newoplocklevel,
    3743             :                 timeout,
    3744             :                 num_unlocks,
    3745             :                 unlocks,
    3746             :                 num_locks,
    3747             :                 locks);
    3748         669 :         if (req == NULL) {
    3749           0 :                 goto fail;
    3750             :         }
    3751         669 :         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
    3752           0 :                 goto fail;
    3753             :         }
    3754         669 :         status = cli_lockingx_recv(req);
    3755             : 
    3756         669 :         if (saved_timeout != 0) {
    3757           1 :                 cli_set_timeout(cli, saved_timeout);
    3758             :         }
    3759        1337 : fail:
    3760         669 :         TALLOC_FREE(frame);
    3761         669 :         return status;
    3762             : }
    3763             : 
    3764             : /****************************************************************************
    3765             :  send a lock with a specified locktype
    3766             :  this is used for testing LOCKING_ANDX_CANCEL_LOCK
    3767             : ****************************************************************************/
    3768             : 
    3769         668 : NTSTATUS cli_locktype(struct cli_state *cli, uint16_t fnum,
    3770             :                       uint32_t offset, uint32_t len,
    3771             :                       int timeout, unsigned char locktype)
    3772             : {
    3773         668 :         struct smb1_lock_element lck = {
    3774         668 :                 .pid = cli_getpid(cli),
    3775             :                 .offset = offset,
    3776             :                 .length = len,
    3777             :         };
    3778             :         NTSTATUS status;
    3779             : 
    3780         668 :         status = cli_lockingx(
    3781             :                 cli,                            /* cli */
    3782             :                 fnum,                           /* fnum */
    3783             :                 locktype,                       /* typeoflock */
    3784             :                 0,                              /* newoplocklevel */
    3785             :                 timeout,                        /* timeout */
    3786             :                 0,                              /* num_unlocks */
    3787             :                 NULL,                           /* unlocks */
    3788             :                 1,                              /* num_locks */
    3789             :                 &lck);                              /* locks */
    3790         668 :         return status;
    3791             : }
    3792             : 
    3793             : /****************************************************************************
    3794             :  Lock a file.
    3795             :  note that timeout is in units of 2 milliseconds
    3796             : ****************************************************************************/
    3797             : 
    3798         663 : NTSTATUS cli_lock32(struct cli_state *cli, uint16_t fnum,
    3799             :                   uint32_t offset, uint32_t len, int timeout,
    3800             :                   enum brl_type lock_type)
    3801             : {
    3802             :         NTSTATUS status;
    3803             : 
    3804         663 :         status = cli_locktype(cli, fnum, offset, len, timeout,
    3805             :                               (lock_type == READ_LOCK? 1 : 0));
    3806         663 :         return status;
    3807             : }
    3808             : 
    3809             : /****************************************************************************
    3810             :  Unlock a file.
    3811             : ****************************************************************************/
    3812             : 
    3813             : struct cli_unlock_state {
    3814             :         struct smb1_lock_element lck;
    3815             : };
    3816             : 
    3817             : static void cli_unlock_done(struct tevent_req *subreq);
    3818             : 
    3819         222 : struct tevent_req *cli_unlock_send(TALLOC_CTX *mem_ctx,
    3820             :                                 struct tevent_context *ev,
    3821             :                                 struct cli_state *cli,
    3822             :                                 uint16_t fnum,
    3823             :                                 uint64_t offset,
    3824             :                                 uint64_t len)
    3825             : 
    3826             : {
    3827         222 :         struct tevent_req *req = NULL, *subreq = NULL;
    3828         222 :         struct cli_unlock_state *state = NULL;
    3829             : 
    3830         222 :         req = tevent_req_create(mem_ctx, &state, struct cli_unlock_state);
    3831         222 :         if (req == NULL) {
    3832           0 :                 return NULL;
    3833             :         }
    3834         444 :         state->lck = (struct smb1_lock_element) {
    3835         222 :                 .pid = cli_getpid(cli),
    3836             :                 .offset = offset,
    3837             :                 .length = len,
    3838             :         };
    3839             : 
    3840         222 :         subreq = cli_lockingx_send(
    3841             :                 state,                          /* mem_ctx */
    3842             :                 ev,                             /* tevent_context */
    3843             :                 cli,                            /* cli */
    3844             :                 fnum,                           /* fnum */
    3845             :                 0,                              /* typeoflock */
    3846             :                 0,                              /* newoplocklevel */
    3847             :                 0,                              /* timeout */
    3848             :                 1,                              /* num_unlocks */
    3849         222 :                 &state->lck,                     /* unlocks */
    3850             :                 0,                              /* num_locks */
    3851             :                 NULL);                          /* locks */
    3852         222 :         if (tevent_req_nomem(subreq, req)) {
    3853           0 :                 return tevent_req_post(req, ev);
    3854             :         }
    3855         222 :         tevent_req_set_callback(subreq, cli_unlock_done, req);
    3856         222 :         return req;
    3857             : }
    3858             : 
    3859         222 : static void cli_unlock_done(struct tevent_req *subreq)
    3860             : {
    3861         222 :         NTSTATUS status = cli_lockingx_recv(subreq);
    3862         222 :         tevent_req_simple_finish_ntstatus(subreq, status);
    3863         222 : }
    3864             : 
    3865         222 : NTSTATUS cli_unlock_recv(struct tevent_req *req)
    3866             : {
    3867         222 :         return tevent_req_simple_recv_ntstatus(req);
    3868             : }
    3869             : 
    3870         222 : NTSTATUS cli_unlock(struct cli_state *cli,
    3871             :                         uint16_t fnum,
    3872             :                         uint32_t offset,
    3873             :                         uint32_t len)
    3874             : {
    3875         222 :         TALLOC_CTX *frame = talloc_stackframe();
    3876             :         struct tevent_context *ev;
    3877             :         struct tevent_req *req;
    3878         222 :         NTSTATUS status = NT_STATUS_OK;
    3879             : 
    3880         222 :         if (smbXcli_conn_has_async_calls(cli->conn)) {
    3881             :                 /*
    3882             :                  * Can't use sync call while an async call is in flight
    3883             :                  */
    3884           0 :                 status = NT_STATUS_INVALID_PARAMETER;
    3885           0 :                 goto fail;
    3886             :         }
    3887             : 
    3888         222 :         ev = samba_tevent_context_init(frame);
    3889         222 :         if (ev == NULL) {
    3890           0 :                 status = NT_STATUS_NO_MEMORY;
    3891           0 :                 goto fail;
    3892             :         }
    3893             : 
    3894         222 :         req = cli_unlock_send(frame, ev, cli,
    3895             :                         fnum, offset, len);
    3896         222 :         if (req == NULL) {
    3897           0 :                 status = NT_STATUS_NO_MEMORY;
    3898           0 :                 goto fail;
    3899             :         }
    3900             : 
    3901         222 :         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
    3902           0 :                 goto fail;
    3903             :         }
    3904             : 
    3905         222 :         status = cli_unlock_recv(req);
    3906             : 
    3907         222 :  fail:
    3908         222 :         TALLOC_FREE(frame);
    3909         222 :         return status;
    3910             : }
    3911             : 
    3912             : /****************************************************************************
    3913             :  Get/unlock a POSIX lock on a file - internal function.
    3914             : ****************************************************************************/
    3915             : 
    3916             : struct posix_lock_state {
    3917             :         uint16_t setup;
    3918             :         uint8_t param[4];
    3919             :         uint8_t data[POSIX_LOCK_DATA_SIZE];
    3920             : };
    3921             : 
    3922           0 : static void cli_posix_unlock_internal_done(struct tevent_req *subreq)
    3923             : {
    3924           0 :         NTSTATUS status = cli_trans_recv(subreq, NULL, NULL, NULL, 0, NULL,
    3925             :                                          NULL, 0, NULL, NULL, 0, NULL);
    3926           0 :         tevent_req_simple_finish_ntstatus(subreq, status);
    3927           0 : }
    3928             : 
    3929           0 : static struct tevent_req *cli_posix_lock_internal_send(TALLOC_CTX *mem_ctx,
    3930             :                                         struct tevent_context *ev,
    3931             :                                         struct cli_state *cli,
    3932             :                                         uint16_t fnum,
    3933             :                                         uint64_t offset,
    3934             :                                         uint64_t len,
    3935             :                                         bool wait_lock,
    3936             :                                         enum brl_type lock_type)
    3937             : {
    3938           0 :         struct tevent_req *req = NULL, *subreq = NULL;
    3939           0 :         struct posix_lock_state *state = NULL;
    3940             : 
    3941           0 :         req = tevent_req_create(mem_ctx, &state, struct posix_lock_state);
    3942           0 :         if (req == NULL) {
    3943           0 :                 return NULL;
    3944             :         }
    3945             : 
    3946             :         /* Setup setup word. */
    3947           0 :         SSVAL(&state->setup, 0, TRANSACT2_SETFILEINFO);
    3948             : 
    3949             :         /* Setup param array. */
    3950           0 :         SSVAL(&state->param, 0, fnum);
    3951           0 :         SSVAL(&state->param, 2, SMB_SET_POSIX_LOCK);
    3952             : 
    3953             :         /* Setup data array. */
    3954           0 :         switch (lock_type) {
    3955           0 :                 case READ_LOCK:
    3956           0 :                         SSVAL(&state->data, POSIX_LOCK_TYPE_OFFSET,
    3957             :                                 POSIX_LOCK_TYPE_READ);
    3958           0 :                         break;
    3959           0 :                 case WRITE_LOCK:
    3960           0 :                         SSVAL(&state->data, POSIX_LOCK_TYPE_OFFSET,
    3961             :                                 POSIX_LOCK_TYPE_WRITE);
    3962           0 :                         break;
    3963           0 :                 case UNLOCK_LOCK:
    3964           0 :                         SSVAL(&state->data, POSIX_LOCK_TYPE_OFFSET,
    3965             :                                 POSIX_LOCK_TYPE_UNLOCK);
    3966           0 :                         break;
    3967           0 :                 default:
    3968           0 :                         return NULL;
    3969             :         }
    3970             : 
    3971           0 :         if (wait_lock) {
    3972           0 :                 SSVAL(&state->data, POSIX_LOCK_FLAGS_OFFSET,
    3973             :                                 POSIX_LOCK_FLAG_WAIT);
    3974             :         } else {
    3975           0 :                 SSVAL(state->data, POSIX_LOCK_FLAGS_OFFSET,
    3976             :                                 POSIX_LOCK_FLAG_NOWAIT);
    3977             :         }
    3978             : 
    3979           0 :         SIVAL(&state->data, POSIX_LOCK_PID_OFFSET, cli_getpid(cli));
    3980           0 :         SOFF_T(&state->data, POSIX_LOCK_START_OFFSET, offset);
    3981           0 :         SOFF_T(&state->data, POSIX_LOCK_LEN_OFFSET, len);
    3982             : 
    3983           0 :         subreq = cli_trans_send(state,                  /* mem ctx. */
    3984             :                                 ev,                     /* event ctx. */
    3985             :                                 cli,                    /* cli_state. */
    3986             :                                 0,                      /* additional_flags2 */
    3987             :                                 SMBtrans2,              /* cmd. */
    3988             :                                 NULL,                   /* pipe name. */
    3989             :                                 -1,                     /* fid. */
    3990             :                                 0,                      /* function. */
    3991             :                                 0,                      /* flags. */
    3992           0 :                                 &state->setup,          /* setup. */
    3993             :                                 1,                      /* num setup uint16_t words. */
    3994             :                                 0,                      /* max returned setup. */
    3995           0 :                                 state->param,           /* param. */
    3996             :                                 4,                      /* num param. */
    3997             :                                 2,                      /* max returned param. */
    3998           0 :                                 state->data,            /* data. */
    3999             :                                 POSIX_LOCK_DATA_SIZE,   /* num data. */
    4000             :                                 0);                     /* max returned data. */
    4001             : 
    4002           0 :         if (tevent_req_nomem(subreq, req)) {
    4003           0 :                 return tevent_req_post(req, ev);
    4004             :         }
    4005           0 :         tevent_req_set_callback(subreq, cli_posix_unlock_internal_done, req);
    4006           0 :         return req;
    4007             : }
    4008             : 
    4009             : /****************************************************************************
    4010             :  POSIX Lock a file.
    4011             : ****************************************************************************/
    4012             : 
    4013           0 : struct tevent_req *cli_posix_lock_send(TALLOC_CTX *mem_ctx,
    4014             :                                         struct tevent_context *ev,
    4015             :                                         struct cli_state *cli,
    4016             :                                         uint16_t fnum,
    4017             :                                         uint64_t offset,
    4018             :                                         uint64_t len,
    4019             :                                         bool wait_lock,
    4020             :                                         enum brl_type lock_type)
    4021             : {
    4022           0 :         return cli_posix_lock_internal_send(mem_ctx, ev, cli, fnum, offset, len,
    4023             :                                         wait_lock, lock_type);
    4024             : }
    4025             : 
    4026           0 : NTSTATUS cli_posix_lock_recv(struct tevent_req *req)
    4027             : {
    4028           0 :         return tevent_req_simple_recv_ntstatus(req);
    4029             : }
    4030             : 
    4031           0 : NTSTATUS cli_posix_lock(struct cli_state *cli, uint16_t fnum,
    4032             :                         uint64_t offset, uint64_t len,
    4033             :                         bool wait_lock, enum brl_type lock_type)
    4034             : {
    4035           0 :         TALLOC_CTX *frame = talloc_stackframe();
    4036           0 :         struct tevent_context *ev = NULL;
    4037           0 :         struct tevent_req *req = NULL;
    4038           0 :         NTSTATUS status = NT_STATUS_OK;
    4039             : 
    4040           0 :         if (smbXcli_conn_has_async_calls(cli->conn)) {
    4041             :                 /*
    4042             :                  * Can't use sync call while an async call is in flight
    4043             :                  */
    4044           0 :                 status = NT_STATUS_INVALID_PARAMETER;
    4045           0 :                 goto fail;
    4046             :         }
    4047             : 
    4048           0 :         if (lock_type != READ_LOCK && lock_type != WRITE_LOCK) {
    4049           0 :                 status = NT_STATUS_INVALID_PARAMETER;
    4050           0 :                 goto fail;
    4051             :         }
    4052             : 
    4053           0 :         ev = samba_tevent_context_init(frame);
    4054           0 :         if (ev == NULL) {
    4055           0 :                 status = NT_STATUS_NO_MEMORY;
    4056           0 :                 goto fail;
    4057             :         }
    4058             : 
    4059           0 :         req = cli_posix_lock_send(frame,
    4060             :                                 ev,
    4061             :                                 cli,
    4062             :                                 fnum,
    4063             :                                 offset,
    4064             :                                 len,
    4065             :                                 wait_lock,
    4066             :                                 lock_type);
    4067           0 :         if (req == NULL) {
    4068           0 :                 status = NT_STATUS_NO_MEMORY;
    4069           0 :                 goto fail;
    4070             :         }
    4071             : 
    4072           0 :         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
    4073           0 :                 goto fail;
    4074             :         }
    4075             : 
    4076           0 :         status = cli_posix_lock_recv(req);
    4077             : 
    4078           0 :  fail:
    4079           0 :         TALLOC_FREE(frame);
    4080           0 :         return status;
    4081             : }
    4082             : 
    4083             : /****************************************************************************
    4084             :  POSIX Unlock a file.
    4085             : ****************************************************************************/
    4086             : 
    4087           0 : struct tevent_req *cli_posix_unlock_send(TALLOC_CTX *mem_ctx,
    4088             :                                         struct tevent_context *ev,
    4089             :                                         struct cli_state *cli,
    4090             :                                         uint16_t fnum,
    4091             :                                         uint64_t offset,
    4092             :                                         uint64_t len)
    4093             : {
    4094           0 :         return cli_posix_lock_internal_send(mem_ctx, ev, cli, fnum, offset, len,
    4095             :                                         false, UNLOCK_LOCK);
    4096             : }
    4097             : 
    4098           0 : NTSTATUS cli_posix_unlock_recv(struct tevent_req *req)
    4099             : {
    4100           0 :         return tevent_req_simple_recv_ntstatus(req);
    4101             : }
    4102             : 
    4103           0 : NTSTATUS cli_posix_unlock(struct cli_state *cli, uint16_t fnum, uint64_t offset, uint64_t len)
    4104             : {
    4105           0 :         TALLOC_CTX *frame = talloc_stackframe();
    4106           0 :         struct tevent_context *ev = NULL;
    4107           0 :         struct tevent_req *req = NULL;
    4108           0 :         NTSTATUS status = NT_STATUS_OK;
    4109             : 
    4110           0 :         if (smbXcli_conn_has_async_calls(cli->conn)) {
    4111             :                 /*
    4112             :                  * Can't use sync call while an async call is in flight
    4113             :                  */
    4114           0 :                 status = NT_STATUS_INVALID_PARAMETER;
    4115           0 :                 goto fail;
    4116             :         }
    4117             : 
    4118           0 :         ev = samba_tevent_context_init(frame);
    4119           0 :         if (ev == NULL) {
    4120           0 :                 status = NT_STATUS_NO_MEMORY;
    4121           0 :                 goto fail;
    4122             :         }
    4123             : 
    4124           0 :         req = cli_posix_unlock_send(frame,
    4125             :                                 ev,
    4126             :                                 cli,
    4127             :                                 fnum,
    4128             :                                 offset,
    4129             :                                 len);
    4130           0 :         if (req == NULL) {
    4131           0 :                 status = NT_STATUS_NO_MEMORY;
    4132           0 :                 goto fail;
    4133             :         }
    4134             : 
    4135           0 :         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
    4136           0 :                 goto fail;
    4137             :         }
    4138             : 
    4139           0 :         status = cli_posix_unlock_recv(req);
    4140             : 
    4141           0 :  fail:
    4142           0 :         TALLOC_FREE(frame);
    4143           0 :         return status;
    4144             : }
    4145             : 
    4146             : /****************************************************************************
    4147             :  Do a SMBgetattrE call.
    4148             : ****************************************************************************/
    4149             : 
    4150             : static void cli_getattrE_done(struct tevent_req *subreq);
    4151             : 
    4152             : struct cli_getattrE_state {
    4153             :         uint16_t vwv[1];
    4154             :         int zone_offset;
    4155             :         uint32_t attr;
    4156             :         off_t size;
    4157             :         time_t change_time;
    4158             :         time_t access_time;
    4159             :         time_t write_time;
    4160             : };
    4161             : 
    4162           0 : struct tevent_req *cli_getattrE_send(TALLOC_CTX *mem_ctx,
    4163             :                                 struct tevent_context *ev,
    4164             :                                 struct cli_state *cli,
    4165             :                                 uint16_t fnum)
    4166             : {
    4167           0 :         struct tevent_req *req = NULL, *subreq = NULL;
    4168           0 :         struct cli_getattrE_state *state = NULL;
    4169           0 :         uint8_t additional_flags = 0;
    4170             : 
    4171           0 :         req = tevent_req_create(mem_ctx, &state, struct cli_getattrE_state);
    4172           0 :         if (req == NULL) {
    4173           0 :                 return NULL;
    4174             :         }
    4175             : 
    4176           0 :         state->zone_offset = smb1cli_conn_server_time_zone(cli->conn);
    4177           0 :         SSVAL(state->vwv+0,0,fnum);
    4178             : 
    4179           0 :         subreq = cli_smb_send(state, ev, cli, SMBgetattrE, additional_flags, 0,
    4180           0 :                               1, state->vwv, 0, NULL);
    4181           0 :         if (tevent_req_nomem(subreq, req)) {
    4182           0 :                 return tevent_req_post(req, ev);
    4183             :         }
    4184           0 :         tevent_req_set_callback(subreq, cli_getattrE_done, req);
    4185           0 :         return req;
    4186             : }
    4187             : 
    4188           0 : static void cli_getattrE_done(struct tevent_req *subreq)
    4189             : {
    4190           0 :         struct tevent_req *req = tevent_req_callback_data(
    4191             :                 subreq, struct tevent_req);
    4192           0 :         struct cli_getattrE_state *state = tevent_req_data(
    4193             :                 req, struct cli_getattrE_state);
    4194             :         uint8_t wct;
    4195           0 :         uint16_t *vwv = NULL;
    4196             :         NTSTATUS status;
    4197             : 
    4198           0 :         status = cli_smb_recv(subreq, state, NULL, 11, &wct, &vwv,
    4199             :                               NULL, NULL);
    4200           0 :         TALLOC_FREE(subreq);
    4201           0 :         if (tevent_req_nterror(req, status)) {
    4202           0 :                 return;
    4203             :         }
    4204             : 
    4205           0 :         state->size = (off_t)IVAL(vwv+6,0);
    4206           0 :         state->attr = SVAL(vwv+10,0);
    4207           0 :         state->change_time = make_unix_date2(vwv+0, state->zone_offset);
    4208           0 :         state->access_time = make_unix_date2(vwv+2, state->zone_offset);
    4209           0 :         state->write_time = make_unix_date2(vwv+4, state->zone_offset);
    4210             : 
    4211           0 :         tevent_req_done(req);
    4212             : }
    4213             : 
    4214           0 : NTSTATUS cli_getattrE_recv(struct tevent_req *req,
    4215             :                         uint32_t *pattr,
    4216             :                         off_t *size,
    4217             :                         time_t *change_time,
    4218             :                         time_t *access_time,
    4219             :                         time_t *write_time)
    4220             : {
    4221           0 :         struct cli_getattrE_state *state = tevent_req_data(
    4222             :                                 req, struct cli_getattrE_state);
    4223             :         NTSTATUS status;
    4224             : 
    4225           0 :         if (tevent_req_is_nterror(req, &status)) {
    4226           0 :                 return status;
    4227             :         }
    4228           0 :         if (pattr) {
    4229           0 :                 *pattr = state->attr;
    4230             :         }
    4231           0 :         if (size) {
    4232           0 :                 *size = state->size;
    4233             :         }
    4234           0 :         if (change_time) {
    4235           0 :                 *change_time = state->change_time;
    4236             :         }
    4237           0 :         if (access_time) {
    4238           0 :                 *access_time = state->access_time;
    4239             :         }
    4240           0 :         if (write_time) {
    4241           0 :                 *write_time = state->write_time;
    4242             :         }
    4243           0 :         return NT_STATUS_OK;
    4244             : }
    4245             : 
    4246             : /****************************************************************************
    4247             :  Do a SMBgetatr call
    4248             : ****************************************************************************/
    4249             : 
    4250             : static void cli_getatr_done(struct tevent_req *subreq);
    4251             : 
    4252             : struct cli_getatr_state {
    4253             :         int zone_offset;
    4254             :         uint32_t attr;
    4255             :         off_t size;
    4256             :         time_t write_time;
    4257             : };
    4258             : 
    4259           9 : struct tevent_req *cli_getatr_send(TALLOC_CTX *mem_ctx,
    4260             :                                 struct tevent_context *ev,
    4261             :                                 struct cli_state *cli,
    4262             :                                 const char *fname)
    4263             : {
    4264           9 :         struct tevent_req *req = NULL, *subreq = NULL;
    4265           9 :         struct cli_getatr_state *state = NULL;
    4266           9 :         uint8_t additional_flags = 0;
    4267           9 :         uint16_t additional_flags2 = 0;
    4268           9 :         uint8_t *bytes = NULL;
    4269             : 
    4270           9 :         req = tevent_req_create(mem_ctx, &state, struct cli_getatr_state);
    4271           9 :         if (req == NULL) {
    4272           0 :                 return NULL;
    4273             :         }
    4274             : 
    4275           9 :         state->zone_offset = smb1cli_conn_server_time_zone(cli->conn);
    4276             : 
    4277           9 :         bytes = talloc_array(state, uint8_t, 1);
    4278           9 :         if (tevent_req_nomem(bytes, req)) {
    4279           0 :                 return tevent_req_post(req, ev);
    4280             :         }
    4281           9 :         bytes[0] = 4;
    4282           9 :         bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), fname,
    4283           9 :                                    strlen(fname)+1, NULL);
    4284             : 
    4285           9 :         if (tevent_req_nomem(bytes, req)) {
    4286           0 :                 return tevent_req_post(req, ev);
    4287             :         }
    4288             : 
    4289           9 :         if (clistr_is_previous_version_path(fname, NULL, NULL, NULL)) {
    4290           0 :                 additional_flags2 = FLAGS2_REPARSE_PATH;
    4291             :         }
    4292             : 
    4293           9 :         subreq = cli_smb_send(state, ev, cli, SMBgetatr, additional_flags,
    4294             :                         additional_flags2,
    4295           9 :                         0, NULL, talloc_get_size(bytes), bytes);
    4296           9 :         if (tevent_req_nomem(subreq, req)) {
    4297           0 :                 return tevent_req_post(req, ev);
    4298             :         }
    4299           9 :         tevent_req_set_callback(subreq, cli_getatr_done, req);
    4300           9 :         return req;
    4301             : }
    4302             : 
    4303           9 : static void cli_getatr_done(struct tevent_req *subreq)
    4304             : {
    4305           9 :         struct tevent_req *req = tevent_req_callback_data(
    4306             :                 subreq, struct tevent_req);
    4307           9 :         struct cli_getatr_state *state = tevent_req_data(
    4308             :                 req, struct cli_getatr_state);
    4309             :         uint8_t wct;
    4310           9 :         uint16_t *vwv = NULL;
    4311             :         NTSTATUS status;
    4312             : 
    4313           9 :         status = cli_smb_recv(subreq, state, NULL, 4, &wct, &vwv, NULL,
    4314             :                               NULL);
    4315           9 :         TALLOC_FREE(subreq);
    4316           9 :         if (tevent_req_nterror(req, status)) {
    4317           0 :                 return;
    4318             :         }
    4319             : 
    4320           9 :         state->attr = SVAL(vwv+0,0);
    4321           9 :         state->size = (off_t)IVAL(vwv+3,0);
    4322           9 :         state->write_time = make_unix_date3(vwv+1, state->zone_offset);
    4323             : 
    4324           9 :         tevent_req_done(req);
    4325             : }
    4326             : 
    4327           9 : NTSTATUS cli_getatr_recv(struct tevent_req *req,
    4328             :                         uint32_t *pattr,
    4329             :                         off_t *size,
    4330             :                         time_t *write_time)
    4331             : {
    4332           9 :         struct cli_getatr_state *state = tevent_req_data(
    4333             :                                 req, struct cli_getatr_state);
    4334             :         NTSTATUS status;
    4335             : 
    4336           9 :         if (tevent_req_is_nterror(req, &status)) {
    4337           0 :                 return status;
    4338             :         }
    4339           9 :         if (pattr) {
    4340           5 :                 *pattr = state->attr;
    4341             :         }
    4342           9 :         if (size) {
    4343           2 :                 *size = state->size;
    4344             :         }
    4345           9 :         if (write_time) {
    4346           2 :                 *write_time = state->write_time;
    4347             :         }
    4348           9 :         return NT_STATUS_OK;
    4349             : }
    4350             : 
    4351          65 : NTSTATUS cli_getatr(struct cli_state *cli,
    4352             :                         const char *fname,
    4353             :                         uint32_t *pattr,
    4354             :                         off_t *size,
    4355             :                         time_t *write_time)
    4356             : {
    4357          65 :         TALLOC_CTX *frame = NULL;
    4358          65 :         struct tevent_context *ev = NULL;
    4359          65 :         struct tevent_req *req = NULL;
    4360          65 :         NTSTATUS status = NT_STATUS_OK;
    4361             : 
    4362          65 :         if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
    4363          56 :                 return cli_smb2_getatr(cli,
    4364             :                                         fname,
    4365             :                                         pattr,
    4366             :                                         size,
    4367             :                                         write_time);
    4368             :         }
    4369             : 
    4370           9 :         frame = talloc_stackframe();
    4371             : 
    4372           9 :         if (smbXcli_conn_has_async_calls(cli->conn)) {
    4373             :                 /*
    4374             :                  * Can't use sync call while an async call is in flight
    4375             :                  */
    4376           0 :                 status = NT_STATUS_INVALID_PARAMETER;
    4377           0 :                 goto fail;
    4378             :         }
    4379             : 
    4380           9 :         ev = samba_tevent_context_init(frame);
    4381           9 :         if (ev == NULL) {
    4382           0 :                 status = NT_STATUS_NO_MEMORY;
    4383           0 :                 goto fail;
    4384             :         }
    4385             : 
    4386           9 :         req = cli_getatr_send(frame, ev, cli, fname);
    4387           9 :         if (req == NULL) {
    4388           0 :                 status = NT_STATUS_NO_MEMORY;
    4389           0 :                 goto fail;
    4390             :         }
    4391             : 
    4392           9 :         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
    4393           0 :                 goto fail;
    4394             :         }
    4395             : 
    4396           9 :         status = cli_getatr_recv(req,
    4397             :                                 pattr,
    4398             :                                 size,
    4399             :                                 write_time);
    4400             : 
    4401           9 :  fail:
    4402           9 :         TALLOC_FREE(frame);
    4403           9 :         return status;
    4404             : }
    4405             : 
    4406             : /****************************************************************************
    4407             :  Do a SMBsetattrE call.
    4408             : ****************************************************************************/
    4409             : 
    4410             : static void cli_setattrE_done(struct tevent_req *subreq);
    4411             : 
    4412             : struct cli_setattrE_state {
    4413             :         uint16_t vwv[7];
    4414             : };
    4415             : 
    4416           0 : struct tevent_req *cli_setattrE_send(TALLOC_CTX *mem_ctx,
    4417             :                                 struct tevent_context *ev,
    4418             :                                 struct cli_state *cli,
    4419             :                                 uint16_t fnum,
    4420             :                                 time_t change_time,
    4421             :                                 time_t access_time,
    4422             :                                 time_t write_time)
    4423             : {
    4424           0 :         struct tevent_req *req = NULL, *subreq = NULL;
    4425           0 :         struct cli_setattrE_state *state = NULL;
    4426           0 :         uint8_t additional_flags = 0;
    4427             : 
    4428           0 :         req = tevent_req_create(mem_ctx, &state, struct cli_setattrE_state);
    4429           0 :         if (req == NULL) {
    4430           0 :                 return NULL;
    4431             :         }
    4432             : 
    4433           0 :         SSVAL(state->vwv+0, 0, fnum);
    4434           0 :         push_dos_date2((uint8_t *)&state->vwv[1], 0, change_time,
    4435             :                        smb1cli_conn_server_time_zone(cli->conn));
    4436           0 :         push_dos_date2((uint8_t *)&state->vwv[3], 0, access_time,
    4437             :                        smb1cli_conn_server_time_zone(cli->conn));
    4438           0 :         push_dos_date2((uint8_t *)&state->vwv[5], 0, write_time,
    4439             :                        smb1cli_conn_server_time_zone(cli->conn));
    4440             : 
    4441           0 :         subreq = cli_smb_send(state, ev, cli, SMBsetattrE, additional_flags, 0,
    4442           0 :                               7, state->vwv, 0, NULL);
    4443           0 :         if (tevent_req_nomem(subreq, req)) {
    4444           0 :                 return tevent_req_post(req, ev);
    4445             :         }
    4446           0 :         tevent_req_set_callback(subreq, cli_setattrE_done, req);
    4447           0 :         return req;
    4448             : }
    4449             : 
    4450           0 : static void cli_setattrE_done(struct tevent_req *subreq)
    4451             : {
    4452           0 :         struct tevent_req *req = tevent_req_callback_data(
    4453             :                 subreq, struct tevent_req);
    4454             :         NTSTATUS status;
    4455             : 
    4456           0 :         status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
    4457           0 :         TALLOC_FREE(subreq);
    4458           0 :         if (tevent_req_nterror(req, status)) {
    4459           0 :                 return;
    4460             :         }
    4461           0 :         tevent_req_done(req);
    4462             : }
    4463             : 
    4464           0 : NTSTATUS cli_setattrE_recv(struct tevent_req *req)
    4465             : {
    4466           0 :         return tevent_req_simple_recv_ntstatus(req);
    4467             : }
    4468             : 
    4469           0 : NTSTATUS cli_setattrE(struct cli_state *cli,
    4470             :                         uint16_t fnum,
    4471             :                         time_t change_time,
    4472             :                         time_t access_time,
    4473             :                         time_t write_time)
    4474             : {
    4475           0 :         TALLOC_CTX *frame = NULL;
    4476           0 :         struct tevent_context *ev = NULL;
    4477           0 :         struct tevent_req *req = NULL;
    4478           0 :         NTSTATUS status = NT_STATUS_OK;
    4479             : 
    4480           0 :         if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
    4481           0 :                 return cli_smb2_setattrE(cli,
    4482             :                                         fnum,
    4483             :                                         change_time,
    4484             :                                         access_time,
    4485             :                                         write_time);
    4486             :         }
    4487             : 
    4488           0 :         frame = talloc_stackframe();
    4489             : 
    4490           0 :         if (smbXcli_conn_has_async_calls(cli->conn)) {
    4491             :                 /*
    4492             :                  * Can't use sync call while an async call is in flight
    4493             :                  */
    4494           0 :                 status = NT_STATUS_INVALID_PARAMETER;
    4495           0 :                 goto fail;
    4496             :         }
    4497             : 
    4498           0 :         ev = samba_tevent_context_init(frame);
    4499           0 :         if (ev == NULL) {
    4500           0 :                 status = NT_STATUS_NO_MEMORY;
    4501           0 :                 goto fail;
    4502             :         }
    4503             : 
    4504           0 :         req = cli_setattrE_send(frame, ev,
    4505             :                         cli,
    4506             :                         fnum,
    4507             :                         change_time,
    4508             :                         access_time,
    4509             :                         write_time);
    4510             : 
    4511           0 :         if (req == NULL) {
    4512           0 :                 status = NT_STATUS_NO_MEMORY;
    4513           0 :                 goto fail;
    4514             :         }
    4515             : 
    4516           0 :         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
    4517           0 :                 goto fail;
    4518             :         }
    4519             : 
    4520           0 :         status = cli_setattrE_recv(req);
    4521             : 
    4522           0 :  fail:
    4523           0 :         TALLOC_FREE(frame);
    4524           0 :         return status;
    4525             : }
    4526             : 
    4527             : /****************************************************************************
    4528             :  Do a SMBsetatr call.
    4529             : ****************************************************************************/
    4530             : 
    4531             : static void cli_setatr_done(struct tevent_req *subreq);
    4532             : 
    4533             : struct cli_setatr_state {
    4534             :         uint16_t vwv[8];
    4535             : };
    4536             : 
    4537          18 : struct tevent_req *cli_setatr_send(TALLOC_CTX *mem_ctx,
    4538             :                                 struct tevent_context *ev,
    4539             :                                 struct cli_state *cli,
    4540             :                                 const char *fname,
    4541             :                                 uint32_t attr,
    4542             :                                 time_t mtime)
    4543             : {
    4544          18 :         struct tevent_req *req = NULL, *subreq = NULL;
    4545          18 :         struct cli_setatr_state *state = NULL;
    4546          18 :         uint8_t additional_flags = 0;
    4547          18 :         uint16_t additional_flags2 = 0;
    4548          18 :         uint8_t *bytes = NULL;
    4549             : 
    4550          18 :         req = tevent_req_create(mem_ctx, &state, struct cli_setatr_state);
    4551          18 :         if (req == NULL) {
    4552           0 :                 return NULL;
    4553             :         }
    4554             : 
    4555          18 :         if (attr & 0xFFFF0000) {
    4556             :                 /*
    4557             :                  * Don't allow attributes greater than
    4558             :                  * 16-bits for a 16-bit protocol value.
    4559             :                  */
    4560           1 :                 if (tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER)) {
    4561           1 :                         return tevent_req_post(req, ev);
    4562             :                 }
    4563             :         }
    4564             : 
    4565          17 :         SSVAL(state->vwv+0, 0, attr);
    4566          17 :         push_dos_date3((uint8_t *)&state->vwv[1], 0, mtime, smb1cli_conn_server_time_zone(cli->conn));
    4567             : 
    4568          17 :         bytes = talloc_array(state, uint8_t, 1);
    4569          17 :         if (tevent_req_nomem(bytes, req)) {
    4570           0 :                 return tevent_req_post(req, ev);
    4571             :         }
    4572          17 :         bytes[0] = 4;
    4573          17 :         bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), fname,
    4574          17 :                                    strlen(fname)+1, NULL);
    4575          17 :         if (tevent_req_nomem(bytes, req)) {
    4576           0 :                 return tevent_req_post(req, ev);
    4577             :         }
    4578          17 :         bytes = talloc_realloc(state, bytes, uint8_t,
    4579             :                         talloc_get_size(bytes)+1);
    4580          17 :         if (tevent_req_nomem(bytes, req)) {
    4581           0 :                 return tevent_req_post(req, ev);
    4582             :         }
    4583             : 
    4584          17 :         bytes[talloc_get_size(bytes)-1] = 4;
    4585          17 :         bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "",
    4586             :                                    1, NULL);
    4587          17 :         if (tevent_req_nomem(bytes, req)) {
    4588           0 :                 return tevent_req_post(req, ev);
    4589             :         }
    4590             : 
    4591          17 :         if (clistr_is_previous_version_path(fname, NULL, NULL, NULL)) {
    4592           0 :                 additional_flags2 = FLAGS2_REPARSE_PATH;
    4593             :         }
    4594             : 
    4595          34 :         subreq = cli_smb_send(state, ev, cli, SMBsetatr, additional_flags,
    4596             :                         additional_flags2,
    4597          34 :                         8, state->vwv, talloc_get_size(bytes), bytes);
    4598          17 :         if (tevent_req_nomem(subreq, req)) {
    4599           0 :                 return tevent_req_post(req, ev);
    4600             :         }
    4601          17 :         tevent_req_set_callback(subreq, cli_setatr_done, req);
    4602          17 :         return req;
    4603             : }
    4604             : 
    4605          17 : static void cli_setatr_done(struct tevent_req *subreq)
    4606             : {
    4607          17 :         struct tevent_req *req = tevent_req_callback_data(
    4608             :                 subreq, struct tevent_req);
    4609             :         NTSTATUS status;
    4610             : 
    4611          17 :         status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
    4612          17 :         TALLOC_FREE(subreq);
    4613          17 :         if (tevent_req_nterror(req, status)) {
    4614          10 :                 return;
    4615             :         }
    4616           7 :         tevent_req_done(req);
    4617             : }
    4618             : 
    4619          18 : NTSTATUS cli_setatr_recv(struct tevent_req *req)
    4620             : {
    4621          18 :         return tevent_req_simple_recv_ntstatus(req);
    4622             : }
    4623             : 
    4624          76 : NTSTATUS cli_setatr(struct cli_state *cli,
    4625             :                 const char *fname,
    4626             :                 uint32_t attr,
    4627             :                 time_t mtime)
    4628             : {
    4629          76 :         TALLOC_CTX *frame = NULL;
    4630          76 :         struct tevent_context *ev = NULL;
    4631          76 :         struct tevent_req *req = NULL;
    4632          76 :         NTSTATUS status = NT_STATUS_OK;
    4633             : 
    4634          76 :         if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
    4635          58 :                 return cli_smb2_setatr(cli,
    4636             :                                         fname,
    4637             :                                         attr,
    4638             :                                         mtime);
    4639             :         }
    4640             : 
    4641          18 :         frame = talloc_stackframe();
    4642             : 
    4643          18 :         if (smbXcli_conn_has_async_calls(cli->conn)) {
    4644             :                 /*
    4645             :                  * Can't use sync call while an async call is in flight
    4646             :                  */
    4647           0 :                 status = NT_STATUS_INVALID_PARAMETER;
    4648           0 :                 goto fail;
    4649             :         }
    4650             : 
    4651          18 :         ev = samba_tevent_context_init(frame);
    4652          18 :         if (ev == NULL) {
    4653           0 :                 status = NT_STATUS_NO_MEMORY;
    4654           0 :                 goto fail;
    4655             :         }
    4656             : 
    4657          18 :         req = cli_setatr_send(frame, ev, cli, fname, attr, mtime);
    4658          18 :         if (req == NULL) {
    4659           0 :                 status = NT_STATUS_NO_MEMORY;
    4660           0 :                 goto fail;
    4661             :         }
    4662             : 
    4663          18 :         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
    4664           0 :                 goto fail;
    4665             :         }
    4666             : 
    4667          18 :         status = cli_setatr_recv(req);
    4668             : 
    4669          18 :  fail:
    4670          18 :         TALLOC_FREE(frame);
    4671          18 :         return status;
    4672             : }
    4673             : 
    4674             : /****************************************************************************
    4675             :  Check for existence of a dir.
    4676             : ****************************************************************************/
    4677             : 
    4678             : static void cli_chkpath_done(struct tevent_req *subreq);
    4679             : static void cli_chkpath_opened(struct tevent_req *subreq);
    4680             : static void cli_chkpath_closed(struct tevent_req *subreq);
    4681             : 
    4682             : struct cli_chkpath_state {
    4683             :         struct tevent_context *ev;
    4684             :         struct cli_state *cli;
    4685             : };
    4686             : 
    4687        2977 : struct tevent_req *cli_chkpath_send(TALLOC_CTX *mem_ctx,
    4688             :                                   struct tevent_context *ev,
    4689             :                                   struct cli_state *cli,
    4690             :                                   const char *fname)
    4691             : {
    4692        2977 :         struct tevent_req *req = NULL, *subreq = NULL;
    4693        2977 :         struct cli_chkpath_state *state = NULL;
    4694        2977 :         uint8_t additional_flags = 0;
    4695        2977 :         uint16_t additional_flags2 = 0;
    4696        2977 :         uint8_t *bytes = NULL;
    4697             : 
    4698        2977 :         req = tevent_req_create(mem_ctx, &state, struct cli_chkpath_state);
    4699        2977 :         if (req == NULL) {
    4700           0 :                 return NULL;
    4701             :         }
    4702        2977 :         state->ev = ev;
    4703        2977 :         state->cli = cli;
    4704             : 
    4705        2977 :         if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_NT1) {
    4706        5916 :                 subreq = cli_ntcreate_send(
    4707             :                         state,                    /* mem_ctx */
    4708        2977 :                         state->ev,             /* ev */
    4709        2977 :                         state->cli,            /* cli */
    4710             :                         fname,                    /* fname */
    4711             :                         0,                        /* create_flags */
    4712             :                         FILE_READ_ATTRIBUTES,     /* desired_access */
    4713             :                         FILE_ATTRIBUTE_DIRECTORY, /* FileAttributes */
    4714             :                         FILE_SHARE_READ|
    4715             :                         FILE_SHARE_WRITE|
    4716             :                         FILE_SHARE_DELETE, /* share_access */
    4717             :                         FILE_OPEN,      /* CreateDisposition */
    4718             :                         FILE_DIRECTORY_FILE, /* CreateOptions */
    4719             :                         SMB2_IMPERSONATION_IMPERSONATION,
    4720             :                         0);             /* SecurityFlags */
    4721        2977 :                 if (tevent_req_nomem(subreq, req)) {
    4722           0 :                         return tevent_req_post(req, ev);
    4723             :                 }
    4724        2977 :                 tevent_req_set_callback(subreq, cli_chkpath_opened, req);
    4725        2977 :                 return req;
    4726             :         }
    4727             : 
    4728           0 :         bytes = talloc_array(state, uint8_t, 1);
    4729           0 :         if (tevent_req_nomem(bytes, req)) {
    4730           0 :                 return tevent_req_post(req, ev);
    4731             :         }
    4732           0 :         bytes[0] = 4;
    4733           0 :         bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), fname,
    4734           0 :                                    strlen(fname)+1, NULL);
    4735             : 
    4736           0 :         if (tevent_req_nomem(bytes, req)) {
    4737           0 :                 return tevent_req_post(req, ev);
    4738             :         }
    4739             : 
    4740           0 :         if (clistr_is_previous_version_path(fname, NULL, NULL, NULL)) {
    4741           0 :                 additional_flags2 = FLAGS2_REPARSE_PATH;
    4742             :         }
    4743             : 
    4744           0 :         subreq = cli_smb_send(state, ev, cli, SMBcheckpath, additional_flags,
    4745             :                         additional_flags2,
    4746           0 :                         0, NULL, talloc_get_size(bytes), bytes);
    4747           0 :         if (tevent_req_nomem(subreq, req)) {
    4748           0 :                 return tevent_req_post(req, ev);
    4749             :         }
    4750           0 :         tevent_req_set_callback(subreq, cli_chkpath_done, req);
    4751           0 :         return req;
    4752             : }
    4753             : 
    4754           0 : static void cli_chkpath_done(struct tevent_req *subreq)
    4755             : {
    4756           0 :         NTSTATUS status = cli_smb_recv(
    4757             :                 subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
    4758           0 :         tevent_req_simple_finish_ntstatus(subreq, status);
    4759           0 : }
    4760             : 
    4761        2977 : static void cli_chkpath_opened(struct tevent_req *subreq)
    4762             : {
    4763        2977 :         struct tevent_req *req = tevent_req_callback_data(
    4764             :                 subreq, struct tevent_req);
    4765        2977 :         struct cli_chkpath_state *state = tevent_req_data(
    4766             :                 req, struct cli_chkpath_state);
    4767             :         NTSTATUS status;
    4768             :         uint16_t fnum;
    4769             : 
    4770        2977 :         status = cli_ntcreate_recv(subreq, &fnum, NULL);
    4771        2977 :         TALLOC_FREE(subreq);
    4772        2977 :         if (tevent_req_nterror(req, status)) {
    4773        1579 :                 return;
    4774             :         }
    4775             : 
    4776        2186 :         subreq = cli_close_send(state, state->ev, state->cli, fnum);
    4777        2186 :         if (tevent_req_nomem(subreq, req)) {
    4778           0 :                 return;
    4779             :         }
    4780        2186 :         tevent_req_set_callback(subreq, cli_chkpath_closed, req);
    4781             : }
    4782             : 
    4783        2186 : static void cli_chkpath_closed(struct tevent_req *subreq)
    4784             : {
    4785        2186 :         NTSTATUS status = cli_close_recv(subreq);
    4786        2186 :         tevent_req_simple_finish_ntstatus(subreq, status);
    4787        2186 : }
    4788             : 
    4789        2977 : NTSTATUS cli_chkpath_recv(struct tevent_req *req)
    4790             : {
    4791        2977 :         return tevent_req_simple_recv_ntstatus(req);
    4792             : }
    4793             : 
    4794          70 : NTSTATUS cli_chkpath(struct cli_state *cli, const char *path)
    4795             : {
    4796          70 :         TALLOC_CTX *frame = NULL;
    4797          70 :         struct tevent_context *ev = NULL;
    4798          70 :         struct tevent_req *req = NULL;
    4799          70 :         char *path2 = NULL;
    4800          70 :         NTSTATUS status = NT_STATUS_OK;
    4801             : 
    4802          70 :         frame = talloc_stackframe();
    4803             : 
    4804          70 :         if (smbXcli_conn_has_async_calls(cli->conn)) {
    4805             :                 /*
    4806             :                  * Can't use sync call while an async call is in flight
    4807             :                  */
    4808           0 :                 status = NT_STATUS_INVALID_PARAMETER;
    4809           0 :                 goto fail;
    4810             :         }
    4811             : 
    4812          70 :         path2 = talloc_strdup(frame, path);
    4813          70 :         if (!path2) {
    4814           0 :                 status = NT_STATUS_NO_MEMORY;
    4815           0 :                 goto fail;
    4816             :         }
    4817          70 :         trim_char(path2,'\0','\\');
    4818          70 :         if (!*path2) {
    4819           0 :                 path2 = talloc_strdup(frame, "\\");
    4820           0 :                 if (!path2) {
    4821           0 :                         status = NT_STATUS_NO_MEMORY;
    4822           0 :                         goto fail;
    4823             :                 }
    4824             :         }
    4825             : 
    4826          70 :         ev = samba_tevent_context_init(frame);
    4827          70 :         if (ev == NULL) {
    4828           0 :                 status = NT_STATUS_NO_MEMORY;
    4829           0 :                 goto fail;
    4830             :         }
    4831             : 
    4832          70 :         req = cli_chkpath_send(frame, ev, cli, path2);
    4833          70 :         if (req == NULL) {
    4834           0 :                 status = NT_STATUS_NO_MEMORY;
    4835           0 :                 goto fail;
    4836             :         }
    4837             : 
    4838          70 :         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
    4839           0 :                 goto fail;
    4840             :         }
    4841             : 
    4842          70 :         status = cli_chkpath_recv(req);
    4843          70 :         cli->raw_status = status; /* cli_smb2_chkpath_recv doesn't set this */
    4844             : 
    4845          70 :  fail:
    4846          70 :         TALLOC_FREE(frame);
    4847          70 :         return status;
    4848             : }
    4849             : 
    4850             : /****************************************************************************
    4851             :  Query disk space.
    4852             : ****************************************************************************/
    4853             : 
    4854             : static void cli_dskattr_done(struct tevent_req *subreq);
    4855             : 
    4856             : struct cli_dskattr_state {
    4857             :         int bsize;
    4858             :         int total;
    4859             :         int avail;
    4860             : };
    4861             : 
    4862           0 : struct tevent_req *cli_dskattr_send(TALLOC_CTX *mem_ctx,
    4863             :                                   struct tevent_context *ev,
    4864             :                                   struct cli_state *cli)
    4865             : {
    4866           0 :         struct tevent_req *req = NULL, *subreq = NULL;
    4867           0 :         struct cli_dskattr_state *state = NULL;
    4868           0 :         uint8_t additional_flags = 0;
    4869             : 
    4870           0 :         req = tevent_req_create(mem_ctx, &state, struct cli_dskattr_state);
    4871           0 :         if (req == NULL) {
    4872           0 :                 return NULL;
    4873             :         }
    4874             : 
    4875           0 :         subreq = cli_smb_send(state, ev, cli, SMBdskattr, additional_flags, 0,
    4876             :                               0, NULL, 0, NULL);
    4877           0 :         if (tevent_req_nomem(subreq, req)) {
    4878           0 :                 return tevent_req_post(req, ev);
    4879             :         }
    4880           0 :         tevent_req_set_callback(subreq, cli_dskattr_done, req);
    4881           0 :         return req;
    4882             : }
    4883             : 
    4884           0 : static void cli_dskattr_done(struct tevent_req *subreq)
    4885             : {
    4886           0 :         struct tevent_req *req = tevent_req_callback_data(
    4887             :                 subreq, struct tevent_req);
    4888           0 :         struct cli_dskattr_state *state = tevent_req_data(
    4889             :                 req, struct cli_dskattr_state);
    4890             :         uint8_t wct;
    4891           0 :         uint16_t *vwv = NULL;
    4892             :         NTSTATUS status;
    4893             : 
    4894           0 :         status = cli_smb_recv(subreq, state, NULL, 4, &wct, &vwv, NULL,
    4895             :                               NULL);
    4896           0 :         TALLOC_FREE(subreq);
    4897           0 :         if (tevent_req_nterror(req, status)) {
    4898           0 :                 return;
    4899             :         }
    4900           0 :         state->bsize = SVAL(vwv+1, 0)*SVAL(vwv+2,0);
    4901           0 :         state->total = SVAL(vwv+0, 0);
    4902           0 :         state->avail = SVAL(vwv+3, 0);
    4903           0 :         tevent_req_done(req);
    4904             : }
    4905             : 
    4906           0 : NTSTATUS cli_dskattr_recv(struct tevent_req *req, int *bsize, int *total, int *avail)
    4907             : {
    4908           0 :         struct cli_dskattr_state *state = tevent_req_data(
    4909             :                                 req, struct cli_dskattr_state);
    4910             :         NTSTATUS status;
    4911             : 
    4912           0 :         if (tevent_req_is_nterror(req, &status)) {
    4913           0 :                 return status;
    4914             :         }
    4915           0 :         *bsize = state->bsize;
    4916           0 :         *total = state->total;
    4917           0 :         *avail = state->avail;
    4918           0 :         return NT_STATUS_OK;
    4919             : }
    4920             : 
    4921           0 : NTSTATUS cli_dskattr(struct cli_state *cli, int *bsize, int *total, int *avail)
    4922             : {
    4923           0 :         TALLOC_CTX *frame = NULL;
    4924           0 :         struct tevent_context *ev = NULL;
    4925           0 :         struct tevent_req *req = NULL;
    4926           0 :         NTSTATUS status = NT_STATUS_OK;
    4927             : 
    4928           0 :         frame = talloc_stackframe();
    4929             : 
    4930           0 :         if (smbXcli_conn_has_async_calls(cli->conn)) {
    4931             :                 /*
    4932             :                  * Can't use sync call while an async call is in flight
    4933             :                  */
    4934           0 :                 status = NT_STATUS_INVALID_PARAMETER;
    4935           0 :                 goto fail;
    4936             :         }
    4937             : 
    4938           0 :         ev = samba_tevent_context_init(frame);
    4939           0 :         if (ev == NULL) {
    4940           0 :                 status = NT_STATUS_NO_MEMORY;
    4941           0 :                 goto fail;
    4942             :         }
    4943             : 
    4944           0 :         req = cli_dskattr_send(frame, ev, cli);
    4945           0 :         if (req == NULL) {
    4946           0 :                 status = NT_STATUS_NO_MEMORY;
    4947           0 :                 goto fail;
    4948             :         }
    4949             : 
    4950           0 :         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
    4951           0 :                 goto fail;
    4952             :         }
    4953             : 
    4954           0 :         status = cli_dskattr_recv(req, bsize, total, avail);
    4955             : 
    4956           0 :  fail:
    4957           0 :         TALLOC_FREE(frame);
    4958           0 :         return status;
    4959             : }
    4960             : 
    4961         387 : NTSTATUS cli_disk_size(struct cli_state *cli, const char *path, uint64_t *bsize,
    4962             :                        uint64_t *total, uint64_t *avail)
    4963             : {
    4964             :         uint64_t sectors_per_block;
    4965             :         uint64_t bytes_per_sector;
    4966         387 :         int old_bsize = 0, old_total = 0, old_avail = 0;
    4967             :         NTSTATUS status;
    4968             : 
    4969         387 :         if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
    4970         387 :                 return cli_smb2_dskattr(cli, path, bsize, total, avail);
    4971             :         }
    4972             : 
    4973             :         /*
    4974             :          * Try the trans2 disk full size info call first.
    4975             :          * We already use this in SMBC_fstatvfs_ctx().
    4976             :          * Ignore 'actual_available_units' as we only
    4977             :          * care about the quota for the caller.
    4978             :          */
    4979             : 
    4980           0 :         status = cli_get_fs_full_size_info(cli,
    4981             :                         total,
    4982             :                         avail,
    4983             :                         NULL,
    4984             :                         &sectors_per_block,
    4985             :                         &bytes_per_sector);
    4986             : 
    4987             :         /* Try and cope will all varients of "we don't do this call"
    4988             :            and fall back to cli_dskattr. */
    4989             : 
    4990           0 :         if (NT_STATUS_EQUAL(status,NT_STATUS_NOT_IMPLEMENTED) ||
    4991           0 :                         NT_STATUS_EQUAL(status,NT_STATUS_NOT_SUPPORTED) ||
    4992           0 :                         NT_STATUS_EQUAL(status,NT_STATUS_INVALID_INFO_CLASS) ||
    4993           0 :                         NT_STATUS_EQUAL(status,NT_STATUS_PROCEDURE_NOT_FOUND) ||
    4994           0 :                         NT_STATUS_EQUAL(status,NT_STATUS_INVALID_LEVEL) ||
    4995           0 :                         NT_STATUS_EQUAL(status,NT_STATUS_INVALID_PARAMETER) ||
    4996           0 :                         NT_STATUS_EQUAL(status,NT_STATUS_INVALID_DEVICE_REQUEST) ||
    4997           0 :                         NT_STATUS_EQUAL(status,NT_STATUS_INVALID_DEVICE_STATE) ||
    4998           0 :                         NT_STATUS_EQUAL(status,NT_STATUS_CTL_FILE_NOT_SUPPORTED) ||
    4999           0 :                         NT_STATUS_EQUAL(status,NT_STATUS_UNSUCCESSFUL)) {
    5000           0 :                 goto try_dskattr;
    5001             :         }
    5002             : 
    5003           0 :         if (!NT_STATUS_IS_OK(status)) {
    5004           0 :                 return status;
    5005             :         }
    5006             : 
    5007           0 :         if (bsize) {
    5008           0 :                 *bsize = sectors_per_block *
    5009             :                          bytes_per_sector;
    5010             :         }
    5011             : 
    5012           0 :         return NT_STATUS_OK;
    5013             : 
    5014           0 :   try_dskattr:
    5015             : 
    5016             :         /* Old SMB1 core protocol fallback. */
    5017           0 :         status = cli_dskattr(cli, &old_bsize, &old_total, &old_avail);
    5018           0 :         if (!NT_STATUS_IS_OK(status)) {
    5019           0 :                 return status;
    5020             :         }
    5021           0 :         if (bsize) {
    5022           0 :                 *bsize = (uint64_t)old_bsize;
    5023             :         }
    5024           0 :         if (total) {
    5025           0 :                 *total = (uint64_t)old_total;
    5026             :         }
    5027           0 :         if (avail) {
    5028           0 :                 *avail = (uint64_t)old_avail;
    5029             :         }
    5030           0 :         return NT_STATUS_OK;
    5031             : }
    5032             : 
    5033             : /****************************************************************************
    5034             :  Create and open a temporary file.
    5035             : ****************************************************************************/
    5036             : 
    5037             : static void cli_ctemp_done(struct tevent_req *subreq);
    5038             : 
    5039             : struct ctemp_state {
    5040             :         uint16_t vwv[3];
    5041             :         char *ret_path;
    5042             :         uint16_t fnum;
    5043             : };
    5044             : 
    5045           1 : struct tevent_req *cli_ctemp_send(TALLOC_CTX *mem_ctx,
    5046             :                                 struct tevent_context *ev,
    5047             :                                 struct cli_state *cli,
    5048             :                                 const char *path)
    5049             : {
    5050           1 :         struct tevent_req *req = NULL, *subreq = NULL;
    5051           1 :         struct ctemp_state *state = NULL;
    5052           1 :         uint8_t additional_flags = 0;
    5053           1 :         uint16_t additional_flags2 = 0;
    5054           1 :         uint8_t *bytes = NULL;
    5055             : 
    5056           1 :         req = tevent_req_create(mem_ctx, &state, struct ctemp_state);
    5057           1 :         if (req == NULL) {
    5058           0 :                 return NULL;
    5059             :         }
    5060             : 
    5061           1 :         SSVAL(state->vwv,0,0);
    5062           1 :         SIVALS(state->vwv+1,0,-1);
    5063             : 
    5064           1 :         bytes = talloc_array(state, uint8_t, 1);
    5065           1 :         if (tevent_req_nomem(bytes, req)) {
    5066           0 :                 return tevent_req_post(req, ev);
    5067             :         }
    5068           1 :         bytes[0] = 4;
    5069           1 :         bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), path,
    5070           1 :                                    strlen(path)+1, NULL);
    5071           1 :         if (tevent_req_nomem(bytes, req)) {
    5072           0 :                 return tevent_req_post(req, ev);
    5073             :         }
    5074             : 
    5075           1 :         if (clistr_is_previous_version_path(path, NULL, NULL, NULL)) {
    5076           0 :                 additional_flags2 = FLAGS2_REPARSE_PATH;
    5077             :         }
    5078             : 
    5079           2 :         subreq = cli_smb_send(state, ev, cli, SMBctemp, additional_flags,
    5080             :                         additional_flags2,
    5081           2 :                         3, state->vwv, talloc_get_size(bytes), bytes);
    5082           1 :         if (tevent_req_nomem(subreq, req)) {
    5083           0 :                 return tevent_req_post(req, ev);
    5084             :         }
    5085           1 :         tevent_req_set_callback(subreq, cli_ctemp_done, req);
    5086           1 :         return req;
    5087             : }
    5088             : 
    5089           1 : static void cli_ctemp_done(struct tevent_req *subreq)
    5090             : {
    5091           1 :         struct tevent_req *req = tevent_req_callback_data(
    5092             :                                 subreq, struct tevent_req);
    5093           1 :         struct ctemp_state *state = tevent_req_data(
    5094             :                                 req, struct ctemp_state);
    5095             :         NTSTATUS status;
    5096             :         uint8_t wcnt;
    5097             :         uint16_t *vwv;
    5098           1 :         uint32_t num_bytes = 0;
    5099           1 :         uint8_t *bytes = NULL;
    5100             : 
    5101           1 :         status = cli_smb_recv(subreq, state, NULL, 1, &wcnt, &vwv,
    5102             :                               &num_bytes, &bytes);
    5103           1 :         TALLOC_FREE(subreq);
    5104           1 :         if (tevent_req_nterror(req, status)) {
    5105           0 :                 return;
    5106             :         }
    5107             : 
    5108           1 :         state->fnum = SVAL(vwv+0, 0);
    5109             : 
    5110             :         /* From W2K3, the result is just the ASCII name */
    5111           1 :         if (num_bytes < 2) {
    5112           0 :                 tevent_req_nterror(req, NT_STATUS_DATA_ERROR);
    5113           0 :                 return;
    5114             :         }
    5115             : 
    5116           1 :         if (pull_string_talloc(state,
    5117             :                         NULL,
    5118             :                         0,
    5119             :                         &state->ret_path,
    5120             :                         bytes,
    5121             :                         num_bytes,
    5122             :                         STR_ASCII) == 0) {
    5123           0 :                 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
    5124           0 :                 return;
    5125             :         }
    5126           1 :         tevent_req_done(req);
    5127             : }
    5128             : 
    5129           1 : NTSTATUS cli_ctemp_recv(struct tevent_req *req,
    5130             :                         TALLOC_CTX *ctx,
    5131             :                         uint16_t *pfnum,
    5132             :                         char **outfile)
    5133             : {
    5134           1 :         struct ctemp_state *state = tevent_req_data(req,
    5135             :                         struct ctemp_state);
    5136             :         NTSTATUS status;
    5137             : 
    5138           1 :         if (tevent_req_is_nterror(req, &status)) {
    5139           0 :                 return status;
    5140             :         }
    5141           1 :         *pfnum = state->fnum;
    5142           1 :         *outfile = talloc_strdup(ctx, state->ret_path);
    5143           1 :         if (!*outfile) {
    5144           0 :                 return NT_STATUS_NO_MEMORY;
    5145             :         }
    5146           1 :         return NT_STATUS_OK;
    5147             : }
    5148             : 
    5149           1 : NTSTATUS cli_ctemp(struct cli_state *cli,
    5150             :                         TALLOC_CTX *ctx,
    5151             :                         const char *path,
    5152             :                         uint16_t *pfnum,
    5153             :                         char **out_path)
    5154             : {
    5155           1 :         TALLOC_CTX *frame = talloc_stackframe();
    5156             :         struct tevent_context *ev;
    5157             :         struct tevent_req *req;
    5158           1 :         NTSTATUS status = NT_STATUS_OK;
    5159             : 
    5160           1 :         if (smbXcli_conn_has_async_calls(cli->conn)) {
    5161             :                 /*
    5162             :                  * Can't use sync call while an async call is in flight
    5163             :                  */
    5164           0 :                 status = NT_STATUS_INVALID_PARAMETER;
    5165           0 :                 goto fail;
    5166             :         }
    5167             : 
    5168           1 :         ev = samba_tevent_context_init(frame);
    5169           1 :         if (ev == NULL) {
    5170           0 :                 status = NT_STATUS_NO_MEMORY;
    5171           0 :                 goto fail;
    5172             :         }
    5173             : 
    5174           1 :         req = cli_ctemp_send(frame, ev, cli, path);
    5175           1 :         if (req == NULL) {
    5176           0 :                 status = NT_STATUS_NO_MEMORY;
    5177           0 :                 goto fail;
    5178             :         }
    5179             : 
    5180           1 :         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
    5181           0 :                 goto fail;
    5182             :         }
    5183             : 
    5184           1 :         status = cli_ctemp_recv(req, ctx, pfnum, out_path);
    5185             : 
    5186           1 :  fail:
    5187           1 :         TALLOC_FREE(frame);
    5188           1 :         return status;
    5189             : }
    5190             : 
    5191             : /*
    5192             :    send a raw ioctl - used by the torture code
    5193             : */
    5194       65538 : NTSTATUS cli_raw_ioctl(struct cli_state *cli, uint16_t fnum, uint32_t code, DATA_BLOB *blob)
    5195             : {
    5196             :         uint16_t vwv[3];
    5197             :         NTSTATUS status;
    5198             : 
    5199       65538 :         SSVAL(vwv+0, 0, fnum);
    5200       65538 :         SSVAL(vwv+1, 0, code>>16);
    5201       65538 :         SSVAL(vwv+2, 0, (code&0xFFFF));
    5202             : 
    5203       65538 :         status = cli_smb(talloc_tos(), cli, SMBioctl, 0, 3, vwv, 0, NULL,
    5204             :                          NULL, 0, NULL, NULL, NULL, NULL);
    5205       65538 :         if (!NT_STATUS_IS_OK(status)) {
    5206       65538 :                 return status;
    5207             :         }
    5208           0 :         *blob = data_blob_null;
    5209           0 :         return NT_STATUS_OK;
    5210             : }
    5211             : 
    5212             : /*********************************************************
    5213             :  Set an extended attribute utility fn.
    5214             : *********************************************************/
    5215             : 
    5216           0 : static NTSTATUS cli_set_ea(struct cli_state *cli, uint16_t setup_val,
    5217             :                            uint8_t *param, unsigned int param_len,
    5218             :                            const char *ea_name,
    5219             :                            const char *ea_val, size_t ea_len)
    5220             : {
    5221             :         uint16_t setup[1];
    5222           0 :         unsigned int data_len = 0;
    5223           0 :         uint8_t *data = NULL;
    5224             :         char *p;
    5225           0 :         size_t ea_namelen = strlen(ea_name);
    5226             :         NTSTATUS status;
    5227             : 
    5228           0 :         SSVAL(setup, 0, setup_val);
    5229             : 
    5230           0 :         if (ea_namelen == 0 && ea_len == 0) {
    5231           0 :                 data_len = 4;
    5232           0 :                 data = talloc_array(talloc_tos(),
    5233             :                                 uint8_t,
    5234             :                                 data_len);
    5235           0 :                 if (!data) {
    5236           0 :                         return NT_STATUS_NO_MEMORY;
    5237             :                 }
    5238           0 :                 p = (char *)data;
    5239           0 :                 SIVAL(p,0,data_len);
    5240             :         } else {
    5241           0 :                 data_len = 4 + 4 + ea_namelen + 1 + ea_len;
    5242           0 :                 data = talloc_array(talloc_tos(),
    5243             :                                 uint8_t,
    5244             :                                 data_len);
    5245           0 :                 if (!data) {
    5246           0 :                         return NT_STATUS_NO_MEMORY;
    5247             :                 }
    5248           0 :                 p = (char *)data;
    5249           0 :                 SIVAL(p,0,data_len);
    5250           0 :                 p += 4;
    5251           0 :                 SCVAL(p, 0, 0); /* EA flags. */
    5252           0 :                 SCVAL(p, 1, ea_namelen);
    5253           0 :                 SSVAL(p, 2, ea_len);
    5254           0 :                 memcpy(p+4, ea_name, ea_namelen+1); /* Copy in the name. */
    5255           0 :                 memcpy(p+4+ea_namelen+1, ea_val, ea_len);
    5256             :         }
    5257             : 
    5258             :         /*
    5259             :          * FIXME - if we want to do previous version path
    5260             :          * processing on an EA set call we need to turn this
    5261             :          * into calls to cli_trans_send()/cli_trans_recv()
    5262             :          * with a temporary event context, as cli_trans_send()
    5263             :          * have access to the additional_flags2 needed to
    5264             :          * send @GMT- paths. JRA.
    5265             :          */
    5266             : 
    5267           0 :         status = cli_trans(talloc_tos(), cli, SMBtrans2, NULL, -1, 0, 0,
    5268             :                            setup, 1, 0,
    5269             :                            param, param_len, 2,
    5270             :                            data,  data_len, 0,
    5271             :                            NULL,
    5272             :                            NULL, 0, NULL, /* rsetup */
    5273             :                            NULL, 0, NULL, /* rparam */
    5274             :                            NULL, 0, NULL); /* rdata */
    5275           0 :         talloc_free(data);
    5276           0 :         return status;
    5277             : }
    5278             : 
    5279             : /*********************************************************
    5280             :  Set an extended attribute on a pathname.
    5281             : *********************************************************/
    5282             : 
    5283           0 : NTSTATUS cli_set_ea_path(struct cli_state *cli, const char *path,
    5284             :                          const char *ea_name, const char *ea_val,
    5285             :                          size_t ea_len)
    5286             : {
    5287           0 :         unsigned int param_len = 0;
    5288             :         uint8_t *param;
    5289             :         NTSTATUS status;
    5290           0 :         TALLOC_CTX *frame = NULL;
    5291             : 
    5292           0 :         if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
    5293           0 :                 return cli_smb2_set_ea_path(cli,
    5294             :                                         path,
    5295             :                                         ea_name,
    5296             :                                         ea_val,
    5297             :                                         ea_len);
    5298             :         }
    5299             : 
    5300           0 :         frame = talloc_stackframe();
    5301             : 
    5302           0 :         param = talloc_array(frame, uint8_t, 6);
    5303           0 :         if (!param) {
    5304           0 :                 status = NT_STATUS_NO_MEMORY;
    5305           0 :                 goto fail;
    5306             :         }
    5307           0 :         SSVAL(param,0,SMB_INFO_SET_EA);
    5308           0 :         SSVAL(param,2,0);
    5309           0 :         SSVAL(param,4,0);
    5310             : 
    5311           0 :         param = trans2_bytes_push_str(param, smbXcli_conn_use_unicode(cli->conn),
    5312           0 :                                       path, strlen(path)+1,
    5313             :                                       NULL);
    5314           0 :         param_len = talloc_get_size(param);
    5315             : 
    5316           0 :         status = cli_set_ea(cli, TRANSACT2_SETPATHINFO, param, param_len,
    5317             :                             ea_name, ea_val, ea_len);
    5318             : 
    5319           0 :   fail:
    5320             : 
    5321           0 :         TALLOC_FREE(frame);
    5322           0 :         return status;
    5323             : }
    5324             : 
    5325             : /*********************************************************
    5326             :  Set an extended attribute on an fnum.
    5327             : *********************************************************/
    5328             : 
    5329           0 : NTSTATUS cli_set_ea_fnum(struct cli_state *cli, uint16_t fnum,
    5330             :                          const char *ea_name, const char *ea_val,
    5331             :                          size_t ea_len)
    5332             : {
    5333           0 :         uint8_t param[6] = { 0, };
    5334             : 
    5335           0 :         if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
    5336           0 :                 return cli_smb2_set_ea_fnum(cli,
    5337             :                                         fnum,
    5338             :                                         ea_name,
    5339             :                                         ea_val,
    5340             :                                         ea_len);
    5341             :         }
    5342             : 
    5343           0 :         SSVAL(param,0,fnum);
    5344           0 :         SSVAL(param,2,SMB_INFO_SET_EA);
    5345             : 
    5346           0 :         return cli_set_ea(cli, TRANSACT2_SETFILEINFO, param, 6,
    5347             :                           ea_name, ea_val, ea_len);
    5348             : }
    5349             : 
    5350             : /*********************************************************
    5351             :  Get an extended attribute list utility fn.
    5352             : *********************************************************/
    5353             : 
    5354           0 : static bool parse_ea_blob(TALLOC_CTX *ctx, const uint8_t *rdata,
    5355             :                           size_t rdata_len,
    5356             :                           size_t *pnum_eas, struct ea_struct **pea_list)
    5357             : {
    5358           0 :         struct ea_struct *ea_list = NULL;
    5359             :         size_t num_eas;
    5360             :         size_t ea_size;
    5361             :         const uint8_t *p;
    5362             : 
    5363           0 :         if (rdata_len < 4) {
    5364           0 :                 return false;
    5365             :         }
    5366             : 
    5367           0 :         ea_size = (size_t)IVAL(rdata,0);
    5368           0 :         if (ea_size > rdata_len) {
    5369           0 :                 return false;
    5370             :         }
    5371             : 
    5372           0 :         if (ea_size == 0) {
    5373             :                 /* No EA's present. */
    5374           0 :                 *pnum_eas = 0;
    5375           0 :                 *pea_list = NULL;
    5376           0 :                 return true;
    5377             :         }
    5378             : 
    5379           0 :         p = rdata + 4;
    5380           0 :         ea_size -= 4;
    5381             : 
    5382             :         /* Validate the EA list and count it. */
    5383           0 :         for (num_eas = 0; ea_size >= 4; num_eas++) {
    5384           0 :                 unsigned int ea_namelen = CVAL(p,1);
    5385           0 :                 unsigned int ea_valuelen = SVAL(p,2);
    5386           0 :                 if (ea_namelen == 0) {
    5387           0 :                         return false;
    5388             :                 }
    5389           0 :                 if (4 + ea_namelen + 1 + ea_valuelen > ea_size) {
    5390           0 :                         return false;
    5391             :                 }
    5392           0 :                 ea_size -= 4 + ea_namelen + 1 + ea_valuelen;
    5393           0 :                 p += 4 + ea_namelen + 1 + ea_valuelen;
    5394             :         }
    5395             : 
    5396           0 :         if (num_eas == 0) {
    5397           0 :                 *pnum_eas = 0;
    5398           0 :                 *pea_list = NULL;
    5399           0 :                 return true;
    5400             :         }
    5401             : 
    5402           0 :         *pnum_eas = num_eas;
    5403           0 :         if (!pea_list) {
    5404             :                 /* Caller only wants number of EA's. */
    5405           0 :                 return true;
    5406             :         }
    5407             : 
    5408           0 :         ea_list = talloc_array(ctx, struct ea_struct, num_eas);
    5409           0 :         if (!ea_list) {
    5410           0 :                 return false;
    5411             :         }
    5412             : 
    5413           0 :         p = rdata + 4;
    5414             : 
    5415           0 :         for (num_eas = 0; num_eas < *pnum_eas; num_eas++ ) {
    5416           0 :                 struct ea_struct *ea = &ea_list[num_eas];
    5417             :                 fstring unix_ea_name;
    5418           0 :                 unsigned int ea_namelen = CVAL(p,1);
    5419           0 :                 unsigned int ea_valuelen = SVAL(p,2);
    5420             : 
    5421           0 :                 ea->flags = CVAL(p,0);
    5422           0 :                 unix_ea_name[0] = '\0';
    5423           0 :                 pull_ascii(unix_ea_name, p + 4, sizeof(unix_ea_name), rdata_len - PTR_DIFF(p+4, rdata), STR_TERMINATE);
    5424           0 :                 ea->name = talloc_strdup(ea_list, unix_ea_name);
    5425           0 :                 if (!ea->name) {
    5426           0 :                         goto fail;
    5427             :                 }
    5428             :                 /* Ensure the value is null terminated (in case it's a string). */
    5429           0 :                 ea->value = data_blob_talloc(ea_list, NULL, ea_valuelen + 1);
    5430           0 :                 if (!ea->value.data) {
    5431           0 :                         goto fail;
    5432             :                 }
    5433           0 :                 if (ea_valuelen) {
    5434           0 :                         memcpy(ea->value.data, p+4+ea_namelen+1, ea_valuelen);
    5435             :                 }
    5436           0 :                 ea->value.data[ea_valuelen] = 0;
    5437           0 :                 ea->value.length--;
    5438           0 :                 p += 4 + ea_namelen + 1 + ea_valuelen;
    5439             :         }
    5440             : 
    5441           0 :         *pea_list = ea_list;
    5442           0 :         return true;
    5443             : 
    5444           0 : fail:
    5445           0 :         TALLOC_FREE(ea_list);
    5446           0 :         return false;
    5447             : }
    5448             : 
    5449             : /*********************************************************
    5450             :  Get an extended attribute list from a pathname.
    5451             : *********************************************************/
    5452             : 
    5453             : struct cli_get_ea_list_path_state {
    5454             :         uint32_t num_data;
    5455             :         uint8_t *data;
    5456             : };
    5457             : 
    5458             : static void cli_get_ea_list_path_done(struct tevent_req *subreq);
    5459             : 
    5460           0 : struct tevent_req *cli_get_ea_list_path_send(TALLOC_CTX *mem_ctx,
    5461             :                                              struct tevent_context *ev,
    5462             :                                              struct cli_state *cli,
    5463             :                                              const char *fname)
    5464             : {
    5465             :         struct tevent_req *req, *subreq;
    5466             :         struct cli_get_ea_list_path_state *state;
    5467             : 
    5468           0 :         req = tevent_req_create(mem_ctx, &state,
    5469             :                                 struct cli_get_ea_list_path_state);
    5470           0 :         if (req == NULL) {
    5471           0 :                 return NULL;
    5472             :         }
    5473           0 :         subreq = cli_qpathinfo_send(state, ev, cli, fname,
    5474             :                                     SMB_INFO_QUERY_ALL_EAS, 4,
    5475             :                                     CLI_BUFFER_SIZE);
    5476           0 :         if (tevent_req_nomem(subreq, req)) {
    5477           0 :                 return tevent_req_post(req, ev);
    5478             :         }
    5479           0 :         tevent_req_set_callback(subreq, cli_get_ea_list_path_done, req);
    5480           0 :         return req;
    5481             : }
    5482             : 
    5483           0 : static void cli_get_ea_list_path_done(struct tevent_req *subreq)
    5484             : {
    5485           0 :         struct tevent_req *req = tevent_req_callback_data(
    5486             :                                 subreq, struct tevent_req);
    5487           0 :         struct cli_get_ea_list_path_state *state = tevent_req_data(
    5488             :                 req, struct cli_get_ea_list_path_state);
    5489             :         NTSTATUS status;
    5490             : 
    5491           0 :         status = cli_qpathinfo_recv(subreq, state, &state->data,
    5492             :                                     &state->num_data);
    5493           0 :         TALLOC_FREE(subreq);
    5494           0 :         if (tevent_req_nterror(req, status)) {
    5495           0 :                 return;
    5496             :         }
    5497           0 :         tevent_req_done(req);
    5498             : }
    5499             : 
    5500           0 : NTSTATUS cli_get_ea_list_path_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
    5501             :                                    size_t *pnum_eas, struct ea_struct **peas)
    5502             : {
    5503           0 :         struct cli_get_ea_list_path_state *state = tevent_req_data(
    5504             :                 req, struct cli_get_ea_list_path_state);
    5505             :         NTSTATUS status;
    5506             : 
    5507           0 :         if (tevent_req_is_nterror(req, &status)) {
    5508           0 :                 return status;
    5509             :         }
    5510           0 :         if (!parse_ea_blob(mem_ctx, state->data, state->num_data,
    5511             :                            pnum_eas, peas)) {
    5512           0 :                 return NT_STATUS_INVALID_NETWORK_RESPONSE;
    5513             :         }
    5514           0 :         return NT_STATUS_OK;
    5515             : }
    5516             : 
    5517           0 : NTSTATUS cli_get_ea_list_path(struct cli_state *cli, const char *path,
    5518             :                 TALLOC_CTX *ctx,
    5519             :                 size_t *pnum_eas,
    5520             :                 struct ea_struct **pea_list)
    5521             : {
    5522           0 :         TALLOC_CTX *frame = NULL;
    5523           0 :         struct tevent_context *ev = NULL;
    5524           0 :         struct tevent_req *req = NULL;
    5525           0 :         NTSTATUS status = NT_STATUS_NO_MEMORY;
    5526             : 
    5527           0 :         if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
    5528           0 :                 return cli_smb2_get_ea_list_path(cli,
    5529             :                                         path,
    5530             :                                         ctx,
    5531             :                                         pnum_eas,
    5532             :                                         pea_list);
    5533             :         }
    5534             : 
    5535           0 :         frame = talloc_stackframe();
    5536             : 
    5537           0 :         if (smbXcli_conn_has_async_calls(cli->conn)) {
    5538             :                 /*
    5539             :                  * Can't use sync call while an async call is in flight
    5540             :                  */
    5541           0 :                 status = NT_STATUS_INVALID_PARAMETER;
    5542           0 :                 goto fail;
    5543             :         }
    5544           0 :         ev = samba_tevent_context_init(frame);
    5545           0 :         if (ev == NULL) {
    5546           0 :                 goto fail;
    5547             :         }
    5548           0 :         req = cli_get_ea_list_path_send(frame, ev, cli, path);
    5549           0 :         if (req == NULL) {
    5550           0 :                 goto fail;
    5551             :         }
    5552           0 :         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
    5553           0 :                 goto fail;
    5554             :         }
    5555           0 :         status = cli_get_ea_list_path_recv(req, ctx, pnum_eas, pea_list);
    5556           0 :  fail:
    5557           0 :         TALLOC_FREE(frame);
    5558           0 :         return status;
    5559             : }
    5560             : 
    5561             : /****************************************************************************
    5562             :  Convert open "flags" arg to uint32_t on wire.
    5563             : ****************************************************************************/
    5564             : 
    5565           0 : static uint32_t open_flags_to_wire(int flags)
    5566             : {
    5567           0 :         int open_mode = flags & O_ACCMODE;
    5568           0 :         uint32_t ret = 0;
    5569             : 
    5570           0 :         switch (open_mode) {
    5571           0 :                 case O_WRONLY:
    5572           0 :                         ret |= SMB_O_WRONLY;
    5573           0 :                         break;
    5574           0 :                 case O_RDWR:
    5575           0 :                         ret |= SMB_O_RDWR;
    5576           0 :                         break;
    5577           0 :                 default:
    5578             :                 case O_RDONLY:
    5579           0 :                         ret |= SMB_O_RDONLY;
    5580           0 :                         break;
    5581             :         }
    5582             : 
    5583           0 :         if (flags & O_CREAT) {
    5584           0 :                 ret |= SMB_O_CREAT;
    5585             :         }
    5586           0 :         if (flags & O_EXCL) {
    5587           0 :                 ret |= SMB_O_EXCL;
    5588             :         }
    5589           0 :         if (flags & O_TRUNC) {
    5590           0 :                 ret |= SMB_O_TRUNC;
    5591             :         }
    5592             : #if defined(O_SYNC)
    5593           0 :         if (flags & O_SYNC) {
    5594           0 :                 ret |= SMB_O_SYNC;
    5595             :         }
    5596             : #endif /* O_SYNC */
    5597           0 :         if (flags & O_APPEND) {
    5598           0 :                 ret |= SMB_O_APPEND;
    5599             :         }
    5600             : #if defined(O_DIRECT)
    5601           0 :         if (flags & O_DIRECT) {
    5602           0 :                 ret |= SMB_O_DIRECT;
    5603             :         }
    5604             : #endif
    5605             : #if defined(O_DIRECTORY)
    5606           0 :         if (flags & O_DIRECTORY) {
    5607           0 :                 ret |= SMB_O_DIRECTORY;
    5608             :         }
    5609             : #endif
    5610           0 :         return ret;
    5611             : }
    5612             : 
    5613             : /****************************************************************************
    5614             :  Open a file - POSIX semantics. Returns fnum. Doesn't request oplock.
    5615             : ****************************************************************************/
    5616             : 
    5617             : struct cli_posix_open_internal_state {
    5618             :         uint16_t setup;
    5619             :         uint8_t *param;
    5620             :         uint8_t data[18];
    5621             :         uint16_t fnum; /* Out */
    5622             : };
    5623             : 
    5624             : static void cli_posix_open_internal_done(struct tevent_req *subreq);
    5625             : 
    5626           0 : static struct tevent_req *cli_posix_open_internal_send(TALLOC_CTX *mem_ctx,
    5627             :                                         struct tevent_context *ev,
    5628             :                                         struct cli_state *cli,
    5629             :                                         const char *fname,
    5630             :                                         uint32_t wire_flags,
    5631             :                                         mode_t mode)
    5632             : {
    5633           0 :         struct tevent_req *req = NULL, *subreq = NULL;
    5634           0 :         struct cli_posix_open_internal_state *state = NULL;
    5635             : 
    5636           0 :         req = tevent_req_create(
    5637             :                 mem_ctx, &state, struct cli_posix_open_internal_state);
    5638           0 :         if (req == NULL) {
    5639           0 :                 return NULL;
    5640             :         }
    5641             : 
    5642             :         /* Setup setup word. */
    5643           0 :         SSVAL(&state->setup, 0, TRANSACT2_SETPATHINFO);
    5644             : 
    5645             :         /* Setup param array. */
    5646           0 :         state->param = talloc_zero_array(state, uint8_t, 6);
    5647           0 :         if (tevent_req_nomem(state->param, req)) {
    5648           0 :                 return tevent_req_post(req, ev);
    5649             :         }
    5650           0 :         SSVAL(state->param, 0, SMB_POSIX_PATH_OPEN);
    5651             : 
    5652           0 :         state->param = trans2_bytes_push_str(
    5653           0 :                 state->param,
    5654           0 :                 smbXcli_conn_use_unicode(cli->conn),
    5655             :                 fname,
    5656           0 :                 strlen(fname)+1,
    5657             :                 NULL);
    5658             : 
    5659           0 :         if (tevent_req_nomem(state->param, req)) {
    5660           0 :                 return tevent_req_post(req, ev);
    5661             :         }
    5662             : 
    5663           0 :         SIVAL(state->data,0,0); /* No oplock. */
    5664           0 :         SIVAL(state->data,4,wire_flags);
    5665           0 :         SIVAL(state->data,8,unix_perms_to_wire(mode));
    5666           0 :         SIVAL(state->data,12,0); /* Top bits of perms currently undefined. */
    5667           0 :         SSVAL(state->data,16,SMB_NO_INFO_LEVEL_RETURNED); /* No info level returned. */
    5668             : 
    5669           0 :         subreq = cli_trans_send(state,                  /* mem ctx. */
    5670             :                                 ev,                     /* event ctx. */
    5671             :                                 cli,                    /* cli_state. */
    5672             :                                 0,                      /* additional_flags2 */
    5673             :                                 SMBtrans2,              /* cmd. */
    5674             :                                 NULL,                   /* pipe name. */
    5675             :                                 -1,                     /* fid. */
    5676             :                                 0,                      /* function. */
    5677             :                                 0,                      /* flags. */
    5678           0 :                                 &state->setup,           /* setup. */
    5679             :                                 1,                      /* num setup uint16_t words. */
    5680             :                                 0,                      /* max returned setup. */
    5681           0 :                                 state->param,                /* param. */
    5682           0 :                                 talloc_get_size(state->param),/* num param. */
    5683             :                                 2,                      /* max returned param. */
    5684           0 :                                 state->data,         /* data. */
    5685             :                                 18,                     /* num data. */
    5686             :                                 12);                    /* max returned data. */
    5687             : 
    5688           0 :         if (tevent_req_nomem(subreq, req)) {
    5689           0 :                 return tevent_req_post(req, ev);
    5690             :         }
    5691           0 :         tevent_req_set_callback(subreq, cli_posix_open_internal_done, req);
    5692           0 :         return req;
    5693             : }
    5694             : 
    5695           0 : static void cli_posix_open_internal_done(struct tevent_req *subreq)
    5696             : {
    5697           0 :         struct tevent_req *req = tevent_req_callback_data(
    5698             :                 subreq, struct tevent_req);
    5699           0 :         struct cli_posix_open_internal_state *state = tevent_req_data(
    5700             :                 req, struct cli_posix_open_internal_state);
    5701             :         NTSTATUS status;
    5702             :         uint8_t *data;
    5703             :         uint32_t num_data;
    5704             : 
    5705           0 :         status = cli_trans_recv(
    5706             :                 subreq,
    5707             :                 state,
    5708             :                 NULL,
    5709             :                 NULL,
    5710             :                 0,
    5711             :                 NULL,
    5712             :                 NULL,
    5713             :                 0,
    5714             :                 NULL,
    5715             :                 &data,
    5716             :                 12,
    5717             :                 &num_data);
    5718           0 :         TALLOC_FREE(subreq);
    5719           0 :         if (tevent_req_nterror(req, status)) {
    5720           0 :                 return;
    5721             :         }
    5722           0 :         state->fnum = SVAL(data,2);
    5723           0 :         tevent_req_done(req);
    5724             : }
    5725             : 
    5726           0 : static NTSTATUS cli_posix_open_internal_recv(struct tevent_req *req,
    5727             :                                              uint16_t *pfnum)
    5728             : {
    5729           0 :         struct cli_posix_open_internal_state *state = tevent_req_data(
    5730             :                 req, struct cli_posix_open_internal_state);
    5731             :         NTSTATUS status;
    5732             : 
    5733           0 :         if (tevent_req_is_nterror(req, &status)) {
    5734           0 :                 return status;
    5735             :         }
    5736           0 :         *pfnum = state->fnum;
    5737           0 :         return NT_STATUS_OK;
    5738             : }
    5739             : 
    5740             : struct cli_posix_open_state {
    5741             :         uint16_t fnum;
    5742             : };
    5743             : 
    5744             : static void cli_posix_open_done(struct tevent_req *subreq);
    5745             : 
    5746           0 : struct tevent_req *cli_posix_open_send(TALLOC_CTX *mem_ctx,
    5747             :                                         struct tevent_context *ev,
    5748             :                                         struct cli_state *cli,
    5749             :                                         const char *fname,
    5750             :                                         int flags,
    5751             :                                         mode_t mode)
    5752             : {
    5753           0 :         struct tevent_req *req = NULL, *subreq = NULL;
    5754           0 :         struct cli_posix_open_state *state = NULL;
    5755             :         uint32_t wire_flags;
    5756             : 
    5757           0 :         req = tevent_req_create(mem_ctx, &state,
    5758             :                                 struct cli_posix_open_state);
    5759           0 :         if (req == NULL) {
    5760           0 :                 return NULL;
    5761             :         }
    5762             : 
    5763           0 :         wire_flags = open_flags_to_wire(flags);
    5764             : 
    5765           0 :         subreq = cli_posix_open_internal_send(
    5766             :                 mem_ctx, ev, cli, fname, wire_flags, mode);
    5767           0 :         if (tevent_req_nomem(subreq, req)) {
    5768           0 :                 return tevent_req_post(req, ev);
    5769             :         }
    5770           0 :         tevent_req_set_callback(subreq, cli_posix_open_done, req);
    5771           0 :         return req;
    5772             : }
    5773             : 
    5774           0 : static void cli_posix_open_done(struct tevent_req *subreq)
    5775             : {
    5776           0 :         struct tevent_req *req = tevent_req_callback_data(
    5777             :                 subreq, struct tevent_req);
    5778           0 :         struct cli_posix_open_state *state = tevent_req_data(
    5779             :                 req, struct cli_posix_open_state);
    5780             :         NTSTATUS status;
    5781             : 
    5782           0 :         status = cli_posix_open_internal_recv(subreq, &state->fnum);
    5783           0 :         tevent_req_simple_finish_ntstatus(subreq, status);
    5784           0 : }
    5785             : 
    5786           0 : NTSTATUS cli_posix_open_recv(struct tevent_req *req, uint16_t *pfnum)
    5787             : {
    5788           0 :         struct cli_posix_open_state *state = tevent_req_data(
    5789             :                 req, struct cli_posix_open_state);
    5790             :         NTSTATUS status;
    5791             : 
    5792           0 :         if (tevent_req_is_nterror(req, &status)) {
    5793           0 :                 return status;
    5794             :         }
    5795           0 :         *pfnum = state->fnum;
    5796           0 :         return NT_STATUS_OK;
    5797             : }
    5798             : 
    5799             : /****************************************************************************
    5800             :  Open - POSIX semantics. Doesn't request oplock.
    5801             : ****************************************************************************/
    5802             : 
    5803           0 : NTSTATUS cli_posix_open(struct cli_state *cli, const char *fname,
    5804             :                         int flags, mode_t mode, uint16_t *pfnum)
    5805             : {
    5806             : 
    5807           0 :         TALLOC_CTX *frame = talloc_stackframe();
    5808           0 :         struct tevent_context *ev = NULL;
    5809           0 :         struct tevent_req *req = NULL;
    5810           0 :         NTSTATUS status = NT_STATUS_NO_MEMORY;
    5811             : 
    5812           0 :         if (smbXcli_conn_has_async_calls(cli->conn)) {
    5813             :                 /*
    5814             :                  * Can't use sync call while an async call is in flight
    5815             :                  */
    5816           0 :                 status = NT_STATUS_INVALID_PARAMETER;
    5817           0 :                 goto fail;
    5818             :         }
    5819           0 :         ev = samba_tevent_context_init(frame);
    5820           0 :         if (ev == NULL) {
    5821           0 :                 goto fail;
    5822             :         }
    5823           0 :         req = cli_posix_open_send(
    5824             :                 frame, ev, cli, fname, flags, mode);
    5825           0 :         if (req == NULL) {
    5826           0 :                 goto fail;
    5827             :         }
    5828           0 :         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
    5829           0 :                 goto fail;
    5830             :         }
    5831           0 :         status = cli_posix_open_recv(req, pfnum);
    5832           0 :  fail:
    5833           0 :         TALLOC_FREE(frame);
    5834           0 :         return status;
    5835             : }
    5836             : 
    5837             : struct cli_posix_mkdir_state {
    5838             :         struct tevent_context *ev;
    5839             :         struct cli_state *cli;
    5840             : };
    5841             : 
    5842             : static void cli_posix_mkdir_done(struct tevent_req *subreq);
    5843             : 
    5844           0 : struct tevent_req *cli_posix_mkdir_send(TALLOC_CTX *mem_ctx,
    5845             :                                         struct tevent_context *ev,
    5846             :                                         struct cli_state *cli,
    5847             :                                         const char *fname,
    5848             :                                         mode_t mode)
    5849             : {
    5850           0 :         struct tevent_req *req = NULL, *subreq = NULL;
    5851           0 :         struct cli_posix_mkdir_state *state = NULL;
    5852             :         uint32_t wire_flags;
    5853             : 
    5854           0 :         req = tevent_req_create(
    5855             :                 mem_ctx, &state, struct cli_posix_mkdir_state);
    5856           0 :         if (req == NULL) {
    5857           0 :                 return NULL;
    5858             :         }
    5859           0 :         state->ev = ev;
    5860           0 :         state->cli = cli;
    5861             : 
    5862           0 :         wire_flags = SMB_O_CREAT | SMB_O_DIRECTORY;
    5863             : 
    5864           0 :         subreq = cli_posix_open_internal_send(
    5865             :                 mem_ctx, ev, cli, fname, wire_flags, mode);
    5866           0 :         if (tevent_req_nomem(subreq, req)) {
    5867           0 :                 return tevent_req_post(req, ev);
    5868             :         }
    5869           0 :         tevent_req_set_callback(subreq, cli_posix_mkdir_done, req);
    5870           0 :         return req;
    5871             : }
    5872             : 
    5873           0 : static void cli_posix_mkdir_done(struct tevent_req *subreq)
    5874             : {
    5875           0 :         struct tevent_req *req = tevent_req_callback_data(
    5876             :                 subreq, struct tevent_req);
    5877             :         NTSTATUS status;
    5878             :         uint16_t fnum;
    5879             : 
    5880           0 :         status = cli_posix_open_internal_recv(subreq, &fnum);
    5881           0 :         TALLOC_FREE(subreq);
    5882           0 :         if (tevent_req_nterror(req, status)) {
    5883           0 :                 return;
    5884             :         }
    5885           0 :         tevent_req_done(req);
    5886             : }
    5887             : 
    5888           0 : NTSTATUS cli_posix_mkdir_recv(struct tevent_req *req)
    5889             : {
    5890           0 :         return tevent_req_simple_recv_ntstatus(req);
    5891             : }
    5892             : 
    5893           0 : NTSTATUS cli_posix_mkdir(struct cli_state *cli, const char *fname, mode_t mode)
    5894             : {
    5895           0 :         TALLOC_CTX *frame = talloc_stackframe();
    5896           0 :         struct tevent_context *ev = NULL;
    5897           0 :         struct tevent_req *req = NULL;
    5898           0 :         NTSTATUS status = NT_STATUS_NO_MEMORY;
    5899             : 
    5900           0 :         if (smbXcli_conn_has_async_calls(cli->conn)) {
    5901             :                 /*
    5902             :                  * Can't use sync call while an async call is in flight
    5903             :                  */
    5904           0 :                 status = NT_STATUS_INVALID_PARAMETER;
    5905           0 :                 goto fail;
    5906             :         }
    5907             : 
    5908           0 :         ev = samba_tevent_context_init(frame);
    5909           0 :         if (ev == NULL) {
    5910           0 :                 goto fail;
    5911             :         }
    5912           0 :         req = cli_posix_mkdir_send(
    5913             :                 frame, ev, cli, fname, mode);
    5914           0 :         if (req == NULL) {
    5915           0 :                 goto fail;
    5916             :         }
    5917           0 :         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
    5918           0 :                 goto fail;
    5919             :         }
    5920           0 :         status = cli_posix_mkdir_recv(req);
    5921           0 :  fail:
    5922           0 :         TALLOC_FREE(frame);
    5923           0 :         return status;
    5924             : }
    5925             : 
    5926             : /****************************************************************************
    5927             :  unlink or rmdir - POSIX semantics.
    5928             : ****************************************************************************/
    5929             : 
    5930             : struct cli_posix_unlink_internal_state {
    5931             :         uint8_t data[2];
    5932             : };
    5933             : 
    5934             : static void cli_posix_unlink_internal_done(struct tevent_req *subreq);
    5935             : 
    5936           0 : static struct tevent_req *cli_posix_unlink_internal_send(TALLOC_CTX *mem_ctx,
    5937             :                                         struct tevent_context *ev,
    5938             :                                         struct cli_state *cli,
    5939             :                                         const char *fname,
    5940             :                                         uint16_t level)
    5941             : {
    5942           0 :         struct tevent_req *req = NULL, *subreq = NULL;
    5943           0 :         struct cli_posix_unlink_internal_state *state = NULL;
    5944             : 
    5945           0 :         req = tevent_req_create(mem_ctx, &state,
    5946             :                                 struct cli_posix_unlink_internal_state);
    5947           0 :         if (req == NULL) {
    5948           0 :                 return NULL;
    5949             :         }
    5950             : 
    5951             :         /* Setup data word. */
    5952           0 :         SSVAL(state->data, 0, level);
    5953             : 
    5954           0 :         subreq = cli_setpathinfo_send(state, ev, cli,
    5955             :                                       SMB_POSIX_PATH_UNLINK,
    5956             :                                       fname,
    5957           0 :                                       state->data, sizeof(state->data));
    5958           0 :         if (tevent_req_nomem(subreq, req)) {
    5959           0 :                 return tevent_req_post(req, ev);
    5960             :         }
    5961           0 :         tevent_req_set_callback(subreq, cli_posix_unlink_internal_done, req);
    5962           0 :         return req;
    5963             : }
    5964             : 
    5965           0 : static void cli_posix_unlink_internal_done(struct tevent_req *subreq)
    5966             : {
    5967           0 :         NTSTATUS status = cli_setpathinfo_recv(subreq);
    5968           0 :         tevent_req_simple_finish_ntstatus(subreq, status);
    5969           0 : }
    5970             : 
    5971           0 : static NTSTATUS cli_posix_unlink_internal_recv(struct tevent_req *req)
    5972             : {
    5973           0 :         return tevent_req_simple_recv_ntstatus(req);
    5974             : }
    5975             : 
    5976             : struct cli_posix_unlink_state {
    5977             :         uint8_t dummy;
    5978             : };
    5979             : 
    5980             : static void cli_posix_unlink_done(struct tevent_req *subreq);
    5981             : 
    5982           0 : struct tevent_req *cli_posix_unlink_send(TALLOC_CTX *mem_ctx,
    5983             :                                         struct tevent_context *ev,
    5984             :                                         struct cli_state *cli,
    5985             :                                         const char *fname)
    5986             : {
    5987           0 :         struct tevent_req *req = NULL, *subreq = NULL;
    5988             :         struct cli_posix_unlink_state *state;
    5989             : 
    5990           0 :         req = tevent_req_create(
    5991             :                 mem_ctx, &state, struct cli_posix_unlink_state);
    5992           0 :         if (req == NULL) {
    5993           0 :                 return NULL;
    5994             :         }
    5995           0 :         subreq = cli_posix_unlink_internal_send(
    5996             :                 mem_ctx, ev, cli, fname, SMB_POSIX_UNLINK_FILE_TARGET);
    5997           0 :         if (tevent_req_nomem(subreq, req)) {
    5998           0 :                 return tevent_req_post(req, ev);
    5999             :         }
    6000           0 :         tevent_req_set_callback(subreq, cli_posix_unlink_done, req);
    6001           0 :         return req;
    6002             : }
    6003             : 
    6004           0 : static void cli_posix_unlink_done(struct tevent_req *subreq)
    6005             : {
    6006           0 :         NTSTATUS status = cli_posix_unlink_internal_recv(subreq);
    6007           0 :         tevent_req_simple_finish_ntstatus(subreq, status);
    6008           0 : }
    6009             : 
    6010           0 : NTSTATUS cli_posix_unlink_recv(struct tevent_req *req)
    6011             : {
    6012           0 :         return tevent_req_simple_recv_ntstatus(req);
    6013             : }
    6014             : 
    6015             : /****************************************************************************
    6016             :  unlink - POSIX semantics.
    6017             : ****************************************************************************/
    6018             : 
    6019           0 : NTSTATUS cli_posix_unlink(struct cli_state *cli, const char *fname)
    6020             : {
    6021           0 :         TALLOC_CTX *frame = talloc_stackframe();
    6022           0 :         struct tevent_context *ev = NULL;
    6023           0 :         struct tevent_req *req = NULL;
    6024           0 :         NTSTATUS status = NT_STATUS_OK;
    6025             : 
    6026           0 :         if (smbXcli_conn_has_async_calls(cli->conn)) {
    6027             :                 /*
    6028             :                  * Can't use sync call while an async call is in flight
    6029             :                  */
    6030           0 :                 status = NT_STATUS_INVALID_PARAMETER;
    6031           0 :                 goto fail;
    6032             :         }
    6033             : 
    6034           0 :         ev = samba_tevent_context_init(frame);
    6035           0 :         if (ev == NULL) {
    6036           0 :                 status = NT_STATUS_NO_MEMORY;
    6037           0 :                 goto fail;
    6038             :         }
    6039             : 
    6040           0 :         req = cli_posix_unlink_send(frame,
    6041             :                                 ev,
    6042             :                                 cli,
    6043             :                                 fname);
    6044           0 :         if (req == NULL) {
    6045           0 :                 status = NT_STATUS_NO_MEMORY;
    6046           0 :                 goto fail;
    6047             :         }
    6048             : 
    6049           0 :         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
    6050           0 :                 goto fail;
    6051             :         }
    6052             : 
    6053           0 :         status = cli_posix_unlink_recv(req);
    6054             : 
    6055           0 :  fail:
    6056           0 :         TALLOC_FREE(frame);
    6057           0 :         return status;
    6058             : }
    6059             : 
    6060             : /****************************************************************************
    6061             :  rmdir - POSIX semantics.
    6062             : ****************************************************************************/
    6063             : 
    6064             : struct cli_posix_rmdir_state {
    6065             :         uint8_t dummy;
    6066             : };
    6067             : 
    6068             : static void cli_posix_rmdir_done(struct tevent_req *subreq);
    6069             : 
    6070           0 : struct tevent_req *cli_posix_rmdir_send(TALLOC_CTX *mem_ctx,
    6071             :                                         struct tevent_context *ev,
    6072             :                                         struct cli_state *cli,
    6073             :                                         const char *fname)
    6074             : {
    6075           0 :         struct tevent_req *req = NULL, *subreq = NULL;
    6076             :         struct cli_posix_rmdir_state *state;
    6077             : 
    6078           0 :         req = tevent_req_create(mem_ctx, &state, struct cli_posix_rmdir_state);
    6079           0 :         if (req == NULL) {
    6080           0 :                 return NULL;
    6081             :         }
    6082           0 :         subreq = cli_posix_unlink_internal_send(
    6083             :                 mem_ctx, ev, cli, fname, SMB_POSIX_UNLINK_DIRECTORY_TARGET);
    6084           0 :         if (tevent_req_nomem(subreq, req)) {
    6085           0 :                 return tevent_req_post(req, ev);
    6086             :         }
    6087           0 :         tevent_req_set_callback(subreq, cli_posix_rmdir_done, req);
    6088           0 :         return req;
    6089             : }
    6090             : 
    6091           0 : static void cli_posix_rmdir_done(struct tevent_req *subreq)
    6092             : {
    6093           0 :         NTSTATUS status = cli_posix_unlink_internal_recv(subreq);
    6094           0 :         tevent_req_simple_finish_ntstatus(subreq, status);
    6095           0 : }
    6096             : 
    6097           0 : NTSTATUS cli_posix_rmdir_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx)
    6098             : {
    6099           0 :         return tevent_req_simple_recv_ntstatus(req);
    6100             : }
    6101             : 
    6102           0 : NTSTATUS cli_posix_rmdir(struct cli_state *cli, const char *fname)
    6103             : {
    6104           0 :         TALLOC_CTX *frame = talloc_stackframe();
    6105           0 :         struct tevent_context *ev = NULL;
    6106           0 :         struct tevent_req *req = NULL;
    6107           0 :         NTSTATUS status = NT_STATUS_OK;
    6108             : 
    6109           0 :         if (smbXcli_conn_has_async_calls(cli->conn)) {
    6110             :                 /*
    6111             :                  * Can't use sync call while an async call is in flight
    6112             :                  */
    6113           0 :                 status = NT_STATUS_INVALID_PARAMETER;
    6114           0 :                 goto fail;
    6115             :         }
    6116             : 
    6117           0 :         ev = samba_tevent_context_init(frame);
    6118           0 :         if (ev == NULL) {
    6119           0 :                 status = NT_STATUS_NO_MEMORY;
    6120           0 :                 goto fail;
    6121             :         }
    6122             : 
    6123           0 :         req = cli_posix_rmdir_send(frame,
    6124             :                                 ev,
    6125             :                                 cli,
    6126             :                                 fname);
    6127           0 :         if (req == NULL) {
    6128           0 :                 status = NT_STATUS_NO_MEMORY;
    6129           0 :                 goto fail;
    6130             :         }
    6131             : 
    6132           0 :         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
    6133           0 :                 goto fail;
    6134             :         }
    6135             : 
    6136           0 :         status = cli_posix_rmdir_recv(req, frame);
    6137             : 
    6138           0 :  fail:
    6139           0 :         TALLOC_FREE(frame);
    6140           0 :         return status;
    6141             : }
    6142             : 
    6143             : /****************************************************************************
    6144             :  filechangenotify
    6145             : ****************************************************************************/
    6146             : 
    6147             : struct cli_notify_state {
    6148             :         struct tevent_req *subreq;
    6149             :         uint8_t setup[8];
    6150             :         uint32_t num_changes;
    6151             :         struct notify_change *changes;
    6152             : };
    6153             : 
    6154             : static void cli_notify_done(struct tevent_req *subreq);
    6155             : static void cli_notify_done_smb2(struct tevent_req *subreq);
    6156             : static bool cli_notify_cancel(struct tevent_req *req);
    6157             : 
    6158          42 : struct tevent_req *cli_notify_send(TALLOC_CTX *mem_ctx,
    6159             :                                    struct tevent_context *ev,
    6160             :                                    struct cli_state *cli, uint16_t fnum,
    6161             :                                    uint32_t buffer_size,
    6162             :                                    uint32_t completion_filter, bool recursive)
    6163             : {
    6164             :         struct tevent_req *req;
    6165             :         struct cli_notify_state *state;
    6166             :         unsigned old_timeout;
    6167             : 
    6168          42 :         req = tevent_req_create(mem_ctx, &state, struct cli_notify_state);
    6169          42 :         if (req == NULL) {
    6170           0 :                 return NULL;
    6171             :         }
    6172             : 
    6173          42 :         if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
    6174             :                 /*
    6175             :                  * Notifies should not time out
    6176             :                  */
    6177          42 :                 old_timeout = cli_set_timeout(cli, 0);
    6178             : 
    6179          42 :                 state->subreq = cli_smb2_notify_send(
    6180             :                         state,
    6181             :                         ev,
    6182             :                         cli,
    6183             :                         fnum,
    6184             :                         buffer_size,
    6185             :                         completion_filter,
    6186             :                         recursive);
    6187             : 
    6188          42 :                 cli_set_timeout(cli, old_timeout);
    6189             : 
    6190          42 :                 if (tevent_req_nomem(state->subreq, req)) {
    6191           0 :                         return tevent_req_post(req, ev);
    6192             :                 }
    6193          42 :                 tevent_req_set_callback(
    6194          42 :                         state->subreq, cli_notify_done_smb2, req);
    6195          42 :                 goto done;
    6196             :         }
    6197             : 
    6198           0 :         SIVAL(state->setup, 0, completion_filter);
    6199           0 :         SSVAL(state->setup, 4, fnum);
    6200           0 :         SSVAL(state->setup, 6, recursive);
    6201             : 
    6202             :         /*
    6203             :          * Notifies should not time out
    6204             :          */
    6205           0 :         old_timeout = cli_set_timeout(cli, 0);
    6206             : 
    6207           0 :         state->subreq = cli_trans_send(
    6208             :                 state,                  /* mem ctx. */
    6209             :                 ev,                     /* event ctx. */
    6210             :                 cli,                    /* cli_state. */
    6211             :                 0,                      /* additional_flags2 */
    6212             :                 SMBnttrans,             /* cmd. */
    6213             :                 NULL,                   /* pipe name. */
    6214             :                 -1,                     /* fid. */
    6215             :                 NT_TRANSACT_NOTIFY_CHANGE, /* function. */
    6216             :                 0,                      /* flags. */
    6217           0 :                 (uint16_t *)state->setup, /* setup. */
    6218             :                 4,                      /* num setup uint16_t words. */
    6219             :                 0,                      /* max returned setup. */
    6220             :                 NULL,                   /* param. */
    6221             :                 0,                      /* num param. */
    6222             :                 buffer_size,            /* max returned param. */
    6223             :                 NULL,                   /* data. */
    6224             :                 0,                      /* num data. */
    6225             :                 0);                     /* max returned data. */
    6226             : 
    6227           0 :         cli_set_timeout(cli, old_timeout);
    6228             : 
    6229           0 :         if (tevent_req_nomem(state->subreq, req)) {
    6230           0 :                 return tevent_req_post(req, ev);
    6231             :         }
    6232           0 :         tevent_req_set_callback(state->subreq, cli_notify_done, req);
    6233          42 : done:
    6234          42 :         tevent_req_set_cancel_fn(req, cli_notify_cancel);
    6235          42 :         return req;
    6236             : }
    6237             : 
    6238           0 : static bool cli_notify_cancel(struct tevent_req *req)
    6239             : {
    6240           0 :         struct cli_notify_state *state = tevent_req_data(
    6241             :                 req, struct cli_notify_state);
    6242             :         bool ok;
    6243             : 
    6244           0 :         ok = tevent_req_cancel(state->subreq);
    6245           0 :         return ok;
    6246             : }
    6247             : 
    6248           0 : static void cli_notify_done(struct tevent_req *subreq)
    6249             : {
    6250           0 :         struct tevent_req *req = tevent_req_callback_data(
    6251             :                 subreq, struct tevent_req);
    6252           0 :         struct cli_notify_state *state = tevent_req_data(
    6253             :                 req, struct cli_notify_state);
    6254             :         NTSTATUS status;
    6255             :         uint8_t *params;
    6256             :         uint32_t i, ofs, num_params;
    6257             :         uint16_t flags2;
    6258             : 
    6259           0 :         status = cli_trans_recv(subreq, talloc_tos(), &flags2, NULL, 0, NULL,
    6260             :                                 &params, 0, &num_params, NULL, 0, NULL);
    6261           0 :         TALLOC_FREE(subreq);
    6262           0 :         state->subreq = NULL;
    6263           0 :         if (tevent_req_nterror(req, status)) {
    6264           0 :                 DEBUG(10, ("cli_trans_recv returned %s\n", nt_errstr(status)));
    6265           0 :                 return;
    6266             :         }
    6267             : 
    6268           0 :         state->num_changes = 0;
    6269           0 :         ofs = 0;
    6270             : 
    6271           0 :         while (num_params - ofs > 12) {
    6272           0 :                 uint32_t next = IVAL(params, ofs);
    6273           0 :                 state->num_changes += 1;
    6274             : 
    6275           0 :                 if ((next == 0) || (ofs+next >= num_params)) {
    6276             :                         break;
    6277             :                 }
    6278           0 :                 ofs += next;
    6279             :         }
    6280             : 
    6281           0 :         state->changes = talloc_array(state, struct notify_change,
    6282             :                                       state->num_changes);
    6283           0 :         if (tevent_req_nomem(state->changes, req)) {
    6284           0 :                 TALLOC_FREE(params);
    6285           0 :                 return;
    6286             :         }
    6287             : 
    6288           0 :         ofs = 0;
    6289             : 
    6290           0 :         for (i=0; i<state->num_changes; i++) {
    6291           0 :                 uint32_t next = IVAL(params, ofs);
    6292           0 :                 uint32_t len = IVAL(params, ofs+8);
    6293             :                 ssize_t ret;
    6294             :                 char *name;
    6295             : 
    6296           0 :                 if (smb_buffer_oob(num_params, ofs + 12, len)) {
    6297           0 :                         TALLOC_FREE(params);
    6298           0 :                         tevent_req_nterror(
    6299             :                                 req, NT_STATUS_INVALID_NETWORK_RESPONSE);
    6300           0 :                         return;
    6301             :                 }
    6302             : 
    6303           0 :                 state->changes[i].action = IVAL(params, ofs+4);
    6304           0 :                 ret = pull_string_talloc(state->changes,
    6305             :                                          (char *)params,
    6306             :                                          flags2,
    6307             :                                          &name,
    6308           0 :                                          params+ofs+12,
    6309             :                                          len,
    6310             :                                          STR_TERMINATE|STR_UNICODE);
    6311           0 :                 if (ret == -1) {
    6312           0 :                         TALLOC_FREE(params);
    6313           0 :                         tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
    6314           0 :                         return;
    6315             :                 }
    6316           0 :                 state->changes[i].name = name;
    6317           0 :                 ofs += next;
    6318             :         }
    6319             : 
    6320           0 :         TALLOC_FREE(params);
    6321           0 :         tevent_req_done(req);
    6322             : }
    6323             : 
    6324          42 : static void cli_notify_done_smb2(struct tevent_req *subreq)
    6325             : {
    6326          42 :         struct tevent_req *req = tevent_req_callback_data(
    6327             :                 subreq, struct tevent_req);
    6328          42 :         struct cli_notify_state *state = tevent_req_data(
    6329             :                 req, struct cli_notify_state);
    6330             :         NTSTATUS status;
    6331             : 
    6332          42 :         status = cli_smb2_notify_recv(
    6333             :                 subreq,
    6334             :                 state,
    6335             :                 &state->changes,
    6336             :                 &state->num_changes);
    6337          42 :         TALLOC_FREE(subreq);
    6338          42 :         if (tevent_req_nterror(req, status)) {
    6339          12 :                 return;
    6340             :         }
    6341          30 :         tevent_req_done(req);
    6342             : }
    6343             : 
    6344          42 : NTSTATUS cli_notify_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
    6345             :                          uint32_t *pnum_changes,
    6346             :                          struct notify_change **pchanges)
    6347             : {
    6348          42 :         struct cli_notify_state *state = tevent_req_data(
    6349             :                 req, struct cli_notify_state);
    6350             :         NTSTATUS status;
    6351             : 
    6352          42 :         if (tevent_req_is_nterror(req, &status)) {
    6353          12 :                 return status;
    6354             :         }
    6355             : 
    6356          30 :         *pnum_changes = state->num_changes;
    6357          30 :         *pchanges = talloc_move(mem_ctx, &state->changes);
    6358          30 :         return NT_STATUS_OK;
    6359             : }
    6360             : 
    6361           0 : NTSTATUS cli_notify(struct cli_state *cli, uint16_t fnum, uint32_t buffer_size,
    6362             :                     uint32_t completion_filter, bool recursive,
    6363             :                     TALLOC_CTX *mem_ctx, uint32_t *pnum_changes,
    6364             :                     struct notify_change **pchanges)
    6365             : {
    6366             :         TALLOC_CTX *frame;
    6367             :         struct tevent_context *ev;
    6368             :         struct tevent_req *req;
    6369           0 :         NTSTATUS status = NT_STATUS_NO_MEMORY;
    6370             : 
    6371           0 :         frame = talloc_stackframe();
    6372             : 
    6373           0 :         if (smbXcli_conn_has_async_calls(cli->conn)) {
    6374             :                 /*
    6375             :                  * Can't use sync call while an async call is in flight
    6376             :                  */
    6377           0 :                 status = NT_STATUS_INVALID_PARAMETER;
    6378           0 :                 goto fail;
    6379             :         }
    6380           0 :         ev = samba_tevent_context_init(frame);
    6381           0 :         if (ev == NULL) {
    6382           0 :                 goto fail;
    6383             :         }
    6384           0 :         req = cli_notify_send(ev, ev, cli, fnum, buffer_size,
    6385             :                               completion_filter, recursive);
    6386           0 :         if (req == NULL) {
    6387           0 :                 goto fail;
    6388             :         }
    6389           0 :         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
    6390           0 :                 goto fail;
    6391             :         }
    6392           0 :         status = cli_notify_recv(req, mem_ctx, pnum_changes, pchanges);
    6393           0 :  fail:
    6394           0 :         TALLOC_FREE(frame);
    6395           0 :         return status;
    6396             : }
    6397             : 
    6398             : struct cli_qpathinfo_state {
    6399             :         uint8_t *param;
    6400             :         uint8_t *data;
    6401             :         uint16_t setup[1];
    6402             :         uint32_t min_rdata;
    6403             :         uint8_t *rdata;
    6404             :         uint32_t num_rdata;
    6405             : };
    6406             : 
    6407             : static void cli_qpathinfo_done(struct tevent_req *subreq);
    6408             : 
    6409           4 : struct tevent_req *cli_qpathinfo_send(TALLOC_CTX *mem_ctx,
    6410             :                                       struct tevent_context *ev,
    6411             :                                       struct cli_state *cli, const char *fname,
    6412             :                                       uint16_t level, uint32_t min_rdata,
    6413             :                                       uint32_t max_rdata)
    6414             : {
    6415             :         struct tevent_req *req, *subreq;
    6416             :         struct cli_qpathinfo_state *state;
    6417           4 :         uint16_t additional_flags2 = 0;
    6418             : 
    6419           4 :         req = tevent_req_create(mem_ctx, &state, struct cli_qpathinfo_state);
    6420           4 :         if (req == NULL) {
    6421           0 :                 return NULL;
    6422             :         }
    6423           4 :         state->min_rdata = min_rdata;
    6424           4 :         SSVAL(state->setup, 0, TRANSACT2_QPATHINFO);
    6425             : 
    6426           4 :         state->param = talloc_zero_array(state, uint8_t, 6);
    6427           4 :         if (tevent_req_nomem(state->param, req)) {
    6428           0 :                 return tevent_req_post(req, ev);
    6429             :         }
    6430           4 :         SSVAL(state->param, 0, level);
    6431          12 :         state->param = trans2_bytes_push_str(
    6432          12 :                 state->param, smbXcli_conn_use_unicode(cli->conn), fname, strlen(fname)+1, NULL);
    6433           4 :         if (tevent_req_nomem(state->param, req)) {
    6434           0 :                 return tevent_req_post(req, ev);
    6435             :         }
    6436             : 
    6437           4 :         if (clistr_is_previous_version_path(fname, NULL, NULL, NULL) &&
    6438           0 :                         !INFO_LEVEL_IS_UNIX(level)) {
    6439           0 :                 additional_flags2 = FLAGS2_REPARSE_PATH;
    6440             :         }
    6441             : 
    6442          12 :         subreq = cli_trans_send(
    6443             :                 state,                  /* mem ctx. */
    6444             :                 ev,                     /* event ctx. */
    6445             :                 cli,                    /* cli_state. */
    6446             :                 additional_flags2,      /* additional_flags2 */
    6447             :                 SMBtrans2,              /* cmd. */
    6448             :                 NULL,                   /* pipe name. */
    6449             :                 -1,                     /* fid. */
    6450             :                 0,                      /* function. */
    6451             :                 0,                      /* flags. */
    6452           4 :                 state->setup,                /* setup. */
    6453             :                 1,                      /* num setup uint16_t words. */
    6454             :                 0,                      /* max returned setup. */
    6455           4 :                 state->param,                /* param. */
    6456           4 :                 talloc_get_size(state->param),       /* num param. */
    6457             :                 2,                      /* max returned param. */
    6458             :                 NULL,                   /* data. */
    6459             :                 0,                      /* num data. */
    6460             :                 max_rdata);             /* max returned data. */
    6461             : 
    6462           4 :         if (tevent_req_nomem(subreq, req)) {
    6463           0 :                 return tevent_req_post(req, ev);
    6464             :         }
    6465           4 :         tevent_req_set_callback(subreq, cli_qpathinfo_done, req);
    6466           4 :         return req;
    6467             : }
    6468             : 
    6469           4 : static void cli_qpathinfo_done(struct tevent_req *subreq)
    6470             : {
    6471           4 :         struct tevent_req *req = tevent_req_callback_data(
    6472             :                 subreq, struct tevent_req);
    6473           4 :         struct cli_qpathinfo_state *state = tevent_req_data(
    6474             :                 req, struct cli_qpathinfo_state);
    6475             :         NTSTATUS status;
    6476             : 
    6477           4 :         status = cli_trans_recv(subreq, state, NULL, NULL, 0, NULL,
    6478             :                                 NULL, 0, NULL,
    6479             :                                 &state->rdata, state->min_rdata,
    6480             :                                 &state->num_rdata);
    6481           4 :         if (tevent_req_nterror(req, status)) {
    6482           0 :                 return;
    6483             :         }
    6484           4 :         tevent_req_done(req);
    6485             : }
    6486             : 
    6487           4 : NTSTATUS cli_qpathinfo_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
    6488             :                             uint8_t **rdata, uint32_t *num_rdata)
    6489             : {
    6490           4 :         struct cli_qpathinfo_state *state = tevent_req_data(
    6491             :                 req, struct cli_qpathinfo_state);
    6492             :         NTSTATUS status;
    6493             : 
    6494           4 :         if (tevent_req_is_nterror(req, &status)) {
    6495           0 :                 return status;
    6496             :         }
    6497           4 :         if (rdata != NULL) {
    6498           4 :                 *rdata = talloc_move(mem_ctx, &state->rdata);
    6499             :         } else {
    6500           0 :                 TALLOC_FREE(state->rdata);
    6501             :         }
    6502           4 :         if (num_rdata != NULL) {
    6503           4 :                 *num_rdata = state->num_rdata;
    6504             :         }
    6505           4 :         return NT_STATUS_OK;
    6506             : }
    6507             : 
    6508           0 : NTSTATUS cli_qpathinfo(TALLOC_CTX *mem_ctx, struct cli_state *cli,
    6509             :                        const char *fname, uint16_t level, uint32_t min_rdata,
    6510             :                        uint32_t max_rdata,
    6511             :                        uint8_t **rdata, uint32_t *num_rdata)
    6512             : {
    6513           0 :         TALLOC_CTX *frame = talloc_stackframe();
    6514             :         struct tevent_context *ev;
    6515             :         struct tevent_req *req;
    6516           0 :         NTSTATUS status = NT_STATUS_NO_MEMORY;
    6517             : 
    6518           0 :         if (smbXcli_conn_has_async_calls(cli->conn)) {
    6519             :                 /*
    6520             :                  * Can't use sync call while an async call is in flight
    6521             :                  */
    6522           0 :                 status = NT_STATUS_INVALID_PARAMETER;
    6523           0 :                 goto fail;
    6524             :         }
    6525           0 :         ev = samba_tevent_context_init(frame);
    6526           0 :         if (ev == NULL) {
    6527           0 :                 goto fail;
    6528             :         }
    6529           0 :         req = cli_qpathinfo_send(frame, ev, cli, fname, level, min_rdata,
    6530             :                                  max_rdata);
    6531           0 :         if (req == NULL) {
    6532           0 :                 goto fail;
    6533             :         }
    6534           0 :         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
    6535           0 :                 goto fail;
    6536             :         }
    6537           0 :         status = cli_qpathinfo_recv(req, mem_ctx, rdata, num_rdata);
    6538           0 :  fail:
    6539           0 :         TALLOC_FREE(frame);
    6540           0 :         return status;
    6541             : }
    6542             : 
    6543             : struct cli_qfileinfo_state {
    6544             :         uint16_t setup[1];
    6545             :         uint8_t param[4];
    6546             :         uint8_t *data;
    6547             :         uint16_t recv_flags2;
    6548             :         uint32_t min_rdata;
    6549             :         uint8_t *rdata;
    6550             :         uint32_t num_rdata;
    6551             : };
    6552             : 
    6553             : static void cli_qfileinfo_done(struct tevent_req *subreq);
    6554             : 
    6555          42 : struct tevent_req *cli_qfileinfo_send(TALLOC_CTX *mem_ctx,
    6556             :                                       struct tevent_context *ev,
    6557             :                                       struct cli_state *cli, uint16_t fnum,
    6558             :                                       uint16_t level, uint32_t min_rdata,
    6559             :                                       uint32_t max_rdata)
    6560             : {
    6561             :         struct tevent_req *req, *subreq;
    6562             :         struct cli_qfileinfo_state *state;
    6563             : 
    6564          42 :         req = tevent_req_create(mem_ctx, &state, struct cli_qfileinfo_state);
    6565          42 :         if (req == NULL) {
    6566           0 :                 return NULL;
    6567             :         }
    6568          42 :         state->min_rdata = min_rdata;
    6569          42 :         SSVAL(state->param, 0, fnum);
    6570          42 :         SSVAL(state->param, 2, level);
    6571          42 :         SSVAL(state->setup, 0, TRANSACT2_QFILEINFO);
    6572             : 
    6573          42 :         subreq = cli_trans_send(
    6574             :                 state,                  /* mem ctx. */
    6575             :                 ev,                     /* event ctx. */
    6576             :                 cli,                    /* cli_state. */
    6577             :                 0,                      /* additional_flags2 */
    6578             :                 SMBtrans2,              /* cmd. */
    6579             :                 NULL,                   /* pipe name. */
    6580             :                 -1,                     /* fid. */
    6581             :                 0,                      /* function. */
    6582             :                 0,                      /* flags. */
    6583          42 :                 state->setup,                /* setup. */
    6584             :                 1,                      /* num setup uint16_t words. */
    6585             :                 0,                      /* max returned setup. */
    6586          42 :                 state->param,                /* param. */
    6587             :                 sizeof(state->param),        /* num param. */
    6588             :                 2,                      /* max returned param. */
    6589             :                 NULL,                   /* data. */
    6590             :                 0,                      /* num data. */
    6591             :                 max_rdata);             /* max returned data. */
    6592             : 
    6593          42 :         if (tevent_req_nomem(subreq, req)) {
    6594           0 :                 return tevent_req_post(req, ev);
    6595             :         }
    6596          42 :         tevent_req_set_callback(subreq, cli_qfileinfo_done, req);
    6597          42 :         return req;
    6598             : }
    6599             : 
    6600          42 : static void cli_qfileinfo_done(struct tevent_req *subreq)
    6601             : {
    6602          42 :         struct tevent_req *req = tevent_req_callback_data(
    6603             :                 subreq, struct tevent_req);
    6604          42 :         struct cli_qfileinfo_state *state = tevent_req_data(
    6605             :                 req, struct cli_qfileinfo_state);
    6606             :         NTSTATUS status;
    6607             : 
    6608          42 :         status = cli_trans_recv(subreq, state,
    6609             :                                 &state->recv_flags2,
    6610             :                                 NULL, 0, NULL,
    6611             :                                 NULL, 0, NULL,
    6612             :                                 &state->rdata, state->min_rdata,
    6613             :                                 &state->num_rdata);
    6614          42 :         if (tevent_req_nterror(req, status)) {
    6615          36 :                 return;
    6616             :         }
    6617           6 :         tevent_req_done(req);
    6618             : }
    6619             : 
    6620          42 : NTSTATUS cli_qfileinfo_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
    6621             :                             uint16_t *recv_flags2,
    6622             :                             uint8_t **rdata, uint32_t *num_rdata)
    6623             : {
    6624          42 :         struct cli_qfileinfo_state *state = tevent_req_data(
    6625             :                 req, struct cli_qfileinfo_state);
    6626             :         NTSTATUS status;
    6627             : 
    6628          42 :         if (tevent_req_is_nterror(req, &status)) {
    6629          36 :                 return status;
    6630             :         }
    6631             : 
    6632           6 :         if (recv_flags2 != NULL) {
    6633           1 :                 *recv_flags2 = state->recv_flags2;
    6634             :         }
    6635           6 :         if (rdata != NULL) {
    6636           6 :                 *rdata = talloc_move(mem_ctx, &state->rdata);
    6637             :         }
    6638           6 :         if (num_rdata != NULL) {
    6639           6 :                 *num_rdata = state->num_rdata;
    6640             :         }
    6641             : 
    6642           6 :         tevent_req_received(req);
    6643           6 :         return NT_STATUS_OK;
    6644             : }
    6645             : 
    6646          37 : NTSTATUS cli_qfileinfo(TALLOC_CTX *mem_ctx, struct cli_state *cli,
    6647             :                        uint16_t fnum, uint16_t level, uint32_t min_rdata,
    6648             :                        uint32_t max_rdata, uint16_t *recv_flags2,
    6649             :                        uint8_t **rdata, uint32_t *num_rdata)
    6650             : {
    6651          37 :         TALLOC_CTX *frame = talloc_stackframe();
    6652             :         struct tevent_context *ev;
    6653             :         struct tevent_req *req;
    6654          37 :         NTSTATUS status = NT_STATUS_NO_MEMORY;
    6655             : 
    6656          37 :         if (smbXcli_conn_has_async_calls(cli->conn)) {
    6657             :                 /*
    6658             :                  * Can't use sync call while an async call is in flight
    6659             :                  */
    6660           0 :                 status = NT_STATUS_INVALID_PARAMETER;
    6661           0 :                 goto fail;
    6662             :         }
    6663          37 :         ev = samba_tevent_context_init(frame);
    6664          37 :         if (ev == NULL) {
    6665           0 :                 goto fail;
    6666             :         }
    6667          37 :         req = cli_qfileinfo_send(frame, ev, cli, fnum, level, min_rdata,
    6668             :                                  max_rdata);
    6669          37 :         if (req == NULL) {
    6670           0 :                 goto fail;
    6671             :         }
    6672          37 :         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
    6673           0 :                 goto fail;
    6674             :         }
    6675          37 :         status = cli_qfileinfo_recv(req, mem_ctx, recv_flags2, rdata, num_rdata);
    6676          37 :  fail:
    6677          37 :         TALLOC_FREE(frame);
    6678          37 :         return status;
    6679             : }
    6680             : 
    6681             : struct cli_flush_state {
    6682             :         uint16_t vwv[1];
    6683             : };
    6684             : 
    6685             : static void cli_flush_done(struct tevent_req *subreq);
    6686             : 
    6687           0 : struct tevent_req *cli_flush_send(TALLOC_CTX *mem_ctx,
    6688             :                                   struct tevent_context *ev,
    6689             :                                   struct cli_state *cli,
    6690             :                                   uint16_t fnum)
    6691             : {
    6692             :         struct tevent_req *req, *subreq;
    6693             :         struct cli_flush_state *state;
    6694             : 
    6695           0 :         req = tevent_req_create(mem_ctx, &state, struct cli_flush_state);
    6696           0 :         if (req == NULL) {
    6697           0 :                 return NULL;
    6698             :         }
    6699           0 :         SSVAL(state->vwv + 0, 0, fnum);
    6700             : 
    6701           0 :         subreq = cli_smb_send(state, ev, cli, SMBflush, 0, 0, 1, state->vwv,
    6702             :                               0, NULL);
    6703           0 :         if (tevent_req_nomem(subreq, req)) {
    6704           0 :                 return tevent_req_post(req, ev);
    6705             :         }
    6706           0 :         tevent_req_set_callback(subreq, cli_flush_done, req);
    6707           0 :         return req;
    6708             : }
    6709             : 
    6710           0 : static void cli_flush_done(struct tevent_req *subreq)
    6711             : {
    6712           0 :         struct tevent_req *req = tevent_req_callback_data(
    6713             :                 subreq, struct tevent_req);
    6714             :         NTSTATUS status;
    6715             : 
    6716           0 :         status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
    6717           0 :         TALLOC_FREE(subreq);
    6718           0 :         if (tevent_req_nterror(req, status)) {
    6719           0 :                 return;
    6720             :         }
    6721           0 :         tevent_req_done(req);
    6722             : }
    6723             : 
    6724           0 : NTSTATUS cli_flush_recv(struct tevent_req *req)
    6725             : {
    6726           0 :         return tevent_req_simple_recv_ntstatus(req);
    6727             : }
    6728             : 
    6729           0 : NTSTATUS cli_flush(TALLOC_CTX *mem_ctx, struct cli_state *cli, uint16_t fnum)
    6730             : {
    6731           0 :         TALLOC_CTX *frame = talloc_stackframe();
    6732             :         struct tevent_context *ev;
    6733             :         struct tevent_req *req;
    6734           0 :         NTSTATUS status = NT_STATUS_NO_MEMORY;
    6735             : 
    6736           0 :         if (smbXcli_conn_has_async_calls(cli->conn)) {
    6737             :                 /*
    6738             :                  * Can't use sync call while an async call is in flight
    6739             :                  */
    6740           0 :                 status = NT_STATUS_INVALID_PARAMETER;
    6741           0 :                 goto fail;
    6742             :         }
    6743           0 :         ev = samba_tevent_context_init(frame);
    6744           0 :         if (ev == NULL) {
    6745           0 :                 goto fail;
    6746             :         }
    6747           0 :         req = cli_flush_send(frame, ev, cli, fnum);
    6748           0 :         if (req == NULL) {
    6749           0 :                 goto fail;
    6750             :         }
    6751           0 :         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
    6752           0 :                 goto fail;
    6753             :         }
    6754           0 :         status = cli_flush_recv(req);
    6755           0 :  fail:
    6756           0 :         TALLOC_FREE(frame);
    6757           0 :         return status;
    6758             : }
    6759             : 
    6760             : struct cli_shadow_copy_data_state {
    6761             :         uint16_t setup[4];
    6762             :         uint8_t *data;
    6763             :         uint32_t num_data;
    6764             :         bool get_names;
    6765             : };
    6766             : 
    6767             : static void cli_shadow_copy_data_done(struct tevent_req *subreq);
    6768             : 
    6769           0 : struct tevent_req *cli_shadow_copy_data_send(TALLOC_CTX *mem_ctx,
    6770             :                                              struct tevent_context *ev,
    6771             :                                              struct cli_state *cli,
    6772             :                                              uint16_t fnum,
    6773             :                                              bool get_names)
    6774             : {
    6775             :         struct tevent_req *req, *subreq;
    6776             :         struct cli_shadow_copy_data_state *state;
    6777             :         uint32_t ret_size;
    6778             : 
    6779           0 :         req = tevent_req_create(mem_ctx, &state,
    6780             :                                 struct cli_shadow_copy_data_state);
    6781           0 :         if (req == NULL) {
    6782           0 :                 return NULL;
    6783             :         }
    6784           0 :         state->get_names = get_names;
    6785           0 :         ret_size = get_names ? CLI_BUFFER_SIZE : 16;
    6786             : 
    6787           0 :         SIVAL(state->setup + 0, 0, FSCTL_GET_SHADOW_COPY_DATA);
    6788           0 :         SSVAL(state->setup + 2, 0, fnum);
    6789           0 :         SCVAL(state->setup + 3, 0, 1); /* isFsctl */
    6790           0 :         SCVAL(state->setup + 3, 1, 0); /* compfilter, isFlags (WSSP) */
    6791             : 
    6792           0 :         subreq = cli_trans_send(
    6793             :                 state, ev, cli, 0, SMBnttrans, NULL, 0, NT_TRANSACT_IOCTL, 0,
    6794           0 :                 state->setup, ARRAY_SIZE(state->setup),
    6795             :                 ARRAY_SIZE(state->setup),
    6796             :                 NULL, 0, 0,
    6797             :                 NULL, 0, ret_size);
    6798           0 :         if (tevent_req_nomem(subreq, req)) {
    6799           0 :                 return tevent_req_post(req, ev);
    6800             :         }
    6801           0 :         tevent_req_set_callback(subreq, cli_shadow_copy_data_done, req);
    6802           0 :         return req;
    6803             : }
    6804             : 
    6805           0 : static void cli_shadow_copy_data_done(struct tevent_req *subreq)
    6806             : {
    6807           0 :         struct tevent_req *req = tevent_req_callback_data(
    6808             :                 subreq, struct tevent_req);
    6809           0 :         struct cli_shadow_copy_data_state *state = tevent_req_data(
    6810             :                 req, struct cli_shadow_copy_data_state);
    6811             :         NTSTATUS status;
    6812             : 
    6813           0 :         status = cli_trans_recv(subreq, state, NULL,
    6814             :                                 NULL, 0, NULL, /* setup */
    6815             :                                 NULL, 0, NULL, /* param */
    6816             :                                 &state->data, 12, &state->num_data);
    6817           0 :         TALLOC_FREE(subreq);
    6818           0 :         if (tevent_req_nterror(req, status)) {
    6819           0 :                 return;
    6820             :         }
    6821           0 :         tevent_req_done(req);
    6822             : }
    6823             : 
    6824           0 : NTSTATUS cli_shadow_copy_data_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
    6825             :                                    char ***pnames, int *pnum_names)
    6826             : {
    6827           0 :         struct cli_shadow_copy_data_state *state = tevent_req_data(
    6828             :                 req, struct cli_shadow_copy_data_state);
    6829           0 :         char **names = NULL;
    6830             :         uint32_t i, num_names;
    6831             :         uint32_t dlength;
    6832           0 :         uint8_t *endp = NULL;
    6833             :         NTSTATUS status;
    6834             : 
    6835           0 :         if (tevent_req_is_nterror(req, &status)) {
    6836           0 :                 return status;
    6837             :         }
    6838             : 
    6839           0 :         if (state->num_data < 16) {
    6840           0 :                 return NT_STATUS_INVALID_NETWORK_RESPONSE;
    6841             :         }
    6842             : 
    6843           0 :         num_names = IVAL(state->data, 4);
    6844           0 :         dlength = IVAL(state->data, 8);
    6845             : 
    6846           0 :         if (num_names > 0x7FFFFFFF) {
    6847           0 :                 return NT_STATUS_INVALID_NETWORK_RESPONSE;
    6848             :         }
    6849             : 
    6850           0 :         if (!state->get_names) {
    6851           0 :                 *pnum_names = (int)num_names;
    6852           0 :                 return NT_STATUS_OK;
    6853             :         }
    6854             : 
    6855           0 :         if (dlength + 12 < 12) {
    6856           0 :                 return NT_STATUS_INVALID_NETWORK_RESPONSE;
    6857             :         }
    6858           0 :         if (dlength + 12 > state->num_data) {
    6859           0 :                 return NT_STATUS_INVALID_NETWORK_RESPONSE;
    6860             :         }
    6861             :         if (state->num_data + (2 * sizeof(SHADOW_COPY_LABEL)) <
    6862             :                         state->num_data) {
    6863             :                 return NT_STATUS_INVALID_NETWORK_RESPONSE;
    6864             :         }
    6865             : 
    6866           0 :         names = talloc_array(mem_ctx, char *, num_names);
    6867           0 :         if (names == NULL) {
    6868           0 :                 return NT_STATUS_NO_MEMORY;
    6869             :         }
    6870             : 
    6871           0 :         endp = state->data + state->num_data;
    6872             : 
    6873           0 :         for (i=0; i<num_names; i++) {
    6874             :                 bool ret;
    6875             :                 uint8_t *src;
    6876             :                 size_t converted_size;
    6877             : 
    6878           0 :                 src = state->data + 12 + i * 2 * sizeof(SHADOW_COPY_LABEL);
    6879             : 
    6880           0 :                 if (src + (2 * sizeof(SHADOW_COPY_LABEL)) > endp) {
    6881           0 :                         return NT_STATUS_INVALID_NETWORK_RESPONSE;
    6882             :                 }
    6883             : 
    6884           0 :                 ret = convert_string_talloc(
    6885             :                         names, CH_UTF16LE, CH_UNIX,
    6886             :                         src, 2 * sizeof(SHADOW_COPY_LABEL),
    6887           0 :                         &names[i], &converted_size);
    6888           0 :                 if (!ret) {
    6889           0 :                         TALLOC_FREE(names);
    6890           0 :                         return NT_STATUS_INVALID_NETWORK_RESPONSE;
    6891             :                 }
    6892             :         }
    6893           0 :         *pnum_names = (int)num_names;
    6894           0 :         *pnames = names;
    6895           0 :         return NT_STATUS_OK;
    6896             : }
    6897             : 
    6898          44 : NTSTATUS cli_shadow_copy_data(TALLOC_CTX *mem_ctx, struct cli_state *cli,
    6899             :                               uint16_t fnum, bool get_names,
    6900             :                               char ***pnames, int *pnum_names)
    6901             : {
    6902          44 :         TALLOC_CTX *frame = NULL;
    6903             :         struct tevent_context *ev;
    6904             :         struct tevent_req *req;
    6905          44 :         NTSTATUS status = NT_STATUS_NO_MEMORY;
    6906             : 
    6907          44 :         if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
    6908          44 :                 return cli_smb2_shadow_copy_data(mem_ctx,
    6909             :                                         cli,
    6910             :                                         fnum,
    6911             :                                         get_names,
    6912             :                                         pnames,
    6913             :                                         pnum_names);
    6914             :         }
    6915             : 
    6916           0 :         frame = talloc_stackframe();
    6917             : 
    6918           0 :         if (smbXcli_conn_has_async_calls(cli->conn)) {
    6919             :                 /*
    6920             :                  * Can't use sync call while an async call is in flight
    6921             :                  */
    6922           0 :                 status = NT_STATUS_INVALID_PARAMETER;
    6923           0 :                 goto fail;
    6924             :         }
    6925           0 :         ev = samba_tevent_context_init(frame);
    6926           0 :         if (ev == NULL) {
    6927           0 :                 goto fail;
    6928             :         }
    6929           0 :         req = cli_shadow_copy_data_send(frame, ev, cli, fnum, get_names);
    6930           0 :         if (req == NULL) {
    6931           0 :                 goto fail;
    6932             :         }
    6933           0 :         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
    6934           0 :                 goto fail;
    6935             :         }
    6936           0 :         status = cli_shadow_copy_data_recv(req, mem_ctx, pnames, pnum_names);
    6937           0 :  fail:
    6938           0 :         TALLOC_FREE(frame);
    6939           0 :         return status;
    6940             : }

Generated by: LCOV version 1.13