Ok - fixed a bug in our levelII oplock code. We need to break a level II on
[tprouty/samba.git] / source / 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 BOOL cli_rename(struct cli_state *cli, char *fname_src, char *fname_dst)
30 {
31         char *p;
32
33         memset(cli->outbuf,'\0',smb_size);
34         memset(cli->inbuf,'\0',smb_size);
35
36         set_message(cli->outbuf,1, 4 + strlen(fname_src) + strlen(fname_dst), True);
37
38         CVAL(cli->outbuf,smb_com) = SMBmv;
39         SSVAL(cli->outbuf,smb_tid,cli->cnum);
40         cli_setup_packet(cli);
41
42         SSVAL(cli->outbuf,smb_vwv0,aSYSTEM | aHIDDEN | aDIR);
43
44         p = smb_buf(cli->outbuf);
45         *p++ = 4;
46         pstrcpy(p,fname_src);
47         unix_to_dos(p,True);
48         p = skip_string(p,1);
49         *p++ = 4;
50         pstrcpy(p,fname_dst);
51         unix_to_dos(p,True);
52
53         cli_send_smb(cli);
54         if (!cli_receive_smb(cli)) {
55                 return False;
56         }
57
58         if (CVAL(cli->inbuf,smb_rcls) != 0) {
59                 return False;
60         }
61
62         return True;
63 }
64
65 /****************************************************************************
66 delete a file
67 ****************************************************************************/
68 BOOL cli_unlink(struct cli_state *cli, char *fname)
69 {
70         char *p;
71
72         memset(cli->outbuf,'\0',smb_size);
73         memset(cli->inbuf,'\0',smb_size);
74
75         set_message(cli->outbuf,1, 2 + strlen(fname),True);
76
77         CVAL(cli->outbuf,smb_com) = SMBunlink;
78         SSVAL(cli->outbuf,smb_tid,cli->cnum);
79         cli_setup_packet(cli);
80
81         SSVAL(cli->outbuf,smb_vwv0,aSYSTEM | aHIDDEN);
82   
83         p = smb_buf(cli->outbuf);
84         *p++ = 4;      
85         pstrcpy(p,fname);
86     unix_to_dos(p,True);
87
88         cli_send_smb(cli);
89         if (!cli_receive_smb(cli)) {
90                 return False;
91         }
92
93         if (CVAL(cli->inbuf,smb_rcls) != 0) {
94                 return False;
95         }
96
97         return True;
98 }
99
100 /****************************************************************************
101 create a directory
102 ****************************************************************************/
103 BOOL cli_mkdir(struct cli_state *cli, 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, 2 + strlen(dname),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         pstrcpy(p,dname);
119     unix_to_dos(p,True);
120
121         cli_send_smb(cli);
122         if (!cli_receive_smb(cli)) {
123                 return False;
124         }
125
126         if (CVAL(cli->inbuf,smb_rcls) != 0) {
127                 return False;
128         }
129
130         return True;
131 }
132
133 /****************************************************************************
134 remove a directory
135 ****************************************************************************/
136 BOOL cli_rmdir(struct cli_state *cli, char *dname)
137 {
138         char *p;
139
140         memset(cli->outbuf,'\0',smb_size);
141         memset(cli->inbuf,'\0',smb_size);
142
143         set_message(cli->outbuf,0, 2 + strlen(dname),True);
144
145         CVAL(cli->outbuf,smb_com) = SMBrmdir;
146         SSVAL(cli->outbuf,smb_tid,cli->cnum);
147         cli_setup_packet(cli);
148
149         p = smb_buf(cli->outbuf);
150         *p++ = 4;      
151         pstrcpy(p,dname);
152     unix_to_dos(p,True);
153
154         cli_send_smb(cli);
155         if (!cli_receive_smb(cli)) {
156                 return False;
157         }
158
159         if (CVAL(cli->inbuf,smb_rcls) != 0) {
160                 return False;
161         }
162
163         return True;
164 }
165
166
167
168 /****************************************************************************
169 open a file
170 ****************************************************************************/
171 int cli_nt_create(struct cli_state *cli, char *fname)
172 {
173         char *p;
174
175         memset(cli->outbuf,'\0',smb_size);
176         memset(cli->inbuf,'\0',smb_size);
177
178         set_message(cli->outbuf,24,1 + strlen(fname),True);
179
180         CVAL(cli->outbuf,smb_com) = SMBntcreateX;
181         SSVAL(cli->outbuf,smb_tid,cli->cnum);
182         cli_setup_packet(cli);
183
184         SSVAL(cli->outbuf,smb_vwv0,0xFF);
185         if (cli->use_oplocks)
186                 SIVAL(cli->outbuf,smb_ntcreate_Flags, REQUEST_OPLOCK|REQUEST_BATCH_OPLOCK);
187         else
188                 SIVAL(cli->outbuf,smb_ntcreate_Flags, 0);
189         SIVAL(cli->outbuf,smb_ntcreate_RootDirectoryFid, 0x0);
190         SIVAL(cli->outbuf,smb_ntcreate_DesiredAccess, 0x2019f);
191         SIVAL(cli->outbuf,smb_ntcreate_FileAttributes, 0x0);
192         SIVAL(cli->outbuf,smb_ntcreate_ShareAccess, 0x03);
193         SIVAL(cli->outbuf,smb_ntcreate_CreateDisposition, 0x01);
194         SIVAL(cli->outbuf,smb_ntcreate_CreateOptions, 0x0);
195         SIVAL(cli->outbuf,smb_ntcreate_ImpersonationLevel, 0x02);
196         SSVAL(cli->outbuf,smb_ntcreate_NameLength, strlen(fname));
197
198         p = smb_buf(cli->outbuf);
199         pstrcpy(p,fname);
200     unix_to_dos(p,True);
201         p = skip_string(p,1);
202
203         cli_send_smb(cli);
204         if (!cli_receive_smb(cli)) {
205                 return -1;
206         }
207
208         if (CVAL(cli->inbuf,smb_rcls) != 0) {
209                 return -1;
210         }
211
212         return SVAL(cli->inbuf,smb_vwv2 + 1);
213 }
214
215
216 /****************************************************************************
217 open a file
218 WARNING: if you open with O_WRONLY then getattrE won't work!
219 ****************************************************************************/
220 int cli_open(struct cli_state *cli, char *fname, int flags, int share_mode)
221 {
222         char *p;
223         unsigned openfn=0;
224         unsigned accessmode=0;
225
226         if (flags & O_CREAT)
227                 openfn |= (1<<4);
228         if (!(flags & O_EXCL)) {
229                 if (flags & O_TRUNC)
230                         openfn |= (1<<1);
231                 else
232                         openfn |= (1<<0);
233         }
234
235         accessmode = (share_mode<<4);
236
237         if ((flags & O_ACCMODE) == O_RDWR) {
238                 accessmode |= 2;
239         } else if ((flags & O_ACCMODE) == O_WRONLY) {
240                 accessmode |= 1;
241         } 
242
243 #if defined(O_SYNC)
244         if ((flags & O_SYNC) == O_SYNC) {
245                 accessmode |= (1<<14);
246         }
247 #endif /* O_SYNC */
248
249         if (share_mode == DENY_FCB) {
250                 accessmode = 0xFF;
251         }
252
253         memset(cli->outbuf,'\0',smb_size);
254         memset(cli->inbuf,'\0',smb_size);
255
256         set_message(cli->outbuf,15,1 + strlen(fname),True);
257
258         CVAL(cli->outbuf,smb_com) = SMBopenX;
259         SSVAL(cli->outbuf,smb_tid,cli->cnum);
260         cli_setup_packet(cli);
261
262         SSVAL(cli->outbuf,smb_vwv0,0xFF);
263         SSVAL(cli->outbuf,smb_vwv2,0);  /* no additional info */
264         SSVAL(cli->outbuf,smb_vwv3,accessmode);
265         SSVAL(cli->outbuf,smb_vwv4,aSYSTEM | aHIDDEN);
266         SSVAL(cli->outbuf,smb_vwv5,0);
267         SSVAL(cli->outbuf,smb_vwv8,openfn);
268
269         if (cli->use_oplocks) {
270                 /* if using oplocks then ask for a batch oplock via
271                    core and extended methods */
272                 CVAL(cli->outbuf,smb_flg) |= 
273                         FLAG_REQUEST_OPLOCK|FLAG_REQUEST_BATCH_OPLOCK;
274                 SSVAL(cli->outbuf,smb_vwv2,SVAL(cli->outbuf,smb_vwv2) | 6);
275         }
276   
277         p = smb_buf(cli->outbuf);
278         pstrcpy(p,fname);
279         unix_to_dos(p,True);
280         p = skip_string(p,1);
281
282         cli_send_smb(cli);
283         if (!cli_receive_smb(cli)) {
284                 return -1;
285         }
286
287         if (CVAL(cli->inbuf,smb_rcls) != 0) {
288                 return -1;
289         }
290
291         return SVAL(cli->inbuf,smb_vwv2);
292 }
293
294
295
296
297 /****************************************************************************
298   close a file
299 ****************************************************************************/
300 BOOL cli_close(struct cli_state *cli, int fnum)
301 {
302         memset(cli->outbuf,'\0',smb_size);
303         memset(cli->inbuf,'\0',smb_size);
304
305         set_message(cli->outbuf,3,0,True);
306
307         CVAL(cli->outbuf,smb_com) = SMBclose;
308         SSVAL(cli->outbuf,smb_tid,cli->cnum);
309         cli_setup_packet(cli);
310
311         SSVAL(cli->outbuf,smb_vwv0,fnum);
312         SIVALS(cli->outbuf,smb_vwv1,-1);
313
314         cli_send_smb(cli);
315         if (!cli_receive_smb(cli)) {
316                 return False;
317         }
318
319         if (CVAL(cli->inbuf,smb_rcls) != 0) {
320                 return False;
321         }
322
323         return True;
324 }
325
326
327 /****************************************************************************
328   lock a file
329 ****************************************************************************/
330 BOOL cli_lock(struct cli_state *cli, int fnum, 
331               uint32 offset, uint32 len, int timeout, enum brl_type lock_type)
332 {
333         char *p;
334         int saved_timeout = cli->timeout;
335
336         memset(cli->outbuf,'\0',smb_size);
337         memset(cli->inbuf,'\0', smb_size);
338
339         set_message(cli->outbuf,8,10,True);
340
341         CVAL(cli->outbuf,smb_com) = SMBlockingX;
342         SSVAL(cli->outbuf,smb_tid,cli->cnum);
343         cli_setup_packet(cli);
344
345         CVAL(cli->outbuf,smb_vwv0) = 0xFF;
346         SSVAL(cli->outbuf,smb_vwv2,fnum);
347         CVAL(cli->outbuf,smb_vwv3) = (lock_type == READ_LOCK? 1 : 0);
348         SIVALS(cli->outbuf, smb_vwv4, timeout);
349         SSVAL(cli->outbuf,smb_vwv6,0);
350         SSVAL(cli->outbuf,smb_vwv7,1);
351
352         p = smb_buf(cli->outbuf);
353         SSVAL(p, 0, cli->pid);
354         SIVAL(p, 2, offset);
355         SIVAL(p, 6, len);
356         cli_send_smb(cli);
357
358         cli->timeout = (timeout == -1) ? 0x7FFFFFFF : (timeout + 2*1000);
359
360         if (!cli_receive_smb(cli)) {
361                 cli->timeout = saved_timeout;
362                 return False;
363         }
364
365         cli->timeout = saved_timeout;
366
367         if (CVAL(cli->inbuf,smb_rcls) != 0) {
368                 return False;
369         }
370
371         return True;
372 }
373
374 /****************************************************************************
375   unlock a file
376 ****************************************************************************/
377 BOOL cli_unlock(struct cli_state *cli, int fnum, uint32 offset, uint32 len)
378 {
379         char *p;
380
381         memset(cli->outbuf,'\0',smb_size);
382         memset(cli->inbuf,'\0',smb_size);
383
384         set_message(cli->outbuf,8,10,True);
385
386         CVAL(cli->outbuf,smb_com) = SMBlockingX;
387         SSVAL(cli->outbuf,smb_tid,cli->cnum);
388         cli_setup_packet(cli);
389
390         CVAL(cli->outbuf,smb_vwv0) = 0xFF;
391         SSVAL(cli->outbuf,smb_vwv2,fnum);
392         CVAL(cli->outbuf,smb_vwv3) = 0;
393         SIVALS(cli->outbuf, smb_vwv4, 0);
394         SSVAL(cli->outbuf,smb_vwv6,1);
395         SSVAL(cli->outbuf,smb_vwv7,0);
396
397         p = smb_buf(cli->outbuf);
398         SSVAL(p, 0, cli->pid);
399         SIVAL(p, 2, offset);
400         SIVAL(p, 6, len);
401
402         cli_send_smb(cli);
403         if (!cli_receive_smb(cli)) {
404                 return False;
405         }
406
407         if (CVAL(cli->inbuf,smb_rcls) != 0) {
408                 return False;
409         }
410
411         return True;
412 }
413
414
415 /****************************************************************************
416   lock a file with 64 bit offsets
417 ****************************************************************************/
418 BOOL cli_lock64(struct cli_state *cli, int fnum, 
419                 SMB_BIG_UINT offset, SMB_BIG_UINT len, int timeout, enum brl_type lock_type)
420 {
421         char *p;
422         int saved_timeout = cli->timeout;
423         int ltype;
424
425         ltype = (lock_type == READ_LOCK? 1 : 0);
426         ltype |= LOCKING_ANDX_LARGE_FILES;
427
428         memset(cli->outbuf,'\0',smb_size);
429         memset(cli->inbuf,'\0', smb_size);
430
431         set_message(cli->outbuf,8,20,True);
432
433         CVAL(cli->outbuf,smb_com) = SMBlockingX;
434         SSVAL(cli->outbuf,smb_tid,cli->cnum);
435         cli_setup_packet(cli);
436
437         CVAL(cli->outbuf,smb_vwv0) = 0xFF;
438         SSVAL(cli->outbuf,smb_vwv2,fnum);
439         CVAL(cli->outbuf,smb_vwv3) = ltype;
440         SIVALS(cli->outbuf, smb_vwv4, timeout);
441         SSVAL(cli->outbuf,smb_vwv6,0);
442         SSVAL(cli->outbuf,smb_vwv7,1);
443
444         p = smb_buf(cli->outbuf);
445         SIVAL(p, 0, cli->pid);
446         SIVAL(p, 4, (offset>>32));
447         SIVAL(p, 8, (offset&0xffffffff));
448         SIVAL(p, 12, (len>>32));
449         SIVAL(p, 16, (len&0xffffffff));
450         cli_send_smb(cli);
451
452         cli->timeout = (timeout == -1) ? 0x7FFFFFFF : (timeout + 2*1000);
453
454         if (!cli_receive_smb(cli)) {
455                 cli->timeout = saved_timeout;
456                 return False;
457         }
458
459         cli->timeout = saved_timeout;
460
461         if (CVAL(cli->inbuf,smb_rcls) != 0) {
462                 return False;
463         }
464
465         return True;
466 }
467
468 /****************************************************************************
469   unlock a file with 64 bit offsets
470 ****************************************************************************/
471 BOOL cli_unlock64(struct cli_state *cli, int fnum, SMB_BIG_UINT offset, SMB_BIG_UINT len)
472 {
473         char *p;
474
475         memset(cli->outbuf,'\0',smb_size);
476         memset(cli->inbuf,'\0',smb_size);
477
478         set_message(cli->outbuf,8,20,True);
479
480         CVAL(cli->outbuf,smb_com) = SMBlockingX;
481         SSVAL(cli->outbuf,smb_tid,cli->cnum);
482         cli_setup_packet(cli);
483
484         CVAL(cli->outbuf,smb_vwv0) = 0xFF;
485         SSVAL(cli->outbuf,smb_vwv2,fnum);
486         CVAL(cli->outbuf,smb_vwv3) = LOCKING_ANDX_LARGE_FILES;
487         SIVALS(cli->outbuf, smb_vwv4, 0);
488         SSVAL(cli->outbuf,smb_vwv6,1);
489         SSVAL(cli->outbuf,smb_vwv7,0);
490
491         p = smb_buf(cli->outbuf);
492         SIVAL(p, 0, cli->pid);
493         SIVAL(p, 4, (offset>>32));
494         SIVAL(p, 8, (offset&0xffffffff));
495         SIVAL(p, 12, (len>>32));
496         SIVAL(p, 16, (len&0xffffffff));
497
498         cli_send_smb(cli);
499         if (!cli_receive_smb(cli)) {
500                 return False;
501         }
502
503         if (CVAL(cli->inbuf,smb_rcls) != 0) {
504                 return False;
505         }
506
507         return True;
508 }
509
510
511
512
513
514 /****************************************************************************
515 do a SMBgetattrE call
516 ****************************************************************************/
517 BOOL cli_getattrE(struct cli_state *cli, int fd, 
518                   uint16 *attr, size_t *size, 
519                   time_t *c_time, time_t *a_time, time_t *m_time)
520 {
521         memset(cli->outbuf,'\0',smb_size);
522         memset(cli->inbuf,'\0',smb_size);
523
524         set_message(cli->outbuf,1,0,True);
525
526         CVAL(cli->outbuf,smb_com) = SMBgetattrE;
527         SSVAL(cli->outbuf,smb_tid,cli->cnum);
528         cli_setup_packet(cli);
529
530         SSVAL(cli->outbuf,smb_vwv0,fd);
531
532         cli_send_smb(cli);
533         if (!cli_receive_smb(cli)) {
534                 return False;
535         }
536         
537         if (CVAL(cli->inbuf,smb_rcls) != 0) {
538                 return False;
539         }
540
541         if (size) {
542                 *size = IVAL(cli->inbuf, smb_vwv6);
543         }
544
545         if (attr) {
546                 *attr = SVAL(cli->inbuf,smb_vwv10);
547         }
548
549         if (c_time) {
550                 *c_time = make_unix_date3(cli->inbuf+smb_vwv0);
551         }
552
553         if (a_time) {
554                 *a_time = make_unix_date3(cli->inbuf+smb_vwv2);
555         }
556
557         if (m_time) {
558                 *m_time = make_unix_date3(cli->inbuf+smb_vwv4);
559         }
560
561         return True;
562 }
563
564
565 /****************************************************************************
566 do a SMBgetatr call
567 ****************************************************************************/
568 BOOL cli_getatr(struct cli_state *cli, char *fname, 
569                 uint16 *attr, size_t *size, time_t *t)
570 {
571         char *p;
572
573         memset(cli->outbuf,'\0',smb_size);
574         memset(cli->inbuf,'\0',smb_size);
575
576         set_message(cli->outbuf,0,strlen(fname)+2,True);
577
578         CVAL(cli->outbuf,smb_com) = SMBgetatr;
579         SSVAL(cli->outbuf,smb_tid,cli->cnum);
580         cli_setup_packet(cli);
581
582         p = smb_buf(cli->outbuf);
583         *p = 4;
584         pstrcpy(p+1, fname);
585     unix_to_dos(p+1,True);
586
587         cli_send_smb(cli);
588         if (!cli_receive_smb(cli)) {
589                 return False;
590         }
591         
592         if (CVAL(cli->inbuf,smb_rcls) != 0) {
593                 return False;
594         }
595
596         if (size) {
597                 *size = IVAL(cli->inbuf, smb_vwv3);
598         }
599
600         if (t) {
601                 *t = make_unix_date3(cli->inbuf+smb_vwv1);
602         }
603
604         if (attr) {
605                 *attr = SVAL(cli->inbuf,smb_vwv0);
606         }
607
608
609         return True;
610 }
611
612
613 /****************************************************************************
614 do a SMBsetatr call
615 ****************************************************************************/
616 BOOL cli_setatr(struct cli_state *cli, char *fname, uint16 attr, time_t t)
617 {
618         char *p;
619
620         memset(cli->outbuf,'\0',smb_size);
621         memset(cli->inbuf,'\0',smb_size);
622
623         set_message(cli->outbuf,8,strlen(fname)+4,True);
624
625         CVAL(cli->outbuf,smb_com) = SMBsetatr;
626         SSVAL(cli->outbuf,smb_tid,cli->cnum);
627         cli_setup_packet(cli);
628
629         SSVAL(cli->outbuf,smb_vwv0, attr);
630         put_dos_date3(cli->outbuf,smb_vwv1, t);
631
632         p = smb_buf(cli->outbuf);
633         *p = 4;
634         pstrcpy(p+1, fname);
635     unix_to_dos(p+1,True);
636         p = skip_string(p,1);
637         *p = 4;
638
639         cli_send_smb(cli);
640         if (!cli_receive_smb(cli)) {
641                 return False;
642         }
643         
644         if (CVAL(cli->inbuf,smb_rcls) != 0) {
645                 return False;
646         }
647
648         return True;
649 }
650
651
652 /****************************************************************************
653 check for existance of a dir
654 ****************************************************************************/
655 BOOL cli_chkpath(struct cli_state *cli, char *path)
656 {
657         pstring path2;
658         char *p;
659         
660         safe_strcpy(path2,path,sizeof(pstring));
661         trim_string(path2,NULL,"\\");
662         if (!*path2) *path2 = '\\';
663         
664         memset(cli->outbuf,'\0',smb_size);
665         set_message(cli->outbuf,0,4 + strlen(path2),True);
666         SCVAL(cli->outbuf,smb_com,SMBchkpth);
667         SSVAL(cli->outbuf,smb_tid,cli->cnum);
668         cli_setup_packet(cli);
669         p = smb_buf(cli->outbuf);
670         *p++ = 4;
671         safe_strcpy(p,path2,strlen(path2));
672         unix_to_dos(p,True);
673
674         cli_send_smb(cli);
675         if (!cli_receive_smb(cli)) {
676                 return False;
677         }
678
679         if (cli_error(cli, NULL, NULL, NULL)) return False;
680
681         return True;
682 }
683
684
685
686 /****************************************************************************
687 query disk space
688 ****************************************************************************/
689 BOOL cli_dskattr(struct cli_state *cli, int *bsize, int *total, int *avail)
690 {
691         memset(cli->outbuf,'\0',smb_size);
692         set_message(cli->outbuf,0,0,True);
693         CVAL(cli->outbuf,smb_com) = SMBdskattr;
694         SSVAL(cli->outbuf,smb_tid,cli->cnum);
695         cli_setup_packet(cli);
696
697         cli_send_smb(cli);
698         if (!cli_receive_smb(cli)) {
699                 return False;
700         }
701
702         *bsize = SVAL(cli->inbuf,smb_vwv1)*SVAL(cli->inbuf,smb_vwv2);
703         *total = SVAL(cli->inbuf,smb_vwv0);
704         *avail = SVAL(cli->inbuf,smb_vwv3);
705         
706         return True;
707 }
708