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