Ignore:
Timestamp:
Nov 27, 2012, 4:43:17 PM (13 years ago)
Author:
Silvan Scherrer
Message:

Samba Server: updated trunk to 3.6.0

Location:
trunk/server
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/server

  • trunk/server/source3/libsmb/clifile.c

    r454 r745  
    44   Copyright (C) Andrew Tridgell 1994-1998
    55   Copyright (C) Jeremy Allison 2001-2009
    6    
     6
    77   This program is free software; you can redistribute it and/or modify
    88   it under the terms of the GNU General Public License as published by
    99   the Free Software Foundation; either version 3 of the License, or
    1010   (at your option) any later version.
    11    
     11
    1212   This program is distributed in the hope that it will be useful,
    1313   but WITHOUT ANY WARRANTY; without even the implied warranty of
    1414   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    1515   GNU General Public License for more details.
    16    
     16
    1717   You should have received a copy of the GNU General Public License
    1818   along with this program.  If not, see <http://www.gnu.org/licenses/>.
     
    2020
    2121#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"
    2229
    2330/***********************************************************
     
    9299}
    93100
     101uint8_t *smb_bytes_push_bytes(uint8_t *buf, uint8_t prefix,
     102                              const uint8_t *bytes, size_t num_bytes)
     103{
     104        size_t buflen;
     105
     106        if (buf == NULL) {
     107                return NULL;
     108        }
     109        buflen = talloc_get_size(buf);
     110
     111        buf = TALLOC_REALLOC_ARRAY(NULL, buf, uint8_t,
     112                                   buflen + 1 + num_bytes);
     113        if (buf == NULL) {
     114                return NULL;
     115        }
     116        buf[buflen] = prefix;
     117        memcpy(&buf[buflen+1], bytes, num_bytes);
     118        return buf;
     119}
     120
    94121/***********************************************************
    95122 Same as smb_bytes_push_str(), but without the odd byte
     
    107134}
    108135
     136struct cli_setpathinfo_state {
     137        uint16_t setup;
     138        uint8_t *param;
     139};
     140
     141static void cli_setpathinfo_done(struct tevent_req *subreq);
     142
     143struct tevent_req *cli_setpathinfo_send(TALLOC_CTX *mem_ctx,
     144                                        struct tevent_context *ev,
     145                                        struct cli_state *cli,
     146                                        uint16_t level,
     147                                        const char *path,
     148                                        uint8_t *data,
     149                                        size_t data_len)
     150{
     151        struct tevent_req *req, *subreq;
     152        struct cli_setpathinfo_state *state;
     153
     154        req = tevent_req_create(mem_ctx, &state,
     155                                struct cli_setpathinfo_state);
     156        if (req == NULL) {
     157                return NULL;
     158        }
     159
     160        /* Setup setup word. */
     161        SSVAL(&state->setup, 0, TRANSACT2_SETPATHINFO);
     162
     163        /* Setup param array. */
     164        state->param = TALLOC_ZERO_ARRAY(state, uint8_t, 6);
     165        if (tevent_req_nomem(state->param, req)) {
     166                return tevent_req_post(req, ev);
     167        }
     168        SSVAL(state->param, 0, level);
     169
     170        state->param = trans2_bytes_push_str(
     171                state->param, cli_ucs2(cli), path, strlen(path)+1, NULL);
     172        if (tevent_req_nomem(state->param, req)) {
     173                return tevent_req_post(req, ev);
     174        }
     175
     176        subreq = cli_trans_send(
     177                state,                  /* mem ctx. */
     178                ev,                     /* event ctx. */
     179                cli,                    /* cli_state. */
     180                SMBtrans2,              /* cmd. */
     181                NULL,                   /* pipe name. */
     182                -1,                     /* fid. */
     183                0,                      /* function. */
     184                0,                      /* flags. */
     185                &state->setup,          /* setup. */
     186                1,                      /* num setup uint16_t words. */
     187                0,                      /* max returned setup. */
     188                state->param,           /* param. */
     189                talloc_get_size(state->param),  /* num param. */
     190                2,                      /* max returned param. */
     191                data,                   /* data. */
     192                data_len,               /* num data. */
     193                0);                     /* max returned data. */
     194
     195        if (tevent_req_nomem(subreq, req)) {
     196                return tevent_req_post(req, ev);
     197        }
     198        tevent_req_set_callback(subreq, cli_setpathinfo_done, req);
     199        return req;
     200}
     201
     202static void cli_setpathinfo_done(struct tevent_req *subreq)
     203{
     204        NTSTATUS status = cli_trans_recv(subreq, NULL, NULL, NULL, 0, NULL,
     205                                         NULL, 0, NULL, NULL, 0, NULL);
     206        tevent_req_simple_finish_ntstatus(subreq, status);
     207}
     208
     209NTSTATUS cli_setpathinfo_recv(struct tevent_req *req)
     210{
     211        return tevent_req_simple_recv_ntstatus(req);
     212}
     213
     214NTSTATUS cli_setpathinfo(struct cli_state *cli,
     215                         uint16_t level,
     216                         const char *path,
     217                         uint8_t *data,
     218                         size_t data_len)
     219{
     220        TALLOC_CTX *frame = talloc_stackframe();
     221        struct tevent_context *ev;
     222        struct tevent_req *req;
     223        NTSTATUS status = NT_STATUS_NO_MEMORY;
     224
     225        if (cli_has_async_calls(cli)) {
     226                /*
     227                 * Can't use sync call while an async call is in flight
     228                 */
     229                status = NT_STATUS_INVALID_PARAMETER;
     230                goto fail;
     231        }
     232        ev = tevent_context_init(frame);
     233        if (ev == NULL) {
     234                goto fail;
     235        }
     236        req = cli_setpathinfo_send(ev, ev, cli, level, path, data, data_len);
     237        if (req == NULL) {
     238                goto fail;
     239        }
     240        if (!tevent_req_poll_ntstatus(req, ev, &status)) {
     241                goto fail;
     242        }
     243        status = cli_setpathinfo_recv(req);
     244 fail:
     245        TALLOC_FREE(frame);
     246        return status;
     247}
     248
    109249/****************************************************************************
    110250 Hard/Symlink a file (UNIX extensions).
     
    112252****************************************************************************/
    113253
    114 struct link_state {
    115         uint16_t setup;
    116         uint8_t *param;
     254struct cli_posix_link_internal_state {
    117255        uint8_t *data;
    118256};
    119257
    120 static void cli_posix_link_internal_done(struct tevent_req *subreq)
    121 {
    122         struct tevent_req *req = tevent_req_callback_data(
    123                                 subreq, struct tevent_req);
    124         struct link_state *state = tevent_req_data(req, struct link_state);
    125         NTSTATUS status;
    126 
    127         status = cli_trans_recv(subreq, state, NULL, NULL, NULL, NULL, NULL, NULL);
    128         TALLOC_FREE(subreq);
    129         if (!NT_STATUS_IS_OK(status)) {
    130                 tevent_req_nterror(req, status);
    131                 return;
    132         }
    133         tevent_req_done(req);
    134 }
     258static void cli_posix_link_internal_done(struct tevent_req *subreq);
    135259
    136260static struct tevent_req *cli_posix_link_internal_send(TALLOC_CTX *mem_ctx,
    137261                                        struct event_context *ev,
    138262                                        struct cli_state *cli,
     263                                        uint16_t level,
    139264                                        const char *oldname,
    140                                         const char *newname,
    141                                         bool hardlink)
     265                                        const char *newname)
    142266{
    143267        struct tevent_req *req = NULL, *subreq = NULL;
    144         struct link_state *state = NULL;
    145 
    146         req = tevent_req_create(mem_ctx, &state, struct link_state);
     268        struct cli_posix_link_internal_state *state = NULL;
     269
     270        req = tevent_req_create(mem_ctx, &state,
     271                                struct cli_posix_link_internal_state);
    147272        if (req == NULL) {
    148273                return NULL;
    149         }
    150 
    151         /* Setup setup word. */
    152         SSVAL(&state->setup, 0, TRANSACT2_SETPATHINFO);
    153 
    154         /* Setup param array. */
    155         state->param = talloc_array(state, uint8_t, 6);
    156         if (tevent_req_nomem(state->param, req)) {
    157                 return tevent_req_post(req, ev);
    158         }
    159         memset(state->param, '\0', 6);
    160         SSVAL(state->param,0,hardlink ? SMB_SET_FILE_UNIX_HLINK : SMB_SET_FILE_UNIX_LINK);
    161 
    162         state->param = trans2_bytes_push_str(state->param, cli_ucs2(cli), newname,
    163                                    strlen(newname)+1, NULL);
    164 
    165         if (tevent_req_nomem(state->param, req)) {
    166                 return tevent_req_post(req, ev);
    167274        }
    168275
     
    172279                return tevent_req_post(req, ev);
    173280        }
    174         state->data = trans2_bytes_push_str(state->data, cli_ucs2(cli), oldname,
    175                                    strlen(oldname)+1, NULL);
    176 
    177         subreq = cli_trans_send(state,                  /* mem ctx. */
    178                                 ev,                     /* event ctx. */
    179                                 cli,                    /* cli_state. */
    180                                 SMBtrans2,              /* cmd. */
    181                                 NULL,                   /* pipe name. */
    182                                 -1,                     /* fid. */
    183                                 0,                      /* function. */
    184                                 0,                      /* flags. */
    185                                 &state->setup,          /* setup. */
    186                                 1,                      /* num setup uint16_t words. */
    187                                 0,                      /* max returned setup. */
    188                                 state->param,           /* param. */
    189                                 talloc_get_size(state->param),  /* num param. */
    190                                 2,                      /* max returned param. */
    191                                 state->data,            /* data. */
    192                                 talloc_get_size(state->data),   /* num data. */
    193                                 0);                     /* max returned data. */
    194 
     281        state->data = trans2_bytes_push_str(
     282                state->data, cli_ucs2(cli), oldname, strlen(oldname)+1, NULL);
     283
     284        subreq = cli_setpathinfo_send(
     285                state, ev, cli, level, newname,
     286                state->data, talloc_get_size(state->data));
    195287        if (tevent_req_nomem(subreq, req)) {
    196288                return tevent_req_post(req, ev);
     
    198290        tevent_req_set_callback(subreq, cli_posix_link_internal_done, req);
    199291        return req;
     292}
     293
     294static void cli_posix_link_internal_done(struct tevent_req *subreq)
     295{
     296        NTSTATUS status = cli_setpathinfo_recv(subreq);
     297        tevent_req_simple_finish_ntstatus(subreq, status);
    200298}
    201299
     
    210308                                        const char *newname)
    211309{
    212         return cli_posix_link_internal_send(mem_ctx, ev, cli,
    213                         oldname, newname, false);
     310        return cli_posix_link_internal_send(
     311                mem_ctx, ev, cli, SMB_SET_FILE_UNIX_LINK, oldname, newname);
    214312}
    215313
    216314NTSTATUS cli_posix_symlink_recv(struct tevent_req *req)
    217315{
    218         NTSTATUS status;
    219 
    220         if (tevent_req_is_nterror(req, &status)) {
    221                 return status;
    222         }
    223         return NT_STATUS_OK;
     316        return tevent_req_simple_recv_ntstatus(req);
    224317}
    225318
     
    277370
    278371struct readlink_state {
    279         uint16_t setup;
    280         uint8_t *param;
    281372        uint8_t *data;
    282373        uint32_t num_data;
    283374};
    284375
    285 static void cli_posix_readlink_done(struct tevent_req *subreq)
    286 {
    287         struct tevent_req *req = tevent_req_callback_data(
    288                                 subreq, struct tevent_req);
    289         struct readlink_state *state = tevent_req_data(req, struct readlink_state);
    290         NTSTATUS status;
    291 
    292         status = cli_trans_recv(subreq, state, NULL, NULL, NULL, NULL,
    293                         &state->data, &state->num_data);
    294         TALLOC_FREE(subreq);
    295         if (!NT_STATUS_IS_OK(status)) {
    296                 tevent_req_nterror(req, status);
    297                 return;
    298         }
    299         if (state->num_data == 0) {
    300                 tevent_req_nterror(req, NT_STATUS_DATA_ERROR);
    301                 return;
    302         }
    303         if (state->data[state->num_data-1] != '\0') {
    304                 tevent_req_nterror(req, NT_STATUS_DATA_ERROR);
    305                 return;
    306         }
    307         tevent_req_done(req);
    308 }
     376static void cli_posix_readlink_done(struct tevent_req *subreq);
    309377
    310378struct tevent_req *cli_posix_readlink_send(TALLOC_CTX *mem_ctx,
     
    318386        uint32_t maxbytelen = (uint32_t)(cli_ucs2(cli) ? len*3 : len);
    319387
    320         if (maxbytelen < len) {
     388        req = tevent_req_create(mem_ctx, &state, struct readlink_state);
     389        if (req == NULL) {
    321390                return NULL;
    322391        }
    323392
    324         req = tevent_req_create(mem_ctx, &state, struct readlink_state);
    325         if (req == NULL) {
    326                 return NULL;
    327         }
    328 
    329         /* Setup setup word. */
    330         SSVAL(&state->setup, 0, TRANSACT2_QPATHINFO);
    331 
    332         /* Setup param array. */
    333         state->param = talloc_array(state, uint8_t, 6);
    334         if (tevent_req_nomem(state->param, req)) {
    335                 return tevent_req_post(req, ev);
    336         }
    337         memset(state->param, '\0', 6);
    338         SSVAL(state->param,0,SMB_QUERY_FILE_UNIX_LINK);
    339 
    340         state->param = trans2_bytes_push_str(state->param, cli_ucs2(cli), fname,
    341                                    strlen(fname)+1, NULL);
    342 
    343         if (tevent_req_nomem(state->param, req)) {
    344                 return tevent_req_post(req, ev);
    345         }
    346 
    347         subreq = cli_trans_send(state,                  /* mem ctx. */
    348                                 ev,                     /* event ctx. */
    349                                 cli,                    /* cli_state. */
    350                                 SMBtrans2,              /* cmd. */
    351                                 NULL,                   /* pipe name. */
    352                                 -1,                     /* fid. */
    353                                 0,                      /* function. */
    354                                 0,                      /* flags. */
    355                                 &state->setup,          /* setup. */
    356                                 1,                      /* num setup uint16_t words. */
    357                                 0,                      /* max returned setup. */
    358                                 state->param,           /* param. */
    359                                 talloc_get_size(state->param),  /* num param. */
    360                                 2,                      /* max returned param. */
    361                                 NULL,                   /* data. */
    362                                 0,                      /* num data. */
    363                                 maxbytelen);            /* max returned data. */
    364 
     393        /*
     394         * Len is in bytes, we need it in UCS2 units.
     395         */
     396        if ((2*len < len) || (maxbytelen < len)) {
     397                tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
     398                return tevent_req_post(req, ev);
     399        }
     400
     401        subreq = cli_qpathinfo_send(state, ev, cli, fname,
     402                                    SMB_QUERY_FILE_UNIX_LINK, 1, maxbytelen);
    365403        if (tevent_req_nomem(subreq, req)) {
    366404                return tevent_req_post(req, ev);
     
    368406        tevent_req_set_callback(subreq, cli_posix_readlink_done, req);
    369407        return req;
     408}
     409
     410static void cli_posix_readlink_done(struct tevent_req *subreq)
     411{
     412        struct tevent_req *req = tevent_req_callback_data(
     413                subreq, struct tevent_req);
     414        struct readlink_state *state = tevent_req_data(
     415                req, struct readlink_state);
     416        NTSTATUS status;
     417
     418        status = cli_qpathinfo_recv(subreq, state, &state->data,
     419                                    &state->num_data);
     420        TALLOC_FREE(subreq);
     421        if (tevent_req_nterror(req, status)) {
     422                return;
     423        }
     424        /*
     425         * num_data is > 1, we've given 1 as minimum to cli_qpathinfo_send
     426         */
     427        if (state->data[state->num_data-1] != '\0') {
     428                tevent_req_nterror(req, NT_STATUS_DATA_ERROR);
     429                return;
     430        }
     431        tevent_req_done(req);
    370432}
    371433
     
    423485        }
    424486
    425         /* Len is in bytes, we need it in UCS2 units. */
    426         if (2*len < len) {
    427                 status = NT_STATUS_INVALID_PARAMETER;
    428                 goto fail;
    429         }
    430 
    431487        req = cli_posix_readlink_send(frame,
    432488                                ev,
     
    464520                                        const char *newname)
    465521{
    466         return cli_posix_link_internal_send(mem_ctx, ev, cli,
    467                         oldname, newname, true);
     522        return cli_posix_link_internal_send(
     523                mem_ctx, ev, cli, SMB_SET_FILE_UNIX_HLINK, oldname, newname);
    468524}
    469525
    470526NTSTATUS cli_posix_hardlink_recv(struct tevent_req *req)
    471527{
    472         NTSTATUS status;
    473 
    474         if (tevent_req_is_nterror(req, &status)) {
    475                 return status;
    476         }
    477         return NT_STATUS_OK;
     528        return tevent_req_simple_recv_ntstatus(req);
    478529}
    479530
     
    625676
    626677struct getfacl_state {
    627         uint16_t setup;
    628         uint8_t *param;
    629678        uint32_t num_data;
    630679        uint8_t *data;
    631680};
    632681
    633 static void cli_posix_getfacl_done(struct tevent_req *subreq)
    634 {
    635         struct tevent_req *req = tevent_req_callback_data(
    636                                 subreq, struct tevent_req);
    637         struct getfacl_state *state = tevent_req_data(req, struct getfacl_state);
    638         NTSTATUS status;
    639 
    640         status = cli_trans_recv(subreq, state, NULL, NULL, NULL, NULL,
    641                         &state->data, &state->num_data);
    642         TALLOC_FREE(subreq);
    643         if (!NT_STATUS_IS_OK(status)) {
    644                 tevent_req_nterror(req, status);
    645                 return;
    646         }
    647         tevent_req_done(req);
    648 }
     682static void cli_posix_getfacl_done(struct tevent_req *subreq);
    649683
    650684struct tevent_req *cli_posix_getfacl_send(TALLOC_CTX *mem_ctx,
     
    654688{
    655689        struct tevent_req *req = NULL, *subreq = NULL;
    656         struct link_state *state = NULL;
     690        struct getfacl_state *state = NULL;
    657691
    658692        req = tevent_req_create(mem_ctx, &state, struct getfacl_state);
     
    660694                return NULL;
    661695        }
    662 
    663         /* Setup setup word. */
    664         SSVAL(&state->setup, 0, TRANSACT2_QPATHINFO);
    665 
    666         /* Setup param array. */
    667         state->param = talloc_array(state, uint8_t, 6);
    668         if (tevent_req_nomem(state->param, req)) {
    669                 return tevent_req_post(req, ev);
    670         }
    671         memset(state->param, '\0', 6);
    672         SSVAL(state->param, 0, SMB_QUERY_POSIX_ACL);
    673 
    674         state->param = trans2_bytes_push_str(state->param, cli_ucs2(cli), fname,
    675                                    strlen(fname)+1, NULL);
    676 
    677         if (tevent_req_nomem(state->param, req)) {
    678                 return tevent_req_post(req, ev);
    679         }
    680 
    681         subreq = cli_trans_send(state,                  /* mem ctx. */
    682                                 ev,                     /* event ctx. */
    683                                 cli,                    /* cli_state. */
    684                                 SMBtrans2,              /* cmd. */
    685                                 NULL,                   /* pipe name. */
    686                                 -1,                     /* fid. */
    687                                 0,                      /* function. */
    688                                 0,                      /* flags. */
    689                                 &state->setup,          /* setup. */
    690                                 1,                      /* num setup uint16_t words. */
    691                                 0,                      /* max returned setup. */
    692                                 state->param,           /* param. */
    693                                 talloc_get_size(state->param),  /* num param. */
    694                                 2,                      /* max returned param. */
    695                                 NULL,                   /* data. */
    696                                 0,                      /* num data. */
    697                                 cli->max_xmit);         /* max returned data. */
    698 
     696        subreq = cli_qpathinfo_send(state, ev, cli, fname, SMB_QUERY_POSIX_ACL,
     697                                    0, cli->max_xmit);
    699698        if (tevent_req_nomem(subreq, req)) {
    700699                return tevent_req_post(req, ev);
     
    702701        tevent_req_set_callback(subreq, cli_posix_getfacl_done, req);
    703702        return req;
     703}
     704
     705static void cli_posix_getfacl_done(struct tevent_req *subreq)
     706{
     707        struct tevent_req *req = tevent_req_callback_data(
     708                subreq, struct tevent_req);
     709        struct getfacl_state *state = tevent_req_data(
     710                req, struct getfacl_state);
     711        NTSTATUS status;
     712
     713        status = cli_qpathinfo_recv(subreq, state, &state->data,
     714                                    &state->num_data);
     715        TALLOC_FREE(subreq);
     716        if (tevent_req_nterror(req, status)) {
     717                return;
     718        }
     719        tevent_req_done(req);
    704720}
    705721
     
    774790
    775791struct stat_state {
    776         uint16_t setup;
    777         uint8_t *param;
    778792        uint32_t num_data;
    779793        uint8_t *data;
    780794};
     795
     796static void cli_posix_stat_done(struct tevent_req *subreq);
     797
     798struct tevent_req *cli_posix_stat_send(TALLOC_CTX *mem_ctx,
     799                                        struct event_context *ev,
     800                                        struct cli_state *cli,
     801                                        const char *fname)
     802{
     803        struct tevent_req *req = NULL, *subreq = NULL;
     804        struct stat_state *state = NULL;
     805
     806        req = tevent_req_create(mem_ctx, &state, struct stat_state);
     807        if (req == NULL) {
     808                return NULL;
     809        }
     810        subreq = cli_qpathinfo_send(state, ev, cli, fname,
     811                                    SMB_QUERY_FILE_UNIX_BASIC, 100, 100);
     812        if (tevent_req_nomem(subreq, req)) {
     813                return tevent_req_post(req, ev);
     814        }
     815        tevent_req_set_callback(subreq, cli_posix_stat_done, req);
     816        return req;
     817}
    781818
    782819static void cli_posix_stat_done(struct tevent_req *subreq)
     
    787824        NTSTATUS status;
    788825
    789         status = cli_trans_recv(subreq, state, NULL, NULL, NULL, NULL,
    790                         &state->data, &state->num_data);
     826        status = cli_qpathinfo_recv(subreq, state, &state->data,
     827                                    &state->num_data);
    791828        TALLOC_FREE(subreq);
    792         if (!NT_STATUS_IS_OK(status)) {
    793                 tevent_req_nterror(req, status);
     829        if (tevent_req_nterror(req, status)) {
    794830                return;
    795831        }
    796832        tevent_req_done(req);
    797 }
    798 
    799 struct tevent_req *cli_posix_stat_send(TALLOC_CTX *mem_ctx,
    800                                         struct event_context *ev,
    801                                         struct cli_state *cli,
    802                                         const char *fname)
    803 {
    804         struct tevent_req *req = NULL, *subreq = NULL;
    805         struct stat_state *state = NULL;
    806 
    807         req = tevent_req_create(mem_ctx, &state, struct stat_state);
    808         if (req == NULL) {
    809                 return NULL;
    810         }
    811 
    812         /* Setup setup word. */
    813         SSVAL(&state->setup, 0, TRANSACT2_QPATHINFO);
    814 
    815         /* Setup param array. */
    816         state->param = talloc_array(state, uint8_t, 6);
    817         if (tevent_req_nomem(state->param, req)) {
    818                 return tevent_req_post(req, ev);
    819         }
    820         memset(state->param, '\0', 6);
    821         SSVAL(state->param, 0, SMB_QUERY_FILE_UNIX_BASIC);
    822 
    823         state->param = trans2_bytes_push_str(state->param, cli_ucs2(cli), fname,
    824                                    strlen(fname)+1, NULL);
    825 
    826         if (tevent_req_nomem(state->param, req)) {
    827                 return tevent_req_post(req, ev);
    828         }
    829 
    830         subreq = cli_trans_send(state,                  /* mem ctx. */
    831                                 ev,                     /* event ctx. */
    832                                 cli,                    /* cli_state. */
    833                                 SMBtrans2,              /* cmd. */
    834                                 NULL,                   /* pipe name. */
    835                                 -1,                     /* fid. */
    836                                 0,                      /* function. */
    837                                 0,                      /* flags. */
    838                                 &state->setup,          /* setup. */
    839                                 1,                      /* num setup uint16_t words. */
    840                                 0,                      /* max returned setup. */
    841                                 state->param,           /* param. */
    842                                 talloc_get_size(state->param),  /* num param. */
    843                                 2,                      /* max returned param. */
    844                                 NULL,                   /* data. */
    845                                 0,                      /* num data. */
    846                                 96);                    /* max returned data. */
    847 
    848         if (tevent_req_nomem(subreq, req)) {
    849                 return tevent_req_post(req, ev);
    850         }
    851         tevent_req_set_callback(subreq, cli_posix_stat_done, req);
    852         return req;
    853833}
    854834
     
    861841        if (tevent_req_is_nterror(req, &status)) {
    862842                return status;
    863         }
    864 
    865         if (state->num_data != 96) {
    866                 return NT_STATUS_DATA_ERROR;
    867843        }
    868844
     
    891867        sbuf->st_ex_ino = (SMB_INO_T)IVAL2_TO_SMB_BIG_UINT(state->data,76);      /* inode */
    892868        sbuf->st_ex_mode |= wire_perms_to_unix(IVAL(state->data,84));     /* protection */
    893         sbuf->st_ex_nlink = IVAL(state->data,92);    /* number of hard links */
     869        sbuf->st_ex_nlink = BIG_UINT(state->data,92); /* number of hard links */
    894870
    895871        return NT_STATUS_OK;
     
    947923****************************************************************************/
    948924
    949 struct ch_state {
    950         uint16_t setup;
    951         uint8_t *param;
    952         uint8_t *data;
     925struct cli_posix_chown_chmod_internal_state {
     926        uint8_t data[100];
    953927};
    954928
    955 static void cli_posix_chown_chmod_internal_done(struct tevent_req *subreq)
    956 {
    957         struct tevent_req *req = tevent_req_callback_data(
    958                                 subreq, struct tevent_req);
    959         struct ch_state *state = tevent_req_data(req, struct ch_state);
    960         NTSTATUS status;
    961 
    962         status = cli_trans_recv(subreq, state, NULL, NULL, NULL, NULL, NULL, NULL);
    963         TALLOC_FREE(subreq);
    964         if (!NT_STATUS_IS_OK(status)) {
    965                 tevent_req_nterror(req, status);
    966                 return;
    967         }
    968         tevent_req_done(req);
    969 }
     929static void cli_posix_chown_chmod_internal_done(struct tevent_req *subreq);
    970930
    971931static struct tevent_req *cli_posix_chown_chmod_internal_send(TALLOC_CTX *mem_ctx,
     
    978938{
    979939        struct tevent_req *req = NULL, *subreq = NULL;
    980         struct ch_state *state = NULL;
    981 
    982         req = tevent_req_create(mem_ctx, &state, struct ch_state);
     940        struct cli_posix_chown_chmod_internal_state *state = NULL;
     941
     942        req = tevent_req_create(mem_ctx, &state,
     943                                struct cli_posix_chown_chmod_internal_state);
    983944        if (req == NULL) {
    984945                return NULL;
    985946        }
    986947
    987         /* Setup setup word. */
    988         SSVAL(&state->setup, 0, TRANSACT2_SETPATHINFO);
    989 
    990         /* Setup param array. */
    991         state->param = talloc_array(state, uint8_t, 6);
    992         if (tevent_req_nomem(state->param, req)) {
    993                 return tevent_req_post(req, ev);
    994         }
    995         memset(state->param, '\0', 6);
    996         SSVAL(state->param,0,SMB_SET_FILE_UNIX_BASIC);
    997 
    998         state->param = trans2_bytes_push_str(state->param, cli_ucs2(cli), fname,
    999                                    strlen(fname)+1, NULL);
    1000 
    1001         if (tevent_req_nomem(state->param, req)) {
    1002                 return tevent_req_post(req, ev);
    1003         }
    1004 
    1005         /* Setup data array. */
    1006         state->data = talloc_array(state, uint8_t, 100);
    1007         if (tevent_req_nomem(state->data, req)) {
    1008                 return tevent_req_post(req, ev);
    1009         }
    1010948        memset(state->data, 0xff, 40); /* Set all sizes/times to no change. */
    1011949        memset(&state->data[40], '\0', 60);
     
    1014952        SIVAL(state->data,84,mode);
    1015953
    1016         subreq = cli_trans_send(state,                  /* mem ctx. */
    1017                                 ev,                     /* event ctx. */
    1018                                 cli,                    /* cli_state. */
    1019                                 SMBtrans2,              /* cmd. */
    1020                                 NULL,                   /* pipe name. */
    1021                                 -1,                     /* fid. */
    1022                                 0,                      /* function. */
    1023                                 0,                      /* flags. */
    1024                                 &state->setup,          /* setup. */
    1025                                 1,                      /* num setup uint16_t words. */
    1026                                 0,                      /* max returned setup. */
    1027                                 state->param,           /* param. */
    1028                                 talloc_get_size(state->param),  /* num param. */
    1029                                 2,                      /* max returned param. */
    1030                                 state->data,            /* data. */
    1031                                 talloc_get_size(state->data),   /* num data. */
    1032                                 0);                     /* max returned data. */
    1033 
     954        subreq = cli_setpathinfo_send(state, ev, cli, SMB_SET_FILE_UNIX_BASIC,
     955                                      fname, state->data, sizeof(state->data));
    1034956        if (tevent_req_nomem(subreq, req)) {
    1035957                return tevent_req_post(req, ev);
    1036958        }
    1037         tevent_req_set_callback(subreq, cli_posix_chown_chmod_internal_done, req);
     959        tevent_req_set_callback(subreq, cli_posix_chown_chmod_internal_done,
     960                                req);
    1038961        return req;
     962}
     963
     964static void cli_posix_chown_chmod_internal_done(struct tevent_req *subreq)
     965{
     966        NTSTATUS status = cli_setpathinfo_recv(subreq);
     967        tevent_req_simple_finish_ntstatus(subreq, status);
    1039968}
    1040969
     
    1058987NTSTATUS cli_posix_chmod_recv(struct tevent_req *req)
    1059988{
    1060         NTSTATUS status;
    1061 
    1062         if (tevent_req_is_nterror(req, &status)) {
    1063                 return status;
    1064         }
    1065         return NT_STATUS_OK;
     989        return tevent_req_simple_recv_ntstatus(req);
    1066990}
    1067991
     
    11321056NTSTATUS cli_posix_chown_recv(struct tevent_req *req)
    11331057{
    1134         NTSTATUS status;
    1135 
    1136         if (tevent_req_is_nterror(req, &status)) {
    1137                 return status;
    1138         }
    1139         return NT_STATUS_OK;
     1058        return tevent_req_simple_recv_ntstatus(req);
    11401059}
    11411060
     
    12161135        }
    12171136
    1218         SSVAL(state->vwv+0, 0, aSYSTEM | aHIDDEN | aDIR);
     1137        SSVAL(state->vwv+0, 0, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_DIRECTORY);
    12191138
    12201139        bytes = talloc_array(state, uint8_t, 1);
     
    12571176        NTSTATUS status;
    12581177
    1259         status = cli_smb_recv(subreq, 0, NULL, NULL, NULL, NULL);
     1178        status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
    12601179        TALLOC_FREE(subreq);
    1261         if (!NT_STATUS_IS_OK(status)) {
    1262                 tevent_req_nterror(req, status);
     1180        if (tevent_req_nterror(req, status)) {
    12631181                return;
    12641182        }
     
    13411259        }
    13421260
    1343         SSVAL(state->vwv+0, 0 ,aSYSTEM | aHIDDEN | aDIR);
     1261        SSVAL(state->vwv+0, 0 ,FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_DIRECTORY);
    13441262        SSVAL(state->vwv+1, 0, rename_flag);
    13451263
     
    13831301        NTSTATUS status;
    13841302
    1385         status = cli_smb_recv(subreq, 0, NULL, NULL, NULL, NULL);
     1303        status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
    13861304        TALLOC_FREE(subreq);
    1387         if (!NT_STATUS_IS_OK(status)) {
    1388                 tevent_req_nterror(req, status);
     1305        if (tevent_req_nterror(req, status)) {
    13891306                return;
    13901307        }
     
    15781495        NTSTATUS status;
    15791496
    1580         status = cli_smb_recv(subreq, 0, NULL, NULL, NULL, NULL);
     1497        status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
    15811498        TALLOC_FREE(subreq);
    1582         if (!NT_STATUS_IS_OK(status)) {
    1583                 tevent_req_nterror(req, status);
     1499        if (tevent_req_nterror(req, status)) {
    15841500                return;
    15851501        }
     
    16861602        NTSTATUS status;
    16871603
    1688         status = cli_smb_recv(subreq, 0, NULL, NULL, NULL, NULL);
     1604        status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
    16891605        TALLOC_FREE(subreq);
    1690         if (!NT_STATUS_IS_OK(status)) {
    1691                 tevent_req_nterror(req, status);
     1606        if (tevent_req_nterror(req, status)) {
    16921607                return;
    16931608        }
     
    17941709        NTSTATUS status;
    17951710
    1796         status = cli_smb_recv(subreq, 0, NULL, NULL, NULL, NULL);
     1711        status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
    17971712        TALLOC_FREE(subreq);
    1798         if (!NT_STATUS_IS_OK(status)) {
    1799                 tevent_req_nterror(req, status);
     1713        if (tevent_req_nterror(req, status)) {
    18001714                return;
    18011715        }
     
    18621776static void cli_nt_delete_on_close_done(struct tevent_req *subreq)
    18631777{
    1864         struct tevent_req *req = tevent_req_callback_data(
    1865                                 subreq, struct tevent_req);
    1866         struct doc_state *state = tevent_req_data(req, struct doc_state);
    1867         NTSTATUS status;
    1868 
    1869         status = cli_trans_recv(subreq, state, NULL, NULL, NULL, NULL, NULL, NULL);
    1870         TALLOC_FREE(subreq);
    1871         if (!NT_STATUS_IS_OK(status)) {
    1872                 tevent_req_nterror(req, status);
    1873                 return;
    1874         }
    1875         tevent_req_done(req);
     1778        NTSTATUS status = cli_trans_recv(subreq, NULL, NULL, NULL, 0, NULL,
     1779                                         NULL, 0, NULL, NULL, 0, NULL);
     1780        tevent_req_simple_finish_ntstatus(subreq, status);
    18761781}
    18771782
     
    19271832NTSTATUS cli_nt_delete_on_close_recv(struct tevent_req *req)
    19281833{
    1929         NTSTATUS status;
    1930 
    1931         if (tevent_req_is_nterror(req, &status)) {
    1932                 return status;
    1933         }
    1934         return NT_STATUS_OK;
     1834        return tevent_req_simple_recv_ntstatus(req);
    19351835}
    19361836
     
    20661966        uint32_t num_bytes;
    20671967        uint8_t *bytes;
     1968        uint8_t *inbuf;
    20681969        NTSTATUS status;
    20691970
    2070         status = cli_smb_recv(subreq, 3, &wct, &vwv, &num_bytes, &bytes);
    2071         if (!NT_STATUS_IS_OK(status)) {
    2072                 TALLOC_FREE(subreq);
    2073                 tevent_req_nterror(req, status);
     1971        status = cli_smb_recv(subreq, state, &inbuf, 3, &wct, &vwv,
     1972                              &num_bytes, &bytes);
     1973        TALLOC_FREE(subreq);
     1974        if (tevent_req_nterror(req, status)) {
    20741975                return;
    20751976        }
     
    22092110        SSVAL(state->vwv + 2, 0, 0);  /* no additional info */
    22102111        SSVAL(state->vwv + 3, 0, accessmode);
    2211         SSVAL(state->vwv + 4, 0, aSYSTEM | aHIDDEN);
     2112        SSVAL(state->vwv + 4, 0, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
    22122113        SSVAL(state->vwv + 5, 0, 0);
    22132114        SIVAL(state->vwv + 6, 0, 0);
     
    22632164
    22642165        status = cli_smb_req_send(subreq);
    2265         if (!NT_STATUS_IS_OK(status)) {
    2266                 tevent_req_nterror(req, status);
     2166        if (tevent_req_nterror(req, status)) {
    22672167                return tevent_req_post(req, ev);
    22682168        }
     
    22782178        uint8_t wct;
    22792179        uint16_t *vwv;
     2180        uint8_t *inbuf;
    22802181        NTSTATUS status;
    22812182
    2282         status = cli_smb_recv(subreq, 3, &wct, &vwv, NULL, NULL);
    2283         if (!NT_STATUS_IS_OK(status)) {
    2284                 TALLOC_FREE(subreq);
    2285                 tevent_req_nterror(req, status);
     2183        status = cli_smb_recv(subreq, state, &inbuf, 3, &wct, &vwv, NULL,
     2184                              NULL);
     2185        TALLOC_FREE(subreq);
     2186        if (tevent_req_nterror(req, status)) {
    22862187                return;
    22872188        }
     
    23972298
    23982299        status = cli_smb_req_send(subreq);
    2399         if (!NT_STATUS_IS_OK(status)) {
    2400                 tevent_req_nterror(req, status);
     2300        if (tevent_req_nterror(req, status)) {
    24012301                return tevent_req_post(req, ev);
    24022302        }
     
    24102310        NTSTATUS status;
    24112311
    2412         status = cli_smb_recv(subreq, 0, NULL, NULL, NULL, NULL);
     2312        status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
    24132313        TALLOC_FREE(subreq);
    2414         if (!NT_STATUS_IS_OK(status)) {
    2415                 tevent_req_nterror(req, status);
     2314        if (tevent_req_nterror(req, status)) {
    24162315                return;
    24172316        }
     
    24772376static void cli_ftruncate_done(struct tevent_req *subreq)
    24782377{
    2479         struct tevent_req *req = tevent_req_callback_data(
    2480                                 subreq, struct tevent_req);
    2481         struct ftrunc_state *state = tevent_req_data(req, struct ftrunc_state);
    2482         NTSTATUS status;
    2483 
    2484         status = cli_trans_recv(subreq, state, NULL, NULL, NULL, NULL, NULL, NULL);
    2485         TALLOC_FREE(subreq);
    2486         if (!NT_STATUS_IS_OK(status)) {
    2487                 tevent_req_nterror(req, status);
    2488                 return;
    2489         }
    2490         tevent_req_done(req);
     2378        NTSTATUS status = cli_trans_recv(subreq, NULL, NULL, NULL, 0, NULL,
     2379                                         NULL, 0, NULL, NULL, 0, NULL);
     2380        tevent_req_simple_finish_ntstatus(subreq, status);
    24912381}
    24922382
     
    25432433NTSTATUS cli_ftruncate_recv(struct tevent_req *req)
    25442434{
    2545         NTSTATUS status;
    2546 
    2547         if (tevent_req_is_nterror(req, &status)) {
    2548                 return status;
    2549         }
    2550         return NT_STATUS_OK;
     2435        return tevent_req_simple_recv_ntstatus(req);
    25512436}
    25522437
     
    26062491                      int timeout, unsigned char locktype)
    26072492{
    2608         char *p;
    2609         int saved_timeout = cli->timeout;
    2610 
    2611         memset(cli->outbuf,'\0',smb_size);
    2612         memset(cli->inbuf,'\0', smb_size);
    2613 
    2614         cli_set_message(cli->outbuf,8,0,True);
    2615 
    2616         SCVAL(cli->outbuf,smb_com,SMBlockingX);
    2617         SSVAL(cli->outbuf,smb_tid,cli->cnum);
    2618         cli_setup_packet(cli);
    2619 
    2620         SCVAL(cli->outbuf,smb_vwv0,0xFF);
    2621         SSVAL(cli->outbuf,smb_vwv2,fnum);
    2622         SCVAL(cli->outbuf,smb_vwv3,locktype);
    2623         SIVALS(cli->outbuf, smb_vwv4, timeout);
    2624         SSVAL(cli->outbuf,smb_vwv6,0);
    2625         SSVAL(cli->outbuf,smb_vwv7,1);
    2626 
    2627         p = smb_buf(cli->outbuf);
    2628         SSVAL(p, 0, cli->pid);
    2629         SIVAL(p, 2, offset);
    2630         SIVAL(p, 6, len);
    2631 
    2632         p += 10;
    2633 
    2634         cli_setup_bcc(cli, p);
    2635 
    2636         cli_send_smb(cli);
     2493        uint16_t vwv[8];
     2494        uint8_t bytes[10];
     2495        NTSTATUS status;
     2496        int saved_timeout;
     2497
     2498        SCVAL(vwv + 0, 0, 0xff);
     2499        SCVAL(vwv + 0, 1, 0);
     2500        SSVAL(vwv + 1, 0, 0);
     2501        SSVAL(vwv + 2, 0, fnum);
     2502        SCVAL(vwv + 3, 0, locktype);
     2503        SCVAL(vwv + 3, 1, 0);
     2504        SIVALS(vwv + 4, 0, timeout);
     2505        SSVAL(vwv + 6, 0, 0);
     2506        SSVAL(vwv + 7, 0, 1);
     2507
     2508        SSVAL(bytes, 0, cli->pid);
     2509        SIVAL(bytes, 2, offset);
     2510        SIVAL(bytes, 6, len);
     2511
     2512        saved_timeout = cli->timeout;
    26372513
    26382514        if (timeout != 0) {
    2639                 cli->timeout = (timeout == -1) ? 0x7FFFFFFF : (timeout + 2*1000);
    2640         }
    2641 
    2642         if (!cli_receive_smb(cli)) {
    2643                 cli->timeout = saved_timeout;
    2644                 return NT_STATUS_UNSUCCESSFUL;
    2645         }
     2515                cli->timeout = (timeout == -1)
     2516                        ? 0x7FFFFFFF : (timeout + 2*1000);
     2517        }
     2518
     2519        status = cli_smb(talloc_tos(), cli, SMBlockingX, 0, 8, vwv,
     2520                         10, bytes, NULL, 0, NULL, NULL, NULL, NULL);
    26462521
    26472522        cli->timeout = saved_timeout;
    26482523
    2649         return cli_nt_error(cli);
     2524        return status;
    26502525}
    26512526
     
    26562531
    26572532bool cli_lock(struct cli_state *cli, uint16_t fnum,
    2658               uint32_t offset, uint32_t len, int timeout, enum brl_type lock_type)
    2659 {
    2660         char *p;
    2661         int saved_timeout = cli->timeout;
    2662 
    2663         memset(cli->outbuf,'\0',smb_size);
    2664         memset(cli->inbuf,'\0', smb_size);
    2665 
    2666         cli_set_message(cli->outbuf,8,0,True);
    2667 
    2668         SCVAL(cli->outbuf,smb_com,SMBlockingX);
    2669         SSVAL(cli->outbuf,smb_tid,cli->cnum);
    2670         cli_setup_packet(cli);
    2671 
    2672         SCVAL(cli->outbuf,smb_vwv0,0xFF);
    2673         SSVAL(cli->outbuf,smb_vwv2,fnum);
    2674         SCVAL(cli->outbuf,smb_vwv3,(lock_type == READ_LOCK? 1 : 0));
    2675         SIVALS(cli->outbuf, smb_vwv4, timeout);
    2676         SSVAL(cli->outbuf,smb_vwv6,0);
    2677         SSVAL(cli->outbuf,smb_vwv7,1);
    2678 
    2679         p = smb_buf(cli->outbuf);
    2680         SSVAL(p, 0, cli->pid);
    2681         SIVAL(p, 2, offset);
    2682         SIVAL(p, 6, len);
    2683 
    2684         p += 10;
    2685 
    2686         cli_setup_bcc(cli, p);
    2687 
    2688         cli_send_smb(cli);
    2689 
    2690         if (timeout != 0) {
    2691                 cli->timeout = (timeout == -1) ? 0x7FFFFFFF : (timeout*2 + 5*1000);
    2692         }
    2693 
    2694         if (!cli_receive_smb(cli)) {
    2695                 cli->timeout = saved_timeout;
    2696                 return False;
    2697         }
    2698 
    2699         cli->timeout = saved_timeout;
    2700 
    2701         if (cli_is_error(cli)) {
    2702                 return False;
    2703         }
    2704 
    2705         return True;
     2533                  uint32_t offset, uint32_t len, int timeout,
     2534                  enum brl_type lock_type)
     2535{
     2536        NTSTATUS status;
     2537
     2538        status = cli_locktype(cli, fnum, offset, len, timeout,
     2539                              (lock_type == READ_LOCK? 1 : 0));
     2540        cli_set_error(cli, status);
     2541        return NT_STATUS_IS_OK(status);
    27062542}
    27072543
     
    27602596        NTSTATUS status;
    27612597
    2762         status = cli_smb_recv(subreq, 0, NULL, NULL, NULL, NULL);
     2598        status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
    27632599        TALLOC_FREE(subreq);
    2764         if (!NT_STATUS_IS_OK(status)) {
    2765                 tevent_req_nterror(req, status);
     2600        if (tevent_req_nterror(req, status)) {
    27662601                return;
    27672602        }
     
    28252660
    28262661bool cli_lock64(struct cli_state *cli, uint16_t fnum,
    2827                 uint64_t offset, uint64_t len, int timeout, enum brl_type lock_type)
    2828 {
    2829         char *p;
     2662                uint64_t offset, uint64_t len, int timeout,
     2663                enum brl_type lock_type)
     2664{
     2665        uint16_t vwv[8];
     2666        uint8_t bytes[20];
    28302667        int saved_timeout = cli->timeout;
    28312668        int ltype;
     2669        NTSTATUS status;
    28322670
    28332671        if (! (cli->capabilities & CAP_LARGE_FILES)) {
     
    28382676        ltype |= LOCKING_ANDX_LARGE_FILES;
    28392677
    2840         memset(cli->outbuf,'\0',smb_size);
    2841         memset(cli->inbuf,'\0', smb_size);
    2842 
    2843         cli_set_message(cli->outbuf,8,0,True);
    2844 
    2845         SCVAL(cli->outbuf,smb_com,SMBlockingX);
    2846         SSVAL(cli->outbuf,smb_tid,cli->cnum);
    2847         cli_setup_packet(cli);
    2848 
    2849         SCVAL(cli->outbuf,smb_vwv0,0xFF);
    2850         SSVAL(cli->outbuf,smb_vwv2,fnum);
    2851         SCVAL(cli->outbuf,smb_vwv3,ltype);
    2852         SIVALS(cli->outbuf, smb_vwv4, timeout);
    2853         SSVAL(cli->outbuf,smb_vwv6,0);
    2854         SSVAL(cli->outbuf,smb_vwv7,1);
    2855 
    2856         p = smb_buf(cli->outbuf);
    2857         SIVAL(p, 0, cli->pid);
    2858         SOFF_T_R(p, 4, offset);
    2859         SOFF_T_R(p, 12, len);
    2860         p += 20;
    2861 
    2862         cli_setup_bcc(cli, p);
    2863         cli_send_smb(cli);
     2678        SCVAL(vwv + 0, 0, 0xff);
     2679        SCVAL(vwv + 0, 1, 0);
     2680        SSVAL(vwv + 1, 0, 0);
     2681        SSVAL(vwv + 2, 0, fnum);
     2682        SCVAL(vwv + 3, 0, ltype);
     2683        SCVAL(vwv + 3, 1, 0);
     2684        SIVALS(vwv + 4, 0, timeout);
     2685        SSVAL(vwv + 6, 0, 0);
     2686        SSVAL(vwv + 7, 0, 1);
     2687
     2688        SIVAL(bytes, 0, cli->pid);
     2689        SOFF_T_R(bytes, 4, offset);
     2690        SOFF_T_R(bytes, 12, len);
     2691
     2692        saved_timeout = cli->timeout;
    28642693
    28652694        if (timeout != 0) {
    2866                 cli->timeout = (timeout == -1) ? 0x7FFFFFFF : (timeout + 5*1000);
    2867         }
    2868 
    2869         if (!cli_receive_smb(cli)) {
    2870                 cli->timeout = saved_timeout;
    2871                 return False;
    2872         }
     2695                cli->timeout = (timeout == -1)
     2696                        ? 0x7FFFFFFF : (timeout + 2*1000);
     2697        }
     2698
     2699        status = cli_smb(talloc_tos(), cli, SMBlockingX, 0, 8, vwv,
     2700                         20, bytes, NULL, 0, NULL, NULL, NULL, NULL);
    28732701
    28742702        cli->timeout = saved_timeout;
    28752703
    2876         if (cli_is_error(cli)) {
    2877                 return False;
    2878         }
    2879 
    2880         return True;
     2704        cli_set_error(cli, status);
     2705        return NT_STATUS_IS_OK(status);
    28812706}
    28822707
     
    29352760        NTSTATUS status;
    29362761
    2937         status = cli_smb_recv(subreq, 0, NULL, NULL, NULL, NULL);
     2762        status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
    29382763        TALLOC_FREE(subreq);
    2939         if (!NT_STATUS_IS_OK(status)) {
    2940                 tevent_req_nterror(req, status);
     2764        if (tevent_req_nterror(req, status)) {
    29412765                return;
    29422766        }
     
    30112835static void cli_posix_unlock_internal_done(struct tevent_req *subreq)
    30122836{
    3013         struct tevent_req *req = tevent_req_callback_data(
    3014                                         subreq, struct tevent_req);
    3015         struct posix_lock_state *state = tevent_req_data(req, struct posix_lock_state);
    3016         NTSTATUS status;
    3017 
    3018         status = cli_trans_recv(subreq, state, NULL, NULL, NULL, NULL, NULL, NULL);
    3019         TALLOC_FREE(subreq);
    3020         if (!NT_STATUS_IS_OK(status)) {
    3021                 tevent_req_nterror(req, status);
    3022                 return;
    3023         }
    3024         tevent_req_done(req);
     2837        NTSTATUS status = cli_trans_recv(subreq, NULL, NULL, NULL, 0, NULL,
     2838                                         NULL, 0, NULL, NULL, 0, NULL);
     2839        tevent_req_simple_finish_ntstatus(subreq, status);
    30252840}
    30262841
     
    31232938NTSTATUS cli_posix_lock_recv(struct tevent_req *req)
    31242939{
    3125         NTSTATUS status;
    3126 
    3127         if (tevent_req_is_nterror(req, &status)) {
    3128                 return status;
    3129         }
    3130         return NT_STATUS_OK;
     2940        return tevent_req_simple_recv_ntstatus(req);
    31312941}
    31322942
     
    32043014NTSTATUS cli_posix_unlock_recv(struct tevent_req *req)
    32053015{
    3206         NTSTATUS status;
    3207 
    3208         if (tevent_req_is_nterror(req, &status)) {
    3209                 return status;
    3210         }
    3211         return NT_STATUS_OK;
     3016        return tevent_req_simple_recv_ntstatus(req);
    32123017}
    32133018
     
    33093114        uint8_t wct;
    33103115        uint16_t *vwv = NULL;
     3116        uint8_t *inbuf;
    33113117        NTSTATUS status;
    33123118
    3313         status = cli_smb_recv(subreq, 11, &wct, &vwv, NULL, NULL);
    3314         if (!NT_STATUS_IS_OK(status)) {
    3315                 tevent_req_nterror(req, status);
     3119        status = cli_smb_recv(subreq, state, &inbuf, 11, &wct, &vwv,
     3120                              NULL, NULL);
     3121        TALLOC_FREE(subreq);
     3122        if (tevent_req_nterror(req, status)) {
    33163123                return;
    33173124        }
     
    33233130        state->write_time = make_unix_date2(vwv+4, state->zone_offset);
    33243131
    3325         TALLOC_FREE(subreq);
    33263132        tevent_req_done(req);
    33273133}
     
    34713277        uint8_t wct;
    34723278        uint16_t *vwv = NULL;
     3279        uint8_t *inbuf;
    34733280        NTSTATUS status;
    34743281
    3475         status = cli_smb_recv(subreq, 4, &wct, &vwv, NULL, NULL);
    3476         if (!NT_STATUS_IS_OK(status)) {
    3477                 tevent_req_nterror(req, status);
     3282        status = cli_smb_recv(subreq, state, &inbuf, 4, &wct, &vwv, NULL,
     3283                              NULL);
     3284        TALLOC_FREE(subreq);
     3285        if (tevent_req_nterror(req, status)) {
    34783286                return;
    34793287        }
     
    34833291        state->write_time = make_unix_date3(vwv+1, state->zone_offset);
    34843292
    3485         TALLOC_FREE(subreq);
    34863293        tevent_req_done(req);
    34873294}
     
    35883395
    35893396        SSVAL(state->vwv+0, 0, fnum);
    3590         cli_put_dos_date2(cli, (char *)&state->vwv[1], 0, change_time);
    3591         cli_put_dos_date2(cli, (char *)&state->vwv[3], 0, access_time);
    3592         cli_put_dos_date2(cli, (char *)&state->vwv[5], 0, write_time);
     3397        push_dos_date2((uint8_t *)&state->vwv[1], 0, change_time,
     3398                       cli->serverzone);
     3399        push_dos_date2((uint8_t *)&state->vwv[3], 0, access_time,
     3400                       cli->serverzone);
     3401        push_dos_date2((uint8_t *)&state->vwv[5], 0, write_time,
     3402                       cli->serverzone);
    35933403
    35943404        subreq = cli_smb_send(state, ev, cli, SMBsetattrE, additional_flags,
     
    36073417        NTSTATUS status;
    36083418
    3609         status = cli_smb_recv(subreq, 0, NULL, NULL, NULL, NULL);
     3419        status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
    36103420        TALLOC_FREE(subreq);
    3611         if (!NT_STATUS_IS_OK(status)) {
    3612                 tevent_req_nterror(req, status);
     3421        if (tevent_req_nterror(req, status)) {
    36133422                return;
    36143423        }
     
    37013510
    37023511        SSVAL(state->vwv+0, 0, attr);
    3703         cli_put_dos_date3(cli, (char *)&state->vwv[1], 0, mtime);
     3512        push_dos_date3((uint8_t *)&state->vwv[1], 0, mtime, cli->serverzone);
    37043513
    37053514        bytes = talloc_array(state, uint8_t, 1);
     
    37413550        NTSTATUS status;
    37423551
    3743         status = cli_smb_recv(subreq, 0, NULL, NULL, NULL, NULL);
     3552        status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
    37443553        TALLOC_FREE(subreq);
    3745         if (!NT_STATUS_IS_OK(status)) {
    3746                 tevent_req_nterror(req, status);
     3554        if (tevent_req_nterror(req, status)) {
    37473555                return;
    37483556        }
     
    38523660        NTSTATUS status;
    38533661
    3854         status = cli_smb_recv(subreq, 0, NULL, NULL, NULL, NULL);
     3662        status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
    38553663        TALLOC_FREE(subreq);
    3856         if (!NT_STATUS_IS_OK(status)) {
    3857                 tevent_req_nterror(req, status);
     3664        if (tevent_req_nterror(req, status)) {
    38583665                return;
    38593666        }
     
    39653772        uint8_t wct;
    39663773        uint16_t *vwv = NULL;
     3774        uint8_t *inbuf;
    39673775        NTSTATUS status;
    39683776
    3969         status = cli_smb_recv(subreq, 4, &wct, &vwv, NULL, NULL);
    3970         if (!NT_STATUS_IS_OK(status)) {
    3971                 tevent_req_nterror(req, status);
     3777        status = cli_smb_recv(subreq, state, &inbuf, 4, &wct, &vwv, NULL,
     3778                              NULL);
     3779        TALLOC_FREE(subreq);
     3780        if (tevent_req_nterror(req, status)) {
    39723781                return;
    39733782        }
     
    39753784        state->total = SVAL(vwv+0, 0);
    39763785        state->avail = SVAL(vwv+3, 0);
    3977         TALLOC_FREE(subreq);
    39783786        tevent_req_done(req);
    39793787}
     
    40973905        uint32_t num_bytes = 0;
    40983906        uint8_t *bytes = NULL;
    4099 
    4100         status = cli_smb_recv(subreq, 1, &wcnt, &vwv, &num_bytes, &bytes);
    4101         if (!NT_STATUS_IS_OK(status)) {
    4102                 TALLOC_FREE(subreq);
    4103                 tevent_req_nterror(req, status);
     3907        uint8_t *inbuf;
     3908
     3909        status = cli_smb_recv(subreq, state, &inbuf, 1, &wcnt, &vwv,
     3910                              &num_bytes, &bytes);
     3911        TALLOC_FREE(subreq);
     3912        if (tevent_req_nterror(req, status)) {
    41043913                return;
    41053914        }
    41063915
    41073916        state->fnum = SVAL(vwv+0, 0);
    4108 
    4109         TALLOC_FREE(subreq);
    41103917
    41113918        /* From W2K3, the result is just the ASCII name */
     
    41994006NTSTATUS cli_raw_ioctl(struct cli_state *cli, uint16_t fnum, uint32_t code, DATA_BLOB *blob)
    42004007{
    4201         memset(cli->outbuf,'\0',smb_size);
    4202         memset(cli->inbuf,'\0',smb_size);
    4203 
    4204         cli_set_message(cli->outbuf, 3, 0, True);
    4205         SCVAL(cli->outbuf,smb_com,SMBioctl);
    4206         cli_setup_packet(cli);
    4207 
    4208         SSVAL(cli->outbuf, smb_vwv0, fnum);
    4209         SSVAL(cli->outbuf, smb_vwv1, code>>16);
    4210         SSVAL(cli->outbuf, smb_vwv2, (code&0xFFFF));
    4211 
    4212         cli_send_smb(cli);
    4213         if (!cli_receive_smb(cli)) {
    4214                 return NT_STATUS_UNEXPECTED_NETWORK_ERROR;
    4215         }
    4216 
    4217         if (cli_is_error(cli)) {
    4218                 return cli_nt_error(cli);
    4219         }
    4220 
     4008        uint16_t vwv[3];
     4009        NTSTATUS status;
     4010
     4011        SSVAL(vwv+0, 0, fnum);
     4012        SSVAL(vwv+1, 0, code>>16);
     4013        SSVAL(vwv+2, 0, (code&0xFFFF));
     4014
     4015        status = cli_smb(talloc_tos(), cli, SMBioctl, 0, 3, vwv, 0, NULL,
     4016                         NULL, 0, NULL, NULL, NULL, NULL);
     4017        if (!NT_STATUS_IS_OK(status)) {
     4018                return status;
     4019        }
    42214020        *blob = data_blob_null;
    4222 
    42234021        return NT_STATUS_OK;
    42244022}
     
    42284026*********************************************************/
    42294027
    4230 static bool cli_set_ea(struct cli_state *cli, uint16_t setup, char *param, unsigned int param_len,
    4231                         const char *ea_name, const char *ea_val, size_t ea_len)
    4232 {
     4028static NTSTATUS cli_set_ea(struct cli_state *cli, uint16_t setup_val,
     4029                           uint8_t *param, unsigned int param_len,
     4030                           const char *ea_name,
     4031                           const char *ea_val, size_t ea_len)
     4032{
     4033        uint16_t setup[1];
    42334034        unsigned int data_len = 0;
    4234         char *data = NULL;
    4235         char *rparam=NULL, *rdata=NULL;
     4035        uint8_t *data = NULL;
    42364036        char *p;
    42374037        size_t ea_namelen = strlen(ea_name);
     4038        NTSTATUS status;
     4039
     4040        SSVAL(setup, 0, setup_val);
    42384041
    42394042        if (ea_namelen == 0 && ea_len == 0) {
    42404043                data_len = 4;
    4241                 data = (char *)SMB_MALLOC(data_len);
     4044                data = (uint8_t *)SMB_MALLOC(data_len);
    42424045                if (!data) {
    4243                         return False;
     4046                        return NT_STATUS_NO_MEMORY;
    42444047                }
    4245                 p = data;
     4048                p = (char *)data;
    42464049                SIVAL(p,0,data_len);
    42474050        } else {
    42484051                data_len = 4 + 4 + ea_namelen + 1 + ea_len;
    4249                 data = (char *)SMB_MALLOC(data_len);
     4052                data = (uint8_t *)SMB_MALLOC(data_len);
    42504053                if (!data) {
    4251                         return False;
     4054                        return NT_STATUS_NO_MEMORY;
    42524055                }
    4253                 p = data;
     4056                p = (char *)data;
    42544057                SIVAL(p,0,data_len);
    42554058                p += 4;
     
    42614064        }
    42624065
    4263         if (!cli_send_trans(cli, SMBtrans2,
    4264                         NULL,                        /* name */
    4265                         -1, 0,                          /* fid, flags */
    4266                         &setup, 1, 0,                   /* setup, length, max */
    4267                         param, param_len, 2,            /* param, length, max */
    4268                         data,  data_len, cli->max_xmit /* data, length, max */
    4269                         )) {
    4270                 SAFE_FREE(data);
    4271                 return False;
    4272         }
    4273 
    4274         if (!cli_receive_trans(cli, SMBtrans2,
    4275                         &rparam, &param_len,
    4276                         &rdata, &data_len)) {
    4277                         SAFE_FREE(data);
    4278                 return false;
    4279         }
    4280 
     4066        status = cli_trans(talloc_tos(), cli, SMBtrans2, NULL, -1, 0, 0,
     4067                           setup, 1, 0,
     4068                           param, param_len, 2,
     4069                           data,  data_len, cli->max_xmit,
     4070                           NULL,
     4071                           NULL, 0, NULL, /* rsetup */
     4072                           NULL, 0, NULL, /* rparam */
     4073                           NULL, 0, NULL); /* rdata */
    42814074        SAFE_FREE(data);
    4282         SAFE_FREE(rdata);
    4283         SAFE_FREE(rparam);
    4284 
    4285         return True;
     4075        return status;
    42864076}
    42874077
     
    42904080*********************************************************/
    42914081
    4292 bool cli_set_ea_path(struct cli_state *cli, const char *path, const char *ea_name, const char *ea_val, size_t ea_len)
    4293 {
    4294         uint16_t setup = TRANSACT2_SETPATHINFO;
     4082NTSTATUS cli_set_ea_path(struct cli_state *cli, const char *path,
     4083                         const char *ea_name, const char *ea_val,
     4084                         size_t ea_len)
     4085{
    42954086        unsigned int param_len = 0;
    4296         char *param;
     4087        uint8_t *param;
    42974088        size_t srclen = 2*(strlen(path)+1);
    42984089        char *p;
    4299         bool ret;
    4300 
    4301         param = SMB_MALLOC_ARRAY(char, 6+srclen+2);
     4090        NTSTATUS status;
     4091
     4092        param = SMB_MALLOC_ARRAY(uint8_t, 6+srclen+2);
    43024093        if (!param) {
    4303                 return false;
     4094                return NT_STATUS_NO_MEMORY;
    43044095        }
    43054096        memset(param, '\0', 6);
    43064097        SSVAL(param,0,SMB_INFO_SET_EA);
    4307         p = &param[6];
     4098        p = (char *)(&param[6]);
    43084099
    43094100        p += clistr_push(cli, p, path, srclen, STR_TERMINATE);
    43104101        param_len = PTR_DIFF(p, param);
    43114102
    4312         ret = cli_set_ea(cli, setup, param, param_len, ea_name, ea_val, ea_len);
     4103        status = cli_set_ea(cli, TRANSACT2_SETPATHINFO, param, param_len,
     4104                            ea_name, ea_val, ea_len);
    43134105        SAFE_FREE(param);
    4314         return ret;
     4106        return status;
    43154107}
    43164108
     
    43194111*********************************************************/
    43204112
    4321 bool cli_set_ea_fnum(struct cli_state *cli, uint16_t fnum, const char *ea_name, const char *ea_val, size_t ea_len)
    4322 {
    4323         char param[6];
    4324         uint16_t setup = TRANSACT2_SETFILEINFO;
     4113NTSTATUS cli_set_ea_fnum(struct cli_state *cli, uint16_t fnum,
     4114                         const char *ea_name, const char *ea_val,
     4115                         size_t ea_len)
     4116{
     4117        uint8_t param[6];
    43254118
    43264119        memset(param, 0, 6);
     
    43284121        SSVAL(param,2,SMB_INFO_SET_EA);
    43294122
    4330         return cli_set_ea(cli, setup, param, 6, ea_name, ea_val, ea_len);
     4123        return cli_set_ea(cli, TRANSACT2_SETFILEINFO, param, 6,
     4124                          ea_name, ea_val, ea_len);
    43314125}
    43324126
     
    43354129*********************************************************/
    43364130
    4337 static bool cli_get_ea_list(struct cli_state *cli,
    4338                 uint16_t setup, char *param, unsigned int param_len,
    4339                 TALLOC_CTX *ctx,
    4340                 size_t *pnum_eas,
    4341                 struct ea_struct **pea_list)
    4342 {
    4343         unsigned int data_len = 0;
    4344         unsigned int rparam_len, rdata_len;
    4345         char *rparam=NULL, *rdata=NULL;
    4346         char *p;
     4131static bool parse_ea_blob(TALLOC_CTX *ctx, const uint8_t *rdata,
     4132                          size_t rdata_len,
     4133                          size_t *pnum_eas, struct ea_struct **pea_list)
     4134{
     4135        struct ea_struct *ea_list = NULL;
     4136        size_t num_eas;
    43474137        size_t ea_size;
    4348         size_t num_eas;
    4349         bool ret = False;
    4350         struct ea_struct *ea_list;
    4351 
    4352         *pnum_eas = 0;
    4353         if (pea_list) {
    4354                 *pea_list = NULL;
    4355         }
    4356 
    4357         if (!cli_send_trans(cli, SMBtrans2,
    4358                         NULL,           /* Name */
    4359                         -1, 0,          /* fid, flags */
    4360                         &setup, 1, 0,   /* setup, length, max */
    4361                         param, param_len, 10, /* param, length, max */
    4362 #ifdef __OS2__
    4363                         NULL, data_len, CLI_BUFFER_SIZE /* data, length, max */
    4364 #else
    4365                         NULL, data_len, cli->max_xmit /* data, length, max */
    4366 #endif
    4367                                 )) {
    4368                 return False;
    4369         }
    4370 
    4371         if (!cli_receive_trans(cli, SMBtrans2,
    4372                         &rparam, &rparam_len,
    4373                         &rdata, &rdata_len)) {
    4374                 return False;
    4375         }
    4376 
    4377         if (!rdata || rdata_len < 4) {
    4378                 goto out;
     4138        const uint8_t *p;
     4139
     4140        if (rdata_len < 4) {
     4141                return false;
    43794142        }
    43804143
    43814144        ea_size = (size_t)IVAL(rdata,0);
    43824145        if (ea_size > rdata_len) {
    4383                 goto out;
     4146                return false;
    43844147        }
    43854148
    43864149        if (ea_size == 0) {
    43874150                /* No EA's present. */
    4388                 ret = True;
    4389                 goto out;
     4151                *pnum_eas = 0;
     4152                *pea_list = NULL;
     4153                return true;
    43904154        }
    43914155
     
    43984162                unsigned int ea_valuelen = SVAL(p,2);
    43994163                if (ea_namelen == 0) {
    4400                         goto out;
     4164                        return false;
    44014165                }
    44024166                if (4 + ea_namelen + 1 + ea_valuelen > ea_size) {
    4403                         goto out;
     4167                        return false;
    44044168                }
    44054169                ea_size -= 4 + ea_namelen + 1 + ea_valuelen;
     
    44084172
    44094173        if (num_eas == 0) {
    4410                 ret = True;
    4411                 goto out;
     4174                *pnum_eas = 0;
     4175                *pea_list = NULL;
     4176                return true;
    44124177        }
    44134178
     
    44154180        if (!pea_list) {
    44164181                /* Caller only wants number of EA's. */
    4417                 ret = True;
    4418                 goto out;
     4182                return true;
    44194183        }
    44204184
    44214185        ea_list = TALLOC_ARRAY(ctx, struct ea_struct, num_eas);
    44224186        if (!ea_list) {
    4423                 goto out;
     4187                return false;
    44244188        }
    44254189
     
    44364200                unix_ea_name[0] = '\0';
    44374201                pull_ascii_fstring(unix_ea_name, p + 4);
    4438                 ea->name = talloc_strdup(ctx, unix_ea_name);
     4202                ea->name = talloc_strdup(ea_list, unix_ea_name);
     4203                if (!ea->name) {
     4204                        goto fail;
     4205                }
    44394206                /* Ensure the value is null terminated (in case it's a string). */
    4440                 ea->value = data_blob_talloc(ctx, NULL, ea_valuelen + 1);
     4207                ea->value = data_blob_talloc(ea_list, NULL, ea_valuelen + 1);
    44414208                if (!ea->value.data) {
    4442                         goto out;
     4209                        goto fail;
    44434210                }
    44444211                if (ea_valuelen) {
     
    44514218
    44524219        *pea_list = ea_list;
    4453         ret = True;
    4454 
    4455  out :
    4456 
    4457         SAFE_FREE(rdata);
    4458         SAFE_FREE(rparam);
    4459         return ret;
     4220        return true;
     4221
     4222fail:
     4223        TALLOC_FREE(ea_list);
     4224        return false;
    44604225}
    44614226
     
    44644229*********************************************************/
    44654230
    4466 bool cli_get_ea_list_path(struct cli_state *cli, const char *path,
     4231struct cli_get_ea_list_path_state {
     4232        uint32_t num_data;
     4233        uint8_t *data;
     4234};
     4235
     4236static void cli_get_ea_list_path_done(struct tevent_req *subreq);
     4237
     4238struct tevent_req *cli_get_ea_list_path_send(TALLOC_CTX *mem_ctx,
     4239                                             struct tevent_context *ev,
     4240                                             struct cli_state *cli,
     4241                                             const char *fname)
     4242{
     4243        struct tevent_req *req, *subreq;
     4244        struct cli_get_ea_list_path_state *state;
     4245
     4246        req = tevent_req_create(mem_ctx, &state,
     4247                                struct cli_get_ea_list_path_state);
     4248        if (req == NULL) {
     4249                return NULL;
     4250        }
     4251        subreq = cli_qpathinfo_send(state, ev, cli, fname,
     4252                                    SMB_INFO_QUERY_ALL_EAS, 4,
     4253                                    cli->max_xmit);
     4254// @todo in earlier port the above cli->max_xmit was changed to CLI_BUFFER_SIZE
     4255// @todo is that still needed? if no regressions are found please remove it
     4256        if (tevent_req_nomem(subreq, req)) {
     4257                return tevent_req_post(req, ev);
     4258        }
     4259        tevent_req_set_callback(subreq, cli_get_ea_list_path_done, req);
     4260        return req;
     4261}
     4262
     4263static void cli_get_ea_list_path_done(struct tevent_req *subreq)
     4264{
     4265        struct tevent_req *req = tevent_req_callback_data(
     4266                                subreq, struct tevent_req);
     4267        struct cli_get_ea_list_path_state *state = tevent_req_data(
     4268                req, struct cli_get_ea_list_path_state);
     4269        NTSTATUS status;
     4270
     4271        status = cli_qpathinfo_recv(subreq, state, &state->data,
     4272                                    &state->num_data);
     4273        TALLOC_FREE(subreq);
     4274        if (tevent_req_nterror(req, status)) {
     4275                return;
     4276        }
     4277        tevent_req_done(req);
     4278}
     4279
     4280NTSTATUS cli_get_ea_list_path_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
     4281                                   size_t *pnum_eas, struct ea_struct **peas)
     4282{
     4283        struct cli_get_ea_list_path_state *state = tevent_req_data(
     4284                req, struct cli_get_ea_list_path_state);
     4285        NTSTATUS status;
     4286
     4287        if (tevent_req_is_nterror(req, &status)) {
     4288                return status;
     4289        }
     4290        if (!parse_ea_blob(mem_ctx, state->data, state->num_data,
     4291                           pnum_eas, peas)) {
     4292                return NT_STATUS_INVALID_NETWORK_RESPONSE;
     4293        }
     4294        return NT_STATUS_OK;
     4295}
     4296
     4297NTSTATUS cli_get_ea_list_path(struct cli_state *cli, const char *path,
    44674298                TALLOC_CTX *ctx,
    44684299                size_t *pnum_eas,
    44694300                struct ea_struct **pea_list)
    44704301{
    4471         uint16_t setup = TRANSACT2_QPATHINFO;
    4472         unsigned int param_len = 0;
    4473         char *param;
    4474         char *p;
    4475         size_t srclen = 2*(strlen(path)+1);
    4476         bool ret;
    4477 
    4478         param = SMB_MALLOC_ARRAY(char, 6+srclen+2);
    4479         if (!param) {
    4480                 return false;
    4481         }
    4482         p = param;
    4483         memset(p, 0, 6);
    4484         SSVAL(p, 0, SMB_INFO_QUERY_ALL_EAS);
    4485         p += 6;
    4486         p += clistr_push(cli, p, path, srclen, STR_TERMINATE);
    4487         param_len = PTR_DIFF(p, param);
    4488 
    4489         ret = cli_get_ea_list(cli, setup, param, param_len, ctx, pnum_eas, pea_list);
    4490         SAFE_FREE(param);
    4491         return ret;
    4492 }
    4493 
    4494 /*********************************************************
    4495  Get an extended attribute list from an fnum.
    4496 *********************************************************/
    4497 
    4498 bool cli_get_ea_list_fnum(struct cli_state *cli, uint16_t fnum,
    4499                 TALLOC_CTX *ctx,
    4500                 size_t *pnum_eas,
    4501                 struct ea_struct **pea_list)
    4502 {
    4503         uint16_t setup = TRANSACT2_QFILEINFO;
    4504         char param[6];
    4505 
    4506         memset(param, 0, 6);
    4507         SSVAL(param,0,fnum);
    4508 #ifndef __OS2__
    4509         SSVAL(param,2,SMB_INFO_SET_EA);
    4510 #else
    4511         SSVAL(param,2,SMB_INFO_QUERY_ALL_EAS);
    4512 #endif
    4513 
    4514         return cli_get_ea_list(cli, setup, param, 6, ctx, pnum_eas, pea_list);
     4302        TALLOC_CTX *frame = talloc_stackframe();
     4303        struct event_context *ev = NULL;
     4304        struct tevent_req *req = NULL;
     4305        NTSTATUS status = NT_STATUS_NO_MEMORY;
     4306
     4307        if (cli_has_async_calls(cli)) {
     4308                /*
     4309                 * Can't use sync call while an async call is in flight
     4310                 */
     4311                status = NT_STATUS_INVALID_PARAMETER;
     4312                goto fail;
     4313        }
     4314        ev = event_context_init(frame);
     4315        if (ev == NULL) {
     4316                goto fail;
     4317        }
     4318        req = cli_get_ea_list_path_send(frame, ev, cli, path);
     4319        if (req == NULL) {
     4320                goto fail;
     4321        }
     4322        if (!tevent_req_poll_ntstatus(req, ev, &status)) {
     4323                goto fail;
     4324        }
     4325        status = cli_get_ea_list_path_recv(req, ctx, pnum_eas, pea_list);
     4326 fail:
     4327        TALLOC_FREE(frame);
     4328        if (!NT_STATUS_IS_OK(status)) {
     4329                cli_set_error(cli, status);
     4330        }
     4331        return status;
    45154332}
    45164333
     
    45614378#if defined(O_DIRECTORY)
    45624379        if (flags & O_DIRECTORY) {
    4563                 ret &= ~(SMB_O_RDONLY|SMB_O_RDWR|SMB_O_WRONLY);
    45644380                ret |= SMB_O_DIRECTORY;
    45654381        }
     
    45884404        uint32_t num_data;
    45894405
    4590         status = cli_trans_recv(subreq, state, NULL, NULL, NULL, NULL, &data, &num_data);
     4406        status = cli_trans_recv(subreq, state, NULL, NULL, 0, NULL,
     4407                                NULL, 0, NULL, &data, 12, &num_data);
    45914408        TALLOC_FREE(subreq);
    4592         if (!NT_STATUS_IS_OK(status)) {
    4593                 tevent_req_nterror(req, status);
    4594                 return;
    4595         }
    4596         if (num_data < 12) {
    4597                 tevent_req_nterror(req, status);
     4409        if (tevent_req_nterror(req, status)) {
    45984410                return;
    45994411        }
     
    46394451        /* Setup data words. */
    46404452        if (is_dir) {
    4641                 wire_flags &= ~(SMB_O_RDONLY|SMB_O_RDWR|SMB_O_WRONLY);
    46424453                wire_flags |= SMB_O_DIRECTORY;
    46434454        }
     
    47624573NTSTATUS cli_posix_mkdir_recv(struct tevent_req *req)
    47634574{
    4764         NTSTATUS status;
    4765 
    4766         if (tevent_req_is_nterror(req, &status)) {
    4767                 return status;
    4768         }
    4769         return NT_STATUS_OK;
     4575        return tevent_req_simple_recv_ntstatus(req);
    47704576}
    47714577
     
    48204626****************************************************************************/
    48214627
    4822 struct unlink_state {
    4823         uint16_t setup;
     4628struct cli_posix_unlink_internal_state {
    48244629        uint8_t data[2];
    48254630};
    48264631
    4827 static void cli_posix_unlink_internal_done(struct tevent_req *subreq)
    4828 {
    4829         struct tevent_req *req = tevent_req_callback_data(
    4830                                 subreq, struct tevent_req);
    4831         struct unlink_state *state = tevent_req_data(req, struct unlink_state);
    4832         NTSTATUS status;
    4833 
    4834         status = cli_trans_recv(subreq, state, NULL, NULL, NULL, NULL, NULL, NULL);
    4835         TALLOC_FREE(subreq);
    4836         if (!NT_STATUS_IS_OK(status)) {
    4837                 tevent_req_nterror(req, status);
    4838                 return;
    4839         }
    4840         tevent_req_done(req);
    4841 }
     4632static void cli_posix_unlink_internal_done(struct tevent_req *subreq);
    48424633
    48434634static struct tevent_req *cli_posix_unlink_internal_send(TALLOC_CTX *mem_ctx,
     
    48454636                                        struct cli_state *cli,
    48464637                                        const char *fname,
    4847                                         bool is_dir)
     4638                                        uint16_t level)
    48484639{
    48494640        struct tevent_req *req = NULL, *subreq = NULL;
    4850         struct unlink_state *state = NULL;
    4851         uint8_t *param = NULL;
    4852 
    4853         req = tevent_req_create(mem_ctx, &state, struct unlink_state);
     4641        struct cli_posix_unlink_internal_state *state = NULL;
     4642
     4643        req = tevent_req_create(mem_ctx, &state,
     4644                                struct cli_posix_unlink_internal_state);
    48544645        if (req == NULL) {
    48554646                return NULL;
    48564647        }
    48574648
    4858         /* Setup setup word. */
    4859         SSVAL(&state->setup, 0, TRANSACT2_SETPATHINFO);
    4860 
    4861         /* Setup param array. */
    4862         param = talloc_array(state, uint8_t, 6);
    4863         if (tevent_req_nomem(param, req)) {
    4864                 return tevent_req_post(req, ev);
    4865         }
    4866         memset(param, '\0', 6);
    4867         SSVAL(param, 0, SMB_POSIX_PATH_UNLINK);
    4868 
    4869         param = trans2_bytes_push_str(param, cli_ucs2(cli), fname,
    4870                                    strlen(fname)+1, NULL);
    4871 
    4872         if (tevent_req_nomem(param, req)) {
    4873                 return tevent_req_post(req, ev);
    4874         }
    4875 
    48764649        /* Setup data word. */
    4877         SSVAL(state->data, 0, is_dir ? SMB_POSIX_UNLINK_DIRECTORY_TARGET :
    4878                         SMB_POSIX_UNLINK_FILE_TARGET);
    4879 
    4880         subreq = cli_trans_send(state,                  /* mem ctx. */
    4881                                 ev,                     /* event ctx. */
    4882                                 cli,                    /* cli_state. */
    4883                                 SMBtrans2,              /* cmd. */
    4884                                 NULL,                   /* pipe name. */
    4885                                 -1,                     /* fid. */
    4886                                 0,                      /* function. */
    4887                                 0,                      /* flags. */
    4888                                 &state->setup,          /* setup. */
    4889                                 1,                      /* num setup uint16_t words. */
    4890                                 0,                      /* max returned setup. */
    4891                                 param,                  /* param. */
    4892                                 talloc_get_size(param), /* num param. */
    4893                                 2,                      /* max returned param. */
    4894                                 state->data,            /* data. */
    4895                                 2,                      /* num data. */
    4896                                 0);                     /* max returned data. */
    4897 
     4650        SSVAL(state->data, 0, level);
     4651
     4652        subreq = cli_setpathinfo_send(state, ev, cli,
     4653                                      SMB_POSIX_PATH_UNLINK,
     4654                                      fname,
     4655                                      state->data, sizeof(state->data));
    48984656        if (tevent_req_nomem(subreq, req)) {
    48994657                return tevent_req_post(req, ev);
     
    49014659        tevent_req_set_callback(subreq, cli_posix_unlink_internal_done, req);
    49024660        return req;
     4661}
     4662
     4663static void cli_posix_unlink_internal_done(struct tevent_req *subreq)
     4664{
     4665        NTSTATUS status = cli_setpathinfo_recv(subreq);
     4666        tevent_req_simple_finish_ntstatus(subreq, status);
    49034667}
    49044668
     
    49084672                                        const char *fname)
    49094673{
    4910         return cli_posix_unlink_internal_send(mem_ctx, ev, cli, fname, false);
     4674        return cli_posix_unlink_internal_send(mem_ctx, ev, cli, fname,
     4675                                              SMB_POSIX_UNLINK_FILE_TARGET);
    49114676}
    49124677
    49134678NTSTATUS cli_posix_unlink_recv(struct tevent_req *req)
    49144679{
    4915         NTSTATUS status;
    4916 
    4917         if (tevent_req_is_nterror(req, &status)) {
    4918                 return status;
    4919         }
    4920         return NT_STATUS_OK;
     4680        return tevent_req_simple_recv_ntstatus(req);
    49214681}
    49224682
     
    49794739                                        const char *fname)
    49804740{
    4981         return cli_posix_unlink_internal_send(mem_ctx, ev, cli, fname, true);
     4741        return cli_posix_unlink_internal_send(
     4742                mem_ctx, ev, cli, fname,
     4743                SMB_POSIX_UNLINK_DIRECTORY_TARGET);
    49824744}
    49834745
    49844746NTSTATUS cli_posix_rmdir_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx)
    49854747{
    4986         NTSTATUS status;
    4987 
    4988         if (tevent_req_is_nterror(req, &status)) {
    4989                 return status;
    4990         }
    4991         return NT_STATUS_OK;
     4748        return tevent_req_simple_recv_ntstatus(req);
    49924749}
    49934750
     
    51024859        uint8_t *params;
    51034860        uint32_t i, ofs, num_params;
    5104 
    5105         status = cli_trans_recv(subreq, talloc_tos(), NULL, NULL,
    5106                                 &params, &num_params, NULL, NULL);
     4861        uint16_t flags2;
     4862
     4863        status = cli_trans_recv(subreq, talloc_tos(), &flags2, NULL, 0, NULL,
     4864                                &params, 0, &num_params, NULL, 0, NULL);
    51074865        TALLOC_FREE(subreq);
    5108         if (!NT_STATUS_IS_OK(status)) {
     4866        if (tevent_req_nterror(req, status)) {
    51094867                DEBUG(10, ("cli_trans_recv returned %s\n", nt_errstr(status)));
    5110                 tevent_req_nterror(req, status);
    51114868                return;
    51124869        }
     
    51484905
    51494906                state->changes[i].action = IVAL(params, ofs+4);
    5150                 ret = clistr_pull_talloc(params, (char *)params, &name,
    5151                                          params+ofs+12, len,
     4907                ret = clistr_pull_talloc(params, (char *)params, flags2,
     4908                                         &name, params+ofs+12, len,
    51524909                                         STR_TERMINATE|STR_UNICODE);
    51534910                if (ret == -1) {
     
    51804937        return NT_STATUS_OK;
    51814938}
     4939
     4940struct cli_qpathinfo_state {
     4941        uint8_t *param;
     4942        uint8_t *data;
     4943        uint16_t setup[1];
     4944        uint32_t min_rdata;
     4945        uint8_t *rdata;
     4946        uint32_t num_rdata;
     4947};
     4948
     4949static void cli_qpathinfo_done(struct tevent_req *subreq);
     4950
     4951struct tevent_req *cli_qpathinfo_send(TALLOC_CTX *mem_ctx,
     4952                                      struct tevent_context *ev,
     4953                                      struct cli_state *cli, const char *fname,
     4954                                      uint16_t level, uint32_t min_rdata,
     4955                                      uint32_t max_rdata)
     4956{
     4957        struct tevent_req *req, *subreq;
     4958        struct cli_qpathinfo_state *state;
     4959
     4960        req = tevent_req_create(mem_ctx, &state, struct cli_qpathinfo_state);
     4961        if (req == NULL) {
     4962                return NULL;
     4963        }
     4964        state->min_rdata = min_rdata;
     4965        SSVAL(state->setup, 0, TRANSACT2_QPATHINFO);
     4966
     4967        state->param = talloc_zero_array(state, uint8_t, 6);
     4968        if (tevent_req_nomem(state->param, req)) {
     4969                return tevent_req_post(req, ev);
     4970        }
     4971        SSVAL(state->param, 0, level);
     4972        state->param = trans2_bytes_push_str(
     4973                state->param, cli_ucs2(cli), fname, strlen(fname)+1, NULL);
     4974        if (tevent_req_nomem(state->param, req)) {
     4975                return tevent_req_post(req, ev);
     4976        }
     4977
     4978        subreq = cli_trans_send(
     4979                state,                  /* mem ctx. */
     4980                ev,                     /* event ctx. */
     4981                cli,                    /* cli_state. */
     4982                SMBtrans2,              /* cmd. */
     4983                NULL,                   /* pipe name. */
     4984                -1,                     /* fid. */
     4985                0,                      /* function. */
     4986                0,                      /* flags. */
     4987                state->setup,           /* setup. */
     4988                1,                      /* num setup uint16_t words. */
     4989                0,                      /* max returned setup. */
     4990                state->param,           /* param. */
     4991                talloc_get_size(state->param),  /* num param. */
     4992                2,                      /* max returned param. */
     4993                NULL,                   /* data. */
     4994                0,                      /* num data. */
     4995                max_rdata);             /* max returned data. */
     4996
     4997        if (tevent_req_nomem(subreq, req)) {
     4998                return tevent_req_post(req, ev);
     4999        }
     5000        tevent_req_set_callback(subreq, cli_qpathinfo_done, req);
     5001        return req;
     5002}
     5003
     5004static void cli_qpathinfo_done(struct tevent_req *subreq)
     5005{
     5006        struct tevent_req *req = tevent_req_callback_data(
     5007                subreq, struct tevent_req);
     5008        struct cli_qpathinfo_state *state = tevent_req_data(
     5009                req, struct cli_qpathinfo_state);
     5010        NTSTATUS status;
     5011
     5012        status = cli_trans_recv(subreq, state, NULL, NULL, 0, NULL,
     5013                                NULL, 0, NULL,
     5014                                &state->rdata, state->min_rdata,
     5015                                &state->num_rdata);
     5016        if (tevent_req_nterror(req, status)) {
     5017                return;
     5018        }
     5019        tevent_req_done(req);
     5020}
     5021
     5022NTSTATUS cli_qpathinfo_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
     5023                            uint8_t **rdata, uint32_t *num_rdata)
     5024{
     5025        struct cli_qpathinfo_state *state = tevent_req_data(
     5026                req, struct cli_qpathinfo_state);
     5027        NTSTATUS status;
     5028
     5029        if (tevent_req_is_nterror(req, &status)) {
     5030                return status;
     5031        }
     5032        if (rdata != NULL) {
     5033                *rdata = talloc_move(mem_ctx, &state->rdata);
     5034        } else {
     5035                TALLOC_FREE(state->rdata);
     5036        }
     5037        if (num_rdata != NULL) {
     5038                *num_rdata = state->num_rdata;
     5039        }
     5040        return NT_STATUS_OK;
     5041}
     5042
     5043NTSTATUS cli_qpathinfo(TALLOC_CTX *mem_ctx, struct cli_state *cli,
     5044                       const char *fname, uint16_t level, uint32_t min_rdata,
     5045                       uint32_t max_rdata,
     5046                       uint8_t **rdata, uint32_t *num_rdata)
     5047{
     5048        TALLOC_CTX *frame = talloc_stackframe();
     5049        struct event_context *ev;
     5050        struct tevent_req *req;
     5051        NTSTATUS status = NT_STATUS_NO_MEMORY;
     5052
     5053        if (cli_has_async_calls(cli)) {
     5054                /*
     5055                 * Can't use sync call while an async call is in flight
     5056                 */
     5057                status = NT_STATUS_INVALID_PARAMETER;
     5058                goto fail;
     5059        }
     5060        ev = event_context_init(frame);
     5061        if (ev == NULL) {
     5062                goto fail;
     5063        }
     5064        req = cli_qpathinfo_send(frame, ev, cli, fname, level, min_rdata,
     5065                                 max_rdata);
     5066        if (req == NULL) {
     5067                goto fail;
     5068        }
     5069        if (!tevent_req_poll_ntstatus(req, ev, &status)) {
     5070                goto fail;
     5071        }
     5072        status = cli_qpathinfo_recv(req, mem_ctx, rdata, num_rdata);
     5073 fail:
     5074        TALLOC_FREE(frame);
     5075        if (!NT_STATUS_IS_OK(status)) {
     5076                cli_set_error(cli, status);
     5077        }
     5078        return status;
     5079}
     5080
     5081struct cli_qfileinfo_state {
     5082        uint16_t setup[1];
     5083        uint8_t param[4];
     5084        uint8_t *data;
     5085        uint32_t min_rdata;
     5086        uint8_t *rdata;
     5087        uint32_t num_rdata;
     5088};
     5089
     5090static void cli_qfileinfo_done(struct tevent_req *subreq);
     5091
     5092struct tevent_req *cli_qfileinfo_send(TALLOC_CTX *mem_ctx,
     5093                                      struct tevent_context *ev,
     5094                                      struct cli_state *cli, uint16_t fnum,
     5095                                      uint16_t level, uint32_t min_rdata,
     5096                                      uint32_t max_rdata)
     5097{
     5098        struct tevent_req *req, *subreq;
     5099        struct cli_qfileinfo_state *state;
     5100
     5101        req = tevent_req_create(mem_ctx, &state, struct cli_qfileinfo_state);
     5102        if (req == NULL) {
     5103                return NULL;
     5104        }
     5105        state->min_rdata = min_rdata;
     5106        SSVAL(state->param, 0, fnum);
     5107        SSVAL(state->param, 2, level);
     5108        SSVAL(state->setup, 0, TRANSACT2_QFILEINFO);
     5109
     5110        subreq = cli_trans_send(
     5111                state,                  /* mem ctx. */
     5112                ev,                     /* event ctx. */
     5113                cli,                    /* cli_state. */
     5114                SMBtrans2,              /* cmd. */
     5115                NULL,                   /* pipe name. */
     5116                -1,                     /* fid. */
     5117                0,                      /* function. */
     5118                0,                      /* flags. */
     5119                state->setup,           /* setup. */
     5120                1,                      /* num setup uint16_t words. */
     5121                0,                      /* max returned setup. */
     5122                state->param,           /* param. */
     5123                sizeof(state->param),   /* num param. */
     5124                2,                      /* max returned param. */
     5125                NULL,                   /* data. */
     5126                0,                      /* num data. */
     5127                max_rdata);             /* max returned data. */
     5128
     5129        if (tevent_req_nomem(subreq, req)) {
     5130                return tevent_req_post(req, ev);
     5131        }
     5132        tevent_req_set_callback(subreq, cli_qfileinfo_done, req);
     5133        return req;
     5134}
     5135
     5136static void cli_qfileinfo_done(struct tevent_req *subreq)
     5137{
     5138        struct tevent_req *req = tevent_req_callback_data(
     5139                subreq, struct tevent_req);
     5140        struct cli_qfileinfo_state *state = tevent_req_data(
     5141                req, struct cli_qfileinfo_state);
     5142        NTSTATUS status;
     5143
     5144        status = cli_trans_recv(subreq, state, NULL, NULL, 0, NULL,
     5145                                NULL, 0, NULL,
     5146                                &state->rdata, state->min_rdata,
     5147                                &state->num_rdata);
     5148        if (tevent_req_nterror(req, status)) {
     5149                return;
     5150        }
     5151        tevent_req_done(req);
     5152}
     5153
     5154NTSTATUS cli_qfileinfo_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
     5155                            uint8_t **rdata, uint32_t *num_rdata)
     5156{
     5157        struct cli_qfileinfo_state *state = tevent_req_data(
     5158                req, struct cli_qfileinfo_state);
     5159        NTSTATUS status;
     5160
     5161        if (tevent_req_is_nterror(req, &status)) {
     5162                return status;
     5163        }
     5164        if (rdata != NULL) {
     5165                *rdata = talloc_move(mem_ctx, &state->rdata);
     5166        } else {
     5167                TALLOC_FREE(state->rdata);
     5168        }
     5169        if (num_rdata != NULL) {
     5170                *num_rdata = state->num_rdata;
     5171        }
     5172        return NT_STATUS_OK;
     5173}
     5174
     5175NTSTATUS cli_qfileinfo(TALLOC_CTX *mem_ctx, struct cli_state *cli,
     5176                       uint16_t fnum, uint16_t level, uint32_t min_rdata,
     5177                       uint32_t max_rdata,
     5178                       uint8_t **rdata, uint32_t *num_rdata)
     5179{
     5180        TALLOC_CTX *frame = talloc_stackframe();
     5181        struct event_context *ev;
     5182        struct tevent_req *req;
     5183        NTSTATUS status = NT_STATUS_NO_MEMORY;
     5184
     5185        if (cli_has_async_calls(cli)) {
     5186                /*
     5187                 * Can't use sync call while an async call is in flight
     5188                 */
     5189                status = NT_STATUS_INVALID_PARAMETER;
     5190                goto fail;
     5191        }
     5192        ev = event_context_init(frame);
     5193        if (ev == NULL) {
     5194                goto fail;
     5195        }
     5196        req = cli_qfileinfo_send(frame, ev, cli, fnum, level, min_rdata,
     5197                                 max_rdata);
     5198        if (req == NULL) {
     5199                goto fail;
     5200        }
     5201        if (!tevent_req_poll_ntstatus(req, ev, &status)) {
     5202                goto fail;
     5203        }
     5204        status = cli_qfileinfo_recv(req, mem_ctx, rdata, num_rdata);
     5205 fail:
     5206        TALLOC_FREE(frame);
     5207        if (!NT_STATUS_IS_OK(status)) {
     5208                cli_set_error(cli, status);
     5209        }
     5210        return status;
     5211}
     5212
     5213struct cli_flush_state {
     5214        uint16_t vwv[1];
     5215};
     5216
     5217static void cli_flush_done(struct tevent_req *subreq);
     5218
     5219struct tevent_req *cli_flush_send(TALLOC_CTX *mem_ctx,
     5220                                  struct event_context *ev,
     5221                                  struct cli_state *cli,
     5222                                  uint16_t fnum)
     5223{
     5224        struct tevent_req *req, *subreq;
     5225        struct cli_flush_state *state;
     5226
     5227        req = tevent_req_create(mem_ctx, &state, struct cli_flush_state);
     5228        if (req == NULL) {
     5229                return NULL;
     5230        }
     5231        SSVAL(state->vwv + 0, 0, fnum);
     5232
     5233        subreq = cli_smb_send(state, ev, cli, SMBflush, 0, 1, state->vwv,
     5234                              0, NULL);
     5235        if (tevent_req_nomem(subreq, req)) {
     5236                return tevent_req_post(req, ev);
     5237        }
     5238        tevent_req_set_callback(subreq, cli_flush_done, req);
     5239        return req;
     5240}
     5241
     5242static void cli_flush_done(struct tevent_req *subreq)
     5243{
     5244        struct tevent_req *req = tevent_req_callback_data(
     5245                subreq, struct tevent_req);
     5246        NTSTATUS status;
     5247
     5248        status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
     5249        TALLOC_FREE(subreq);
     5250        if (tevent_req_nterror(req, status)) {
     5251                return;
     5252        }
     5253        tevent_req_done(req);
     5254}
     5255
     5256NTSTATUS cli_flush_recv(struct tevent_req *req)
     5257{
     5258        return tevent_req_simple_recv_ntstatus(req);
     5259}
     5260
     5261NTSTATUS cli_flush(TALLOC_CTX *mem_ctx, struct cli_state *cli, uint16_t fnum)
     5262{
     5263        TALLOC_CTX *frame = talloc_stackframe();
     5264        struct event_context *ev;
     5265        struct tevent_req *req;
     5266        NTSTATUS status = NT_STATUS_NO_MEMORY;
     5267
     5268        if (cli_has_async_calls(cli)) {
     5269                /*
     5270                 * Can't use sync call while an async call is in flight
     5271                 */
     5272                status = NT_STATUS_INVALID_PARAMETER;
     5273                goto fail;
     5274        }
     5275        ev = event_context_init(frame);
     5276        if (ev == NULL) {
     5277                goto fail;
     5278        }
     5279        req = cli_flush_send(frame, ev, cli, fnum);
     5280        if (req == NULL) {
     5281                goto fail;
     5282        }
     5283        if (!tevent_req_poll_ntstatus(req, ev, &status)) {
     5284                goto fail;
     5285        }
     5286        status = cli_flush_recv(req);
     5287 fail:
     5288        TALLOC_FREE(frame);
     5289        if (!NT_STATUS_IS_OK(status)) {
     5290                cli_set_error(cli, status);
     5291        }
     5292        return status;
     5293}
     5294
     5295struct cli_shadow_copy_data_state {
     5296        uint16_t setup[4];
     5297        uint8_t *data;
     5298        uint32_t num_data;
     5299        bool get_names;
     5300};
     5301
     5302static void cli_shadow_copy_data_done(struct tevent_req *subreq);
     5303
     5304struct tevent_req *cli_shadow_copy_data_send(TALLOC_CTX *mem_ctx,
     5305                                             struct tevent_context *ev,
     5306                                             struct cli_state *cli,
     5307                                             uint16_t fnum,
     5308                                             bool get_names)
     5309{
     5310        struct tevent_req *req, *subreq;
     5311        struct cli_shadow_copy_data_state *state;
     5312        uint32_t ret_size;
     5313
     5314        req = tevent_req_create(mem_ctx, &state,
     5315                                struct cli_shadow_copy_data_state);
     5316        if (req == NULL) {
     5317                return NULL;
     5318        }
     5319        state->get_names = get_names;
     5320        ret_size = get_names ? cli->max_xmit : 16;
     5321
     5322        SIVAL(state->setup + 0, 0, FSCTL_GET_SHADOW_COPY_DATA);
     5323        SSVAL(state->setup + 2, 0, fnum);
     5324        SCVAL(state->setup + 3, 0, 0); /* isFsctl */
     5325        SCVAL(state->setup + 3, 1, 0); /* compfilter, isFlags (WSSP) */
     5326
     5327        subreq = cli_trans_send(
     5328                state, ev, cli, SMBnttrans, NULL, 0, NT_TRANSACT_IOCTL, 0,
     5329                state->setup, ARRAY_SIZE(state->setup), 0,
     5330                NULL, 0, 0,
     5331                NULL, 0, ret_size);
     5332        if (tevent_req_nomem(subreq, req)) {
     5333                return tevent_req_post(req, ev);
     5334        }
     5335        tevent_req_set_callback(subreq, cli_shadow_copy_data_done, req);
     5336        return req;
     5337}
     5338
     5339static void cli_shadow_copy_data_done(struct tevent_req *subreq)
     5340{
     5341        struct tevent_req *req = tevent_req_callback_data(
     5342                subreq, struct tevent_req);
     5343        struct cli_shadow_copy_data_state *state = tevent_req_data(
     5344                req, struct cli_shadow_copy_data_state);
     5345        NTSTATUS status;
     5346
     5347        status = cli_trans_recv(subreq, state, NULL,
     5348                                NULL, 0, NULL, /* setup */
     5349                                NULL, 0, NULL, /* param */
     5350                                &state->data, 12, &state->num_data);
     5351        TALLOC_FREE(subreq);
     5352        if (tevent_req_nterror(req, status)) {
     5353                return;
     5354        }
     5355        tevent_req_done(req);
     5356}
     5357
     5358NTSTATUS cli_shadow_copy_data_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
     5359                                   char ***pnames, int *pnum_names)
     5360{
     5361        struct cli_shadow_copy_data_state *state = tevent_req_data(
     5362                req, struct cli_shadow_copy_data_state);
     5363        char **names;
     5364        int i, num_names;
     5365        uint32_t dlength;
     5366        NTSTATUS status;
     5367
     5368        if (tevent_req_is_nterror(req, &status)) {
     5369                return status;
     5370        }
     5371        num_names = IVAL(state->data, 4);
     5372        dlength = IVAL(state->data, 8);
     5373
     5374        if (!state->get_names) {
     5375                *pnum_names = num_names;
     5376                return NT_STATUS_OK;
     5377        }
     5378
     5379        if (dlength+12 > state->num_data) {
     5380                return NT_STATUS_INVALID_NETWORK_RESPONSE;
     5381        }
     5382        names = talloc_array(mem_ctx, char *, num_names);
     5383        if (names == NULL) {
     5384                return NT_STATUS_NO_MEMORY;
     5385        }
     5386
     5387        for (i=0; i<num_names; i++) {
     5388                bool ret;
     5389                uint8_t *src;
     5390                size_t converted_size;
     5391
     5392                src = state->data + 12 + i * 2 * sizeof(SHADOW_COPY_LABEL);
     5393                ret = convert_string_talloc(
     5394                        names, CH_UTF16LE, CH_UNIX,
     5395                        src, 2 * sizeof(SHADOW_COPY_LABEL),
     5396                        &names[i], &converted_size, True);
     5397                if (!ret) {
     5398                        TALLOC_FREE(names);
     5399                        return NT_STATUS_INVALID_NETWORK_RESPONSE;
     5400                }
     5401        }
     5402        *pnum_names = num_names;
     5403        *pnames = names;
     5404        return NT_STATUS_OK;
     5405}
     5406
     5407NTSTATUS cli_shadow_copy_data(TALLOC_CTX *mem_ctx, struct cli_state *cli,
     5408                              uint16_t fnum, bool get_names,
     5409                              char ***pnames, int *pnum_names)
     5410{
     5411        TALLOC_CTX *frame = talloc_stackframe();
     5412        struct event_context *ev;
     5413        struct tevent_req *req;
     5414        NTSTATUS status = NT_STATUS_NO_MEMORY;
     5415
     5416        if (cli_has_async_calls(cli)) {
     5417                /*
     5418                 * Can't use sync call while an async call is in flight
     5419                 */
     5420                status = NT_STATUS_INVALID_PARAMETER;
     5421                goto fail;
     5422        }
     5423        ev = event_context_init(frame);
     5424        if (ev == NULL) {
     5425                goto fail;
     5426        }
     5427        req = cli_shadow_copy_data_send(frame, ev, cli, fnum, get_names);
     5428        if (req == NULL) {
     5429                goto fail;
     5430        }
     5431        if (!tevent_req_poll_ntstatus(req, ev, &status)) {
     5432                goto fail;
     5433        }
     5434        status = cli_shadow_copy_data_recv(req, mem_ctx, pnames, pnum_names);
     5435 fail:
     5436        TALLOC_FREE(frame);
     5437        if (!NT_STATUS_IS_OK(status)) {
     5438                cli_set_error(cli, status);
     5439        }
     5440        return status;
     5441}
Note: See TracChangeset for help on using the changeset viewer.