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