64b3e652cf95ad25b394182ce7591718f7d1300e
[samba.git] / source3 / libsmb / clifile.c
1 /* 
2    Unix SMB/CIFS implementation.
3    client file operations
4    Copyright (C) Andrew Tridgell 1994-1998
5    Copyright (C) Jeremy Allison 2001-2002
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 2 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, write to the Free Software
19    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22 #include "includes.h"
23
24 /****************************************************************************
25  Hard/Symlink a file (UNIX extensions).
26  Creates new name (sym)linked to oldname.
27 ****************************************************************************/
28
29 static BOOL cli_link_internal(struct cli_state *cli, const char *oldname, const char *newname, BOOL hard_link)
30 {
31         unsigned int data_len = 0;
32         unsigned int param_len = 0;
33         uint16 setup = TRANSACT2_SETPATHINFO;
34         char param[sizeof(pstring)+6];
35         pstring data;
36         char *rparam=NULL, *rdata=NULL;
37         char *p;
38         size_t oldlen = 2*(strlen(oldname)+1);
39         size_t newlen = 2*(strlen(newname)+1);
40
41         memset(param, 0, sizeof(param));
42         SSVAL(param,0,hard_link ? SMB_SET_FILE_UNIX_HLINK : SMB_SET_FILE_UNIX_LINK);
43         p = &param[6];
44
45         p += clistr_push(cli, p, newname, MIN(newlen, sizeof(param)-6), STR_TERMINATE);
46         param_len = PTR_DIFF(p, param);
47
48         p = data;
49         p += clistr_push(cli, p, oldname, MIN(oldlen,sizeof(data)), STR_TERMINATE);
50         data_len = PTR_DIFF(p, data);
51
52         if (!cli_send_trans(cli, SMBtrans2,
53                 NULL,                        /* name */
54                 -1, 0,                          /* fid, flags */
55                 &setup, 1, 0,                   /* setup, length, max */
56                 param, param_len, 2,            /* param, length, max */
57                 (char *)&data,  data_len, cli->max_xmit /* data, length, max */
58                 )) {
59                         return False;
60         }
61
62         if (!cli_receive_trans(cli, SMBtrans2,
63                 &rparam, &param_len,
64                 &rdata, &data_len)) {
65                         return False;
66         }
67
68         SAFE_FREE(rdata);
69         SAFE_FREE(rparam);
70
71         return True;
72 }
73
74 /****************************************************************************
75  Map standard UNIX permissions onto wire representations.
76 ****************************************************************************/
77
78 uint32 unix_perms_to_wire(mode_t perms)
79 {
80         unsigned int ret = 0;
81
82         ret |= ((perms & S_IXOTH) ?  UNIX_X_OTH : 0);
83         ret |= ((perms & S_IWOTH) ?  UNIX_W_OTH : 0);
84         ret |= ((perms & S_IROTH) ?  UNIX_R_OTH : 0);
85         ret |= ((perms & S_IXGRP) ?  UNIX_X_GRP : 0);
86         ret |= ((perms & S_IWGRP) ?  UNIX_W_GRP : 0);
87         ret |= ((perms & S_IRGRP) ?  UNIX_R_GRP : 0);
88         ret |= ((perms & S_IXUSR) ?  UNIX_X_USR : 0);
89         ret |= ((perms & S_IWUSR) ?  UNIX_W_USR : 0);
90         ret |= ((perms & S_IRUSR) ?  UNIX_R_USR : 0);
91 #ifdef S_ISVTX
92         ret |= ((perms & S_ISVTX) ?  UNIX_STICKY : 0);
93 #endif
94 #ifdef S_ISGID
95         ret |= ((perms & S_ISGID) ?  UNIX_SET_GID : 0);
96 #endif
97 #ifdef S_ISUID
98         ret |= ((perms & S_ISUID) ?  UNIX_SET_UID : 0);
99 #endif
100         return ret;
101 }
102
103 /****************************************************************************
104  Map wire permissions to standard UNIX.
105 ****************************************************************************/
106
107 mode_t wire_perms_to_unix(uint32 perms)
108 {
109         mode_t ret = (mode_t)0;
110
111         ret |= ((perms & UNIX_X_OTH) ? S_IXOTH : 0);
112         ret |= ((perms & UNIX_W_OTH) ? S_IWOTH : 0);
113         ret |= ((perms & UNIX_R_OTH) ? S_IROTH : 0);
114         ret |= ((perms & UNIX_X_GRP) ? S_IXGRP : 0);
115         ret |= ((perms & UNIX_W_GRP) ? S_IWGRP : 0);
116         ret |= ((perms & UNIX_R_GRP) ? S_IRGRP : 0);
117         ret |= ((perms & UNIX_X_USR) ? S_IXUSR : 0);
118         ret |= ((perms & UNIX_W_USR) ? S_IWUSR : 0);
119         ret |= ((perms & UNIX_R_USR) ? S_IRUSR : 0);
120 #ifdef S_ISVTX
121         ret |= ((perms & UNIX_STICKY) ? S_ISVTX : 0);
122 #endif
123 #ifdef S_ISGID
124         ret |= ((perms & UNIX_SET_GID) ? S_ISGID : 0);
125 #endif
126 #ifdef S_ISUID
127         ret |= ((perms & UNIX_SET_UID) ? S_ISUID : 0);
128 #endif
129         return ret;
130 }
131
132 /****************************************************************************
133  Return the file type from the wire filetype for UNIX extensions.
134 ****************************************************************************/
135                                                                                                                 
136 static mode_t unix_filetype_from_wire(uint32 wire_type)
137 {
138         switch (wire_type) {
139                 case UNIX_TYPE_FILE:
140                         return S_IFREG;
141                 case UNIX_TYPE_DIR:
142                         return S_IFDIR;
143 #ifdef S_IFLNK
144                 case UNIX_TYPE_SYMLINK:
145                         return S_IFLNK;
146 #endif
147 #ifdef S_IFCHR
148                 case UNIX_TYPE_CHARDEV:
149                         return S_IFCHR;
150 #endif
151 #ifdef S_IFBLK
152                 case UNIX_TYPE_BLKDEV:
153                         return S_IFBLK;
154 #endif
155 #ifdef S_IFIFO
156                 case UNIX_TYPE_FIFO:
157                         return S_IFIFO;
158 #endif
159 #ifdef S_IFSOCK
160                 case UNIX_TYPE_SOCKET:
161                         return S_IFSOCK;
162 #endif
163                 default:
164                         return (mode_t)0;
165         }
166 }
167
168 /****************************************************************************
169  Do a POSIX getfacl (UNIX extensions).
170 ****************************************************************************/
171
172 BOOL cli_unix_getfacl(struct cli_state *cli, const char *name, size_t *prb_size, char **retbuf)
173 {
174         unsigned int param_len = 0;
175         unsigned int data_len = 0;
176         uint16 setup = TRANSACT2_QPATHINFO;
177         char param[sizeof(pstring)+6];
178         char *rparam=NULL, *rdata=NULL;
179         char *p;
180
181         p = param;
182         memset(p, 0, 6);
183         SSVAL(p, 0, SMB_QUERY_POSIX_ACL);
184         p += 6;
185         p += clistr_push(cli, p, name, sizeof(pstring)-6, STR_TERMINATE);
186         param_len = PTR_DIFF(p, param);
187
188         if (!cli_send_trans(cli, SMBtrans2,
189                 NULL,                        /* name */
190                 -1, 0,                       /* fid, flags */
191                 &setup, 1, 0,                /* setup, length, max */
192                 param, param_len, 2,         /* param, length, max */
193                 NULL,  0, cli->max_xmit      /* data, length, max */
194                 )) {
195                         return False;
196         }
197
198         if (!cli_receive_trans(cli, SMBtrans2,
199                 &rparam, &param_len,
200                 &rdata, &data_len)) {
201                         return False;
202         }
203
204         if (data_len < 6) {
205                 SAFE_FREE(rdata);
206                 SAFE_FREE(rparam);
207                 return False;
208         }
209
210         SAFE_FREE(rparam);
211         *retbuf = rdata;
212         *prb_size = (size_t)data_len;
213
214         return True;
215 }
216
217 /****************************************************************************
218  Stat a file (UNIX extensions).
219 ****************************************************************************/
220
221 BOOL cli_unix_stat(struct cli_state *cli, const char *name, SMB_STRUCT_STAT *sbuf)
222 {
223         unsigned int param_len = 0;
224         unsigned int data_len = 0;
225         uint16 setup = TRANSACT2_QPATHINFO;
226         char param[sizeof(pstring)+6];
227         char *rparam=NULL, *rdata=NULL;
228         char *p;
229
230         ZERO_STRUCTP(sbuf);
231
232         p = param;
233         memset(p, 0, 6);
234         SSVAL(p, 0, SMB_QUERY_FILE_UNIX_BASIC);
235         p += 6;
236         p += clistr_push(cli, p, name, sizeof(pstring)-6, STR_TERMINATE);
237         param_len = PTR_DIFF(p, param);
238
239         if (!cli_send_trans(cli, SMBtrans2,
240                 NULL,                        /* name */
241                 -1, 0,                       /* fid, flags */
242                 &setup, 1, 0,                /* setup, length, max */
243                 param, param_len, 2,         /* param, length, max */
244                 NULL,  0, cli->max_xmit      /* data, length, max */
245                 )) {
246                         return False;
247         }
248
249         if (!cli_receive_trans(cli, SMBtrans2,
250                 &rparam, &param_len,
251                 &rdata, &data_len)) {
252                         return False;
253         }
254
255         if (data_len < 96) {
256                 SAFE_FREE(rdata);
257                 SAFE_FREE(rparam);
258                 return False;
259         }
260
261         sbuf->st_size = IVAL2_TO_SMB_BIG_UINT(rdata,0);     /* total size, in bytes */
262         sbuf->st_blocks = IVAL2_TO_SMB_BIG_UINT(rdata,8);   /* number of blocks allocated */
263 #if defined (HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
264         sbuf->st_blocks /= STAT_ST_BLOCKSIZE;
265 #else
266         /* assume 512 byte blocks */
267         sbuf->st_blocks /= 512;
268 #endif
269         set_ctimespec(sbuf, interpret_long_date(rdata + 16));    /* time of last change */
270         set_atimespec(sbuf, interpret_long_date(rdata + 24));    /* time of last access */
271         set_mtimespec(sbuf, interpret_long_date(rdata + 32));    /* time of last modification */
272
273         sbuf->st_uid = (uid_t) IVAL(rdata,40);      /* user ID of owner */
274         sbuf->st_gid = (gid_t) IVAL(rdata,48);      /* group ID of owner */
275         sbuf->st_mode |= unix_filetype_from_wire(IVAL(rdata, 56));
276 #if defined(HAVE_MAKEDEV)
277         {
278                 uint32 dev_major = IVAL(rdata,60);
279                 uint32 dev_minor = IVAL(rdata,68);
280                 sbuf->st_rdev = makedev(dev_major, dev_minor);
281         }
282 #endif
283         sbuf->st_ino = (SMB_INO_T)IVAL2_TO_SMB_BIG_UINT(rdata,76);      /* inode */
284         sbuf->st_mode |= wire_perms_to_unix(IVAL(rdata,84));     /* protection */
285         sbuf->st_nlink = IVAL(rdata,92);    /* number of hard links */
286
287         SAFE_FREE(rdata);
288         SAFE_FREE(rparam);
289
290         return True;
291 }
292
293 /****************************************************************************
294  Symlink a file (UNIX extensions).
295 ****************************************************************************/
296
297 BOOL cli_unix_symlink(struct cli_state *cli, const char *oldname, const char *newname)
298 {
299         return cli_link_internal(cli, oldname, newname, False);
300 }
301
302 /****************************************************************************
303  Hard a file (UNIX extensions).
304 ****************************************************************************/
305
306 BOOL cli_unix_hardlink(struct cli_state *cli, const char *oldname, const char *newname)
307 {
308         return cli_link_internal(cli, oldname, newname, True);
309 }
310
311 /****************************************************************************
312  Chmod or chown a file internal (UNIX extensions).
313 ****************************************************************************/
314
315 static BOOL cli_unix_chmod_chown_internal(struct cli_state *cli, const char *fname, uint32 mode, uint32 uid, uint32 gid)
316 {
317         unsigned int data_len = 0;
318         unsigned int param_len = 0;
319         uint16 setup = TRANSACT2_SETPATHINFO;
320         char param[sizeof(pstring)+6];
321         char data[100];
322         char *rparam=NULL, *rdata=NULL;
323         char *p;
324
325         memset(param, 0, sizeof(param));
326         memset(data, 0, sizeof(data));
327         SSVAL(param,0,SMB_SET_FILE_UNIX_BASIC);
328         p = &param[6];
329
330         p += clistr_push(cli, p, fname, -1, STR_TERMINATE);
331         param_len = PTR_DIFF(p, param);
332
333         memset(data, 0xff, 40); /* Set all sizes/times to no change. */
334
335         SIVAL(data,40,uid);
336         SIVAL(data,48,gid);
337         SIVAL(data,84,mode);
338
339         data_len = 100;
340
341         if (!cli_send_trans(cli, SMBtrans2,
342                 NULL,                        /* name */
343                 -1, 0,                          /* fid, flags */
344                 &setup, 1, 0,                   /* setup, length, max */
345                 param, param_len, 2,            /* param, length, max */
346                 (char *)&data,  data_len, cli->max_xmit /* data, length, max */
347                 )) {
348                         return False;
349         }
350
351         if (!cli_receive_trans(cli, SMBtrans2,
352                 &rparam, &param_len,
353                 &rdata, &data_len)) {
354                         return False;
355         }
356
357         SAFE_FREE(rdata);
358         SAFE_FREE(rparam);
359
360         return True;
361 }
362
363 /****************************************************************************
364  chmod a file (UNIX extensions).
365 ****************************************************************************/
366
367 BOOL cli_unix_chmod(struct cli_state *cli, const char *fname, mode_t mode)
368 {
369         return cli_unix_chmod_chown_internal(cli, fname, 
370                 unix_perms_to_wire(mode), SMB_UID_NO_CHANGE, SMB_GID_NO_CHANGE);
371 }
372
373 /****************************************************************************
374  chown a file (UNIX extensions).
375 ****************************************************************************/
376
377 BOOL cli_unix_chown(struct cli_state *cli, const char *fname, uid_t uid, gid_t gid)
378 {
379         return cli_unix_chmod_chown_internal(cli, fname, SMB_MODE_NO_CHANGE, (uint32)uid, (uint32)gid);
380 }
381
382 /****************************************************************************
383  Rename a file.
384 ****************************************************************************/
385
386 BOOL cli_rename(struct cli_state *cli, const char *fname_src, const char *fname_dst)
387 {
388         char *p;
389
390         memset(cli->outbuf,'\0',smb_size);
391         memset(cli->inbuf,'\0',smb_size);
392
393         set_message(NULL,cli->outbuf,1, 0, True);
394
395         SCVAL(cli->outbuf,smb_com,SMBmv);
396         SSVAL(cli->outbuf,smb_tid,cli->cnum);
397         cli_setup_packet(cli);
398
399         SSVAL(cli->outbuf,smb_vwv0,aSYSTEM | aHIDDEN | aDIR);
400
401         p = smb_buf(cli->outbuf);
402         *p++ = 4;
403         p += clistr_push(cli, p, fname_src, -1, STR_TERMINATE);
404         *p++ = 4;
405         p += clistr_push(cli, p, fname_dst, -1, STR_TERMINATE);
406
407         cli_setup_bcc(cli, p);
408
409         cli_send_smb(cli);
410         if (!cli_receive_smb(cli))
411                 return False;
412
413         if (cli_is_error(cli))
414                 return False;
415
416         return True;
417 }
418
419 /****************************************************************************
420  NT Rename a file.
421 ****************************************************************************/
422
423 BOOL cli_ntrename(struct cli_state *cli, const char *fname_src, const char *fname_dst)
424 {
425         char *p;
426
427         memset(cli->outbuf,'\0',smb_size);
428         memset(cli->inbuf,'\0',smb_size);
429
430         set_message(NULL,cli->outbuf, 4, 0, True);
431
432         SCVAL(cli->outbuf,smb_com,SMBntrename);
433         SSVAL(cli->outbuf,smb_tid,cli->cnum);
434         cli_setup_packet(cli);
435
436         SSVAL(cli->outbuf,smb_vwv0,aSYSTEM | aHIDDEN | aDIR);
437         SSVAL(cli->outbuf,smb_vwv1, RENAME_FLAG_RENAME);
438
439         p = smb_buf(cli->outbuf);
440         *p++ = 4;
441         p += clistr_push(cli, p, fname_src, -1, STR_TERMINATE);
442         *p++ = 4;
443         p += clistr_push(cli, p, fname_dst, -1, STR_TERMINATE);
444
445         cli_setup_bcc(cli, p);
446
447         cli_send_smb(cli);
448         if (!cli_receive_smb(cli))
449                 return False;
450
451         if (cli_is_error(cli))
452                 return False;
453
454         return True;
455 }
456
457 /****************************************************************************
458  NT hardlink a file.
459 ****************************************************************************/
460
461 BOOL cli_nt_hardlink(struct cli_state *cli, const char *fname_src, const char *fname_dst)
462 {
463         char *p;
464
465         memset(cli->outbuf,'\0',smb_size);
466         memset(cli->inbuf,'\0',smb_size);
467
468         set_message(NULL,cli->outbuf, 4, 0, True);
469
470         SCVAL(cli->outbuf,smb_com,SMBntrename);
471         SSVAL(cli->outbuf,smb_tid,cli->cnum);
472         cli_setup_packet(cli);
473
474         SSVAL(cli->outbuf,smb_vwv0,aSYSTEM | aHIDDEN | aDIR);
475         SSVAL(cli->outbuf,smb_vwv1, RENAME_FLAG_HARD_LINK);
476
477         p = smb_buf(cli->outbuf);
478         *p++ = 4;
479         p += clistr_push(cli, p, fname_src, -1, STR_TERMINATE);
480         *p++ = 4;
481         p += clistr_push(cli, p, fname_dst, -1, STR_TERMINATE);
482
483         cli_setup_bcc(cli, p);
484
485         cli_send_smb(cli);
486         if (!cli_receive_smb(cli))
487                 return False;
488
489         if (cli_is_error(cli))
490                 return False;
491
492         return True;
493 }
494
495 /****************************************************************************
496  Delete a file.
497 ****************************************************************************/
498
499 BOOL cli_unlink_full(struct cli_state *cli, const char *fname, uint16 attrs)
500 {
501         char *p;
502
503         memset(cli->outbuf,'\0',smb_size);
504         memset(cli->inbuf,'\0',smb_size);
505
506         set_message(NULL,cli->outbuf,1, 0,True);
507
508         SCVAL(cli->outbuf,smb_com,SMBunlink);
509         SSVAL(cli->outbuf,smb_tid,cli->cnum);
510         cli_setup_packet(cli);
511
512         SSVAL(cli->outbuf,smb_vwv0, attrs);
513   
514         p = smb_buf(cli->outbuf);
515         *p++ = 4;      
516         p += clistr_push(cli, p, fname, -1, STR_TERMINATE);
517
518         cli_setup_bcc(cli, p);
519         cli_send_smb(cli);
520         if (!cli_receive_smb(cli)) {
521                 return False;
522         }
523
524         if (cli_is_error(cli)) {
525                 return False;
526         }
527
528         return True;
529 }
530
531 /****************************************************************************
532  Delete a file.
533 ****************************************************************************/
534
535 BOOL cli_unlink(struct cli_state *cli, const char *fname)
536 {
537         return cli_unlink_full(cli, fname, aSYSTEM | aHIDDEN);
538 }
539
540 /****************************************************************************
541  Create a directory.
542 ****************************************************************************/
543
544 BOOL cli_mkdir(struct cli_state *cli, const char *dname)
545 {
546         char *p;
547
548         memset(cli->outbuf,'\0',smb_size);
549         memset(cli->inbuf,'\0',smb_size);
550
551         set_message(NULL,cli->outbuf,0, 0,True);
552
553         SCVAL(cli->outbuf,smb_com,SMBmkdir);
554         SSVAL(cli->outbuf,smb_tid,cli->cnum);
555         cli_setup_packet(cli);
556
557         p = smb_buf(cli->outbuf);
558         *p++ = 4;      
559         p += clistr_push(cli, p, dname, -1, STR_TERMINATE);
560
561         cli_setup_bcc(cli, p);
562
563         cli_send_smb(cli);
564         if (!cli_receive_smb(cli)) {
565                 return False;
566         }
567
568         if (cli_is_error(cli)) {
569                 return False;
570         }
571
572         return True;
573 }
574
575 /****************************************************************************
576  Remove a directory.
577 ****************************************************************************/
578
579 BOOL cli_rmdir(struct cli_state *cli, const char *dname)
580 {
581         char *p;
582
583         memset(cli->outbuf,'\0',smb_size);
584         memset(cli->inbuf,'\0',smb_size);
585
586         set_message(NULL,cli->outbuf,0, 0, True);
587
588         SCVAL(cli->outbuf,smb_com,SMBrmdir);
589         SSVAL(cli->outbuf,smb_tid,cli->cnum);
590         cli_setup_packet(cli);
591
592         p = smb_buf(cli->outbuf);
593         *p++ = 4;      
594         p += clistr_push(cli, p, dname, -1, STR_TERMINATE);
595
596         cli_setup_bcc(cli, p);
597
598         cli_send_smb(cli);
599         if (!cli_receive_smb(cli)) {
600                 return False;
601         }
602
603         if (cli_is_error(cli)) {
604                 return False;
605         }
606
607         return True;
608 }
609
610 /****************************************************************************
611  Set or clear the delete on close flag.
612 ****************************************************************************/
613
614 int cli_nt_delete_on_close(struct cli_state *cli, int fnum, BOOL flag)
615 {
616         unsigned int data_len = 1;
617         unsigned int param_len = 6;
618         uint16 setup = TRANSACT2_SETFILEINFO;
619         pstring param;
620         unsigned char data;
621         char *rparam=NULL, *rdata=NULL;
622
623         memset(param, 0, param_len);
624         SSVAL(param,0,fnum);
625         SSVAL(param,2,SMB_SET_FILE_DISPOSITION_INFO);
626
627         data = flag ? 1 : 0;
628
629         if (!cli_send_trans(cli, SMBtrans2,
630                                                 NULL,                        /* name */
631                                                 -1, 0,                          /* fid, flags */
632                                                 &setup, 1, 0,                   /* setup, length, max */
633                                                 param, param_len, 2,            /* param, length, max */
634                                                 (char *)&data,  data_len, cli->max_xmit /* data, length, max */
635                                                 )) {
636                 return False;
637         }
638
639         if (!cli_receive_trans(cli, SMBtrans2,
640                                                 &rparam, &param_len,
641                                                 &rdata, &data_len)) {
642                 return False;
643         }
644
645         SAFE_FREE(rdata);
646         SAFE_FREE(rparam);
647
648         return True;
649 }
650
651 /****************************************************************************
652  Open a file - exposing the full horror of the NT API :-).
653  Used in smbtorture.
654 ****************************************************************************/
655
656 int cli_nt_create_full(struct cli_state *cli, const char *fname, 
657                  uint32 CreatFlags, uint32 DesiredAccess,
658                  uint32 FileAttributes, uint32 ShareAccess,
659                  uint32 CreateDisposition, uint32 CreateOptions,
660                  uint8 SecuityFlags)
661 {
662         char *p;
663         int len;
664
665         memset(cli->outbuf,'\0',smb_size);
666         memset(cli->inbuf,'\0',smb_size);
667
668         set_message(NULL,cli->outbuf,24,0,True);
669
670         SCVAL(cli->outbuf,smb_com,SMBntcreateX);
671         SSVAL(cli->outbuf,smb_tid,cli->cnum);
672         cli_setup_packet(cli);
673
674         SSVAL(cli->outbuf,smb_vwv0,0xFF);
675         if (cli->use_oplocks)
676                 CreatFlags |= (REQUEST_OPLOCK|REQUEST_BATCH_OPLOCK);
677         
678         SIVAL(cli->outbuf,smb_ntcreate_Flags, CreatFlags);
679         SIVAL(cli->outbuf,smb_ntcreate_RootDirectoryFid, 0x0);
680         SIVAL(cli->outbuf,smb_ntcreate_DesiredAccess, DesiredAccess);
681         SIVAL(cli->outbuf,smb_ntcreate_FileAttributes, FileAttributes);
682         SIVAL(cli->outbuf,smb_ntcreate_ShareAccess, ShareAccess);
683         SIVAL(cli->outbuf,smb_ntcreate_CreateDisposition, CreateDisposition);
684         SIVAL(cli->outbuf,smb_ntcreate_CreateOptions, CreateOptions);
685         SIVAL(cli->outbuf,smb_ntcreate_ImpersonationLevel, 0x02);
686         SCVAL(cli->outbuf,smb_ntcreate_SecurityFlags, SecuityFlags);
687
688         p = smb_buf(cli->outbuf);
689         /* this alignment and termination is critical for netapp filers. Don't change */
690         p += clistr_align_out(cli, p, 0);
691         len = clistr_push(cli, p, fname, -1, 0);
692         p += len;
693         SSVAL(cli->outbuf,smb_ntcreate_NameLength, len);
694         /* sigh. this copes with broken netapp filer behaviour */
695         p += clistr_push(cli, p, "", -1, STR_TERMINATE);
696
697         cli_setup_bcc(cli, p);
698
699         cli_send_smb(cli);
700         if (!cli_receive_smb(cli)) {
701                 return -1;
702         }
703
704         if (cli_is_error(cli)) {
705                 return -1;
706         }
707
708         return SVAL(cli->inbuf,smb_vwv2 + 1);
709 }
710
711 /****************************************************************************
712  Open a file.
713 ****************************************************************************/
714
715 int cli_nt_create(struct cli_state *cli, const char *fname, uint32 DesiredAccess)
716 {
717         return cli_nt_create_full(cli, fname, 0, DesiredAccess, 0,
718                                 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN, 0x0, 0x0);
719 }
720
721 /****************************************************************************
722  Open a file
723  WARNING: if you open with O_WRONLY then getattrE won't work!
724 ****************************************************************************/
725
726 int cli_open(struct cli_state *cli, const char *fname, int flags, int share_mode)
727 {
728         char *p;
729         unsigned openfn=0;
730         unsigned accessmode=0;
731
732         if (flags & O_CREAT)
733                 openfn |= (1<<4);
734         if (!(flags & O_EXCL)) {
735                 if (flags & O_TRUNC)
736                         openfn |= (1<<1);
737                 else
738                         openfn |= (1<<0);
739         }
740
741         accessmode = (share_mode<<4);
742
743         if ((flags & O_ACCMODE) == O_RDWR) {
744                 accessmode |= 2;
745         } else if ((flags & O_ACCMODE) == O_WRONLY) {
746                 accessmode |= 1;
747         } 
748
749 #if defined(O_SYNC)
750         if ((flags & O_SYNC) == O_SYNC) {
751                 accessmode |= (1<<14);
752         }
753 #endif /* O_SYNC */
754
755         if (share_mode == DENY_FCB) {
756                 accessmode = 0xFF;
757         }
758
759         memset(cli->outbuf,'\0',smb_size);
760         memset(cli->inbuf,'\0',smb_size);
761
762         set_message(NULL,cli->outbuf,15,0,True);
763
764         SCVAL(cli->outbuf,smb_com,SMBopenX);
765         SSVAL(cli->outbuf,smb_tid,cli->cnum);
766         cli_setup_packet(cli);
767
768         SSVAL(cli->outbuf,smb_vwv0,0xFF);
769         SSVAL(cli->outbuf,smb_vwv2,0);  /* no additional info */
770         SSVAL(cli->outbuf,smb_vwv3,accessmode);
771         SSVAL(cli->outbuf,smb_vwv4,aSYSTEM | aHIDDEN);
772         SSVAL(cli->outbuf,smb_vwv5,0);
773         SSVAL(cli->outbuf,smb_vwv8,openfn);
774
775         if (cli->use_oplocks) {
776                 /* if using oplocks then ask for a batch oplock via
777                    core and extended methods */
778                 SCVAL(cli->outbuf,smb_flg, CVAL(cli->outbuf,smb_flg)|
779                         FLAG_REQUEST_OPLOCK|FLAG_REQUEST_BATCH_OPLOCK);
780                 SSVAL(cli->outbuf,smb_vwv2,SVAL(cli->outbuf,smb_vwv2) | 6);
781         }
782   
783         p = smb_buf(cli->outbuf);
784         p += clistr_push(cli, p, fname, -1, STR_TERMINATE);
785
786         cli_setup_bcc(cli, p);
787
788         cli_send_smb(cli);
789         if (!cli_receive_smb(cli)) {
790                 return -1;
791         }
792
793         if (cli_is_error(cli)) {
794                 return -1;
795         }
796
797         return SVAL(cli->inbuf,smb_vwv2);
798 }
799
800 /****************************************************************************
801  Close a file.
802 ****************************************************************************/
803
804 BOOL cli_close(struct cli_state *cli, int fnum)
805 {
806         memset(cli->outbuf,'\0',smb_size);
807         memset(cli->inbuf,'\0',smb_size);
808
809         set_message(NULL,cli->outbuf,3,0,True);
810
811         SCVAL(cli->outbuf,smb_com,SMBclose);
812         SSVAL(cli->outbuf,smb_tid,cli->cnum);
813         cli_setup_packet(cli);
814
815         SSVAL(cli->outbuf,smb_vwv0,fnum);
816         SIVALS(cli->outbuf,smb_vwv1,-1);
817
818         cli_send_smb(cli);
819         if (!cli_receive_smb(cli)) {
820                 return False;
821         }
822
823         return !cli_is_error(cli);
824 }
825
826
827 /****************************************************************************
828  send a lock with a specified locktype 
829  this is used for testing LOCKING_ANDX_CANCEL_LOCK
830 ****************************************************************************/
831
832 NTSTATUS cli_locktype(struct cli_state *cli, int fnum, 
833                       uint32 offset, uint32 len, int timeout, unsigned char locktype)
834 {
835         char *p;
836         int saved_timeout = cli->timeout;
837
838         memset(cli->outbuf,'\0',smb_size);
839         memset(cli->inbuf,'\0', smb_size);
840
841         set_message(NULL,cli->outbuf,8,0,True);
842
843         SCVAL(cli->outbuf,smb_com,SMBlockingX);
844         SSVAL(cli->outbuf,smb_tid,cli->cnum);
845         cli_setup_packet(cli);
846
847         SCVAL(cli->outbuf,smb_vwv0,0xFF);
848         SSVAL(cli->outbuf,smb_vwv2,fnum);
849         SCVAL(cli->outbuf,smb_vwv3,locktype);
850         SIVALS(cli->outbuf, smb_vwv4, timeout);
851         SSVAL(cli->outbuf,smb_vwv6,0);
852         SSVAL(cli->outbuf,smb_vwv7,1);
853
854         p = smb_buf(cli->outbuf);
855         SSVAL(p, 0, cli->pid);
856         SIVAL(p, 2, offset);
857         SIVAL(p, 6, len);
858
859         p += 10;
860
861         cli_setup_bcc(cli, p);
862
863         cli_send_smb(cli);
864
865         if (timeout != 0) {
866                 cli->timeout = (timeout == -1) ? 0x7FFFFFFF : (timeout + 2*1000);
867         }
868
869         if (!cli_receive_smb(cli)) {
870                 cli->timeout = saved_timeout;
871                 return NT_STATUS_UNSUCCESSFUL;
872         }
873
874         cli->timeout = saved_timeout;
875
876         return cli_nt_error(cli);
877 }
878
879 /****************************************************************************
880  Lock a file.
881  note that timeout is in units of 2 milliseconds
882 ****************************************************************************/
883
884 BOOL cli_lock(struct cli_state *cli, int fnum, 
885               uint32 offset, uint32 len, int timeout, enum brl_type lock_type)
886 {
887         char *p;
888         int saved_timeout = cli->timeout;
889
890         memset(cli->outbuf,'\0',smb_size);
891         memset(cli->inbuf,'\0', smb_size);
892
893         set_message(NULL,cli->outbuf,8,0,True);
894
895         SCVAL(cli->outbuf,smb_com,SMBlockingX);
896         SSVAL(cli->outbuf,smb_tid,cli->cnum);
897         cli_setup_packet(cli);
898
899         SCVAL(cli->outbuf,smb_vwv0,0xFF);
900         SSVAL(cli->outbuf,smb_vwv2,fnum);
901         SCVAL(cli->outbuf,smb_vwv3,(lock_type == READ_LOCK? 1 : 0));
902         SIVALS(cli->outbuf, smb_vwv4, timeout);
903         SSVAL(cli->outbuf,smb_vwv6,0);
904         SSVAL(cli->outbuf,smb_vwv7,1);
905
906         p = smb_buf(cli->outbuf);
907         SSVAL(p, 0, cli->pid);
908         SIVAL(p, 2, offset);
909         SIVAL(p, 6, len);
910
911         p += 10;
912
913         cli_setup_bcc(cli, p);
914
915         cli_send_smb(cli);
916
917         if (timeout != 0) {
918                 cli->timeout = (timeout == -1) ? 0x7FFFFFFF : (timeout*2 + 5*1000);
919         }
920
921         if (!cli_receive_smb(cli)) {
922                 cli->timeout = saved_timeout;
923                 return False;
924         }
925
926         cli->timeout = saved_timeout;
927
928         if (cli_is_error(cli)) {
929                 return False;
930         }
931
932         return True;
933 }
934
935 /****************************************************************************
936  Unlock a file.
937 ****************************************************************************/
938
939 BOOL cli_unlock(struct cli_state *cli, int fnum, uint32 offset, uint32 len)
940 {
941         char *p;
942
943         memset(cli->outbuf,'\0',smb_size);
944         memset(cli->inbuf,'\0',smb_size);
945
946         set_message(NULL,cli->outbuf,8,0,True);
947
948         SCVAL(cli->outbuf,smb_com,SMBlockingX);
949         SSVAL(cli->outbuf,smb_tid,cli->cnum);
950         cli_setup_packet(cli);
951
952         SCVAL(cli->outbuf,smb_vwv0,0xFF);
953         SSVAL(cli->outbuf,smb_vwv2,fnum);
954         SCVAL(cli->outbuf,smb_vwv3,0);
955         SIVALS(cli->outbuf, smb_vwv4, 0);
956         SSVAL(cli->outbuf,smb_vwv6,1);
957         SSVAL(cli->outbuf,smb_vwv7,0);
958
959         p = smb_buf(cli->outbuf);
960         SSVAL(p, 0, cli->pid);
961         SIVAL(p, 2, offset);
962         SIVAL(p, 6, len);
963         p += 10;
964         cli_setup_bcc(cli, p);
965         cli_send_smb(cli);
966         if (!cli_receive_smb(cli)) {
967                 return False;
968         }
969
970         if (cli_is_error(cli)) {
971                 return False;
972         }
973
974         return True;
975 }
976
977 /****************************************************************************
978  Lock a file with 64 bit offsets.
979 ****************************************************************************/
980
981 BOOL cli_lock64(struct cli_state *cli, int fnum, 
982                 SMB_BIG_UINT offset, SMB_BIG_UINT len, int timeout, enum brl_type lock_type)
983 {
984         char *p;
985         int saved_timeout = cli->timeout;
986         int ltype;
987
988         if (! (cli->capabilities & CAP_LARGE_FILES)) {
989                 return cli_lock(cli, fnum, offset, len, timeout, lock_type);
990         }
991
992         ltype = (lock_type == READ_LOCK? 1 : 0);
993         ltype |= LOCKING_ANDX_LARGE_FILES;
994
995         memset(cli->outbuf,'\0',smb_size);
996         memset(cli->inbuf,'\0', smb_size);
997
998         set_message(NULL,cli->outbuf,8,0,True);
999
1000         SCVAL(cli->outbuf,smb_com,SMBlockingX);
1001         SSVAL(cli->outbuf,smb_tid,cli->cnum);
1002         cli_setup_packet(cli);
1003
1004         SCVAL(cli->outbuf,smb_vwv0,0xFF);
1005         SSVAL(cli->outbuf,smb_vwv2,fnum);
1006         SCVAL(cli->outbuf,smb_vwv3,ltype);
1007         SIVALS(cli->outbuf, smb_vwv4, timeout);
1008         SSVAL(cli->outbuf,smb_vwv6,0);
1009         SSVAL(cli->outbuf,smb_vwv7,1);
1010
1011         p = smb_buf(cli->outbuf);
1012         SIVAL(p, 0, cli->pid);
1013         SOFF_T_R(p, 4, offset);
1014         SOFF_T_R(p, 12, len);
1015         p += 20;
1016
1017         cli_setup_bcc(cli, p);
1018         cli_send_smb(cli);
1019
1020         if (timeout != 0) {
1021                 cli->timeout = (timeout == -1) ? 0x7FFFFFFF : (timeout + 5*1000);
1022         }
1023
1024         if (!cli_receive_smb(cli)) {
1025                 cli->timeout = saved_timeout;
1026                 return False;
1027         }
1028
1029         cli->timeout = saved_timeout;
1030
1031         if (cli_is_error(cli)) {
1032                 return False;
1033         }
1034
1035         return True;
1036 }
1037
1038 /****************************************************************************
1039  Unlock a file with 64 bit offsets.
1040 ****************************************************************************/
1041
1042 BOOL cli_unlock64(struct cli_state *cli, int fnum, SMB_BIG_UINT offset, SMB_BIG_UINT len)
1043 {
1044         char *p;
1045
1046         if (! (cli->capabilities & CAP_LARGE_FILES)) {
1047                 return cli_unlock(cli, fnum, offset, len);
1048         }
1049
1050         memset(cli->outbuf,'\0',smb_size);
1051         memset(cli->inbuf,'\0',smb_size);
1052
1053         set_message(NULL,cli->outbuf,8,0,True);
1054
1055         SCVAL(cli->outbuf,smb_com,SMBlockingX);
1056         SSVAL(cli->outbuf,smb_tid,cli->cnum);
1057         cli_setup_packet(cli);
1058
1059         SCVAL(cli->outbuf,smb_vwv0,0xFF);
1060         SSVAL(cli->outbuf,smb_vwv2,fnum);
1061         SCVAL(cli->outbuf,smb_vwv3,LOCKING_ANDX_LARGE_FILES);
1062         SIVALS(cli->outbuf, smb_vwv4, 0);
1063         SSVAL(cli->outbuf,smb_vwv6,1);
1064         SSVAL(cli->outbuf,smb_vwv7,0);
1065
1066         p = smb_buf(cli->outbuf);
1067         SIVAL(p, 0, cli->pid);
1068         SOFF_T_R(p, 4, offset);
1069         SOFF_T_R(p, 12, len);
1070         p += 20;
1071         cli_setup_bcc(cli, p);
1072         cli_send_smb(cli);
1073         if (!cli_receive_smb(cli)) {
1074                 return False;
1075         }
1076
1077         if (cli_is_error(cli)) {
1078                 return False;
1079         }
1080
1081         return True;
1082 }
1083
1084 /****************************************************************************
1085  Get/unlock a POSIX lock on a file - internal function.
1086 ****************************************************************************/
1087
1088 static BOOL cli_posix_lock_internal(struct cli_state *cli, int fnum, 
1089                 SMB_BIG_UINT offset, SMB_BIG_UINT len, BOOL wait_lock, enum brl_type lock_type)
1090 {
1091         unsigned int param_len = 4;
1092         unsigned int data_len = POSIX_LOCK_DATA_SIZE;
1093         uint16 setup = TRANSACT2_SETFILEINFO;
1094         char param[4];
1095         unsigned char data[POSIX_LOCK_DATA_SIZE];
1096         char *rparam=NULL, *rdata=NULL;
1097         int saved_timeout = cli->timeout;
1098
1099         SSVAL(param,0,fnum);
1100         SSVAL(param,2,SMB_SET_POSIX_LOCK);
1101
1102         switch (lock_type) {
1103                 case READ_LOCK:
1104                         SSVAL(data, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_READ);
1105                         break;
1106                 case WRITE_LOCK:
1107                         SSVAL(data, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_WRITE);
1108                         break;
1109                 case UNLOCK_LOCK:
1110                         SSVAL(data, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
1111                         break;
1112                 default:
1113                         return False;
1114         }
1115
1116         if (wait_lock) {
1117                 SSVAL(data, POSIX_LOCK_FLAGS_OFFSET, POSIX_LOCK_FLAG_WAIT);
1118                 cli->timeout = 0x7FFFFFFF;
1119         } else {
1120                 SSVAL(data, POSIX_LOCK_FLAGS_OFFSET, POSIX_LOCK_FLAG_NOWAIT);
1121         }
1122
1123         SIVAL(data, POSIX_LOCK_PID_OFFSET, cli->pid);
1124         SOFF_T(data, POSIX_LOCK_START_OFFSET, offset);
1125         SOFF_T(data, POSIX_LOCK_LEN_OFFSET, len);
1126
1127         if (!cli_send_trans(cli, SMBtrans2,
1128                                 NULL,                        /* name */
1129                                 -1, 0,                          /* fid, flags */
1130                                 &setup, 1, 0,                   /* setup, length, max */
1131                                 param, param_len, 2,            /* param, length, max */
1132                                 (char *)&data,  data_len, cli->max_xmit /* data, length, max */
1133                                 )) {
1134                 cli->timeout = saved_timeout;
1135                 return False;
1136         }
1137
1138         if (!cli_receive_trans(cli, SMBtrans2,
1139                                 &rparam, &param_len,
1140                                 &rdata, &data_len)) {
1141                 cli->timeout = saved_timeout;
1142                 SAFE_FREE(rdata);
1143                 SAFE_FREE(rparam);
1144                 return False;
1145         }
1146
1147         cli->timeout = saved_timeout;
1148
1149         SAFE_FREE(rdata);
1150         SAFE_FREE(rparam);
1151
1152         return True;
1153 }
1154
1155 /****************************************************************************
1156  POSIX Lock a file.
1157 ****************************************************************************/
1158
1159 BOOL cli_posix_lock(struct cli_state *cli, int fnum,
1160                         SMB_BIG_UINT offset, SMB_BIG_UINT len,
1161                         BOOL wait_lock, enum brl_type lock_type)
1162 {
1163         if (lock_type != READ_LOCK && lock_type != WRITE_LOCK) {
1164                 return False;
1165         }
1166         return cli_posix_lock_internal(cli, fnum, offset, len, wait_lock, lock_type);
1167 }
1168
1169 /****************************************************************************
1170  POSIX Unlock a file.
1171 ****************************************************************************/
1172
1173 BOOL cli_posix_unlock(struct cli_state *cli, int fnum, SMB_BIG_UINT offset, SMB_BIG_UINT len)
1174 {
1175         return cli_posix_lock_internal(cli, fnum, offset, len, False, UNLOCK_LOCK);
1176 }
1177
1178 /****************************************************************************
1179  POSIX Get any lock covering a file.
1180 ****************************************************************************/
1181
1182 BOOL cli_posix_getlock(struct cli_state *cli, int fnum, SMB_BIG_UINT *poffset, SMB_BIG_UINT *plen)
1183 {
1184         return True;
1185 }
1186
1187 /****************************************************************************
1188  Do a SMBgetattrE call.
1189 ****************************************************************************/
1190
1191 BOOL cli_getattrE(struct cli_state *cli, int fd, 
1192                   uint16 *attr, SMB_OFF_T *size, 
1193                   time_t *change_time,
1194                   time_t *access_time,
1195                   time_t *write_time)
1196 {
1197         memset(cli->outbuf,'\0',smb_size);
1198         memset(cli->inbuf,'\0',smb_size);
1199
1200         set_message(NULL,cli->outbuf,1,0,True);
1201
1202         SCVAL(cli->outbuf,smb_com,SMBgetattrE);
1203         SSVAL(cli->outbuf,smb_tid,cli->cnum);
1204         cli_setup_packet(cli);
1205
1206         SSVAL(cli->outbuf,smb_vwv0,fd);
1207
1208         cli_send_smb(cli);
1209         if (!cli_receive_smb(cli)) {
1210                 return False;
1211         }
1212         
1213         if (cli_is_error(cli)) {
1214                 return False;
1215         }
1216
1217         if (size) {
1218                 *size = IVAL(cli->inbuf, smb_vwv6);
1219         }
1220
1221         if (attr) {
1222                 *attr = SVAL(cli->inbuf,smb_vwv10);
1223         }
1224
1225         if (change_time) {
1226                 *change_time = cli_make_unix_date2(cli, cli->inbuf+smb_vwv0);
1227         }
1228
1229         if (access_time) {
1230                 *access_time = cli_make_unix_date2(cli, cli->inbuf+smb_vwv2);
1231         }
1232
1233         if (write_time) {
1234                 *write_time = cli_make_unix_date2(cli, cli->inbuf+smb_vwv4);
1235         }
1236
1237         return True;
1238 }
1239
1240 /****************************************************************************
1241  Do a SMBgetatr call
1242 ****************************************************************************/
1243
1244 BOOL cli_getatr(struct cli_state *cli, const char *fname, 
1245                 uint16 *attr, SMB_OFF_T *size, time_t *write_time)
1246 {
1247         char *p;
1248
1249         memset(cli->outbuf,'\0',smb_size);
1250         memset(cli->inbuf,'\0',smb_size);
1251
1252         set_message(NULL,cli->outbuf,0,0,True);
1253
1254         SCVAL(cli->outbuf,smb_com,SMBgetatr);
1255         SSVAL(cli->outbuf,smb_tid,cli->cnum);
1256         cli_setup_packet(cli);
1257
1258         p = smb_buf(cli->outbuf);
1259         *p++ = 4;
1260         p += clistr_push(cli, p, fname, -1, STR_TERMINATE);
1261
1262         cli_setup_bcc(cli, p);
1263
1264         cli_send_smb(cli);
1265         if (!cli_receive_smb(cli)) {
1266                 return False;
1267         }
1268         
1269         if (cli_is_error(cli)) {
1270                 return False;
1271         }
1272
1273         if (size) {
1274                 *size = IVAL(cli->inbuf, smb_vwv3);
1275         }
1276
1277         if (write_time) {
1278                 *write_time = cli_make_unix_date3(cli, cli->inbuf+smb_vwv1);
1279         }
1280
1281         if (attr) {
1282                 *attr = SVAL(cli->inbuf,smb_vwv0);
1283         }
1284
1285
1286         return True;
1287 }
1288
1289 /****************************************************************************
1290  Do a SMBsetattrE call.
1291 ****************************************************************************/
1292
1293 BOOL cli_setattrE(struct cli_state *cli, int fd,
1294                   time_t change_time,
1295                   time_t access_time,
1296                   time_t write_time)
1297
1298 {
1299         char *p;
1300
1301         memset(cli->outbuf,'\0',smb_size);
1302         memset(cli->inbuf,'\0',smb_size);
1303
1304         set_message(NULL,cli->outbuf,7,0,True);
1305
1306         SCVAL(cli->outbuf,smb_com,SMBsetattrE);
1307         SSVAL(cli->outbuf,smb_tid,cli->cnum);
1308         cli_setup_packet(cli);
1309
1310         SSVAL(cli->outbuf,smb_vwv0, fd);
1311         cli_put_dos_date2(cli, cli->outbuf,smb_vwv1, change_time);
1312         cli_put_dos_date2(cli, cli->outbuf,smb_vwv3, access_time);
1313         cli_put_dos_date2(cli, cli->outbuf,smb_vwv5, write_time);
1314
1315         p = smb_buf(cli->outbuf);
1316         *p++ = 4;
1317
1318         cli_setup_bcc(cli, p);
1319
1320         cli_send_smb(cli);
1321         if (!cli_receive_smb(cli)) {
1322                 return False;
1323         }
1324         
1325         if (cli_is_error(cli)) {
1326                 return False;
1327         }
1328
1329         return True;
1330 }
1331
1332 /****************************************************************************
1333  Do a SMBsetatr call.
1334 ****************************************************************************/
1335
1336 BOOL cli_setatr(struct cli_state *cli, const char *fname, uint16 attr, time_t t)
1337 {
1338         char *p;
1339
1340         memset(cli->outbuf,'\0',smb_size);
1341         memset(cli->inbuf,'\0',smb_size);
1342
1343         set_message(NULL,cli->outbuf,8,0,True);
1344
1345         SCVAL(cli->outbuf,smb_com,SMBsetatr);
1346         SSVAL(cli->outbuf,smb_tid,cli->cnum);
1347         cli_setup_packet(cli);
1348
1349         SSVAL(cli->outbuf,smb_vwv0, attr);
1350         cli_put_dos_date3(cli, cli->outbuf,smb_vwv1, t);
1351
1352         p = smb_buf(cli->outbuf);
1353         *p++ = 4;
1354         p += clistr_push(cli, p, fname, -1, STR_TERMINATE);
1355         *p++ = 4;
1356
1357         cli_setup_bcc(cli, p);
1358
1359         cli_send_smb(cli);
1360         if (!cli_receive_smb(cli)) {
1361                 return False;
1362         }
1363         
1364         if (cli_is_error(cli)) {
1365                 return False;
1366         }
1367
1368         return True;
1369 }
1370
1371 /****************************************************************************
1372  Check for existance of a dir.
1373 ****************************************************************************/
1374 BOOL cli_chkpath(struct cli_state *cli, const char *path)
1375 {
1376         pstring path2;
1377         char *p;
1378         
1379         pstrcpy(path2,path);
1380         trim_char(path2,'\0','\\');
1381         if (!*path2)
1382                 *path2 = '\\';
1383         
1384         memset(cli->outbuf,'\0',smb_size);
1385         set_message(NULL,cli->outbuf,0,0,True);
1386         SCVAL(cli->outbuf,smb_com,SMBcheckpath);
1387         SSVAL(cli->outbuf,smb_tid,cli->cnum);
1388         cli_setup_packet(cli);
1389         p = smb_buf(cli->outbuf);
1390         *p++ = 4;
1391         p += clistr_push(cli, p, path2, -1, STR_TERMINATE);
1392
1393         cli_setup_bcc(cli, p);
1394
1395         cli_send_smb(cli);
1396         if (!cli_receive_smb(cli)) {
1397                 return False;
1398         }
1399
1400         if (cli_is_error(cli)) return False;
1401
1402         return True;
1403 }
1404
1405 /****************************************************************************
1406  Query disk space.
1407 ****************************************************************************/
1408
1409 BOOL cli_dskattr(struct cli_state *cli, int *bsize, int *total, int *avail)
1410 {
1411         memset(cli->outbuf,'\0',smb_size);
1412         set_message(NULL,cli->outbuf,0,0,True);
1413         SCVAL(cli->outbuf,smb_com,SMBdskattr);
1414         SSVAL(cli->outbuf,smb_tid,cli->cnum);
1415         cli_setup_packet(cli);
1416
1417         cli_send_smb(cli);
1418         if (!cli_receive_smb(cli)) {
1419                 return False;
1420         }
1421
1422         *bsize = SVAL(cli->inbuf,smb_vwv1)*SVAL(cli->inbuf,smb_vwv2);
1423         *total = SVAL(cli->inbuf,smb_vwv0);
1424         *avail = SVAL(cli->inbuf,smb_vwv3);
1425         
1426         return True;
1427 }
1428
1429 /****************************************************************************
1430  Create and open a temporary file.
1431 ****************************************************************************/
1432
1433 int cli_ctemp(struct cli_state *cli, const char *path, char **tmp_path)
1434 {
1435         int len;
1436         char *p;
1437
1438         memset(cli->outbuf,'\0',smb_size);
1439         memset(cli->inbuf,'\0',smb_size);
1440
1441         set_message(NULL,cli->outbuf,3,0,True);
1442
1443         SCVAL(cli->outbuf,smb_com,SMBctemp);
1444         SSVAL(cli->outbuf,smb_tid,cli->cnum);
1445         cli_setup_packet(cli);
1446
1447         SSVAL(cli->outbuf,smb_vwv0,0);
1448         SIVALS(cli->outbuf,smb_vwv1,-1);
1449
1450         p = smb_buf(cli->outbuf);
1451         *p++ = 4;
1452         p += clistr_push(cli, p, path, -1, STR_TERMINATE);
1453
1454         cli_setup_bcc(cli, p);
1455
1456         cli_send_smb(cli);
1457         if (!cli_receive_smb(cli)) {
1458                 return -1;
1459         }
1460
1461         if (cli_is_error(cli)) {
1462                 return -1;
1463         }
1464
1465         /* despite the spec, the result has a -1, followed by
1466            length, followed by name */
1467         p = smb_buf(cli->inbuf);
1468         p += 4;
1469         len = smb_buflen(cli->inbuf) - 4;
1470         if (len <= 0) return -1;
1471
1472         if (tmp_path) {
1473                 pstring path2;
1474                 clistr_pull(cli, path2, p, 
1475                             sizeof(path2), len, STR_ASCII);
1476                 *tmp_path = SMB_STRDUP(path2);
1477         }
1478
1479         return SVAL(cli->inbuf,smb_vwv0);
1480 }
1481
1482
1483 /* 
1484    send a raw ioctl - used by the torture code
1485 */
1486 NTSTATUS cli_raw_ioctl(struct cli_state *cli, int fnum, uint32 code, DATA_BLOB *blob)
1487 {
1488         memset(cli->outbuf,'\0',smb_size);
1489         memset(cli->inbuf,'\0',smb_size);
1490
1491         set_message(NULL,cli->outbuf, 3, 0, True);
1492         SCVAL(cli->outbuf,smb_com,SMBioctl);
1493         cli_setup_packet(cli);
1494
1495         SSVAL(cli->outbuf, smb_vwv0, fnum);
1496         SSVAL(cli->outbuf, smb_vwv1, code>>16);
1497         SSVAL(cli->outbuf, smb_vwv2, (code&0xFFFF));
1498
1499         cli_send_smb(cli);
1500         if (!cli_receive_smb(cli)) {
1501                 return NT_STATUS_UNEXPECTED_NETWORK_ERROR;
1502         }
1503
1504         if (cli_is_error(cli)) {
1505                 return cli_nt_error(cli);
1506         }
1507
1508         *blob = data_blob_null;
1509
1510         return NT_STATUS_OK;
1511 }
1512
1513 /*********************************************************
1514  Set an extended attribute utility fn.
1515 *********************************************************/
1516
1517 static BOOL cli_set_ea(struct cli_state *cli, uint16 setup, char *param, unsigned int param_len,
1518                         const char *ea_name, const char *ea_val, size_t ea_len)
1519 {       
1520         unsigned int data_len = 0;
1521         char *data = NULL;
1522         char *rparam=NULL, *rdata=NULL;
1523         char *p;
1524         size_t ea_namelen = strlen(ea_name);
1525
1526         if (ea_namelen == 0 && ea_len == 0) {
1527                 data_len = 4;
1528                 data = (char *)SMB_MALLOC(data_len);
1529                 if (!data) {
1530                         return False;
1531                 }
1532                 p = data;
1533                 SIVAL(p,0,data_len);
1534         } else {
1535                 data_len = 4 + 4 + ea_namelen + 1 + ea_len;
1536                 data = (char *)SMB_MALLOC(data_len);
1537                 if (!data) {
1538                         return False;
1539                 }
1540                 p = data;
1541                 SIVAL(p,0,data_len);
1542                 p += 4;
1543                 SCVAL(p, 0, 0); /* EA flags. */
1544                 SCVAL(p, 1, ea_namelen);
1545                 SSVAL(p, 2, ea_len);
1546                 memcpy(p+4, ea_name, ea_namelen+1); /* Copy in the name. */
1547                 memcpy(p+4+ea_namelen+1, ea_val, ea_len);
1548         }
1549
1550         if (!cli_send_trans(cli, SMBtrans2,
1551                 NULL,                        /* name */
1552                 -1, 0,                          /* fid, flags */
1553                 &setup, 1, 0,                   /* setup, length, max */
1554                 param, param_len, 2,            /* param, length, max */
1555                 data,  data_len, cli->max_xmit /* data, length, max */
1556                 )) {
1557                         return False;
1558         }
1559
1560         if (!cli_receive_trans(cli, SMBtrans2,
1561                 &rparam, &param_len,
1562                 &rdata, &data_len)) {
1563                         return False;
1564         }
1565
1566         SAFE_FREE(data);
1567         SAFE_FREE(rdata);
1568         SAFE_FREE(rparam);
1569
1570         return True;
1571 }
1572
1573 /*********************************************************
1574  Set an extended attribute on a pathname.
1575 *********************************************************/
1576
1577 BOOL cli_set_ea_path(struct cli_state *cli, const char *path, const char *ea_name, const char *ea_val, size_t ea_len)
1578 {
1579         uint16 setup = TRANSACT2_SETPATHINFO;
1580         unsigned int param_len = 0;
1581         char param[sizeof(pstring)+6];
1582         size_t srclen = 2*(strlen(path)+1);
1583         char *p;
1584
1585         memset(param, 0, sizeof(param));
1586         SSVAL(param,0,SMB_INFO_SET_EA);
1587         p = &param[6];
1588
1589         p += clistr_push(cli, p, path, MIN(srclen, sizeof(param)-6), STR_TERMINATE);
1590         param_len = PTR_DIFF(p, param);
1591
1592         return cli_set_ea(cli, setup, param, param_len, ea_name, ea_val, ea_len);
1593 }
1594
1595 /*********************************************************
1596  Set an extended attribute on an fnum.
1597 *********************************************************/
1598
1599 BOOL cli_set_ea_fnum(struct cli_state *cli, int fnum, const char *ea_name, const char *ea_val, size_t ea_len)
1600 {
1601         char param[6];
1602         uint16 setup = TRANSACT2_SETFILEINFO;
1603
1604         memset(param, 0, 6);
1605         SSVAL(param,0,fnum);
1606         SSVAL(param,2,SMB_INFO_SET_EA);
1607
1608         return cli_set_ea(cli, setup, param, 6, ea_name, ea_val, ea_len);
1609 }
1610
1611 /*********************************************************
1612  Get an extended attribute list tility fn.
1613 *********************************************************/
1614
1615 static BOOL cli_get_ea_list(struct cli_state *cli,
1616                 uint16 setup, char *param, unsigned int param_len,
1617                 TALLOC_CTX *ctx,
1618                 size_t *pnum_eas,
1619                 struct ea_struct **pea_list)
1620 {
1621         unsigned int data_len = 0;
1622         unsigned int rparam_len, rdata_len;
1623         char *rparam=NULL, *rdata=NULL;
1624         char *p;
1625         size_t ea_size;
1626         size_t num_eas;
1627         BOOL ret = False;
1628         struct ea_struct *ea_list;
1629
1630         *pnum_eas = 0;
1631         if (pea_list) {
1632                 *pea_list = NULL;
1633         }
1634
1635         if (!cli_send_trans(cli, SMBtrans2,
1636                         NULL,           /* Name */
1637                         -1, 0,          /* fid, flags */
1638                         &setup, 1, 0,   /* setup, length, max */
1639                         param, param_len, 10, /* param, length, max */
1640                         NULL, data_len, cli->max_xmit /* data, length, max */
1641                                 )) {
1642                 return False;
1643         }
1644
1645         if (!cli_receive_trans(cli, SMBtrans2,
1646                         &rparam, &rparam_len,
1647                         &rdata, &rdata_len)) {
1648                 return False;
1649         }
1650
1651         if (!rdata || rdata_len < 4) {
1652                 goto out;
1653         }
1654
1655         ea_size = (size_t)IVAL(rdata,0);
1656         if (ea_size > rdata_len) {
1657                 goto out;
1658         }
1659
1660         if (ea_size == 0) {
1661                 /* No EA's present. */
1662                 ret = True;
1663                 goto out;
1664         }
1665
1666         p = rdata + 4;
1667         ea_size -= 4;
1668
1669         /* Validate the EA list and count it. */
1670         for (num_eas = 0; ea_size >= 4; num_eas++) {
1671                 unsigned int ea_namelen = CVAL(p,1);
1672                 unsigned int ea_valuelen = SVAL(p,2);
1673                 if (ea_namelen == 0) {
1674                         goto out;
1675                 }
1676                 if (4 + ea_namelen + 1 + ea_valuelen > ea_size) {
1677                         goto out;
1678                 }
1679                 ea_size -= 4 + ea_namelen + 1 + ea_valuelen;
1680                 p += 4 + ea_namelen + 1 + ea_valuelen;
1681         }
1682
1683         if (num_eas == 0) {
1684                 ret = True;
1685                 goto out;
1686         }
1687
1688         *pnum_eas = num_eas;
1689         if (!pea_list) {
1690                 /* Caller only wants number of EA's. */
1691                 ret = True;
1692                 goto out;
1693         }
1694
1695         ea_list = TALLOC_ARRAY(ctx, struct ea_struct, num_eas);
1696         if (!ea_list) {
1697                 goto out;
1698         }
1699
1700         ea_size = (size_t)IVAL(rdata,0);
1701         p = rdata + 4;
1702
1703         for (num_eas = 0; num_eas < *pnum_eas; num_eas++ ) {
1704                 struct ea_struct *ea = &ea_list[num_eas];
1705                 fstring unix_ea_name;
1706                 unsigned int ea_namelen = CVAL(p,1);
1707                 unsigned int ea_valuelen = SVAL(p,2);
1708
1709                 ea->flags = CVAL(p,0);
1710                 unix_ea_name[0] = '\0';
1711                 pull_ascii_fstring(unix_ea_name, p + 4);
1712                 ea->name = talloc_strdup(ctx, unix_ea_name);
1713                 /* Ensure the value is null terminated (in case it's a string). */
1714                 ea->value = data_blob_talloc(ctx, NULL, ea_valuelen + 1);
1715                 if (!ea->value.data) {
1716                         goto out;
1717                 }
1718                 if (ea_valuelen) {
1719                         memcpy(ea->value.data, p+4+ea_namelen+1, ea_valuelen);
1720                 }
1721                 ea->value.data[ea_valuelen] = 0;
1722                 ea->value.length--;
1723                 p += 4 + ea_namelen + 1 + ea_valuelen;
1724         }
1725
1726         *pea_list = ea_list;
1727         ret = True;
1728
1729  out :
1730
1731         SAFE_FREE(rdata);
1732         SAFE_FREE(rparam);
1733         return ret;
1734 }
1735
1736 /*********************************************************
1737  Get an extended attribute list from a pathname.
1738 *********************************************************/
1739
1740 BOOL cli_get_ea_list_path(struct cli_state *cli, const char *path,
1741                 TALLOC_CTX *ctx,
1742                 size_t *pnum_eas,
1743                 struct ea_struct **pea_list)
1744 {
1745         uint16 setup = TRANSACT2_QPATHINFO;
1746         unsigned int param_len = 0;
1747         char param[sizeof(pstring)+6];
1748         char *p;
1749
1750         p = param;
1751         memset(p, 0, 6);
1752         SSVAL(p, 0, SMB_INFO_QUERY_ALL_EAS);
1753         p += 6;
1754         p += clistr_push(cli, p, path, sizeof(pstring)-6, STR_TERMINATE);
1755         param_len = PTR_DIFF(p, param);
1756
1757         return cli_get_ea_list(cli, setup, param, param_len, ctx, pnum_eas, pea_list);
1758 }
1759
1760 /*********************************************************
1761  Get an extended attribute list from an fnum.
1762 *********************************************************/
1763
1764 BOOL cli_get_ea_list_fnum(struct cli_state *cli, int fnum,
1765                 TALLOC_CTX *ctx,
1766                 size_t *pnum_eas,
1767                 struct ea_struct **pea_list)
1768 {
1769         uint16 setup = TRANSACT2_QFILEINFO;
1770         char param[6];
1771
1772         memset(param, 0, 6);
1773         SSVAL(param,0,fnum);
1774         SSVAL(param,2,SMB_INFO_SET_EA);
1775
1776         return cli_get_ea_list(cli, setup, param, 6, ctx, pnum_eas, pea_list);
1777 }
1778
1779 /****************************************************************************
1780  Convert open "flags" arg to uint32 on wire.
1781 ****************************************************************************/
1782
1783 static uint32 open_flags_to_wire(int flags)
1784 {
1785         int open_mode = flags & O_ACCMODE;
1786         uint32 ret = 0;
1787
1788         switch (open_mode) {
1789                 case O_WRONLY:
1790                         ret |= SMB_O_WRONLY;
1791                         break;
1792                 case O_RDWR:
1793                         ret |= SMB_O_RDWR;
1794                         break;
1795                 default:
1796                 case O_RDONLY:
1797                         ret |= SMB_O_RDONLY;
1798                         break;
1799         }
1800
1801         if (flags & O_CREAT) {
1802                 ret |= SMB_O_CREAT;
1803         }
1804         if (flags & O_EXCL) {
1805                 ret |= SMB_O_EXCL;
1806         }
1807         if (flags & O_TRUNC) {
1808                 ret |= SMB_O_TRUNC;
1809         }
1810 #if defined(O_SYNC)
1811         if (flags & O_SYNC) {
1812                 ret |= SMB_O_SYNC;
1813         }
1814 #endif /* O_SYNC */
1815         if (flags & O_APPEND) {
1816                 ret |= SMB_O_APPEND;
1817         }
1818 #if defined(O_DIRECT)
1819         if (flags & O_DIRECT) {
1820                 ret |= SMB_O_DIRECT;
1821         }
1822 #endif
1823 #if defined(O_DIRECTORY)
1824         if (flags & O_DIRECTORY) {
1825                 ret &= ~(SMB_O_RDONLY|SMB_O_RDWR|SMB_O_WRONLY);
1826                 ret |= SMB_O_DIRECTORY;
1827         }
1828 #endif
1829         return ret;
1830 }
1831
1832 /****************************************************************************
1833  Open a file - POSIX semantics. Returns fnum. Doesn't request oplock.
1834 ****************************************************************************/
1835
1836 static int cli_posix_open_internal(struct cli_state *cli, const char *fname, int flags, mode_t mode, BOOL is_dir)
1837 {
1838         unsigned int data_len = 0;
1839         unsigned int param_len = 0;
1840         uint16 setup = TRANSACT2_SETPATHINFO;
1841         char param[sizeof(pstring)+6];
1842         char data[18];
1843         char *rparam=NULL, *rdata=NULL;
1844         char *p;
1845         int fnum = -1;
1846         uint32 wire_flags = open_flags_to_wire(flags);
1847
1848         memset(param, 0, sizeof(param));
1849         SSVAL(param,0, SMB_POSIX_PATH_OPEN);
1850         p = &param[6];
1851
1852         p += clistr_push(cli, p, fname, sizeof(param)-6, STR_TERMINATE);
1853         param_len = PTR_DIFF(p, param);
1854
1855         if (is_dir) {
1856                 wire_flags &= ~(SMB_O_RDONLY|SMB_O_RDWR|SMB_O_WRONLY);
1857                 wire_flags |= SMB_O_DIRECTORY;
1858         }
1859
1860         p = data;
1861         SIVAL(p,0,0); /* No oplock. */
1862         SIVAL(p,4,wire_flags);
1863         SIVAL(p,8,unix_perms_to_wire(mode));
1864         SIVAL(p,12,0); /* Top bits of perms currently undefined. */
1865         SSVAL(p,16,SMB_NO_INFO_LEVEL_RETURNED); /* No info level returned. */
1866
1867         data_len = 18;
1868
1869         if (!cli_send_trans(cli, SMBtrans2,
1870                 NULL,                        /* name */
1871                 -1, 0,                          /* fid, flags */
1872                 &setup, 1, 0,                   /* setup, length, max */
1873                 param, param_len, 2,            /* param, length, max */
1874                 (char *)&data,  data_len, cli->max_xmit /* data, length, max */
1875                 )) {
1876                         return -1;
1877         }
1878
1879         if (!cli_receive_trans(cli, SMBtrans2,
1880                 &rparam, &param_len,
1881                 &rdata, &data_len)) {
1882                         return -1;
1883         }
1884
1885         fnum = SVAL(rdata,2);
1886
1887         SAFE_FREE(rdata);
1888         SAFE_FREE(rparam);
1889
1890         return fnum;
1891 }
1892
1893 /****************************************************************************
1894  open - POSIX semantics.
1895 ****************************************************************************/
1896
1897 int cli_posix_open(struct cli_state *cli, const char *fname, int flags, mode_t mode)
1898 {
1899         return cli_posix_open_internal(cli, fname, flags, mode, False);
1900 }
1901
1902 /****************************************************************************
1903  mkdir - POSIX semantics.
1904 ****************************************************************************/
1905
1906 int cli_posix_mkdir(struct cli_state *cli, const char *fname, mode_t mode)
1907 {
1908         return (cli_posix_open_internal(cli, fname, O_CREAT, mode, True) == -1) ? -1 : 0;
1909 }
1910
1911 /****************************************************************************
1912  unlink or rmdir - POSIX semantics.
1913 ****************************************************************************/
1914
1915 static BOOL cli_posix_unlink_internal(struct cli_state *cli, const char *fname, BOOL is_dir)
1916 {
1917         unsigned int data_len = 0;
1918         unsigned int param_len = 0;
1919         uint16 setup = TRANSACT2_SETPATHINFO;
1920         char param[sizeof(pstring)+6];
1921         char data[2];
1922         char *rparam=NULL, *rdata=NULL;
1923         char *p;
1924
1925         memset(param, 0, sizeof(param));
1926         SSVAL(param,0, SMB_POSIX_PATH_UNLINK);
1927         p = &param[6];
1928
1929         p += clistr_push(cli, p, fname, sizeof(param)-6, STR_TERMINATE);
1930         param_len = PTR_DIFF(p, param);
1931
1932         SSVAL(data, 0, is_dir ? SMB_POSIX_UNLINK_DIRECTORY_TARGET :
1933                         SMB_POSIX_UNLINK_FILE_TARGET);
1934         data_len = 2;
1935
1936         if (!cli_send_trans(cli, SMBtrans2,
1937                 NULL,                        /* name */
1938                 -1, 0,                          /* fid, flags */
1939                 &setup, 1, 0,                   /* setup, length, max */
1940                 param, param_len, 2,            /* param, length, max */
1941                 (char *)&data,  data_len, cli->max_xmit /* data, length, max */
1942                 )) {
1943                         return False;
1944         }
1945
1946         if (!cli_receive_trans(cli, SMBtrans2,
1947                 &rparam, &param_len,
1948                 &rdata, &data_len)) {
1949                         return False;
1950         }
1951
1952         SAFE_FREE(rdata);
1953         SAFE_FREE(rparam);
1954
1955         return True;
1956 }
1957
1958 /****************************************************************************
1959  unlink - POSIX semantics.
1960 ****************************************************************************/
1961
1962 BOOL cli_posix_unlink(struct cli_state *cli, const char *fname)
1963 {
1964         return cli_posix_unlink_internal(cli, fname, False);
1965 }
1966
1967 /****************************************************************************
1968  rmdir - POSIX semantics.
1969 ****************************************************************************/
1970
1971 int cli_posix_rmdir(struct cli_state *cli, const char *fname)
1972 {
1973         return cli_posix_unlink_internal(cli, fname, True);
1974 }