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