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