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