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