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