When re-writing tdb version numbers as little endian int32, we must
[ira/wip.git] / source3 / libsmb / clifile.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 3.0
4    client file operations
5    Copyright (C) Andrew Tridgell 1994-1998
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 #define NO_SYSLOG
23
24 #include "includes.h"
25
26 /****************************************************************************
27  Rename a file.
28 ****************************************************************************/
29
30 BOOL cli_rename(struct cli_state *cli, const char *fname_src, const char *fname_dst)
31 {
32         char *p;
33
34         memset(cli->outbuf,'\0',smb_size);
35         memset(cli->inbuf,'\0',smb_size);
36
37         set_message(cli->outbuf,1, 0, True);
38
39         CVAL(cli->outbuf,smb_com) = SMBmv;
40         SSVAL(cli->outbuf,smb_tid,cli->cnum);
41         cli_setup_packet(cli);
42
43         SSVAL(cli->outbuf,smb_vwv0,aSYSTEM | aHIDDEN | aDIR);
44
45         p = smb_buf(cli->outbuf);
46         *p++ = 4;
47         p += clistr_push(cli, p, fname_src, -1, STR_TERMINATE);
48         *p++ = 4;
49         p += clistr_push(cli, p, fname_dst, -1, STR_TERMINATE);
50
51         cli_setup_bcc(cli, p);
52
53         cli_send_smb(cli);
54         if (!cli_receive_smb(cli))
55                 return False;
56
57         if (cli_is_error(cli))
58                 return False;
59
60         return True;
61 }
62
63 /****************************************************************************
64  Delete a file.
65 ****************************************************************************/
66
67 BOOL cli_unlink(struct cli_state *cli, const char *fname)
68 {
69         char *p;
70
71         memset(cli->outbuf,'\0',smb_size);
72         memset(cli->inbuf,'\0',smb_size);
73
74         set_message(cli->outbuf,1, 0,True);
75
76         CVAL(cli->outbuf,smb_com) = SMBunlink;
77         SSVAL(cli->outbuf,smb_tid,cli->cnum);
78         cli_setup_packet(cli);
79
80         SSVAL(cli->outbuf,smb_vwv0,aSYSTEM | aHIDDEN);
81   
82         p = smb_buf(cli->outbuf);
83         *p++ = 4;      
84         p += clistr_push(cli, p, fname, -1, STR_TERMINATE);
85
86         cli_setup_bcc(cli, p);
87         cli_send_smb(cli);
88         if (!cli_receive_smb(cli)) {
89                 return False;
90         }
91
92         if (cli_is_error(cli)) {
93                 return False;
94         }
95
96         return True;
97 }
98
99 /****************************************************************************
100  Create a directory.
101 ****************************************************************************/
102
103 BOOL cli_mkdir(struct cli_state *cli, const char *dname)
104 {
105         char *p;
106
107         memset(cli->outbuf,'\0',smb_size);
108         memset(cli->inbuf,'\0',smb_size);
109
110         set_message(cli->outbuf,0, 0,True);
111
112         CVAL(cli->outbuf,smb_com) = SMBmkdir;
113         SSVAL(cli->outbuf,smb_tid,cli->cnum);
114         cli_setup_packet(cli);
115
116         p = smb_buf(cli->outbuf);
117         *p++ = 4;      
118         p += clistr_push(cli, p, dname, -1, STR_TERMINATE);
119
120         cli_setup_bcc(cli, p);
121
122         cli_send_smb(cli);
123         if (!cli_receive_smb(cli)) {
124                 return False;
125         }
126
127         if (cli_is_error(cli)) {
128                 return False;
129         }
130
131         return True;
132 }
133
134 /****************************************************************************
135  Remove a directory.
136 ****************************************************************************/
137
138 BOOL cli_rmdir(struct cli_state *cli, const char *dname)
139 {
140         char *p;
141
142         memset(cli->outbuf,'\0',smb_size);
143         memset(cli->inbuf,'\0',smb_size);
144
145         set_message(cli->outbuf,0, 0, True);
146
147         CVAL(cli->outbuf,smb_com) = SMBrmdir;
148         SSVAL(cli->outbuf,smb_tid,cli->cnum);
149         cli_setup_packet(cli);
150
151         p = smb_buf(cli->outbuf);
152         *p++ = 4;      
153         p += clistr_push(cli, p, dname, -1, STR_TERMINATE);
154
155         cli_setup_bcc(cli, p);
156
157         cli_send_smb(cli);
158         if (!cli_receive_smb(cli)) {
159                 return False;
160         }
161
162         if (cli_is_error(cli)) {
163                 return False;
164         }
165
166         return True;
167 }
168
169 /****************************************************************************
170  Set or clear the delete on close flag.
171 ****************************************************************************/
172
173 int cli_nt_delete_on_close(struct cli_state *cli, int fnum, BOOL flag)
174 {
175         int data_len = 1;
176         int param_len = 6;
177         uint16 setup = TRANSACT2_SETFILEINFO;
178         pstring param;
179         unsigned char data;
180         char *rparam=NULL, *rdata=NULL;
181
182         memset(param, 0, param_len);
183         SSVAL(param,0,fnum);
184         SSVAL(param,2,SMB_SET_FILE_DISPOSITION_INFO);
185
186         data = flag ? 1 : 0;
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                                                 (char *)&data,  data_len, 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         SAFE_FREE(rdata);
205         SAFE_FREE(rparam);
206
207         return True;
208 }
209
210 /****************************************************************************
211  Open a file - exposing the full horror of the NT API :-).
212  Used in smbtorture.
213 ****************************************************************************/
214
215 int cli_nt_create_full(struct cli_state *cli, const char *fname, uint32 DesiredAccess,
216                  uint32 FileAttributes, uint32 ShareAccess,
217                  uint32 CreateDisposition, uint32 CreateOptions)
218 {
219         char *p;
220         int len;
221
222         memset(cli->outbuf,'\0',smb_size);
223         memset(cli->inbuf,'\0',smb_size);
224
225         set_message(cli->outbuf,24,0,True);
226
227         CVAL(cli->outbuf,smb_com) = SMBntcreateX;
228         SSVAL(cli->outbuf,smb_tid,cli->cnum);
229         cli_setup_packet(cli);
230
231         SSVAL(cli->outbuf,smb_vwv0,0xFF);
232         if (cli->use_oplocks)
233                 SIVAL(cli->outbuf,smb_ntcreate_Flags, REQUEST_OPLOCK|REQUEST_BATCH_OPLOCK);
234         else
235                 SIVAL(cli->outbuf,smb_ntcreate_Flags, 0);
236         SIVAL(cli->outbuf,smb_ntcreate_RootDirectoryFid, 0x0);
237         SIVAL(cli->outbuf,smb_ntcreate_DesiredAccess, DesiredAccess);
238         SIVAL(cli->outbuf,smb_ntcreate_FileAttributes, FileAttributes);
239         SIVAL(cli->outbuf,smb_ntcreate_ShareAccess, ShareAccess);
240         SIVAL(cli->outbuf,smb_ntcreate_CreateDisposition, CreateDisposition);
241         SIVAL(cli->outbuf,smb_ntcreate_CreateOptions, CreateOptions);
242         SIVAL(cli->outbuf,smb_ntcreate_ImpersonationLevel, 0x02);
243
244         p = smb_buf(cli->outbuf);
245         /* this alignment and termination is critical for netapp filers. Don't change */
246         p += clistr_align_out(cli, p, 0);
247         len = clistr_push(cli, p, fname, -1, 0);
248         p += len;
249         SSVAL(cli->outbuf,smb_ntcreate_NameLength, len);
250         /* sigh. this copes with broken netapp filer behaviour */
251         p += clistr_push(cli, p, "", -1, STR_TERMINATE);
252
253         cli_setup_bcc(cli, p);
254
255         cli_send_smb(cli);
256         if (!cli_receive_smb(cli)) {
257                 return -1;
258         }
259
260         if (cli_is_error(cli)) {
261                 return -1;
262         }
263
264         return SVAL(cli->inbuf,smb_vwv2 + 1);
265 }
266
267 /****************************************************************************
268  Open a file.
269 ****************************************************************************/
270
271 int cli_nt_create(struct cli_state *cli, const char *fname, uint32 DesiredAccess)
272 {
273         return cli_nt_create_full(cli, fname, DesiredAccess, 0,
274                                 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_EXISTS_OPEN, 0x0);
275 }
276
277 /****************************************************************************
278  Open a file
279  WARNING: if you open with O_WRONLY then getattrE won't work!
280 ****************************************************************************/
281
282 int cli_open(struct cli_state *cli, const char *fname, int flags, int share_mode)
283 {
284         char *p;
285         unsigned openfn=0;
286         unsigned accessmode=0;
287
288         if (flags & O_CREAT)
289                 openfn |= (1<<4);
290         if (!(flags & O_EXCL)) {
291                 if (flags & O_TRUNC)
292                         openfn |= (1<<1);
293                 else
294                         openfn |= (1<<0);
295         }
296
297         accessmode = (share_mode<<4);
298
299         if ((flags & O_ACCMODE) == O_RDWR) {
300                 accessmode |= 2;
301         } else if ((flags & O_ACCMODE) == O_WRONLY) {
302                 accessmode |= 1;
303         } 
304
305 #if defined(O_SYNC)
306         if ((flags & O_SYNC) == O_SYNC) {
307                 accessmode |= (1<<14);
308         }
309 #endif /* O_SYNC */
310
311         if (share_mode == DENY_FCB) {
312                 accessmode = 0xFF;
313         }
314
315         memset(cli->outbuf,'\0',smb_size);
316         memset(cli->inbuf,'\0',smb_size);
317
318         set_message(cli->outbuf,15,0,True);
319
320         CVAL(cli->outbuf,smb_com) = SMBopenX;
321         SSVAL(cli->outbuf,smb_tid,cli->cnum);
322         cli_setup_packet(cli);
323
324         SSVAL(cli->outbuf,smb_vwv0,0xFF);
325         SSVAL(cli->outbuf,smb_vwv2,0);  /* no additional info */
326         SSVAL(cli->outbuf,smb_vwv3,accessmode);
327         SSVAL(cli->outbuf,smb_vwv4,aSYSTEM | aHIDDEN);
328         SSVAL(cli->outbuf,smb_vwv5,0);
329         SSVAL(cli->outbuf,smb_vwv8,openfn);
330
331         if (cli->use_oplocks) {
332                 /* if using oplocks then ask for a batch oplock via
333                    core and extended methods */
334                 CVAL(cli->outbuf,smb_flg) |= 
335                         FLAG_REQUEST_OPLOCK|FLAG_REQUEST_BATCH_OPLOCK;
336                 SSVAL(cli->outbuf,smb_vwv2,SVAL(cli->outbuf,smb_vwv2) | 6);
337         }
338   
339         p = smb_buf(cli->outbuf);
340         p += clistr_push(cli, p, fname, -1, STR_TERMINATE);
341
342         cli_setup_bcc(cli, p);
343
344         cli_send_smb(cli);
345         if (!cli_receive_smb(cli)) {
346                 return -1;
347         }
348
349         if (cli_is_error(cli)) {
350                 return -1;
351         }
352
353         return SVAL(cli->inbuf,smb_vwv2);
354 }
355
356 /****************************************************************************
357  Close a file.
358 ****************************************************************************/
359
360 BOOL cli_close(struct cli_state *cli, int fnum)
361 {
362         memset(cli->outbuf,'\0',smb_size);
363         memset(cli->inbuf,'\0',smb_size);
364
365         set_message(cli->outbuf,3,0,True);
366
367         CVAL(cli->outbuf,smb_com) = SMBclose;
368         SSVAL(cli->outbuf,smb_tid,cli->cnum);
369         cli_setup_packet(cli);
370
371         SSVAL(cli->outbuf,smb_vwv0,fnum);
372         SIVALS(cli->outbuf,smb_vwv1,-1);
373
374         cli_send_smb(cli);
375         if (!cli_receive_smb(cli)) {
376                 return False;
377         }
378
379         return !cli_is_error(cli);
380 }
381
382 /****************************************************************************
383  Lock a file.
384 ****************************************************************************/
385
386 BOOL cli_lock(struct cli_state *cli, int fnum, 
387               uint32 offset, uint32 len, int timeout, enum brl_type lock_type)
388 {
389         char *p;
390         int saved_timeout = cli->timeout;
391
392         memset(cli->outbuf,'\0',smb_size);
393         memset(cli->inbuf,'\0', smb_size);
394
395         set_message(cli->outbuf,8,0,True);
396
397         CVAL(cli->outbuf,smb_com) = SMBlockingX;
398         SSVAL(cli->outbuf,smb_tid,cli->cnum);
399         cli_setup_packet(cli);
400
401         CVAL(cli->outbuf,smb_vwv0) = 0xFF;
402         SSVAL(cli->outbuf,smb_vwv2,fnum);
403         CVAL(cli->outbuf,smb_vwv3) = (lock_type == READ_LOCK? 1 : 0);
404         SIVALS(cli->outbuf, smb_vwv4, timeout);
405         SSVAL(cli->outbuf,smb_vwv6,0);
406         SSVAL(cli->outbuf,smb_vwv7,1);
407
408         p = smb_buf(cli->outbuf);
409         SSVAL(p, 0, cli->pid);
410         SIVAL(p, 2, offset);
411         SIVAL(p, 6, len);
412
413         p += 10;
414
415         cli_setup_bcc(cli, p);
416
417         cli_send_smb(cli);
418
419         cli->timeout = (timeout == -1) ? 0x7FFFFFFF : (timeout + 2*1000);
420
421         if (!cli_receive_smb(cli)) {
422                 cli->timeout = saved_timeout;
423                 return False;
424         }
425
426         cli->timeout = saved_timeout;
427
428         if (cli_is_error(cli)) {
429                 return False;
430         }
431
432         return True;
433 }
434
435 /****************************************************************************
436  Unlock a file.
437 ****************************************************************************/
438
439 BOOL cli_unlock(struct cli_state *cli, int fnum, uint32 offset, uint32 len)
440 {
441         char *p;
442
443         memset(cli->outbuf,'\0',smb_size);
444         memset(cli->inbuf,'\0',smb_size);
445
446         set_message(cli->outbuf,8,0,True);
447
448         CVAL(cli->outbuf,smb_com) = SMBlockingX;
449         SSVAL(cli->outbuf,smb_tid,cli->cnum);
450         cli_setup_packet(cli);
451
452         CVAL(cli->outbuf,smb_vwv0) = 0xFF;
453         SSVAL(cli->outbuf,smb_vwv2,fnum);
454         CVAL(cli->outbuf,smb_vwv3) = 0;
455         SIVALS(cli->outbuf, smb_vwv4, 0);
456         SSVAL(cli->outbuf,smb_vwv6,1);
457         SSVAL(cli->outbuf,smb_vwv7,0);
458
459         p = smb_buf(cli->outbuf);
460         SSVAL(p, 0, cli->pid);
461         SIVAL(p, 2, offset);
462         SIVAL(p, 6, len);
463         p += 10;
464         cli_setup_bcc(cli, p);
465         cli_send_smb(cli);
466         if (!cli_receive_smb(cli)) {
467                 return False;
468         }
469
470         if (cli_is_error(cli)) {
471                 return False;
472         }
473
474         return True;
475 }
476
477 /****************************************************************************
478  Lock a file with 64 bit offsets.
479 ****************************************************************************/
480
481 BOOL cli_lock64(struct cli_state *cli, int fnum, 
482                 SMB_BIG_UINT offset, SMB_BIG_UINT len, int timeout, enum brl_type lock_type)
483 {
484         char *p;
485         int saved_timeout = cli->timeout;
486         int ltype;
487
488         if (! (cli->capabilities & CAP_LARGE_FILES)) {
489                 return cli_lock(cli, fnum, offset, len, timeout, lock_type);
490         }
491
492         ltype = (lock_type == READ_LOCK? 1 : 0);
493         ltype |= LOCKING_ANDX_LARGE_FILES;
494
495         memset(cli->outbuf,'\0',smb_size);
496         memset(cli->inbuf,'\0', smb_size);
497
498         set_message(cli->outbuf,8,0,True);
499
500         CVAL(cli->outbuf,smb_com) = SMBlockingX;
501         SSVAL(cli->outbuf,smb_tid,cli->cnum);
502         cli_setup_packet(cli);
503
504         CVAL(cli->outbuf,smb_vwv0) = 0xFF;
505         SSVAL(cli->outbuf,smb_vwv2,fnum);
506         CVAL(cli->outbuf,smb_vwv3) = ltype;
507         SIVALS(cli->outbuf, smb_vwv4, timeout);
508         SSVAL(cli->outbuf,smb_vwv6,0);
509         SSVAL(cli->outbuf,smb_vwv7,1);
510
511         p = smb_buf(cli->outbuf);
512         SIVAL(p, 0, cli->pid);
513         SOFF_T_R(p, 4, offset);
514         SOFF_T_R(p, 12, len);
515         p += 20;
516
517         cli_setup_bcc(cli, p);
518         cli_send_smb(cli);
519
520         cli->timeout = (timeout == -1) ? 0x7FFFFFFF : (timeout + 2*1000);
521
522         if (!cli_receive_smb(cli)) {
523                 cli->timeout = saved_timeout;
524                 return False;
525         }
526
527         cli->timeout = saved_timeout;
528
529         if (cli_is_error(cli)) {
530                 return False;
531         }
532
533         return True;
534 }
535
536 /****************************************************************************
537  Unlock a file with 64 bit offsets.
538 ****************************************************************************/
539
540 BOOL cli_unlock64(struct cli_state *cli, int fnum, SMB_BIG_UINT offset, SMB_BIG_UINT len)
541 {
542         char *p;
543
544         if (! (cli->capabilities & CAP_LARGE_FILES)) {
545                 return cli_unlock(cli, fnum, offset, len);
546         }
547
548         memset(cli->outbuf,'\0',smb_size);
549         memset(cli->inbuf,'\0',smb_size);
550
551         set_message(cli->outbuf,8,0,True);
552
553         CVAL(cli->outbuf,smb_com) = SMBlockingX;
554         SSVAL(cli->outbuf,smb_tid,cli->cnum);
555         cli_setup_packet(cli);
556
557         CVAL(cli->outbuf,smb_vwv0) = 0xFF;
558         SSVAL(cli->outbuf,smb_vwv2,fnum);
559         CVAL(cli->outbuf,smb_vwv3) = LOCKING_ANDX_LARGE_FILES;
560         SIVALS(cli->outbuf, smb_vwv4, 0);
561         SSVAL(cli->outbuf,smb_vwv6,1);
562         SSVAL(cli->outbuf,smb_vwv7,0);
563
564         p = smb_buf(cli->outbuf);
565         SIVAL(p, 0, cli->pid);
566         SOFF_T_R(p, 4, offset);
567         SOFF_T_R(p, 12, len);
568         p += 20;
569         cli_setup_bcc(cli, p);
570         cli_send_smb(cli);
571         if (!cli_receive_smb(cli)) {
572                 return False;
573         }
574
575         if (cli_is_error(cli)) {
576                 return False;
577         }
578
579         return True;
580 }
581
582 /****************************************************************************
583  Do a SMBgetattrE call.
584 ****************************************************************************/
585
586 BOOL cli_getattrE(struct cli_state *cli, int fd, 
587                   uint16 *attr, size_t *size, 
588                   time_t *c_time, time_t *a_time, time_t *m_time)
589 {
590         memset(cli->outbuf,'\0',smb_size);
591         memset(cli->inbuf,'\0',smb_size);
592
593         set_message(cli->outbuf,1,0,True);
594
595         CVAL(cli->outbuf,smb_com) = SMBgetattrE;
596         SSVAL(cli->outbuf,smb_tid,cli->cnum);
597         cli_setup_packet(cli);
598
599         SSVAL(cli->outbuf,smb_vwv0,fd);
600
601         cli_send_smb(cli);
602         if (!cli_receive_smb(cli)) {
603                 return False;
604         }
605         
606         if (cli_is_error(cli)) {
607                 return False;
608         }
609
610         if (size) {
611                 *size = IVAL(cli->inbuf, smb_vwv6);
612         }
613
614         if (attr) {
615                 *attr = SVAL(cli->inbuf,smb_vwv10);
616         }
617
618         if (c_time) {
619                 *c_time = make_unix_date3(cli->inbuf+smb_vwv0);
620         }
621
622         if (a_time) {
623                 *a_time = make_unix_date3(cli->inbuf+smb_vwv2);
624         }
625
626         if (m_time) {
627                 *m_time = make_unix_date3(cli->inbuf+smb_vwv4);
628         }
629
630         return True;
631 }
632
633 /****************************************************************************
634  Do a SMBgetatr call
635 ****************************************************************************/
636
637 BOOL cli_getatr(struct cli_state *cli, const char *fname, 
638                 uint16 *attr, size_t *size, time_t *t)
639 {
640         char *p;
641
642         memset(cli->outbuf,'\0',smb_size);
643         memset(cli->inbuf,'\0',smb_size);
644
645         set_message(cli->outbuf,0,0,True);
646
647         CVAL(cli->outbuf,smb_com) = SMBgetatr;
648         SSVAL(cli->outbuf,smb_tid,cli->cnum);
649         cli_setup_packet(cli);
650
651         p = smb_buf(cli->outbuf);
652         *p++ = 4;
653         p += clistr_push(cli, p, fname, -1, STR_TERMINATE);
654
655         cli_setup_bcc(cli, p);
656
657         cli_send_smb(cli);
658         if (!cli_receive_smb(cli)) {
659                 return False;
660         }
661         
662         if (cli_is_error(cli)) {
663                 return False;
664         }
665
666         if (size) {
667                 *size = IVAL(cli->inbuf, smb_vwv3);
668         }
669
670         if (t) {
671                 *t = make_unix_date3(cli->inbuf+smb_vwv1);
672         }
673
674         if (attr) {
675                 *attr = SVAL(cli->inbuf,smb_vwv0);
676         }
677
678
679         return True;
680 }
681
682 /****************************************************************************
683  Do a SMBsetatr call.
684 ****************************************************************************/
685
686 BOOL cli_setatr(struct cli_state *cli, const char *fname, uint16 attr, time_t t)
687 {
688         char *p;
689
690         memset(cli->outbuf,'\0',smb_size);
691         memset(cli->inbuf,'\0',smb_size);
692
693         set_message(cli->outbuf,8,0,True);
694
695         CVAL(cli->outbuf,smb_com) = SMBsetatr;
696         SSVAL(cli->outbuf,smb_tid,cli->cnum);
697         cli_setup_packet(cli);
698
699         SSVAL(cli->outbuf,smb_vwv0, attr);
700         put_dos_date3(cli->outbuf,smb_vwv1, t);
701
702         p = smb_buf(cli->outbuf);
703         *p++ = 4;
704         p += clistr_push(cli, p, fname, -1, STR_TERMINATE);
705         *p++ = 4;
706
707         cli_setup_bcc(cli, p);
708
709         cli_send_smb(cli);
710         if (!cli_receive_smb(cli)) {
711                 return False;
712         }
713         
714         if (cli_is_error(cli)) {
715                 return False;
716         }
717
718         return True;
719 }
720
721 /****************************************************************************
722  Check for existance of a dir.
723 ****************************************************************************/
724
725 BOOL cli_chkpath(struct cli_state *cli, const char *path)
726 {
727         pstring path2;
728         char *p;
729         
730         safe_strcpy(path2,path,sizeof(pstring));
731         trim_string(path2,NULL,"\\");
732         if (!*path2) *path2 = '\\';
733         
734         memset(cli->outbuf,'\0',smb_size);
735         set_message(cli->outbuf,0,0,True);
736         SCVAL(cli->outbuf,smb_com,SMBchkpth);
737         SSVAL(cli->outbuf,smb_tid,cli->cnum);
738         cli_setup_packet(cli);
739         p = smb_buf(cli->outbuf);
740         *p++ = 4;
741         p += clistr_push(cli, p, path2, -1, STR_TERMINATE);
742
743         cli_setup_bcc(cli, p);
744
745         cli_send_smb(cli);
746         if (!cli_receive_smb(cli)) {
747                 return False;
748         }
749
750         if (cli_is_error(cli)) return False;
751
752         return True;
753 }
754
755 /****************************************************************************
756  Query disk space.
757 ****************************************************************************/
758
759 BOOL cli_dskattr(struct cli_state *cli, int *bsize, int *total, int *avail)
760 {
761         memset(cli->outbuf,'\0',smb_size);
762         set_message(cli->outbuf,0,0,True);
763         CVAL(cli->outbuf,smb_com) = SMBdskattr;
764         SSVAL(cli->outbuf,smb_tid,cli->cnum);
765         cli_setup_packet(cli);
766
767         cli_send_smb(cli);
768         if (!cli_receive_smb(cli)) {
769                 return False;
770         }
771
772         *bsize = SVAL(cli->inbuf,smb_vwv1)*SVAL(cli->inbuf,smb_vwv2);
773         *total = SVAL(cli->inbuf,smb_vwv0);
774         *avail = SVAL(cli->inbuf,smb_vwv3);
775         
776         return True;
777 }
778
779 /****************************************************************************
780  Create and open a temporary file.
781 ****************************************************************************/
782
783 int cli_ctemp(struct cli_state *cli, const char *path, char **tmp_path)
784 {
785         int len;
786         char *p;
787
788         memset(cli->outbuf,'\0',smb_size);
789         memset(cli->inbuf,'\0',smb_size);
790
791         set_message(cli->outbuf,3,0,True);
792
793         CVAL(cli->outbuf,smb_com) = SMBctemp;
794         SSVAL(cli->outbuf,smb_tid,cli->cnum);
795         cli_setup_packet(cli);
796
797         SSVAL(cli->outbuf,smb_vwv0,0);
798         SIVALS(cli->outbuf,smb_vwv1,-1);
799
800         p = smb_buf(cli->outbuf);
801         *p++ = 4;
802         p += clistr_push(cli, p, path, -1, STR_TERMINATE);
803
804         cli_setup_bcc(cli, p);
805
806         cli_send_smb(cli);
807         if (!cli_receive_smb(cli)) {
808                 return -1;
809         }
810
811         if (cli_is_error(cli)) {
812                 return -1;
813         }
814
815         /* despite the spec, the result has a -1, followed by
816            length, followed by name */
817         p = smb_buf(cli->inbuf);
818         p += 4;
819         len = smb_buflen(cli->inbuf) - 4;
820         if (len <= 0) return -1;
821
822         if (tmp_path) {
823                 pstring path2;
824                 clistr_pull(cli, path2, p, 
825                             sizeof(path2), len, STR_ASCII);
826                 *tmp_path = strdup(path2);
827         }
828
829         return SVAL(cli->inbuf,smb_vwv0);
830 }