Fix bug 6726 - Filename length overwrites oplock request field in cli_nt_create().
[ira/wip.git] / source3 / libsmb / clifile.c
1 /* 
2    Unix SMB/CIFS implementation.
3    client file operations
4    Copyright (C) Andrew Tridgell 1994-1998
5    Copyright (C) Jeremy Allison 2001-2009
6    
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 3 of the License, or
10    (at your option) any later version.
11    
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16    
17    You should have received a copy of the GNU General Public License
18    along with this program.  If not, see <http://www.gnu.org/licenses/>.
19 */
20
21 #include "includes.h"
22
23 /***********************************************************
24  Common function for pushing stings, used by smb_bytes_push_str()
25  and trans_bytes_push_str(). Only difference is the align_odd
26  parameter setting.
27 ***********************************************************/
28
29 static uint8_t *internal_bytes_push_str(uint8_t *buf, bool ucs2,
30                                 const char *str, size_t str_len,
31                                 bool align_odd,
32                                 size_t *pconverted_size)
33 {
34         size_t buflen;
35         char *converted;
36         size_t converted_size;
37
38         if (buf == NULL) {
39                 return NULL;
40         }
41
42         buflen = talloc_get_size(buf);
43
44         if (align_odd && ucs2 && (buflen % 2 == 0)) {
45                 /*
46                  * We're pushing into an SMB buffer, align odd
47                  */
48                 buf = TALLOC_REALLOC_ARRAY(NULL, buf, uint8_t, buflen + 1);
49                 if (buf == NULL) {
50                         return NULL;
51                 }
52                 buf[buflen] = '\0';
53                 buflen += 1;
54         }
55
56         if (!convert_string_talloc(talloc_tos(), CH_UNIX,
57                                    ucs2 ? CH_UTF16LE : CH_DOS,
58                                    str, str_len, &converted,
59                                    &converted_size, true)) {
60                 return NULL;
61         }
62
63         buf = TALLOC_REALLOC_ARRAY(NULL, buf, uint8_t,
64                                    buflen + converted_size);
65         if (buf == NULL) {
66                 TALLOC_FREE(converted);
67                 return NULL;
68         }
69
70         memcpy(buf + buflen, converted, converted_size);
71
72         TALLOC_FREE(converted);
73
74         if (pconverted_size) {
75                 *pconverted_size = converted_size;
76         }
77
78         return buf;
79 }
80
81 /***********************************************************
82  Push a string into an SMB buffer, with odd byte alignment
83  if it's a UCS2 string.
84 ***********************************************************/
85
86 uint8_t *smb_bytes_push_str(uint8_t *buf, bool ucs2,
87                             const char *str, size_t str_len,
88                             size_t *pconverted_size)
89 {
90         return internal_bytes_push_str(buf, ucs2, str, str_len,
91                         true, pconverted_size);
92 }
93
94 /***********************************************************
95  Same as smb_bytes_push_str(), but without the odd byte
96  align for ucs2 (we're pushing into a param or data block).
97  static for now, although this will probably change when
98  other modules use async trans calls.
99 ***********************************************************/
100
101 static uint8_t *trans2_bytes_push_str(uint8_t *buf, bool ucs2,
102                             const char *str, size_t str_len,
103                             size_t *pconverted_size)
104 {
105         return internal_bytes_push_str(buf, ucs2, str, str_len,
106                         false, pconverted_size);
107 }
108
109 /****************************************************************************
110  Hard/Symlink a file (UNIX extensions).
111  Creates new name (sym)linked to oldname.
112 ****************************************************************************/
113
114 struct link_state {
115         uint16_t setup;
116         uint8_t *param;
117         uint8_t *data;
118 };
119
120 static void cli_posix_link_internal_done(struct tevent_req *subreq)
121 {
122         struct tevent_req *req = tevent_req_callback_data(
123                                 subreq, struct tevent_req);
124         struct link_state *state = tevent_req_data(req, struct link_state);
125         NTSTATUS status;
126
127         status = cli_trans_recv(subreq, state, NULL, NULL, NULL, NULL, NULL, NULL);
128         TALLOC_FREE(subreq);
129         if (!NT_STATUS_IS_OK(status)) {
130                 tevent_req_nterror(req, status);
131                 return;
132         }
133         tevent_req_done(req);
134 }
135
136 static struct tevent_req *cli_posix_link_internal_send(TALLOC_CTX *mem_ctx,
137                                         struct event_context *ev,
138                                         struct cli_state *cli,
139                                         const char *oldname,
140                                         const char *newname,
141                                         bool hardlink)
142 {
143         struct tevent_req *req = NULL, *subreq = NULL;
144         struct link_state *state = NULL;
145
146         req = tevent_req_create(mem_ctx, &state, struct link_state);
147         if (req == NULL) {
148                 return NULL;
149         }
150
151         /* Setup setup word. */
152         SSVAL(&state->setup, 0, TRANSACT2_SETPATHINFO);
153
154         /* Setup param array. */
155         state->param = talloc_array(state, uint8_t, 6);
156         if (tevent_req_nomem(state->param, req)) {
157                 return tevent_req_post(req, ev);
158         }
159         memset(state->param, '\0', 6);
160         SSVAL(state->param,0,hardlink ? SMB_SET_FILE_UNIX_HLINK : SMB_SET_FILE_UNIX_LINK);
161
162         state->param = trans2_bytes_push_str(state->param, cli_ucs2(cli), newname,
163                                    strlen(newname)+1, NULL);
164
165         if (tevent_req_nomem(state->param, req)) {
166                 return tevent_req_post(req, ev);
167         }
168
169         /* Setup data array. */
170         state->data = talloc_array(state, uint8_t, 0);
171         if (tevent_req_nomem(state->data, req)) {
172                 return tevent_req_post(req, ev);
173         }
174         state->data = trans2_bytes_push_str(state->data, cli_ucs2(cli), oldname,
175                                    strlen(oldname)+1, NULL);
176
177         subreq = cli_trans_send(state,                  /* mem ctx. */
178                                 ev,                     /* event ctx. */
179                                 cli,                    /* cli_state. */
180                                 SMBtrans2,              /* cmd. */
181                                 NULL,                   /* pipe name. */
182                                 -1,                     /* fid. */
183                                 0,                      /* function. */
184                                 0,                      /* flags. */
185                                 &state->setup,          /* setup. */
186                                 1,                      /* num setup uint16_t words. */
187                                 0,                      /* max returned setup. */
188                                 state->param,           /* param. */
189                                 talloc_get_size(state->param),  /* num param. */
190                                 2,                      /* max returned param. */
191                                 state->data,            /* data. */
192                                 talloc_get_size(state->data),   /* num data. */
193                                 0);                     /* max returned data. */
194
195         if (tevent_req_nomem(subreq, req)) {
196                 return tevent_req_post(req, ev);
197         }
198         tevent_req_set_callback(subreq, cli_posix_link_internal_done, req);
199         return req;
200 }
201
202 /****************************************************************************
203  Symlink a file (UNIX extensions).
204 ****************************************************************************/
205
206 struct tevent_req *cli_posix_symlink_send(TALLOC_CTX *mem_ctx,
207                                         struct event_context *ev,
208                                         struct cli_state *cli,
209                                         const char *oldname,
210                                         const char *newname)
211 {
212         return cli_posix_link_internal_send(mem_ctx, ev, cli,
213                         oldname, newname, false);
214 }
215
216 NTSTATUS cli_posix_symlink_recv(struct tevent_req *req)
217 {
218         NTSTATUS status;
219
220         if (tevent_req_is_nterror(req, &status)) {
221                 return status;
222         }
223         return NT_STATUS_OK;
224 }
225
226 NTSTATUS cli_posix_symlink(struct cli_state *cli,
227                         const char *oldname,
228                         const char *newname)
229 {
230         TALLOC_CTX *frame = talloc_stackframe();
231         struct event_context *ev = NULL;
232         struct tevent_req *req = NULL;
233         NTSTATUS status = NT_STATUS_OK;
234
235         if (cli_has_async_calls(cli)) {
236                 /*
237                  * Can't use sync call while an async call is in flight
238                  */
239                 status = NT_STATUS_INVALID_PARAMETER;
240                 goto fail;
241         }
242
243         ev = event_context_init(frame);
244         if (ev == NULL) {
245                 status = NT_STATUS_NO_MEMORY;
246                 goto fail;
247         }
248
249         req = cli_posix_symlink_send(frame,
250                                 ev,
251                                 cli,
252                                 oldname,
253                                 newname);
254         if (req == NULL) {
255                 status = NT_STATUS_NO_MEMORY;
256                 goto fail;
257         }
258
259         if (!tevent_req_poll(req, ev)) {
260                 status = map_nt_error_from_unix(errno);
261                 goto fail;
262         }
263
264         status = cli_posix_symlink_recv(req);
265
266  fail:
267         TALLOC_FREE(frame);
268         if (!NT_STATUS_IS_OK(status)) {
269                 cli_set_error(cli, status);
270         }
271         return status;
272 }
273
274 /****************************************************************************
275  Read a POSIX symlink.
276 ****************************************************************************/
277
278 struct readlink_state {
279         uint16_t setup;
280         uint8_t *param;
281         uint8_t *data;
282         uint32_t num_data;
283 };
284
285 static void cli_posix_readlink_done(struct tevent_req *subreq)
286 {
287         struct tevent_req *req = tevent_req_callback_data(
288                                 subreq, struct tevent_req);
289         struct readlink_state *state = tevent_req_data(req, struct readlink_state);
290         NTSTATUS status;
291
292         status = cli_trans_recv(subreq, state, NULL, NULL, NULL, NULL,
293                         &state->data, &state->num_data);
294         TALLOC_FREE(subreq);
295         if (!NT_STATUS_IS_OK(status)) {
296                 tevent_req_nterror(req, status);
297                 return;
298         }
299         if (state->num_data == 0) {
300                 tevent_req_nterror(req, NT_STATUS_DATA_ERROR);
301                 return;
302         }
303         if (state->data[state->num_data-1] != '\0') {
304                 tevent_req_nterror(req, NT_STATUS_DATA_ERROR);
305                 return;
306         }
307         tevent_req_done(req);
308 }
309
310 struct tevent_req *cli_posix_readlink_send(TALLOC_CTX *mem_ctx,
311                                         struct event_context *ev,
312                                         struct cli_state *cli,
313                                         const char *fname,
314                                         size_t len)
315 {
316         struct tevent_req *req = NULL, *subreq = NULL;
317         struct readlink_state *state = NULL;
318         uint32_t maxbytelen = (uint32_t)(cli_ucs2(cli) ? len*3 : len);
319
320         if (maxbytelen < len) {
321                 return NULL;
322         }
323
324         req = tevent_req_create(mem_ctx, &state, struct readlink_state);
325         if (req == NULL) {
326                 return NULL;
327         }
328
329         /* Setup setup word. */
330         SSVAL(&state->setup, 0, TRANSACT2_QPATHINFO);
331
332         /* Setup param array. */
333         state->param = talloc_array(state, uint8_t, 6);
334         if (tevent_req_nomem(state->param, req)) {
335                 return tevent_req_post(req, ev);
336         }
337         memset(state->param, '\0', 6);
338         SSVAL(state->param,0,SMB_QUERY_FILE_UNIX_LINK);
339
340         state->param = trans2_bytes_push_str(state->param, cli_ucs2(cli), fname,
341                                    strlen(fname)+1, NULL);
342
343         if (tevent_req_nomem(state->param, req)) {
344                 return tevent_req_post(req, ev);
345         }
346
347         subreq = cli_trans_send(state,                  /* mem ctx. */
348                                 ev,                     /* event ctx. */
349                                 cli,                    /* cli_state. */
350                                 SMBtrans2,              /* cmd. */
351                                 NULL,                   /* pipe name. */
352                                 -1,                     /* fid. */
353                                 0,                      /* function. */
354                                 0,                      /* flags. */
355                                 &state->setup,          /* setup. */
356                                 1,                      /* num setup uint16_t words. */
357                                 0,                      /* max returned setup. */
358                                 state->param,           /* param. */
359                                 talloc_get_size(state->param),  /* num param. */
360                                 2,                      /* max returned param. */
361                                 NULL,                   /* data. */
362                                 0,                      /* num data. */
363                                 maxbytelen);            /* max returned data. */
364
365         if (tevent_req_nomem(subreq, req)) {
366                 return tevent_req_post(req, ev);
367         }
368         tevent_req_set_callback(subreq, cli_posix_readlink_done, req);
369         return req;
370 }
371
372 NTSTATUS cli_posix_readlink_recv(struct tevent_req *req, struct cli_state *cli,
373                                 char *retpath, size_t len)
374 {
375         NTSTATUS status;
376         char *converted = NULL;
377         size_t converted_size = 0;
378         struct readlink_state *state = tevent_req_data(req, struct readlink_state);
379
380         if (tevent_req_is_nterror(req, &status)) {
381                 return status;
382         }
383         /* The returned data is a pushed string, not raw data. */
384         if (!convert_string_talloc(state,
385                                 cli_ucs2(cli) ? CH_UTF16LE : CH_DOS, 
386                                 CH_UNIX,
387                                 state->data,
388                                 state->num_data,
389                                 &converted,
390                                 &converted_size,
391                                 true)) {
392                 return NT_STATUS_NO_MEMORY;
393         }
394
395         len = MIN(len,converted_size);
396         if (len == 0) {
397                 return NT_STATUS_DATA_ERROR;
398         }
399         memcpy(retpath, converted, len);
400         return NT_STATUS_OK;
401 }
402
403 NTSTATUS cli_posix_readlink(struct cli_state *cli, const char *fname,
404                                 char *linkpath, size_t len)
405 {
406         TALLOC_CTX *frame = talloc_stackframe();
407         struct event_context *ev = NULL;
408         struct tevent_req *req = NULL;
409         NTSTATUS status = NT_STATUS_OK;
410
411         if (cli_has_async_calls(cli)) {
412                 /*
413                  * Can't use sync call while an async call is in flight
414                  */
415                 status = NT_STATUS_INVALID_PARAMETER;
416                 goto fail;
417         }
418
419         ev = event_context_init(frame);
420         if (ev == NULL) {
421                 status = NT_STATUS_NO_MEMORY;
422                 goto fail;
423         }
424
425         /* Len is in bytes, we need it in UCS2 units. */
426         if (2*len < len) {
427                 status = NT_STATUS_INVALID_PARAMETER;
428                 goto fail;
429         }
430
431         req = cli_posix_readlink_send(frame,
432                                 ev,
433                                 cli,
434                                 fname,
435                                 len);
436         if (req == NULL) {
437                 status = NT_STATUS_NO_MEMORY;
438                 goto fail;
439         }
440
441         if (!tevent_req_poll(req, ev)) {
442                 status = map_nt_error_from_unix(errno);
443                 goto fail;
444         }
445
446         status = cli_posix_readlink_recv(req, cli, linkpath, len);
447
448  fail:
449         TALLOC_FREE(frame);
450         if (!NT_STATUS_IS_OK(status)) {
451                 cli_set_error(cli, status);
452         }
453         return status;
454 }
455
456 /****************************************************************************
457  Hard link a file (UNIX extensions).
458 ****************************************************************************/
459
460 struct tevent_req *cli_posix_hardlink_send(TALLOC_CTX *mem_ctx,
461                                         struct event_context *ev,
462                                         struct cli_state *cli,
463                                         const char *oldname,
464                                         const char *newname)
465 {
466         return cli_posix_link_internal_send(mem_ctx, ev, cli,
467                         oldname, newname, true);
468 }
469
470 NTSTATUS cli_posix_hardlink_recv(struct tevent_req *req)
471 {
472         NTSTATUS status;
473
474         if (tevent_req_is_nterror(req, &status)) {
475                 return status;
476         }
477         return NT_STATUS_OK;
478 }
479
480 NTSTATUS cli_posix_hardlink(struct cli_state *cli,
481                         const char *oldname,
482                         const char *newname)
483 {
484         TALLOC_CTX *frame = talloc_stackframe();
485         struct event_context *ev = NULL;
486         struct tevent_req *req = NULL;
487         NTSTATUS status = NT_STATUS_OK;
488
489         if (cli_has_async_calls(cli)) {
490                 /*
491                  * Can't use sync call while an async call is in flight
492                  */
493                 status = NT_STATUS_INVALID_PARAMETER;
494                 goto fail;
495         }
496
497         ev = event_context_init(frame);
498         if (ev == NULL) {
499                 status = NT_STATUS_NO_MEMORY;
500                 goto fail;
501         }
502
503         req = cli_posix_hardlink_send(frame,
504                                 ev,
505                                 cli,
506                                 oldname,
507                                 newname);
508         if (req == NULL) {
509                 status = NT_STATUS_NO_MEMORY;
510                 goto fail;
511         }
512
513         if (!tevent_req_poll(req, ev)) {
514                 status = map_nt_error_from_unix(errno);
515                 goto fail;
516         }
517
518         status = cli_posix_hardlink_recv(req);
519
520  fail:
521         TALLOC_FREE(frame);
522         if (!NT_STATUS_IS_OK(status)) {
523                 cli_set_error(cli, status);
524         }
525         return status;
526 }
527
528 /****************************************************************************
529  Map standard UNIX permissions onto wire representations.
530 ****************************************************************************/
531
532 uint32_t unix_perms_to_wire(mode_t perms)
533 {
534         unsigned int ret = 0;
535
536         ret |= ((perms & S_IXOTH) ?  UNIX_X_OTH : 0);
537         ret |= ((perms & S_IWOTH) ?  UNIX_W_OTH : 0);
538         ret |= ((perms & S_IROTH) ?  UNIX_R_OTH : 0);
539         ret |= ((perms & S_IXGRP) ?  UNIX_X_GRP : 0);
540         ret |= ((perms & S_IWGRP) ?  UNIX_W_GRP : 0);
541         ret |= ((perms & S_IRGRP) ?  UNIX_R_GRP : 0);
542         ret |= ((perms & S_IXUSR) ?  UNIX_X_USR : 0);
543         ret |= ((perms & S_IWUSR) ?  UNIX_W_USR : 0);
544         ret |= ((perms & S_IRUSR) ?  UNIX_R_USR : 0);
545 #ifdef S_ISVTX
546         ret |= ((perms & S_ISVTX) ?  UNIX_STICKY : 0);
547 #endif
548 #ifdef S_ISGID
549         ret |= ((perms & S_ISGID) ?  UNIX_SET_GID : 0);
550 #endif
551 #ifdef S_ISUID
552         ret |= ((perms & S_ISUID) ?  UNIX_SET_UID : 0);
553 #endif
554         return ret;
555 }
556
557 /****************************************************************************
558  Map wire permissions to standard UNIX.
559 ****************************************************************************/
560
561 mode_t wire_perms_to_unix(uint32_t perms)
562 {
563         mode_t ret = (mode_t)0;
564
565         ret |= ((perms & UNIX_X_OTH) ? S_IXOTH : 0);
566         ret |= ((perms & UNIX_W_OTH) ? S_IWOTH : 0);
567         ret |= ((perms & UNIX_R_OTH) ? S_IROTH : 0);
568         ret |= ((perms & UNIX_X_GRP) ? S_IXGRP : 0);
569         ret |= ((perms & UNIX_W_GRP) ? S_IWGRP : 0);
570         ret |= ((perms & UNIX_R_GRP) ? S_IRGRP : 0);
571         ret |= ((perms & UNIX_X_USR) ? S_IXUSR : 0);
572         ret |= ((perms & UNIX_W_USR) ? S_IWUSR : 0);
573         ret |= ((perms & UNIX_R_USR) ? S_IRUSR : 0);
574 #ifdef S_ISVTX
575         ret |= ((perms & UNIX_STICKY) ? S_ISVTX : 0);
576 #endif
577 #ifdef S_ISGID
578         ret |= ((perms & UNIX_SET_GID) ? S_ISGID : 0);
579 #endif
580 #ifdef S_ISUID
581         ret |= ((perms & UNIX_SET_UID) ? S_ISUID : 0);
582 #endif
583         return ret;
584 }
585
586 /****************************************************************************
587  Return the file type from the wire filetype for UNIX extensions.
588 ****************************************************************************/
589
590 static mode_t unix_filetype_from_wire(uint32_t wire_type)
591 {
592         switch (wire_type) {
593                 case UNIX_TYPE_FILE:
594                         return S_IFREG;
595                 case UNIX_TYPE_DIR:
596                         return S_IFDIR;
597 #ifdef S_IFLNK
598                 case UNIX_TYPE_SYMLINK:
599                         return S_IFLNK;
600 #endif
601 #ifdef S_IFCHR
602                 case UNIX_TYPE_CHARDEV:
603                         return S_IFCHR;
604 #endif
605 #ifdef S_IFBLK
606                 case UNIX_TYPE_BLKDEV:
607                         return S_IFBLK;
608 #endif
609 #ifdef S_IFIFO
610                 case UNIX_TYPE_FIFO:
611                         return S_IFIFO;
612 #endif
613 #ifdef S_IFSOCK
614                 case UNIX_TYPE_SOCKET:
615                         return S_IFSOCK;
616 #endif
617                 default:
618                         return (mode_t)0;
619         }
620 }
621
622 /****************************************************************************
623  Do a POSIX getfacl (UNIX extensions).
624 ****************************************************************************/
625
626 struct getfacl_state {
627         uint16_t setup;
628         uint8_t *param;
629         uint32_t num_data;
630         uint8_t *data;
631 };
632
633 static void cli_posix_getfacl_done(struct tevent_req *subreq)
634 {
635         struct tevent_req *req = tevent_req_callback_data(
636                                 subreq, struct tevent_req);
637         struct getfacl_state *state = tevent_req_data(req, struct getfacl_state);
638         NTSTATUS status;
639
640         status = cli_trans_recv(subreq, state, NULL, NULL, NULL, NULL,
641                         &state->data, &state->num_data);
642         TALLOC_FREE(subreq);
643         if (!NT_STATUS_IS_OK(status)) {
644                 tevent_req_nterror(req, status);
645                 return;
646         }
647         tevent_req_done(req);
648 }
649
650 struct tevent_req *cli_posix_getfacl_send(TALLOC_CTX *mem_ctx,
651                                         struct event_context *ev,
652                                         struct cli_state *cli,
653                                         const char *fname)
654 {
655         struct tevent_req *req = NULL, *subreq = NULL;
656         struct link_state *state = NULL;
657
658         req = tevent_req_create(mem_ctx, &state, struct getfacl_state);
659         if (req == NULL) {
660                 return NULL;
661         }
662
663         /* Setup setup word. */
664         SSVAL(&state->setup, 0, TRANSACT2_QPATHINFO);
665
666         /* Setup param array. */
667         state->param = talloc_array(state, uint8_t, 6);
668         if (tevent_req_nomem(state->param, req)) {
669                 return tevent_req_post(req, ev);
670         }
671         memset(state->param, '\0', 6);
672         SSVAL(state->param, 0, SMB_QUERY_POSIX_ACL);
673
674         state->param = trans2_bytes_push_str(state->param, cli_ucs2(cli), fname,
675                                    strlen(fname)+1, NULL);
676
677         if (tevent_req_nomem(state->param, req)) {
678                 return tevent_req_post(req, ev);
679         }
680
681         subreq = cli_trans_send(state,                  /* mem ctx. */
682                                 ev,                     /* event ctx. */
683                                 cli,                    /* cli_state. */
684                                 SMBtrans2,              /* cmd. */
685                                 NULL,                   /* pipe name. */
686                                 -1,                     /* fid. */
687                                 0,                      /* function. */
688                                 0,                      /* flags. */
689                                 &state->setup,          /* setup. */
690                                 1,                      /* num setup uint16_t words. */
691                                 0,                      /* max returned setup. */
692                                 state->param,           /* param. */
693                                 talloc_get_size(state->param),  /* num param. */
694                                 2,                      /* max returned param. */
695                                 NULL,                   /* data. */
696                                 0,                      /* num data. */
697                                 cli->max_xmit);         /* max returned data. */
698
699         if (tevent_req_nomem(subreq, req)) {
700                 return tevent_req_post(req, ev);
701         }
702         tevent_req_set_callback(subreq, cli_posix_getfacl_done, req);
703         return req;
704 }
705
706 NTSTATUS cli_posix_getfacl_recv(struct tevent_req *req,
707                                 TALLOC_CTX *mem_ctx,
708                                 size_t *prb_size,
709                                 char **retbuf)
710 {
711         struct getfacl_state *state = tevent_req_data(req, struct getfacl_state);
712         NTSTATUS status;
713
714         if (tevent_req_is_nterror(req, &status)) {
715                 return status;
716         }
717         *prb_size = (size_t)state->num_data;
718         *retbuf = (char *)talloc_move(mem_ctx, &state->data);
719         return NT_STATUS_OK;
720 }
721
722 NTSTATUS cli_posix_getfacl(struct cli_state *cli,
723                         const char *fname,
724                         TALLOC_CTX *mem_ctx,
725                         size_t *prb_size,
726                         char **retbuf)
727 {
728         TALLOC_CTX *frame = talloc_stackframe();
729         struct event_context *ev = NULL;
730         struct tevent_req *req = NULL;
731         NTSTATUS status = NT_STATUS_OK;
732
733         if (cli_has_async_calls(cli)) {
734                 /*
735                  * Can't use sync call while an async call is in flight
736                  */
737                 status = NT_STATUS_INVALID_PARAMETER;
738                 goto fail;
739         }
740
741         ev = event_context_init(frame);
742         if (ev == NULL) {
743                 status = NT_STATUS_NO_MEMORY;
744                 goto fail;
745         }
746
747         req = cli_posix_getfacl_send(frame,
748                                 ev,
749                                 cli,
750                                 fname);
751         if (req == NULL) {
752                 status = NT_STATUS_NO_MEMORY;
753                 goto fail;
754         }
755
756         if (!tevent_req_poll(req, ev)) {
757                 status = map_nt_error_from_unix(errno);
758                 goto fail;
759         }
760
761         status = cli_posix_getfacl_recv(req, mem_ctx, prb_size, retbuf);
762
763  fail:
764         TALLOC_FREE(frame);
765         if (!NT_STATUS_IS_OK(status)) {
766                 cli_set_error(cli, status);
767         }
768         return status;
769 }
770
771 /****************************************************************************
772  Stat a file (UNIX extensions).
773 ****************************************************************************/
774
775 struct stat_state {
776         uint16_t setup;
777         uint8_t *param;
778         uint32_t num_data;
779         uint8_t *data;
780 };
781
782 static void cli_posix_stat_done(struct tevent_req *subreq)
783 {
784         struct tevent_req *req = tevent_req_callback_data(
785                                 subreq, struct tevent_req);
786         struct stat_state *state = tevent_req_data(req, struct stat_state);
787         NTSTATUS status;
788
789         status = cli_trans_recv(subreq, state, NULL, NULL, NULL, NULL,
790                         &state->data, &state->num_data);
791         TALLOC_FREE(subreq);
792         if (!NT_STATUS_IS_OK(status)) {
793                 tevent_req_nterror(req, status);
794                 return;
795         }
796         tevent_req_done(req);
797 }
798
799 struct tevent_req *cli_posix_stat_send(TALLOC_CTX *mem_ctx,
800                                         struct event_context *ev,
801                                         struct cli_state *cli,
802                                         const char *fname)
803 {
804         struct tevent_req *req = NULL, *subreq = NULL;
805         struct stat_state *state = NULL;
806
807         req = tevent_req_create(mem_ctx, &state, struct stat_state);
808         if (req == NULL) {
809                 return NULL;
810         }
811
812         /* Setup setup word. */
813         SSVAL(&state->setup, 0, TRANSACT2_QPATHINFO);
814
815         /* Setup param array. */
816         state->param = talloc_array(state, uint8_t, 6);
817         if (tevent_req_nomem(state->param, req)) {
818                 return tevent_req_post(req, ev);
819         }
820         memset(state->param, '\0', 6);
821         SSVAL(state->param, 0, SMB_QUERY_FILE_UNIX_BASIC);
822
823         state->param = trans2_bytes_push_str(state->param, cli_ucs2(cli), fname,
824                                    strlen(fname)+1, NULL);
825
826         if (tevent_req_nomem(state->param, req)) {
827                 return tevent_req_post(req, ev);
828         }
829
830         subreq = cli_trans_send(state,                  /* mem ctx. */
831                                 ev,                     /* event ctx. */
832                                 cli,                    /* cli_state. */
833                                 SMBtrans2,              /* cmd. */
834                                 NULL,                   /* pipe name. */
835                                 -1,                     /* fid. */
836                                 0,                      /* function. */
837                                 0,                      /* flags. */
838                                 &state->setup,          /* setup. */
839                                 1,                      /* num setup uint16_t words. */
840                                 0,                      /* max returned setup. */
841                                 state->param,           /* param. */
842                                 talloc_get_size(state->param),  /* num param. */
843                                 2,                      /* max returned param. */
844                                 NULL,                   /* data. */
845                                 0,                      /* num data. */
846                                 96);                    /* max returned data. */
847
848         if (tevent_req_nomem(subreq, req)) {
849                 return tevent_req_post(req, ev);
850         }
851         tevent_req_set_callback(subreq, cli_posix_stat_done, req);
852         return req;
853 }
854
855 NTSTATUS cli_posix_stat_recv(struct tevent_req *req,
856                                 SMB_STRUCT_STAT *sbuf)
857 {
858         struct stat_state *state = tevent_req_data(req, struct stat_state);
859         NTSTATUS status;
860
861         if (tevent_req_is_nterror(req, &status)) {
862                 return status;
863         }
864
865         if (state->num_data != 96) {
866                 return NT_STATUS_DATA_ERROR;
867         }
868
869         sbuf->st_ex_size = IVAL2_TO_SMB_BIG_UINT(state->data,0);     /* total size, in bytes */
870         sbuf->st_ex_blocks = IVAL2_TO_SMB_BIG_UINT(state->data,8);   /* number of blocks allocated */
871 #if defined (HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
872         sbuf->st_ex_blocks /= STAT_ST_BLOCKSIZE;
873 #else
874         /* assume 512 byte blocks */
875         sbuf->st_ex_blocks /= 512;
876 #endif
877         sbuf->st_ex_ctime = interpret_long_date((char *)(state->data + 16));    /* time of last change */
878         sbuf->st_ex_atime = interpret_long_date((char *)(state->data + 24));    /* time of last access */
879         sbuf->st_ex_mtime = interpret_long_date((char *)(state->data + 32));    /* time of last modification */
880
881         sbuf->st_ex_uid = (uid_t) IVAL(state->data,40);      /* user ID of owner */
882         sbuf->st_ex_gid = (gid_t) IVAL(state->data,48);      /* group ID of owner */
883         sbuf->st_ex_mode = unix_filetype_from_wire(IVAL(state->data, 56));
884 #if defined(HAVE_MAKEDEV)
885         {
886                 uint32_t dev_major = IVAL(state->data,60);
887                 uint32_t dev_minor = IVAL(state->data,68);
888                 sbuf->st_ex_rdev = makedev(dev_major, dev_minor);
889         }
890 #endif
891         sbuf->st_ex_ino = (SMB_INO_T)IVAL2_TO_SMB_BIG_UINT(state->data,76);      /* inode */
892         sbuf->st_ex_mode |= wire_perms_to_unix(IVAL(state->data,84));     /* protection */
893         sbuf->st_ex_nlink = IVAL(state->data,92);    /* number of hard links */
894
895         return NT_STATUS_OK;
896 }
897
898 NTSTATUS cli_posix_stat(struct cli_state *cli,
899                         const char *fname,
900                         SMB_STRUCT_STAT *sbuf)
901 {
902         TALLOC_CTX *frame = talloc_stackframe();
903         struct event_context *ev = NULL;
904         struct tevent_req *req = NULL;
905         NTSTATUS status = NT_STATUS_OK;
906
907         if (cli_has_async_calls(cli)) {
908                 /*
909                  * Can't use sync call while an async call is in flight
910                  */
911                 status = NT_STATUS_INVALID_PARAMETER;
912                 goto fail;
913         }
914
915         ev = event_context_init(frame);
916         if (ev == NULL) {
917                 status = NT_STATUS_NO_MEMORY;
918                 goto fail;
919         }
920
921         req = cli_posix_stat_send(frame,
922                                 ev,
923                                 cli,
924                                 fname);
925         if (req == NULL) {
926                 status = NT_STATUS_NO_MEMORY;
927                 goto fail;
928         }
929
930         if (!tevent_req_poll(req, ev)) {
931                 status = map_nt_error_from_unix(errno);
932                 goto fail;
933         }
934
935         status = cli_posix_stat_recv(req, sbuf);
936
937  fail:
938         TALLOC_FREE(frame);
939         if (!NT_STATUS_IS_OK(status)) {
940                 cli_set_error(cli, status);
941         }
942         return status;
943 }
944
945 /****************************************************************************
946  Chmod or chown a file internal (UNIX extensions).
947 ****************************************************************************/
948
949 struct ch_state {
950         uint16_t setup;
951         uint8_t *param;
952         uint8_t *data;
953 };
954
955 static void cli_posix_chown_chmod_internal_done(struct tevent_req *subreq)
956 {
957         struct tevent_req *req = tevent_req_callback_data(
958                                 subreq, struct tevent_req);
959         struct ch_state *state = tevent_req_data(req, struct ch_state);
960         NTSTATUS status;
961
962         status = cli_trans_recv(subreq, state, NULL, NULL, NULL, NULL, NULL, NULL);
963         TALLOC_FREE(subreq);
964         if (!NT_STATUS_IS_OK(status)) {
965                 tevent_req_nterror(req, status);
966                 return;
967         }
968         tevent_req_done(req);
969 }
970
971 static struct tevent_req *cli_posix_chown_chmod_internal_send(TALLOC_CTX *mem_ctx,
972                                         struct event_context *ev,
973                                         struct cli_state *cli,
974                                         const char *fname,
975                                         uint32_t mode,
976                                         uint32_t uid,
977                                         uint32_t gid)
978 {
979         struct tevent_req *req = NULL, *subreq = NULL;
980         struct ch_state *state = NULL;
981
982         req = tevent_req_create(mem_ctx, &state, struct ch_state);
983         if (req == NULL) {
984                 return NULL;
985         }
986
987         /* Setup setup word. */
988         SSVAL(&state->setup, 0, TRANSACT2_SETPATHINFO);
989
990         /* Setup param array. */
991         state->param = talloc_array(state, uint8_t, 6);
992         if (tevent_req_nomem(state->param, req)) {
993                 return tevent_req_post(req, ev);
994         }
995         memset(state->param, '\0', 6);
996         SSVAL(state->param,0,SMB_SET_FILE_UNIX_BASIC);
997
998         state->param = trans2_bytes_push_str(state->param, cli_ucs2(cli), fname,
999                                    strlen(fname)+1, NULL);
1000
1001         if (tevent_req_nomem(state->param, req)) {
1002                 return tevent_req_post(req, ev);
1003         }
1004
1005         /* Setup data array. */
1006         state->data = talloc_array(state, uint8_t, 100);
1007         if (tevent_req_nomem(state->data, req)) {
1008                 return tevent_req_post(req, ev);
1009         }
1010         memset(state->data, 0xff, 40); /* Set all sizes/times to no change. */
1011         memset(&state->data[40], '\0', 60);
1012         SIVAL(state->data,40,uid);
1013         SIVAL(state->data,48,gid);
1014         SIVAL(state->data,84,mode);
1015
1016         subreq = cli_trans_send(state,                  /* mem ctx. */
1017                                 ev,                     /* event ctx. */
1018                                 cli,                    /* cli_state. */
1019                                 SMBtrans2,              /* cmd. */
1020                                 NULL,                   /* pipe name. */
1021                                 -1,                     /* fid. */
1022                                 0,                      /* function. */
1023                                 0,                      /* flags. */
1024                                 &state->setup,          /* setup. */
1025                                 1,                      /* num setup uint16_t words. */
1026                                 0,                      /* max returned setup. */
1027                                 state->param,           /* param. */
1028                                 talloc_get_size(state->param),  /* num param. */
1029                                 2,                      /* max returned param. */
1030                                 state->data,            /* data. */
1031                                 talloc_get_size(state->data),   /* num data. */
1032                                 0);                     /* max returned data. */
1033
1034         if (tevent_req_nomem(subreq, req)) {
1035                 return tevent_req_post(req, ev);
1036         }
1037         tevent_req_set_callback(subreq, cli_posix_chown_chmod_internal_done, req);
1038         return req;
1039 }
1040
1041 /****************************************************************************
1042  chmod a file (UNIX extensions).
1043 ****************************************************************************/
1044
1045 struct tevent_req *cli_posix_chmod_send(TALLOC_CTX *mem_ctx,
1046                                         struct event_context *ev,
1047                                         struct cli_state *cli,
1048                                         const char *fname,
1049                                         mode_t mode)
1050 {
1051         return cli_posix_chown_chmod_internal_send(mem_ctx, ev, cli,
1052                         fname,
1053                         unix_perms_to_wire(mode),
1054                         SMB_UID_NO_CHANGE,
1055                         SMB_GID_NO_CHANGE);
1056 }
1057
1058 NTSTATUS cli_posix_chmod_recv(struct tevent_req *req)
1059 {
1060         NTSTATUS status;
1061
1062         if (tevent_req_is_nterror(req, &status)) {
1063                 return status;
1064         }
1065         return NT_STATUS_OK;
1066 }
1067
1068 NTSTATUS cli_posix_chmod(struct cli_state *cli, const char *fname, mode_t mode)
1069 {
1070         TALLOC_CTX *frame = talloc_stackframe();
1071         struct event_context *ev = NULL;
1072         struct tevent_req *req = NULL;
1073         NTSTATUS status = NT_STATUS_OK;
1074
1075         if (cli_has_async_calls(cli)) {
1076                 /*
1077                  * Can't use sync call while an async call is in flight
1078                  */
1079                 status = NT_STATUS_INVALID_PARAMETER;
1080                 goto fail;
1081         }
1082
1083         ev = event_context_init(frame);
1084         if (ev == NULL) {
1085                 status = NT_STATUS_NO_MEMORY;
1086                 goto fail;
1087         }
1088
1089         req = cli_posix_chmod_send(frame,
1090                                 ev,
1091                                 cli,
1092                                 fname,
1093                                 mode);
1094         if (req == NULL) {
1095                 status = NT_STATUS_NO_MEMORY;
1096                 goto fail;
1097         }
1098
1099         if (!tevent_req_poll(req, ev)) {
1100                 status = map_nt_error_from_unix(errno);
1101                 goto fail;
1102         }
1103
1104         status = cli_posix_chmod_recv(req);
1105
1106  fail:
1107         TALLOC_FREE(frame);
1108         if (!NT_STATUS_IS_OK(status)) {
1109                 cli_set_error(cli, status);
1110         }
1111         return status;
1112 }
1113
1114 /****************************************************************************
1115  chown a file (UNIX extensions).
1116 ****************************************************************************/
1117
1118 struct tevent_req *cli_posix_chown_send(TALLOC_CTX *mem_ctx,
1119                                         struct event_context *ev,
1120                                         struct cli_state *cli,
1121                                         const char *fname,
1122                                         uid_t uid,
1123                                         gid_t gid)
1124 {
1125         return cli_posix_chown_chmod_internal_send(mem_ctx, ev, cli,
1126                         fname,
1127                         SMB_MODE_NO_CHANGE,
1128                         (uint32_t)uid,
1129                         (uint32_t)gid);
1130 }
1131
1132 NTSTATUS cli_posix_chown_recv(struct tevent_req *req)
1133 {
1134         NTSTATUS status;
1135
1136         if (tevent_req_is_nterror(req, &status)) {
1137                 return status;
1138         }
1139         return NT_STATUS_OK;
1140 }
1141
1142 NTSTATUS cli_posix_chown(struct cli_state *cli,
1143                         const char *fname,
1144                         uid_t uid,
1145                         gid_t gid)
1146 {
1147         TALLOC_CTX *frame = talloc_stackframe();
1148         struct event_context *ev = NULL;
1149         struct tevent_req *req = NULL;
1150         NTSTATUS status = NT_STATUS_OK;
1151
1152         if (cli_has_async_calls(cli)) {
1153                 /*
1154                  * Can't use sync call while an async call is in flight
1155                  */
1156                 status = NT_STATUS_INVALID_PARAMETER;
1157                 goto fail;
1158         }
1159
1160         ev = event_context_init(frame);
1161         if (ev == NULL) {
1162                 status = NT_STATUS_NO_MEMORY;
1163                 goto fail;
1164         }
1165
1166         req = cli_posix_chown_send(frame,
1167                                 ev,
1168                                 cli,
1169                                 fname,
1170                                 uid,
1171                                 gid);
1172         if (req == NULL) {
1173                 status = NT_STATUS_NO_MEMORY;
1174                 goto fail;
1175         }
1176
1177         if (!tevent_req_poll(req, ev)) {
1178                 status = map_nt_error_from_unix(errno);
1179                 goto fail;
1180         }
1181
1182         status = cli_posix_chown_recv(req);
1183
1184  fail:
1185         TALLOC_FREE(frame);
1186         if (!NT_STATUS_IS_OK(status)) {
1187                 cli_set_error(cli, status);
1188         }
1189         return status;
1190 }
1191
1192 /****************************************************************************
1193  Rename a file.
1194 ****************************************************************************/
1195
1196 static void cli_rename_done(struct tevent_req *subreq);
1197
1198 struct cli_rename_state {
1199         uint16_t vwv[1];
1200 };
1201
1202 struct tevent_req *cli_rename_send(TALLOC_CTX *mem_ctx,
1203                                 struct event_context *ev,
1204                                 struct cli_state *cli,
1205                                 const char *fname_src,
1206                                 const char *fname_dst)
1207 {
1208         struct tevent_req *req = NULL, *subreq = NULL;
1209         struct cli_rename_state *state = NULL;
1210         uint8_t additional_flags = 0;
1211         uint8_t *bytes = NULL;
1212
1213         req = tevent_req_create(mem_ctx, &state, struct cli_rename_state);
1214         if (req == NULL) {
1215                 return NULL;
1216         }
1217
1218         SSVAL(state->vwv+0, 0, aSYSTEM | aHIDDEN | aDIR);
1219
1220         bytes = talloc_array(state, uint8_t, 1);
1221         if (tevent_req_nomem(bytes, req)) {
1222                 return tevent_req_post(req, ev);
1223         }
1224         bytes[0] = 4;
1225         bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), fname_src,
1226                                    strlen(fname_src)+1, NULL);
1227         if (tevent_req_nomem(bytes, req)) {
1228                 return tevent_req_post(req, ev);
1229         }
1230
1231         bytes = TALLOC_REALLOC_ARRAY(state, bytes, uint8_t,
1232                         talloc_get_size(bytes)+1);
1233         if (tevent_req_nomem(bytes, req)) {
1234                 return tevent_req_post(req, ev);
1235         }
1236
1237         bytes[talloc_get_size(bytes)-1] = 4;
1238         bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), fname_dst,
1239                                    strlen(fname_dst)+1, NULL);
1240         if (tevent_req_nomem(bytes, req)) {
1241                 return tevent_req_post(req, ev);
1242         }
1243
1244         subreq = cli_smb_send(state, ev, cli, SMBmv, additional_flags,
1245                               1, state->vwv, talloc_get_size(bytes), bytes);
1246         if (tevent_req_nomem(subreq, req)) {
1247                 return tevent_req_post(req, ev);
1248         }
1249         tevent_req_set_callback(subreq, cli_rename_done, req);
1250         return req;
1251 }
1252
1253 static void cli_rename_done(struct tevent_req *subreq)
1254 {
1255         struct tevent_req *req = tevent_req_callback_data(
1256                                 subreq, struct tevent_req);
1257         NTSTATUS status;
1258
1259         status = cli_smb_recv(subreq, 0, NULL, NULL, NULL, NULL);
1260         TALLOC_FREE(subreq);
1261         if (!NT_STATUS_IS_OK(status)) {
1262                 tevent_req_nterror(req, status);
1263                 return;
1264         }
1265         tevent_req_done(req);
1266 }
1267
1268 NTSTATUS cli_rename_recv(struct tevent_req *req)
1269 {
1270         return tevent_req_simple_recv_ntstatus(req);
1271 }
1272
1273 NTSTATUS cli_rename(struct cli_state *cli, const char *fname_src, const char *fname_dst)
1274 {
1275         TALLOC_CTX *frame = talloc_stackframe();
1276         struct event_context *ev;
1277         struct tevent_req *req;
1278         NTSTATUS status = NT_STATUS_OK;
1279
1280         if (cli_has_async_calls(cli)) {
1281                 /*
1282                  * Can't use sync call while an async call is in flight
1283                  */
1284                 status = NT_STATUS_INVALID_PARAMETER;
1285                 goto fail;
1286         }
1287
1288         ev = event_context_init(frame);
1289         if (ev == NULL) {
1290                 status = NT_STATUS_NO_MEMORY;
1291                 goto fail;
1292         }
1293
1294         req = cli_rename_send(frame, ev, cli, fname_src, fname_dst);
1295         if (req == NULL) {
1296                 status = NT_STATUS_NO_MEMORY;
1297                 goto fail;
1298         }
1299
1300         if (!tevent_req_poll(req, ev)) {
1301                 status = map_nt_error_from_unix(errno);
1302                 goto fail;
1303         }
1304
1305         status = cli_rename_recv(req);
1306
1307  fail:
1308         TALLOC_FREE(frame);
1309         if (!NT_STATUS_IS_OK(status)) {
1310                 cli_set_error(cli, status);
1311         }
1312         return status;
1313 }
1314
1315 /****************************************************************************
1316  NT Rename a file.
1317 ****************************************************************************/
1318
1319 static void cli_ntrename_internal_done(struct tevent_req *subreq);
1320
1321 struct cli_ntrename_internal_state {
1322         uint16_t vwv[4];
1323 };
1324
1325 static struct tevent_req *cli_ntrename_internal_send(TALLOC_CTX *mem_ctx,
1326                                 struct event_context *ev,
1327                                 struct cli_state *cli,
1328                                 const char *fname_src,
1329                                 const char *fname_dst,
1330                                 uint16_t rename_flag)
1331 {
1332         struct tevent_req *req = NULL, *subreq = NULL;
1333         struct cli_ntrename_internal_state *state = NULL;
1334         uint8_t additional_flags = 0;
1335         uint8_t *bytes = NULL;
1336
1337         req = tevent_req_create(mem_ctx, &state,
1338                                 struct cli_ntrename_internal_state);
1339         if (req == NULL) {
1340                 return NULL;
1341         }
1342
1343         SSVAL(state->vwv+0, 0 ,aSYSTEM | aHIDDEN | aDIR);
1344         SSVAL(state->vwv+1, 0, rename_flag);
1345
1346         bytes = talloc_array(state, uint8_t, 1);
1347         if (tevent_req_nomem(bytes, req)) {
1348                 return tevent_req_post(req, ev);
1349         }
1350         bytes[0] = 4;
1351         bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), fname_src,
1352                                    strlen(fname_src)+1, NULL);
1353         if (tevent_req_nomem(bytes, req)) {
1354                 return tevent_req_post(req, ev);
1355         }
1356
1357         bytes = TALLOC_REALLOC_ARRAY(state, bytes, uint8_t,
1358                         talloc_get_size(bytes)+1);
1359         if (tevent_req_nomem(bytes, req)) {
1360                 return tevent_req_post(req, ev);
1361         }
1362
1363         bytes[talloc_get_size(bytes)-1] = 4;
1364         bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), fname_dst,
1365                                    strlen(fname_dst)+1, NULL);
1366         if (tevent_req_nomem(bytes, req)) {
1367                 return tevent_req_post(req, ev);
1368         }
1369
1370         subreq = cli_smb_send(state, ev, cli, SMBntrename, additional_flags,
1371                               4, state->vwv, talloc_get_size(bytes), bytes);
1372         if (tevent_req_nomem(subreq, req)) {
1373                 return tevent_req_post(req, ev);
1374         }
1375         tevent_req_set_callback(subreq, cli_ntrename_internal_done, req);
1376         return req;
1377 }
1378
1379 static void cli_ntrename_internal_done(struct tevent_req *subreq)
1380 {
1381         struct tevent_req *req = tevent_req_callback_data(
1382                                 subreq, struct tevent_req);
1383         NTSTATUS status;
1384
1385         status = cli_smb_recv(subreq, 0, NULL, NULL, NULL, NULL);
1386         TALLOC_FREE(subreq);
1387         if (!NT_STATUS_IS_OK(status)) {
1388                 tevent_req_nterror(req, status);
1389                 return;
1390         }
1391         tevent_req_done(req);
1392 }
1393
1394 static NTSTATUS cli_ntrename_internal_recv(struct tevent_req *req)
1395 {
1396         return tevent_req_simple_recv_ntstatus(req);
1397 }
1398
1399 struct tevent_req *cli_ntrename_send(TALLOC_CTX *mem_ctx,
1400                                 struct event_context *ev,
1401                                 struct cli_state *cli,
1402                                 const char *fname_src,
1403                                 const char *fname_dst)
1404 {
1405         return cli_ntrename_internal_send(mem_ctx,
1406                                           ev,
1407                                           cli,
1408                                           fname_src,
1409                                           fname_dst,
1410                                           RENAME_FLAG_RENAME);
1411 }
1412
1413 NTSTATUS cli_ntrename_recv(struct tevent_req *req)
1414 {
1415         return cli_ntrename_internal_recv(req);
1416 }
1417
1418 NTSTATUS cli_ntrename(struct cli_state *cli, const char *fname_src, const char *fname_dst)
1419 {
1420         TALLOC_CTX *frame = talloc_stackframe();
1421         struct event_context *ev;
1422         struct tevent_req *req;
1423         NTSTATUS status = NT_STATUS_OK;
1424
1425         if (cli_has_async_calls(cli)) {
1426                 /*
1427                  * Can't use sync call while an async call is in flight
1428                  */
1429                 status = NT_STATUS_INVALID_PARAMETER;
1430                 goto fail;
1431         }
1432
1433         ev = event_context_init(frame);
1434         if (ev == NULL) {
1435                 status = NT_STATUS_NO_MEMORY;
1436                 goto fail;
1437         }
1438
1439         req = cli_ntrename_send(frame, ev, cli, fname_src, fname_dst);
1440         if (req == NULL) {
1441                 status = NT_STATUS_NO_MEMORY;
1442                 goto fail;
1443         }
1444
1445         if (!tevent_req_poll(req, ev)) {
1446                 status = map_nt_error_from_unix(errno);
1447                 goto fail;
1448         }
1449
1450         status = cli_ntrename_recv(req);
1451
1452  fail:
1453         TALLOC_FREE(frame);
1454         if (!NT_STATUS_IS_OK(status)) {
1455                 cli_set_error(cli, status);
1456         }
1457         return status;
1458 }
1459
1460 /****************************************************************************
1461  NT hardlink a file.
1462 ****************************************************************************/
1463
1464 struct tevent_req *cli_nt_hardlink_send(TALLOC_CTX *mem_ctx,
1465                                 struct event_context *ev,
1466                                 struct cli_state *cli,
1467                                 const char *fname_src,
1468                                 const char *fname_dst)
1469 {
1470         return cli_ntrename_internal_send(mem_ctx,
1471                                           ev,
1472                                           cli,
1473                                           fname_src,
1474                                           fname_dst,
1475                                           RENAME_FLAG_HARD_LINK);
1476 }
1477
1478 NTSTATUS cli_nt_hardlink_recv(struct tevent_req *req)
1479 {
1480         return cli_ntrename_internal_recv(req);
1481 }
1482
1483 NTSTATUS cli_nt_hardlink(struct cli_state *cli, const char *fname_src, const char *fname_dst)
1484 {
1485         TALLOC_CTX *frame = talloc_stackframe();
1486         struct event_context *ev;
1487         struct tevent_req *req;
1488         NTSTATUS status = NT_STATUS_OK;
1489
1490         if (cli_has_async_calls(cli)) {
1491                 /*
1492                  * Can't use sync call while an async call is in flight
1493                  */
1494                 status = NT_STATUS_INVALID_PARAMETER;
1495                 goto fail;
1496         }
1497
1498         ev = event_context_init(frame);
1499         if (ev == NULL) {
1500                 status = NT_STATUS_NO_MEMORY;
1501                 goto fail;
1502         }
1503
1504         req = cli_nt_hardlink_send(frame, ev, cli, fname_src, fname_dst);
1505         if (req == NULL) {
1506                 status = NT_STATUS_NO_MEMORY;
1507                 goto fail;
1508         }
1509
1510         if (!tevent_req_poll(req, ev)) {
1511                 status = map_nt_error_from_unix(errno);
1512                 goto fail;
1513         }
1514
1515         status = cli_nt_hardlink_recv(req);
1516
1517  fail:
1518         TALLOC_FREE(frame);
1519         if (!NT_STATUS_IS_OK(status)) {
1520                 cli_set_error(cli, status);
1521         }
1522         return status;
1523 }
1524
1525 /****************************************************************************
1526  Delete a file.
1527 ****************************************************************************/
1528
1529 static void cli_unlink_done(struct tevent_req *subreq);
1530
1531 struct cli_unlink_state {
1532         uint16_t vwv[1];
1533 };
1534
1535 struct tevent_req *cli_unlink_send(TALLOC_CTX *mem_ctx,
1536                                 struct event_context *ev,
1537                                 struct cli_state *cli,
1538                                 const char *fname,
1539                                 uint16_t mayhave_attrs)
1540 {
1541         struct tevent_req *req = NULL, *subreq = NULL;
1542         struct cli_unlink_state *state = NULL;
1543         uint8_t additional_flags = 0;
1544         uint8_t *bytes = NULL;
1545
1546         req = tevent_req_create(mem_ctx, &state, struct cli_unlink_state);
1547         if (req == NULL) {
1548                 return NULL;
1549         }
1550
1551         SSVAL(state->vwv+0, 0, mayhave_attrs);
1552
1553         bytes = talloc_array(state, uint8_t, 1);
1554         if (tevent_req_nomem(bytes, req)) {
1555                 return tevent_req_post(req, ev);
1556         }
1557         bytes[0] = 4;
1558         bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), fname,
1559                                    strlen(fname)+1, NULL);
1560
1561         if (tevent_req_nomem(bytes, req)) {
1562                 return tevent_req_post(req, ev);
1563         }
1564
1565         subreq = cli_smb_send(state, ev, cli, SMBunlink, additional_flags,
1566                                 1, state->vwv, talloc_get_size(bytes), bytes);
1567         if (tevent_req_nomem(subreq, req)) {
1568                 return tevent_req_post(req, ev);
1569         }
1570         tevent_req_set_callback(subreq, cli_unlink_done, req);
1571         return req;
1572 }
1573
1574 static void cli_unlink_done(struct tevent_req *subreq)
1575 {
1576         struct tevent_req *req = tevent_req_callback_data(
1577                 subreq, struct tevent_req);
1578         NTSTATUS status;
1579
1580         status = cli_smb_recv(subreq, 0, NULL, NULL, NULL, NULL);
1581         TALLOC_FREE(subreq);
1582         if (!NT_STATUS_IS_OK(status)) {
1583                 tevent_req_nterror(req, status);
1584                 return;
1585         }
1586         tevent_req_done(req);
1587 }
1588
1589 NTSTATUS cli_unlink_recv(struct tevent_req *req)
1590 {
1591         return tevent_req_simple_recv_ntstatus(req);
1592 }
1593
1594 NTSTATUS cli_unlink(struct cli_state *cli, const char *fname, uint16_t mayhave_attrs)
1595 {
1596         TALLOC_CTX *frame = talloc_stackframe();
1597         struct event_context *ev;
1598         struct tevent_req *req;
1599         NTSTATUS status = NT_STATUS_OK;
1600
1601         if (cli_has_async_calls(cli)) {
1602                 /*
1603                  * Can't use sync call while an async call is in flight
1604                  */
1605                 status = NT_STATUS_INVALID_PARAMETER;
1606                 goto fail;
1607         }
1608
1609         ev = event_context_init(frame);
1610         if (ev == NULL) {
1611                 status = NT_STATUS_NO_MEMORY;
1612                 goto fail;
1613         }
1614
1615         req = cli_unlink_send(frame, ev, cli, fname, mayhave_attrs);
1616         if (req == NULL) {
1617                 status = NT_STATUS_NO_MEMORY;
1618                 goto fail;
1619         }
1620
1621         if (!tevent_req_poll(req, ev)) {
1622                 status = map_nt_error_from_unix(errno);
1623                 goto fail;
1624         }
1625
1626         status = cli_unlink_recv(req);
1627
1628  fail:
1629         TALLOC_FREE(frame);
1630         if (!NT_STATUS_IS_OK(status)) {
1631                 cli_set_error(cli, status);
1632         }
1633         return status;
1634 }
1635
1636 /****************************************************************************
1637  Create a directory.
1638 ****************************************************************************/
1639
1640 static void cli_mkdir_done(struct tevent_req *subreq);
1641
1642 struct cli_mkdir_state {
1643         int dummy;
1644 };
1645
1646 struct tevent_req *cli_mkdir_send(TALLOC_CTX *mem_ctx,
1647                                   struct event_context *ev,
1648                                   struct cli_state *cli,
1649                                   const char *dname)
1650 {
1651         struct tevent_req *req = NULL, *subreq = NULL;
1652         struct cli_mkdir_state *state = NULL;
1653         uint8_t additional_flags = 0;
1654         uint8_t *bytes = NULL;
1655
1656         req = tevent_req_create(mem_ctx, &state, struct cli_mkdir_state);
1657         if (req == NULL) {
1658                 return NULL;
1659         }
1660
1661         bytes = talloc_array(state, uint8_t, 1);
1662         if (tevent_req_nomem(bytes, req)) {
1663                 return tevent_req_post(req, ev);
1664         }
1665         bytes[0] = 4;
1666         bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), dname,
1667                                    strlen(dname)+1, NULL);
1668
1669         if (tevent_req_nomem(bytes, req)) {
1670                 return tevent_req_post(req, ev);
1671         }
1672
1673         subreq = cli_smb_send(state, ev, cli, SMBmkdir, additional_flags,
1674                               0, NULL, talloc_get_size(bytes), bytes);
1675         if (tevent_req_nomem(subreq, req)) {
1676                 return tevent_req_post(req, ev);
1677         }
1678         tevent_req_set_callback(subreq, cli_mkdir_done, req);
1679         return req;
1680 }
1681
1682 static void cli_mkdir_done(struct tevent_req *subreq)
1683 {
1684         struct tevent_req *req = tevent_req_callback_data(
1685                 subreq, struct tevent_req);
1686         NTSTATUS status;
1687
1688         status = cli_smb_recv(subreq, 0, NULL, NULL, NULL, NULL);
1689         TALLOC_FREE(subreq);
1690         if (!NT_STATUS_IS_OK(status)) {
1691                 tevent_req_nterror(req, status);
1692                 return;
1693         }
1694         tevent_req_done(req);
1695 }
1696
1697 NTSTATUS cli_mkdir_recv(struct tevent_req *req)
1698 {
1699         return tevent_req_simple_recv_ntstatus(req);
1700 }
1701
1702 NTSTATUS cli_mkdir(struct cli_state *cli, const char *dname)
1703 {
1704         TALLOC_CTX *frame = talloc_stackframe();
1705         struct event_context *ev;
1706         struct tevent_req *req;
1707         NTSTATUS status = NT_STATUS_OK;
1708
1709         if (cli_has_async_calls(cli)) {
1710                 /*
1711                  * Can't use sync call while an async call is in flight
1712                  */
1713                 status = NT_STATUS_INVALID_PARAMETER;
1714                 goto fail;
1715         }
1716
1717         ev = event_context_init(frame);
1718         if (ev == NULL) {
1719                 status = NT_STATUS_NO_MEMORY;
1720                 goto fail;
1721         }
1722
1723         req = cli_mkdir_send(frame, ev, cli, dname);
1724         if (req == NULL) {
1725                 status = NT_STATUS_NO_MEMORY;
1726                 goto fail;
1727         }
1728
1729         if (!tevent_req_poll(req, ev)) {
1730                 status = map_nt_error_from_unix(errno);
1731                 goto fail;
1732         }
1733
1734         status = cli_mkdir_recv(req);
1735
1736  fail:
1737         TALLOC_FREE(frame);
1738         if (!NT_STATUS_IS_OK(status)) {
1739                 cli_set_error(cli, status);
1740         }
1741         return status;
1742 }
1743
1744 /****************************************************************************
1745  Remove a directory.
1746 ****************************************************************************/
1747
1748 static void cli_rmdir_done(struct tevent_req *subreq);
1749
1750 struct cli_rmdir_state {
1751         int dummy;
1752 };
1753
1754 struct tevent_req *cli_rmdir_send(TALLOC_CTX *mem_ctx,
1755                                   struct event_context *ev,
1756                                   struct cli_state *cli,
1757                                   const char *dname)
1758 {
1759         struct tevent_req *req = NULL, *subreq = NULL;
1760         struct cli_rmdir_state *state = NULL;
1761         uint8_t additional_flags = 0;
1762         uint8_t *bytes = NULL;
1763
1764         req = tevent_req_create(mem_ctx, &state, struct cli_rmdir_state);
1765         if (req == NULL) {
1766                 return NULL;
1767         }
1768
1769         bytes = talloc_array(state, uint8_t, 1);
1770         if (tevent_req_nomem(bytes, req)) {
1771                 return tevent_req_post(req, ev);
1772         }
1773         bytes[0] = 4;
1774         bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), dname,
1775                                    strlen(dname)+1, NULL);
1776
1777         if (tevent_req_nomem(bytes, req)) {
1778                 return tevent_req_post(req, ev);
1779         }
1780
1781         subreq = cli_smb_send(state, ev, cli, SMBrmdir, additional_flags,
1782                               0, NULL, talloc_get_size(bytes), bytes);
1783         if (tevent_req_nomem(subreq, req)) {
1784                 return tevent_req_post(req, ev);
1785         }
1786         tevent_req_set_callback(subreq, cli_rmdir_done, req);
1787         return req;
1788 }
1789
1790 static void cli_rmdir_done(struct tevent_req *subreq)
1791 {
1792         struct tevent_req *req = tevent_req_callback_data(
1793                 subreq, struct tevent_req);
1794         NTSTATUS status;
1795
1796         status = cli_smb_recv(subreq, 0, NULL, NULL, NULL, NULL);
1797         TALLOC_FREE(subreq);
1798         if (!NT_STATUS_IS_OK(status)) {
1799                 tevent_req_nterror(req, status);
1800                 return;
1801         }
1802         tevent_req_done(req);
1803 }
1804
1805 NTSTATUS cli_rmdir_recv(struct tevent_req *req)
1806 {
1807         return tevent_req_simple_recv_ntstatus(req);
1808 }
1809
1810 NTSTATUS cli_rmdir(struct cli_state *cli, const char *dname)
1811 {
1812         TALLOC_CTX *frame = talloc_stackframe();
1813         struct event_context *ev;
1814         struct tevent_req *req;
1815         NTSTATUS status = NT_STATUS_OK;
1816
1817         if (cli_has_async_calls(cli)) {
1818                 /*
1819                  * Can't use sync call while an async call is in flight
1820                  */
1821                 status = NT_STATUS_INVALID_PARAMETER;
1822                 goto fail;
1823         }
1824
1825         ev = event_context_init(frame);
1826         if (ev == NULL) {
1827                 status = NT_STATUS_NO_MEMORY;
1828                 goto fail;
1829         }
1830
1831         req = cli_rmdir_send(frame, ev, cli, dname);
1832         if (req == NULL) {
1833                 status = NT_STATUS_NO_MEMORY;
1834                 goto fail;
1835         }
1836
1837         if (!tevent_req_poll(req, ev)) {
1838                 status = map_nt_error_from_unix(errno);
1839                 goto fail;
1840         }
1841
1842         status = cli_rmdir_recv(req);
1843
1844  fail:
1845         TALLOC_FREE(frame);
1846         if (!NT_STATUS_IS_OK(status)) {
1847                 cli_set_error(cli, status);
1848         }
1849         return status;
1850 }
1851
1852 /****************************************************************************
1853  Set or clear the delete on close flag.
1854 ****************************************************************************/
1855
1856 struct doc_state {
1857         uint16_t setup;
1858         uint8_t param[6];
1859         uint8_t data[1];
1860 };
1861
1862 static void cli_nt_delete_on_close_done(struct tevent_req *subreq)
1863 {
1864         struct tevent_req *req = tevent_req_callback_data(
1865                                 subreq, struct tevent_req);
1866         struct doc_state *state = tevent_req_data(req, struct doc_state);
1867         NTSTATUS status;
1868
1869         status = cli_trans_recv(subreq, state, NULL, NULL, NULL, NULL, NULL, NULL);
1870         TALLOC_FREE(subreq);
1871         if (!NT_STATUS_IS_OK(status)) {
1872                 tevent_req_nterror(req, status);
1873                 return;
1874         }
1875         tevent_req_done(req);
1876 }
1877
1878 struct tevent_req *cli_nt_delete_on_close_send(TALLOC_CTX *mem_ctx,
1879                                         struct event_context *ev,
1880                                         struct cli_state *cli,
1881                                         uint16_t fnum,
1882                                         bool flag)
1883 {
1884         struct tevent_req *req = NULL, *subreq = NULL;
1885         struct doc_state *state = NULL;
1886
1887         req = tevent_req_create(mem_ctx, &state, struct doc_state);
1888         if (req == NULL) {
1889                 return NULL;
1890         }
1891
1892         /* Setup setup word. */
1893         SSVAL(&state->setup, 0, TRANSACT2_SETFILEINFO);
1894
1895         /* Setup param array. */
1896         SSVAL(state->param,0,fnum);
1897         SSVAL(state->param,2,SMB_SET_FILE_DISPOSITION_INFO);
1898
1899         /* Setup data array. */
1900         SCVAL(&state->data[0], 0, flag ? 1 : 0);
1901
1902         subreq = cli_trans_send(state,                  /* mem ctx. */
1903                                 ev,                     /* event ctx. */
1904                                 cli,                    /* cli_state. */
1905                                 SMBtrans2,              /* cmd. */
1906                                 NULL,                   /* pipe name. */
1907                                 -1,                     /* fid. */
1908                                 0,                      /* function. */
1909                                 0,                      /* flags. */
1910                                 &state->setup,          /* setup. */
1911                                 1,                      /* num setup uint16_t words. */
1912                                 0,                      /* max returned setup. */
1913                                 state->param,           /* param. */
1914                                 6,                      /* num param. */
1915                                 2,                      /* max returned param. */
1916                                 state->data,            /* data. */
1917                                 1,                      /* num data. */
1918                                 0);                     /* max returned data. */
1919
1920         if (tevent_req_nomem(subreq, req)) {
1921                 return tevent_req_post(req, ev);
1922         }
1923         tevent_req_set_callback(subreq, cli_nt_delete_on_close_done, req);
1924         return req;
1925 }
1926
1927 NTSTATUS cli_nt_delete_on_close_recv(struct tevent_req *req)
1928 {
1929         NTSTATUS status;
1930
1931         if (tevent_req_is_nterror(req, &status)) {
1932                 return status;
1933         }
1934         return NT_STATUS_OK;
1935 }
1936
1937 NTSTATUS cli_nt_delete_on_close(struct cli_state *cli, uint16_t fnum, bool flag)
1938 {
1939         TALLOC_CTX *frame = talloc_stackframe();
1940         struct event_context *ev = NULL;
1941         struct tevent_req *req = NULL;
1942         NTSTATUS status = NT_STATUS_OK;
1943
1944         if (cli_has_async_calls(cli)) {
1945                 /*
1946                  * Can't use sync call while an async call is in flight
1947                  */
1948                 status = NT_STATUS_INVALID_PARAMETER;
1949                 goto fail;
1950         }
1951
1952         ev = event_context_init(frame);
1953         if (ev == NULL) {
1954                 status = NT_STATUS_NO_MEMORY;
1955                 goto fail;
1956         }
1957
1958         req = cli_nt_delete_on_close_send(frame,
1959                                 ev,
1960                                 cli,
1961                                 fnum,
1962                                 flag);
1963         if (req == NULL) {
1964                 status = NT_STATUS_NO_MEMORY;
1965                 goto fail;
1966         }
1967
1968         if (!tevent_req_poll(req, ev)) {
1969                 status = map_nt_error_from_unix(errno);
1970                 goto fail;
1971         }
1972
1973         status = cli_nt_delete_on_close_recv(req);
1974
1975  fail:
1976         TALLOC_FREE(frame);
1977         if (!NT_STATUS_IS_OK(status)) {
1978                 cli_set_error(cli, status);
1979         }
1980         return status;
1981 }
1982
1983 struct cli_ntcreate_state {
1984         uint16_t vwv[24];
1985         uint16_t fnum;
1986 };
1987
1988 static void cli_ntcreate_done(struct tevent_req *subreq);
1989
1990 struct tevent_req *cli_ntcreate_send(TALLOC_CTX *mem_ctx,
1991                                      struct event_context *ev,
1992                                      struct cli_state *cli,
1993                                      const char *fname,
1994                                      uint32_t CreatFlags,
1995                                      uint32_t DesiredAccess,
1996                                      uint32_t FileAttributes,
1997                                      uint32_t ShareAccess,
1998                                      uint32_t CreateDisposition,
1999                                      uint32_t CreateOptions,
2000                                      uint8_t SecurityFlags)
2001 {
2002         struct tevent_req *req, *subreq;
2003         struct cli_ntcreate_state *state;
2004         uint16_t *vwv;
2005         uint8_t *bytes;
2006         size_t converted_len;
2007
2008         req = tevent_req_create(mem_ctx, &state, struct cli_ntcreate_state);
2009         if (req == NULL) {
2010                 return NULL;
2011         }
2012
2013         vwv = state->vwv;
2014
2015         SCVAL(vwv+0, 0, 0xFF);
2016         SCVAL(vwv+0, 1, 0);
2017         SSVAL(vwv+1, 0, 0);
2018         SCVAL(vwv+2, 0, 0);
2019
2020         if (cli->use_oplocks) {
2021                 CreatFlags |= (REQUEST_OPLOCK|REQUEST_BATCH_OPLOCK);
2022         }
2023         SIVAL(vwv+3, 1, CreatFlags);
2024         SIVAL(vwv+5, 1, 0x0);   /* RootDirectoryFid */
2025         SIVAL(vwv+7, 1, DesiredAccess);
2026         SIVAL(vwv+9, 1, 0x0);   /* AllocationSize */
2027         SIVAL(vwv+11, 1, 0x0);  /* AllocationSize */
2028         SIVAL(vwv+13, 1, FileAttributes);
2029         SIVAL(vwv+15, 1, ShareAccess);
2030         SIVAL(vwv+17, 1, CreateDisposition);
2031         SIVAL(vwv+19, 1, CreateOptions);
2032         SIVAL(vwv+21, 1, 0x02); /* ImpersonationLevel */
2033         SCVAL(vwv+23, 1, SecurityFlags);
2034
2035         bytes = talloc_array(state, uint8_t, 0);
2036         bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
2037                                    fname, strlen(fname)+1,
2038                                    &converted_len);
2039
2040         /* sigh. this copes with broken netapp filer behaviour */
2041         bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "", 1, NULL);
2042
2043         if (tevent_req_nomem(bytes, req)) {
2044                 return tevent_req_post(req, ev);
2045         }
2046
2047         SSVAL(vwv+2, 1, converted_len);
2048
2049         subreq = cli_smb_send(state, ev, cli, SMBntcreateX, 0, 24, vwv,
2050                               talloc_get_size(bytes), bytes);
2051         if (tevent_req_nomem(subreq, req)) {
2052                 return tevent_req_post(req, ev);
2053         }
2054         tevent_req_set_callback(subreq, cli_ntcreate_done, req);
2055         return req;
2056 }
2057
2058 static void cli_ntcreate_done(struct tevent_req *subreq)
2059 {
2060         struct tevent_req *req = tevent_req_callback_data(
2061                 subreq, struct tevent_req);
2062         struct cli_ntcreate_state *state = tevent_req_data(
2063                 req, struct cli_ntcreate_state);
2064         uint8_t wct;
2065         uint16_t *vwv;
2066         uint32_t num_bytes;
2067         uint8_t *bytes;
2068         NTSTATUS status;
2069
2070         status = cli_smb_recv(subreq, 3, &wct, &vwv, &num_bytes, &bytes);
2071         if (!NT_STATUS_IS_OK(status)) {
2072                 TALLOC_FREE(subreq);
2073                 tevent_req_nterror(req, status);
2074                 return;
2075         }
2076         state->fnum = SVAL(vwv+2, 1);
2077         tevent_req_done(req);
2078 }
2079
2080 NTSTATUS cli_ntcreate_recv(struct tevent_req *req, uint16_t *pfnum)
2081 {
2082         struct cli_ntcreate_state *state = tevent_req_data(
2083                 req, struct cli_ntcreate_state);
2084         NTSTATUS status;
2085
2086         if (tevent_req_is_nterror(req, &status)) {
2087                 return status;
2088         }
2089         *pfnum = state->fnum;
2090         return NT_STATUS_OK;
2091 }
2092
2093 NTSTATUS cli_ntcreate(struct cli_state *cli,
2094                       const char *fname,
2095                       uint32_t CreatFlags,
2096                       uint32_t DesiredAccess,
2097                       uint32_t FileAttributes,
2098                       uint32_t ShareAccess,
2099                       uint32_t CreateDisposition,
2100                       uint32_t CreateOptions,
2101                       uint8_t SecurityFlags,
2102                       uint16_t *pfid)
2103 {
2104         TALLOC_CTX *frame = talloc_stackframe();
2105         struct event_context *ev;
2106         struct tevent_req *req;
2107         NTSTATUS status = NT_STATUS_OK;
2108
2109         if (cli_has_async_calls(cli)) {
2110                 /*
2111                  * Can't use sync call while an async call is in flight
2112                  */
2113                 status = NT_STATUS_INVALID_PARAMETER;
2114                 goto fail;
2115         }
2116
2117         ev = event_context_init(frame);
2118         if (ev == NULL) {
2119                 status = NT_STATUS_NO_MEMORY;
2120                 goto fail;
2121         }
2122
2123         req = cli_ntcreate_send(frame, ev, cli, fname, CreatFlags,
2124                                 DesiredAccess, FileAttributes, ShareAccess,
2125                                 CreateDisposition, CreateOptions,
2126                                 SecurityFlags);
2127         if (req == NULL) {
2128                 status = NT_STATUS_NO_MEMORY;
2129                 goto fail;
2130         }
2131
2132         if (!tevent_req_poll(req, ev)) {
2133                 status = map_nt_error_from_unix(errno);
2134                 goto fail;
2135         }
2136
2137         status = cli_ntcreate_recv(req, pfid);
2138  fail:
2139         TALLOC_FREE(frame);
2140         if (!NT_STATUS_IS_OK(status)) {
2141                 cli_set_error(cli, status);
2142         }
2143         return status;
2144 }
2145
2146 /****************************************************************************
2147  Open a file
2148  WARNING: if you open with O_WRONLY then getattrE won't work!
2149 ****************************************************************************/
2150
2151 struct cli_open_state {
2152         uint16_t vwv[15];
2153         uint16_t fnum;
2154         struct iovec bytes;
2155 };
2156
2157 static void cli_open_done(struct tevent_req *subreq);
2158
2159 struct tevent_req *cli_open_create(TALLOC_CTX *mem_ctx,
2160                                    struct event_context *ev,
2161                                    struct cli_state *cli, const char *fname,
2162                                    int flags, int share_mode,
2163                                    struct tevent_req **psmbreq)
2164 {
2165         struct tevent_req *req, *subreq;
2166         struct cli_open_state *state;
2167         unsigned openfn;
2168         unsigned accessmode;
2169         uint8_t additional_flags;
2170         uint8_t *bytes;
2171
2172         req = tevent_req_create(mem_ctx, &state, struct cli_open_state);
2173         if (req == NULL) {
2174                 return NULL;
2175         }
2176
2177         openfn = 0;
2178         if (flags & O_CREAT) {
2179                 openfn |= (1<<4);
2180         }
2181         if (!(flags & O_EXCL)) {
2182                 if (flags & O_TRUNC)
2183                         openfn |= (1<<1);
2184                 else
2185                         openfn |= (1<<0);
2186         }
2187
2188         accessmode = (share_mode<<4);
2189
2190         if ((flags & O_ACCMODE) == O_RDWR) {
2191                 accessmode |= 2;
2192         } else if ((flags & O_ACCMODE) == O_WRONLY) {
2193                 accessmode |= 1;
2194         }
2195
2196 #if defined(O_SYNC)
2197         if ((flags & O_SYNC) == O_SYNC) {
2198                 accessmode |= (1<<14);
2199         }
2200 #endif /* O_SYNC */
2201
2202         if (share_mode == DENY_FCB) {
2203                 accessmode = 0xFF;
2204         }
2205
2206         SCVAL(state->vwv + 0, 0, 0xFF);
2207         SCVAL(state->vwv + 0, 1, 0);
2208         SSVAL(state->vwv + 1, 0, 0);
2209         SSVAL(state->vwv + 2, 0, 0);  /* no additional info */
2210         SSVAL(state->vwv + 3, 0, accessmode);
2211         SSVAL(state->vwv + 4, 0, aSYSTEM | aHIDDEN);
2212         SSVAL(state->vwv + 5, 0, 0);
2213         SIVAL(state->vwv + 6, 0, 0);
2214         SSVAL(state->vwv + 8, 0, openfn);
2215         SIVAL(state->vwv + 9, 0, 0);
2216         SIVAL(state->vwv + 11, 0, 0);
2217         SIVAL(state->vwv + 13, 0, 0);
2218
2219         additional_flags = 0;
2220
2221         if (cli->use_oplocks) {
2222                 /* if using oplocks then ask for a batch oplock via
2223                    core and extended methods */
2224                 additional_flags =
2225                         FLAG_REQUEST_OPLOCK|FLAG_REQUEST_BATCH_OPLOCK;
2226                 SSVAL(state->vwv+2, 0, SVAL(state->vwv+2, 0) | 6);
2227         }
2228
2229         bytes = talloc_array(state, uint8_t, 0);
2230         bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), fname,
2231                                    strlen(fname)+1, NULL);
2232
2233         if (tevent_req_nomem(bytes, req)) {
2234                 return tevent_req_post(req, ev);
2235         }
2236
2237         state->bytes.iov_base = (void *)bytes;
2238         state->bytes.iov_len = talloc_get_size(bytes);
2239
2240         subreq = cli_smb_req_create(state, ev, cli, SMBopenX, additional_flags,
2241                                     15, state->vwv, 1, &state->bytes);
2242         if (subreq == NULL) {
2243                 TALLOC_FREE(req);
2244                 return NULL;
2245         }
2246         tevent_req_set_callback(subreq, cli_open_done, req);
2247         *psmbreq = subreq;
2248         return req;
2249 }
2250
2251 struct tevent_req *cli_open_send(TALLOC_CTX *mem_ctx, struct event_context *ev,
2252                                  struct cli_state *cli, const char *fname,
2253                                  int flags, int share_mode)
2254 {
2255         struct tevent_req *req, *subreq;
2256         NTSTATUS status;
2257
2258         req = cli_open_create(mem_ctx, ev, cli, fname, flags, share_mode,
2259                               &subreq);
2260         if (req == NULL) {
2261                 return NULL;
2262         }
2263
2264         status = cli_smb_req_send(subreq);
2265         if (!NT_STATUS_IS_OK(status)) {
2266                 tevent_req_nterror(req, status);
2267                 return tevent_req_post(req, ev);
2268         }
2269         return req;
2270 }
2271
2272 static void cli_open_done(struct tevent_req *subreq)
2273 {
2274         struct tevent_req *req = tevent_req_callback_data(
2275                 subreq, struct tevent_req);
2276         struct cli_open_state *state = tevent_req_data(
2277                 req, struct cli_open_state);
2278         uint8_t wct;
2279         uint16_t *vwv;
2280         NTSTATUS status;
2281
2282         status = cli_smb_recv(subreq, 3, &wct, &vwv, NULL, NULL);
2283         if (!NT_STATUS_IS_OK(status)) {
2284                 TALLOC_FREE(subreq);
2285                 tevent_req_nterror(req, status);
2286                 return;
2287         }
2288         state->fnum = SVAL(vwv+2, 0);
2289         tevent_req_done(req);
2290 }
2291
2292 NTSTATUS cli_open_recv(struct tevent_req *req, uint16_t *pfnum)
2293 {
2294         struct cli_open_state *state = tevent_req_data(
2295                 req, struct cli_open_state);
2296         NTSTATUS status;
2297
2298         if (tevent_req_is_nterror(req, &status)) {
2299                 return status;
2300         }
2301         *pfnum = state->fnum;
2302         return NT_STATUS_OK;
2303 }
2304
2305 NTSTATUS cli_open(struct cli_state *cli, const char *fname, int flags,
2306              int share_mode, uint16_t *pfnum)
2307 {
2308         TALLOC_CTX *frame = talloc_stackframe();
2309         struct event_context *ev;
2310         struct tevent_req *req;
2311         NTSTATUS status = NT_STATUS_OK;
2312
2313         if (cli_has_async_calls(cli)) {
2314                 /*
2315                  * Can't use sync call while an async call is in flight
2316                  */
2317                 status = NT_STATUS_INVALID_PARAMETER;
2318                 goto fail;
2319         }
2320
2321         ev = event_context_init(frame);
2322         if (ev == NULL) {
2323                 status = NT_STATUS_NO_MEMORY;
2324                 goto fail;
2325         }
2326
2327         req = cli_open_send(frame, ev, cli, fname, flags, share_mode);
2328         if (req == NULL) {
2329                 status = NT_STATUS_NO_MEMORY;
2330                 goto fail;
2331         }
2332
2333         if (!tevent_req_poll(req, ev)) {
2334                 status = map_nt_error_from_unix(errno);
2335                 goto fail;
2336         }
2337
2338         status = cli_open_recv(req, pfnum);
2339  fail:
2340         TALLOC_FREE(frame);
2341         if (!NT_STATUS_IS_OK(status)) {
2342                 cli_set_error(cli, status);
2343         }
2344         return status;
2345 }
2346
2347 /****************************************************************************
2348  Close a file.
2349 ****************************************************************************/
2350
2351 struct cli_close_state {
2352         uint16_t vwv[3];
2353 };
2354
2355 static void cli_close_done(struct tevent_req *subreq);
2356
2357 struct tevent_req *cli_close_create(TALLOC_CTX *mem_ctx,
2358                                 struct event_context *ev,
2359                                 struct cli_state *cli,
2360                                 uint16_t fnum,
2361                                 struct tevent_req **psubreq)
2362 {
2363         struct tevent_req *req, *subreq;
2364         struct cli_close_state *state;
2365
2366         req = tevent_req_create(mem_ctx, &state, struct cli_close_state);
2367         if (req == NULL) {
2368                 return NULL;
2369         }
2370
2371         SSVAL(state->vwv+0, 0, fnum);
2372         SIVALS(state->vwv+1, 0, -1);
2373
2374         subreq = cli_smb_req_create(state, ev, cli, SMBclose, 0, 3, state->vwv,
2375                                     0, NULL);
2376         if (subreq == NULL) {
2377                 TALLOC_FREE(req);
2378                 return NULL;
2379         }
2380         tevent_req_set_callback(subreq, cli_close_done, req);
2381         *psubreq = subreq;
2382         return req;
2383 }
2384
2385 struct tevent_req *cli_close_send(TALLOC_CTX *mem_ctx,
2386                                 struct event_context *ev,
2387                                 struct cli_state *cli,
2388                                 uint16_t fnum)
2389 {
2390         struct tevent_req *req, *subreq;
2391         NTSTATUS status;
2392
2393         req = cli_close_create(mem_ctx, ev, cli, fnum, &subreq);
2394         if (req == NULL) {
2395                 return NULL;
2396         }
2397
2398         status = cli_smb_req_send(subreq);
2399         if (!NT_STATUS_IS_OK(status)) {
2400                 tevent_req_nterror(req, status);
2401                 return tevent_req_post(req, ev);
2402         }
2403         return req;
2404 }
2405
2406 static void cli_close_done(struct tevent_req *subreq)
2407 {
2408         struct tevent_req *req = tevent_req_callback_data(
2409                 subreq, struct tevent_req);
2410         NTSTATUS status;
2411
2412         status = cli_smb_recv(subreq, 0, NULL, NULL, NULL, NULL);
2413         TALLOC_FREE(subreq);
2414         if (!NT_STATUS_IS_OK(status)) {
2415                 tevent_req_nterror(req, status);
2416                 return;
2417         }
2418         tevent_req_done(req);
2419 }
2420
2421 NTSTATUS cli_close_recv(struct tevent_req *req)
2422 {
2423         return tevent_req_simple_recv_ntstatus(req);
2424 }
2425
2426 NTSTATUS cli_close(struct cli_state *cli, uint16_t fnum)
2427 {
2428         TALLOC_CTX *frame = talloc_stackframe();
2429         struct event_context *ev;
2430         struct tevent_req *req;
2431         NTSTATUS status = NT_STATUS_OK;
2432
2433         if (cli_has_async_calls(cli)) {
2434                 /*
2435                  * Can't use sync call while an async call is in flight
2436                  */
2437                 status = NT_STATUS_INVALID_PARAMETER;
2438                 goto fail;
2439         }
2440
2441         ev = event_context_init(frame);
2442         if (ev == NULL) {
2443                 status = NT_STATUS_NO_MEMORY;
2444                 goto fail;
2445         }
2446
2447         req = cli_close_send(frame, ev, cli, fnum);
2448         if (req == NULL) {
2449                 status = NT_STATUS_NO_MEMORY;
2450                 goto fail;
2451         }
2452
2453         if (!tevent_req_poll(req, ev)) {
2454                 status = map_nt_error_from_unix(errno);
2455                 goto fail;
2456         }
2457
2458         status = cli_close_recv(req);
2459  fail:
2460         TALLOC_FREE(frame);
2461         if (!NT_STATUS_IS_OK(status)) {
2462                 cli_set_error(cli, status);
2463         }
2464         return status;
2465 }
2466
2467 /****************************************************************************
2468  Truncate a file to a specified size
2469 ****************************************************************************/
2470
2471 struct ftrunc_state {
2472         uint16_t setup;
2473         uint8_t param[6];
2474         uint8_t data[8];
2475 };
2476
2477 static void cli_ftruncate_done(struct tevent_req *subreq)
2478 {
2479         struct tevent_req *req = tevent_req_callback_data(
2480                                 subreq, struct tevent_req);
2481         struct ftrunc_state *state = tevent_req_data(req, struct ftrunc_state);
2482         NTSTATUS status;
2483
2484         status = cli_trans_recv(subreq, state, NULL, NULL, NULL, NULL, NULL, NULL);
2485         TALLOC_FREE(subreq);
2486         if (!NT_STATUS_IS_OK(status)) {
2487                 tevent_req_nterror(req, status);
2488                 return;
2489         }
2490         tevent_req_done(req);
2491 }
2492
2493 struct tevent_req *cli_ftruncate_send(TALLOC_CTX *mem_ctx,
2494                                         struct event_context *ev,
2495                                         struct cli_state *cli,
2496                                         uint16_t fnum,
2497                                         uint64_t size)
2498 {
2499         struct tevent_req *req = NULL, *subreq = NULL;
2500         struct ftrunc_state *state = NULL;
2501
2502         req = tevent_req_create(mem_ctx, &state, struct ftrunc_state);
2503         if (req == NULL) {
2504                 return NULL;
2505         }
2506
2507         /* Setup setup word. */
2508         SSVAL(&state->setup, 0, TRANSACT2_SETFILEINFO);
2509
2510         /* Setup param array. */
2511         SSVAL(state->param,0,fnum);
2512         SSVAL(state->param,2,SMB_SET_FILE_END_OF_FILE_INFO);
2513         SSVAL(state->param,4,0);
2514
2515         /* Setup data array. */
2516         SBVAL(state->data, 0, size);
2517
2518         subreq = cli_trans_send(state,                  /* mem ctx. */
2519                                 ev,                     /* event ctx. */
2520                                 cli,                    /* cli_state. */
2521                                 SMBtrans2,              /* cmd. */
2522                                 NULL,                   /* pipe name. */
2523                                 -1,                     /* fid. */
2524                                 0,                      /* function. */
2525                                 0,                      /* flags. */
2526                                 &state->setup,          /* setup. */
2527                                 1,                      /* num setup uint16_t words. */
2528                                 0,                      /* max returned setup. */
2529                                 state->param,           /* param. */
2530                                 6,                      /* num param. */
2531                                 2,                      /* max returned param. */
2532                                 state->data,            /* data. */
2533                                 8,                      /* num data. */
2534                                 0);                     /* max returned data. */
2535
2536         if (tevent_req_nomem(subreq, req)) {
2537                 return tevent_req_post(req, ev);
2538         }
2539         tevent_req_set_callback(subreq, cli_ftruncate_done, req);
2540         return req;
2541 }
2542
2543 NTSTATUS cli_ftruncate_recv(struct tevent_req *req)
2544 {
2545         NTSTATUS status;
2546
2547         if (tevent_req_is_nterror(req, &status)) {
2548                 return status;
2549         }
2550         return NT_STATUS_OK;
2551 }
2552
2553 NTSTATUS cli_ftruncate(struct cli_state *cli, uint16_t fnum, uint64_t size)
2554 {
2555         TALLOC_CTX *frame = talloc_stackframe();
2556         struct event_context *ev = NULL;
2557         struct tevent_req *req = NULL;
2558         NTSTATUS status = NT_STATUS_OK;
2559
2560         if (cli_has_async_calls(cli)) {
2561                 /*
2562                  * Can't use sync call while an async call is in flight
2563                  */
2564                 status = NT_STATUS_INVALID_PARAMETER;
2565                 goto fail;
2566         }
2567
2568         ev = event_context_init(frame);
2569         if (ev == NULL) {
2570                 status = NT_STATUS_NO_MEMORY;
2571                 goto fail;
2572         }
2573
2574         req = cli_ftruncate_send(frame,
2575                                 ev,
2576                                 cli,
2577                                 fnum,
2578                                 size);
2579         if (req == NULL) {
2580                 status = NT_STATUS_NO_MEMORY;
2581                 goto fail;
2582         }
2583
2584         if (!tevent_req_poll(req, ev)) {
2585                 status = map_nt_error_from_unix(errno);
2586                 goto fail;
2587         }
2588
2589         status = cli_ftruncate_recv(req);
2590
2591  fail:
2592         TALLOC_FREE(frame);
2593         if (!NT_STATUS_IS_OK(status)) {
2594                 cli_set_error(cli, status);
2595         }
2596         return status;
2597 }
2598
2599 /****************************************************************************
2600  send a lock with a specified locktype
2601  this is used for testing LOCKING_ANDX_CANCEL_LOCK
2602 ****************************************************************************/
2603
2604 NTSTATUS cli_locktype(struct cli_state *cli, uint16_t fnum,
2605                       uint32_t offset, uint32_t len,
2606                       int timeout, unsigned char locktype)
2607 {
2608         char *p;
2609         int saved_timeout = cli->timeout;
2610
2611         memset(cli->outbuf,'\0',smb_size);
2612         memset(cli->inbuf,'\0', smb_size);
2613
2614         cli_set_message(cli->outbuf,8,0,True);
2615
2616         SCVAL(cli->outbuf,smb_com,SMBlockingX);
2617         SSVAL(cli->outbuf,smb_tid,cli->cnum);
2618         cli_setup_packet(cli);
2619
2620         SCVAL(cli->outbuf,smb_vwv0,0xFF);
2621         SSVAL(cli->outbuf,smb_vwv2,fnum);
2622         SCVAL(cli->outbuf,smb_vwv3,locktype);
2623         SIVALS(cli->outbuf, smb_vwv4, timeout);
2624         SSVAL(cli->outbuf,smb_vwv6,0);
2625         SSVAL(cli->outbuf,smb_vwv7,1);
2626
2627         p = smb_buf(cli->outbuf);
2628         SSVAL(p, 0, cli->pid);
2629         SIVAL(p, 2, offset);
2630         SIVAL(p, 6, len);
2631
2632         p += 10;
2633
2634         cli_setup_bcc(cli, p);
2635
2636         cli_send_smb(cli);
2637
2638         if (timeout != 0) {
2639                 cli->timeout = (timeout == -1) ? 0x7FFFFFFF : (timeout + 2*1000);
2640         }
2641
2642         if (!cli_receive_smb(cli)) {
2643                 cli->timeout = saved_timeout;
2644                 return NT_STATUS_UNSUCCESSFUL;
2645         }
2646
2647         cli->timeout = saved_timeout;
2648
2649         return cli_nt_error(cli);
2650 }
2651
2652 /****************************************************************************
2653  Lock a file.
2654  note that timeout is in units of 2 milliseconds
2655 ****************************************************************************/
2656
2657 bool cli_lock(struct cli_state *cli, uint16_t fnum,
2658               uint32_t offset, uint32_t len, int timeout, enum brl_type lock_type)
2659 {
2660         char *p;
2661         int saved_timeout = cli->timeout;
2662
2663         memset(cli->outbuf,'\0',smb_size);
2664         memset(cli->inbuf,'\0', smb_size);
2665
2666         cli_set_message(cli->outbuf,8,0,True);
2667
2668         SCVAL(cli->outbuf,smb_com,SMBlockingX);
2669         SSVAL(cli->outbuf,smb_tid,cli->cnum);
2670         cli_setup_packet(cli);
2671
2672         SCVAL(cli->outbuf,smb_vwv0,0xFF);
2673         SSVAL(cli->outbuf,smb_vwv2,fnum);
2674         SCVAL(cli->outbuf,smb_vwv3,(lock_type == READ_LOCK? 1 : 0));
2675         SIVALS(cli->outbuf, smb_vwv4, timeout);
2676         SSVAL(cli->outbuf,smb_vwv6,0);
2677         SSVAL(cli->outbuf,smb_vwv7,1);
2678
2679         p = smb_buf(cli->outbuf);
2680         SSVAL(p, 0, cli->pid);
2681         SIVAL(p, 2, offset);
2682         SIVAL(p, 6, len);
2683
2684         p += 10;
2685
2686         cli_setup_bcc(cli, p);
2687
2688         cli_send_smb(cli);
2689
2690         if (timeout != 0) {
2691                 cli->timeout = (timeout == -1) ? 0x7FFFFFFF : (timeout*2 + 5*1000);
2692         }
2693
2694         if (!cli_receive_smb(cli)) {
2695                 cli->timeout = saved_timeout;
2696                 return False;
2697         }
2698
2699         cli->timeout = saved_timeout;
2700
2701         if (cli_is_error(cli)) {
2702                 return False;
2703         }
2704
2705         return True;
2706 }
2707
2708 /****************************************************************************
2709  Unlock a file.
2710 ****************************************************************************/
2711
2712 struct cli_unlock_state {
2713         uint16_t vwv[8];
2714         uint8_t data[10];
2715 };
2716
2717 static void cli_unlock_done(struct tevent_req *subreq);
2718
2719 struct tevent_req *cli_unlock_send(TALLOC_CTX *mem_ctx,
2720                                 struct event_context *ev,
2721                                 struct cli_state *cli,
2722                                 uint16_t fnum,
2723                                 uint64_t offset,
2724                                 uint64_t len)
2725
2726 {
2727         struct tevent_req *req = NULL, *subreq = NULL;
2728         struct cli_unlock_state *state = NULL;
2729         uint8_t additional_flags = 0;
2730
2731         req = tevent_req_create(mem_ctx, &state, struct cli_unlock_state);
2732         if (req == NULL) {
2733                 return NULL;
2734         }
2735
2736         SCVAL(state->vwv+0, 0, 0xFF);
2737         SSVAL(state->vwv+2, 0, fnum);
2738         SCVAL(state->vwv+3, 0, 0);
2739         SIVALS(state->vwv+4, 0, 0);
2740         SSVAL(state->vwv+6, 0, 1);
2741         SSVAL(state->vwv+7, 0, 0);
2742
2743         SSVAL(state->data, 0, cli->pid);
2744         SIVAL(state->data, 2, offset);
2745         SIVAL(state->data, 6, len);
2746
2747         subreq = cli_smb_send(state, ev, cli, SMBlockingX, additional_flags,
2748                                 8, state->vwv, 10, state->data);
2749         if (tevent_req_nomem(subreq, req)) {
2750                 return tevent_req_post(req, ev);
2751         }
2752         tevent_req_set_callback(subreq, cli_unlock_done, req);
2753         return req;
2754 }
2755
2756 static void cli_unlock_done(struct tevent_req *subreq)
2757 {
2758         struct tevent_req *req = tevent_req_callback_data(
2759                                 subreq, struct tevent_req);
2760         NTSTATUS status;
2761
2762         status = cli_smb_recv(subreq, 0, NULL, NULL, NULL, NULL);
2763         TALLOC_FREE(subreq);
2764         if (!NT_STATUS_IS_OK(status)) {
2765                 tevent_req_nterror(req, status);
2766                 return;
2767         }
2768         tevent_req_done(req);
2769 }
2770
2771 NTSTATUS cli_unlock_recv(struct tevent_req *req)
2772 {
2773         return tevent_req_simple_recv_ntstatus(req);
2774 }
2775
2776 NTSTATUS cli_unlock(struct cli_state *cli,
2777                         uint16_t fnum,
2778                         uint32_t offset,
2779                         uint32_t len)
2780 {
2781         TALLOC_CTX *frame = talloc_stackframe();
2782         struct event_context *ev;
2783         struct tevent_req *req;
2784         NTSTATUS status = NT_STATUS_OK;
2785
2786         if (cli_has_async_calls(cli)) {
2787                 /*
2788                  * Can't use sync call while an async call is in flight
2789                  */
2790                 status = NT_STATUS_INVALID_PARAMETER;
2791                 goto fail;
2792         }
2793
2794         ev = event_context_init(frame);
2795         if (ev == NULL) {
2796                 status = NT_STATUS_NO_MEMORY;
2797                 goto fail;
2798         }
2799
2800         req = cli_unlock_send(frame, ev, cli,
2801                         fnum, offset, len);
2802         if (req == NULL) {
2803                 status = NT_STATUS_NO_MEMORY;
2804                 goto fail;
2805         }
2806
2807         if (!tevent_req_poll(req, ev)) {
2808                 status = map_nt_error_from_unix(errno);
2809                 goto fail;
2810         }
2811
2812         status = cli_unlock_recv(req);
2813
2814  fail:
2815         TALLOC_FREE(frame);
2816         if (!NT_STATUS_IS_OK(status)) {
2817                 cli_set_error(cli, status);
2818         }
2819         return status;
2820 }
2821
2822 /****************************************************************************
2823  Lock a file with 64 bit offsets.
2824 ****************************************************************************/
2825
2826 bool cli_lock64(struct cli_state *cli, uint16_t fnum,
2827                 uint64_t offset, uint64_t len, int timeout, enum brl_type lock_type)
2828 {
2829         char *p;
2830         int saved_timeout = cli->timeout;
2831         int ltype;
2832
2833         if (! (cli->capabilities & CAP_LARGE_FILES)) {
2834                 return cli_lock(cli, fnum, offset, len, timeout, lock_type);
2835         }
2836
2837         ltype = (lock_type == READ_LOCK? 1 : 0);
2838         ltype |= LOCKING_ANDX_LARGE_FILES;
2839
2840         memset(cli->outbuf,'\0',smb_size);
2841         memset(cli->inbuf,'\0', smb_size);
2842
2843         cli_set_message(cli->outbuf,8,0,True);
2844
2845         SCVAL(cli->outbuf,smb_com,SMBlockingX);
2846         SSVAL(cli->outbuf,smb_tid,cli->cnum);
2847         cli_setup_packet(cli);
2848
2849         SCVAL(cli->outbuf,smb_vwv0,0xFF);
2850         SSVAL(cli->outbuf,smb_vwv2,fnum);
2851         SCVAL(cli->outbuf,smb_vwv3,ltype);
2852         SIVALS(cli->outbuf, smb_vwv4, timeout);
2853         SSVAL(cli->outbuf,smb_vwv6,0);
2854         SSVAL(cli->outbuf,smb_vwv7,1);
2855
2856         p = smb_buf(cli->outbuf);
2857         SIVAL(p, 0, cli->pid);
2858         SOFF_T_R(p, 4, offset);
2859         SOFF_T_R(p, 12, len);
2860         p += 20;
2861
2862         cli_setup_bcc(cli, p);
2863         cli_send_smb(cli);
2864
2865         if (timeout != 0) {
2866                 cli->timeout = (timeout == -1) ? 0x7FFFFFFF : (timeout + 5*1000);
2867         }
2868
2869         if (!cli_receive_smb(cli)) {
2870                 cli->timeout = saved_timeout;
2871                 return False;
2872         }
2873
2874         cli->timeout = saved_timeout;
2875
2876         if (cli_is_error(cli)) {
2877                 return False;
2878         }
2879
2880         return True;
2881 }
2882
2883 /****************************************************************************
2884  Unlock a file with 64 bit offsets.
2885 ****************************************************************************/
2886
2887 struct cli_unlock64_state {
2888         uint16_t vwv[8];
2889         uint8_t data[20];
2890 };
2891
2892 static void cli_unlock64_done(struct tevent_req *subreq);
2893
2894 struct tevent_req *cli_unlock64_send(TALLOC_CTX *mem_ctx,
2895                                 struct event_context *ev,
2896                                 struct cli_state *cli,
2897                                 uint16_t fnum,
2898                                 uint64_t offset,
2899                                 uint64_t len)
2900
2901 {
2902         struct tevent_req *req = NULL, *subreq = NULL;
2903         struct cli_unlock64_state *state = NULL;
2904         uint8_t additional_flags = 0;
2905
2906         req = tevent_req_create(mem_ctx, &state, struct cli_unlock64_state);
2907         if (req == NULL) {
2908                 return NULL;
2909         }
2910
2911         SCVAL(state->vwv+0, 0, 0xff);
2912         SSVAL(state->vwv+2, 0, fnum);
2913         SCVAL(state->vwv+3, 0,LOCKING_ANDX_LARGE_FILES);
2914         SIVALS(state->vwv+4, 0, 0);
2915         SSVAL(state->vwv+6, 0, 1);
2916         SSVAL(state->vwv+7, 0, 0);
2917
2918         SIVAL(state->data, 0, cli->pid);
2919         SOFF_T_R(state->data, 4, offset);
2920         SOFF_T_R(state->data, 12, len);
2921
2922         subreq = cli_smb_send(state, ev, cli, SMBlockingX, additional_flags,
2923                                 8, state->vwv, 20, state->data);
2924         if (tevent_req_nomem(subreq, req)) {
2925                 return tevent_req_post(req, ev);
2926         }
2927         tevent_req_set_callback(subreq, cli_unlock64_done, req);
2928         return req;
2929 }
2930
2931 static void cli_unlock64_done(struct tevent_req *subreq)
2932 {
2933         struct tevent_req *req = tevent_req_callback_data(
2934                                 subreq, struct tevent_req);
2935         NTSTATUS status;
2936
2937         status = cli_smb_recv(subreq, 0, NULL, NULL, NULL, NULL);
2938         TALLOC_FREE(subreq);
2939         if (!NT_STATUS_IS_OK(status)) {
2940                 tevent_req_nterror(req, status);
2941                 return;
2942         }
2943         tevent_req_done(req);
2944 }
2945
2946 NTSTATUS cli_unlock64_recv(struct tevent_req *req)
2947 {
2948         return tevent_req_simple_recv_ntstatus(req);
2949 }
2950
2951 NTSTATUS cli_unlock64(struct cli_state *cli,
2952                                 uint16_t fnum,
2953                                 uint64_t offset,
2954                                 uint64_t len)
2955 {
2956         TALLOC_CTX *frame = talloc_stackframe();
2957         struct event_context *ev;
2958         struct tevent_req *req;
2959         NTSTATUS status = NT_STATUS_OK;
2960
2961         if (! (cli->capabilities & CAP_LARGE_FILES)) {
2962                 return cli_unlock(cli, fnum, offset, len);
2963         }
2964
2965         if (cli_has_async_calls(cli)) {
2966                 /*
2967                  * Can't use sync call while an async call is in flight
2968                  */
2969                 status = NT_STATUS_INVALID_PARAMETER;
2970                 goto fail;
2971         }
2972
2973         ev = event_context_init(frame);
2974         if (ev == NULL) {
2975                 status = NT_STATUS_NO_MEMORY;
2976                 goto fail;
2977         }
2978
2979         req = cli_unlock64_send(frame, ev, cli,
2980                         fnum, offset, len);
2981         if (req == NULL) {
2982                 status = NT_STATUS_NO_MEMORY;
2983                 goto fail;
2984         }
2985
2986         if (!tevent_req_poll(req, ev)) {
2987                 status = map_nt_error_from_unix(errno);
2988                 goto fail;
2989         }
2990
2991         status = cli_unlock64_recv(req);
2992
2993  fail:
2994         TALLOC_FREE(frame);
2995         if (!NT_STATUS_IS_OK(status)) {
2996                 cli_set_error(cli, status);
2997         }
2998         return status;
2999 }
3000
3001 /****************************************************************************
3002  Get/unlock a POSIX lock on a file - internal function.
3003 ****************************************************************************/
3004
3005 struct posix_lock_state {
3006         uint16_t setup;
3007         uint8_t param[4];
3008         uint8_t data[POSIX_LOCK_DATA_SIZE];
3009 };
3010
3011 static void cli_posix_unlock_internal_done(struct tevent_req *subreq)
3012 {
3013         struct tevent_req *req = tevent_req_callback_data(
3014                                         subreq, struct tevent_req);
3015         struct posix_lock_state *state = tevent_req_data(req, struct posix_lock_state);
3016         NTSTATUS status;
3017
3018         status = cli_trans_recv(subreq, state, NULL, NULL, NULL, NULL, NULL, NULL);
3019         TALLOC_FREE(subreq);
3020         if (!NT_STATUS_IS_OK(status)) {
3021                 tevent_req_nterror(req, status);
3022                 return;
3023         }
3024         tevent_req_done(req);
3025 }
3026
3027 static struct tevent_req *cli_posix_lock_internal_send(TALLOC_CTX *mem_ctx,
3028                                         struct event_context *ev,
3029                                         struct cli_state *cli,
3030                                         uint16_t fnum,
3031                                         uint64_t offset,
3032                                         uint64_t len,
3033                                         bool wait_lock,
3034                                         enum brl_type lock_type)
3035 {
3036         struct tevent_req *req = NULL, *subreq = NULL;
3037         struct posix_lock_state *state = NULL;
3038
3039         req = tevent_req_create(mem_ctx, &state, struct posix_lock_state);
3040         if (req == NULL) {
3041                 return NULL;
3042         }
3043
3044         /* Setup setup word. */
3045         SSVAL(&state->setup, 0, TRANSACT2_SETFILEINFO);
3046
3047         /* Setup param array. */
3048         SSVAL(&state->param, 0, fnum);
3049         SSVAL(&state->param, 2, SMB_SET_POSIX_LOCK);
3050
3051         /* Setup data array. */
3052         switch (lock_type) {
3053                 case READ_LOCK:
3054                         SSVAL(&state->data, POSIX_LOCK_TYPE_OFFSET,
3055                                 POSIX_LOCK_TYPE_READ);
3056                         break;
3057                 case WRITE_LOCK:
3058                         SSVAL(&state->data, POSIX_LOCK_TYPE_OFFSET,
3059                                 POSIX_LOCK_TYPE_WRITE);
3060                         break;
3061                 case UNLOCK_LOCK:
3062                         SSVAL(&state->data, POSIX_LOCK_TYPE_OFFSET,
3063                                 POSIX_LOCK_TYPE_UNLOCK);
3064                         break;
3065                 default:
3066                         return NULL;
3067         }
3068
3069         if (wait_lock) {
3070                 SSVAL(&state->data, POSIX_LOCK_FLAGS_OFFSET,
3071                                 POSIX_LOCK_FLAG_WAIT);
3072         } else {
3073                 SSVAL(state->data, POSIX_LOCK_FLAGS_OFFSET,
3074                                 POSIX_LOCK_FLAG_NOWAIT);
3075         }
3076
3077         SIVAL(&state->data, POSIX_LOCK_PID_OFFSET, cli->pid);
3078         SOFF_T(&state->data, POSIX_LOCK_START_OFFSET, offset);
3079         SOFF_T(&state->data, POSIX_LOCK_LEN_OFFSET, len);
3080
3081         subreq = cli_trans_send(state,                  /* mem ctx. */
3082                                 ev,                     /* event ctx. */
3083                                 cli,                    /* cli_state. */
3084                                 SMBtrans2,              /* cmd. */
3085                                 NULL,                   /* pipe name. */
3086                                 -1,                     /* fid. */
3087                                 0,                      /* function. */
3088                                 0,                      /* flags. */
3089                                 &state->setup,          /* setup. */
3090                                 1,                      /* num setup uint16_t words. */
3091                                 0,                      /* max returned setup. */
3092                                 state->param,           /* param. */
3093                                 4,                      /* num param. */
3094                                 2,                      /* max returned param. */
3095                                 state->data,            /* data. */
3096                                 POSIX_LOCK_DATA_SIZE,   /* num data. */
3097                                 0);                     /* max returned data. */
3098
3099         if (tevent_req_nomem(subreq, req)) {
3100                 return tevent_req_post(req, ev);
3101         }
3102         tevent_req_set_callback(subreq, cli_posix_unlock_internal_done, req);
3103         return req;
3104 }
3105
3106 /****************************************************************************
3107  POSIX Lock a file.
3108 ****************************************************************************/
3109
3110 struct tevent_req *cli_posix_lock_send(TALLOC_CTX *mem_ctx,
3111                                         struct event_context *ev,
3112                                         struct cli_state *cli,
3113                                         uint16_t fnum,
3114                                         uint64_t offset,
3115                                         uint64_t len,
3116                                         bool wait_lock,
3117                                         enum brl_type lock_type)
3118 {
3119         return cli_posix_lock_internal_send(mem_ctx, ev, cli, fnum, offset, len,
3120                                         wait_lock, lock_type);
3121 }
3122
3123 NTSTATUS cli_posix_lock_recv(struct tevent_req *req)
3124 {
3125         NTSTATUS status;
3126
3127         if (tevent_req_is_nterror(req, &status)) {
3128                 return status;
3129         }
3130         return NT_STATUS_OK;
3131 }
3132
3133 NTSTATUS cli_posix_lock(struct cli_state *cli, uint16_t fnum,
3134                         uint64_t offset, uint64_t len,
3135                         bool wait_lock, enum brl_type lock_type)
3136 {
3137         TALLOC_CTX *frame = talloc_stackframe();
3138         struct event_context *ev = NULL;
3139         struct tevent_req *req = NULL;
3140         NTSTATUS status = NT_STATUS_OK;
3141
3142         if (cli_has_async_calls(cli)) {
3143                 /*
3144                  * Can't use sync call while an async call is in flight
3145                  */
3146                 status = NT_STATUS_INVALID_PARAMETER;
3147                 goto fail;
3148         }
3149
3150         if (lock_type != READ_LOCK && lock_type != WRITE_LOCK) {
3151                 status = NT_STATUS_INVALID_PARAMETER;
3152                 goto fail;
3153         }
3154
3155         ev = event_context_init(frame);
3156         if (ev == NULL) {
3157                 status = NT_STATUS_NO_MEMORY;
3158                 goto fail;
3159         }
3160
3161         req = cli_posix_lock_send(frame,
3162                                 ev,
3163                                 cli,
3164                                 fnum,
3165                                 offset,
3166                                 len,
3167                                 wait_lock,
3168                                 lock_type);
3169         if (req == NULL) {
3170                 status = NT_STATUS_NO_MEMORY;
3171                 goto fail;
3172         }
3173
3174         if (!tevent_req_poll(req, ev)) {
3175                 status = map_nt_error_from_unix(errno);
3176                 goto fail;
3177         }
3178
3179         status = cli_posix_lock_recv(req);
3180
3181  fail:
3182         TALLOC_FREE(frame);
3183         if (!NT_STATUS_IS_OK(status)) {
3184                 cli_set_error(cli, status);
3185         }
3186         return status;
3187 }
3188
3189 /****************************************************************************
3190  POSIX Unlock a file.
3191 ****************************************************************************/
3192
3193 struct tevent_req *cli_posix_unlock_send(TALLOC_CTX *mem_ctx,
3194                                         struct event_context *ev,
3195                                         struct cli_state *cli,
3196                                         uint16_t fnum,
3197                                         uint64_t offset,
3198                                         uint64_t len)
3199 {
3200         return cli_posix_lock_internal_send(mem_ctx, ev, cli, fnum, offset, len,
3201                                         false, UNLOCK_LOCK);
3202 }
3203
3204 NTSTATUS cli_posix_unlock_recv(struct tevent_req *req)
3205 {
3206         NTSTATUS status;
3207
3208         if (tevent_req_is_nterror(req, &status)) {
3209                 return status;
3210         }
3211         return NT_STATUS_OK;
3212 }
3213
3214 NTSTATUS cli_posix_unlock(struct cli_state *cli, uint16_t fnum, uint64_t offset, uint64_t len)
3215 {
3216         TALLOC_CTX *frame = talloc_stackframe();
3217         struct event_context *ev = NULL;
3218         struct tevent_req *req = NULL;
3219         NTSTATUS status = NT_STATUS_OK;
3220
3221         if (cli_has_async_calls(cli)) {
3222                 /*
3223                  * Can't use sync call while an async call is in flight
3224                  */
3225                 status = NT_STATUS_INVALID_PARAMETER;
3226                 goto fail;
3227         }
3228
3229         ev = event_context_init(frame);
3230         if (ev == NULL) {
3231                 status = NT_STATUS_NO_MEMORY;
3232                 goto fail;
3233         }
3234
3235         req = cli_posix_unlock_send(frame,
3236                                 ev,
3237                                 cli,
3238                                 fnum,
3239                                 offset,
3240                                 len);
3241         if (req == NULL) {
3242                 status = NT_STATUS_NO_MEMORY;
3243                 goto fail;
3244         }
3245
3246         if (!tevent_req_poll(req, ev)) {
3247                 status = map_nt_error_from_unix(errno);
3248                 goto fail;
3249         }
3250
3251         status = cli_posix_unlock_recv(req);
3252
3253  fail:
3254         TALLOC_FREE(frame);
3255         if (!NT_STATUS_IS_OK(status)) {
3256                 cli_set_error(cli, status);
3257         }
3258         return status;
3259 }
3260
3261 /****************************************************************************
3262  Do a SMBgetattrE call.
3263 ****************************************************************************/
3264
3265 static void cli_getattrE_done(struct tevent_req *subreq);
3266
3267 struct cli_getattrE_state {
3268         uint16_t vwv[1];
3269         int zone_offset;
3270         uint16_t attr;
3271         SMB_OFF_T size;
3272         time_t change_time;
3273         time_t access_time;
3274         time_t write_time;
3275 };
3276
3277 struct tevent_req *cli_getattrE_send(TALLOC_CTX *mem_ctx,
3278                                 struct event_context *ev,
3279                                 struct cli_state *cli,
3280                                 uint16_t fnum)
3281 {
3282         struct tevent_req *req = NULL, *subreq = NULL;
3283         struct cli_getattrE_state *state = NULL;
3284         uint8_t additional_flags = 0;
3285
3286         req = tevent_req_create(mem_ctx, &state, struct cli_getattrE_state);
3287         if (req == NULL) {
3288                 return NULL;
3289         }
3290
3291         state->zone_offset = cli->serverzone;
3292         SSVAL(state->vwv+0,0,fnum);
3293
3294         subreq = cli_smb_send(state, ev, cli, SMBgetattrE, additional_flags,
3295                               1, state->vwv, 0, NULL);
3296         if (tevent_req_nomem(subreq, req)) {
3297                 return tevent_req_