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