s3: libsmb: Add cli_smb2_chkpath() and use from cli_chkpath().
[bbaumbach/samba-autobuild/.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_smb1_done(struct tevent_req *subreq);
1807 static void cli_nt_delete_on_close_smb2_done(struct tevent_req *subreq);
1808
1809 struct tevent_req *cli_nt_delete_on_close_send(TALLOC_CTX *mem_ctx,
1810                                         struct tevent_context *ev,
1811                                         struct cli_state *cli,
1812                                         uint16_t fnum,
1813                                         bool flag)
1814 {
1815         struct tevent_req *req = NULL, *subreq = NULL;
1816         struct doc_state *state = NULL;
1817
1818         req = tevent_req_create(mem_ctx, &state, struct doc_state);
1819         if (req == NULL) {
1820                 return NULL;
1821         }
1822
1823         if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
1824                 subreq = cli_smb2_delete_on_close_send(state, ev, cli,
1825                                                        fnum, flag);
1826                 if (tevent_req_nomem(subreq, req)) {
1827                         return tevent_req_post(req, ev);
1828                 }
1829                 tevent_req_set_callback(subreq,
1830                                         cli_nt_delete_on_close_smb2_done,
1831                                         req);
1832                 return req;
1833         }
1834
1835         /* Setup setup word. */
1836         SSVAL(&state->setup, 0, TRANSACT2_SETFILEINFO);
1837
1838         /* Setup param array. */
1839         SSVAL(state->param,0,fnum);
1840         SSVAL(state->param,2,SMB_SET_FILE_DISPOSITION_INFO);
1841
1842         /* Setup data array. */
1843         SCVAL(&state->data[0], 0, flag ? 1 : 0);
1844
1845         subreq = cli_trans_send(state,                  /* mem ctx. */
1846                                 ev,                     /* event ctx. */
1847                                 cli,                    /* cli_state. */
1848                                 0,                      /* additional_flags2 */
1849                                 SMBtrans2,              /* cmd. */
1850                                 NULL,                   /* pipe name. */
1851                                 -1,                     /* fid. */
1852                                 0,                      /* function. */
1853                                 0,                      /* flags. */
1854                                 &state->setup,          /* setup. */
1855                                 1,                      /* num setup uint16_t words. */
1856                                 0,                      /* max returned setup. */
1857                                 state->param,           /* param. */
1858                                 6,                      /* num param. */
1859                                 2,                      /* max returned param. */
1860                                 state->data,            /* data. */
1861                                 1,                      /* num data. */
1862                                 0);                     /* max returned data. */
1863
1864         if (tevent_req_nomem(subreq, req)) {
1865                 return tevent_req_post(req, ev);
1866         }
1867         tevent_req_set_callback(subreq,
1868                                 cli_nt_delete_on_close_smb1_done,
1869                                 req);
1870         return req;
1871 }
1872
1873 static void cli_nt_delete_on_close_smb1_done(struct tevent_req *subreq)
1874 {
1875         NTSTATUS status = cli_trans_recv(subreq, NULL, NULL, NULL, 0, NULL,
1876                                          NULL, 0, NULL, NULL, 0, NULL);
1877         tevent_req_simple_finish_ntstatus(subreq, status);
1878 }
1879
1880 static void cli_nt_delete_on_close_smb2_done(struct tevent_req *subreq)
1881 {
1882         NTSTATUS status = cli_smb2_delete_on_close_recv(subreq);
1883         tevent_req_simple_finish_ntstatus(subreq, status);
1884 }
1885
1886 NTSTATUS cli_nt_delete_on_close_recv(struct tevent_req *req)
1887 {
1888         return tevent_req_simple_recv_ntstatus(req);
1889 }
1890
1891 NTSTATUS cli_nt_delete_on_close(struct cli_state *cli, uint16_t fnum, bool flag)
1892 {
1893         TALLOC_CTX *frame = talloc_stackframe();
1894         struct tevent_context *ev = NULL;
1895         struct tevent_req *req = NULL;
1896         NTSTATUS status = NT_STATUS_OK;
1897
1898         if (smbXcli_conn_has_async_calls(cli->conn)) {
1899                 /*
1900                  * Can't use sync call while an async call is in flight
1901                  */
1902                 status = NT_STATUS_INVALID_PARAMETER;
1903                 goto fail;
1904         }
1905
1906         ev = samba_tevent_context_init(frame);
1907         if (ev == NULL) {
1908                 status = NT_STATUS_NO_MEMORY;
1909                 goto fail;
1910         }
1911
1912         req = cli_nt_delete_on_close_send(frame,
1913                                 ev,
1914                                 cli,
1915                                 fnum,
1916                                 flag);
1917         if (req == NULL) {
1918                 status = NT_STATUS_NO_MEMORY;
1919                 goto fail;
1920         }
1921
1922         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
1923                 goto fail;
1924         }
1925
1926         status = cli_nt_delete_on_close_recv(req);
1927
1928  fail:
1929         TALLOC_FREE(frame);
1930         return status;
1931 }
1932
1933 struct cli_ntcreate1_state {
1934         uint16_t vwv[24];
1935         uint16_t fnum;
1936         struct smb_create_returns cr;
1937         struct tevent_req *subreq;
1938 };
1939
1940 static void cli_ntcreate1_done(struct tevent_req *subreq);
1941 static bool cli_ntcreate1_cancel(struct tevent_req *req);
1942
1943 static struct tevent_req *cli_ntcreate1_send(TALLOC_CTX *mem_ctx,
1944                                              struct tevent_context *ev,
1945                                              struct cli_state *cli,
1946                                              const char *fname,
1947                                              uint32_t CreatFlags,
1948                                              uint32_t DesiredAccess,
1949                                              uint32_t FileAttributes,
1950                                              uint32_t ShareAccess,
1951                                              uint32_t CreateDisposition,
1952                                              uint32_t CreateOptions,
1953                                              uint8_t SecurityFlags)
1954 {
1955         struct tevent_req *req, *subreq;
1956         struct cli_ntcreate1_state *state;
1957         uint16_t *vwv;
1958         uint8_t *bytes;
1959         size_t converted_len;
1960         uint16_t additional_flags2 = 0;
1961
1962         req = tevent_req_create(mem_ctx, &state, struct cli_ntcreate1_state);
1963         if (req == NULL) {
1964                 return NULL;
1965         }
1966
1967         vwv = state->vwv;
1968
1969         SCVAL(vwv+0, 0, 0xFF);
1970         SCVAL(vwv+0, 1, 0);
1971         SSVAL(vwv+1, 0, 0);
1972         SCVAL(vwv+2, 0, 0);
1973
1974         if (cli->use_oplocks) {
1975                 CreatFlags |= (REQUEST_OPLOCK|REQUEST_BATCH_OPLOCK);
1976         }
1977         SIVAL(vwv+3, 1, CreatFlags);
1978         SIVAL(vwv+5, 1, 0x0);   /* RootDirectoryFid */
1979         SIVAL(vwv+7, 1, DesiredAccess);
1980         SIVAL(vwv+9, 1, 0x0);   /* AllocationSize */
1981         SIVAL(vwv+11, 1, 0x0);  /* AllocationSize */
1982         SIVAL(vwv+13, 1, FileAttributes);
1983         SIVAL(vwv+15, 1, ShareAccess);
1984         SIVAL(vwv+17, 1, CreateDisposition);
1985         SIVAL(vwv+19, 1, CreateOptions |
1986                 (cli->backup_intent ? FILE_OPEN_FOR_BACKUP_INTENT : 0));
1987         SIVAL(vwv+21, 1, 0x02); /* ImpersonationLevel */
1988         SCVAL(vwv+23, 1, SecurityFlags);
1989
1990         bytes = talloc_array(state, uint8_t, 0);
1991         bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
1992                                    fname, strlen(fname)+1,
1993                                    &converted_len);
1994
1995         if (clistr_is_previous_version_path(fname, NULL, NULL, NULL)) {
1996                 additional_flags2 = FLAGS2_REPARSE_PATH;
1997         }
1998
1999         /* sigh. this copes with broken netapp filer behaviour */
2000         bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "", 1, NULL);
2001
2002         if (tevent_req_nomem(bytes, req)) {
2003                 return tevent_req_post(req, ev);
2004         }
2005
2006         SSVAL(vwv+2, 1, converted_len);
2007
2008         subreq = cli_smb_send(state, ev, cli, SMBntcreateX, 0,
2009                         additional_flags2, 24, vwv,
2010                         talloc_get_size(bytes), bytes);
2011         if (tevent_req_nomem(subreq, req)) {
2012                 return tevent_req_post(req, ev);
2013         }
2014         tevent_req_set_callback(subreq, cli_ntcreate1_done, req);
2015
2016         state->subreq = subreq;
2017         tevent_req_set_cancel_fn(req, cli_ntcreate1_cancel);
2018
2019         return req;
2020 }
2021
2022 static void cli_ntcreate1_done(struct tevent_req *subreq)
2023 {
2024         struct tevent_req *req = tevent_req_callback_data(
2025                 subreq, struct tevent_req);
2026         struct cli_ntcreate1_state *state = tevent_req_data(
2027                 req, struct cli_ntcreate1_state);
2028         uint8_t wct;
2029         uint16_t *vwv;
2030         uint32_t num_bytes;
2031         uint8_t *bytes;
2032         NTSTATUS status;
2033
2034         status = cli_smb_recv(subreq, state, NULL, 34, &wct, &vwv,
2035                               &num_bytes, &bytes);
2036         TALLOC_FREE(subreq);
2037         if (tevent_req_nterror(req, status)) {
2038                 return;
2039         }
2040         state->cr.oplock_level = CVAL(vwv+2, 0);
2041         state->fnum = SVAL(vwv+2, 1);
2042         state->cr.create_action = IVAL(vwv+3, 1);
2043         state->cr.creation_time = BVAL(vwv+5, 1);
2044         state->cr.last_access_time = BVAL(vwv+9, 1);
2045         state->cr.last_write_time = BVAL(vwv+13, 1);
2046         state->cr.change_time   = BVAL(vwv+17, 1);
2047         state->cr.file_attributes = IVAL(vwv+21, 1);
2048         state->cr.allocation_size = BVAL(vwv+23, 1);
2049         state->cr.end_of_file   = BVAL(vwv+27, 1);
2050
2051         tevent_req_done(req);
2052 }
2053
2054 static bool cli_ntcreate1_cancel(struct tevent_req *req)
2055 {
2056         struct cli_ntcreate1_state *state = tevent_req_data(
2057                 req, struct cli_ntcreate1_state);
2058         return tevent_req_cancel(state->subreq);
2059 }
2060
2061 static NTSTATUS cli_ntcreate1_recv(struct tevent_req *req,
2062                                    uint16_t *pfnum,
2063                                    struct smb_create_returns *cr)
2064 {
2065         struct cli_ntcreate1_state *state = tevent_req_data(
2066                 req, struct cli_ntcreate1_state);
2067         NTSTATUS status;
2068
2069         if (tevent_req_is_nterror(req, &status)) {
2070                 return status;
2071         }
2072         *pfnum = state->fnum;
2073         if (cr != NULL) {
2074                 *cr = state->cr;
2075         }
2076         return NT_STATUS_OK;
2077 }
2078
2079 struct cli_ntcreate_state {
2080         NTSTATUS (*recv)(struct tevent_req *req, uint16_t *fnum,
2081                          struct smb_create_returns *cr);
2082         struct smb_create_returns cr;
2083         uint16_t fnum;
2084         struct tevent_req *subreq;
2085 };
2086
2087 static void cli_ntcreate_done(struct tevent_req *subreq);
2088 static bool cli_ntcreate_cancel(struct tevent_req *req);
2089
2090 struct tevent_req *cli_ntcreate_send(TALLOC_CTX *mem_ctx,
2091                                      struct tevent_context *ev,
2092                                      struct cli_state *cli,
2093                                      const char *fname,
2094                                      uint32_t create_flags,
2095                                      uint32_t desired_access,
2096                                      uint32_t file_attributes,
2097                                      uint32_t share_access,
2098                                      uint32_t create_disposition,
2099                                      uint32_t create_options,
2100                                      uint8_t security_flags)
2101 {
2102         struct tevent_req *req, *subreq;
2103         struct cli_ntcreate_state *state;
2104
2105         req = tevent_req_create(mem_ctx, &state, struct cli_ntcreate_state);
2106         if (req == NULL) {
2107                 return NULL;
2108         }
2109
2110         if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
2111                 state->recv = cli_smb2_create_fnum_recv;
2112
2113                 if (cli->use_oplocks) {
2114                         create_flags |= REQUEST_OPLOCK|REQUEST_BATCH_OPLOCK;
2115                 }
2116
2117                 subreq = cli_smb2_create_fnum_send(
2118                         state, ev, cli, fname, create_flags, desired_access,
2119                         file_attributes, share_access, create_disposition,
2120                         create_options);
2121         } else {
2122                 state->recv = cli_ntcreate1_recv;
2123                 subreq = cli_ntcreate1_send(
2124                         state, ev, cli, fname, create_flags, desired_access,
2125                         file_attributes, share_access, create_disposition,
2126                         create_options, security_flags);
2127         }
2128         if (tevent_req_nomem(subreq, req)) {
2129                 return tevent_req_post(req, ev);
2130         }
2131         tevent_req_set_callback(subreq, cli_ntcreate_done, req);
2132
2133         state->subreq = subreq;
2134         tevent_req_set_cancel_fn(req, cli_ntcreate_cancel);
2135
2136         return req;
2137 }
2138
2139 static void cli_ntcreate_done(struct tevent_req *subreq)
2140 {
2141         struct tevent_req *req = tevent_req_callback_data(
2142                 subreq, struct tevent_req);
2143         struct cli_ntcreate_state *state = tevent_req_data(
2144                 req, struct cli_ntcreate_state);
2145         NTSTATUS status;
2146
2147         status = state->recv(subreq, &state->fnum, &state->cr);
2148         TALLOC_FREE(subreq);
2149         if (tevent_req_nterror(req, status)) {
2150                 return;
2151         }
2152         tevent_req_done(req);
2153 }
2154
2155 static bool cli_ntcreate_cancel(struct tevent_req *req)
2156 {
2157         struct cli_ntcreate_state *state = tevent_req_data(
2158                 req, struct cli_ntcreate_state);
2159         return tevent_req_cancel(state->subreq);
2160 }
2161
2162 NTSTATUS cli_ntcreate_recv(struct tevent_req *req, uint16_t *fnum,
2163                            struct smb_create_returns *cr)
2164 {
2165         struct cli_ntcreate_state *state = tevent_req_data(
2166                 req, struct cli_ntcreate_state);
2167         NTSTATUS status;
2168
2169         if (tevent_req_is_nterror(req, &status)) {
2170                 return status;
2171         }
2172         if (fnum != NULL) {
2173                 *fnum = state->fnum;
2174         }
2175         if (cr != NULL) {
2176                 *cr = state->cr;
2177         }
2178         return NT_STATUS_OK;
2179 }
2180
2181 NTSTATUS cli_ntcreate(struct cli_state *cli,
2182                       const char *fname,
2183                       uint32_t CreatFlags,
2184                       uint32_t DesiredAccess,
2185                       uint32_t FileAttributes,
2186                       uint32_t ShareAccess,
2187                       uint32_t CreateDisposition,
2188                       uint32_t CreateOptions,
2189                       uint8_t SecurityFlags,
2190                       uint16_t *pfid,
2191                       struct smb_create_returns *cr)
2192 {
2193         TALLOC_CTX *frame = talloc_stackframe();
2194         struct tevent_context *ev;
2195         struct tevent_req *req;
2196         NTSTATUS status = NT_STATUS_NO_MEMORY;
2197
2198         if (smbXcli_conn_has_async_calls(cli->conn)) {
2199                 /*
2200                  * Can't use sync call while an async call is in flight
2201                  */
2202                 status = NT_STATUS_INVALID_PARAMETER;
2203                 goto fail;
2204         }
2205
2206         ev = samba_tevent_context_init(frame);
2207         if (ev == NULL) {
2208                 goto fail;
2209         }
2210
2211         req = cli_ntcreate_send(frame, ev, cli, fname, CreatFlags,
2212                                 DesiredAccess, FileAttributes, ShareAccess,
2213                                 CreateDisposition, CreateOptions,
2214                                 SecurityFlags);
2215         if (req == NULL) {
2216                 goto fail;
2217         }
2218
2219         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2220                 goto fail;
2221         }
2222
2223         status = cli_ntcreate_recv(req, pfid, cr);
2224  fail:
2225         TALLOC_FREE(frame);
2226         return status;
2227 }
2228
2229 struct cli_nttrans_create_state {
2230         uint16_t fnum;
2231         struct smb_create_returns cr;
2232 };
2233
2234 static void cli_nttrans_create_done(struct tevent_req *subreq);
2235
2236 struct tevent_req *cli_nttrans_create_send(TALLOC_CTX *mem_ctx,
2237                                            struct tevent_context *ev,
2238                                            struct cli_state *cli,
2239                                            const char *fname,
2240                                            uint32_t CreatFlags,
2241                                            uint32_t DesiredAccess,
2242                                            uint32_t FileAttributes,
2243                                            uint32_t ShareAccess,
2244                                            uint32_t CreateDisposition,
2245                                            uint32_t CreateOptions,
2246                                            uint8_t SecurityFlags,
2247                                            struct security_descriptor *secdesc,
2248                                            struct ea_struct *eas,
2249                                            int num_eas)
2250 {
2251         struct tevent_req *req, *subreq;
2252         struct cli_nttrans_create_state *state;
2253         uint8_t *param;
2254         uint8_t *secdesc_buf;
2255         size_t secdesc_len;
2256         NTSTATUS status;
2257         size_t converted_len;
2258         uint16_t additional_flags2 = 0;
2259
2260         req = tevent_req_create(mem_ctx,
2261                                 &state, struct cli_nttrans_create_state);
2262         if (req == NULL) {
2263                 return NULL;
2264         }
2265
2266         if (secdesc != NULL) {
2267                 status = marshall_sec_desc(talloc_tos(), secdesc,
2268                                            &secdesc_buf, &secdesc_len);
2269                 if (tevent_req_nterror(req, status)) {
2270                         DEBUG(10, ("marshall_sec_desc failed: %s\n",
2271                                    nt_errstr(status)));
2272                         return tevent_req_post(req, ev);
2273                 }
2274         } else {
2275                 secdesc_buf = NULL;
2276                 secdesc_len = 0;
2277         }
2278
2279         if (num_eas != 0) {
2280                 /*
2281                  * TODO ;-)
2282                  */
2283                 tevent_req_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
2284                 return tevent_req_post(req, ev);
2285         }
2286
2287         param = talloc_array(state, uint8_t, 53);
2288         if (tevent_req_nomem(param, req)) {
2289                 return tevent_req_post(req, ev);
2290         }
2291
2292         param = trans2_bytes_push_str(param, smbXcli_conn_use_unicode(cli->conn),
2293                                       fname, strlen(fname),
2294                                       &converted_len);
2295         if (tevent_req_nomem(param, req)) {
2296                 return tevent_req_post(req, ev);
2297         }
2298
2299         if (clistr_is_previous_version_path(fname, NULL, NULL, NULL)) {
2300                 additional_flags2 = FLAGS2_REPARSE_PATH;
2301         }
2302
2303         SIVAL(param, 0, CreatFlags);
2304         SIVAL(param, 4, 0x0);   /* RootDirectoryFid */
2305         SIVAL(param, 8, DesiredAccess);
2306         SIVAL(param, 12, 0x0);  /* AllocationSize */
2307         SIVAL(param, 16, 0x0);  /* AllocationSize */
2308         SIVAL(param, 20, FileAttributes);
2309         SIVAL(param, 24, ShareAccess);
2310         SIVAL(param, 28, CreateDisposition);
2311         SIVAL(param, 32, CreateOptions |
2312                 (cli->backup_intent ? FILE_OPEN_FOR_BACKUP_INTENT : 0));
2313         SIVAL(param, 36, secdesc_len);
2314         SIVAL(param, 40, 0);     /* EA length*/
2315         SIVAL(param, 44, converted_len);
2316         SIVAL(param, 48, 0x02); /* ImpersonationLevel */
2317         SCVAL(param, 52, SecurityFlags);
2318
2319         subreq = cli_trans_send(state, ev, cli,
2320                                 additional_flags2, /* additional_flags2 */
2321                                 SMBnttrans,
2322                                 NULL, -1, /* name, fid */
2323                                 NT_TRANSACT_CREATE, 0,
2324                                 NULL, 0, 0, /* setup */
2325                                 param, talloc_get_size(param), 128, /* param */
2326                                 secdesc_buf, secdesc_len, 0); /* data */
2327         if (tevent_req_nomem(subreq, req)) {
2328                 return tevent_req_post(req, ev);
2329         }
2330         tevent_req_set_callback(subreq, cli_nttrans_create_done, req);
2331         return req;
2332 }
2333
2334 static void cli_nttrans_create_done(struct tevent_req *subreq)
2335 {
2336         struct tevent_req *req = tevent_req_callback_data(
2337                 subreq, struct tevent_req);
2338         struct cli_nttrans_create_state *state = tevent_req_data(
2339                 req, struct cli_nttrans_create_state);
2340         uint8_t *param;
2341         uint32_t num_param;
2342         NTSTATUS status;
2343
2344         status = cli_trans_recv(subreq, talloc_tos(), NULL,
2345                                 NULL, 0, NULL, /* rsetup */
2346                                 &param, 69, &num_param,
2347                                 NULL, 0, NULL);
2348         if (tevent_req_nterror(req, status)) {
2349                 return;
2350         }
2351         state->cr.oplock_level = CVAL(param, 0);
2352         state->fnum = SVAL(param, 2);
2353         state->cr.create_action = IVAL(param, 4);
2354         state->cr.creation_time = BVAL(param, 12);
2355         state->cr.last_access_time = BVAL(param, 20);
2356         state->cr.last_write_time = BVAL(param, 28);
2357         state->cr.change_time   = BVAL(param, 36);
2358         state->cr.file_attributes = IVAL(param, 44);
2359         state->cr.allocation_size = BVAL(param, 48);
2360         state->cr.end_of_file   = BVAL(param, 56);
2361
2362         TALLOC_FREE(param);
2363         tevent_req_done(req);
2364 }
2365
2366 NTSTATUS cli_nttrans_create_recv(struct tevent_req *req,
2367                         uint16_t *fnum,
2368                         struct smb_create_returns *cr)
2369 {
2370         struct cli_nttrans_create_state *state = tevent_req_data(
2371                 req, struct cli_nttrans_create_state);
2372         NTSTATUS status;
2373
2374         if (tevent_req_is_nterror(req, &status)) {
2375                 return status;
2376         }
2377         *fnum = state->fnum;
2378         if (cr != NULL) {
2379                 *cr = state->cr;
2380         }
2381         return NT_STATUS_OK;
2382 }
2383
2384 NTSTATUS cli_nttrans_create(struct cli_state *cli,
2385                             const char *fname,
2386                             uint32_t CreatFlags,
2387                             uint32_t DesiredAccess,
2388                             uint32_t FileAttributes,
2389                             uint32_t ShareAccess,
2390                             uint32_t CreateDisposition,
2391                             uint32_t CreateOptions,
2392                             uint8_t SecurityFlags,
2393                             struct security_descriptor *secdesc,
2394                             struct ea_struct *eas,
2395                             int num_eas,
2396                             uint16_t *pfid,
2397                             struct smb_create_returns *cr)
2398 {
2399         TALLOC_CTX *frame = talloc_stackframe();
2400         struct tevent_context *ev;
2401         struct tevent_req *req;
2402         NTSTATUS status = NT_STATUS_NO_MEMORY;
2403
2404         if (smbXcli_conn_has_async_calls(cli->conn)) {
2405                 /*
2406                  * Can't use sync call while an async call is in flight
2407                  */
2408                 status = NT_STATUS_INVALID_PARAMETER;
2409                 goto fail;
2410         }
2411         ev = samba_tevent_context_init(frame);
2412         if (ev == NULL) {
2413                 goto fail;
2414         }
2415         req = cli_nttrans_create_send(frame, ev, cli, fname, CreatFlags,
2416                                       DesiredAccess, FileAttributes,
2417                                       ShareAccess, CreateDisposition,
2418                                       CreateOptions, SecurityFlags,
2419                                       secdesc, eas, num_eas);
2420         if (req == NULL) {
2421                 goto fail;
2422         }
2423         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2424                 goto fail;
2425         }
2426         status = cli_nttrans_create_recv(req, pfid, cr);
2427  fail:
2428         TALLOC_FREE(frame);
2429         return status;
2430 }
2431
2432 /****************************************************************************
2433  Open a file
2434  WARNING: if you open with O_WRONLY then getattrE won't work!
2435 ****************************************************************************/
2436
2437 struct cli_openx_state {
2438         const char *fname;
2439         uint16_t vwv[15];
2440         uint16_t fnum;
2441         struct iovec bytes;
2442 };
2443
2444 static void cli_openx_done(struct tevent_req *subreq);
2445
2446 struct tevent_req *cli_openx_create(TALLOC_CTX *mem_ctx,
2447                                    struct tevent_context *ev,
2448                                    struct cli_state *cli, const char *fname,
2449                                    int flags, int share_mode,
2450                                    struct tevent_req **psmbreq)
2451 {
2452         struct tevent_req *req, *subreq;
2453         struct cli_openx_state *state;
2454         unsigned openfn;
2455         unsigned accessmode;
2456         uint8_t additional_flags;
2457         uint16_t additional_flags2 = 0;
2458         uint8_t *bytes;
2459
2460         req = tevent_req_create(mem_ctx, &state, struct cli_openx_state);
2461         if (req == NULL) {
2462                 return NULL;
2463         }
2464
2465         openfn = 0;
2466         if (flags & O_CREAT) {
2467                 openfn |= (1<<4);
2468         }
2469         if (!(flags & O_EXCL)) {
2470                 if (flags & O_TRUNC)
2471                         openfn |= (1<<1);
2472                 else
2473                         openfn |= (1<<0);
2474         }
2475
2476         accessmode = (share_mode<<4);
2477
2478         if ((flags & O_ACCMODE) == O_RDWR) {
2479                 accessmode |= 2;
2480         } else if ((flags & O_ACCMODE) == O_WRONLY) {
2481                 accessmode |= 1;
2482         }
2483
2484 #if defined(O_SYNC)
2485         if ((flags & O_SYNC) == O_SYNC) {
2486                 accessmode |= (1<<14);
2487         }
2488 #endif /* O_SYNC */
2489
2490         if (share_mode == DENY_FCB) {
2491                 accessmode = 0xFF;
2492         }
2493
2494         SCVAL(state->vwv + 0, 0, 0xFF);
2495         SCVAL(state->vwv + 0, 1, 0);
2496         SSVAL(state->vwv + 1, 0, 0);
2497         SSVAL(state->vwv + 2, 0, 0);  /* no additional info */
2498         SSVAL(state->vwv + 3, 0, accessmode);
2499         SSVAL(state->vwv + 4, 0, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2500         SSVAL(state->vwv + 5, 0, 0);
2501         SIVAL(state->vwv + 6, 0, 0);
2502         SSVAL(state->vwv + 8, 0, openfn);
2503         SIVAL(state->vwv + 9, 0, 0);
2504         SIVAL(state->vwv + 11, 0, 0);
2505         SIVAL(state->vwv + 13, 0, 0);
2506
2507         additional_flags = 0;
2508
2509         if (cli->use_oplocks) {
2510                 /* if using oplocks then ask for a batch oplock via
2511                    core and extended methods */
2512                 additional_flags =
2513                         FLAG_REQUEST_OPLOCK|FLAG_REQUEST_BATCH_OPLOCK;
2514                 SSVAL(state->vwv+2, 0, SVAL(state->vwv+2, 0) | 6);
2515         }
2516
2517         bytes = talloc_array(state, uint8_t, 0);
2518         bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), fname,
2519                                    strlen(fname)+1, NULL);
2520
2521         if (tevent_req_nomem(bytes, req)) {
2522                 return tevent_req_post(req, ev);
2523         }
2524
2525         if (clistr_is_previous_version_path(fname, NULL, NULL, NULL)) {
2526                 additional_flags2 = FLAGS2_REPARSE_PATH;
2527         }
2528
2529         state->bytes.iov_base = (void *)bytes;
2530         state->bytes.iov_len = talloc_get_size(bytes);
2531
2532         subreq = cli_smb_req_create(state, ev, cli, SMBopenX, additional_flags,
2533                         additional_flags2, 15, state->vwv, 1, &state->bytes);
2534         if (subreq == NULL) {
2535                 TALLOC_FREE(req);
2536                 return NULL;
2537         }
2538         tevent_req_set_callback(subreq, cli_openx_done, req);
2539         *psmbreq = subreq;
2540         return req;
2541 }
2542
2543 struct tevent_req *cli_openx_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev,
2544                                  struct cli_state *cli, const char *fname,
2545                                  int flags, int share_mode)
2546 {
2547         struct tevent_req *req, *subreq;
2548         NTSTATUS status;
2549
2550         req = cli_openx_create(mem_ctx, ev, cli, fname, flags, share_mode,
2551                               &subreq);
2552         if (req == NULL) {
2553                 return NULL;
2554         }
2555
2556         status = smb1cli_req_chain_submit(&subreq, 1);
2557         if (tevent_req_nterror(req, status)) {
2558                 return tevent_req_post(req, ev);
2559         }
2560         return req;
2561 }
2562
2563 static void cli_openx_done(struct tevent_req *subreq)
2564 {
2565         struct tevent_req *req = tevent_req_callback_data(
2566                 subreq, struct tevent_req);
2567         struct cli_openx_state *state = tevent_req_data(
2568                 req, struct cli_openx_state);
2569         uint8_t wct;
2570         uint16_t *vwv;
2571         NTSTATUS status;
2572
2573         status = cli_smb_recv(subreq, state, NULL, 3, &wct, &vwv, NULL,
2574                               NULL);
2575         TALLOC_FREE(subreq);
2576         if (tevent_req_nterror(req, status)) {
2577                 return;
2578         }
2579         state->fnum = SVAL(vwv+2, 0);
2580         tevent_req_done(req);
2581 }
2582
2583 NTSTATUS cli_openx_recv(struct tevent_req *req, uint16_t *pfnum)
2584 {
2585         struct cli_openx_state *state = tevent_req_data(
2586                 req, struct cli_openx_state);
2587         NTSTATUS status;
2588
2589         if (tevent_req_is_nterror(req, &status)) {
2590                 return status;
2591         }
2592         *pfnum = state->fnum;
2593         return NT_STATUS_OK;
2594 }
2595
2596 NTSTATUS cli_openx(struct cli_state *cli, const char *fname, int flags,
2597              int share_mode, uint16_t *pfnum)
2598 {
2599         TALLOC_CTX *frame = talloc_stackframe();
2600         struct tevent_context *ev;
2601         struct tevent_req *req;
2602         NTSTATUS status = NT_STATUS_NO_MEMORY;
2603
2604         if (smbXcli_conn_has_async_calls(cli->conn)) {
2605                 /*
2606                  * Can't use sync call while an async call is in flight
2607                  */
2608                 status = NT_STATUS_INVALID_PARAMETER;
2609                 goto fail;
2610         }
2611
2612         ev = samba_tevent_context_init(frame);
2613         if (ev == NULL) {
2614                 goto fail;
2615         }
2616
2617         req = cli_openx_send(frame, ev, cli, fname, flags, share_mode);
2618         if (req == NULL) {
2619                 goto fail;
2620         }
2621
2622         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2623                 goto fail;
2624         }
2625
2626         status = cli_openx_recv(req, pfnum);
2627  fail:
2628         TALLOC_FREE(frame);
2629         return status;
2630 }
2631 /****************************************************************************
2632  Synchronous wrapper function that does an NtCreateX open by preference
2633  and falls back to openX if this fails.
2634 ****************************************************************************/
2635
2636 NTSTATUS cli_open(struct cli_state *cli, const char *fname, int flags,
2637                         int share_mode_in, uint16_t *pfnum)
2638 {
2639         NTSTATUS status;
2640         unsigned int openfn = 0;
2641         unsigned int dos_deny = 0;
2642         uint32_t access_mask, share_mode, create_disposition, create_options;
2643         struct smb_create_returns cr;
2644
2645         /* Do the initial mapping into OpenX parameters. */
2646         if (flags & O_CREAT) {
2647                 openfn |= (1<<4);
2648         }
2649         if (!(flags & O_EXCL)) {
2650                 if (flags & O_TRUNC)
2651                         openfn |= (1<<1);
2652                 else
2653                         openfn |= (1<<0);
2654         }
2655
2656         dos_deny = (share_mode_in<<4);
2657
2658         if ((flags & O_ACCMODE) == O_RDWR) {
2659                 dos_deny |= 2;
2660         } else if ((flags & O_ACCMODE) == O_WRONLY) {
2661                 dos_deny |= 1;
2662         }
2663
2664 #if defined(O_SYNC)
2665         if ((flags & O_SYNC) == O_SYNC) {
2666                 dos_deny |= (1<<14);
2667         }
2668 #endif /* O_SYNC */
2669
2670         if (share_mode_in == DENY_FCB) {
2671                 dos_deny = 0xFF;
2672         }
2673
2674 #if 0
2675         /* Hmmm. This is what I think the above code
2676            should look like if it's using the constants
2677            we #define. JRA. */
2678
2679         if (flags & O_CREAT) {
2680                 openfn |= OPENX_FILE_CREATE_IF_NOT_EXIST;
2681         }
2682         if (!(flags & O_EXCL)) {
2683                 if (flags & O_TRUNC)
2684                         openfn |= OPENX_FILE_EXISTS_TRUNCATE;
2685                 else
2686                         openfn |= OPENX_FILE_EXISTS_OPEN;
2687         }
2688
2689         dos_deny = SET_DENY_MODE(share_mode_in);
2690
2691         if ((flags & O_ACCMODE) == O_RDWR) {
2692                 dos_deny |= DOS_OPEN_RDWR;
2693         } else if ((flags & O_ACCMODE) == O_WRONLY) {
2694                 dos_deny |= DOS_OPEN_WRONLY;
2695         }
2696
2697 #if defined(O_SYNC)
2698         if ((flags & O_SYNC) == O_SYNC) {
2699                 dos_deny |= FILE_SYNC_OPENMODE;
2700         }
2701 #endif /* O_SYNC */
2702
2703         if (share_mode_in == DENY_FCB) {
2704                 dos_deny = 0xFF;
2705         }
2706 #endif
2707
2708         if (!map_open_params_to_ntcreate(fname, dos_deny,
2709                                         openfn, &access_mask,
2710                                         &share_mode, &create_disposition,
2711                                         &create_options, NULL)) {
2712                 goto try_openx;
2713         }
2714
2715         status = cli_ntcreate(cli,
2716                                 fname,
2717                                 0,
2718                                 access_mask,
2719                                 0,
2720                                 share_mode,
2721                                 create_disposition,
2722                                 create_options,
2723                                 0,
2724                                 pfnum,
2725                                 &cr);
2726
2727         /* Try and cope will all varients of "we don't do this call"
2728            and fall back to openX. */
2729
2730         if (NT_STATUS_EQUAL(status,NT_STATUS_NOT_IMPLEMENTED) ||
2731                         NT_STATUS_EQUAL(status,NT_STATUS_INVALID_INFO_CLASS) ||
2732                         NT_STATUS_EQUAL(status,NT_STATUS_PROCEDURE_NOT_FOUND) ||
2733                         NT_STATUS_EQUAL(status,NT_STATUS_INVALID_LEVEL) ||
2734                         NT_STATUS_EQUAL(status,NT_STATUS_INVALID_PARAMETER) ||
2735                         NT_STATUS_EQUAL(status,NT_STATUS_INVALID_DEVICE_REQUEST) ||
2736                         NT_STATUS_EQUAL(status,NT_STATUS_INVALID_DEVICE_STATE) ||
2737                         NT_STATUS_EQUAL(status,NT_STATUS_CTL_FILE_NOT_SUPPORTED) ||
2738                         NT_STATUS_EQUAL(status,NT_STATUS_UNSUCCESSFUL)) {
2739                 goto try_openx;
2740         }
2741
2742         if (NT_STATUS_IS_OK(status) &&
2743             (create_options & FILE_NON_DIRECTORY_FILE) &&
2744             (cr.file_attributes & FILE_ATTRIBUTE_DIRECTORY))
2745         {
2746                 /*
2747                  * Some (broken) servers return a valid handle
2748                  * for directories even if FILE_NON_DIRECTORY_FILE
2749                  * is set. Just close the handle and set the
2750                  * error explicitly to NT_STATUS_FILE_IS_A_DIRECTORY.
2751                  */
2752                 status = cli_close(cli, *pfnum);
2753                 if (!NT_STATUS_IS_OK(status)) {
2754                         return status;
2755                 }
2756                 status = NT_STATUS_FILE_IS_A_DIRECTORY;
2757                 /* Set this so libsmbclient can retrieve it. */
2758                 cli->raw_status = status;
2759         }
2760
2761         return status;
2762
2763   try_openx:
2764
2765         return cli_openx(cli, fname, flags, share_mode_in, pfnum);
2766 }
2767
2768 /****************************************************************************
2769  Close a file.
2770 ****************************************************************************/
2771
2772 struct cli_close_state {
2773         uint16_t vwv[3];
2774 };
2775
2776 static void cli_close_done(struct tevent_req *subreq);
2777
2778 struct tevent_req *cli_close_create(TALLOC_CTX *mem_ctx,
2779                                 struct tevent_context *ev,
2780                                 struct cli_state *cli,
2781                                 uint16_t fnum,
2782                                 struct tevent_req **psubreq)
2783 {
2784         struct tevent_req *req, *subreq;
2785         struct cli_close_state *state;
2786
2787         req = tevent_req_create(mem_ctx, &state, struct cli_close_state);
2788         if (req == NULL) {
2789                 return NULL;
2790         }
2791
2792         SSVAL(state->vwv+0, 0, fnum);
2793         SIVALS(state->vwv+1, 0, -1);
2794
2795         subreq = cli_smb_req_create(state, ev, cli, SMBclose, 0, 0,
2796                                 3, state->vwv, 0, NULL);
2797         if (subreq == NULL) {
2798                 TALLOC_FREE(req);
2799                 return NULL;
2800         }
2801         tevent_req_set_callback(subreq, cli_close_done, req);
2802         *psubreq = subreq;
2803         return req;
2804 }
2805
2806 struct tevent_req *cli_close_send(TALLOC_CTX *mem_ctx,
2807                                 struct tevent_context *ev,
2808                                 struct cli_state *cli,
2809                                 uint16_t fnum)
2810 {
2811         struct tevent_req *req, *subreq;
2812         NTSTATUS status;
2813
2814         req = cli_close_create(mem_ctx, ev, cli, fnum, &subreq);
2815         if (req == NULL) {
2816                 return NULL;
2817         }
2818
2819         status = smb1cli_req_chain_submit(&subreq, 1);
2820         if (tevent_req_nterror(req, status)) {
2821                 return tevent_req_post(req, ev);
2822         }
2823         return req;
2824 }
2825
2826 static void cli_close_done(struct tevent_req *subreq)
2827 {
2828         struct tevent_req *req = tevent_req_callback_data(
2829                 subreq, struct tevent_req);
2830         NTSTATUS status;
2831
2832         status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
2833         TALLOC_FREE(subreq);
2834         if (tevent_req_nterror(req, status)) {
2835                 return;
2836         }
2837         tevent_req_done(req);
2838 }
2839
2840 NTSTATUS cli_close_recv(struct tevent_req *req)
2841 {
2842         return tevent_req_simple_recv_ntstatus(req);
2843 }
2844
2845 NTSTATUS cli_close(struct cli_state *cli, uint16_t fnum)
2846 {
2847         TALLOC_CTX *frame = NULL;
2848         struct tevent_context *ev;
2849         struct tevent_req *req;
2850         NTSTATUS status = NT_STATUS_OK;
2851
2852         if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
2853                 return cli_smb2_close_fnum(cli, fnum);
2854         }
2855
2856         frame = talloc_stackframe();
2857
2858         if (smbXcli_conn_has_async_calls(cli->conn)) {
2859                 /*
2860                  * Can't use sync call while an async call is in flight
2861                  */
2862                 status = NT_STATUS_INVALID_PARAMETER;
2863                 goto fail;
2864         }
2865
2866         ev = samba_tevent_context_init(frame);
2867         if (ev == NULL) {
2868                 status = NT_STATUS_NO_MEMORY;
2869                 goto fail;
2870         }
2871
2872         req = cli_close_send(frame, ev, cli, fnum);
2873         if (req == NULL) {
2874                 status = NT_STATUS_NO_MEMORY;
2875                 goto fail;
2876         }
2877
2878         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2879                 goto fail;
2880         }
2881
2882         status = cli_close_recv(req);
2883  fail:
2884         TALLOC_FREE(frame);
2885         return status;
2886 }
2887
2888 /****************************************************************************
2889  Truncate a file to a specified size
2890 ****************************************************************************/
2891
2892 struct ftrunc_state {
2893         uint16_t setup;
2894         uint8_t param[6];
2895         uint8_t data[8];
2896 };
2897
2898 static void cli_ftruncate_done(struct tevent_req *subreq)
2899 {
2900         NTSTATUS status = cli_trans_recv(subreq, NULL, NULL, NULL, 0, NULL,
2901                                          NULL, 0, NULL, NULL, 0, NULL);
2902         tevent_req_simple_finish_ntstatus(subreq, status);
2903 }
2904
2905 struct tevent_req *cli_ftruncate_send(TALLOC_CTX *mem_ctx,
2906                                         struct tevent_context *ev,
2907                                         struct cli_state *cli,
2908                                         uint16_t fnum,
2909                                         uint64_t size)
2910 {
2911         struct tevent_req *req = NULL, *subreq = NULL;
2912         struct ftrunc_state *state = NULL;
2913
2914         req = tevent_req_create(mem_ctx, &state, struct ftrunc_state);
2915         if (req == NULL) {
2916                 return NULL;
2917         }
2918
2919         /* Setup setup word. */
2920         SSVAL(&state->setup, 0, TRANSACT2_SETFILEINFO);
2921
2922         /* Setup param array. */
2923         SSVAL(state->param,0,fnum);
2924         SSVAL(state->param,2,SMB_SET_FILE_END_OF_FILE_INFO);
2925         SSVAL(state->param,4,0);
2926
2927         /* Setup data array. */
2928         SBVAL(state->data, 0, size);
2929
2930         subreq = cli_trans_send(state,                  /* mem ctx. */
2931                                 ev,                     /* event ctx. */
2932                                 cli,                    /* cli_state. */
2933                                 0,                      /* additional_flags2 */
2934                                 SMBtrans2,              /* cmd. */
2935                                 NULL,                   /* pipe name. */
2936                                 -1,                     /* fid. */
2937                                 0,                      /* function. */
2938                                 0,                      /* flags. */
2939                                 &state->setup,          /* setup. */
2940                                 1,                      /* num setup uint16_t words. */
2941                                 0,                      /* max returned setup. */
2942                                 state->param,           /* param. */
2943                                 6,                      /* num param. */
2944                                 2,                      /* max returned param. */
2945                                 state->data,            /* data. */
2946                                 8,                      /* num data. */
2947                                 0);                     /* max returned data. */
2948
2949         if (tevent_req_nomem(subreq, req)) {
2950                 return tevent_req_post(req, ev);
2951         }
2952         tevent_req_set_callback(subreq, cli_ftruncate_done, req);
2953         return req;
2954 }
2955
2956 NTSTATUS cli_ftruncate_recv(struct tevent_req *req)
2957 {
2958         return tevent_req_simple_recv_ntstatus(req);
2959 }
2960
2961 NTSTATUS cli_ftruncate(struct cli_state *cli, uint16_t fnum, uint64_t size)
2962 {
2963         TALLOC_CTX *frame = NULL;
2964         struct tevent_context *ev = NULL;
2965         struct tevent_req *req = NULL;
2966         NTSTATUS status = NT_STATUS_OK;
2967
2968         if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
2969                 return cli_smb2_ftruncate(cli, fnum, size);
2970         }
2971
2972         frame = talloc_stackframe();
2973
2974         if (smbXcli_conn_has_async_calls(cli->conn)) {
2975                 /*
2976                  * Can't use sync call while an async call is in flight
2977                  */
2978                 status = NT_STATUS_INVALID_PARAMETER;
2979                 goto fail;
2980         }
2981
2982         ev = samba_tevent_context_init(frame);
2983         if (ev == NULL) {
2984                 status = NT_STATUS_NO_MEMORY;
2985                 goto fail;
2986         }
2987
2988         req = cli_ftruncate_send(frame,
2989                                 ev,
2990                                 cli,
2991                                 fnum,
2992                                 size);
2993         if (req == NULL) {
2994                 status = NT_STATUS_NO_MEMORY;
2995                 goto fail;
2996         }
2997
2998         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2999                 goto fail;
3000         }
3001
3002         status = cli_ftruncate_recv(req);
3003
3004  fail:
3005         TALLOC_FREE(frame);
3006         return status;
3007 }
3008
3009 /****************************************************************************
3010  send a lock with a specified locktype
3011  this is used for testing LOCKING_ANDX_CANCEL_LOCK
3012 ****************************************************************************/
3013
3014 NTSTATUS cli_locktype(struct cli_state *cli, uint16_t fnum,
3015                       uint32_t offset, uint32_t len,
3016                       int timeout, unsigned char locktype)
3017 {
3018         uint16_t vwv[8];
3019         uint8_t bytes[10];
3020         NTSTATUS status;
3021         unsigned int set_timeout = 0;
3022         unsigned int saved_timeout = 0;
3023
3024         SCVAL(vwv + 0, 0, 0xff);
3025         SCVAL(vwv + 0, 1, 0);
3026         SSVAL(vwv + 1, 0, 0);
3027         SSVAL(vwv + 2, 0, fnum);
3028         SCVAL(vwv + 3, 0, locktype);
3029         SCVAL(vwv + 3, 1, 0);
3030         SIVALS(vwv + 4, 0, timeout);
3031         SSVAL(vwv + 6, 0, 0);
3032         SSVAL(vwv + 7, 0, 1);
3033
3034         SSVAL(bytes, 0, cli_getpid(cli));
3035         SIVAL(bytes, 2, offset);
3036         SIVAL(bytes, 6, len);
3037
3038         if (timeout != 0) {
3039                 if (timeout == -1) {
3040                         set_timeout = 0x7FFFFFFF;
3041                 } else {
3042                         set_timeout = timeout + 2*1000;
3043                 }
3044                 saved_timeout = cli_set_timeout(cli, set_timeout);
3045         }
3046
3047         status = cli_smb(talloc_tos(), cli, SMBlockingX, 0, 8, vwv,
3048                          10, bytes, NULL, 0, NULL, NULL, NULL, NULL);
3049
3050         if (saved_timeout != 0) {
3051                 cli_set_timeout(cli, saved_timeout);
3052         }
3053
3054         return status;
3055 }
3056
3057 /****************************************************************************
3058  Lock a file.
3059  note that timeout is in units of 2 milliseconds
3060 ****************************************************************************/
3061
3062 NTSTATUS cli_lock32(struct cli_state *cli, uint16_t fnum,
3063                   uint32_t offset, uint32_t len, int timeout,
3064                   enum brl_type lock_type)
3065 {
3066         NTSTATUS status;
3067
3068         status = cli_locktype(cli, fnum, offset, len, timeout,
3069                               (lock_type == READ_LOCK? 1 : 0));
3070         return status;
3071 }
3072
3073 /****************************************************************************
3074  Unlock a file.
3075 ****************************************************************************/
3076
3077 struct cli_unlock_state {
3078         uint16_t vwv[8];
3079         uint8_t data[10];
3080 };
3081
3082 static void cli_unlock_done(struct tevent_req *subreq);
3083
3084 struct tevent_req *cli_unlock_send(TALLOC_CTX *mem_ctx,
3085                                 struct tevent_context *ev,
3086                                 struct cli_state *cli,
3087                                 uint16_t fnum,
3088                                 uint64_t offset,
3089                                 uint64_t len)
3090
3091 {
3092         struct tevent_req *req = NULL, *subreq = NULL;
3093         struct cli_unlock_state *state = NULL;
3094         uint8_t additional_flags = 0;
3095
3096         req = tevent_req_create(mem_ctx, &state, struct cli_unlock_state);
3097         if (req == NULL) {
3098                 return NULL;
3099         }
3100
3101         SCVAL(state->vwv+0, 0, 0xFF);
3102         SSVAL(state->vwv+2, 0, fnum);
3103         SCVAL(state->vwv+3, 0, 0);
3104         SIVALS(state->vwv+4, 0, 0);
3105         SSVAL(state->vwv+6, 0, 1);
3106         SSVAL(state->vwv+7, 0, 0);
3107
3108         SSVAL(state->data, 0, cli_getpid(cli));
3109         SIVAL(state->data, 2, offset);
3110         SIVAL(state->data, 6, len);
3111
3112         subreq = cli_smb_send(state, ev, cli, SMBlockingX, additional_flags, 0,
3113                                 8, state->vwv, 10, state->data);
3114         if (tevent_req_nomem(subreq, req)) {
3115                 return tevent_req_post(req, ev);
3116         }
3117         tevent_req_set_callback(subreq, cli_unlock_done, req);
3118         return req;
3119 }
3120
3121 static void cli_unlock_done(struct tevent_req *subreq)
3122 {
3123         struct tevent_req *req = tevent_req_callback_data(
3124                                 subreq, struct tevent_req);
3125         NTSTATUS status;
3126
3127         status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
3128         TALLOC_FREE(subreq);
3129         if (tevent_req_nterror(req, status)) {
3130                 return;
3131         }
3132         tevent_req_done(req);
3133 }
3134
3135 NTSTATUS cli_unlock_recv(struct tevent_req *req)
3136 {
3137         return tevent_req_simple_recv_ntstatus(req);
3138 }
3139
3140 NTSTATUS cli_unlock(struct cli_state *cli,
3141                         uint16_t fnum,
3142                         uint32_t offset,
3143                         uint32_t len)
3144 {
3145         TALLOC_CTX *frame = talloc_stackframe();
3146         struct tevent_context *ev;
3147         struct tevent_req *req;
3148         NTSTATUS status = NT_STATUS_OK;
3149
3150         if (smbXcli_conn_has_async_calls(cli->conn)) {
3151                 /*
3152                  * Can't use sync call while an async call is in flight
3153                  */
3154                 status = NT_STATUS_INVALID_PARAMETER;
3155                 goto fail;
3156         }
3157
3158         ev = samba_tevent_context_init(frame);
3159         if (ev == NULL) {
3160                 status = NT_STATUS_NO_MEMORY;
3161                 goto fail;
3162         }
3163
3164         req = cli_unlock_send(frame, ev, cli,
3165                         fnum, offset, len);
3166         if (req == NULL) {
3167                 status = NT_STATUS_NO_MEMORY;
3168                 goto fail;
3169         }
3170
3171         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3172                 goto fail;
3173         }
3174
3175         status = cli_unlock_recv(req);
3176
3177  fail:
3178         TALLOC_FREE(frame);
3179         return status;
3180 }
3181
3182 /****************************************************************************
3183  Lock a file with 64 bit offsets.
3184 ****************************************************************************/
3185
3186 NTSTATUS cli_lock64(struct cli_state *cli, uint16_t fnum,
3187                     uint64_t offset, uint64_t len, int timeout,
3188                     enum brl_type lock_type)
3189 {
3190         uint16_t vwv[8];
3191         uint8_t bytes[20];
3192         unsigned int set_timeout = 0;
3193         unsigned int saved_timeout = 0;
3194         int ltype;
3195         NTSTATUS status;
3196
3197         if (! (smb1cli_conn_capabilities(cli->conn) & CAP_LARGE_FILES)) {
3198                 return cli_lock32(cli, fnum, offset, len, timeout, lock_type);
3199         }
3200
3201         ltype = (lock_type == READ_LOCK? 1 : 0);
3202         ltype |= LOCKING_ANDX_LARGE_FILES;
3203
3204         SCVAL(vwv + 0, 0, 0xff);
3205         SCVAL(vwv + 0, 1, 0);
3206         SSVAL(vwv + 1, 0, 0);
3207         SSVAL(vwv + 2, 0, fnum);
3208         SCVAL(vwv + 3, 0, ltype);
3209         SCVAL(vwv + 3, 1, 0);
3210         SIVALS(vwv + 4, 0, timeout);
3211         SSVAL(vwv + 6, 0, 0);
3212         SSVAL(vwv + 7, 0, 1);
3213
3214         SIVAL(bytes, 0, cli_getpid(cli));
3215         SOFF_T_R(bytes, 4, offset);
3216         SOFF_T_R(bytes, 12, len);
3217
3218         if (timeout != 0) {
3219                 if (timeout == -1) {
3220                         set_timeout = 0x7FFFFFFF;
3221                 } else {
3222                         set_timeout = timeout + 2*1000;
3223                 }
3224                 saved_timeout = cli_set_timeout(cli, set_timeout);
3225         }
3226
3227         status = cli_smb(talloc_tos(), cli, SMBlockingX, 0, 8, vwv,
3228                          20, bytes, NULL, 0, NULL, NULL, NULL, NULL);
3229
3230         if (saved_timeout != 0) {
3231                 cli_set_timeout(cli, saved_timeout);
3232         }
3233
3234         return status;
3235 }
3236
3237 /****************************************************************************
3238  Unlock a file with 64 bit offsets.
3239 ****************************************************************************/
3240
3241 struct cli_unlock64_state {
3242         uint16_t vwv[8];
3243         uint8_t data[20];
3244 };
3245
3246 static void cli_unlock64_done(struct tevent_req *subreq);
3247
3248 struct tevent_req *cli_unlock64_send(TALLOC_CTX *mem_ctx,
3249                                 struct tevent_context *ev,
3250                                 struct cli_state *cli,
3251                                 uint16_t fnum,
3252                                 uint64_t offset,
3253                                 uint64_t len)
3254
3255 {
3256         struct tevent_req *req = NULL, *subreq = NULL;
3257         struct cli_unlock64_state *state = NULL;
3258         uint8_t additional_flags = 0;
3259
3260         req = tevent_req_create(mem_ctx, &state, struct cli_unlock64_state);
3261         if (req == NULL) {
3262                 return NULL;
3263         }
3264
3265         SCVAL(state->vwv+0, 0, 0xff);
3266         SSVAL(state->vwv+2, 0, fnum);
3267         SCVAL(state->vwv+3, 0,LOCKING_ANDX_LARGE_FILES);
3268         SIVALS(state->vwv+4, 0, 0);
3269         SSVAL(state->vwv+6, 0, 1);
3270         SSVAL(state->vwv+7, 0, 0);
3271
3272         SIVAL(state->data, 0, cli_getpid(cli));
3273         SOFF_T_R(state->data, 4, offset);
3274         SOFF_T_R(state->data, 12, len);
3275
3276         subreq = cli_smb_send(state, ev, cli, SMBlockingX, additional_flags, 0,
3277                                 8, state->vwv, 20, state->data);
3278         if (tevent_req_nomem(subreq, req)) {
3279                 return tevent_req_post(req, ev);
3280         }
3281         tevent_req_set_callback(subreq, cli_unlock64_done, req);
3282         return req;
3283 }
3284
3285 static void cli_unlock64_done(struct tevent_req *subreq)
3286 {
3287         struct tevent_req *req = tevent_req_callback_data(
3288                                 subreq, struct tevent_req);
3289         NTSTATUS status;
3290
3291         status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
3292         TALLOC_FREE(subreq);
3293         if (tevent_req_nterror(req, status)) {
3294                 return;
3295         }
3296         tevent_req_done(req);
3297 }
3298
3299 NTSTATUS cli_unlock64_recv(struct tevent_req *req)
3300 {
3301         return tevent_req_simple_recv_ntstatus(req);
3302 }
3303
3304 NTSTATUS cli_unlock64(struct cli_state *cli,
3305                                 uint16_t fnum,
3306                                 uint64_t offset,
3307                                 uint64_t len)
3308 {
3309         TALLOC_CTX *frame = talloc_stackframe();
3310         struct tevent_context *ev;
3311         struct tevent_req *req;
3312         NTSTATUS status = NT_STATUS_OK;
3313
3314         if (! (smb1cli_conn_capabilities(cli->conn) & CAP_LARGE_FILES)) {
3315                 return cli_unlock(cli, fnum, offset, len);
3316         }
3317
3318         if (smbXcli_conn_has_async_calls(cli->conn)) {
3319                 /*
3320                  * Can't use sync call while an async call is in flight
3321                  */
3322                 status = NT_STATUS_INVALID_PARAMETER;
3323                 goto fail;
3324         }
3325
3326         ev = samba_tevent_context_init(frame);
3327         if (ev == NULL) {
3328                 status = NT_STATUS_NO_MEMORY;
3329                 goto fail;
3330         }
3331
3332         req = cli_unlock64_send(frame, ev, cli,
3333                         fnum, offset, len);
3334         if (req == NULL) {
3335                 status = NT_STATUS_NO_MEMORY;
3336                 goto fail;
3337         }
3338
3339         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3340                 goto fail;
3341         }
3342
3343         status = cli_unlock64_recv(req);
3344
3345  fail:
3346         TALLOC_FREE(frame);
3347         return status;
3348 }
3349
3350 /****************************************************************************
3351  Get/unlock a POSIX lock on a file - internal function.
3352 ****************************************************************************/
3353
3354 struct posix_lock_state {
3355         uint16_t setup;
3356         uint8_t param[4];
3357         uint8_t data[POSIX_LOCK_DATA_SIZE];
3358 };
3359
3360 static void cli_posix_unlock_internal_done(struct tevent_req *subreq)
3361 {
3362         NTSTATUS status = cli_trans_recv(subreq, NULL, NULL, NULL, 0, NULL,
3363                                          NULL, 0, NULL, NULL, 0, NULL);
3364         tevent_req_simple_finish_ntstatus(subreq, status);
3365 }
3366
3367 static struct tevent_req *cli_posix_lock_internal_send(TALLOC_CTX *mem_ctx,
3368                                         struct tevent_context *ev,
3369                                         struct cli_state *cli,
3370                                         uint16_t fnum,
3371                                         uint64_t offset,
3372                                         uint64_t len,
3373                                         bool wait_lock,
3374                                         enum brl_type lock_type)
3375 {
3376         struct tevent_req *req = NULL, *subreq = NULL;
3377         struct posix_lock_state *state = NULL;
3378
3379         req = tevent_req_create(mem_ctx, &state, struct posix_lock_state);
3380         if (req == NULL) {
3381                 return NULL;
3382         }
3383
3384         /* Setup setup word. */
3385         SSVAL(&state->setup, 0, TRANSACT2_SETFILEINFO);
3386
3387         /* Setup param array. */
3388         SSVAL(&state->param, 0, fnum);
3389         SSVAL(&state->param, 2, SMB_SET_POSIX_LOCK);
3390
3391         /* Setup data array. */
3392         switch (lock_type) {
3393                 case READ_LOCK:
3394                         SSVAL(&state->data, POSIX_LOCK_TYPE_OFFSET,
3395                                 POSIX_LOCK_TYPE_READ);
3396                         break;
3397                 case WRITE_LOCK:
3398                         SSVAL(&state->data, POSIX_LOCK_TYPE_OFFSET,
3399                                 POSIX_LOCK_TYPE_WRITE);
3400                         break;
3401                 case UNLOCK_LOCK:
3402                         SSVAL(&state->data, POSIX_LOCK_TYPE_OFFSET,
3403                                 POSIX_LOCK_TYPE_UNLOCK);
3404                         break;
3405                 default:
3406                         return NULL;
3407         }
3408
3409         if (wait_lock) {
3410                 SSVAL(&state->data, POSIX_LOCK_FLAGS_OFFSET,
3411                                 POSIX_LOCK_FLAG_WAIT);
3412         } else {
3413                 SSVAL(state->data, POSIX_LOCK_FLAGS_OFFSET,
3414                                 POSIX_LOCK_FLAG_NOWAIT);
3415         }
3416
3417         SIVAL(&state->data, POSIX_LOCK_PID_OFFSET, cli_getpid(cli));
3418         SOFF_T(&state->data, POSIX_LOCK_START_OFFSET, offset);
3419         SOFF_T(&state->data, POSIX_LOCK_LEN_OFFSET, len);
3420
3421         subreq = cli_trans_send(state,                  /* mem ctx. */
3422                                 ev,                     /* event ctx. */
3423                                 cli,                    /* cli_state. */
3424                                 0,                      /* additional_flags2 */
3425                                 SMBtrans2,              /* cmd. */
3426                                 NULL,                   /* pipe name. */
3427                                 -1,                     /* fid. */
3428                                 0,                      /* function. */
3429                                 0,                      /* flags. */
3430                                 &state->setup,          /* setup. */
3431                                 1,                      /* num setup uint16_t words. */
3432                                 0,                      /* max returned setup. */
3433                                 state->param,           /* param. */
3434                                 4,                      /* num param. */
3435                                 2,                      /* max returned param. */
3436                                 state->data,            /* data. */
3437                                 POSIX_LOCK_DATA_SIZE,   /* num data. */
3438                                 0);                     /* max returned data. */
3439
3440         if (tevent_req_nomem(subreq, req)) {
3441                 return tevent_req_post(req, ev);
3442         }
3443         tevent_req_set_callback(subreq, cli_posix_unlock_internal_done, req);
3444         return req;
3445 }
3446
3447 /****************************************************************************
3448  POSIX Lock a file.
3449 ****************************************************************************/
3450
3451 struct tevent_req *cli_posix_lock_send(TALLOC_CTX *mem_ctx,
3452                                         struct tevent_context *ev,
3453                                         struct cli_state *cli,
3454                                         uint16_t fnum,
3455                                         uint64_t offset,
3456                                         uint64_t len,
3457                                         bool wait_lock,
3458                                         enum brl_type lock_type)
3459 {
3460         return cli_posix_lock_internal_send(mem_ctx, ev, cli, fnum, offset, len,
3461                                         wait_lock, lock_type);
3462 }
3463
3464 NTSTATUS cli_posix_lock_recv(struct tevent_req *req)
3465 {
3466         return tevent_req_simple_recv_ntstatus(req);
3467 }
3468
3469 NTSTATUS cli_posix_lock(struct cli_state *cli, uint16_t fnum,
3470                         uint64_t offset, uint64_t len,
3471                         bool wait_lock, enum brl_type lock_type)
3472 {
3473         TALLOC_CTX *frame = talloc_stackframe();
3474         struct tevent_context *ev = NULL;
3475         struct tevent_req *req = NULL;
3476         NTSTATUS status = NT_STATUS_OK;
3477
3478         if (smbXcli_conn_has_async_calls(cli->conn)) {
3479                 /*
3480                  * Can't use sync call while an async call is in flight
3481                  */
3482                 status = NT_STATUS_INVALID_PARAMETER;
3483                 goto fail;
3484         }
3485
3486         if (lock_type != READ_LOCK && lock_type != WRITE_LOCK) {
3487                 status = NT_STATUS_INVALID_PARAMETER;
3488                 goto fail;
3489         }
3490
3491         ev = samba_tevent_context_init(frame);
3492         if (ev == NULL) {
3493                 status = NT_STATUS_NO_MEMORY;
3494                 goto fail;
3495         }
3496
3497         req = cli_posix_lock_send(frame,
3498                                 ev,
3499                                 cli,
3500                                 fnum,
3501                                 offset,
3502                                 len,
3503                                 wait_lock,
3504                                 lock_type);
3505         if (req == NULL) {
3506                 status = NT_STATUS_NO_MEMORY;
3507                 goto fail;
3508         }
3509
3510         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3511                 goto fail;
3512         }
3513
3514         status = cli_posix_lock_recv(req);
3515
3516  fail:
3517         TALLOC_FREE(frame);
3518         return status;
3519 }
3520
3521 /****************************************************************************
3522  POSIX Unlock a file.
3523 ****************************************************************************/
3524
3525 struct tevent_req *cli_posix_unlock_send(TALLOC_CTX *mem_ctx,
3526                                         struct tevent_context *ev,
3527                                         struct cli_state *cli,
3528                                         uint16_t fnum,
3529                                         uint64_t offset,
3530                                         uint64_t len)
3531 {
3532         return cli_posix_lock_internal_send(mem_ctx, ev, cli, fnum, offset, len,
3533                                         false, UNLOCK_LOCK);
3534 }
3535
3536 NTSTATUS cli_posix_unlock_recv(struct tevent_req *req)
3537 {
3538         return tevent_req_simple_recv_ntstatus(req);
3539 }
3540
3541 NTSTATUS cli_posix_unlock(struct cli_state *cli, uint16_t fnum, uint64_t offset, uint64_t len)
3542 {
3543         TALLOC_CTX *frame = talloc_stackframe();
3544         struct tevent_context *ev = NULL;
3545         struct tevent_req *req = NULL;
3546         NTSTATUS status = NT_STATUS_OK;
3547
3548         if (smbXcli_conn_has_async_calls(cli->conn)) {
3549                 /*
3550                  * Can't use sync call while an async call is in flight
3551                  */
3552                 status = NT_STATUS_INVALID_PARAMETER;
3553                 goto fail;
3554         }
3555
3556         ev = samba_tevent_context_init(frame);
3557         if (ev == NULL) {
3558                 status = NT_STATUS_NO_MEMORY;
3559                 goto fail;
3560         }
3561
3562         req = cli_posix_unlock_send(frame,
3563                                 ev,
3564                                 cli,
3565                                 fnum,
3566                                 offset,
3567                                 len);
3568         if (req == NULL) {
3569                 status = NT_STATUS_NO_MEMORY;
3570                 goto fail;
3571         }
3572
3573         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3574                 goto fail;
3575         }
3576
3577         status = cli_posix_unlock_recv(req);
3578
3579  fail:
3580         TALLOC_FREE(frame);
3581         return status;
3582 }
3583
3584 /****************************************************************************
3585  Do a SMBgetattrE call.
3586 ****************************************************************************/
3587
3588 static void cli_getattrE_done(struct tevent_req *subreq);
3589
3590 struct cli_getattrE_state {
3591         uint16_t vwv[1];
3592         int zone_offset;
3593         uint16_t attr;
3594         off_t size;
3595         time_t change_time;
3596         time_t access_time;
3597         time_t write_time;
3598 };
3599
3600 struct tevent_req *cli_getattrE_send(TALLOC_CTX *mem_ctx,
3601                                 struct tevent_context *ev,
3602                                 struct cli_state *cli,
3603                                 uint16_t fnum)
3604 {
3605         struct tevent_req *req = NULL, *subreq = NULL;
3606         struct cli_getattrE_state *state = NULL;
3607         uint8_t additional_flags = 0;
3608
3609         req = tevent_req_create(mem_ctx, &state, struct cli_getattrE_state);
3610         if (req == NULL) {
3611                 return NULL;
3612         }
3613
3614         state->zone_offset = smb1cli_conn_server_time_zone(cli->conn);
3615         SSVAL(state->vwv+0,0,fnum);
3616
3617         subreq = cli_smb_send(state, ev, cli, SMBgetattrE, additional_flags, 0,
3618                               1, state->vwv, 0, NULL);
3619         if (tevent_req_nomem(subreq, req)) {
3620                 return tevent_req_post(req, ev);
3621         }
3622         tevent_req_set_callback(subreq, cli_getattrE_done, req);
3623         return req;
3624 }
3625
3626 static void cli_getattrE_done(struct tevent_req *subreq)
3627 {
3628         struct tevent_req *req = tevent_req_callback_data(
3629                 subreq, struct tevent_req);
3630         struct cli_getattrE_state *state = tevent_req_data(
3631                 req, struct cli_getattrE_state);
3632         uint8_t wct;
3633         uint16_t *vwv = NULL;
3634         NTSTATUS status;
3635
3636         status = cli_smb_recv(subreq, state, NULL, 11, &wct, &vwv,
3637                               NULL, NULL);
3638         TALLOC_FREE(subreq);
3639         if (tevent_req_nterror(req, status)) {
3640                 return;
3641         }
3642
3643         state->size = (off_t)IVAL(vwv+6,0);
3644         state->attr = SVAL(vwv+10,0);
3645         state->change_time = make_unix_date2(vwv+0, state->zone_offset);
3646         state->access_time = make_unix_date2(vwv+2, state->zone_offset);
3647         state->write_time = make_unix_date2(vwv+4, state->zone_offset);
3648
3649         tevent_req_done(req);
3650 }
3651
3652 NTSTATUS cli_getattrE_recv(struct tevent_req *req,
3653                         uint16_t *attr,
3654                         off_t *size,
3655                         time_t *change_time,
3656                         time_t *access_time,
3657                         time_t *write_time)
3658 {
3659         struct cli_getattrE_state *state = tevent_req_data(
3660                                 req, struct cli_getattrE_state);
3661         NTSTATUS status;
3662
3663         if (tevent_req_is_nterror(req, &status)) {
3664                 return status;
3665         }
3666         if (attr) {
3667                 *attr = state->attr;
3668         }
3669         if (size) {
3670                 *size = state->size;
3671         }
3672         if (change_time) {
3673                 *change_time = state->change_time;
3674         }
3675         if (access_time) {
3676                 *access_time = state->access_time;
3677         }
3678         if (write_time) {
3679                 *write_time = state->write_time;
3680         }
3681         return NT_STATUS_OK;
3682 }
3683
3684 NTSTATUS cli_getattrE(struct cli_state *cli,
3685                         uint16_t fnum,
3686                         uint16_t *attr,
3687                         off_t *size,
3688                         time_t *change_time,
3689                         time_t *access_time,
3690                         time_t *write_time)
3691 {
3692         TALLOC_CTX *frame = NULL;
3693         struct tevent_context *ev = NULL;
3694         struct tevent_req *req = NULL;
3695         NTSTATUS status = NT_STATUS_OK;
3696
3697         if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
3698                 return cli_smb2_getattrE(cli,
3699                                         fnum,
3700                                         attr,
3701                                         size,
3702                                         change_time,
3703                                         access_time,
3704                                         write_time);
3705         }
3706
3707         frame = talloc_stackframe();
3708
3709         if (smbXcli_conn_has_async_calls(cli->conn)) {
3710                 /*
3711                  * Can't use sync call while an async call is in flight
3712                  */
3713                 status = NT_STATUS_INVALID_PARAMETER;
3714                 goto fail;
3715         }
3716
3717         ev = samba_tevent_context_init(frame);
3718         if (ev == NULL) {
3719                 status = NT_STATUS_NO_MEMORY;
3720                 goto fail;
3721         }
3722
3723         req = cli_getattrE_send(frame, ev, cli, fnum);
3724         if (req == NULL) {
3725                 status = NT_STATUS_NO_MEMORY;
3726                 goto fail;
3727         }
3728
3729         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3730                 goto fail;
3731         }
3732
3733         status = cli_getattrE_recv(req,
3734                                         attr,
3735                                         size,
3736                                         change_time,
3737                                         access_time,
3738                                         write_time);
3739
3740  fail:
3741         TALLOC_FREE(frame);
3742         return status;
3743 }
3744
3745 /****************************************************************************
3746  Do a SMBgetatr call
3747 ****************************************************************************/
3748
3749 static void cli_getatr_done(struct tevent_req *subreq);
3750
3751 struct cli_getatr_state {
3752         int zone_offset;
3753         uint16_t attr;
3754         off_t size;
3755         time_t write_time;
3756 };
3757
3758 struct tevent_req *cli_getatr_send(TALLOC_CTX *mem_ctx,
3759                                 struct tevent_context *ev,
3760                                 struct cli_state *cli,
3761                                 const char *fname)
3762 {
3763         struct tevent_req *req = NULL, *subreq = NULL;
3764         struct cli_getatr_state *state = NULL;
3765         uint8_t additional_flags = 0;
3766         uint16_t additional_flags2 = 0;
3767         uint8_t *bytes = NULL;
3768
3769         req = tevent_req_create(mem_ctx, &state, struct cli_getatr_state);
3770         if (req == NULL) {
3771                 return NULL;
3772         }
3773
3774         state->zone_offset = smb1cli_conn_server_time_zone(cli->conn);
3775
3776         bytes = talloc_array(state, uint8_t, 1);
3777         if (tevent_req_nomem(bytes, req)) {
3778                 return tevent_req_post(req, ev);
3779         }
3780         bytes[0] = 4;
3781         bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), fname,
3782                                    strlen(fname)+1, NULL);
3783
3784         if (tevent_req_nomem(bytes, req)) {
3785                 return tevent_req_post(req, ev);
3786         }
3787
3788         if (clistr_is_previous_version_path(fname, NULL, NULL, NULL)) {
3789                 additional_flags2 = FLAGS2_REPARSE_PATH;
3790         }
3791
3792         subreq = cli_smb_send(state, ev, cli, SMBgetatr, additional_flags,
3793                         additional_flags2,
3794                         0, NULL, talloc_get_size(bytes), bytes);
3795         if (tevent_req_nomem(subreq, req)) {
3796                 return tevent_req_post(req, ev);
3797         }
3798         tevent_req_set_callback(subreq, cli_getatr_done, req);
3799         return req;
3800 }
3801
3802 static void cli_getatr_done(struct tevent_req *subreq)
3803 {
3804         struct tevent_req *req = tevent_req_callback_data(
3805                 subreq, struct tevent_req);
3806         struct cli_getatr_state *state = tevent_req_data(
3807                 req, struct cli_getatr_state);
3808         uint8_t wct;
3809         uint16_t *vwv = NULL;
3810         NTSTATUS status;
3811
3812         status = cli_smb_recv(subreq, state, NULL, 4, &wct, &vwv, NULL,
3813                               NULL);
3814         TALLOC_FREE(subreq);
3815         if (tevent_req_nterror(req, status)) {
3816                 return;
3817         }
3818
3819         state->attr = SVAL(vwv+0,0);
3820         state->size = (off_t)IVAL(vwv+3,0);
3821         state->write_time = make_unix_date3(vwv+1, state->zone_offset);
3822
3823         tevent_req_done(req);
3824 }
3825
3826 NTSTATUS cli_getatr_recv(struct tevent_req *req,
3827                         uint16_t *attr,
3828                         off_t *size,
3829                         time_t *write_time)
3830 {
3831         struct cli_getatr_state *state = tevent_req_data(
3832                                 req, struct cli_getatr_state);
3833         NTSTATUS status;
3834
3835         if (tevent_req_is_nterror(req, &status)) {
3836                 return status;
3837         }
3838         if (attr) {
3839                 *attr = state->attr;
3840         }
3841         if (size) {
3842                 *size = state->size;
3843         }
3844         if (write_time) {
3845                 *write_time = state->write_time;
3846         }
3847         return NT_STATUS_OK;
3848 }
3849
3850 NTSTATUS cli_getatr(struct cli_state *cli,
3851                         const char *fname,
3852                         uint16_t *attr,
3853                         off_t *size,
3854                         time_t *write_time)
3855 {
3856         TALLOC_CTX *frame = NULL;
3857         struct tevent_context *ev = NULL;
3858         struct tevent_req *req = NULL;
3859         NTSTATUS status = NT_STATUS_OK;
3860
3861         if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
3862                 return cli_smb2_getatr(cli,
3863                                         fname,
3864                                         attr,
3865                                         size,
3866                                         write_time);
3867         }
3868
3869         frame = talloc_stackframe();
3870
3871         if (smbXcli_conn_has_async_calls(cli->conn)) {
3872                 /*
3873                  * Can't use sync call while an async call is in flight
3874                  */
3875                 status = NT_STATUS_INVALID_PARAMETER;
3876                 goto fail;
3877         }
3878
3879         ev = samba_tevent_context_init(frame);
3880         if (ev == NULL) {
3881                 status = NT_STATUS_NO_MEMORY;
3882                 goto fail;
3883         }
3884
3885         req = cli_getatr_send(frame, ev, cli, fname);
3886         if (req == NULL) {
3887                 status = NT_STATUS_NO_MEMORY;
3888                 goto fail;
3889         }
3890
3891         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3892                 goto fail;
3893         }
3894
3895         status = cli_getatr_recv(req,
3896                                 attr,
3897                                 size,
3898                                 write_time);
3899
3900  fail:
3901         TALLOC_FREE(frame);
3902         return status;
3903 }
3904
3905 /****************************************************************************
3906  Do a SMBsetattrE call.
3907 ****************************************************************************/
3908
3909 static void cli_setattrE_done(struct tevent_req *subreq);
3910
3911 struct cli_setattrE_state {
3912         uint16_t vwv[7];
3913 };
3914
3915 struct tevent_req *cli_setattrE_send(TALLOC_CTX *mem_ctx,
3916                                 struct tevent_context *ev,
3917                                 struct cli_state *cli,
3918                                 uint16_t fnum,
3919                                 time_t change_time,
3920                                 time_t access_time,
3921                                 time_t write_time)
3922 {
3923         struct tevent_req *req = NULL, *subreq = NULL;
3924         struct cli_setattrE_state *state = NULL;
3925         uint8_t additional_flags = 0;
3926
3927         req = tevent_req_create(mem_ctx, &state, struct cli_setattrE_state);
3928         if (req == NULL) {
3929                 return NULL;
3930         }
3931
3932         SSVAL(state->vwv+0, 0, fnum);
3933         push_dos_date2((uint8_t *)&state->vwv[1], 0, change_time,
3934                        smb1cli_conn_server_time_zone(cli->conn));
3935         push_dos_date2((uint8_t *)&state->vwv[3], 0, access_time,
3936                        smb1cli_conn_server_time_zone(cli->conn));
3937         push_dos_date2((uint8_t *)&state->vwv[5], 0, write_time,
3938                        smb1cli_conn_server_time_zone(cli->conn));
3939
3940         subreq = cli_smb_send(state, ev, cli, SMBsetattrE, additional_flags, 0,
3941                               7, state->vwv, 0, NULL);
3942         if (tevent_req_nomem(subreq, req)) {
3943                 return tevent_req_post(req, ev);
3944         }
3945         tevent_req_set_callback(subreq, cli_setattrE_done, req);
3946         return req;
3947 }
3948
3949 static void cli_setattrE_done(struct tevent_req *subreq)
3950 {
3951         struct tevent_req *req = tevent_req_callback_data(
3952                 subreq, struct tevent_req);
3953         NTSTATUS status;
3954
3955         status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
3956         TALLOC_FREE(subreq);
3957         if (tevent_req_nterror(req, status)) {
3958                 return;
3959         }
3960         tevent_req_done(req);
3961 }
3962
3963 NTSTATUS cli_setattrE_recv(struct tevent_req *req)
3964 {
3965         return tevent_req_simple_recv_ntstatus(req);
3966 }
3967
3968 NTSTATUS cli_setattrE(struct cli_state *cli,
3969                         uint16_t fnum,
3970                         time_t change_time,
3971                         time_t access_time,
3972                         time_t write_time)
3973 {
3974         TALLOC_CTX *frame = NULL;
3975         struct tevent_context *ev = NULL;
3976         struct tevent_req *req = NULL;
3977         NTSTATUS status = NT_STATUS_OK;
3978
3979         if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
3980                 return cli_smb2_setattrE(cli,
3981                                         fnum,
3982                                         change_time,
3983                                         access_time,
3984                                         write_time);
3985         }
3986
3987         frame = talloc_stackframe();
3988
3989         if (smbXcli_conn_has_async_calls(cli->conn)) {
3990                 /*
3991                  * Can't use sync call while an async call is in flight
3992                  */
3993                 status = NT_STATUS_INVALID_PARAMETER;
3994                 goto fail;
3995         }
3996
3997         ev = samba_tevent_context_init(frame);
3998         if (ev == NULL) {
3999                 status = NT_STATUS_NO_MEMORY;
4000                 goto fail;
4001         }
4002
4003         req = cli_setattrE_send(frame, ev,
4004                         cli,
4005                         fnum,
4006                         change_time,
4007                         access_time,
4008                         write_time);
4009
4010         if (req == NULL) {
4011                 status = NT_STATUS_NO_MEMORY;
4012                 goto fail;
4013         }
4014
4015         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
4016                 goto fail;
4017         }
4018
4019         status = cli_setattrE_recv(req);
4020
4021  fail:
4022         TALLOC_FREE(frame);
4023         return status;
4024 }
4025
4026 /****************************************************************************
4027  Do a SMBsetatr call.
4028 ****************************************************************************/
4029
4030 static void cli_setatr_done(struct tevent_req *subreq);
4031
4032 struct cli_setatr_state {
4033         uint16_t vwv[8];
4034 };
4035
4036 struct tevent_req *cli_setatr_send(TALLOC_CTX *mem_ctx,
4037                                 struct tevent_context *ev,
4038                                 struct cli_state *cli,
4039                                 const char *fname,
4040                                 uint16_t attr,
4041                                 time_t mtime)
4042 {
4043         struct tevent_req *req = NULL, *subreq = NULL;
4044         struct cli_setatr_state *state = NULL;
4045         uint8_t additional_flags = 0;
4046         uint16_t additional_flags2 = 0;
4047         uint8_t *bytes = NULL;
4048
4049         req = tevent_req_create(mem_ctx, &state, struct cli_setatr_state);
4050         if (req == NULL) {
4051                 return NULL;
4052         }
4053
4054         SSVAL(state->vwv+0, 0, attr);
4055         push_dos_date3((uint8_t *)&state->vwv[1], 0, mtime, smb1cli_conn_server_time_zone(cli->conn));
4056
4057         bytes = talloc_array(state, uint8_t, 1);
4058         if (tevent_req_nomem(bytes, req)) {
4059                 return tevent_req_post(req, ev);
4060         }
4061         bytes[0] = 4;
4062         bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), fname,
4063                                    strlen(fname)+1, NULL);
4064         if (tevent_req_nomem(bytes, req)) {
4065                 return tevent_req_post(req, ev);
4066         }
4067         bytes = talloc_realloc(state, bytes, uint8_t,
4068                         talloc_get_size(bytes)+1);
4069         if (tevent_req_nomem(bytes, req)) {
4070                 return tevent_req_post(req, ev);
4071         }
4072
4073         bytes[talloc_get_size(bytes)-1] = 4;
4074         bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "",
4075                                    1, NULL);
4076         if (tevent_req_nomem(bytes, req)) {
4077                 return tevent_req_post(req, ev);
4078         }
4079
4080         if (clistr_is_previous_version_path(fname, NULL, NULL, NULL)) {
4081                 additional_flags2 = FLAGS2_REPARSE_PATH;
4082         }
4083
4084         subreq = cli_smb_send(state, ev, cli, SMBsetatr, additional_flags,
4085                         additional_flags2,
4086                         8, state->vwv, talloc_get_size(bytes), bytes);
4087         if (tevent_req_nomem(subreq, req)) {
4088                 return tevent_req_post(req, ev);
4089         }
4090         tevent_req_set_callback(subreq, cli_setatr_done, req);
4091         return req;
4092 }
4093
4094 static void cli_setatr_done(struct tevent_req *subreq)
4095 {
4096         struct tevent_req *req = tevent_req_callback_data(
4097                 subreq, struct tevent_req);
4098         NTSTATUS status;
4099
4100         status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
4101         TALLOC_FREE(subreq);
4102         if (tevent_req_nterror(req, status)) {
4103                 return;
4104         }
4105         tevent_req_done(req);
4106 }
4107
4108 NTSTATUS cli_setatr_recv(struct tevent_req *req)
4109 {
4110         return tevent_req_simple_recv_ntstatus(req);
4111 }
4112
4113 NTSTATUS cli_setatr(struct cli_state *cli,
4114                 const char *fname,
4115                 uint16_t attr,
4116                 time_t mtime)
4117 {
4118         TALLOC_CTX *frame = NULL;
4119         struct tevent_context *ev = NULL;
4120         struct tevent_req *req = NULL;
4121         NTSTATUS status = NT_STATUS_OK;
4122
4123         if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
4124                 return cli_smb2_setatr(cli,
4125                                         fname,
4126                                         attr,
4127                                         mtime);
4128         }
4129
4130         frame = talloc_stackframe();
4131
4132         if (smbXcli_conn_has_async_calls(cli->conn)) {
4133                 /*
4134                  * Can't use sync call while an async call is in flight
4135                  */
4136                 status = NT_STATUS_INVALID_PARAMETER;
4137                 goto fail;
4138         }
4139
4140         ev = samba_tevent_context_init(frame);
4141         if (ev == NULL) {
4142                 status = NT_STATUS_NO_MEMORY;
4143                 goto fail;
4144         }
4145
4146         req = cli_setatr_send(frame, ev, cli, fname, attr, mtime);
4147         if (req == NULL) {
4148                 status = NT_STATUS_NO_MEMORY;
4149                 goto fail;
4150         }
4151
4152         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
4153                 goto fail;
4154         }
4155
4156         status = cli_setatr_recv(req);
4157
4158  fail:
4159         TALLOC_FREE(frame);
4160         return status;
4161 }
4162
4163 /****************************************************************************
4164  Check for existence of a dir.
4165 ****************************************************************************/
4166
4167 static void cli_chkpath_done(struct tevent_req *subreq);
4168
4169 struct cli_chkpath_state {
4170         int dummy;
4171 };
4172
4173 struct tevent_req *cli_chkpath_send(TALLOC_CTX *mem_ctx,
4174                                   struct tevent_context *ev,
4175                                   struct cli_state *cli,
4176                                   const char *fname)
4177 {
4178         struct tevent_req *req = NULL, *subreq = NULL;
4179         struct cli_chkpath_state *state = NULL;
4180         uint8_t additional_flags = 0;
4181         uint16_t additional_flags2 = 0;
4182         uint8_t *bytes = NULL;
4183
4184         req = tevent_req_create(mem_ctx, &state, struct cli_chkpath_state);
4185         if (req == NULL) {
4186                 return NULL;
4187         }
4188
4189         bytes = talloc_array(state, uint8_t, 1);
4190         if (tevent_req_nomem(bytes, req)) {
4191                 return tevent_req_post(req, ev);
4192         }
4193         bytes[0] = 4;
4194         bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), fname,
4195                                    strlen(fname)+1, NULL);
4196
4197         if (tevent_req_nomem(bytes, req)) {
4198                 return tevent_req_post(req, ev);
4199         }
4200
4201         if (clistr_is_previous_version_path(fname, NULL, NULL, NULL)) {
4202                 additional_flags2 = FLAGS2_REPARSE_PATH;
4203         }
4204
4205         subreq = cli_smb_send(state, ev, cli, SMBcheckpath, additional_flags,
4206                         additional_flags2,
4207                         0, NULL, talloc_get_size(bytes), bytes);
4208         if (tevent_req_nomem(subreq, req)) {
4209                 return tevent_req_post(req, ev);
4210         }
4211         tevent_req_set_callback(subreq, cli_chkpath_done, req);
4212         return req;
4213 }
4214
4215 static void cli_chkpath_done(struct tevent_req *subreq)
4216 {
4217         struct tevent_req *req = tevent_req_callback_data(
4218                 subreq, struct tevent_req);
4219         NTSTATUS status;
4220
4221         status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
4222         TALLOC_FREE(subreq);
4223         if (tevent_req_nterror(req, status)) {
4224                 return;
4225         }
4226         tevent_req_done(req);
4227 }
4228
4229 NTSTATUS cli_chkpath_recv(struct tevent_req *req)
4230 {
4231         return tevent_req_simple_recv_ntstatus(req);
4232 }
4233
4234 NTSTATUS cli_chkpath(struct cli_state *cli, const char *path)
4235 {
4236         TALLOC_CTX *frame = NULL;
4237         struct tevent_context *ev = NULL;
4238         struct tevent_req *req = NULL;
4239         char *path2 = NULL;
4240         NTSTATUS status = NT_STATUS_OK;
4241
4242         if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
4243                 return cli_smb2_chkpath(cli, path);
4244         }
4245
4246         frame = talloc_stackframe();
4247
4248         if (smbXcli_conn_has_async_calls(cli->conn)) {
4249                 /*
4250                  * Can't use sync call while an async call is in flight
4251                  */
4252                 status = NT_STATUS_INVALID_PARAMETER;
4253                 goto fail;
4254         }
4255
4256         path2 = talloc_strdup(frame, path);
4257         if (!path2) {
4258                 status = NT_STATUS_NO_MEMORY;
4259                 goto fail;
4260         }
4261         trim_char(path2,'\0','\\');
4262         if (!*path2) {
4263                 path2 = talloc_strdup(frame, "\\");
4264                 if (!path2) {
4265                         status = NT_STATUS_NO_MEMORY;
4266                         goto fail;
4267                 }
4268         }
4269
4270         ev = samba_tevent_context_init(frame);
4271         if (ev == NULL) {
4272                 status = NT_STATUS_NO_MEMORY;
4273                 goto fail;
4274         }
4275
4276         req = cli_chkpath_send(frame, ev, cli, path2);
4277         if (req == NULL) {
4278                 status = NT_STATUS_NO_MEMORY;
4279                 goto fail;
4280         }
4281
4282         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
4283                 goto fail;
4284         }
4285
4286         status = cli_chkpath_recv(req);
4287
4288  fail:
4289         TALLOC_FREE(frame);
4290         return status;
4291 }
4292
4293 /****************************************************************************
4294  Query disk space.
4295 ****************************************************************************/
4296
4297 static void cli_dskattr_done(struct tevent_req *subreq);
4298
4299 struct cli_dskattr_state {
4300         int bsize;
4301         int total;
4302         int avail;
4303 };
4304
4305 struct tevent_req *cli_dskattr_send(TALLOC_CTX *mem_ctx,
4306                                   struct tevent_context *ev,
4307                                   struct cli_state *cli)
4308 {
4309         struct tevent_req *req = NULL, *subreq = NULL;
4310         struct cli_dskattr_state *state = NULL;
4311         uint8_t additional_flags = 0;
4312
4313         req = tevent_req_create(mem_ctx, &state, struct cli_dskattr_state);
4314         if (req == NULL) {
4315                 return NULL;
4316         }
4317
4318         subreq = cli_smb_send(state, ev, cli, SMBdskattr, additional_flags, 0,
4319                               0, NULL, 0, NULL);
4320         if (tevent_req_nomem(subreq, req)) {
4321                 return tevent_req_post(req, ev);
4322         }
4323         tevent_req_set_callback(subreq, cli_dskattr_done, req);
4324         return req;
4325 }
4326
4327 static void cli_dskattr_done(struct tevent_req *subreq)
4328 {
4329         struct tevent_req *req = tevent_req_callback_data(
4330                 subreq, struct tevent_req);
4331         struct cli_dskattr_state *state = tevent_req_data(
4332                 req, struct cli_dskattr_state);
4333         uint8_t wct;
4334         uint16_t *vwv = NULL;
4335         NTSTATUS status;
4336
4337         status = cli_smb_recv(subreq, state, NULL, 4, &wct, &vwv, NULL,
4338                               NULL);
4339         TALLOC_FREE(subreq);
4340         if (tevent_req_nterror(req, status)) {
4341                 return;
4342         }
4343         state->bsize = SVAL(vwv+1, 0)*SVAL(vwv+2,0);
4344         state->total = SVAL(vwv+0, 0);
4345         state->avail = SVAL(vwv+3, 0);
4346         tevent_req_done(req);
4347 }
4348
4349 NTSTATUS cli_dskattr_recv(struct tevent_req *req, int *bsize, int *total, int *avail)
4350 {
4351         struct cli_dskattr_state *state = tevent_req_data(
4352                                 req, struct cli_dskattr_state);
4353         NTSTATUS status;
4354
4355         if (tevent_req_is_nterror(req, &status)) {
4356                 return status;
4357         }
4358         *bsize = state->bsize;
4359         *total = state->total;
4360         *avail = state->avail;
4361         return NT_STATUS_OK;
4362 }
4363
4364 NTSTATUS cli_dskattr(struct cli_state *cli, int *bsize, int *total, int *avail)
4365 {
4366         TALLOC_CTX *frame = NULL;
4367         struct tevent_context *ev = NULL;
4368         struct tevent_req *req = NULL;
4369         NTSTATUS status = NT_STATUS_OK;
4370
4371         frame = talloc_stackframe();
4372
4373         if (smbXcli_conn_has_async_calls(cli->conn)) {
4374                 /*
4375                  * Can't use sync call while an async call is in flight
4376                  */
4377                 status = NT_STATUS_INVALID_PARAMETER;
4378                 goto fail;
4379         }
4380
4381         ev = samba_tevent_context_init(frame);
4382         if (ev == NULL) {
4383                 status = NT_STATUS_NO_MEMORY;
4384                 goto fail;
4385         }
4386
4387         req = cli_dskattr_send(frame, ev, cli);
4388         if (req == NULL) {
4389                 status = NT_STATUS_NO_MEMORY;
4390                 goto fail;
4391         }
4392
4393         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
4394                 goto fail;
4395         }
4396
4397         status = cli_dskattr_recv(req, bsize, total, avail);
4398
4399  fail:
4400         TALLOC_FREE(frame);
4401         return status;
4402 }
4403
4404 NTSTATUS cli_disk_size(struct cli_state *cli, const char *path, uint64_t *bsize,
4405                        uint64_t *total, uint64_t *avail)
4406 {
4407         uint64_t sectors_per_block;
4408         uint64_t bytes_per_sector;
4409         int old_bsize, old_total, old_avail;
4410         NTSTATUS status;
4411
4412         if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
4413                 return cli_smb2_dskattr(cli, path, bsize, total, avail);
4414         }
4415
4416         /*
4417          * Try the trans2 disk full size info call first.
4418          * We already use this in SMBC_fstatvfs_ctx().
4419          * Ignore 'actual_available_units' as we only
4420          * care about the quota for the caller.
4421          */
4422
4423         status = cli_get_fs_full_size_info(cli,
4424                         total,
4425                         avail,
4426                         NULL,
4427                         &sectors_per_block,
4428                         &bytes_per_sector);
4429
4430         /* Try and cope will all varients of "we don't do this call"
4431            and fall back to cli_dskattr. */
4432
4433         if (NT_STATUS_EQUAL(status,NT_STATUS_NOT_IMPLEMENTED) ||
4434                         NT_STATUS_EQUAL(status,NT_STATUS_NOT_SUPPORTED) ||
4435                         NT_STATUS_EQUAL(status,NT_STATUS_INVALID_INFO_CLASS) ||
4436                         NT_STATUS_EQUAL(status,NT_STATUS_PROCEDURE_NOT_FOUND) ||
4437                         NT_STATUS_EQUAL(status,NT_STATUS_INVALID_LEVEL) ||
4438                         NT_STATUS_EQUAL(status,NT_STATUS_INVALID_PARAMETER) ||
4439                         NT_STATUS_EQUAL(status,NT_STATUS_INVALID_DEVICE_REQUEST) ||
4440                         NT_STATUS_EQUAL(status,NT_STATUS_INVALID_DEVICE_STATE) ||
4441                         NT_STATUS_EQUAL(status,NT_STATUS_CTL_FILE_NOT_SUPPORTED) ||
4442                         NT_STATUS_EQUAL(status,NT_STATUS_UNSUCCESSFUL)) {
4443                 goto try_dskattr;
4444         }
4445
4446         if (!NT_STATUS_IS_OK(status)) {
4447                 return status;
4448         }
4449
4450         if (bsize) {
4451                 *bsize = sectors_per_block *
4452                          bytes_per_sector;
4453         }
4454
4455         return NT_STATUS_OK;
4456
4457   try_dskattr:
4458
4459         /* Old SMB1 core protocol fallback. */
4460         status = cli_dskattr(cli, &old_bsize, &old_total, &old_avail);
4461         if (!NT_STATUS_IS_OK(status)) {
4462                 return status;
4463         }
4464         if (bsize) {
4465                 *bsize = (uint64_t)old_bsize;
4466         }
4467         if (total) {
4468                 *total = (uint64_t)old_total;
4469         }
4470         if (avail) {
4471                 *avail = (uint64_t)old_avail;
4472         }
4473         return NT_STATUS_OK;
4474 }
4475
4476 /****************************************************************************
4477  Create and open a temporary file.
4478 ****************************************************************************/
4479
4480 static void cli_ctemp_done(struct tevent_req *subreq);
4481
4482 struct ctemp_state {
4483         uint16_t vwv[3];
4484         char *ret_path;
4485         uint16_t fnum;
4486 };
4487
4488 struct tevent_req *cli_ctemp_send(TALLOC_CTX *mem_ctx,
4489                                 struct tevent_context *ev,
4490                                 struct cli_state *cli,
4491                                 const char *path)
4492 {
4493         struct tevent_req *req = NULL, *subreq = NULL;
4494         struct ctemp_state *state = NULL;
4495         uint8_t additional_flags = 0;
4496         uint16_t additional_flags2 = 0;
4497         uint8_t *bytes = NULL;
4498
4499         req = tevent_req_create(mem_ctx, &state, struct ctemp_state);
4500         if (req == NULL) {
4501                 return NULL;
4502         }
4503
4504         SSVAL(state->vwv,0,0);
4505         SIVALS(state->vwv+1,0,-1);
4506
4507         bytes = talloc_array(state, uint8_t, 1);
4508         if (tevent_req_nomem(bytes, req)) {
4509                 return tevent_req_post(req, ev);
4510         }
4511         bytes[0] = 4;
4512         bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), path,
4513                                    strlen(path)+1, NULL);
4514         if (tevent_req_nomem(bytes, req)) {
4515                 return tevent_req_post(req, ev);
4516         }
4517
4518         if (clistr_is_previous_version_path(path, NULL, NULL, NULL)) {
4519                 additional_flags2 = FLAGS2_REPARSE_PATH;
4520         }
4521
4522         subreq = cli_smb_send(state, ev, cli, SMBctemp, additional_flags,
4523                         additional_flags2,
4524                         3, state->vwv, talloc_get_size(bytes), bytes);
4525         if (tevent_req_nomem(subreq, req)) {
4526                 return tevent_req_post(req, ev);
4527         }
4528         tevent_req_set_callback(subreq, cli_ctemp_done, req);
4529         return req;
4530 }
4531
4532 static void cli_ctemp_done(struct tevent_req *subreq)
4533 {
4534         struct tevent_req *req = tevent_req_callback_data(
4535                                 subreq, struct tevent_req);
4536         struct ctemp_state *state = tevent_req_data(
4537                                 req, struct ctemp_state);
4538         NTSTATUS status;
4539         uint8_t wcnt;
4540         uint16_t *vwv;
4541         uint32_t num_bytes = 0;
4542         uint8_t *bytes = NULL;
4543
4544         status = cli_smb_recv(subreq, state, NULL, 1, &wcnt, &vwv,
4545                               &num_bytes, &bytes);
4546         TALLOC_FREE(subreq);
4547         if (tevent_req_nterror(req, status)) {
4548                 return;
4549         }
4550
4551         state->fnum = SVAL(vwv+0, 0);
4552
4553         /* From W2K3, the result is just the ASCII name */
4554         if (num_bytes < 2) {
4555                 tevent_req_nterror(req, NT_STATUS_DATA_ERROR);
4556                 return;
4557         }
4558
4559         if (pull_string_talloc(state,
4560                         NULL,
4561                         0,
4562                         &state->ret_path,
4563                         bytes,
4564                         num_bytes,
4565                         STR_ASCII) == 0) {
4566                 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
4567                 return;
4568         }
4569         tevent_req_done(req);
4570 }
4571
4572 NTSTATUS cli_ctemp_recv(struct tevent_req *req,
4573                         TALLOC_CTX *ctx,
4574                         uint16_t *pfnum,
4575                         char **outfile)
4576 {
4577         struct ctemp_state *state = tevent_req_data(req,
4578                         struct ctemp_state);
4579         NTSTATUS status;
4580
4581         if (tevent_req_is_nterror(req, &status)) {
4582                 return status;
4583         }
4584         *pfnum = state->fnum;
4585         *outfile = talloc_strdup(ctx, state->ret_path);
4586         if (!*outfile) {
4587                 return NT_STATUS_NO_MEMORY;
4588         }
4589         return NT_STATUS_OK;
4590 }
4591
4592 NTSTATUS cli_ctemp(struct cli_state *cli,
4593                         TALLOC_CTX *ctx,
4594                         const char *path,
4595                         uint16_t *pfnum,
4596                         char **out_path)
4597 {
4598         TALLOC_CTX *frame = talloc_stackframe();
4599         struct tevent_context *ev;
4600         struct tevent_req *req;
4601         NTSTATUS status = NT_STATUS_OK;
4602
4603         if (smbXcli_conn_has_async_calls(cli->conn)) {
4604                 /*
4605                  * Can't use sync call while an async call is in flight
4606                  */
4607                 status = NT_STATUS_INVALID_PARAMETER;
4608                 goto fail;
4609         }
4610
4611         ev = samba_tevent_context_init(frame);
4612         if (ev == NULL) {
4613                 status = NT_STATUS_NO_MEMORY;
4614                 goto fail;
4615         }
4616
4617         req = cli_ctemp_send(frame, ev, cli, path);
4618         if (req == NULL) {
4619                 status = NT_STATUS_NO_MEMORY;
4620                 goto fail;
4621         }
4622
4623         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
4624                 goto fail;
4625         }
4626
4627         status = cli_ctemp_recv(req, ctx, pfnum, out_path);
4628
4629  fail:
4630         TALLOC_FREE(frame);
4631         return status;
4632 }
4633
4634 /*
4635    send a raw ioctl - used by the torture code
4636 */
4637 NTSTATUS cli_raw_ioctl(struct cli_state *cli, uint16_t fnum, uint32_t code, DATA_BLOB *blob)
4638 {
4639         uint16_t vwv[3];
4640         NTSTATUS status;
4641
4642         SSVAL(vwv+0, 0, fnum);
4643         SSVAL(vwv+1, 0, code>>16);
4644         SSVAL(vwv+2, 0, (code&0xFFFF));
4645
4646         status = cli_smb(talloc_tos(), cli, SMBioctl, 0, 3, vwv, 0, NULL,
4647                          NULL, 0, NULL, NULL, NULL, NULL);
4648         if (!NT_STATUS_IS_OK(status)) {
4649                 return status;
4650         }
4651         *blob = data_blob_null;
4652         return NT_STATUS_OK;
4653 }
4654
4655 /*********************************************************
4656  Set an extended attribute utility fn.
4657 *********************************************************/
4658
4659 static NTSTATUS cli_set_ea(struct cli_state *cli, uint16_t setup_val,
4660                            uint8_t *param, unsigned int param_len,
4661                            const char *ea_name,
4662                            const char *ea_val, size_t ea_len)
4663 {
4664         uint16_t setup[1];
4665         unsigned int data_len = 0;
4666         uint8_t *data = NULL;
4667         char *p;
4668         size_t ea_namelen = strlen(ea_name);
4669         NTSTATUS status;
4670
4671         SSVAL(setup, 0, setup_val);
4672
4673         if (ea_namelen == 0 && ea_len == 0) {
4674                 data_len = 4;
4675                 data = talloc_array(talloc_tos(),
4676                                 uint8_t,
4677                                 data_len);
4678                 if (!data) {
4679                         return NT_STATUS_NO_MEMORY;
4680                 }
4681                 p = (char *)data;
4682                 SIVAL(p,0,data_len);
4683         } else {
4684                 data_len = 4 + 4 + ea_namelen + 1 + ea_len;
4685                 data = talloc_array(talloc_tos(),
4686                                 uint8_t,
4687                                 data_len);
4688                 if (!data) {
4689                         return NT_STATUS_NO_MEMORY;
4690                 }
4691                 p = (char *)data;
4692                 SIVAL(p,0,data_len);
4693                 p += 4;
4694                 SCVAL(p, 0, 0); /* EA flags. */
4695                 SCVAL(p, 1, ea_namelen);
4696                 SSVAL(p, 2, ea_len);
4697                 memcpy(p+4, ea_name, ea_namelen+1); /* Copy in the name. */
4698                 memcpy(p+4+ea_namelen+1, ea_val, ea_len);
4699         }
4700
4701         /*
4702          * FIXME - if we want to do previous version path
4703          * processing on an EA set call we need to turn this
4704          * into calls to cli_trans_send()/cli_trans_recv()
4705          * with a temporary event context, as cli_trans_send()
4706          * have access to the additional_flags2 needed to
4707          * send @GMT- paths. JRA.
4708          */
4709
4710         status = cli_trans(talloc_tos(), cli, SMBtrans2, NULL, -1, 0, 0,
4711                            setup, 1, 0,
4712                            param, param_len, 2,
4713                            data,  data_len, 0,
4714                            NULL,
4715                            NULL, 0, NULL, /* rsetup */
4716                            NULL, 0, NULL, /* rparam */
4717                            NULL, 0, NULL); /* rdata */
4718         talloc_free(data);
4719         return status;
4720 }
4721
4722 /*********************************************************
4723  Set an extended attribute on a pathname.
4724 *********************************************************/
4725
4726 NTSTATUS cli_set_ea_path(struct cli_state *cli, const char *path,
4727                          const char *ea_name, const char *ea_val,
4728                          size_t ea_len)
4729 {
4730         unsigned int param_len = 0;
4731         uint8_t *param;
4732         NTSTATUS status;
4733         TALLOC_CTX *frame = NULL;
4734
4735         if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
4736                 return cli_smb2_set_ea_path(cli,
4737                                         path,
4738                                         ea_name,
4739                                         ea_val,
4740                                         ea_len);
4741         }
4742
4743         frame = talloc_stackframe();
4744
4745         param = talloc_array(frame, uint8_t, 6);
4746         if (!param) {
4747                 status = NT_STATUS_NO_MEMORY;
4748                 goto fail;
4749         }
4750         SSVAL(param,0,SMB_INFO_SET_EA);
4751         SSVAL(param,2,0);
4752         SSVAL(param,4,0);
4753
4754         param = trans2_bytes_push_str(param, smbXcli_conn_use_unicode(cli->conn),
4755                                       path, strlen(path)+1,
4756                                       NULL);
4757         param_len = talloc_get_size(param);
4758
4759         status = cli_set_ea(cli, TRANSACT2_SETPATHINFO, param, param_len,
4760                             ea_name, ea_val, ea_len);
4761
4762   fail:
4763
4764         TALLOC_FREE(frame);
4765         return status;
4766 }
4767
4768 /*********************************************************
4769  Set an extended attribute on an fnum.
4770 *********************************************************/
4771
4772 NTSTATUS cli_set_ea_fnum(struct cli_state *cli, uint16_t fnum,
4773                          const char *ea_name, const char *ea_val,
4774                          size_t ea_len)
4775 {
4776         uint8_t param[6];
4777
4778         if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
4779                 return cli_smb2_set_ea_fnum(cli,
4780                                         fnum,
4781                                         ea_name,
4782                                         ea_val,
4783                                         ea_len);
4784         }
4785
4786         memset(param, 0, 6);
4787         SSVAL(param,0,fnum);
4788         SSVAL(param,2,SMB_INFO_SET_EA);
4789
4790         return cli_set_ea(cli, TRANSACT2_SETFILEINFO, param, 6,
4791                           ea_name, ea_val, ea_len);
4792 }
4793
4794 /*********************************************************
4795  Get an extended attribute list utility fn.
4796 *********************************************************/
4797
4798 static bool parse_ea_blob(TALLOC_CTX *ctx, const uint8_t *rdata,
4799                           size_t rdata_len,
4800                           size_t *pnum_eas, struct ea_struct **pea_list)
4801 {
4802         struct ea_struct *ea_list = NULL;
4803         size_t num_eas;
4804         size_t ea_size;
4805         const uint8_t *p;
4806
4807         if (rdata_len < 4) {
4808                 return false;
4809         }
4810
4811         ea_size = (size_t)IVAL(rdata,0);
4812         if (ea_size > rdata_len) {
4813                 return false;
4814         }
4815
4816         if (ea_size == 0) {
4817                 /* No EA's present. */
4818                 *pnum_eas = 0;
4819                 *pea_list = NULL;
4820                 return true;
4821         }
4822
4823         p = rdata + 4;
4824         ea_size -= 4;
4825
4826         /* Validate the EA list and count it. */
4827         for (num_eas = 0; ea_size >= 4; num_eas++) {
4828                 unsigned int ea_namelen = CVAL(p,1);
4829                 unsigned int ea_valuelen = SVAL(p,2);
4830                 if (ea_namelen == 0) {
4831                         return false;
4832                 }
4833                 if (4 + ea_namelen + 1 + ea_valuelen > ea_size) {
4834                         return false;
4835                 }
4836                 ea_size -= 4 + ea_namelen + 1 + ea_valuelen;
4837                 p += 4 + ea_namelen + 1 + ea_valuelen;
4838         }
4839
4840         if (num_eas == 0) {
4841                 *pnum_eas = 0;
4842                 *pea_list = NULL;
4843                 return true;
4844         }
4845
4846         *pnum_eas = num_eas;
4847         if (!pea_list) {
4848                 /* Caller only wants number of EA's. */
4849                 return true;
4850         }
4851
4852         ea_list = talloc_array(ctx, struct ea_struct, num_eas);
4853         if (!ea_list) {
4854                 return false;
4855         }
4856
4857         ea_size = (size_t)IVAL(rdata,0);
4858         p = rdata + 4;
4859
4860         for (num_eas = 0; num_eas < *pnum_eas; num_eas++ ) {
4861                 struct ea_struct *ea = &ea_list[num_eas];
4862                 fstring unix_ea_name;
4863                 unsigned int ea_namelen = CVAL(p,1);
4864                 unsigned int ea_valuelen = SVAL(p,2);
4865
4866                 ea->flags = CVAL(p,0);
4867                 unix_ea_name[0] = '\0';
4868                 pull_ascii(unix_ea_name, p + 4, sizeof(unix_ea_name), rdata_len - PTR_DIFF(p+4, rdata), STR_TERMINATE);
4869                 ea->name = talloc_strdup(ea_list, unix_ea_name);
4870                 if (!ea->name) {
4871                         goto fail;
4872                 }
4873                 /* Ensure the value is null terminated (in case it's a string). */
4874                 ea->value = data_blob_talloc(ea_list, NULL, ea_valuelen + 1);
4875                 if (!ea->value.data) {
4876                         goto fail;
4877                 }
4878                 if (ea_valuelen) {
4879                         memcpy(ea->value.data, p+4+ea_namelen+1, ea_valuelen);
4880                 }
4881                 ea->value.data[ea_valuelen] = 0;
4882                 ea->value.length--;
4883                 p += 4 + ea_namelen + 1 + ea_valuelen;
4884         }
4885
4886         *pea_list = ea_list;
4887         return true;
4888
4889 fail:
4890         TALLOC_FREE(ea_list);
4891         return false;
4892 }
4893
4894 /*********************************************************
4895  Get an extended attribute list from a pathname.
4896 *********************************************************/
4897
4898 struct cli_get_ea_list_path_state {
4899         uint32_t num_data;
4900         uint8_t *data;
4901 };
4902
4903 static void cli_get_ea_list_path_done(struct tevent_req *subreq);
4904
4905 struct tevent_req *cli_get_ea_list_path_send(TALLOC_CTX *mem_ctx,
4906                                              struct tevent_context *ev,
4907                                              struct cli_state *cli,
4908                                              const char *fname)
4909 {
4910         struct tevent_req *req, *subreq;
4911         struct cli_get_ea_list_path_state *state;
4912
4913         req = tevent_req_create(mem_ctx, &state,
4914                                 struct cli_get_ea_list_path_state);
4915         if (req == NULL) {
4916                 return NULL;
4917         }
4918         subreq = cli_qpathinfo_send(state, ev, cli, fname,
4919                                     SMB_INFO_QUERY_ALL_EAS, 4,
4920                                     CLI_BUFFER_SIZE);
4921         if (tevent_req_nomem(subreq, req)) {
4922                 return tevent_req_post(req, ev);
4923         }
4924         tevent_req_set_callback(subreq, cli_get_ea_list_path_done, req);
4925         return req;
4926 }
4927
4928 static void cli_get_ea_list_path_done(struct tevent_req *subreq)
4929 {
4930         struct tevent_req *req = tevent_req_callback_data(
4931                                 subreq, struct tevent_req);
4932         struct cli_get_ea_list_path_state *state = tevent_req_data(
4933                 req, struct cli_get_ea_list_path_state);
4934         NTSTATUS status;
4935
4936         status = cli_qpathinfo_recv(subreq, state, &state->data,
4937                                     &state->num_data);
4938         TALLOC_FREE(subreq);
4939         if (tevent_req_nterror(req, status)) {
4940                 return;
4941         }
4942         tevent_req_done(req);
4943 }
4944
4945 NTSTATUS cli_get_ea_list_path_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
4946                                    size_t *pnum_eas, struct ea_struct **peas)
4947 {
4948         struct cli_get_ea_list_path_state *state = tevent_req_data(
4949                 req, struct cli_get_ea_list_path_state);
4950         NTSTATUS status;
4951
4952         if (tevent_req_is_nterror(req, &status)) {
4953                 return status;
4954         }
4955         if (!parse_ea_blob(mem_ctx, state->data, state->num_data,
4956                            pnum_eas, peas)) {
4957                 return NT_STATUS_INVALID_NETWORK_RESPONSE;
4958         }
4959         return NT_STATUS_OK;
4960 }
4961
4962 NTSTATUS cli_get_ea_list_path(struct cli_state *cli, const char *path,
4963                 TALLOC_CTX *ctx,
4964                 size_t *pnum_eas,
4965                 struct ea_struct **pea_list)
4966 {
4967         TALLOC_CTX *frame = NULL;
4968         struct tevent_context *ev = NULL;
4969         struct tevent_req *req = NULL;
4970         NTSTATUS status = NT_STATUS_NO_MEMORY;
4971
4972         if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
4973                 return cli_smb2_get_ea_list_path(cli,
4974                                         path,
4975                                         ctx,
4976                                         pnum_eas,
4977                                         pea_list);
4978         }
4979
4980         frame = talloc_stackframe();
4981
4982         if (smbXcli_conn_has_async_calls(cli->conn)) {
4983                 /*
4984                  * Can't use sync call while an async call is in flight
4985                  */
4986                 status = NT_STATUS_INVALID_PARAMETER;
4987                 goto fail;
4988         }
4989         ev = samba_tevent_context_init(frame);
4990         if (ev == NULL) {
4991                 goto fail;
4992         }
4993         req = cli_get_ea_list_path_send(frame, ev, cli, path);
4994         if (req == NULL) {
4995                 goto fail;
4996         }
4997         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
4998                 goto fail;
4999         }
5000         status = cli_get_ea_list_path_recv(req, ctx, pnum_eas, pea_list);
5001  fail:
5002         TALLOC_FREE(frame);
5003         return status;
5004 }
5005
5006 /****************************************************************************
5007  Convert open "flags" arg to uint32_t on wire.
5008 ****************************************************************************/
5009
5010 static uint32_t open_flags_to_wire(int flags)
5011 {
5012         int open_mode = flags & O_ACCMODE;
5013         uint32_t ret = 0;
5014
5015         switch (open_mode) {
5016                 case O_WRONLY:
5017                         ret |= SMB_O_WRONLY;
5018                         break;
5019                 case O_RDWR:
5020                         ret |= SMB_O_RDWR;
5021                         break;
5022                 default:
5023                 case O_RDONLY:
5024                         ret |= SMB_O_RDONLY;
5025                         break;
5026         }
5027
5028         if (flags & O_CREAT) {
5029                 ret |= SMB_O_CREAT;
5030         }
5031         if (flags & O_EXCL) {
5032                 ret |= SMB_O_EXCL;
5033         }
5034         if (flags & O_TRUNC) {
5035                 ret |= SMB_O_TRUNC;
5036         }
5037 #if defined(O_SYNC)
5038         if (flags & O_SYNC) {
5039                 ret |= SMB_O_SYNC;
5040         }
5041 #endif /* O_SYNC */
5042         if (flags & O_APPEND) {
5043                 ret |= SMB_O_APPEND;
5044         }
5045 #if defined(O_DIRECT)
5046         if (flags & O_DIRECT) {
5047                 ret |= SMB_O_DIRECT;
5048         }
5049 #endif
5050 #if defined(O_DIRECTORY)
5051         if (flags & O_DIRECTORY) {
5052                 ret |= SMB_O_DIRECTORY;
5053         }
5054 #endif
5055         return ret;
5056 }
5057
5058 /****************************************************************************
5059  Open a file - POSIX semantics. Returns fnum. Doesn't request oplock.
5060 ****************************************************************************/
5061
5062 struct posix_open_state {
5063         uint16_t setup;
5064         uint8_t *param;
5065         uint8_t data[18];
5066         uint16_t fnum; /* Out */
5067 };
5068
5069 static void cli_posix_open_internal_done(struct tevent_req *subreq)
5070 {
5071         struct tevent_req *req = tevent_req_callback_data(
5072                                 subreq, struct tevent_req);
5073         struct posix_open_state *state = tevent_req_data(req, struct posix_open_state);
5074         NTSTATUS status;
5075         uint8_t *data;
5076         uint32_t num_data;
5077
5078         status = cli_trans_recv(subreq, state, NULL, NULL, 0, NULL,
5079                                 NULL, 0, NULL, &data, 12, &num_data);
5080         TALLOC_FREE(subreq);
5081         if (tevent_req_nterror(req, status)) {
5082                 return;
5083         }
5084         state->fnum = SVAL(data,2);
5085         tevent_req_done(req);
5086 }
5087
5088 static struct tevent_req *cli_posix_open_internal_send(TALLOC_CTX *mem_ctx,
5089                                         struct tevent_context *ev,
5090                                         struct cli_state *cli,
5091                                         const char *fname,
5092                                         int flags,
5093                                         mode_t mode,
5094                                         bool is_dir)
5095 {
5096         struct tevent_req *req = NULL, *subreq = NULL;
5097         struct posix_open_state *state = NULL;
5098         uint32_t wire_flags = open_flags_to_wire(flags);
5099
5100         req = tevent_req_create(mem_ctx, &state, struct posix_open_state);
5101         if (req == NULL) {
5102                 return NULL;
5103         }
5104
5105         /* Setup setup word. */
5106         SSVAL(&state->setup, 0, TRANSACT2_SETPATHINFO);
5107
5108         /* Setup param array. */
5109         state->param = talloc_array(state, uint8_t, 6);
5110         if (tevent_req_nomem(state->param, req)) {
5111                 return tevent_req_post(req, ev);
5112         }
5113         memset(state->param, '\0', 6);
5114         SSVAL(state->param, 0, SMB_POSIX_PATH_OPEN);
5115
5116         state->param = trans2_bytes_push_str(state->param, smbXcli_conn_use_unicode(cli->conn), fname,
5117                                    strlen(fname)+1, NULL);
5118
5119         if (tevent_req_nomem(state->param, req)) {
5120                 return tevent_req_post(req, ev);
5121         }
5122
5123         /* Setup data words. */
5124         if (is_dir) {
5125                 wire_flags |= SMB_O_DIRECTORY;
5126         }
5127
5128         SIVAL(state->data,0,0); /* No oplock. */
5129         SIVAL(state->data,4,wire_flags);
5130         SIVAL(state->data,8,unix_perms_to_wire(mode));
5131         SIVAL(state->data,12,0); /* Top bits of perms currently undefined. */
5132         SSVAL(state->data,16,SMB_NO_INFO_LEVEL_RETURNED); /* No info level returned. */
5133
5134         subreq = cli_trans_send(state,                  /* mem ctx. */
5135                                 ev,                     /* event ctx. */
5136                                 cli,                    /* cli_state. */
5137                                 0,                      /* additional_flags2 */
5138                                 SMBtrans2,              /* cmd. */
5139                                 NULL,                   /* pipe name. */
5140                                 -1,                     /* fid. */
5141                                 0,                      /* function. */
5142                                 0,                      /* flags. */
5143                                 &state->setup,          /* setup. */
5144                                 1,                      /* num setup uint16_t words. */
5145                                 0,                      /* max returned setup. */
5146                                 state->param,           /* param. */
5147                                 talloc_get_size(state->param),/* num param. */
5148                                 2,                      /* max returned param. */
5149                                 state->data,            /* data. */
5150                                 18,                     /* num data. */
5151                                 12);                    /* max returned data. */
5152
5153         if (tevent_req_nomem(subreq, req)) {
5154                 return tevent_req_post(req, ev);
5155         }
5156         tevent_req_set_callback(subreq, cli_posix_open_internal_done, req);
5157         return req;
5158 }
5159
5160 struct tevent_req *cli_posix_open_send(TALLOC_CTX *mem_ctx,
5161                                         struct tevent_context *ev,
5162                                         struct cli_state *cli,
5163                                         const char *fname,
5164                                         int flags,
5165                                         mode_t mode)
5166 {
5167         return cli_posix_open_internal_send(mem_ctx, ev,
5168                                 cli, fname, flags, mode, false);
5169 }
5170
5171 NTSTATUS cli_posix_open_recv(struct tevent_req *req, uint16_t *pfnum)
5172 {
5173         struct posix_open_state *state = tevent_req_data(req, struct posix_open_state);
5174         NTSTATUS status;
5175
5176         if (tevent_req_is_nterror(req, &status)) {
5177                 return status;
5178         }
5179         *pfnum = state->fnum;
5180         return NT_STATUS_OK;
5181 }
5182
5183 /****************************************************************************
5184  Open - POSIX semantics. Doesn't request oplock.
5185 ****************************************************************************/
5186
5187 NTSTATUS cli_posix_open(struct cli_state *cli, const char *fname,
5188                         int flags, mode_t mode, uint16_t *pfnum)
5189 {
5190
5191         TALLOC_CTX *frame = talloc_stackframe();
5192         struct tevent_context *ev = NULL;
5193         struct tevent_req *req = NULL;
5194         NTSTATUS status = NT_STATUS_OK;
5195
5196         if (smbXcli_conn_has_async_calls(cli->conn)) {
5197                 /*
5198                  * Can't use sync call while an async call is in flight
5199                  */
5200                 status = NT_STATUS_INVALID_PARAMETER;
5201                 goto fail;
5202         }
5203
5204         ev = samba_tevent_context_init(frame);
5205         if (ev == NULL) {
5206                 status = NT_STATUS_NO_MEMORY;
5207                 goto fail;
5208         }
5209
5210         req = cli_posix_open_send(frame,
5211                                 ev,
5212                                 cli,
5213                                 fname,
5214                                 flags,
5215                                 mode);
5216         if (req == NULL) {
5217                 status = NT_STATUS_NO_MEMORY;
5218                 goto fail;
5219         }
5220
5221         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
5222                 goto fail;
5223         }
5224
5225         status = cli_posix_open_recv(req, pfnum);
5226
5227  fail:
5228         TALLOC_FREE(frame);
5229         return status;
5230 }
5231
5232 struct tevent_req *cli_posix_mkdir_send(TALLOC_CTX *mem_ctx,
5233                                         struct tevent_context *ev,
5234                                         struct cli_state *cli,
5235                                         const char *fname,
5236                                         mode_t mode)
5237 {
5238         return cli_posix_open_internal_send(mem_ctx, ev,
5239                                 cli, fname, O_CREAT, mode, true);
5240 }
5241
5242 NTSTATUS cli_posix_mkdir_recv(struct tevent_req *req)
5243 {
5244         return tevent_req_simple_recv_ntstatus(req);
5245 }
5246
5247 NTSTATUS cli_posix_mkdir(struct cli_state *cli, const char *fname, mode_t mode)
5248 {
5249         TALLOC_CTX *frame = talloc_stackframe();
5250         struct tevent_context *ev = NULL;
5251         struct tevent_req *req = NULL;
5252         NTSTATUS status = NT_STATUS_OK;
5253
5254         if (smbXcli_conn_has_async_calls(cli->conn)) {
5255                 /*
5256                  * Can't use sync call while an async call is in flight
5257                  */
5258                 status = NT_STATUS_INVALID_PARAMETER;
5259                 goto fail;
5260         }
5261
5262         ev = samba_tevent_context_init(frame);
5263         if (ev == NULL) {
5264                 status = NT_STATUS_NO_MEMORY;
5265                 goto fail;
5266         }
5267
5268         req = cli_posix_mkdir_send(frame,
5269                                 ev,
5270                                 cli,
5271                                 fname,
5272                                 mode);
5273         if (req == NULL) {
5274                 status = NT_STATUS_NO_MEMORY;
5275                 goto fail;
5276         }
5277
5278         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
5279                 goto fail;
5280         }
5281
5282         status = cli_posix_mkdir_recv(req);
5283
5284  fail:
5285         TALLOC_FREE(frame);
5286         return status;
5287 }
5288
5289 /****************************************************************************
5290  unlink or rmdir - POSIX semantics.
5291 ****************************************************************************/
5292
5293 struct cli_posix_unlink_internal_state {
5294         uint8_t data[2];
5295 };
5296
5297 static void cli_posix_unlink_internal_done(struct tevent_req *subreq);
5298
5299 static struct tevent_req *cli_posix_unlink_internal_send(TALLOC_CTX *mem_ctx,
5300                                         struct tevent_context *ev,
5301                                         struct cli_state *cli,
5302                                         const char *fname,
5303                                         uint16_t level)
5304 {
5305         struct tevent_req *req = NULL, *subreq = NULL;
5306         struct cli_posix_unlink_internal_state *state = NULL;
5307
5308         req = tevent_req_create(mem_ctx, &state,
5309                                 struct cli_posix_unlink_internal_state);
5310         if (req == NULL) {
5311                 return NULL;
5312         }
5313
5314         /* Setup data word. */
5315         SSVAL(state->data, 0, level);
5316
5317         subreq = cli_setpathinfo_send(state, ev, cli,
5318                                       SMB_POSIX_PATH_UNLINK,
5319                                       fname,
5320                                       state->data, sizeof(state->data));
5321         if (tevent_req_nomem(subreq, req)) {
5322                 return tevent_req_post(req, ev);
5323         }
5324         tevent_req_set_callback(subreq, cli_posix_unlink_internal_done, req);
5325         return req;
5326 }
5327
5328 static void cli_posix_unlink_internal_done(struct tevent_req *subreq)
5329 {
5330         NTSTATUS status = cli_setpathinfo_recv(subreq);
5331         tevent_req_simple_finish_ntstatus(subreq, status);
5332 }
5333
5334 struct tevent_req *cli_posix_unlink_send(TALLOC_CTX *mem_ctx,
5335                                         struct tevent_context *ev,
5336                                         struct cli_state *cli,
5337                                         const char *fname)
5338 {
5339         return cli_posix_unlink_internal_send(mem_ctx, ev, cli, fname,
5340                                               SMB_POSIX_UNLINK_FILE_TARGET);
5341 }
5342
5343 NTSTATUS cli_posix_unlink_recv(struct tevent_req *req)
5344 {
5345         return tevent_req_simple_recv_ntstatus(req);
5346 }
5347
5348 /****************************************************************************
5349  unlink - POSIX semantics.
5350 ****************************************************************************/
5351
5352 NTSTATUS cli_posix_unlink(struct cli_state *cli, const char *fname)
5353 {
5354         TALLOC_CTX *frame = talloc_stackframe();
5355         struct tevent_context *ev = NULL;
5356         struct tevent_req *req = NULL;
5357         NTSTATUS status = NT_STATUS_OK;
5358
5359         if (smbXcli_conn_has_async_calls(cli->conn)) {
5360                 /*
5361                  * Can't use sync call while an async call is in flight
5362                  */
5363                 status = NT_STATUS_INVALID_PARAMETER;
5364                 goto fail;
5365         }
5366
5367         ev = samba_tevent_context_init(frame);
5368         if (ev == NULL) {
5369                 status = NT_STATUS_NO_MEMORY;
5370                 goto fail;
5371         }
5372
5373         req = cli_posix_unlink_send(frame,
5374                                 ev,
5375                                 cli,
5376                                 fname);
5377         if (req == NULL) {
5378                 status = NT_STATUS_NO_MEMORY;
5379                 goto fail;
5380         }
5381
5382         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
5383                 goto fail;
5384         }
5385
5386         status = cli_posix_unlink_recv(req);
5387
5388  fail:
5389         TALLOC_FREE(frame);
5390         return status;
5391 }
5392
5393 /****************************************************************************
5394  rmdir - POSIX semantics.
5395 ****************************************************************************/
5396
5397 struct tevent_req *cli_posix_rmdir_send(TALLOC_CTX *mem_ctx,
5398                                         struct tevent_context *ev,
5399                                         struct cli_state *cli,
5400                                         const char *fname)
5401 {
5402         return cli_posix_unlink_internal_send(
5403                 mem_ctx, ev, cli, fname,
5404                 SMB_POSIX_UNLINK_DIRECTORY_TARGET);
5405 }
5406
5407 NTSTATUS cli_posix_rmdir_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx)
5408 {
5409         return tevent_req_simple_recv_ntstatus(req);
5410 }
5411
5412 NTSTATUS cli_posix_rmdir(struct cli_state *cli, const char *fname)
5413 {
5414         TALLOC_CTX *frame = talloc_stackframe();
5415         struct tevent_context *ev = NULL;
5416         struct tevent_req *req = NULL;
5417         NTSTATUS status = NT_STATUS_OK;
5418
5419         if (smbXcli_conn_has_async_calls(cli->conn)) {
5420                 /*
5421                  * Can't use sync call while an async call is in flight
5422                  */
5423                 status = NT_STATUS_INVALID_PARAMETER;
5424                 goto fail;
5425         }
5426
5427         ev = samba_tevent_context_init(frame);
5428         if (ev == NULL) {
5429                 status = NT_STATUS_NO_MEMORY;
5430                 goto fail;
5431         }
5432
5433         req = cli_posix_rmdir_send(frame,
5434                                 ev,
5435                                 cli,
5436                                 fname);
5437         if (req == NULL) {
5438                 status = NT_STATUS_NO_MEMORY;
5439                 goto fail;
5440         }
5441
5442         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
5443                 goto fail;
5444         }
5445
5446         status = cli_posix_rmdir_recv(req, frame);
5447
5448  fail:
5449         TALLOC_FREE(frame);
5450         return status;
5451 }
5452
5453 /****************************************************************************
5454  filechangenotify
5455 ****************************************************************************/
5456
5457 struct cli_notify_state {
5458         uint8_t setup[8];
5459         uint32_t num_changes;
5460         struct notify_change *changes;
5461 };
5462
5463 static void cli_notify_done(struct tevent_req *subreq);
5464
5465 struct tevent_req *cli_notify_send(TALLOC_CTX *mem_ctx,
5466                                    struct tevent_context *ev,
5467                                    struct cli_state *cli, uint16_t fnum,
5468                                    uint32_t buffer_size,
5469                                    uint32_t completion_filter, bool recursive)
5470 {
5471         struct tevent_req *req, *subreq;
5472         struct cli_notify_state *state;
5473         unsigned old_timeout;
5474
5475         req = tevent_req_create(mem_ctx, &state, struct cli_notify_state);
5476         if (req == NULL) {
5477                 return NULL;
5478         }
5479
5480         SIVAL(state->setup, 0, completion_filter);
5481         SSVAL(state->setup, 4, fnum);
5482         SSVAL(state->setup, 6, recursive);
5483
5484         /*
5485          * Notifies should not time out
5486          */
5487         old_timeout = cli_set_timeout(cli, 0);
5488
5489         subreq = cli_trans_send(
5490                 state,                  /* mem ctx. */
5491                 ev,                     /* event ctx. */
5492                 cli,                    /* cli_state. */
5493                 0,                      /* additional_flags2 */
5494                 SMBnttrans,             /* cmd. */
5495                 NULL,                   /* pipe name. */
5496                 -1,                     /* fid. */
5497                 NT_TRANSACT_NOTIFY_CHANGE, /* function. */
5498                 0,                      /* flags. */
5499                 (uint16_t *)state->setup, /* setup. */
5500                 4,                      /* num setup uint16_t words. */
5501                 0,                      /* max returned setup. */
5502                 NULL,                   /* param. */
5503                 0,                      /* num param. */
5504                 buffer_size,            /* max returned param. */
5505                 NULL,                   /* data. */
5506                 0,                      /* num data. */
5507                 0);                     /* max returned data. */
5508
5509         cli_set_timeout(cli, old_timeout);
5510
5511         if (tevent_req_nomem(subreq, req)) {
5512                 return tevent_req_post(req, ev);
5513         }
5514         tevent_req_set_callback(subreq, cli_notify_done, req);
5515         return req;
5516 }
5517
5518 static void cli_notify_done(struct tevent_req *subreq)
5519 {
5520         struct tevent_req *req = tevent_req_callback_data(
5521                 subreq, struct tevent_req);
5522         struct cli_notify_state *state = tevent_req_data(
5523                 req, struct cli_notify_state);
5524         NTSTATUS status;
5525         uint8_t *params;
5526         uint32_t i, ofs, num_params;
5527         uint16_t flags2;
5528
5529         status = cli_trans_recv(subreq, talloc_tos(), &flags2, NULL, 0, NULL,
5530                                 &params, 0, &num_params, NULL, 0, NULL);
5531         TALLOC_FREE(subreq);
5532         if (tevent_req_nterror(req, status)) {
5533                 DEBUG(10, ("cli_trans_recv returned %s\n", nt_errstr(status)));
5534                 return;
5535         }
5536
5537         state->num_changes = 0;
5538         ofs = 0;
5539
5540         while (num_params - ofs > 12) {
5541                 uint32_t next = IVAL(params, ofs);
5542                 state->num_changes += 1;
5543
5544                 if ((next == 0) || (ofs+next >= num_params)) {
5545                         break;
5546                 }
5547                 ofs += next;
5548         }
5549
5550         state->changes = talloc_array(state, struct notify_change,
5551                                       state->num_changes);
5552         if (tevent_req_nomem(state->changes, req)) {
5553                 TALLOC_FREE(params);
5554                 return;
5555         }
5556
5557         ofs = 0;
5558
5559         for (i=0; i<state->num_changes; i++) {
5560                 uint32_t next = IVAL(params, ofs);
5561                 uint32_t len = IVAL(params, ofs+8);
5562                 ssize_t ret;
5563                 char *name;
5564
5565                 if (trans_oob(num_params, ofs + 12, len)) {
5566                         TALLOC_FREE(params);
5567                         tevent_req_nterror(
5568                                 req, NT_STATUS_INVALID_NETWORK_RESPONSE);
5569                         return;
5570                 }
5571
5572                 state->changes[i].action = IVAL(params, ofs+4);
5573                 ret = clistr_pull_talloc(state->changes, (char *)params, flags2,
5574                                          &name, params+ofs+12, len,
5575                                          STR_TERMINATE|STR_UNICODE);
5576                 if (ret == -1) {
5577                         TALLOC_FREE(params);
5578                         tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
5579                         return;
5580                 }
5581                 state->changes[i].name = name;
5582                 ofs += next;
5583         }
5584
5585         TALLOC_FREE(params);
5586         tevent_req_done(req);
5587 }
5588
5589 NTSTATUS cli_notify_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
5590                          uint32_t *pnum_changes,
5591                          struct notify_change **pchanges)
5592 {
5593         struct cli_notify_state *state = tevent_req_data(
5594                 req, struct cli_notify_state);
5595         NTSTATUS status;
5596
5597         if (tevent_req_is_nterror(req, &status)) {
5598                 return status;
5599         }
5600
5601         *pnum_changes = state->num_changes;
5602         *pchanges = talloc_move(mem_ctx, &state->changes);
5603         return NT_STATUS_OK;
5604 }
5605
5606 NTSTATUS cli_notify(struct cli_state *cli, uint16_t fnum, uint32_t buffer_size,
5607                     uint32_t completion_filter, bool recursive,
5608                     TALLOC_CTX *mem_ctx, uint32_t *pnum_changes,
5609                     struct notify_change **pchanges)
5610 {
5611         TALLOC_CTX *frame;
5612         struct tevent_context *ev;
5613         struct tevent_req *req;
5614         NTSTATUS status = NT_STATUS_NO_MEMORY;
5615
5616         if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
5617                 return cli_smb2_notify(cli, fnum, buffer_size,
5618                                        completion_filter, recursive,
5619                                        mem_ctx, pchanges, pnum_changes);
5620         }
5621
5622         frame = talloc_stackframe();
5623
5624         if (smbXcli_conn_has_async_calls(cli->conn)) {
5625                 /*
5626                  * Can't use sync call while an async call is in flight
5627                  */
5628                 status = NT_STATUS_INVALID_PARAMETER;
5629                 goto fail;
5630         }
5631         ev = samba_tevent_context_init(frame);
5632         if (ev == NULL) {
5633                 goto fail;
5634         }
5635         req = cli_notify_send(ev, ev, cli, fnum, buffer_size,
5636                               completion_filter, recursive);
5637         if (req == NULL) {
5638                 goto fail;
5639         }
5640         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
5641                 goto fail;
5642         }
5643         status = cli_notify_recv(req, mem_ctx, pnum_changes, pchanges);
5644  fail:
5645         TALLOC_FREE(frame);
5646         return status;
5647 }
5648
5649 struct cli_qpathinfo_state {
5650         uint8_t *param;
5651         uint8_t *data;
5652         uint16_t setup[1];
5653         uint32_t min_rdata;
5654         uint8_t *rdata;
5655         uint32_t num_rdata;
5656 };
5657
5658 static void cli_qpathinfo_done(struct tevent_req *subreq);
5659
5660 struct tevent_req *cli_qpathinfo_send(TALLOC_CTX *mem_ctx,
5661                                       struct tevent_context *ev,
5662                                       struct cli_state *cli, const char *fname,
5663                                       uint16_t level, uint32_t min_rdata,
5664                                       uint32_t max_rdata)
5665 {
5666         struct tevent_req *req, *subreq;
5667         struct cli_qpathinfo_state *state;
5668         uint16_t additional_flags2 = 0;
5669
5670         req = tevent_req_create(mem_ctx, &state, struct cli_qpathinfo_state);
5671         if (req == NULL) {
5672                 return NULL;
5673         }
5674         state->min_rdata = min_rdata;
5675         SSVAL(state->setup, 0, TRANSACT2_QPATHINFO);
5676
5677         state->param = talloc_zero_array(state, uint8_t, 6);
5678         if (tevent_req_nomem(state->param, req)) {
5679                 return tevent_req_post(req, ev);
5680         }
5681         SSVAL(state->param, 0, level);
5682         state->param = trans2_bytes_push_str(
5683                 state->param, smbXcli_conn_use_unicode(cli->conn), fname, strlen(fname)+1, NULL);
5684         if (tevent_req_nomem(state->param, req)) {
5685                 return tevent_req_post(req, ev);
5686         }
5687
5688         if (clistr_is_previous_version_path(fname, NULL, NULL, NULL) &&
5689                         !INFO_LEVEL_IS_UNIX(level)) {
5690                 additional_flags2 = FLAGS2_REPARSE_PATH;
5691         }
5692
5693         subreq = cli_trans_send(
5694                 state,                  /* mem ctx. */
5695                 ev,                     /* event ctx. */
5696                 cli,                    /* cli_state. */
5697                 additional_flags2,      /* additional_flags2 */
5698                 SMBtrans2,              /* cmd. */
5699                 NULL,                   /* pipe name. */
5700                 -1,                     /* fid. */
5701                 0,                      /* function. */
5702                 0,                      /* flags. */
5703                 state->setup,           /* setup. */
5704                 1,                      /* num setup uint16_t words. */
5705                 0,                      /* max returned setup. */
5706                 state->param,           /* param. */
5707                 talloc_get_size(state->param),  /* num param. */
5708                 2,                      /* max returned param. */
5709                 NULL,                   /* data. */
5710                 0,                      /* num data. */
5711                 max_rdata);             /* max returned data. */
5712
5713         if (tevent_req_nomem(subreq, req)) {
5714                 return tevent_req_post(req, ev);
5715         }
5716         tevent_req_set_callback(subreq, cli_qpathinfo_done, req);
5717         return req;
5718 }
5719
5720 static void cli_qpathinfo_done(struct tevent_req *subreq)
5721 {
5722         struct tevent_req *req = tevent_req_callback_data(
5723                 subreq, struct tevent_req);
5724         struct cli_qpathinfo_state *state = tevent_req_data(
5725                 req, struct cli_qpathinfo_state);
5726         NTSTATUS status;
5727
5728         status = cli_trans_recv(subreq, state, NULL, NULL, 0, NULL,
5729                                 NULL, 0, NULL,
5730                                 &state->rdata, state->min_rdata,
5731                                 &state->num_rdata);
5732         if (tevent_req_nterror(req, status)) {
5733                 return;
5734         }
5735         tevent_req_done(req);
5736 }
5737
5738 NTSTATUS cli_qpathinfo_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
5739                             uint8_t **rdata, uint32_t *num_rdata)
5740 {
5741         struct cli_qpathinfo_state *state = tevent_req_data(
5742                 req, struct cli_qpathinfo_state);
5743         NTSTATUS status;
5744
5745         if (tevent_req_is_nterror(req, &status)) {
5746                 return status;
5747         }
5748         if (rdata != NULL) {
5749                 *rdata = talloc_move(mem_ctx, &state->rdata);
5750         } else {
5751                 TALLOC_FREE(state->rdata);
5752         }
5753         if (num_rdata != NULL) {
5754                 *num_rdata = state->num_rdata;
5755         }
5756         return NT_STATUS_OK;
5757 }
5758
5759 NTSTATUS cli_qpathinfo(TALLOC_CTX *mem_ctx, struct cli_state *cli,
5760                        const char *fname, uint16_t level, uint32_t min_rdata,
5761                        uint32_t max_rdata,
5762                        uint8_t **rdata, uint32_t *num_rdata)
5763 {
5764         TALLOC_CTX *frame = talloc_stackframe();
5765         struct tevent_context *ev;
5766         struct tevent_req *req;
5767         NTSTATUS status = NT_STATUS_NO_MEMORY;
5768
5769         if (smbXcli_conn_has_async_calls(cli->conn)) {
5770                 /*
5771                  * Can't use sync call while an async call is in flight
5772                  */
5773                 status = NT_STATUS_INVALID_PARAMETER;
5774                 goto fail;
5775         }
5776         ev = samba_tevent_context_init(frame);
5777         if (ev == NULL) {
5778                 goto fail;
5779         }
5780         req = cli_qpathinfo_send(frame, ev, cli, fname, level, min_rdata,
5781                                  max_rdata);
5782         if (req == NULL) {
5783                 goto fail;
5784         }
5785         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
5786                 goto fail;
5787         }
5788         status = cli_qpathinfo_recv(req, mem_ctx, rdata, num_rdata);
5789  fail:
5790         TALLOC_FREE(frame);
5791         return status;
5792 }
5793
5794 struct cli_qfileinfo_state {
5795         uint16_t setup[1];
5796         uint8_t param[4];
5797         uint8_t *data;
5798         uint16_t recv_flags2;
5799         uint32_t min_rdata;
5800         uint8_t *rdata;
5801         uint32_t num_rdata;
5802 };
5803
5804 static void cli_qfileinfo_done(struct tevent_req *subreq);
5805
5806 struct tevent_req *cli_qfileinfo_send(TALLOC_CTX *mem_ctx,
5807                                       struct tevent_context *ev,
5808                                       struct cli_state *cli, uint16_t fnum,
5809                                       uint16_t level, uint32_t min_rdata,
5810                                       uint32_t max_rdata)
5811 {
5812         struct tevent_req *req, *subreq;
5813         struct cli_qfileinfo_state *state;
5814
5815         req = tevent_req_create(mem_ctx, &state, struct cli_qfileinfo_state);
5816         if (req == NULL) {
5817                 return NULL;
5818         }
5819         state->min_rdata = min_rdata;
5820         SSVAL(state->param, 0, fnum);
5821         SSVAL(state->param, 2, level);
5822         SSVAL(state->setup, 0, TRANSACT2_QFILEINFO);
5823
5824         subreq = cli_trans_send(
5825                 state,                  /* mem ctx. */
5826                 ev,                     /* event ctx. */
5827                 cli,                    /* cli_state. */
5828                 0,                      /* additional_flags2 */
5829                 SMBtrans2,              /* cmd. */
5830                 NULL,                   /* pipe name. */
5831                 -1,                     /* fid. */
5832                 0,                      /* function. */
5833                 0,                      /* flags. */
5834                 state->setup,           /* setup. */
5835                 1,                      /* num setup uint16_t words. */
5836                 0,                      /* max returned setup. */
5837                 state->param,           /* param. */
5838                 sizeof(state->param),   /* num param. */
5839                 2,                      /* max returned param. */
5840                 NULL,                   /* data. */
5841                 0,                      /* num data. */
5842                 max_rdata);             /* max returned data. */
5843
5844         if (tevent_req_nomem(subreq, req)) {
5845                 return tevent_req_post(req, ev);
5846         }
5847         tevent_req_set_callback(subreq, cli_qfileinfo_done, req);
5848         return req;
5849 }
5850
5851 static void cli_qfileinfo_done(struct tevent_req *subreq)
5852 {
5853         struct tevent_req *req = tevent_req_callback_data(
5854                 subreq, struct tevent_req);
5855         struct cli_qfileinfo_state *state = tevent_req_data(
5856                 req, struct cli_qfileinfo_state);
5857         NTSTATUS status;
5858
5859         status = cli_trans_recv(subreq, state,
5860                                 &state->recv_flags2,
5861                                 NULL, 0, NULL,
5862                                 NULL, 0, NULL,
5863                                 &state->rdata, state->min_rdata,
5864                                 &state->num_rdata);
5865         if (tevent_req_nterror(req, status)) {
5866                 return;
5867         }
5868         tevent_req_done(req);
5869 }
5870
5871 NTSTATUS cli_qfileinfo_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
5872                             uint16_t *recv_flags2,
5873                             uint8_t **rdata, uint32_t *num_rdata)
5874 {
5875         struct cli_qfileinfo_state *state = tevent_req_data(
5876                 req, struct cli_qfileinfo_state);
5877         NTSTATUS status;
5878
5879         if (tevent_req_is_nterror(req, &status)) {
5880                 return status;
5881         }
5882
5883         if (recv_flags2 != NULL) {
5884                 *recv_flags2 = state->recv_flags2;
5885         }
5886         if (rdata != NULL) {
5887                 *rdata = talloc_move(mem_ctx, &state->rdata);
5888         } else {
5889                 TALLOC_FREE(state->rdata);
5890         }
5891         if (num_rdata != NULL) {
5892                 *num_rdata = state->num_rdata;
5893         }
5894         return NT_STATUS_OK;
5895 }
5896
5897 NTSTATUS cli_qfileinfo(TALLOC_CTX *mem_ctx, struct cli_state *cli,
5898                        uint16_t fnum, uint16_t level, uint32_t min_rdata,
5899                        uint32_t max_rdata, uint16_t *recv_flags2,
5900                        uint8_t **rdata, uint32_t *num_rdata)
5901 {
5902         TALLOC_CTX *frame = talloc_stackframe();
5903         struct tevent_context *ev;
5904         struct tevent_req *req;
5905         NTSTATUS status = NT_STATUS_NO_MEMORY;
5906
5907         if (smbXcli_conn_has_async_calls(cli->conn)) {
5908                 /*
5909                  * Can't use sync call while an async call is in flight
5910                  */
5911                 status = NT_STATUS_INVALID_PARAMETER;
5912                 goto fail;
5913         }
5914         ev = samba_tevent_context_init(frame);
5915         if (ev == NULL) {
5916                 goto fail;
5917         }
5918         req = cli_qfileinfo_send(frame, ev, cli, fnum, level, min_rdata,
5919                                  max_rdata);
5920         if (req == NULL) {
5921                 goto fail;
5922         }
5923         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
5924                 goto fail;
5925         }
5926         status = cli_qfileinfo_recv(req, mem_ctx, recv_flags2, rdata, num_rdata);
5927  fail:
5928         TALLOC_FREE(frame);
5929         return status;
5930 }
5931
5932 struct cli_flush_state {
5933         uint16_t vwv[1];
5934 };
5935
5936 static void cli_flush_done(struct tevent_req *subreq);
5937
5938 struct tevent_req *cli_flush_send(TALLOC_CTX *mem_ctx,
5939                                   struct tevent_context *ev,
5940                                   struct cli_state *cli,
5941                                   uint16_t fnum)
5942 {
5943         struct tevent_req *req, *subreq;
5944         struct cli_flush_state *state;
5945
5946         req = tevent_req_create(mem_ctx, &state, struct cli_flush_state);
5947         if (req == NULL) {
5948                 return NULL;
5949         }
5950         SSVAL(state->vwv + 0, 0, fnum);
5951
5952         subreq = cli_smb_send(state, ev, cli, SMBflush, 0, 0, 1, state->vwv,
5953                               0, NULL);
5954         if (tevent_req_nomem(subreq, req)) {
5955                 return tevent_req_post(req, ev);
5956         }
5957         tevent_req_set_callback(subreq, cli_flush_done, req);
5958         return req;
5959 }
5960
5961 static void cli_flush_done(struct tevent_req *subreq)
5962 {
5963         struct tevent_req *req = tevent_req_callback_data(
5964                 subreq, struct tevent_req);
5965         NTSTATUS status;
5966
5967         status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
5968         TALLOC_FREE(subreq);
5969         if (tevent_req_nterror(req, status)) {
5970                 return;
5971         }
5972         tevent_req_done(req);
5973 }
5974
5975 NTSTATUS cli_flush_recv(struct tevent_req *req)
5976 {
5977         return tevent_req_simple_recv_ntstatus(req);
5978 }
5979
5980 NTSTATUS cli_flush(TALLOC_CTX *mem_ctx, struct cli_state *cli, uint16_t fnum)
5981 {
5982         TALLOC_CTX *frame = talloc_stackframe();
5983         struct tevent_context *ev;
5984         struct tevent_req *req;
5985         NTSTATUS status = NT_STATUS_NO_MEMORY;
5986
5987         if (smbXcli_conn_has_async_calls(cli->conn)) {
5988                 /*
5989                  * Can't use sync call while an async call is in flight
5990                  */
5991                 status = NT_STATUS_INVALID_PARAMETER;
5992                 goto fail;
5993         }
5994         ev = samba_tevent_context_init(frame);
5995         if (ev == NULL) {
5996                 goto fail;
5997         }
5998         req = cli_flush_send(frame, ev, cli, fnum);
5999         if (req == NULL) {
6000                 goto fail;
6001         }
6002         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
6003                 goto fail;
6004         }
6005         status = cli_flush_recv(req);
6006  fail:
6007         TALLOC_FREE(frame);
6008         return status;
6009 }
6010
6011 struct cli_shadow_copy_data_state {
6012         uint16_t setup[4];
6013         uint8_t *data;
6014         uint32_t num_data;
6015         bool get_names;
6016 };
6017
6018 static void cli_shadow_copy_data_done(struct tevent_req *subreq);
6019
6020 struct tevent_req *cli_shadow_copy_data_send(TALLOC_CTX *mem_ctx,
6021                                              struct tevent_context *ev,
6022                                              struct cli_state *cli,
6023                                              uint16_t fnum,
6024                                              bool get_names)
6025 {
6026         struct tevent_req *req, *subreq;
6027         struct cli_shadow_copy_data_state *state;
6028         uint32_t ret_size;
6029
6030         req = tevent_req_create(mem_ctx, &state,
6031                                 struct cli_shadow_copy_data_state);
6032         if (req == NULL) {
6033                 return NULL;
6034         }
6035         state->get_names = get_names;
6036         ret_size = get_names ? CLI_BUFFER_SIZE : 16;
6037
6038         SIVAL(state->setup + 0, 0, FSCTL_GET_SHADOW_COPY_DATA);
6039         SSVAL(state->setup + 2, 0, fnum);
6040         SCVAL(state->setup + 3, 0, 1); /* isFsctl */
6041         SCVAL(state->setup + 3, 1, 0); /* compfilter, isFlags (WSSP) */
6042
6043         subreq = cli_trans_send(
6044                 state, ev, cli, 0, SMBnttrans, NULL, 0, NT_TRANSACT_IOCTL, 0,
6045                 state->setup, ARRAY_SIZE(state->setup),
6046                 ARRAY_SIZE(state->setup),
6047                 NULL, 0, 0,
6048                 NULL, 0, ret_size);
6049         if (tevent_req_nomem(subreq, req)) {
6050                 return tevent_req_post(req, ev);
6051         }
6052         tevent_req_set_callback(subreq, cli_shadow_copy_data_done, req);
6053         return req;
6054 }
6055
6056 static void cli_shadow_copy_data_done(struct tevent_req *subreq)
6057 {
6058         struct tevent_req *req = tevent_req_callback_data(
6059                 subreq, struct tevent_req);
6060         struct cli_shadow_copy_data_state *state = tevent_req_data(
6061                 req, struct cli_shadow_copy_data_state);
6062         NTSTATUS status;
6063
6064         status = cli_trans_recv(subreq, state, NULL,
6065                                 NULL, 0, NULL, /* setup */
6066                                 NULL, 0, NULL, /* param */
6067                                 &state->data, 12, &state->num_data);
6068         TALLOC_FREE(subreq);
6069         if (tevent_req_nterror(req, status)) {
6070                 return;
6071         }
6072         tevent_req_done(req);
6073 }
6074
6075 NTSTATUS cli_shadow_copy_data_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
6076                                    char ***pnames, int *pnum_names)
6077 {
6078         struct cli_shadow_copy_data_state *state = tevent_req_data(
6079                 req, struct cli_shadow_copy_data_state);
6080         char **names = NULL;
6081         uint32_t i, num_names;
6082         uint32_t dlength;
6083         uint8_t *endp = NULL;
6084         NTSTATUS status;
6085
6086         if (tevent_req_is_nterror(req, &status)) {
6087                 return status;
6088         }
6089
6090         if (state->num_data < 16) {
6091                 return NT_STATUS_INVALID_NETWORK_RESPONSE;
6092         }
6093
6094         num_names = IVAL(state->data, 4);
6095         dlength = IVAL(state->data, 8);
6096
6097         if (num_names > 0x7FFFFFFF) {
6098                 return NT_STATUS_INVALID_NETWORK_RESPONSE;
6099         }
6100
6101         if (!state->get_names) {
6102                 *pnum_names = (int)num_names;
6103                 return NT_STATUS_OK;
6104         }
6105
6106         if (dlength + 12 < 12) {
6107                 return NT_STATUS_INVALID_NETWORK_RESPONSE;
6108         }
6109         if (dlength + 12 > state->num_data) {
6110                 return NT_STATUS_INVALID_NETWORK_RESPONSE;
6111         }
6112         if (state->num_data + (2 * sizeof(SHADOW_COPY_LABEL)) <
6113                         state->num_data) {
6114                 return NT_STATUS_INVALID_NETWORK_RESPONSE;
6115         }
6116
6117         names = talloc_array(mem_ctx, char *, num_names);
6118         if (names == NULL) {
6119                 return NT_STATUS_NO_MEMORY;
6120         }
6121
6122         endp = state->data + state->num_data;
6123
6124         for (i=0; i<num_names; i++) {
6125                 bool ret;
6126                 uint8_t *src;
6127                 size_t converted_size;
6128
6129                 src = state->data + 12 + i * 2 * sizeof(SHADOW_COPY_LABEL);
6130
6131                 if (src + (2 * sizeof(SHADOW_COPY_LABEL)) > endp) {
6132                         return NT_STATUS_INVALID_NETWORK_RESPONSE;
6133                 }
6134
6135                 ret = convert_string_talloc(
6136                         names, CH_UTF16LE, CH_UNIX,
6137                         src, 2 * sizeof(SHADOW_COPY_LABEL),
6138                         &names[i], &converted_size);
6139                 if (!ret) {
6140                         TALLOC_FREE(names);
6141                         return NT_STATUS_INVALID_NETWORK_RESPONSE;
6142                 }
6143         }
6144         *pnum_names = (int)num_names;
6145         *pnames = names;
6146         return NT_STATUS_OK;
6147 }
6148
6149 NTSTATUS cli_shadow_copy_data(TALLOC_CTX *mem_ctx, struct cli_state *cli,
6150                               uint16_t fnum, bool get_names,
6151                               char ***pnames, int *pnum_names)
6152 {
6153         TALLOC_CTX *frame = NULL;
6154         struct tevent_context *ev;
6155         struct tevent_req *req;
6156         NTSTATUS status = NT_STATUS_NO_MEMORY;
6157
6158         if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
6159                 return cli_smb2_shadow_copy_data(mem_ctx,
6160                                         cli,
6161                                         fnum,
6162                                         get_names,
6163                                         pnames,
6164                                         pnum_names);
6165         }
6166
6167         frame = talloc_stackframe();
6168
6169         if (smbXcli_conn_has_async_calls(cli->conn)) {
6170                 /*
6171                  * Can't use sync call while an async call is in flight
6172                  */
6173                 status = NT_STATUS_INVALID_PARAMETER;
6174                 goto fail;
6175         }
6176         ev = samba_tevent_context_init(frame);
6177         if (ev == NULL) {
6178                 goto fail;
6179         }
6180         req = cli_shadow_copy_data_send(frame, ev, cli, fnum, get_names);
6181         if (req == NULL) {
6182                 goto fail;
6183         }
6184         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
6185                 goto fail;
6186         }
6187         status = cli_shadow_copy_data_recv(req, mem_ctx, pnames, pnum_names);
6188  fail:
6189         TALLOC_FREE(frame);
6190         return status;
6191 }