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