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