LCOV - code coverage report
Current view: top level - source3/libsmb - clifile.c (source / functions) Hit Total Coverage
Test: coverage report for master 2b515b7d Lines: 2309 3496 66.0 %
Date: 2024-02-28 12:06:22 Functions: 210 241 87.1 %

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

Generated by: LCOV version 1.14