Fixup correct timeout values for blocking lock timeouts (tested at connectathon
[ira/wip.git] / source / smbd / reply.c
1 /* 
2    Unix SMB/CIFS implementation.
3    Main SMB reply routines
4    Copyright (C) Andrew Tridgell 1992-1998
5    Copyright (C) Andrew Bartlett      2001
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    This file handles most of the reply_ calls that the server
23    makes to handle specific protocols
24 */
25
26 #include "includes.h"
27
28 /* look in server.c for some explanation of these variables */
29 extern int Protocol;
30 extern int max_send;
31 extern int max_recv;
32 extern char magic_char;
33 extern BOOL case_sensitive;
34 extern BOOL case_preserve;
35 extern BOOL short_case_preserve;
36 extern int global_oplock_break;
37 unsigned int smb_echo_count = 0;
38
39 extern BOOL global_encrypted_passwords_negotiated;
40
41 /****************************************************************************
42  Ensure we check the path in *exactly* the same way as W2K.
43 ****************************************************************************/
44
45 NTSTATUS check_path_syntax(const char *name)
46 {
47         while (*name == '\\' || *name == '/')
48                 name++;
49         if (name[0] == '.' && name[1] == '\0')
50                 return NT_STATUS_OBJECT_NAME_INVALID;
51         else if (name[0] == '.' && name[1] == '.' &&
52                         (name[2] == '\\' || name [2] == '/' || name[2] == '\0'))
53                 return NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
54         return NT_STATUS_OK;
55 }
56
57 /****************************************************************************
58  Pull a string and check the path - provide for error return.
59 ****************************************************************************/
60
61 size_t srvstr_get_path(char *inbuf, char *dest, const char *src, size_t dest_len, int flags, NTSTATUS *err)
62 {
63         size_t ret = srvstr_pull_buf( inbuf, dest, src, dest_len, flags);
64         *err = check_path_syntax(dest);
65         return ret;
66 }
67
68 /****************************************************************************
69  Reply to a special message.
70 ****************************************************************************/
71
72 int reply_special(char *inbuf,char *outbuf)
73 {
74         int outsize = 4;
75         int msg_type = CVAL(inbuf,0);
76         int msg_flags = CVAL(inbuf,1);
77         pstring name1,name2;
78         char name_type = 0;
79         
80         static BOOL already_got_session = False;
81
82         *name1 = *name2 = 0;
83         
84         memset(outbuf,'\0',smb_size);
85
86         smb_setlen(outbuf,0);
87         
88         switch (msg_type) {
89         case 0x81: /* session request */
90                 
91                 if (already_got_session) {
92                         exit_server("multiple session request not permitted");
93                 }
94                 
95                 SCVAL(outbuf,0,0x82);
96                 SCVAL(outbuf,3,0);
97                 if (name_len(inbuf+4) > 50 || 
98                     name_len(inbuf+4 + name_len(inbuf + 4)) > 50) {
99                         DEBUG(0,("Invalid name length in session request\n"));
100                         return(0);
101                 }
102                 name_extract(inbuf,4,name1);
103                 name_type = name_extract(inbuf,4 + name_len(inbuf + 4),name2);
104                 DEBUG(2,("netbios connect: name1=%s name2=%s\n",
105                          name1,name2));      
106
107                 set_local_machine_name(name1, True);
108                 set_remote_machine_name(name2, True);
109
110                 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
111                          get_local_machine_name(), get_remote_machine_name(),
112                          name_type));
113
114                 if (name_type == 'R') {
115                         /* We are being asked for a pathworks session --- 
116                            no thanks! */
117                         SCVAL(outbuf, 0,0x83);
118                         break;
119                 }
120
121                 /* only add the client's machine name to the list
122                    of possibly valid usernames if we are operating
123                    in share mode security */
124                 if (lp_security() == SEC_SHARE) {
125                         add_session_user(get_remote_machine_name());
126                 }
127
128                 reload_services(True);
129                 reopen_logs();
130
131                 claim_connection(NULL,"",0,True,FLAG_MSG_GENERAL|FLAG_MSG_SMBD);
132
133                 already_got_session = True;
134                 break;
135                 
136         case 0x89: /* session keepalive request 
137                       (some old clients produce this?) */
138                 SCVAL(outbuf,0,SMBkeepalive);
139                 SCVAL(outbuf,3,0);
140                 break;
141                 
142         case 0x82: /* positive session response */
143         case 0x83: /* negative session response */
144         case 0x84: /* retarget session response */
145                 DEBUG(0,("Unexpected session response\n"));
146                 break;
147                 
148         case SMBkeepalive: /* session keepalive */
149         default:
150                 return(0);
151         }
152         
153         DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
154                     msg_type, msg_flags));
155         
156         return(outsize);
157 }
158
159 /****************************************************************************
160  Reply to a tcon.
161 ****************************************************************************/
162
163 int reply_tcon(connection_struct *conn,
164                char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
165 {
166         const char *service;
167         pstring service_buf;
168         pstring password;
169         pstring dev;
170         int outsize = 0;
171         uint16 vuid = SVAL(inbuf,smb_uid);
172         int pwlen=0;
173         NTSTATUS nt_status;
174         char *p;
175         DATA_BLOB password_blob;
176         
177         START_PROFILE(SMBtcon);
178
179         *service_buf = *password = *dev = 0;
180
181         p = smb_buf(inbuf)+1;
182         p += srvstr_pull_buf(inbuf, service_buf, p, sizeof(service_buf), STR_TERMINATE) + 1;
183         pwlen = srvstr_pull_buf(inbuf, password, p, sizeof(password), STR_TERMINATE) + 1;
184         p += pwlen;
185         p += srvstr_pull_buf(inbuf, dev, p, sizeof(dev), STR_TERMINATE) + 1;
186
187         p = strrchr_m(service_buf,'\\');
188         if (p) {
189                 service = p+1;
190         } else {
191                 service = service_buf;
192         }
193
194         password_blob = data_blob(password, pwlen+1);
195
196         conn = make_connection(service,password_blob,dev,vuid,&nt_status);
197
198         data_blob_clear_free(&password_blob);
199   
200         if (!conn) {
201                 END_PROFILE(SMBtcon);
202                 return ERROR_NT(nt_status);
203         }
204   
205         outsize = set_message(outbuf,2,0,True);
206         SSVAL(outbuf,smb_vwv0,max_recv);
207         SSVAL(outbuf,smb_vwv1,conn->cnum);
208         SSVAL(outbuf,smb_tid,conn->cnum);
209   
210         DEBUG(3,("tcon service=%s cnum=%d\n", 
211                  service, conn->cnum));
212   
213         END_PROFILE(SMBtcon);
214         return(outsize);
215 }
216
217 /****************************************************************************
218  Reply to a tcon and X.
219 ****************************************************************************/
220
221 int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
222 {
223         fstring service;
224         DATA_BLOB password;
225
226         /* what the cleint thinks the device is */
227         fstring client_devicetype;
228         /* what the server tells the client the share represents */
229         const char *server_devicetype;
230         NTSTATUS nt_status;
231         uint16 vuid = SVAL(inbuf,smb_uid);
232         int passlen = SVAL(inbuf,smb_vwv3);
233         pstring path;
234         char *p, *q;
235         extern BOOL global_encrypted_passwords_negotiated;
236         
237         START_PROFILE(SMBtconX);        
238
239         *service = *client_devicetype = 0;
240
241         /* we might have to close an old one */
242         if ((SVAL(inbuf,smb_vwv2) & 0x1) && conn) {
243                 close_cnum(conn,vuid);
244         }
245
246         if (passlen > MAX_PASS_LEN) {
247                 return ERROR_DOS(ERRDOS,ERRbuftoosmall);
248         }
249  
250         if (global_encrypted_passwords_negotiated) {
251                 password = data_blob(smb_buf(inbuf),passlen);
252         } else {
253                 password = data_blob(smb_buf(inbuf),passlen+1);
254                 /* Ensure correct termination */
255                 password.data[passlen]=0;    
256         }
257
258         p = smb_buf(inbuf) + passlen;
259         p += srvstr_pull_buf(inbuf, path, p, sizeof(path), STR_TERMINATE);
260
261         /*
262          * the service name can be either: \\server\share
263          * or share directly like on the DELL PowerVault 705
264          */
265         if (*path=='\\') {      
266                 q = strchr_m(path+2,'\\');
267                 if (!q) {
268                         END_PROFILE(SMBtconX);
269                         return(ERROR_DOS(ERRDOS,ERRnosuchshare));
270                 }
271                 fstrcpy(service,q+1);
272         }
273         else
274                 fstrcpy(service,path);
275                 
276         p += srvstr_pull(inbuf, client_devicetype, p, sizeof(client_devicetype), 6, STR_ASCII);
277
278         DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
279
280         conn = make_connection(service,password,client_devicetype,vuid,&nt_status);
281         
282         data_blob_clear_free(&password);
283
284         if (!conn) {
285                 END_PROFILE(SMBtconX);
286                 return ERROR_NT(nt_status);
287         }
288
289         if ( IS_IPC(conn) )
290                 server_devicetype = "IPC";
291         else if ( IS_PRINT(conn) )
292                 server_devicetype = "LPT1:";
293         else 
294                 server_devicetype = "A:";
295
296         if (Protocol < PROTOCOL_NT1) {
297                 set_message(outbuf,2,0,True);
298                 p = smb_buf(outbuf);
299                 p += srvstr_push(outbuf, p, server_devicetype, -1, 
300                                  STR_TERMINATE|STR_ASCII);
301                 set_message_end(outbuf,p);
302         } else {
303                 /* NT sets the fstype of IPC$ to the null string */
304                 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
305                 
306                 set_message(outbuf,3,0,True);
307
308                 p = smb_buf(outbuf);
309                 p += srvstr_push(outbuf, p, server_devicetype, -1, 
310                                  STR_TERMINATE|STR_ASCII);
311                 p += srvstr_push(outbuf, p, fstype, -1, 
312                                  STR_TERMINATE);
313                 
314                 set_message_end(outbuf,p);
315                 
316                 /* what does setting this bit do? It is set by NT4 and
317                    may affect the ability to autorun mounted cdroms */
318                 SSVAL(outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS|
319                                 (lp_csc_policy(SNUM(conn)) << 2));
320                 
321                 init_dfsroot(conn, inbuf, outbuf);
322         }
323
324   
325         DEBUG(3,("tconX service=%s \n",
326                  service));
327   
328         /* set the incoming and outgoing tid to the just created one */
329         SSVAL(inbuf,smb_tid,conn->cnum);
330         SSVAL(outbuf,smb_tid,conn->cnum);
331
332         END_PROFILE(SMBtconX);
333         return chain_reply(inbuf,outbuf,length,bufsize);
334 }
335
336 /****************************************************************************
337  Reply to an unknown type.
338 ****************************************************************************/
339
340 int reply_unknown(char *inbuf,char *outbuf)
341 {
342         int type;
343         type = CVAL(inbuf,smb_com);
344   
345         DEBUG(0,("unknown command type (%s): type=%d (0x%X)\n",
346                  smb_fn_name(type), type, type));
347   
348         return(ERROR_DOS(ERRSRV,ERRunknownsmb));
349 }
350
351 /****************************************************************************
352  Reply to an ioctl.
353 ****************************************************************************/
354
355 int reply_ioctl(connection_struct *conn,
356                 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
357 {
358         uint16 device     = SVAL(inbuf,smb_vwv1);
359         uint16 function   = SVAL(inbuf,smb_vwv2);
360         uint32 ioctl_code = (device << 16) + function;
361         int replysize, outsize;
362         char *p;
363         START_PROFILE(SMBioctl);
364
365         DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
366
367         switch (ioctl_code) {
368             case IOCTL_QUERY_JOB_INFO:
369                 replysize = 32;
370                 break;
371             default:
372                 END_PROFILE(SMBioctl);
373                 return(ERROR_DOS(ERRSRV,ERRnosupport));
374         }
375
376         outsize = set_message(outbuf,8,replysize+1,True);
377         SSVAL(outbuf,smb_vwv1,replysize); /* Total data bytes returned */
378         SSVAL(outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
379         SSVAL(outbuf,smb_vwv6,52);        /* Offset to data */
380         p = smb_buf(outbuf) + 1;          /* Allow for alignment */
381
382         switch (ioctl_code) {
383                 case IOCTL_QUERY_JOB_INFO:                  
384                 {
385                         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
386                         if (!fsp) {
387                                 END_PROFILE(SMBioctl);
388                                 return(UNIXERROR(ERRDOS,ERRbadfid));
389                         }
390                         SSVAL(p,0,fsp->rap_print_jobid);             /* Job number */
391                         srvstr_push(outbuf, p+2, global_myname(), 15, STR_TERMINATE|STR_ASCII);
392                         srvstr_push(outbuf, p+18, lp_servicename(SNUM(conn)), 13, STR_TERMINATE|STR_ASCII);
393                         break;
394                 }
395         }
396
397         END_PROFILE(SMBioctl);
398         return outsize;
399 }
400
401 /****************************************************************************
402  Reply to a chkpth.
403 ****************************************************************************/
404
405 int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
406 {
407         int outsize = 0;
408         int mode;
409         pstring name;
410         BOOL ok = False;
411         BOOL bad_path = False;
412         SMB_STRUCT_STAT sbuf;
413         NTSTATUS status;
414
415         START_PROFILE(SMBchkpth);
416
417         srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), STR_TERMINATE, &status);
418         if (!NT_STATUS_IS_OK(status)) {
419                 END_PROFILE(SMBchkpth);
420                 return ERROR_NT(status);
421         }
422
423         RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
424
425         unix_convert(name,conn,0,&bad_path,&sbuf);
426
427         mode = SVAL(inbuf,smb_vwv0);
428
429         if (check_name(name,conn)) {
430                 if (VALID_STAT(sbuf) || SMB_VFS_STAT(conn,name,&sbuf) == 0)
431                         if (!(ok = S_ISDIR(sbuf.st_mode))) {
432                                 END_PROFILE(SMBchkpth);
433                                 return ERROR_BOTH(NT_STATUS_NOT_A_DIRECTORY,ERRDOS,ERRbadpath);
434                         }
435         }
436
437         if (!ok) {
438                 /* We special case this - as when a Windows machine
439                         is parsing a path is steps through the components
440                         one at a time - if a component fails it expects
441                         ERRbadpath, not ERRbadfile.
442                 */
443                 if(errno == ENOENT) {
444                         /*
445                          * Windows returns different error codes if
446                          * the parent directory is valid but not the
447                          * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
448                          * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
449                          * if the path is invalid.
450                          */
451                         if (bad_path) {
452                                 END_PROFILE(SMBchkpth);
453                                 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
454                         } else {
455                                 END_PROFILE(SMBchkpth);
456                                 return ERROR_NT(NT_STATUS_OBJECT_NAME_NOT_FOUND);
457                         }
458                 } else if (errno == ENOTDIR) {
459                         END_PROFILE(SMBchkpth);
460                         return ERROR_NT(NT_STATUS_NOT_A_DIRECTORY);
461                 }
462
463                 END_PROFILE(SMBchkpth);
464                 return(UNIXERROR(ERRDOS,ERRbadpath));
465         }
466
467         outsize = set_message(outbuf,0,0,True);
468
469         DEBUG(3,("chkpth %s mode=%d\n", name, mode));
470
471         END_PROFILE(SMBchkpth);
472         return(outsize);
473 }
474
475 /****************************************************************************
476  Reply to a getatr.
477 ****************************************************************************/
478
479 int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
480 {
481         pstring fname;
482         int outsize = 0;
483         SMB_STRUCT_STAT sbuf;
484         BOOL ok = False;
485         int mode=0;
486         SMB_OFF_T size=0;
487         time_t mtime=0;
488         BOOL bad_path = False;
489         char *p;
490         NTSTATUS status;
491
492         START_PROFILE(SMBgetatr);
493
494         p = smb_buf(inbuf) + 1;
495         p += srvstr_get_path(inbuf, fname, p, sizeof(fname), STR_TERMINATE,&status);
496         if (!NT_STATUS_IS_OK(status)) {
497                 END_PROFILE(SMBgetatr);
498                 return ERROR_NT(status);
499         }
500
501         RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
502   
503         /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
504                 under WfWg - weird! */
505         if (! (*fname)) {
506                 mode = aHIDDEN | aDIR;
507                 if (!CAN_WRITE(conn))
508                         mode |= aRONLY;
509                 size = 0;
510                 mtime = 0;
511                 ok = True;
512         } else {
513                 unix_convert(fname,conn,0,&bad_path,&sbuf);
514                 if (check_name(fname,conn)) {
515                         if (VALID_STAT(sbuf) || SMB_VFS_STAT(conn,fname,&sbuf) == 0) {
516                                 mode = dos_mode(conn,fname,&sbuf);
517                                 size = sbuf.st_size;
518                                 mtime = sbuf.st_mtime;
519                                 if (mode & aDIR)
520                                         size = 0;
521                                 ok = True;
522                         } else {
523                                 DEBUG(3,("stat of %s failed (%s)\n",fname,strerror(errno)));
524                         }
525                 }
526         }
527   
528         if (!ok) {
529                 END_PROFILE(SMBgetatr);
530                 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadfile);
531         }
532  
533         outsize = set_message(outbuf,10,0,True);
534
535         SSVAL(outbuf,smb_vwv0,mode);
536         if(lp_dos_filetime_resolution(SNUM(conn)) )
537                 put_dos_date3(outbuf,smb_vwv1,mtime & ~1);
538         else
539                 put_dos_date3(outbuf,smb_vwv1,mtime);
540         SIVAL(outbuf,smb_vwv3,(uint32)size);
541
542         if (Protocol >= PROTOCOL_NT1)
543                 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
544   
545         DEBUG( 3, ( "getatr name=%s mode=%d size=%d\n", fname, mode, (uint32)size ) );
546   
547         END_PROFILE(SMBgetatr);
548         return(outsize);
549 }
550
551 /****************************************************************************
552  Reply to a setatr.
553 ****************************************************************************/
554
555 int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
556 {
557         pstring fname;
558         int outsize = 0;
559         BOOL ok=False;
560         int mode;
561         time_t mtime;
562         SMB_STRUCT_STAT sbuf;
563         BOOL bad_path = False;
564         char *p;
565         NTSTATUS status;
566
567         START_PROFILE(SMBsetatr);
568
569         p = smb_buf(inbuf) + 1;
570         p += srvstr_get_path(inbuf, fname, p, sizeof(fname), STR_TERMINATE,&status);
571         if (!NT_STATUS_IS_OK(status)) {
572                 END_PROFILE(SMBsetatr);
573                 return ERROR_NT(status);
574         }
575
576         unix_convert(fname,conn,0,&bad_path,&sbuf);
577
578         mode = SVAL(inbuf,smb_vwv0);
579         mtime = make_unix_date3(inbuf+smb_vwv1);
580   
581         if (mode != FILE_ATTRIBUTE_NORMAL) {
582                 if (VALID_STAT_OF_DIR(sbuf))
583                         mode |= aDIR;
584                 else
585                         mode &= ~aDIR;
586
587                 if (check_name(fname,conn))
588                         ok =  (file_chmod(conn,fname,mode,NULL) == 0);
589         } else {
590                 ok = True;
591         }
592
593         if (ok)
594                 ok = set_filetime(conn,fname,mtime);
595   
596         if (!ok) {
597                 END_PROFILE(SMBsetatr);
598                 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
599         }
600  
601         outsize = set_message(outbuf,0,0,True);
602   
603         DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
604   
605         END_PROFILE(SMBsetatr);
606         return(outsize);
607 }
608
609 /****************************************************************************
610  Reply to a dskattr.
611 ****************************************************************************/
612
613 int reply_dskattr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
614 {
615         int outsize = 0;
616         SMB_BIG_UINT dfree,dsize,bsize;
617         START_PROFILE(SMBdskattr);
618
619         SMB_VFS_DISK_FREE(conn,".",True,&bsize,&dfree,&dsize);
620   
621         outsize = set_message(outbuf,5,0,True);
622         
623         if (Protocol <= PROTOCOL_LANMAN2) {
624                 double total_space, free_space;
625                 /* we need to scale this to a number that DOS6 can handle. We
626                    use floating point so we can handle large drives on systems
627                    that don't have 64 bit integers 
628
629                    we end up displaying a maximum of 2G to DOS systems
630                 */
631                 total_space = dsize * (double)bsize;
632                 free_space = dfree * (double)bsize;
633
634                 dsize = (total_space+63*512) / (64*512);
635                 dfree = (free_space+63*512) / (64*512);
636                 
637                 if (dsize > 0xFFFF) dsize = 0xFFFF;
638                 if (dfree > 0xFFFF) dfree = 0xFFFF;
639
640                 SSVAL(outbuf,smb_vwv0,dsize);
641                 SSVAL(outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
642                 SSVAL(outbuf,smb_vwv2,512); /* and this must be 512 */
643                 SSVAL(outbuf,smb_vwv3,dfree);
644         } else {
645                 SSVAL(outbuf,smb_vwv0,dsize);
646                 SSVAL(outbuf,smb_vwv1,bsize/512);
647                 SSVAL(outbuf,smb_vwv2,512);
648                 SSVAL(outbuf,smb_vwv3,dfree);
649         }
650
651         DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
652
653         END_PROFILE(SMBdskattr);
654         return(outsize);
655 }
656
657 /****************************************************************************
658  Reply to a search.
659  Can be called from SMBsearch, SMBffirst or SMBfunique.
660 ****************************************************************************/
661
662 int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
663 {
664         pstring mask;
665         pstring directory;
666         pstring fname;
667         SMB_OFF_T size;
668         int mode;
669         time_t date;
670         int dirtype;
671         int outsize = 0;
672         unsigned int numentries = 0;
673         unsigned int maxentries = 0;
674         BOOL finished = False;
675         char *p;
676         BOOL ok = False;
677         int status_len;
678         pstring path;
679         char status[21];
680         int dptr_num= -1;
681         BOOL check_descend = False;
682         BOOL expect_close = False;
683         BOOL can_open = True;
684         BOOL bad_path = False;
685         NTSTATUS nt_status;
686         START_PROFILE(SMBsearch);
687
688         *mask = *directory = *fname = 0;
689
690         /* If we were called as SMBffirst then we must expect close. */
691         if(CVAL(inbuf,smb_com) == SMBffirst)
692                 expect_close = True;
693   
694         outsize = set_message(outbuf,1,3,True);
695         maxentries = SVAL(inbuf,smb_vwv0); 
696         dirtype = SVAL(inbuf,smb_vwv1);
697         p = smb_buf(inbuf) + 1;
698         p += srvstr_get_path(inbuf, path, p, sizeof(path), STR_TERMINATE,&nt_status);
699         if (!NT_STATUS_IS_OK(nt_status)) {
700                 END_PROFILE(SMBsearch);
701                 return ERROR_NT(nt_status);
702         }
703         p++;
704         status_len = SVAL(p, 0);
705         p += 2;
706   
707         /* dirtype &= ~aDIR; */
708
709         if (status_len == 0) {
710                 SMB_STRUCT_STAT sbuf;
711                 pstring dir2;
712
713                 pstrcpy(directory,path);
714                 pstrcpy(dir2,path);
715                 unix_convert(directory,conn,0,&bad_path,&sbuf);
716                 unix_format(dir2);
717
718                 if (!check_name(directory,conn))
719                         can_open = False;
720
721                 p = strrchr_m(dir2,'/');
722                 if (p == NULL) {
723                         pstrcpy(mask,dir2);
724                         *dir2 = 0;
725                 } else {
726                         *p = 0;
727                         pstrcpy(mask,p+1);
728                 }
729
730                 p = strrchr_m(directory,'/');
731                 if (!p) 
732                         *directory = 0;
733                 else
734                         *p = 0;
735
736                 if (strlen(directory) == 0)
737                         pstrcpy(directory,".");
738                 memset((char *)status,'\0',21);
739                 SCVAL(status,0,(dirtype & 0x1F));
740         } else {
741                 int status_dirtype;
742
743                 memcpy(status,p,21);
744                 status_dirtype = CVAL(status,0) & 0x1F;
745                 if (status_dirtype != (dirtype & 0x1F))
746                         dirtype = status_dirtype;
747
748                 conn->dirptr = dptr_fetch(status+12,&dptr_num);      
749                 if (!conn->dirptr)
750                         goto SearchEmpty;
751                 string_set(&conn->dirpath,dptr_path(dptr_num));
752                 pstrcpy(mask, dptr_wcard(dptr_num));
753         }
754
755         if (can_open) {
756                 p = smb_buf(outbuf) + 3;
757                 ok = True;
758      
759                 if (status_len == 0) {
760                         dptr_num = dptr_create(conn,directory,True,expect_close,SVAL(inbuf,smb_pid));
761                         if (dptr_num < 0) {
762                                 if(dptr_num == -2) {
763                                         END_PROFILE(SMBsearch);
764                                         return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnofids);
765                                 }
766                                 END_PROFILE(SMBsearch);
767                                 return ERROR_DOS(ERRDOS,ERRnofids);
768                         }
769                         dptr_set_wcard(dptr_num, strdup(mask));
770                         dptr_set_attr(dptr_num, dirtype);
771                 } else {
772                         dirtype = dptr_attr(dptr_num);
773                 }
774
775                 DEBUG(4,("dptr_num is %d\n",dptr_num));
776
777                 if (ok) {
778                         if ((dirtype&0x1F) == aVOLID) {   
779                                 memcpy(p,status,21);
780                                 make_dir_struct(p,"???????????",volume_label(SNUM(conn)),0,aVOLID,0);
781                                 dptr_fill(p+12,dptr_num);
782                                 if (dptr_zero(p+12) && (status_len==0))
783                                         numentries = 1;
784                                 else
785                                         numentries = 0;
786                                 p += DIR_STRUCT_SIZE;
787                         } else {
788                                 unsigned int i;
789                                 maxentries = MIN(maxentries, ((BUFFER_SIZE - (p - outbuf))/DIR_STRUCT_SIZE));
790
791                                 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
792                                 conn->dirpath,lp_dontdescend(SNUM(conn))));
793                                 if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True))
794                                         check_descend = True;
795
796                                 for (i=numentries;(i<maxentries) && !finished;i++) {
797                                         finished = !get_dir_entry(conn,mask,dirtype,fname,&size,&mode,&date,check_descend);
798                                         if (!finished) {
799                                                 memcpy(p,status,21);
800                                                 make_dir_struct(p,mask,fname,size,mode,date);
801                                                 dptr_fill(p+12,dptr_num);
802                                                 numentries++;
803                                         }
804                                         p += DIR_STRUCT_SIZE;
805                                 }
806                         }
807                 } /* if (ok ) */
808         }
809
810
811   SearchEmpty:
812
813         /* If we were called as SMBffirst with smb_search_id == NULL
814                 and no entries were found then return error and close dirptr 
815                 (X/Open spec) */
816
817         if(ok && expect_close && numentries == 0 && status_len == 0) {
818                 if (Protocol < PROTOCOL_NT1) {
819                         SCVAL(outbuf,smb_rcls,ERRDOS);
820                         SSVAL(outbuf,smb_err,ERRnofiles);
821                 }
822                 /* Also close the dptr - we know it's gone */
823                 dptr_close(&dptr_num);
824         } else if (numentries == 0 || !ok) {
825                 if (Protocol < PROTOCOL_NT1) {
826                         SCVAL(outbuf,smb_rcls,ERRDOS);
827                         SSVAL(outbuf,smb_err,ERRnofiles);
828                 }
829                 dptr_close(&dptr_num);
830         }
831
832         /* If we were called as SMBfunique, then we can close the dirptr now ! */
833         if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique)
834                 dptr_close(&dptr_num);
835
836         SSVAL(outbuf,smb_vwv0,numentries);
837         SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
838         SCVAL(smb_buf(outbuf),0,5);
839         SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
840
841         if (Protocol >= PROTOCOL_NT1)
842                 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
843   
844         outsize += DIR_STRUCT_SIZE*numentries;
845         smb_setlen(outbuf,outsize - 4);
846   
847         if ((! *directory) && dptr_path(dptr_num))
848                 slprintf(directory, sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
849
850         DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%u of %u\n",
851                 smb_fn_name(CVAL(inbuf,smb_com)), 
852                 mask, directory, dirtype, numentries, maxentries ) );
853
854         END_PROFILE(SMBsearch);
855         return(outsize);
856 }
857
858 /****************************************************************************
859  Reply to a fclose (stop directory search).
860 ****************************************************************************/
861
862 int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
863 {
864         int outsize = 0;
865         int status_len;
866         pstring path;
867         char status[21];
868         int dptr_num= -2;
869         char *p;
870         NTSTATUS err;
871
872         START_PROFILE(SMBfclose);
873
874         outsize = set_message(outbuf,1,0,True);
875         p = smb_buf(inbuf) + 1;
876         p += srvstr_get_path(inbuf, path, p, sizeof(path), STR_TERMINATE,&err);
877         if (!NT_STATUS_IS_OK(err)) {
878                 END_PROFILE(SMBfclose);
879                 return ERROR_NT(err);
880         }
881         p++;
882         status_len = SVAL(p,0);
883         p += 2;
884
885         if (status_len == 0) {
886                 END_PROFILE(SMBfclose);
887                 return ERROR_DOS(ERRSRV,ERRsrverror);
888         }
889
890         memcpy(status,p,21);
891
892         if(dptr_fetch(status+12,&dptr_num)) {
893                 /*  Close the dptr - we know it's gone */
894                 dptr_close(&dptr_num);
895         }
896
897         SSVAL(outbuf,smb_vwv0,0);
898
899         DEBUG(3,("search close\n"));
900
901         END_PROFILE(SMBfclose);
902         return(outsize);
903 }
904
905 /****************************************************************************
906  Reply to an open.
907 ****************************************************************************/
908
909 int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
910 {
911         pstring fname;
912         int outsize = 0;
913         int fmode=0;
914         int share_mode;
915         SMB_OFF_T size = 0;
916         time_t mtime=0;
917         mode_t unixmode;
918         int rmode=0;
919         SMB_STRUCT_STAT sbuf;
920         BOOL bad_path = False;
921         files_struct *fsp;
922         int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
923         NTSTATUS status;
924         START_PROFILE(SMBopen);
925  
926         share_mode = SVAL(inbuf,smb_vwv0);
927
928         srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), STR_TERMINATE,&status);
929         if (!NT_STATUS_IS_OK(status)) {
930                 END_PROFILE(SMBopen);
931                 return ERROR_NT(status);
932         }
933
934         RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
935
936         unix_convert(fname,conn,0,&bad_path,&sbuf);
937     
938         unixmode = unix_mode(conn,aARCH,fname);
939       
940         fsp = open_file_shared(conn,fname,&sbuf,share_mode,(FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
941                         unixmode, oplock_request,&rmode,NULL);
942
943         if (!fsp) {
944                 END_PROFILE(SMBopen);
945                 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
946         }
947
948         size = sbuf.st_size;
949         fmode = dos_mode(conn,fname,&sbuf);
950         mtime = sbuf.st_mtime;
951
952         if (fmode & aDIR) {
953                 DEBUG(3,("attempt to open a directory %s\n",fname));
954                 close_file(fsp,False);
955                 END_PROFILE(SMBopen);
956                 return ERROR_DOS(ERRDOS,ERRnoaccess);
957         }
958   
959         outsize = set_message(outbuf,7,0,True);
960         SSVAL(outbuf,smb_vwv0,fsp->fnum);
961         SSVAL(outbuf,smb_vwv1,fmode);
962         if(lp_dos_filetime_resolution(SNUM(conn)) )
963                 put_dos_date3(outbuf,smb_vwv2,mtime & ~1);
964         else
965                 put_dos_date3(outbuf,smb_vwv2,mtime);
966         SIVAL(outbuf,smb_vwv4,(uint32)size);
967         SSVAL(outbuf,smb_vwv6,rmode);
968
969         if (oplock_request && lp_fake_oplocks(SNUM(conn)))
970                 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
971     
972         if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
973                 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
974         END_PROFILE(SMBopen);
975         return(outsize);
976 }
977
978 /****************************************************************************
979  Reply to an open and X.
980 ****************************************************************************/
981
982 int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
983 {
984         pstring fname;
985         int smb_mode = SVAL(inbuf,smb_vwv3);
986         int smb_attr = SVAL(inbuf,smb_vwv5);
987         /* Breakout the oplock request bits so we can set the
988                 reply bits separately. */
989         BOOL ex_oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf);
990         BOOL core_oplock_request = CORE_OPLOCK_REQUEST(inbuf);
991         BOOL oplock_request = ex_oplock_request | core_oplock_request;
992 #if 0
993         int open_flags = SVAL(inbuf,smb_vwv2);
994         int smb_sattr = SVAL(inbuf,smb_vwv4); 
995         uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
996 #endif
997         int smb_ofun = SVAL(inbuf,smb_vwv8);
998         mode_t unixmode;
999         SMB_OFF_T size=0;
1000         int fmode=0,mtime=0,rmode=0;
1001         SMB_STRUCT_STAT sbuf;
1002         int smb_action = 0;
1003         BOOL bad_path = False;
1004         files_struct *fsp;
1005         NTSTATUS status;
1006         START_PROFILE(SMBopenX);
1007
1008         /* If it's an IPC, pass off the pipe handler. */
1009         if (IS_IPC(conn)) {
1010                 if (lp_nt_pipe_support()) {
1011                         END_PROFILE(SMBopenX);
1012                         return reply_open_pipe_and_X(conn, inbuf,outbuf,length,bufsize);
1013                 } else {
1014                         END_PROFILE(SMBopenX);
1015                         return ERROR_DOS(ERRSRV,ERRaccess);
1016                 }
1017         }
1018
1019         /* XXXX we need to handle passed times, sattr and flags */
1020         srvstr_get_path(inbuf, fname, smb_buf(inbuf), sizeof(fname), STR_TERMINATE,&status);
1021         if (!NT_STATUS_IS_OK(status)) {
1022                 END_PROFILE(SMBopenX);
1023                 return ERROR_NT(status);
1024         }
1025
1026         RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1027
1028         unix_convert(fname,conn,0,&bad_path,&sbuf);
1029     
1030         unixmode = unix_mode(conn,smb_attr | aARCH, fname);
1031       
1032         fsp = open_file_shared(conn,fname,&sbuf,smb_mode,smb_ofun,unixmode,
1033                         oplock_request, &rmode,&smb_action);
1034       
1035         if (!fsp) {
1036                 END_PROFILE(SMBopenX);
1037                 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1038         }
1039
1040         size = sbuf.st_size;
1041         fmode = dos_mode(conn,fname,&sbuf);
1042         mtime = sbuf.st_mtime;
1043         if (fmode & aDIR) {
1044                 close_file(fsp,False);
1045                 END_PROFILE(SMBopenX);
1046                 return ERROR_DOS(ERRDOS,ERRnoaccess);
1047         }
1048
1049         /* If the caller set the extended oplock request bit
1050                 and we granted one (by whatever means) - set the
1051                 correct bit for extended oplock reply.
1052         */
1053
1054         if (ex_oplock_request && lp_fake_oplocks(SNUM(conn)))
1055                 smb_action |= EXTENDED_OPLOCK_GRANTED;
1056
1057         if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1058                 smb_action |= EXTENDED_OPLOCK_GRANTED;
1059
1060         /* If the caller set the core oplock request bit
1061                 and we granted one (by whatever means) - set the
1062                 correct bit for core oplock reply.
1063         */
1064
1065         if (core_oplock_request && lp_fake_oplocks(SNUM(conn)))
1066                 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1067
1068         if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1069                 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1070
1071         set_message(outbuf,15,0,True);
1072         SSVAL(outbuf,smb_vwv2,fsp->fnum);
1073         SSVAL(outbuf,smb_vwv3,fmode);
1074         if(lp_dos_filetime_resolution(SNUM(conn)) )
1075                 put_dos_date3(outbuf,smb_vwv4,mtime & ~1);
1076         else
1077                 put_dos_date3(outbuf,smb_vwv4,mtime);
1078         SIVAL(outbuf,smb_vwv6,(uint32)size);
1079         SSVAL(outbuf,smb_vwv8,rmode);
1080         SSVAL(outbuf,smb_vwv11,smb_action);
1081
1082         END_PROFILE(SMBopenX);
1083         return chain_reply(inbuf,outbuf,length,bufsize);
1084 }
1085
1086 /****************************************************************************
1087  Reply to a SMBulogoffX.
1088 ****************************************************************************/
1089
1090 int reply_ulogoffX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1091 {
1092         uint16 vuid = SVAL(inbuf,smb_uid);
1093         user_struct *vuser = get_valid_user_struct(vuid);
1094         START_PROFILE(SMBulogoffX);
1095
1096         if(vuser == 0)
1097                 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid));
1098
1099         /* in user level security we are supposed to close any files
1100                 open by this user */
1101         if ((vuser != 0) && (lp_security() != SEC_SHARE))
1102                 file_close_user(vuid);
1103
1104         invalidate_vuid(vuid);
1105
1106         set_message(outbuf,2,0,True);
1107
1108         DEBUG( 3, ( "ulogoffX vuid=%d\n", vuid ) );
1109
1110         END_PROFILE(SMBulogoffX);
1111         return chain_reply(inbuf,outbuf,length,bufsize);
1112 }
1113
1114 /****************************************************************************
1115  Reply to a mknew or a create.
1116 ****************************************************************************/
1117
1118 int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1119 {
1120         pstring fname;
1121         int com;
1122         int outsize = 0;
1123         int createmode;
1124         mode_t unixmode;
1125         int ofun = 0;
1126         BOOL bad_path = False;
1127         files_struct *fsp;
1128         int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1129         SMB_STRUCT_STAT sbuf;
1130         NTSTATUS status;
1131         START_PROFILE(SMBcreate);
1132  
1133         com = SVAL(inbuf,smb_com);
1134
1135         createmode = SVAL(inbuf,smb_vwv0);
1136         srvstr_get_path(inbuf, fname, smb_buf(inbuf) + 1, sizeof(fname), STR_TERMINATE,&status);
1137         if (!NT_STATUS_IS_OK(status)) {
1138                 END_PROFILE(SMBcreate);
1139                 return ERROR_NT(status);
1140         }
1141
1142         RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1143
1144         unix_convert(fname,conn,0,&bad_path,&sbuf);
1145
1146         if (createmode & aVOLID)
1147                 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
1148   
1149         unixmode = unix_mode(conn,createmode,fname);
1150   
1151         if(com == SMBmknew) {
1152                 /* We should fail if file exists. */
1153                 ofun = FILE_CREATE_IF_NOT_EXIST;
1154         } else {
1155                 /* SMBcreate - Create if file doesn't exist, truncate if it does. */
1156                 ofun = FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_TRUNCATE;
1157         }
1158
1159         /* Open file in dos compatibility share mode. */
1160         fsp = open_file_shared(conn,fname,&sbuf,SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB), 
1161                         ofun, unixmode, oplock_request, NULL, NULL);
1162   
1163         if (!fsp) {
1164                 END_PROFILE(SMBcreate);
1165                 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1166         }
1167  
1168         outsize = set_message(outbuf,1,0,True);
1169         SSVAL(outbuf,smb_vwv0,fsp->fnum);
1170
1171         if (oplock_request && lp_fake_oplocks(SNUM(conn)))
1172                 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1173  
1174         if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1175                 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1176  
1177         DEBUG( 2, ( "new file %s\n", fname ) );
1178         DEBUG( 3, ( "mknew %s fd=%d dmode=%d umode=%o\n", fname, fsp->fd, createmode, (int)unixmode ) );
1179
1180         END_PROFILE(SMBcreate);
1181         return(outsize);
1182 }
1183
1184 /****************************************************************************
1185  Reply to a create temporary file.
1186 ****************************************************************************/
1187
1188 int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1189 {
1190         pstring fname;
1191         int outsize = 0;
1192         int createmode;
1193         mode_t unixmode;
1194         BOOL bad_path = False;
1195         files_struct *fsp;
1196         int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1197         int tmpfd;
1198         SMB_STRUCT_STAT sbuf;
1199         char *p, *s;
1200         NTSTATUS status;
1201
1202         START_PROFILE(SMBctemp);
1203
1204         createmode = SVAL(inbuf,smb_vwv0);
1205         srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), STR_TERMINATE,&status);
1206         if (!NT_STATUS_IS_OK(status)) {
1207                 END_PROFILE(SMBctemp);
1208                 return ERROR_NT(status);
1209         }
1210         pstrcat(fname,"\\TMXXXXXX");
1211
1212         RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1213
1214         unix_convert(fname,conn,0,&bad_path,&sbuf);
1215   
1216         unixmode = unix_mode(conn,createmode,fname);
1217   
1218         tmpfd = smb_mkstemp(fname);
1219         if (tmpfd == -1) {
1220                 END_PROFILE(SMBctemp);
1221                 return(UNIXERROR(ERRDOS,ERRnoaccess));
1222         }
1223
1224         SMB_VFS_STAT(conn,fname,&sbuf);
1225
1226         /* Open file in dos compatibility share mode. */
1227         /* We should fail if file does not exist. */
1228         fsp = open_file_shared(conn,fname,&sbuf,
1229                 SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1230                 FILE_EXISTS_OPEN|FILE_FAIL_IF_NOT_EXIST,
1231                 unixmode, oplock_request, NULL, NULL);
1232
1233         /* close fd from smb_mkstemp() */
1234         close(tmpfd);
1235
1236         if (!fsp) {
1237                 END_PROFILE(SMBctemp);
1238                 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1239         }
1240
1241         outsize = set_message(outbuf,1,0,True);
1242         SSVAL(outbuf,smb_vwv0,fsp->fnum);
1243
1244         /* the returned filename is relative to the directory */
1245         s = strrchr_m(fname, '/');
1246         if (!s)
1247                 s = fname;
1248         else
1249                 s++;
1250
1251         p = smb_buf(outbuf);
1252         SSVALS(p, 0, -1); /* what is this? not in spec */
1253         SSVAL(p, 2, strlen(s));
1254         p += 4;
1255         p += srvstr_push(outbuf, p, s, -1, STR_ASCII);
1256         outsize = set_message_end(outbuf, p);
1257
1258         if (oplock_request && lp_fake_oplocks(SNUM(conn)))
1259                 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1260   
1261         if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1262                 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1263
1264         DEBUG( 2, ( "created temp file %s\n", fname ) );
1265         DEBUG( 3, ( "ctemp %s fd=%d dmode=%d umode=%o\n",
1266                         fname, fsp->fd, createmode, (int)unixmode ) );
1267
1268         END_PROFILE(SMBctemp);
1269         return(outsize);
1270 }
1271
1272 /*******************************************************************
1273  Check if a user is allowed to rename a file.
1274 ********************************************************************/
1275
1276 static NTSTATUS can_rename(char *fname,connection_struct *conn, SMB_STRUCT_STAT *pst)
1277 {
1278         int smb_action;
1279         int access_mode;
1280         files_struct *fsp;
1281
1282         if (!CAN_WRITE(conn))
1283                 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1284         
1285         if (S_ISDIR(pst->st_mode))
1286                 return NT_STATUS_OK;
1287
1288         /* We need a better way to return NT status codes from open... */
1289         unix_ERR_class = 0;
1290         unix_ERR_code = 0;
1291
1292         fsp = open_file_shared1(conn, fname, pst, DELETE_ACCESS, SET_DENY_MODE(DENY_ALL),
1293                 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), 0, 0, &access_mode, &smb_action);
1294
1295         if (!fsp) {
1296                 NTSTATUS ret = NT_STATUS_ACCESS_DENIED;
1297                 if (unix_ERR_class == ERRDOS && unix_ERR_code == ERRbadshare)
1298                         ret = NT_STATUS_SHARING_VIOLATION;
1299                 unix_ERR_class = 0;
1300                 unix_ERR_code = 0;
1301                 unix_ERR_ntstatus = NT_STATUS_OK;
1302                 return ret;
1303         }
1304         close_file(fsp,False);
1305         return NT_STATUS_OK;
1306 }
1307
1308 /*******************************************************************
1309  Check if a user is allowed to delete a file.
1310 ********************************************************************/
1311
1312 static NTSTATUS can_delete(char *fname,connection_struct *conn, int dirtype)
1313 {
1314         SMB_STRUCT_STAT sbuf;
1315         int fmode;
1316         int smb_action;
1317         int access_mode;
1318         files_struct *fsp;
1319
1320         DEBUG(10,("can_delete: %s, dirtype = %d\n",
1321                 fname, dirtype ));
1322
1323         if (!CAN_WRITE(conn))
1324                 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1325
1326         if (SMB_VFS_LSTAT(conn,fname,&sbuf) != 0)
1327                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1328
1329         fmode = dos_mode(conn,fname,&sbuf);
1330
1331         /* Can't delete a directory. */
1332         if (fmode & aDIR)
1333                 return NT_STATUS_FILE_IS_A_DIRECTORY;
1334 #if 0 /* JRATEST */
1335         else if (dirtype & aDIR) /* Asked for a directory and it isn't. */
1336                 return NT_STATUS_OBJECT_NAME_INVALID;
1337 #endif /* JRATEST */
1338
1339         if (!lp_delete_readonly(SNUM(conn))) {
1340                 if (fmode & aRONLY)
1341                         return NT_STATUS_CANNOT_DELETE;
1342         }
1343         if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
1344                 return NT_STATUS_NO_SUCH_FILE;
1345
1346         /* We need a better way to return NT status codes from open... */
1347         unix_ERR_class = 0;
1348         unix_ERR_code = 0;
1349
1350         fsp = open_file_shared1(conn, fname, &sbuf, DELETE_ACCESS, SET_DENY_MODE(DENY_ALL),
1351                 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), 0, 0, &access_mode, &smb_action);
1352
1353         if (!fsp) {
1354                 NTSTATUS ret = NT_STATUS_ACCESS_DENIED;
1355                 if (!NT_STATUS_IS_OK(unix_ERR_ntstatus))
1356                         ret = unix_ERR_ntstatus;
1357                 else if (unix_ERR_class == ERRDOS && unix_ERR_code == ERRbadshare)
1358                         ret = NT_STATUS_SHARING_VIOLATION;
1359                 unix_ERR_class = 0;
1360                 unix_ERR_code = 0;
1361                 unix_ERR_ntstatus = NT_STATUS_OK;
1362                 return ret;
1363         }
1364         close_file(fsp,False);
1365         return NT_STATUS_OK;
1366 }
1367
1368 /****************************************************************************
1369  The guts of the unlink command, split out so it may be called by the NT SMB
1370  code.
1371 ****************************************************************************/
1372
1373 NTSTATUS unlink_internals(connection_struct *conn, int dirtype, char *name)
1374 {
1375         pstring directory;
1376         pstring mask;
1377         char *p;
1378         int count=0;
1379         NTSTATUS error = NT_STATUS_OK;
1380         BOOL has_wild;
1381         BOOL bad_path = False;
1382         BOOL rc = True;
1383         SMB_STRUCT_STAT sbuf;
1384         
1385         *directory = *mask = 0;
1386         
1387         /* We must check for wildcards in the name given
1388          * directly by the client - before any unmangling.
1389          * This prevents an unmangling of a UNIX name containing
1390          * a DOS wildcard like '*' or '?' from unmangling into
1391          * a wildcard delete which was not intended.
1392          * FIX for #226. JRA.
1393          */
1394
1395         has_wild = ms_has_wild(name);
1396
1397         rc = unix_convert(name,conn,0,&bad_path,&sbuf);
1398         
1399         p = strrchr_m(name,'/');
1400         if (!p) {
1401                 pstrcpy(directory,".");
1402                 pstrcpy(mask,name);
1403         } else {
1404                 *p = 0;
1405                 pstrcpy(directory,name);
1406                 pstrcpy(mask,p+1);
1407         }
1408         
1409         /*
1410          * We should only check the mangled cache
1411          * here if unix_convert failed. This means
1412          * that the path in 'mask' doesn't exist
1413          * on the file system and so we need to look
1414          * for a possible mangle. This patch from
1415          * Tine Smukavec <valentin.smukavec@hermes.si>.
1416          */
1417         
1418         if (!rc && mangle_is_mangled(mask))
1419                 mangle_check_cache( mask );
1420         
1421         if (!has_wild) {
1422                 pstrcat(directory,"/");
1423                 pstrcat(directory,mask);
1424                 error = can_delete(directory,conn,dirtype);
1425                 if (!NT_STATUS_IS_OK(error))
1426                         return error;
1427
1428                 if (SMB_VFS_UNLINK(conn,directory) == 0) {
1429                         count++;
1430                 }
1431         } else {
1432                 void *dirptr = NULL;
1433                 const char *dname;
1434                 
1435                 if (check_name(directory,conn))
1436                         dirptr = OpenDir(conn, directory, True);
1437                 
1438                 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
1439                    the pattern matches against the long name, otherwise the short name 
1440                    We don't implement this yet XXXX
1441                 */
1442                 
1443                 if (dirptr) {
1444                         error = NT_STATUS_NO_SUCH_FILE;
1445                         
1446                         if (strequal(mask,"????????.???"))
1447                                 pstrcpy(mask,"*");
1448
1449                         while ((dname = ReadDirName(dirptr))) {
1450                                 pstring fname;
1451                                 pstrcpy(fname,dname);
1452                                 
1453                                 if(!mask_match(fname, mask, case_sensitive))
1454                                         continue;
1455                                 
1456                                 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
1457                                 error = can_delete(fname,conn,dirtype);
1458                                 if (!NT_STATUS_IS_OK(error))
1459                                         continue;
1460                                 if (SMB_VFS_UNLINK(conn,fname) == 0)
1461                                         count++;
1462                                 DEBUG(3,("unlink_internals: succesful unlink [%s]\n",fname));
1463                         }
1464                         CloseDir(dirptr);
1465                 }
1466         }
1467         
1468         if (count == 0 && NT_STATUS_IS_OK(error)) {
1469                 error = map_nt_error_from_unix(errno);
1470         }
1471
1472         return error;
1473 }
1474
1475 /****************************************************************************
1476  Reply to a unlink
1477 ****************************************************************************/
1478
1479 int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, 
1480                  int dum_buffsize)
1481 {
1482         int outsize = 0;
1483         pstring name;
1484         int dirtype;
1485         NTSTATUS status;
1486         START_PROFILE(SMBunlink);
1487         
1488         dirtype = SVAL(inbuf,smb_vwv0);
1489         
1490         srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), STR_TERMINATE,&status);
1491         if (!NT_STATUS_IS_OK(status)) {
1492                 END_PROFILE(SMBunlink);
1493                 return ERROR_NT(status);
1494         }
1495         
1496         RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
1497         
1498         DEBUG(3,("reply_unlink : %s\n",name));
1499         
1500         status = unlink_internals(conn, dirtype, name);
1501         if (!NT_STATUS_IS_OK(status))
1502                 return ERROR_NT(status);
1503
1504         /*
1505          * Win2k needs a changenotify request response before it will
1506          * update after a rename..
1507          */
1508         process_pending_change_notify_queue((time_t)0);
1509         
1510         outsize = set_message(outbuf,0,0,True);
1511   
1512         END_PROFILE(SMBunlink);
1513         return outsize;
1514 }
1515
1516 /****************************************************************************
1517  Fail for readbraw.
1518 ****************************************************************************/
1519
1520 void fail_readraw(void)
1521 {
1522         pstring errstr;
1523         slprintf(errstr, sizeof(errstr)-1, "FAIL ! reply_readbraw: socket write fail (%s)",
1524                 strerror(errno) );
1525         exit_server(errstr);
1526 }
1527
1528 /****************************************************************************
1529  Use sendfile in readbraw.
1530 ****************************************************************************/
1531
1532 void send_file_readbraw(connection_struct *conn, files_struct *fsp, SMB_OFF_T startpos, size_t nread,
1533                 ssize_t mincount, char *outbuf)
1534 {
1535         ssize_t ret=0;
1536
1537 #if defined(WITH_SENDFILE)
1538         /*
1539          * We can only use sendfile on a non-chained packet and on a file
1540          * that is exclusively oplocked. reply_readbraw has already checked the length.
1541          */
1542
1543         if ((nread > 0) && (lp_write_cache_size(SNUM(conn)) == 0) &&
1544                         EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type) && lp_use_sendfile(SNUM(conn)) ) {
1545                 DATA_BLOB header;
1546
1547                 _smb_setlen(outbuf,nread);
1548                 header.data = outbuf;
1549                 header.length = 4;
1550                 header.free = NULL;
1551
1552                 if ( SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fd, &header, startpos, nread) == -1) {
1553                         /*
1554                          * Special hack for broken Linux with no 64 bit clean sendfile. If we
1555                          * return ENOSYS then pretend we just got a normal read.
1556                          */
1557                         if (errno == ENOSYS)
1558                                 goto normal_read;
1559
1560                         DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n",
1561                                 fsp->fsp_name, strerror(errno) ));
1562                         exit_server("send_file_readbraw sendfile failed");
1563                 }
1564
1565         }
1566
1567   normal_read:
1568 #endif
1569
1570         if (nread > 0) {
1571                 ret = read_file(fsp,outbuf+4,startpos,nread);
1572 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
1573                 if (ret < mincount)
1574                         ret = 0;
1575 #else
1576                 if (ret < nread)
1577                         ret = 0;
1578 #endif
1579         }
1580
1581         _smb_setlen(outbuf,ret);
1582         if (write_data(smbd_server_fd(),outbuf,4+ret) != 4+ret)
1583                 fail_readraw();
1584 }
1585
1586 /****************************************************************************
1587  Reply to a readbraw (core+ protocol).
1588 ****************************************************************************/
1589
1590 int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_size, int dum_buffsize)
1591 {
1592         extern struct current_user current_user;
1593         ssize_t maxcount,mincount;
1594         size_t nread = 0;
1595         SMB_OFF_T startpos;
1596         char *header = outbuf;
1597         files_struct *fsp;
1598         START_PROFILE(SMBreadbraw);
1599
1600         if (srv_is_signing_active()) {
1601                 exit_server("reply_readbraw: SMB signing is active - raw reads/writes are disallowed.");
1602         }
1603
1604         /*
1605          * Special check if an oplock break has been issued
1606          * and the readraw request croses on the wire, we must
1607          * return a zero length response here.
1608          */
1609
1610         if(global_oplock_break) {
1611                 _smb_setlen(header,0);
1612                 if (write_data(smbd_server_fd(),header,4) != 4)
1613                         fail_readraw();
1614                 DEBUG(5,("readbraw - oplock break finished\n"));
1615                 END_PROFILE(SMBreadbraw);
1616                 return -1;
1617         }
1618
1619         fsp = file_fsp(inbuf,smb_vwv0);
1620
1621         if (!FNUM_OK(fsp,conn) || !fsp->can_read) {
1622                 /*
1623                  * fsp could be NULL here so use the value from the packet. JRA.
1624                  */
1625                 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",(int)SVAL(inbuf,smb_vwv0)));
1626                 _smb_setlen(header,0);
1627                 if (write_data(smbd_server_fd(),header,4) != 4)
1628                         fail_readraw();
1629                 END_PROFILE(SMBreadbraw);
1630                 return(-1);
1631         }
1632
1633         CHECK_FSP(fsp,conn);
1634
1635         flush_write_cache(fsp, READRAW_FLUSH);
1636
1637         startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
1638         if(CVAL(inbuf,smb_wct) == 10) {
1639                 /*
1640                  * This is a large offset (64 bit) read.
1641                  */
1642 #ifdef LARGE_SMB_OFF_T
1643
1644                 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv8)) << 32);
1645
1646 #else /* !LARGE_SMB_OFF_T */
1647
1648                 /*
1649                  * Ensure we haven't been sent a >32 bit offset.
1650                  */
1651
1652                 if(IVAL(inbuf,smb_vwv8) != 0) {
1653                         DEBUG(0,("readbraw - large offset (%x << 32) used and we don't support \
1654 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv8) ));
1655                         _smb_setlen(header,0);
1656                         if (write_data(smbd_server_fd(),header,4) != 4)
1657                                 fail_readraw();
1658                         END_PROFILE(SMBreadbraw);
1659                         return(-1);
1660                 }
1661
1662 #endif /* LARGE_SMB_OFF_T */
1663
1664                 if(startpos < 0) {
1665                         DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n", (double)startpos ));
1666                         _smb_setlen(header,0);
1667                         if (write_data(smbd_server_fd(),header,4) != 4)
1668                                 fail_readraw();
1669                         END_PROFILE(SMBreadbraw);
1670                         return(-1);
1671                 }      
1672         }
1673         maxcount = (SVAL(inbuf,smb_vwv3) & 0xFFFF);
1674         mincount = (SVAL(inbuf,smb_vwv4) & 0xFFFF);
1675
1676         /* ensure we don't overrun the packet size */
1677         maxcount = MIN(65535,maxcount);
1678
1679         if (!is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
1680                 SMB_OFF_T size = fsp->size;
1681                 SMB_OFF_T sizeneeded = startpos + maxcount;
1682   
1683                 if (size < sizeneeded) {
1684                         SMB_STRUCT_STAT st;
1685                         if (SMB_VFS_FSTAT(fsp,fsp->fd,&st) == 0)
1686                                 size = st.st_size;
1687                         if (!fsp->can_write) 
1688                                 fsp->size = size;
1689                 }
1690
1691                 if (startpos >= size)
1692                         nread = 0;
1693                 else
1694                         nread = MIN(maxcount,(size - startpos));          
1695         }
1696
1697 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
1698         if (nread < mincount)
1699                 nread = 0;
1700 #endif
1701   
1702         DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%d min=%d nread=%d\n", fsp->fnum, (double)startpos,
1703                                 (int)maxcount, (int)mincount, (int)nread ) );
1704   
1705         send_file_readbraw(conn, fsp, startpos, nread, mincount, outbuf);
1706
1707         DEBUG(5,("readbraw finished\n"));
1708         END_PROFILE(SMBreadbraw);
1709         return -1;
1710 }
1711
1712 /****************************************************************************
1713  Reply to a lockread (core+ protocol).
1714 ****************************************************************************/
1715
1716 int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length, int dum_buffsiz)
1717 {
1718         ssize_t nread = -1;
1719         char *data;
1720         int outsize = 0;
1721         SMB_OFF_T startpos;
1722         size_t numtoread;
1723         NTSTATUS status;
1724         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
1725         BOOL my_lock_ctx = False;
1726         START_PROFILE(SMBlockread);
1727
1728         CHECK_FSP(fsp,conn);
1729         CHECK_READ(fsp);
1730
1731         release_level_2_oplocks_on_change(fsp);
1732
1733         numtoread = SVAL(inbuf,smb_vwv1);
1734         startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
1735   
1736         outsize = set_message(outbuf,5,3,True);
1737         numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1738         data = smb_buf(outbuf) + 3;
1739         
1740         /*
1741          * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
1742          * protocol request that predates the read/write lock concept. 
1743          * Thus instead of asking for a read lock here we need to ask
1744          * for a write lock. JRA.
1745          * Note that the requested lock size is unaffected by max_recv.
1746          */
1747         
1748         status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid), 
1749                          (SMB_BIG_UINT)numtoread, (SMB_BIG_UINT)startpos, WRITE_LOCK, &my_lock_ctx);
1750
1751         if (NT_STATUS_V(status)) {
1752 #if 0
1753                 /*
1754                  * We used to make lockread a blocking lock. It turns out
1755                  * that this isn't on W2k. Found by the Samba 4 RAW-READ torture
1756                  * tester. JRA.
1757                  */
1758
1759                 if (lp_blocking_locks(SNUM(conn)) && !my_lock_ctx && ERROR_WAS_LOCK_DENIED(status)) {
1760                         /*
1761                          * A blocking lock was requested. Package up
1762                          * this smb into a queued request and push it
1763                          * onto the blocking lock queue.
1764                          */
1765                         if(push_blocking_lock_request(inbuf, length, -1, 0, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)startpos,
1766                                                                 (SMB_BIG_UINT)numtoread)) {
1767                                 END_PROFILE(SMBlockread);
1768                                 return -1;
1769                         }
1770                 }
1771 #endif
1772                 END_PROFILE(SMBlockread);
1773                 return ERROR_NT(status);
1774         }
1775
1776         /*
1777          * However the requested READ size IS affected by max_recv. Insanity.... JRA.
1778          */
1779
1780         if (numtoread > max_recv) {
1781                 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
1782 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
1783                         (unsigned int)numtoread, (unsigned int)max_recv ));
1784                 numtoread = MIN(numtoread,max_recv);
1785         }
1786         nread = read_file(fsp,data,startpos,numtoread);
1787
1788         if (nread < 0) {
1789                 END_PROFILE(SMBlockread);
1790                 return(UNIXERROR(ERRDOS,ERRnoaccess));
1791         }
1792         
1793         outsize += nread;
1794         SSVAL(outbuf,smb_vwv0,nread);
1795         SSVAL(outbuf,smb_vwv5,nread+3);
1796         SSVAL(smb_buf(outbuf),1,nread);
1797         
1798         DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
1799                  fsp->fnum, (int)numtoread, (int)nread));
1800
1801         END_PROFILE(SMBlockread);
1802         return(outsize);
1803 }
1804
1805 /****************************************************************************
1806  Reply to a read.
1807 ****************************************************************************/
1808
1809 int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
1810 {
1811         size_t numtoread;
1812         ssize_t nread = 0;
1813         char *data;
1814         SMB_OFF_T startpos;
1815         int outsize = 0;
1816         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
1817         START_PROFILE(SMBread);
1818
1819         CHECK_FSP(fsp,conn);
1820         CHECK_READ(fsp);
1821
1822         numtoread = SVAL(inbuf,smb_vwv1);
1823         startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
1824
1825         outsize = set_message(outbuf,5,3,True);
1826         numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1827         /*
1828          * The requested read size cannot be greater than max_recv. JRA.
1829          */
1830         if (numtoread > max_recv) {
1831                 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
1832 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
1833                         (unsigned int)numtoread, (unsigned int)max_recv ));
1834                 numtoread = MIN(numtoread,max_recv);
1835         }
1836
1837         data = smb_buf(outbuf) + 3;
1838   
1839         if (is_locked(fsp,conn,(SMB_BIG_UINT)numtoread,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
1840                 END_PROFILE(SMBread);
1841                 return ERROR_DOS(ERRDOS,ERRlock);
1842         }
1843
1844         if (numtoread > 0)
1845                 nread = read_file(fsp,data,startpos,numtoread);
1846
1847         if (nread < 0) {
1848                 END_PROFILE(SMBread);
1849                 return(UNIXERROR(ERRDOS,ERRnoaccess));
1850         }
1851   
1852         outsize += nread;
1853         SSVAL(outbuf,smb_vwv0,nread);
1854         SSVAL(outbuf,smb_vwv5,nread+3);
1855         SCVAL(smb_buf(outbuf),0,1);
1856         SSVAL(smb_buf(outbuf),1,nread);
1857   
1858         DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
1859                 fsp->fnum, (int)numtoread, (int)nread ) );
1860
1861         END_PROFILE(SMBread);
1862         return(outsize);
1863 }
1864
1865 /****************************************************************************
1866  Reply to a read and X - possibly using sendfile.
1867 ****************************************************************************/
1868
1869 int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length, 
1870                 files_struct *fsp, SMB_OFF_T startpos, size_t smb_maxcnt)
1871 {
1872         ssize_t nread = -1;
1873         char *data = smb_buf(outbuf);
1874
1875 #if defined(WITH_SENDFILE)
1876         /*
1877          * We can only use sendfile on a non-chained packet and on a file
1878          * that is exclusively oplocked.
1879          */
1880
1881         if ((CVAL(inbuf,smb_vwv0) == 0xFF) && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type) &&
1882                         lp_use_sendfile(SNUM(conn)) && (lp_write_cache_size(SNUM(conn)) == 0) ) {
1883                 SMB_STRUCT_STAT sbuf;
1884                 DATA_BLOB header;
1885
1886                 if(SMB_VFS_FSTAT(fsp,fsp->fd, &sbuf) == -1)
1887                         return(UNIXERROR(ERRDOS,ERRnoaccess));
1888
1889                 if (startpos > sbuf.st_size)
1890                         goto normal_read;
1891
1892                 if (smb_maxcnt > (sbuf.st_size - startpos))
1893                         smb_maxcnt = (sbuf.st_size - startpos);
1894
1895                 if (smb_maxcnt == 0)
1896                         goto normal_read;
1897
1898                 /* 
1899                  * Set up the packet header before send. We
1900                  * assume here the sendfile will work (get the
1901                  * correct amount of data).
1902                  */
1903
1904                 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
1905                 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
1906                 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
1907                 SSVAL(smb_buf(outbuf),-2,smb_maxcnt);
1908                 SCVAL(outbuf,smb_vwv0,0xFF);
1909                 set_message(outbuf,12,smb_maxcnt,False);
1910                 header.data = outbuf;
1911                 header.length = data - outbuf;
1912                 header.free = NULL;
1913
1914                 if ( SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fd, &header, startpos, smb_maxcnt) == -1) {
1915                         /*
1916                          * Special hack for broken Linux with no 64 bit clean sendfile. If we
1917                          * return ENOSYS then pretend we just got a normal read.
1918                          */
1919                         if (errno == ENOSYS)
1920                                 goto normal_read;
1921
1922                         DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n",
1923                                 fsp->fsp_name, strerror(errno) ));
1924                         exit_server("send_file_readX sendfile failed");
1925                 }
1926
1927                 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
1928                         fsp->fnum, (int)smb_maxcnt, (int)nread ) );
1929                 return -1;
1930         }
1931
1932   normal_read:
1933
1934 #endif
1935
1936         nread = read_file(fsp,data,startpos,smb_maxcnt);
1937   
1938         if (nread < 0) {
1939                 END_PROFILE(SMBreadX);
1940                 return(UNIXERROR(ERRDOS,ERRnoaccess));
1941         }
1942
1943         SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
1944         SSVAL(outbuf,smb_vwv5,nread);
1945         SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
1946         SSVAL(smb_buf(outbuf),-2,nread);
1947   
1948         DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
1949                 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
1950
1951         return nread;
1952 }
1953
1954 /****************************************************************************
1955  Reply to a read and X.
1956 ****************************************************************************/
1957
1958 int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1959 {
1960         files_struct *fsp = file_fsp(inbuf,smb_vwv2);
1961         SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
1962         ssize_t nread = -1;
1963         size_t smb_maxcnt = SVAL(inbuf,smb_vwv5);
1964 #if 0
1965         size_t smb_mincnt = SVAL(inbuf,smb_vwv6);
1966 #endif
1967
1968         START_PROFILE(SMBreadX);
1969
1970         /* If it's an IPC, pass off the pipe handler. */
1971         if (IS_IPC(conn)) {
1972                 END_PROFILE(SMBreadX);
1973                 return reply_pipe_read_and_X(inbuf,outbuf,length,bufsize);
1974         }
1975
1976         CHECK_FSP(fsp,conn);
1977         CHECK_READ(fsp);
1978
1979         set_message(outbuf,12,0,True);
1980
1981         if(CVAL(inbuf,smb_wct) == 12) {
1982 #ifdef LARGE_SMB_OFF_T
1983                 /*
1984                  * This is a large offset (64 bit) read.
1985                  */
1986                 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv10)) << 32);
1987
1988 #else /* !LARGE_SMB_OFF_T */
1989
1990                 /*
1991                  * Ensure we haven't been sent a >32 bit offset.
1992                  */
1993
1994                 if(IVAL(inbuf,smb_vwv10) != 0) {
1995                         DEBUG(0,("reply_read_and_X - large offset (%x << 32) used and we don't support \
1996 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv10) ));
1997                         END_PROFILE(SMBreadX);
1998                         return ERROR_DOS(ERRDOS,ERRbadaccess);
1999                 }
2000
2001 #endif /* LARGE_SMB_OFF_T */
2002
2003         }
2004
2005         if (is_locked(fsp,conn,(SMB_BIG_UINT)smb_maxcnt,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
2006                 END_PROFILE(SMBreadX);
2007                 return ERROR_DOS(ERRDOS,ERRlock);
2008         }
2009
2010         nread = send_file_readX(conn, inbuf, outbuf, length, fsp, startpos, smb_maxcnt);
2011         if (nread != -1)
2012                 nread = chain_reply(inbuf,outbuf,length,bufsize);
2013
2014         END_PROFILE(SMBreadX);
2015         return nread;
2016 }
2017
2018 /****************************************************************************
2019  Reply to a writebraw (core+ or LANMAN1.0 protocol).
2020 ****************************************************************************/
2021
2022 int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2023 {
2024         ssize_t nwritten=0;
2025         ssize_t total_written=0;
2026         size_t numtowrite=0;
2027         size_t tcount;
2028         SMB_OFF_T startpos;
2029         char *data=NULL;
2030         BOOL write_through;
2031         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2032         int outsize = 0;
2033         START_PROFILE(SMBwritebraw);
2034
2035         if (srv_is_signing_active()) {
2036                 exit_server("reply_writebraw: SMB signing is active - raw reads/writes are disallowed.");
2037         }
2038
2039         CHECK_FSP(fsp,conn);
2040         CHECK_WRITE(fsp);
2041   
2042         tcount = IVAL(inbuf,smb_vwv1);
2043         startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2044         write_through = BITSETW(inbuf+smb_vwv7,0);
2045
2046         /* We have to deal with slightly different formats depending
2047                 on whether we are using the core+ or lanman1.0 protocol */
2048
2049         if(Protocol <= PROTOCOL_COREPLUS) {
2050                 numtowrite = SVAL(smb_buf(inbuf),-2);
2051                 data = smb_buf(inbuf);
2052         } else {
2053                 numtowrite = SVAL(inbuf,smb_vwv10);
2054                 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
2055         }
2056
2057         /* force the error type */
2058         SCVAL(inbuf,smb_com,SMBwritec);
2059         SCVAL(outbuf,smb_com,SMBwritec);
2060
2061         if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2062                 END_PROFILE(SMBwritebraw);
2063                 return(ERROR_DOS(ERRDOS,ERRlock));
2064         }
2065
2066         if (numtowrite>0)
2067                 nwritten = write_file(fsp,data,startpos,numtowrite);
2068   
2069         DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
2070                 fsp->fnum, (double)startpos, (int)numtowrite, (int)nwritten, (int)write_through));
2071
2072         if (nwritten < (ssize_t)numtowrite)  {
2073                 END_PROFILE(SMBwritebraw);
2074                 return(UNIXERROR(ERRHRD,ERRdiskfull));
2075         }
2076
2077         total_written = nwritten;
2078
2079         /* Return a message to the redirector to tell it to send more bytes */
2080         SCVAL(outbuf,smb_com,SMBwritebraw);
2081         SSVALS(outbuf,smb_vwv0,-1);
2082         outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
2083         if (!send_smb(smbd_server_fd(),outbuf))
2084                 exit_server("reply_writebraw: send_smb failed.");
2085   
2086         /* Now read the raw data into the buffer and write it */
2087         if (read_smb_length(smbd_server_fd(),inbuf,SMB_SECONDARY_WAIT) == -1) {
2088                 exit_server("secondary writebraw failed");
2089         }
2090   
2091         /* Even though this is not an smb message, smb_len returns the generic length of an smb message */
2092         numtowrite = smb_len(inbuf);
2093
2094         /* Set up outbuf to return the correct return */
2095         outsize = set_message(outbuf,1,0,True);
2096         SCVAL(outbuf,smb_com,SMBwritec);
2097         SSVAL(outbuf,smb_vwv0,total_written);
2098
2099         if (numtowrite != 0) {
2100
2101                 if (numtowrite > BUFFER_SIZE) {
2102                         DEBUG(0,("reply_writebraw: Oversize secondary write raw requested (%u). Terminating\n",
2103                                 (unsigned int)numtowrite ));
2104                         exit_server("secondary writebraw failed");
2105                 }
2106
2107                 if (tcount > nwritten+numtowrite) {
2108                         DEBUG(3,("Client overestimated the write %d %d %d\n",
2109                                 (int)tcount,(int)nwritten,(int)numtowrite));
2110                 }
2111
2112                 if (read_data( smbd_server_fd(), inbuf+4, numtowrite) != numtowrite ) {
2113                         DEBUG(0,("reply_writebraw: Oversize secondary write raw read failed (%s). Terminating\n",
2114                                 strerror(errno) ));
2115                         exit_server("secondary writebraw failed");
2116                 }
2117
2118                 nwritten = write_file(fsp,inbuf+4,startpos+nwritten,numtowrite);
2119
2120                 if (nwritten < (ssize_t)numtowrite) {
2121                         SCVAL(outbuf,smb_rcls,ERRHRD);
2122                         SSVAL(outbuf,smb_err,ERRdiskfull);      
2123                 }
2124
2125                 if (nwritten > 0)
2126                         total_written += nwritten;
2127         }
2128  
2129         if ((lp_syncalways(SNUM(conn)) || write_through) && lp_strict_sync(SNUM(conn)))
2130                 sync_file(conn,fsp);
2131
2132         DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
2133                 fsp->fnum, (double)startpos, (int)numtowrite,(int)total_written));
2134
2135         /* we won't return a status if write through is not selected - this follows what WfWg does */
2136         END_PROFILE(SMBwritebraw);
2137         if (!write_through && total_written==tcount) {
2138
2139 #if RABBIT_PELLET_FIX
2140                 /*
2141                  * Fix for "rabbit pellet" mode, trigger an early TCP ack by
2142                  * sending a SMBkeepalive. Thanks to DaveCB at Sun for this. JRA.
2143                  */
2144                 if (!send_keepalive(smbd_server_fd()))
2145                         exit_server("reply_writebraw: send of keepalive failed");
2146 #endif
2147                 return(-1);
2148         }
2149
2150         return(outsize);
2151 }
2152
2153 /****************************************************************************
2154  Reply to a writeunlock (core+).
2155 ****************************************************************************/
2156
2157 int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf, 
2158                       int size, int dum_buffsize)
2159 {
2160         ssize_t nwritten = -1;
2161         size_t numtowrite;
2162         SMB_OFF_T startpos;
2163         char *data;
2164         NTSTATUS status = NT_STATUS_OK;
2165         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2166         int outsize = 0;
2167         START_PROFILE(SMBwriteunlock);
2168         
2169         CHECK_FSP(fsp,conn);
2170         CHECK_WRITE(fsp);
2171
2172         numtowrite = SVAL(inbuf,smb_vwv1);
2173         startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2174         data = smb_buf(inbuf) + 3;
2175   
2176         if (numtowrite && is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, 
2177                       WRITE_LOCK,False)) {
2178                 END_PROFILE(SMBwriteunlock);
2179                 return ERROR_DOS(ERRDOS,ERRlock);
2180         }
2181
2182         /* The special X/Open SMB protocol handling of
2183            zero length writes is *NOT* done for
2184            this call */
2185         if(numtowrite == 0)
2186                 nwritten = 0;
2187         else
2188                 nwritten = write_file(fsp,data,startpos,numtowrite);
2189   
2190         if (lp_syncalways(SNUM(conn)))
2191                 sync_file(conn,fsp);
2192
2193         if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2194                 END_PROFILE(SMBwriteunlock);
2195                 return(UNIXERROR(ERRHRD,ERRdiskfull));
2196         }
2197
2198         if (numtowrite) {
2199                 status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)numtowrite, 
2200                                    (SMB_BIG_UINT)startpos);
2201                 if (NT_STATUS_V(status)) {
2202                         END_PROFILE(SMBwriteunlock);
2203                         return ERROR_NT(status);
2204                 }
2205         }
2206         
2207         outsize = set_message(outbuf,1,0,True);
2208         
2209         SSVAL(outbuf,smb_vwv0,nwritten);
2210         
2211         DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
2212                  fsp->fnum, (int)numtowrite, (int)nwritten));
2213         
2214         END_PROFILE(SMBwriteunlock);
2215         return outsize;
2216 }
2217
2218 /****************************************************************************
2219  Reply to a write.
2220 ****************************************************************************/
2221
2222 int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int dum_buffsize)
2223 {
2224         size_t numtowrite;
2225         ssize_t nwritten = -1;
2226         SMB_OFF_T startpos;
2227         char *data;
2228         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2229         int outsize = 0;
2230         START_PROFILE(SMBwrite);
2231
2232         /* If it's an IPC, pass off the pipe handler. */
2233         if (IS_IPC(conn)) {
2234                 END_PROFILE(SMBwrite);
2235                 return reply_pipe_write(inbuf,outbuf,size,dum_buffsize);
2236         }
2237
2238         CHECK_FSP(fsp,conn);
2239         CHECK_WRITE(fsp);
2240
2241         numtowrite = SVAL(inbuf,smb_vwv1);
2242         startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2243         data = smb_buf(inbuf) + 3;
2244   
2245         if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2246                 END_PROFILE(SMBwrite);
2247                 return ERROR_DOS(ERRDOS,ERRlock);
2248         }
2249
2250         /*
2251          * X/Open SMB protocol says that if smb_vwv1 is
2252          * zero then the file size should be extended or
2253          * truncated to the size given in smb_vwv[2-3].
2254          */
2255
2256         if(numtowrite == 0) {
2257                 /*
2258                  * This is actually an allocate call, and set EOF. JRA.
2259                  */
2260                 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
2261                 if (nwritten < 0) {
2262                         END_PROFILE(SMBwrite);
2263                         return ERROR_NT(NT_STATUS_DISK_FULL);
2264                 }
2265                 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
2266                 if (nwritten < 0) {
2267                         END_PROFILE(SMBwrite);
2268                         return ERROR_NT(NT_STATUS_DISK_FULL);
2269                 }
2270         } else
2271                 nwritten = write_file(fsp,data,startpos,numtowrite);
2272   
2273         if (lp_syncalways(SNUM(conn)))
2274                 sync_file(conn,fsp);
2275
2276         if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2277                 END_PROFILE(SMBwrite);
2278                 return(UNIXERROR(ERRHRD,ERRdiskfull));
2279         }
2280
2281         outsize = set_message(outbuf,1,0,True);
2282   
2283         SSVAL(outbuf,smb_vwv0,nwritten);
2284
2285         if (nwritten < (ssize_t)numtowrite) {
2286                 SCVAL(outbuf,smb_rcls,ERRHRD);
2287                 SSVAL(outbuf,smb_err,ERRdiskfull);      
2288         }
2289   
2290         DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
2291
2292         END_PROFILE(SMBwrite);
2293         return(outsize);
2294 }
2295
2296 /****************************************************************************
2297  Reply to a write and X.
2298 ****************************************************************************/
2299
2300 int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2301 {
2302         files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2303         SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2304         size_t numtowrite = SVAL(inbuf,smb_vwv10);
2305         BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
2306         ssize_t nwritten = -1;
2307         unsigned int smb_doff = SVAL(inbuf,smb_vwv11);
2308         unsigned int smblen = smb_len(inbuf);
2309         char *data;
2310         BOOL large_writeX = ((CVAL(inbuf,smb_wct) == 14) && (smblen > 0xFFFF));
2311         START_PROFILE(SMBwriteX);
2312
2313         /* If it's an IPC, pass off the pipe handler. */
2314         if (IS_IPC(conn)) {
2315                 END_PROFILE(SMBwriteX);
2316                 return reply_pipe_write_and_X(inbuf,outbuf,length,bufsize);
2317         }
2318
2319         CHECK_FSP(fsp,conn);
2320         CHECK_WRITE(fsp);
2321
2322         /* Deal with possible LARGE_WRITEX */
2323         if (large_writeX)
2324                 numtowrite |= ((((size_t)SVAL(inbuf,smb_vwv9)) & 1 )<<16);
2325
2326         if(smb_doff > smblen || (smb_doff + numtowrite > smblen)) {
2327                 END_PROFILE(SMBwriteX);
2328                 return ERROR_DOS(ERRDOS,ERRbadmem);
2329         }
2330
2331         data = smb_base(inbuf) + smb_doff;
2332
2333         if(CVAL(inbuf,smb_wct) == 14) {
2334 #ifdef LARGE_SMB_OFF_T
2335                 /*
2336                  * This is a large offset (64 bit) write.
2337                  */
2338                 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv12)) << 32);
2339
2340 #else /* !LARGE_SMB_OFF_T */
2341
2342                 /*
2343                  * Ensure we haven't been sent a >32 bit offset.
2344                  */
2345
2346                 if(IVAL(inbuf,smb_vwv12) != 0) {
2347                         DEBUG(0,("reply_write_and_X - large offset (%x << 32) used and we don't support \
2348 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv12) ));
2349                         END_PROFILE(SMBwriteX);
2350                         return ERROR_DOS(ERRDOS,ERRbadaccess);
2351                 }
2352
2353 #endif /* LARGE_SMB_OFF_T */
2354         }
2355
2356         if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2357                 END_PROFILE(SMBwriteX);
2358                 return ERROR_DOS(ERRDOS,ERRlock);
2359         }
2360
2361         /* X/Open SMB protocol says that, unlike SMBwrite
2362         if the length is zero then NO truncation is
2363         done, just a write of zero. To truncate a file,
2364         use SMBwrite. */
2365
2366         if(numtowrite == 0)
2367                 nwritten = 0;
2368         else
2369                 nwritten = write_file(fsp,data,startpos,numtowrite);
2370   
2371         if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2372                 END_PROFILE(SMBwriteX);
2373                 return(UNIXERROR(ERRHRD,ERRdiskfull));
2374         }
2375
2376         set_message(outbuf,6,0,True);
2377   
2378         SSVAL(outbuf,smb_vwv2,nwritten);
2379         if (large_writeX)
2380                 SSVAL(outbuf,smb_vwv4,(nwritten>>16)&1);
2381
2382         if (nwritten < (ssize_t)numtowrite) {
2383                 SCVAL(outbuf,smb_rcls,ERRHRD);
2384                 SSVAL(outbuf,smb_err,ERRdiskfull);      
2385         }
2386
2387         DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
2388                 fsp->fnum, (int)numtowrite, (int)nwritten));
2389
2390         if (lp_syncalways(SNUM(conn)) || write_through)
2391                 sync_file(conn,fsp);
2392
2393         END_PROFILE(SMBwriteX);
2394         return chain_reply(inbuf,outbuf,length,bufsize);
2395 }
2396
2397 /****************************************************************************
2398  Reply to a lseek.
2399 ****************************************************************************/
2400
2401 int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2402 {
2403         SMB_OFF_T startpos;
2404         SMB_OFF_T res= -1;
2405         int mode,umode;
2406         int outsize = 0;
2407         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2408         START_PROFILE(SMBlseek);
2409
2410         CHECK_FSP(fsp,conn);
2411
2412         flush_write_cache(fsp, SEEK_FLUSH);
2413
2414         mode = SVAL(inbuf,smb_vwv1) & 3;
2415         /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
2416         startpos = (SMB_OFF_T)IVALS(inbuf,smb_vwv2);
2417
2418         switch (mode) {
2419                 case 0:
2420                         umode = SEEK_SET;
2421                         res = startpos;
2422                         break;
2423                 case 1:
2424                         umode = SEEK_CUR;
2425                         res = fsp->pos + startpos;
2426                         break;
2427                 case 2:
2428                         umode = SEEK_END;
2429                         break;
2430                 default:
2431                         umode = SEEK_SET;
2432                         res = startpos;
2433                         break;
2434         }
2435
2436         if (umode == SEEK_END) {
2437                 if((res = SMB_VFS_LSEEK(fsp,fsp->fd,startpos,umode)) == -1) {
2438                         if(errno == EINVAL) {
2439                                 SMB_OFF_T current_pos = startpos;
2440                                 SMB_STRUCT_STAT sbuf;
2441
2442                                 if(SMB_VFS_FSTAT(fsp,fsp->fd, &sbuf) == -1) {
2443                                         END_PROFILE(SMBlseek);
2444                                         return(UNIXERROR(ERRDOS,ERRnoaccess));
2445                                 }
2446
2447                                 current_pos += sbuf.st_size;
2448                                 if(current_pos < 0)
2449                                         res = SMB_VFS_LSEEK(fsp,fsp->fd,0,SEEK_SET);
2450                         }
2451                 }
2452
2453                 if(res == -1) {
2454                         END_PROFILE(SMBlseek);
2455                         return(UNIXERROR(ERRDOS,ERRnoaccess));
2456                 }
2457         }
2458
2459         fsp->pos = res;
2460   
2461         outsize = set_message(outbuf,2,0,True);
2462         SIVAL(outbuf,smb_vwv0,res);
2463   
2464         DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
2465                 fsp->fnum, (double)startpos, (double)res, mode));
2466
2467         END_PROFILE(SMBlseek);
2468         return(outsize);
2469 }
2470
2471 /****************************************************************************
2472  Reply to a flush.
2473 ****************************************************************************/
2474
2475 int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2476 {
2477         int outsize = set_message(outbuf,0,0,True);
2478         uint16 fnum = SVAL(inbuf,smb_vwv0);
2479         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2480         START_PROFILE(SMBflush);
2481
2482         if (fnum != 0xFFFF)
2483                 CHECK_FSP(fsp,conn);
2484         
2485         if (!fsp) {
2486                 file_sync_all(conn);
2487         } else {
2488                 sync_file(conn,fsp);
2489         }
2490         
2491         DEBUG(3,("flush\n"));
2492         END_PROFILE(SMBflush);
2493         return(outsize);
2494 }
2495
2496 /****************************************************************************
2497  Reply to a exit.
2498 ****************************************************************************/
2499
2500 int reply_exit(connection_struct *conn, 
2501                char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2502 {
2503         int outsize;
2504         START_PROFILE(SMBexit);
2505
2506         file_close_pid(SVAL(inbuf,smb_pid));
2507
2508         outsize = set_message(outbuf,0,0,True);
2509
2510         DEBUG(3,("exit\n"));
2511
2512         END_PROFILE(SMBexit);
2513         return(outsize);
2514 }
2515
2516 /****************************************************************************
2517  Reply to a close - has to deal with closing a directory opened by NT SMB's.
2518 ****************************************************************************/
2519
2520 int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size,
2521                 int dum_buffsize)
2522 {
2523         extern struct current_user current_user;
2524         int outsize = 0;
2525         time_t mtime;
2526         int32 eclass = 0, err = 0;
2527         files_struct *fsp = NULL;
2528         START_PROFILE(SMBclose);
2529
2530         outsize = set_message(outbuf,0,0,True);
2531
2532         /* If it's an IPC, pass off to the pipe handler. */
2533         if (IS_IPC(conn)) {
2534                 END_PROFILE(SMBclose);
2535                 return reply_pipe_close(conn, inbuf,outbuf);
2536         }
2537
2538         fsp = file_fsp(inbuf,smb_vwv0);
2539
2540         /*
2541          * We can only use CHECK_FSP if we know it's not a directory.
2542          */
2543
2544         if(!fsp || (fsp->conn != conn) || (fsp->vuid != current_user.vuid)) {
2545                 END_PROFILE(SMBclose);
2546                 return ERROR_DOS(ERRDOS,ERRbadfid);
2547         }
2548
2549         if(fsp->is_directory) {
2550                 /*
2551                  * Special case - close NT SMB directory handle.
2552                  */
2553                 DEBUG(3,("close %s fnum=%d\n", fsp->is_directory ? "directory" : "stat file open", fsp->fnum));
2554                 close_file(fsp,True);
2555         } else {
2556                 /*
2557                  * Close ordinary file.
2558                  */
2559                 int close_err;
2560                 pstring file_name;
2561
2562                 /* Save the name for time set in close. */
2563                 pstrcpy( file_name, fsp->fsp_name);
2564
2565                 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
2566                          fsp->fd, fsp->fnum,
2567                          conn->num_files_open));
2568  
2569                 /*
2570                  * close_file() returns the unix errno if an error
2571                  * was detected on close - normally this is due to
2572                  * a disk full error. If not then it was probably an I/O error.
2573                  */
2574  
2575                 if((close_err = close_file(fsp,True)) != 0) {
2576                         errno = close_err;
2577                         END_PROFILE(SMBclose);
2578                         return (UNIXERROR(ERRHRD,ERRgeneral));
2579                 }
2580
2581                 /*
2582                  * Now take care of any time sent in the close.
2583                  */
2584
2585                 mtime = make_unix_date3(inbuf+smb_vwv1);
2586                 
2587                 /* try and set the date */
2588                 set_filetime(conn, file_name, mtime);
2589
2590         }  
2591
2592         /* We have a cached error */
2593         if(eclass || err) {
2594                 END_PROFILE(SMBclose);
2595                 return ERROR_DOS(eclass,err);
2596         }
2597
2598         END_PROFILE(SMBclose);
2599         return(outsize);
2600 }
2601
2602 /****************************************************************************
2603  Reply to a writeclose (Core+ protocol).
2604 ****************************************************************************/
2605
2606 int reply_writeclose(connection_struct *conn,
2607                      char *inbuf,char *outbuf, int size, int dum_buffsize)
2608 {
2609         size_t numtowrite;
2610         ssize_t nwritten = -1;
2611         int outsize = 0;
2612         int close_err = 0;
2613         SMB_OFF_T startpos;
2614         char *data;
2615         time_t mtime;
2616         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2617         START_PROFILE(SMBwriteclose);
2618
2619         CHECK_FSP(fsp,conn);
2620         CHECK_WRITE(fsp);
2621
2622         numtowrite = SVAL(inbuf,smb_vwv1);
2623         startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2624         mtime = make_unix_date3(inbuf+smb_vwv4);
2625         data = smb_buf(inbuf) + 1;
2626   
2627         if (numtowrite && is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2628                 END_PROFILE(SMBwriteclose);
2629                 return ERROR_DOS(ERRDOS,ERRlock);
2630         }
2631   
2632         nwritten = write_file(fsp,data,startpos,numtowrite);
2633
2634         set_filetime(conn, fsp->fsp_name,mtime);
2635   
2636         /*
2637          * More insanity. W2K only closes the file if writelen > 0.
2638          * JRA.
2639          */
2640
2641         if (numtowrite) {
2642                 DEBUG(3,("reply_writeclose: zero length write doesn't close file %s\n",
2643                         fsp->fsp_name ));
2644                 close_err = close_file(fsp,True);
2645         }
2646
2647         DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
2648                  fsp->fnum, (int)numtowrite, (int)nwritten,
2649                  conn->num_files_open));
2650   
2651         if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2652                 END_PROFILE(SMBwriteclose);
2653                 return(UNIXERROR(ERRHRD,ERRdiskfull));
2654         }
2655  
2656         if(close_err != 0) {
2657                 errno = close_err;
2658                 END_PROFILE(SMBwriteclose);
2659                 return(UNIXERROR(ERRHRD,ERRgeneral));
2660         }
2661  
2662         outsize = set_message(outbuf,1,0,True);
2663   
2664         SSVAL(outbuf,smb_vwv0,nwritten);
2665         END_PROFILE(SMBwriteclose);
2666         return(outsize);
2667 }
2668
2669 /****************************************************************************
2670  Reply to a lock.
2671 ****************************************************************************/
2672
2673 int reply_lock(connection_struct *conn,
2674                char *inbuf,char *outbuf, int length, int dum_buffsize)
2675 {
2676         int outsize = set_message(outbuf,0,0,True);
2677         SMB_BIG_UINT count,offset;
2678         NTSTATUS status;
2679         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2680         BOOL my_lock_ctx = False;
2681
2682         START_PROFILE(SMBlock);
2683
2684         CHECK_FSP(fsp,conn);
2685
2686         release_level_2_oplocks_on_change(fsp);
2687
2688         count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
2689         offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
2690
2691         DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2692                  fsp->fd, fsp->fnum, (double)offset, (double)count));
2693
2694         status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid), count, offset, WRITE_LOCK, &my_lock_ctx);
2695         if (NT_STATUS_V(status)) {
2696 #if 0
2697                 /* Tests using Samba4 against W2K show this call never creates a blocking lock. */
2698                 if (lp_blocking_locks(SNUM(conn)) && !my_lock_ctx && ERROR_WAS_LOCK_DENIED(status)) {
2699                         /*
2700                          * A blocking lock was requested. Package up
2701                          * this smb into a queued request and push it
2702                          * onto the blocking lock queue.
2703                          */
2704                         if(push_blocking_lock_request(inbuf, length, -1, 0, SVAL(inbuf,smb_pid), offset, count)) {
2705                                 END_PROFILE(SMBlock);
2706                                 return -1;
2707                         }
2708                 }
2709 #endif
2710                 END_PROFILE(SMBlock);
2711                 return ERROR_NT(status);
2712         }
2713
2714         END_PROFILE(SMBlock);
2715         return(outsize);
2716 }
2717
2718 /****************************************************************************
2719  Reply to a unlock.
2720 ****************************************************************************/
2721
2722 int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size, 
2723                  int dum_buffsize)
2724 {
2725         int outsize = set_message(outbuf,0,0,True);
2726         SMB_BIG_UINT count,offset;
2727         NTSTATUS status;
2728         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2729         START_PROFILE(SMBunlock);
2730
2731         CHECK_FSP(fsp,conn);
2732         
2733         count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
2734         offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
2735         
2736         status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), count, offset);
2737         if (NT_STATUS_V(status)) {
2738                 END_PROFILE(SMBunlock);
2739                 return ERROR_NT(status);
2740         }
2741
2742         DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2743                     fsp->fd, fsp->fnum, (double)offset, (double)count ) );
2744         
2745         END_PROFILE(SMBunlock);
2746         return(outsize);
2747 }
2748
2749 /****************************************************************************
2750  Reply to a tdis.
2751 ****************************************************************************/
2752
2753 int reply_tdis(connection_struct *conn, 
2754                char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2755 {
2756         int outsize = set_message(outbuf,0,0,True);
2757         uint16 vuid;
2758         START_PROFILE(SMBtdis);
2759
2760         vuid = SVAL(inbuf,smb_uid);
2761
2762         if (!conn) {
2763                 DEBUG(4,("Invalid connection in tdis\n"));
2764                 END_PROFILE(SMBtdis);
2765                 return ERROR_DOS(ERRSRV,ERRinvnid);
2766         }
2767
2768         conn->used = False;
2769
2770         close_cnum(conn,vuid);
2771   
2772         END_PROFILE(SMBtdis);
2773         return outsize;
2774 }
2775
2776 /****************************************************************************
2777  Reply to a echo.
2778 ****************************************************************************/
2779
2780 int reply_echo(connection_struct *conn,
2781                char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2782 {
2783         int smb_reverb = SVAL(inbuf,smb_vwv0);
2784         int seq_num;
2785         unsigned int data_len = smb_buflen(inbuf);
2786         int outsize = set_message(outbuf,1,data_len,True);
2787         START_PROFILE(SMBecho);
2788
2789         if (data_len > BUFFER_SIZE) {
2790                 DEBUG(0,("reply_echo: data_len too large.\n"));
2791                 END_PROFILE(SMBecho);
2792                 return -1;
2793         }
2794
2795         /* copy any incoming data back out */
2796         if (data_len > 0)
2797                 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
2798
2799         if (smb_reverb > 100) {
2800                 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
2801                 smb_reverb = 100;
2802         }
2803
2804         for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
2805                 SSVAL(outbuf,smb_vwv0,seq_num);
2806
2807                 smb_setlen(outbuf,outsize - 4);
2808
2809                 if (!send_smb(smbd_server_fd(),outbuf))
2810                         exit_server("reply_echo: send_smb failed.");
2811         }
2812
2813         DEBUG(3,("echo %d times\n", smb_reverb));
2814
2815         smb_echo_count++;
2816
2817         END_PROFILE(SMBecho);
2818         return -1;
2819 }
2820
2821 /****************************************************************************
2822  Reply to a printopen.
2823 ****************************************************************************/
2824
2825 int reply_printopen(connection_struct *conn, 
2826                     char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2827 {
2828         int outsize = 0;
2829         files_struct *fsp;
2830         START_PROFILE(SMBsplopen);
2831         
2832         if (!CAN_PRINT(conn)) {
2833                 END_PROFILE(SMBsplopen);
2834                 return ERROR_DOS(ERRDOS,ERRnoaccess);
2835         }
2836
2837         /* Open for exclusive use, write only. */
2838         fsp = print_fsp_open(conn, NULL);
2839
2840         if (!fsp) {
2841                 END_PROFILE(SMBsplopen);
2842                 return(UNIXERROR(ERRDOS,ERRnoaccess));
2843         }
2844
2845         outsize = set_message(outbuf,1,0,True);
2846         SSVAL(outbuf,smb_vwv0,fsp->fnum);
2847   
2848         DEBUG(3,("openprint fd=%d fnum=%d\n",
2849                  fsp->fd, fsp->fnum));
2850
2851         END_PROFILE(SMBsplopen);
2852         return(outsize);
2853 }
2854
2855 /****************************************************************************
2856  Reply to a printclose.
2857 ****************************************************************************/
2858
2859 int reply_printclose(connection_struct *conn,
2860                      char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2861 {
2862         int outsize = set_message(outbuf,0,0,True);
2863         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2864         int close_err = 0;
2865         START_PROFILE(SMBsplclose);
2866
2867         CHECK_FSP(fsp,conn);
2868
2869         if (!CAN_PRINT(conn)) {
2870                 END_PROFILE(SMBsplclose);
2871                 return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
2872         }
2873   
2874         DEBUG(3,("printclose fd=%d fnum=%d\n",
2875                  fsp->fd,fsp->fnum));
2876   
2877         close_err = close_file(fsp,True);
2878
2879         if(close_err != 0) {
2880                 errno = close_err;
2881                 END_PROFILE(SMBsplclose);
2882                 return(UNIXERROR(ERRHRD,ERRgeneral));
2883         }
2884
2885         END_PROFILE(SMBsplclose);
2886         return(outsize);
2887 }
2888
2889 /****************************************************************************
2890  Reply to a printqueue.
2891 ****************************************************************************/
2892
2893 int reply_printqueue(connection_struct *conn,
2894                      char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2895 {
2896         int outsize = set_message(outbuf,2,3,True);
2897         int max_count = SVAL(inbuf,smb_vwv0);
2898         int start_index = SVAL(inbuf,smb_vwv1);
2899         START_PROFILE(SMBsplretq);
2900
2901         /* we used to allow the client to get the cnum wrong, but that
2902            is really quite gross and only worked when there was only
2903            one printer - I think we should now only accept it if they
2904            get it right (tridge) */
2905         if (!CAN_PRINT(conn)) {
2906                 END_PROFILE(SMBsplretq);
2907                 return ERROR_DOS(ERRDOS,ERRnoaccess);
2908         }
2909
2910         SSVAL(outbuf,smb_vwv0,0);
2911         SSVAL(outbuf,smb_vwv1,0);
2912         SCVAL(smb_buf(outbuf),0,1);
2913         SSVAL(smb_buf(outbuf),1,0);
2914   
2915         DEBUG(3,("printqueue start_index=%d max_count=%d\n",
2916                  start_index, max_count));
2917
2918         {
2919                 print_queue_struct *queue = NULL;
2920                 print_status_struct status;
2921                 char *p = smb_buf(outbuf) + 3;
2922                 int count = print_queue_status(SNUM(conn), &queue, &status);
2923                 int num_to_get = ABS(max_count);
2924                 int first = (max_count>0?start_index:start_index+max_count+1);
2925                 int i;
2926
2927                 if (first >= count)
2928                         num_to_get = 0;
2929                 else
2930                         num_to_get = MIN(num_to_get,count-first);
2931     
2932
2933                 for (i=first;i<first+num_to_get;i++) {
2934                         put_dos_date2(p,0,queue[i].time);
2935                         SCVAL(p,4,(queue[i].status==LPQ_PRINTING?2:3));
2936                         SSVAL(p,5, queue[i].job);
2937                         SIVAL(p,7,queue[i].size);
2938                         SCVAL(p,11,0);
2939                         srvstr_push(outbuf, p+12, queue[i].fs_user, 16, STR_ASCII);
2940                         p += 28;
2941                 }
2942
2943                 if (count > 0) {
2944                         outsize = set_message(outbuf,2,28*count+3,False); 
2945                         SSVAL(outbuf,smb_vwv0,count);
2946                         SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
2947                         SCVAL(smb_buf(outbuf),0,1);
2948                         SSVAL(smb_buf(outbuf),1,28*count);
2949                 }
2950
2951                 SAFE_FREE(queue);
2952           
2953                 DEBUG(3,("%d entries returned in queue\n",count));
2954         }
2955   
2956         END_PROFILE(SMBsplretq);
2957         return(outsize);
2958 }
2959
2960 /****************************************************************************
2961  Reply to a printwrite.
2962 ****************************************************************************/
2963
2964 int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2965 {
2966         int numtowrite;
2967         int outsize = set_message(outbuf,0,0,True);
2968         char *data;
2969         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2970
2971         START_PROFILE(SMBsplwr);
2972   
2973         if (!CAN_PRINT(conn)) {
2974                 END_PROFILE(SMBsplwr);
2975                 return ERROR_DOS(ERRDOS,ERRnoaccess);
2976         }
2977
2978         CHECK_FSP(fsp,conn);
2979         CHECK_WRITE(fsp);
2980
2981         numtowrite = SVAL(smb_buf(inbuf),1);
2982         data = smb_buf(inbuf) + 3;
2983   
2984         if (write_file(fsp,data,-1,numtowrite) != numtowrite) {
2985                 END_PROFILE(SMBsplwr);
2986                 return(UNIXERROR(ERRHRD,ERRdiskfull));
2987         }
2988
2989         DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
2990   
2991         END_PROFILE(SMBsplwr);
2992         return(outsize);
2993 }
2994
2995 /****************************************************************************
2996  The guts of the mkdir command, split out so it may be called by the NT SMB
2997  code. 
2998 ****************************************************************************/
2999
3000 NTSTATUS mkdir_internal(connection_struct *conn, pstring directory)
3001 {
3002         BOOL bad_path = False;
3003         SMB_STRUCT_STAT sbuf;
3004         int ret= -1;
3005         
3006         unix_convert(directory,conn,0,&bad_path,&sbuf);
3007
3008         if (ms_has_wild(directory)) {
3009                 return NT_STATUS_OBJECT_NAME_INVALID;
3010         }
3011
3012         if (check_name(directory, conn))
3013                 ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory));
3014         
3015         if (ret == -1) {
3016                 if(errno == ENOENT) {
3017                         if (bad_path)
3018                                 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3019                         else
3020                                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3021                 }
3022                 return map_nt_error_from_unix(errno);
3023         }
3024         
3025         return NT_STATUS_OK;
3026 }
3027
3028 /****************************************************************************
3029  Reply to a mkdir.
3030 ****************************************************************************/
3031
3032 int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3033 {
3034         pstring directory;
3035         int outsize;
3036         NTSTATUS status;
3037         START_PROFILE(SMBmkdir);
3038  
3039         srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), STR_TERMINATE,&status);
3040         if (!NT_STATUS_IS_OK(status)) {
3041                 END_PROFILE(SMBmkdir);
3042                 return ERROR_NT(status);
3043         }
3044
3045         RESOLVE_DFSPATH(directory, conn, inbuf, outbuf);
3046
3047         status = mkdir_internal(conn, directory);
3048         if (!NT_STATUS_IS_OK(status)) {
3049                 END_PROFILE(SMBmkdir);
3050                 return ERROR_NT(status);
3051         }
3052
3053         outsize = set_message(outbuf,0,0,True);
3054
3055         DEBUG( 3, ( "mkdir %s ret=%d\n", directory, outsize ) );
3056
3057         END_PROFILE(SMBmkdir);
3058         return(outsize);
3059 }
3060
3061 /****************************************************************************
3062  Static function used by reply_rmdir to delete an entire directory
3063  tree recursively. Return False on ok, True on fail.
3064 ****************************************************************************/
3065
3066 static BOOL recursive_rmdir(connection_struct *conn, char *directory)
3067 {
3068         const char *dname = NULL;
3069         BOOL ret = False;
3070         void *dirptr = OpenDir(conn, directory, False);
3071
3072         if(dirptr == NULL)
3073                 return True;
3074
3075         while((dname = ReadDirName(dirptr))) {
3076                 pstring fullname;
3077                 SMB_STRUCT_STAT st;
3078
3079                 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3080                         continue;
3081
3082                 /* Construct the full name. */
3083                 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
3084                         errno = ENOMEM;
3085                         ret = True;
3086                         break;
3087                 }
3088
3089                 pstrcpy(fullname, directory);
3090                 pstrcat(fullname, "/");
3091                 pstrcat(fullname, dname);
3092
3093                 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
3094                         ret = True;
3095                         break;
3096                 }
3097
3098                 if(st.st_mode & S_IFDIR) {
3099                         if(recursive_rmdir(conn, fullname)!=0) {
3100                                 ret = True;
3101                                 break;
3102                         }
3103                         if(SMB_VFS_RMDIR(conn,fullname) != 0) {
3104                                 ret = True;
3105                                 break;
3106                         }
3107                 } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
3108                         ret = True;
3109                         break;
3110                 }
3111         }
3112         CloseDir(dirptr);
3113         return ret;
3114 }
3115
3116 /****************************************************************************
3117  The internals of the rmdir code - called elsewhere.
3118 ****************************************************************************/
3119
3120 BOOL rmdir_internals(connection_struct *conn, char *directory)
3121 {
3122         BOOL ok;
3123
3124         ok = (SMB_VFS_RMDIR(conn,directory) == 0);
3125         if(!ok && ((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
3126                 /* 
3127                  * Check to see if the only thing in this directory are
3128                  * vetoed files/directories. If so then delete them and
3129                  * retry. If we fail to delete any of them (and we *don't*
3130                  * do a recursive delete) then fail the rmdir.
3131                  */
3132                 BOOL all_veto_files = True;
3133                 const char *dname;
3134                 void *dirptr = OpenDir(conn, directory, False);
3135
3136                 if(dirptr != NULL) {
3137                         int dirpos = TellDir(dirptr);
3138                         while ((dname = ReadDirName(dirptr))) {
3139                                 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3140                                         continue;
3141                                 if(!IS_VETO_PATH(conn, dname)) {
3142                                         all_veto_files = False;
3143                                         break;
3144                                 }
3145                         }
3146
3147                         if(all_veto_files) {
3148                                 SeekDir(dirptr,dirpos);
3149                                 while ((dname = ReadDirName(dirptr))) {
3150                                         pstring fullname;
3151                                         SMB_STRUCT_STAT st;
3152
3153                                         if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3154                                                 continue;
3155
3156                                         /* Construct the full name. */
3157                                         if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
3158                                                 errno = ENOMEM;
3159                                                 break;
3160                                         }
3161
3162                                         pstrcpy(fullname, directory);
3163                                         pstrcat(fullname, "/");
3164                                         pstrcat(fullname, dname);
3165                      
3166                                         if(SMB_VFS_LSTAT(conn,fullname, &st) != 0)
3167                                                 break;
3168                                         if(st.st_mode & S_IFDIR) {
3169                                                 if(lp_recursive_veto_delete(SNUM(conn))) {
3170                                                         if(recursive_rmdir(conn, fullname) != 0)
3171                                                                 break;
3172                                                 }
3173                                                 if(SMB_VFS_RMDIR(conn,fullname) != 0)
3174                                                         break;
3175                                         } else if(SMB_VFS_UNLINK(conn,fullname) != 0)
3176                                                 break;
3177                                 }
3178                                 CloseDir(dirptr);
3179                                 /* Retry the rmdir */
3180                                 ok = (SMB_VFS_RMDIR(conn,directory) == 0);
3181                         } else {
3182                                 CloseDir(dirptr);
3183                         }
3184                 } else {
3185                         errno = ENOTEMPTY;
3186                 }
3187         }
3188
3189         if (!ok)
3190                 DEBUG(3,("rmdir_internals: couldn't remove directory %s : %s\n", directory,strerror(errno)));
3191
3192         return ok;
3193 }
3194
3195 /****************************************************************************
3196  Reply to a rmdir.
3197 ****************************************************************************/
3198
3199 int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3200 {
3201         pstring directory;
3202         int outsize = 0;
3203         BOOL ok = False;
3204         BOOL bad_path = False;
3205         SMB_STRUCT_STAT sbuf;
3206         NTSTATUS status;
3207         START_PROFILE(SMBrmdir);
3208
3209         srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), STR_TERMINATE,&status);
3210         if (!NT_STATUS_IS_OK(status)) {
3211                 END_PROFILE(SMBrmdir);
3212                 return ERROR_NT(status);
3213         }
3214
3215         RESOLVE_DFSPATH(directory, conn, inbuf, outbuf)
3216
3217         unix_convert(directory,conn, NULL,&bad_path,&sbuf);
3218   
3219         if (check_name(directory,conn)) {
3220                 dptr_closepath(directory,SVAL(inbuf,smb_pid));
3221                 ok = rmdir_internals(conn, directory);
3222         }
3223   
3224         if (!ok) {
3225                 END_PROFILE(SMBrmdir);
3226                 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRbadpath);
3227         }
3228  
3229         outsize = set_message(outbuf,0,0,True);
3230   
3231         DEBUG( 3, ( "rmdir %s\n", directory ) );
3232   
3233         END_PROFILE(SMBrmdir);
3234         return(outsize);
3235 }
3236
3237 /*******************************************************************
3238  Resolve wildcards in a filename rename.
3239 ********************************************************************/
3240
3241 static BOOL resolve_wildcards(const char *name1, char *name2)
3242 {
3243         fstring root1,root2;
3244         fstring ext1,ext2;
3245         char *p,*p2, *pname1, *pname2;
3246         int available_space;
3247         
3248
3249         pname1 = strrchr_m(name1,'/');
3250         pname2 = strrchr_m(name2,'/');
3251
3252         if (!pname1 || !pname2)
3253                 return(False);
3254   
3255         fstrcpy(root1,pname1);
3256         fstrcpy(root2,pname2);
3257         p = strrchr_m(root1,'.');
3258         if (p) {
3259                 *p = 0;
3260                 fstrcpy(ext1,p+1);
3261         } else {
3262                 fstrcpy(ext1,"");    
3263         }
3264         p = strrchr_m(root2,'.');
3265         if (p) {
3266                 *p = 0;
3267                 fstrcpy(ext2,p+1);
3268         } else {
3269                 fstrcpy(ext2,"");    
3270         }
3271
3272         p = root1;
3273         p2 = root2;
3274         while (*p2) {
3275                 if (*p2 == '?') {
3276                         *p2 = *p;
3277                         p2++;
3278                 } else {
3279                         p2++;
3280                 }
3281                 if (*p)
3282                         p++;
3283         }
3284
3285         p = ext1;
3286         p2 = ext2;
3287         while (*p2) {
3288                 if (*p2 == '?') {
3289                         *p2 = *p;
3290                         p2++;
3291                 } else {
3292                         p2++;
3293                 }
3294                 if (*p)
3295                         p++;
3296         }
3297
3298         available_space = sizeof(pstring) - PTR_DIFF(pname2, name2);
3299         
3300         if (ext2[0]) {
3301                 snprintf(pname2, available_space - 1, "%s.%s", root2, ext2);
3302         } else {
3303                 pstrcpy_base(pname2, root2, name2);
3304         }
3305
3306         return(True);
3307 }
3308
3309 /****************************************************************************
3310  Ensure open files have their names updates.
3311 ****************************************************************************/
3312
3313 static void rename_open_files(connection_struct *conn, SMB_DEV_T dev, SMB_INO_T inode, char *newname)
3314 {
3315         files_struct *fsp;
3316         BOOL did_rename = False;
3317
3318         for(fsp = file_find_di_first(dev, inode); fsp; fsp = file_find_di_next(fsp)) {
3319                 DEBUG(10,("rename_open_files: renaming file fnum %d (dev = %x, inode = %.0f) from %s -> %s\n",
3320                         fsp->fnum, (unsigned int)fsp->dev, (double)fsp->inode,
3321                         fsp->fsp_name, newname ));
3322                 string_set(&fsp->fsp_name, newname);
3323                 did_rename = True;
3324         }
3325
3326         if (!did_rename)
3327                 DEBUG(10,("rename_open_files: no open files on dev %x, inode %.0f for %s\n",
3328                         (unsigned int)dev, (double)inode, newname ));
3329 }
3330
3331 /****************************************************************************
3332  Rename an open file - given an fsp.
3333 ****************************************************************************/
3334
3335 NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, char *newname, BOOL replace_if_exists)
3336 {
3337         SMB_STRUCT_STAT sbuf;
3338         BOOL bad_path = False;
3339         pstring newname_last_component;
3340         NTSTATUS error = NT_STATUS_OK;
3341         BOOL dest_exists;
3342
3343         ZERO_STRUCT(sbuf);
3344         unix_convert(newname,conn,newname_last_component,&bad_path,&sbuf);
3345
3346         /* Ensure newname contains a '/' */
3347         if(strrchr_m(newname,'/') == 0) {
3348                 pstring tmpstr;
3349                 
3350                 pstrcpy(tmpstr, "./");
3351                 pstrcat(tmpstr, newname);
3352                 pstrcpy(newname, tmpstr);
3353         }
3354
3355         /*
3356          * Check for special case with case preserving and not
3357          * case sensitive. If the old last component differs from the original
3358          * last component only by case, then we should allow
3359          * the rename (user is trying to change the case of the
3360          * filename).
3361          */
3362
3363         if((case_sensitive == False) && (case_preserve == True) &&
3364                         strequal(newname, fsp->fsp_name)) {
3365                 char *p;
3366                 pstring newname_modified_last_component;
3367
3368                 /*
3369                  * Get the last component of the modified name.
3370                  * Note that we guarantee that newname contains a '/'
3371                  * character above.
3372                  */
3373                 p = strrchr_m(newname,'/');
3374                 pstrcpy(newname_modified_last_component,p+1);
3375                         
3376                 if(strcsequal(newname_modified_last_component, 
3377                               newname_last_component) == False) {
3378                         /*
3379                          * Replace the modified last component with
3380                          * the original.
3381                          */
3382                         pstrcpy(p+1, newname_last_component);
3383                 }
3384         }
3385
3386         /*
3387          * If the src and dest names are identical - including case,
3388          * don't do the rename, just return success.
3389          */
3390
3391         if (strcsequal(fsp->fsp_name, newname)) {
3392                 DEBUG(3,("rename_internals_fsp: identical names in rename %s - returning success\n",
3393                         newname));
3394                 return NT_STATUS_OK;
3395         }
3396
3397         dest_exists = vfs_object_exist(conn,newname,NULL);
3398
3399         if(!replace_if_exists && dest_exists) {
3400                 DEBUG(3,("rename_internals_fsp: dest exists doing rename %s -> %s\n",
3401                         fsp->fsp_name,newname));
3402                 return NT_STATUS_OBJECT_NAME_COLLISION;
3403         }
3404
3405         error = can_rename(newname,conn,&sbuf);
3406
3407         if (dest_exists && !NT_STATUS_IS_OK(error)) {
3408                 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3409                         nt_errstr(error), fsp->fsp_name,newname));
3410                 if (NT_STATUS_EQUAL(error,NT_STATUS_SHARING_VIOLATION))
3411                         error = NT_STATUS_ACCESS_DENIED;
3412                 return error;
3413         }
3414
3415         if(SMB_VFS_RENAME(conn,fsp->fsp_name, newname) == 0) {
3416                 DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n",
3417                         fsp->fsp_name,newname));
3418                 rename_open_files(conn, fsp->dev, fsp->inode, newname);
3419                 return NT_STATUS_OK;    
3420         }
3421
3422         if (errno == ENOTDIR || errno == EISDIR)
3423                 error = NT_STATUS_OBJECT_NAME_COLLISION;
3424         else
3425                 error = map_nt_error_from_unix(errno);
3426                 
3427         DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
3428                 nt_errstr(error), fsp->fsp_name,newname));
3429
3430         return error;
3431 }
3432
3433 /****************************************************************************
3434  The guts of the rename command, split out so it may be called by the NT SMB
3435  code. 
3436 ****************************************************************************/
3437
3438 NTSTATUS rename_internals(connection_struct *conn, char *name, char *newname, BOOL replace_if_exists)
3439 {
3440         pstring directory;
3441         pstring mask;
3442         pstring newname_last_component;
3443         char *p;
3444         BOOL has_wild;
3445         BOOL bad_path1 = False;
3446         BOOL bad_path2 = False;
3447         int count=0;
3448         NTSTATUS error = NT_STATUS_OK;
3449         BOOL rc = True;
3450         SMB_STRUCT_STAT sbuf1, sbuf2;
3451
3452         *directory = *mask = 0;
3453
3454         ZERO_STRUCT(sbuf1);
3455         ZERO_STRUCT(sbuf2);
3456         rc = unix_convert(name,conn,0,&bad_path1,&sbuf1);
3457         unix_convert(newname,conn,newname_last_component,&bad_path2,&sbuf2);
3458
3459         /*
3460          * Split the old name into directory and last component
3461          * strings. Note that unix_convert may have stripped off a 
3462          * leading ./ from both name and newname if the rename is 
3463          * at the root of the share. We need to make sure either both
3464          * name and newname contain a / character or neither of them do
3465          * as this is checked in resolve_wildcards().
3466          */
3467         
3468         p = strrchr_m(name,'/');
3469         if (!p) {
3470                 pstrcpy(directory,".");
3471                 pstrcpy(mask,name);
3472         } else {
3473                 *p = 0;
3474                 pstrcpy(directory,name);
3475                 pstrcpy(mask,p+1);
3476                 *p = '/'; /* Replace needed for exceptional test below. */
3477         }
3478
3479         /*
3480          * We should only check the mangled cache
3481          * here if unix_convert failed. This means
3482          * that the path in 'mask' doesn't exist
3483          * on the file system and so we need to look
3484          * for a possible mangle. This patch from
3485          * Tine Smukavec <valentin.smukavec@hermes.si>.
3486          */
3487
3488         if (!rc && mangle_is_mangled(mask))
3489                 mangle_check_cache( mask );
3490
3491         has_wild = ms_has_wild(mask);
3492
3493         if (!has_wild) {
3494                 /*
3495                  * No wildcards - just process the one file.
3496                  */
3497                 BOOL is_short_name = mangle_is_8_3(name, True);
3498
3499                 /* Add a terminating '/' to the directory name. */
3500                 pstrcat(directory,"/");
3501                 pstrcat(directory,mask);
3502                 
3503                 /* Ensure newname contains a '/' also */
3504                 if(strrchr_m(newname,'/') == 0) {
3505                         pstring tmpstr;
3506                         
3507                         pstrcpy(tmpstr, "./");
3508                         pstrcat(tmpstr, newname);
3509                         pstrcpy(newname, tmpstr);
3510                 }
3511                 
3512                 DEBUG(3,("rename_internals: case_sensitive = %d, case_preserve = %d, short case preserve = %d, \
3513 directory = %s, newname = %s, newname_last_component = %s, is_8_3 = %d\n", 
3514                          case_sensitive, case_preserve, short_case_preserve, directory, 
3515                          newname, newname_last_component, is_short_name));
3516
3517                 /*
3518                  * Check for special case with case preserving and not
3519                  * case sensitive, if directory and newname are identical,
3520                  * and the old last component differs from the original
3521                  * last component only by case, then we should allow
3522                  * the rename (user is trying to change the case of the
3523                  * filename).
3524                  */
3525                 if((case_sensitive == False) && 
3526                    (((case_preserve == True) && 
3527                      (is_short_name == False)) || 
3528                     ((short_case_preserve == True) && 
3529                      (is_short_name == True))) &&
3530                    strcsequal(directory, newname)) {
3531                         pstring newname_modified_last_component;
3532
3533                         /*
3534                          * Get the last component of the modified name.
3535                          * Note that we guarantee that newname contains a '/'
3536                          * character above.
3537                          */
3538                         p = strrchr_m(newname,'/');
3539                         pstrcpy(newname_modified_last_component,p+1);
3540                         
3541                         if(strcsequal(newname_modified_last_component, 
3542                                       newname_last_component) == False) {
3543                                 /*
3544                                  * Replace the modified last component with
3545                                  * the original.
3546                                  */
3547                                 pstrcpy(p+1, newname_last_component);
3548                         }
3549                 }
3550         
3551                 resolve_wildcards(directory,newname);
3552         
3553                 /*
3554                  * The source object must exist.
3555                  */
3556
3557                 if (!vfs_object_exist(conn, directory, &sbuf1)) {
3558                         DEBUG(3,("rename_internals: source doesn't exist doing rename %s -> %s\n",
3559                                 directory,newname));
3560
3561                         if (errno == ENOTDIR || errno == EISDIR || errno == ENOENT) {
3562                                 /*
3563                                  * Must return different errors depending on whether the parent
3564                                  * directory existed or not.
3565                                  */
3566
3567                                 p = strrchr_m(directory, '/');
3568                                 if (!p)
3569                                         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3570                                 *p = '\0';
3571                                 if (vfs_object_exist(conn, directory, NULL))
3572                                         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3573                                 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3574                         }
3575                         error = map_nt_error_from_unix(errno);
3576                         DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3577                                 nt_errstr(error), directory,newname));
3578
3579                         return error;
3580                 }
3581
3582                 error = can_rename(directory,conn,&sbuf1);
3583
3584                 if (!NT_STATUS_IS_OK(error)) {
3585                         DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3586                                 nt_errstr(error), directory,newname));
3587                         return error;
3588                 }
3589
3590                 /*
3591                  * If the src and dest names are identical - including case,
3592                  * don't do the rename, just return success.
3593                  */
3594
3595                 if (strcsequal(directory, newname)) {
3596                         rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
3597                         DEBUG(3,("rename_internals: identical names in rename %s - returning success\n", directory));
3598                         return NT_STATUS_OK;
3599                 }
3600
3601                 if(!replace_if_exists && vfs_object_exist(conn,newname,NULL)) {
3602                         DEBUG(3,("rename_internals: dest exists doing rename %s -> %s\n",
3603                                 directory,newname));
3604                         return NT_STATUS_OBJECT_NAME_COLLISION;
3605                 }
3606
3607                 if(SMB_VFS_RENAME(conn,directory, newname) == 0) {
3608                         DEBUG(3,("rename_internals: succeeded doing rename on %s -> %s\n",
3609                                 directory,newname));
3610                         rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
3611                         return NT_STATUS_OK;    
3612                 }
3613
3614                 if (errno == ENOTDIR || errno == EISDIR)
3615                         error = NT_STATUS_OBJECT_NAME_COLLISION;
3616                 else
3617                         error = map_nt_error_from_unix(errno);
3618                 
3619                 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3620                         nt_errstr(error), directory,newname));
3621
3622                 return error;
3623         } else {
3624                 /*
3625                  * Wildcards - process each file that matches.
3626                  */
3627                 void *dirptr = NULL;
3628                 const char *dname;
3629                 pstring destname;
3630                 
3631                 if (check_name(directory,conn))
3632                         dirptr = OpenDir(conn, directory, True);
3633                 
3634                 if (dirptr) {
3635                         error = NT_STATUS_OBJECT_NAME_NOT_FOUND;
3636                         
3637                         if (strequal(mask,"????????.???"))
3638                                 pstrcpy(mask,"*");
3639                         
3640                         while ((dname = ReadDirName(dirptr))) {
3641                                 pstring fname;
3642
3643                                 pstrcpy(fname,dname);
3644                                 
3645                                 if(!mask_match(fname, mask, case_sensitive))
3646                                         continue;
3647                                 
3648                                 error = NT_STATUS_ACCESS_DENIED;
3649                                 slprintf(fname,sizeof(fname)-1,"%s/%s",directory,dname);
3650                                 if (!vfs_object_exist(conn, fname, &sbuf1)) {
3651                                         error = NT_STATUS_OBJECT_NAME_NOT_FOUND;
3652                                         DEBUG(6,("rename %s failed. Error %s\n", fname, nt_errstr(error)));
3653                                         continue;
3654                                 }
3655                                 error = can_rename(fname,conn,&sbuf1);
3656                                 if (!NT_STATUS_IS_OK(error)) {
3657                                         DEBUG(6,("rename %s refused\n", fname));
3658                                         continue;
3659                                 }
3660                                 pstrcpy(destname,newname);
3661                                 
3662                                 if (!resolve_wildcards(fname,destname)) {
3663                                         DEBUG(6,("resolve_wildcards %s %s failed\n", 
3664                                                  fname, destname));
3665                                         continue;
3666                                 }
3667                                 
3668                                 if (!replace_if_exists && 
3669                                     vfs_file_exist(conn,destname, NULL)) {
3670                                         DEBUG(6,("file_exist %s\n", destname));
3671                                         error = NT_STATUS_OBJECT_NAME_COLLISION;
3672                                         continue;
3673                                 }
3674                                 
3675                                 if (!SMB_VFS_RENAME(conn,fname,destname)) {
3676                                         rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
3677                                         count++;
3678                                 }
3679                                 DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname));
3680                         }
3681                         CloseDir(dirptr);
3682                 }
3683         }
3684         
3685         if (count == 0 && NT_STATUS_IS_OK(error)) {
3686                 error = map_nt_error_from_unix(errno);
3687         }
3688         
3689         return error;
3690 }
3691
3692 /****************************************************************************
3693  Reply to a mv.
3694 ****************************************************************************/
3695
3696 int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, 
3697              int dum_buffsize)
3698 {
3699         int outsize = 0;
3700         pstring name;
3701         pstring newname;
3702         char *p;
3703         NTSTATUS status;
3704
3705         START_PROFILE(SMBmv);
3706
3707         p = smb_buf(inbuf) + 1;
3708         p += srvstr_get_path(inbuf, name, p, sizeof(name), STR_TERMINATE,&status);
3709         if (!NT_STATUS_IS_OK(status)) {
3710                 END_PROFILE(SMBmv);
3711                 return ERROR_NT(status);
3712         }
3713         p++;
3714         p += srvstr_get_path(inbuf, newname, p, sizeof(newname), STR_TERMINATE,&status);
3715         if (!NT_STATUS_IS_OK(status)) {
3716                 END_PROFILE(SMBmv);
3717                 return ERROR_NT(status);
3718         }
3719         
3720         RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
3721         RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
3722         
3723         DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
3724         
3725         status = rename_internals(conn, name, newname, False);
3726         if (!NT_STATUS_IS_OK(status)) {
3727                 END_PROFILE(SMBmv);
3728                 return ERROR_NT(status);
3729         }
3730
3731         /*
3732          * Win2k needs a changenotify request response before it will
3733          * update after a rename..
3734          */     
3735         process_pending_change_notify_queue((time_t)0);
3736         outsize = set_message(outbuf,0,0,True);
3737   
3738         END_PROFILE(SMBmv);
3739         return(outsize);
3740 }
3741
3742 /*******************************************************************
3743  Copy a file as part of a reply_copy.
3744 ******************************************************************/
3745
3746 static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
3747                       int count,BOOL target_is_directory, int *err_ret)
3748 {
3749         int Access,action;
3750         SMB_STRUCT_STAT src_sbuf, sbuf2;
3751         SMB_OFF_T ret=-1;
3752         files_struct *fsp1,*fsp2;
3753         pstring dest;
3754   
3755         *err_ret = 0;
3756
3757         pstrcpy(dest,dest1);
3758         if (target_is_directory) {
3759                 char *p = strrchr_m(src,'/');
3760                 if (p) 
3761                         p++;
3762                 else
3763                         p = src;
3764                 pstrcat(dest,"/");
3765                 pstrcat(dest,p);
3766         }
3767
3768         if (!vfs_file_exist(conn,src,&src_sbuf))
3769                 return(False);
3770
3771         fsp1 = open_file_shared(conn,src,&src_sbuf,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
3772                                         (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),0,0,&Access,&action);
3773
3774         if (!fsp1)
3775                 return(False);
3776
3777         if (!target_is_directory && count)
3778                 ofun = FILE_EXISTS_OPEN;
3779
3780         if (SMB_VFS_STAT(conn,dest,&sbuf2) == -1)
3781                 ZERO_STRUCTP(&sbuf2);
3782
3783         fsp2 = open_file_shared(conn,dest,&sbuf2,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_WRONLY),
3784                         ofun,src_sbuf.st_mode,0,&Access,&action);
3785
3786         if (!fsp2) {
3787                 close_file(fsp1,False);
3788                 return(False);
3789         }
3790
3791         if ((ofun&3) == 1) {
3792                 if(SMB_VFS_LSEEK(fsp2,fsp2->fd,0,SEEK_END) == -1) {
3793                         DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
3794                         /*
3795                          * Stop the copy from occurring.
3796                          */
3797                         ret = -1;
3798                         src_sbuf.st_size = 0;
3799                 }
3800         }
3801   
3802         if (src_sbuf.st_size)
3803                 ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_size);
3804
3805         close_file(fsp1,False);
3806
3807         /* Ensure the modtime is set correctly on the destination file. */
3808         fsp2->pending_modtime = src_sbuf.st_mtime;
3809
3810         /*
3811          * As we are opening fsp1 read-only we only expect
3812          * an error on close on fsp2 if we are out of space.
3813          * Thus we don't look at the error return from the
3814          * close of fsp1.
3815          */
3816         *err_ret = close_file(fsp2,False);
3817
3818         return(ret == (SMB_OFF_T)src_sbuf.st_size);
3819 }
3820
3821 /****************************************************************************
3822  Reply to a file copy.
3823 ****************************************************************************/
3824
3825 int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3826 {
3827         int outsize = 0;
3828         pstring name;
3829         pstring directory;
3830         pstring mask,newname;
3831         char *p;
3832         int count=0;
3833         int error = ERRnoaccess;
3834         int err = 0;
3835         BOOL has_wild;
3836         BOOL exists=False;
3837         int tid2 = SVAL(inbuf,smb_vwv0);
3838         int ofun = SVAL(inbuf,smb_vwv1);
3839         int flags = SVAL(inbuf,smb_vwv2);
3840         BOOL target_is_directory=False;
3841         BOOL bad_path1 = False;
3842         BOOL bad_path2 = False;
3843         BOOL rc = True;
3844         SMB_STRUCT_STAT sbuf1, sbuf2;
3845         NTSTATUS status;
3846
3847         START_PROFILE(SMBcopy);
3848
3849         *directory = *mask = 0;
3850
3851         p = smb_buf(inbuf);
3852         p += srvstr_get_path(inbuf, name, p, sizeof(name), STR_TERMINATE,&status);
3853         if (!NT_STATUS_IS_OK(status)) {
3854                 END_PROFILE(SMBcopy);
3855                 return ERROR_NT(status);
3856         }
3857         p += srvstr_get_path(inbuf, newname, p, sizeof(newname), STR_TERMINATE,&status);
3858         if (!NT_STATUS_IS_OK(status)) {
3859                 END_PROFILE(SMBcopy);
3860                 return ERROR_NT(status);
3861         }
3862    
3863         DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
3864    
3865         if (tid2 != conn->cnum) {
3866                 /* can't currently handle inter share copies XXXX */
3867                 DEBUG(3,("Rejecting inter-share copy\n"));
3868                 END_PROFILE(SMBcopy);
3869                 return ERROR_DOS(ERRSRV,ERRinvdevice);
3870         }
3871
3872         RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
3873         RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
3874
3875         rc = unix_convert(name,conn,0,&bad_path1,&sbuf1);
3876         unix_convert(newname,conn,0,&bad_path2,&sbuf2);
3877
3878         target_is_directory = VALID_STAT_OF_DIR(sbuf2);
3879
3880         if ((flags&1) && target_is_directory) {
3881                 END_PROFILE(SMBcopy);
3882                 return ERROR_DOS(ERRDOS,ERRbadfile);
3883         }
3884
3885         if ((flags&2) && !target_is_directory) {
3886                 END_PROFILE(SMBcopy);
3887                 return ERROR_DOS(ERRDOS,ERRbadpath);
3888         }
3889
3890         if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) {
3891                 /* wants a tree copy! XXXX */
3892                 DEBUG(3,("Rejecting tree copy\n"));
3893                 END_PROFILE(SMBcopy);
3894                 return ERROR_DOS(ERRSRV,ERRerror);
3895         }
3896
3897         p = strrchr_m(name,'/');
3898         if (!p) {
3899                 pstrcpy(directory,"./");
3900                 pstrcpy(mask,name);
3901         } else {
3902                 *p = 0;
3903                 pstrcpy(directory,name);
3904                 pstrcpy(mask,p+1);
3905         }
3906
3907         /*
3908          * We should only check the mangled cache
3909          * here if unix_convert failed. This means
3910          * that the path in 'mask' doesn't exist
3911          * on the file system and so we need to look
3912          * for a possible mangle. This patch from
3913          * Tine Smukavec <valentin.smukavec@hermes.si>.
3914          */
3915
3916         if (!rc && mangle_is_mangled(mask))
3917                 mangle_check_cache( mask );
3918
3919         has_wild = ms_has_wild(mask);
3920
3921         if (!has_wild) {
3922                 pstrcat(directory,"/");
3923                 pstrcat(directory,mask);
3924                 if (resolve_wildcards(directory,newname) &&
3925                                 copy_file(directory,newname,conn,ofun, count,target_is_directory,&err))
3926                         count++;
3927                 if(!count && err) {
3928                         errno = err;
3929                         END_PROFILE(SMBcopy);
3930                         return(UNIXERROR(ERRHRD,ERRgeneral));
3931                 }
3932                 if (!count) {
3933                         exists = vfs_file_exist(conn,directory,NULL);
3934                 }
3935         } else {
3936                 void *dirptr = NULL;
3937                 const char *dname;
3938                 pstring destname;
3939
3940                 if (check_name(directory,conn))
3941                         dirptr = OpenDir(conn, directory, True);
3942
3943                 if (dirptr) {
3944                         error = ERRbadfile;
3945
3946                         if (strequal(mask,"????????.???"))
3947                                 pstrcpy(mask,"*");
3948
3949                         while ((dname = ReadDirName(dirptr))) {
3950                                 pstring fname;
3951                                 pstrcpy(fname,dname);
3952     
3953                                 if(!mask_match(fname, mask, case_sensitive))
3954                                         continue;
3955
3956                                 error = ERRnoaccess;
3957                                 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
3958                                 pstrcpy(destname,newname);
3959                                 if (resolve_wildcards(fname,destname) && 
3960                                                 copy_file(fname,destname,conn,ofun,
3961                                                 count,target_is_directory,&err))
3962                                         count++;
3963                                 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
3964                         }
3965                         CloseDir(dirptr);
3966                 }
3967         }
3968   
3969         if (count == 0) {
3970                 if(err) {
3971                         /* Error on close... */
3972                         errno = err;
3973                         END_PROFILE(SMBcopy);
3974                         return(UNIXERROR(ERRHRD,ERRgeneral));
3975                 }
3976
3977                 if (exists) {
3978                         END_PROFILE(SMBcopy);
3979                         return ERROR_DOS(ERRDOS,error);
3980                 } else {
3981                         if((errno == ENOENT) && (bad_path1 || bad_path2)) {
3982                                 unix_ERR_class = ERRDOS;
3983                                 unix_ERR_code = ERRbadpath;
3984                         }
3985                         END_PROFILE(SMBcopy);
3986                         return(UNIXERROR(ERRDOS,error));
3987                 }
3988         }
3989   
3990         outsize = set_message(outbuf,1,0,True);
3991         SSVAL(outbuf,smb_vwv0,count);
3992
3993         END_PROFILE(SMBcopy);
3994         return(outsize);
3995 }
3996
3997 /****************************************************************************
3998  Reply to a setdir.
3999 ****************************************************************************/
4000
4001 int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4002 {
4003         int snum;
4004         int outsize = 0;
4005         BOOL ok = False;
4006         pstring newdir;
4007         NTSTATUS status;
4008
4009         START_PROFILE(pathworks_setdir);
4010   
4011         snum = SNUM(conn);
4012         if (!CAN_SETDIR(snum)) {
4013                 END_PROFILE(pathworks_setdir);
4014                 return ERROR_DOS(ERRDOS,ERRnoaccess);
4015         }
4016
4017         srvstr_get_path(inbuf, newdir, smb_buf(inbuf) + 1, sizeof(newdir), STR_TERMINATE,&status);
4018         if (!NT_STATUS_IS_OK(status)) {
4019                 END_PROFILE(pathworks_setdir);
4020                 return ERROR_NT(status);
4021         }
4022   
4023         if (strlen(newdir) == 0) {
4024                 ok = True;
4025         } else {
4026                 ok = vfs_directory_exist(conn,newdir,NULL);
4027                 if (ok)
4028                         string_set(&conn->connectpath,newdir);
4029         }
4030   
4031         if (!ok) {
4032                 END_PROFILE(pathworks_setdir);
4033                 return ERROR_DOS(ERRDOS,ERRbadpath);
4034         }
4035   
4036         outsize = set_message(outbuf,0,0,True);
4037         SCVAL(outbuf,smb_reh,CVAL(inbuf,smb_reh));
4038   
4039         DEBUG(3,("setdir %s\n", newdir));
4040
4041         END_PROFILE(pathworks_setdir);
4042         return(outsize);
4043 }
4044
4045 /****************************************************************************
4046  Get a lock pid, dealing with large count requests.
4047 ****************************************************************************/
4048
4049 uint16 get_lock_pid( char *data, int data_offset, BOOL large_file_format)
4050 {
4051         if(!large_file_format)
4052                 return SVAL(data,SMB_LPID_OFFSET(data_offset));
4053         else
4054                 return SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
4055 }
4056
4057 /****************************************************************************
4058  Get a lock count, dealing with large count requests.
4059 ****************************************************************************/
4060
4061 SMB_BIG_UINT get_lock_count( char *data, int data_offset, BOOL large_file_format)
4062 {
4063         SMB_BIG_UINT count = 0;
4064
4065         if(!large_file_format) {
4066                 count = (SMB_BIG_UINT)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
4067         } else {
4068
4069 #if defined(HAVE_LONGLONG)
4070                 count = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
4071                         ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
4072 #else /* HAVE_LONGLONG */
4073
4074                 /*
4075                  * NT4.x seems to be broken in that it sends large file (64 bit)
4076                  * lockingX calls even if the CAP_LARGE_FILES was *not*
4077                  * negotiated. For boxes without large unsigned ints truncate the
4078                  * lock count by dropping the top 32 bits.
4079                  */
4080
4081                 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
4082                         DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
4083                                 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
4084                                 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
4085                                 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
4086                 }
4087
4088                 count = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
4089 #endif /* HAVE_LONGLONG */
4090         }
4091
4092         return count;
4093 }
4094
4095 #if !defined(HAVE_LONGLONG)
4096 /****************************************************************************
4097  Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
4098 ****************************************************************************/
4099
4100 static uint32 map_lock_offset(uint32 high, uint32 low)
4101 {
4102         unsigned int i;
4103         uint32 mask = 0;
4104         uint32 highcopy = high;
4105  
4106         /*
4107          * Try and find out how many significant bits there are in high.
4108          */
4109  
4110         for(i = 0; highcopy; i++)
4111                 highcopy >>= 1;
4112  
4113         /*
4114          * We use 31 bits not 32 here as POSIX
4115          * lock offsets may not be negative.
4116          */
4117  
4118         mask = (~0) << (31 - i);
4119  
4120         if(low & mask)
4121                 return 0; /* Fail. */
4122  
4123         high <<= (31 - i);
4124  
4125         return (high|low);
4126 }
4127 #endif /* !defined(HAVE_LONGLONG) */
4128
4129 /****************************************************************************
4130  Get a lock offset, dealing with large offset requests.
4131 ****************************************************************************/
4132
4133 SMB_BIG_UINT get_lock_offset( char *data, int data_offset, BOOL large_file_format, BOOL *err)
4134 {
4135         SMB_BIG_UINT offset = 0;
4136
4137         *err = False;
4138
4139         if(!large_file_format) {
4140                 offset = (SMB_BIG_UINT)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
4141         } else {
4142
4143 #if defined(HAVE_LONGLONG)
4144                 offset = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
4145                                 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
4146 #else /* HAVE_LONGLONG */
4147
4148                 /*
4149                  * NT4.x seems to be broken in that it sends large file (64 bit)
4150                  * lockingX calls even if the CAP_LARGE_FILES was *not*
4151                  * negotiated. For boxes without large unsigned ints mangle the
4152                  * lock offset by mapping the top 32 bits onto the lower 32.
4153                  */
4154       
4155                 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
4156                         uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
4157                         uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
4158                         uint32 new_low = 0;
4159
4160                         if((new_low = map_lock_offset(high, low)) == 0) {
4161                                 *err = True;
4162                                 return (SMB_BIG_UINT)-1;
4163                         }
4164
4165                         DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
4166                                 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
4167                         SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
4168                         SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
4169                 }
4170
4171                 offset = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
4172 #endif /* HAVE_LONGLONG */
4173         }
4174
4175         return offset;
4176 }
4177
4178 /****************************************************************************
4179  Reply to a lockingX request.
4180 ****************************************************************************/
4181
4182 int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
4183 {
4184         files_struct *fsp = file_fsp(inbuf,smb_vwv2);
4185         unsigned char locktype = CVAL(inbuf,smb_vwv3);
4186         unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
4187         uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
4188         uint16 num_locks = SVAL(inbuf,smb_vwv7);
4189         SMB_BIG_UINT count = 0, offset = 0;
4190         uint16 lock_pid;
4191         int32 lock_timeout = IVAL(inbuf,smb_vwv4);
4192         int i;
4193         char *data;
4194         BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
4195         BOOL err;
4196         BOOL my_lock_ctx = False;
4197         NTSTATUS status;
4198
4199         START_PROFILE(SMBlockingX);
4200         
4201         CHECK_FSP(fsp,conn);
4202         
4203         data = smb_buf(inbuf);
4204
4205         if (locktype & (LOCKING_ANDX_CANCEL_LOCK | LOCKING_ANDX_CHANGE_LOCKTYPE)) {
4206                 /* we don't support these - and CANCEL_LOCK makes w2k
4207                    and XP reboot so I don't really want to be
4208                    compatible! (tridge) */
4209                 return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
4210         }
4211         
4212         /* Check if this is an oplock break on a file
4213            we have granted an oplock on.
4214         */
4215         if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
4216                 /* Client can insist on breaking to none. */
4217                 BOOL break_to_none = (oplocklevel == 0);
4218                 
4219                 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client for fnum = %d\n",
4220                          (unsigned int)oplocklevel, fsp->fnum ));
4221
4222                 /*
4223                  * Make sure we have granted an exclusive or batch oplock on this file.
4224                  */
4225                 
4226                 if(!EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
4227                         DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \
4228 no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name));
4229
4230                         /* if this is a pure oplock break request then don't send a reply */
4231                         if (num_locks == 0 && num_ulocks == 0) {
4232                                 END_PROFILE(SMBlockingX);
4233                                 return -1;
4234                         } else {
4235                                 END_PROFILE(SMBlockingX);
4236                                 return ERROR_DOS(ERRDOS,ERRlock);
4237                         }
4238                 }
4239
4240                 if (remove_oplock(fsp, break_to_none) == False) {
4241                         DEBUG(0,("reply_lockingX: error in removing oplock on file %s\n",
4242                                  fsp->fsp_name ));
4243                 }
4244                 
4245                 /* if this is a pure oplock break request then don't send a reply */
4246                 if (num_locks == 0 && num_ulocks == 0) {
4247                         /* Sanity check - ensure a pure oplock break is not a
4248                            chained request. */
4249                         if(CVAL(inbuf,smb_vwv0) != 0xff)
4250                                 DEBUG(0,("reply_lockingX: Error : pure oplock break is a chained %d request !\n",
4251                                          (unsigned int)CVAL(inbuf,smb_vwv0) ));
4252                         END_PROFILE(SMBlockingX);
4253                         return -1;
4254                 }
4255         }
4256
4257         /*
4258          * We do this check *after* we have checked this is not a oplock break
4259          * response message. JRA.
4260          */
4261         
4262         release_level_2_oplocks_on_change(fsp);
4263         
4264         /* Data now points at the beginning of the list
4265            of smb_unlkrng structs */
4266         for(i = 0; i < (int)num_ulocks; i++) {
4267                 lock_pid = get_lock_pid( data, i, large_file_format);
4268                 count = get_lock_count( data, i, large_file_format);
4269                 offset = get_lock_offset( data, i, large_file_format, &err);
4270                 
4271                 /*
4272                  * There is no error code marked "stupid client bug".... :-).
4273                  */
4274                 if(err) {
4275                         END_PROFILE(SMBlockingX);
4276                         return ERROR_DOS(ERRDOS,ERRnoaccess);
4277                 }
4278
4279                 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for pid %u, file %s\n",
4280                           (double)offset, (double)count, (unsigned int)lock_pid, fsp->fsp_name ));
4281                 
4282                 status = do_unlock(fsp,conn,lock_pid,count,offset);
4283                 if (NT_STATUS_V(status)) {
4284                         END_PROFILE(SMBlockingX);
4285                         return ERROR_NT(status);
4286                 }
4287         }
4288
4289         /* Setup the timeout in seconds. */
4290
4291         lock_timeout = ((lock_timeout == -1) ? -1 : (lock_timeout+999)/1000);
4292         
4293         /* Now do any requested locks */
4294         data += ((large_file_format ? 20 : 10)*num_ulocks);
4295         
4296         /* Data now points at the beginning of the list
4297            of smb_lkrng structs */
4298         
4299         for(i = 0; i < (int)num_locks; i++) {
4300                 lock_pid = get_lock_pid( data, i, large_file_format);
4301                 count = get_lock_count( data, i, large_file_format);
4302                 offset = get_lock_offset( data, i, large_file_format, &err);
4303                 
4304                 /*
4305                  * There is no error code marked "stupid client bug".... :-).
4306                  */
4307                 if(err) {
4308                         END_PROFILE(SMBlockingX);
4309                         return ERROR_DOS(ERRDOS,ERRnoaccess);
4310                 }
4311                 
4312                 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid %u, file %s timeout = %d\n",
4313                         (double)offset, (double)count, (unsigned int)lock_pid,
4314                         fsp->fsp_name, (int)lock_timeout ));
4315                 
4316                 status = do_lock_spin(fsp,conn,lock_pid, count,offset, 
4317                                  ((locktype & 1) ? READ_LOCK : WRITE_LOCK), &my_lock_ctx);
4318                 if (NT_STATUS_V(status)) {
4319                         if ((lock_timeout != 0) && lp_blocking_locks(SNUM(conn)) && !my_lock_ctx && ERROR_WAS_LOCK_DENIED(status)) {
4320                                 /*
4321                                  * A blocking lock was requested. Package up
4322                                  * this smb into a queued request and push it
4323                                  * onto the blocking lock queue.
4324                                  */
4325                                 if(push_blocking_lock_request(inbuf, length, lock_timeout, i, lock_pid, offset, count)) {
4326                                         END_PROFILE(SMBlockingX);
4327                                         return -1;
4328                                 }
4329                         }
4330                         break;
4331                 }
4332         }
4333         
4334         /* If any of the above locks failed, then we must unlock
4335            all of the previous locks (X/Open spec). */
4336         if (i != num_locks && num_locks != 0) {
4337                 /*
4338                  * Ensure we don't do a remove on the lock that just failed,
4339                  * as under POSIX rules, if we have a lock already there, we
4340                  * will delete it (and we shouldn't) .....
4341                  */
4342                 for(i--; i >= 0; i--) {
4343                         lock_pid = get_lock_pid( data, i, large_file_format);
4344                         count = get_lock_count( data, i, large_file_format);
4345                         offset = get_lock_offset( data, i, large_file_format, &err);
4346                         
4347                         /*
4348                          * There is no error code marked "stupid client bug".... :-).
4349                          */
4350                         if(err) {
4351                                 END_PROFILE(SMBlockingX);
4352                                 return ERROR_DOS(ERRDOS,ERRnoaccess);
4353                         }
4354                         
4355                         do_unlock(fsp,conn,lock_pid,count,offset);
4356                 }
4357                 END_PROFILE(SMBlockingX);
4358                 return ERROR_NT(status);
4359         }
4360
4361         set_message(outbuf,2,0,True);
4362         
4363         DEBUG( 3, ( "lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
4364                     fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks ) );
4365         
4366         END_PROFILE(SMBlockingX);
4367         return chain_reply(inbuf,outbuf,length,bufsize);
4368 }
4369
4370 /****************************************************************************
4371  Reply to a SMBreadbmpx (read block multiplex) request.
4372 ****************************************************************************/
4373
4374 int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
4375 {
4376         ssize_t nread = -1;
4377         ssize_t total_read;
4378         char *data;
4379         SMB_OFF_T startpos;
4380         int outsize;
4381         size_t maxcount;
4382         int max_per_packet;
4383         size_t tcount;
4384         int pad;
4385         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4386         START_PROFILE(SMBreadBmpx);
4387
4388         /* this function doesn't seem to work - disable by default */
4389         if (!lp_readbmpx()) {
4390                 END_PROFILE(SMBreadBmpx);
4391                 return ERROR_DOS(ERRSRV,ERRuseSTD);
4392         }
4393
4394         outsize = set_message(outbuf,8,0,True);
4395
4396         CHECK_FSP(fsp,conn);
4397         CHECK_READ(fsp);
4398
4399         startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
4400         maxcount = SVAL(inbuf,smb_vwv3);
4401
4402         data = smb_buf(outbuf);
4403         pad = ((long)data)%4;
4404         if (pad)
4405                 pad = 4 - pad;
4406         data += pad;
4407
4408         max_per_packet = bufsize-(outsize+pad);
4409         tcount = maxcount;
4410         total_read = 0;
4411
4412         if (is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
4413                 END_PROFILE(SMBreadBmpx);
4414                 return ERROR_DOS(ERRDOS,ERRlock);
4415         }
4416
4417         do {
4418                 size_t N = MIN(max_per_packet,tcount-total_read);
4419   
4420                 nread = read_file(fsp,data,startpos,N);
4421
4422                 if (nread <= 0)
4423                         nread = 0;
4424
4425                 if (nread < (ssize_t)N)
4426                         tcount = total_read + nread;
4427
4428                 set_message(outbuf,8,nread,False);
4429                 SIVAL(outbuf,smb_vwv0,startpos);
4430                 SSVAL(outbuf,smb_vwv2,tcount);
4431                 SSVAL(outbuf,smb_vwv6,nread);
4432                 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
4433
4434                 if (!send_smb(smbd_server_fd(),outbuf))
4435                         exit_server("reply_readbmpx: send_smb failed.");
4436
4437                 total_read += nread;
4438                 startpos += nread;
4439         } while (total_read < (ssize_t)tcount);
4440
4441         END_PROFILE(SMBreadBmpx);
4442         return(-1);
4443 }
4444
4445 /****************************************************************************
4446  Reply to a SMBsetattrE.
4447 ****************************************************************************/
4448
4449 int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4450 {
4451         struct utimbuf unix_times;
4452         int outsize = 0;
4453         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4454         START_PROFILE(SMBsetattrE);
4455
4456         outsize = set_message(outbuf,0,0,True);
4457
4458         if(!fsp || (fsp->conn != conn)) {
4459                 END_PROFILE(SMBgetattrE);
4460                 return ERROR_DOS(ERRDOS,ERRbadfid);
4461         }
4462
4463         /*
4464          * Convert the DOS times into unix times. Ignore create
4465          * time as UNIX can't set this.
4466          */
4467
4468         unix_times.actime = make_unix_date2(inbuf+smb_vwv3);
4469         unix_times.modtime = make_unix_date2(inbuf+smb_vwv5);
4470   
4471         /* 
4472          * Patch from Ray Frush <frush@engr.colostate.edu>
4473          * Sometimes times are sent as zero - ignore them.
4474          */
4475
4476         if ((unix_times.actime == 0) && (unix_times.modtime == 0)) {
4477                 /* Ignore request */
4478                 if( DEBUGLVL( 3 ) ) {
4479                         dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
4480                         dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
4481                 }
4482                 END_PROFILE(SMBsetattrE);
4483                 return(outsize);
4484         } else if ((unix_times.actime != 0) && (unix_times.modtime == 0)) {
4485                 /* set modify time = to access time if modify time was 0 */
4486                 unix_times.modtime = unix_times.actime;
4487         }
4488
4489         /* Set the date on this file */
4490         if(file_utime(conn, fsp->fsp_name, &unix_times)) {
4491                 END_PROFILE(SMBsetattrE);
4492                 return ERROR_DOS(ERRDOS,ERRnoaccess);
4493         }
4494   
4495         DEBUG( 3, ( "reply_setattrE fnum=%d actime=%d modtime=%d\n",
4496                 fsp->fnum, (int)unix_times.actime, (int)unix_times.modtime ) );
4497
4498         END_PROFILE(SMBsetattrE);
4499         return(outsize);
4500 }
4501
4502
4503 /* Back from the dead for OS/2..... JRA. */
4504
4505 /****************************************************************************
4506  Reply to a SMBwritebmpx (write block multiplex primary) request.
4507 ****************************************************************************/
4508
4509 int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4510 {
4511         size_t numtowrite;
4512         ssize_t nwritten = -1;
4513         int outsize = 0;
4514         SMB_OFF_T startpos;
4515         size_t tcount;
4516         BOOL write_through;
4517         int smb_doff;
4518         char *data;
4519         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4520         START_PROFILE(SMBwriteBmpx);
4521
4522         CHECK_FSP(fsp,conn);
4523         CHECK_WRITE(fsp);
4524         CHECK_ERROR(fsp);
4525
4526         tcount = SVAL(inbuf,smb_vwv1);
4527         startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
4528         write_through = BITSETW(inbuf+smb_vwv7,0);
4529         numtowrite = SVAL(inbuf,smb_vwv10);
4530         smb_doff = SVAL(inbuf,smb_vwv11);
4531
4532         data = smb_base(inbuf) + smb_doff;
4533
4534         /* If this fails we need to send an SMBwriteC response,
4535                 not an SMBwritebmpx - set this up now so we don't forget */
4536         SCVAL(outbuf,smb_com,SMBwritec);
4537
4538         if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos,WRITE_LOCK,False)) {
4539                 END_PROFILE(SMBwriteBmpx);
4540                 return(ERROR_DOS(ERRDOS,ERRlock));
4541         }
4542
4543         nwritten = write_file(fsp,data,startpos,numtowrite);
4544
4545         if(lp_syncalways(SNUM(conn)) || write_through)
4546                 sync_file(conn,fsp);
4547   
4548         if(nwritten < (ssize_t)numtowrite) {
4549                 END_PROFILE(SMBwriteBmpx);
4550                 return(UNIXERROR(ERRHRD,ERRdiskfull));
4551         }
4552
4553         /* If the maximum to be written to this file
4554                 is greater than what we just wrote then set
4555                 up a secondary struct to be attached to this
4556                 fd, we will use this to cache error messages etc. */
4557
4558         if((ssize_t)tcount > nwritten) {
4559                 write_bmpx_struct *wbms;
4560                 if(fsp->wbmpx_ptr != NULL)
4561                         wbms = fsp->wbmpx_ptr; /* Use an existing struct */
4562                 else
4563                         wbms = (write_bmpx_struct *)malloc(sizeof(write_bmpx_struct));
4564                 if(!wbms) {
4565                         DEBUG(0,("Out of memory in reply_readmpx\n"));
4566                         END_PROFILE(SMBwriteBmpx);
4567                         return(ERROR_DOS(ERRSRV,ERRnoresource));
4568                 }
4569                 wbms->wr_mode = write_through;
4570                 wbms->wr_discard = False; /* No errors yet */
4571                 wbms->wr_total_written = nwritten;
4572                 wbms->wr_errclass = 0;
4573                 wbms->wr_error = 0;
4574                 fsp->wbmpx_ptr = wbms;
4575         }
4576
4577         /* We are returning successfully, set the message type back to
4578                 SMBwritebmpx */
4579         SCVAL(outbuf,smb_com,SMBwriteBmpx);
4580   
4581         outsize = set_message(outbuf,1,0,True);
4582   
4583         SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
4584   
4585         DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
4586                         fsp->fnum, (int)numtowrite, (int)nwritten ) );
4587
4588         if (write_through && tcount==nwritten) {
4589                 /* We need to send both a primary and a secondary response */
4590                 smb_setlen(outbuf,outsize - 4);
4591                 if (!send_smb(smbd_server_fd(),outbuf))
4592                         exit_server("reply_writebmpx: send_smb failed.");
4593
4594                 /* Now the secondary */
4595                 outsize = set_message(outbuf,1,0,True);
4596                 SCVAL(outbuf,smb_com,SMBwritec);
4597                 SSVAL(outbuf,smb_vwv0,nwritten);
4598         }
4599
4600         END_PROFILE(SMBwriteBmpx);
4601         return(outsize);
4602 }
4603
4604 /****************************************************************************
4605  Reply to a SMBwritebs (write block multiplex secondary) request.
4606 ****************************************************************************/
4607
4608 int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4609 {
4610         size_t numtowrite;
4611         ssize_t nwritten = -1;
4612         int outsize = 0;
4613         SMB_OFF_T startpos;
4614         size_t tcount;
4615         BOOL write_through;
4616         int smb_doff;
4617         char *data;
4618         write_bmpx_struct *wbms;
4619         BOOL send_response = False; 
4620         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4621         START_PROFILE(SMBwriteBs);
4622
4623         CHECK_FSP(fsp,conn);
4624         CHECK_WRITE(fsp);
4625
4626         tcount = SVAL(inbuf,smb_vwv1);
4627         startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
4628         numtowrite = SVAL(inbuf,smb_vwv6);
4629         smb_doff = SVAL(inbuf,smb_vwv7);
4630
4631         data = smb_base(inbuf) + smb_doff;
4632
4633         /* We need to send an SMBwriteC response, not an SMBwritebs */
4634         SCVAL(outbuf,smb_com,SMBwritec);
4635
4636         /* This fd should have an auxiliary struct attached,
4637                 check that it does */
4638         wbms = fsp->wbmpx_ptr;
4639         if(!wbms) {
4640                 END_PROFILE(SMBwriteBs);
4641                 return(-1);
4642         }
4643
4644         /* If write through is set we can return errors, else we must cache them */
4645         write_through = wbms->wr_mode;
4646
4647         /* Check for an earlier error */
4648         if(wbms->wr_discard) {
4649                 END_PROFILE(SMBwriteBs);
4650                 return -1; /* Just discard the packet */
4651         }
4652
4653         nwritten = write_file(fsp,data,startpos,numtowrite);
4654
4655         if(lp_syncalways(SNUM(conn)) || write_through)
4656                 sync_file(conn,fsp);
4657   
4658         if (nwritten < (ssize_t)numtowrite) {
4659                 if(write_through) {
4660                         /* We are returning an error - we can delete the aux struct */
4661                         if (wbms)
4662                                 free((char *)wbms);
4663                         fsp->wbmpx_ptr = NULL;
4664                         END_PROFILE(SMBwriteBs);
4665                         return(ERROR_DOS(ERRHRD,ERRdiskfull));
4666                 }
4667                 END_PROFILE(SMBwriteBs);
4668                 return(CACHE_ERROR(wbms,ERRHRD,ERRdiskfull));
4669         }
4670
4671         /* Increment the total written, if this matches tcount
4672                 we can discard the auxiliary struct (hurrah !) and return a writeC */
4673         wbms->wr_total_written += nwritten;
4674         if(wbms->wr_total_written >= tcount) {
4675                 if (write_through) {
4676                         outsize = set_message(outbuf,1,0,True);
4677                         SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);    
4678                         send_response = True;
4679                 }
4680
4681                 free((char *)wbms);
4682                 fsp->wbmpx_ptr = NULL;
4683         }
4684
4685         if(send_response) {
4686                 END_PROFILE(SMBwriteBs);
4687                 return(outsize);
4688         }
4689
4690         END_PROFILE(SMBwriteBs);
4691         return(-1);
4692 }
4693
4694 /****************************************************************************
4695  Reply to a SMBgetattrE.
4696 ****************************************************************************/
4697
4698 int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4699 {
4700         SMB_STRUCT_STAT sbuf;
4701         int outsize = 0;
4702         int mode;
4703         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4704         START_PROFILE(SMBgetattrE);
4705
4706         outsize = set_message(outbuf,11,0,True);
4707
4708         if(!fsp || (fsp->conn != conn)) {
4709                 END_PROFILE(SMBgetattrE);
4710                 return ERROR_DOS(ERRDOS,ERRbadfid);
4711         }
4712
4713         /* Do an fstat on this file */
4714         if(fsp_stat(fsp, &sbuf)) {
4715                 END_PROFILE(SMBgetattrE);
4716                 return(UNIXERROR(ERRDOS,ERRnoaccess));
4717         }
4718   
4719         mode = dos_mode(conn,fsp->fsp_name,&sbuf);
4720   
4721         /*
4722          * Convert the times into dos times. Set create
4723          * date to be last modify date as UNIX doesn't save
4724          * this.
4725          */
4726
4727         put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
4728         put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
4729         put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
4730
4731         if (mode & aDIR) {
4732                 SIVAL(outbuf,smb_vwv6,0);
4733                 SIVAL(outbuf,smb_vwv8,0);
4734         } else {
4735                 uint32 allocation_size = get_allocation_size(fsp, &sbuf);
4736                 SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
4737                 SIVAL(outbuf,smb_vwv8,allocation_size);
4738         }
4739         SSVAL(outbuf,smb_vwv10, mode);
4740   
4741         DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
4742   
4743         END_PROFILE(SMBgetattrE);
4744         return(outsize);
4745 }