Fixes to check for wraps which could cause coredumps.
[tprouty/samba.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                 NTSTATUS nterr = NT_STATUS_OK;
3017                 if(errno == ENOENT) {
3018                         unix_ERR_class = ERRDOS;
3019                         if (bad_path) {
3020                                 unix_ERR_code = ERRbadpath;
3021                                 nterr = NT_STATUS_OBJECT_PATH_NOT_FOUND;
3022                         } else {
3023                                 unix_ERR_code = ERRbadfile;
3024                                 nterr = NT_STATUS_OBJECT_NAME_NOT_FOUND;
3025                         }
3026                 }
3027                 if (!NT_STATUS_IS_OK(nterr))
3028                         return nterr;
3029                 return map_nt_error_from_unix(errno);
3030         }
3031         
3032         return NT_STATUS_OK;
3033 }
3034
3035 /****************************************************************************
3036  Reply to a mkdir.
3037 ****************************************************************************/
3038
3039 int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3040 {
3041         pstring directory;
3042         int outsize;
3043         NTSTATUS status;
3044         START_PROFILE(SMBmkdir);
3045  
3046         srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), STR_TERMINATE,&status);
3047         if (!NT_STATUS_IS_OK(status)) {
3048                 END_PROFILE(SMBmkdir);
3049                 return ERROR_NT(status);
3050         }
3051
3052         RESOLVE_DFSPATH(directory, conn, inbuf, outbuf);
3053
3054         status = mkdir_internal(conn, directory);
3055         if (!NT_STATUS_IS_OK(status)) {
3056                 END_PROFILE(SMBmkdir);
3057                 return ERROR_NT(status);
3058         }
3059
3060         outsize = set_message(outbuf,0,0,True);
3061
3062         DEBUG( 3, ( "mkdir %s ret=%d\n", directory, outsize ) );
3063
3064         END_PROFILE(SMBmkdir);
3065         return(outsize);
3066 }
3067
3068 /****************************************************************************
3069  Static function used by reply_rmdir to delete an entire directory
3070  tree recursively. Return False on ok, True on fail.
3071 ****************************************************************************/
3072
3073 static BOOL recursive_rmdir(connection_struct *conn, char *directory)
3074 {
3075         const char *dname = NULL;
3076         BOOL ret = False;
3077         void *dirptr = OpenDir(conn, directory, False);
3078
3079         if(dirptr == NULL)
3080                 return True;
3081
3082         while((dname = ReadDirName(dirptr))) {
3083                 pstring fullname;
3084                 SMB_STRUCT_STAT st;
3085
3086                 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3087                         continue;
3088
3089                 /* Construct the full name. */
3090                 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
3091                         errno = ENOMEM;
3092                         ret = True;
3093                         break;
3094                 }
3095
3096                 pstrcpy(fullname, directory);
3097                 pstrcat(fullname, "/");
3098                 pstrcat(fullname, dname);
3099
3100                 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
3101                         ret = True;
3102                         break;
3103                 }
3104
3105                 if(st.st_mode & S_IFDIR) {
3106                         if(recursive_rmdir(conn, fullname)!=0) {
3107                                 ret = True;
3108                                 break;
3109                         }
3110                         if(SMB_VFS_RMDIR(conn,fullname) != 0) {
3111                                 ret = True;
3112                                 break;
3113                         }
3114                 } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
3115                         ret = True;
3116                         break;
3117                 }
3118         }
3119         CloseDir(dirptr);
3120         return ret;
3121 }
3122
3123 /****************************************************************************
3124  The internals of the rmdir code - called elsewhere.
3125 ****************************************************************************/
3126
3127 BOOL rmdir_internals(connection_struct *conn, char *directory)
3128 {
3129         BOOL ok;
3130
3131         ok = (SMB_VFS_RMDIR(conn,directory) == 0);
3132         if(!ok && ((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
3133                 /* 
3134                  * Check to see if the only thing in this directory are
3135                  * vetoed files/directories. If so then delete them and
3136                  * retry. If we fail to delete any of them (and we *don't*
3137                  * do a recursive delete) then fail the rmdir.
3138                  */
3139                 BOOL all_veto_files = True;
3140                 const char *dname;
3141                 void *dirptr = OpenDir(conn, directory, False);
3142
3143                 if(dirptr != NULL) {
3144                         int dirpos = TellDir(dirptr);
3145                         while ((dname = ReadDirName(dirptr))) {
3146                                 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3147                                         continue;
3148                                 if(!IS_VETO_PATH(conn, dname)) {
3149                                         all_veto_files = False;
3150                                         break;
3151                                 }
3152                         }
3153
3154                         if(all_veto_files) {
3155                                 SeekDir(dirptr,dirpos);
3156                                 while ((dname = ReadDirName(dirptr))) {
3157                                         pstring fullname;
3158                                         SMB_STRUCT_STAT st;
3159
3160                                         if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3161                                                 continue;
3162
3163                                         /* Construct the full name. */
3164                                         if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
3165                                                 errno = ENOMEM;
3166                                                 break;
3167                                         }
3168
3169                                         pstrcpy(fullname, directory);
3170                                         pstrcat(fullname, "/");
3171                                         pstrcat(fullname, dname);
3172                      
3173                                         if(SMB_VFS_LSTAT(conn,fullname, &st) != 0)
3174                                                 break;
3175                                         if(st.st_mode & S_IFDIR) {
3176                                                 if(lp_recursive_veto_delete(SNUM(conn))) {
3177                                                         if(recursive_rmdir(conn, fullname) != 0)
3178                                                                 break;
3179                                                 }
3180                                                 if(SMB_VFS_RMDIR(conn,fullname) != 0)
3181                                                         break;
3182                                         } else if(SMB_VFS_UNLINK(conn,fullname) != 0)
3183                                                 break;
3184                                 }
3185                                 CloseDir(dirptr);
3186                                 /* Retry the rmdir */
3187                                 ok = (SMB_VFS_RMDIR(conn,directory) == 0);
3188                         } else {
3189                                 CloseDir(dirptr);
3190                         }
3191                 } else {
3192                         errno = ENOTEMPTY;
3193                 }
3194         }
3195
3196         if (!ok)
3197                 DEBUG(3,("rmdir_internals: couldn't remove directory %s : %s\n", directory,strerror(errno)));
3198
3199         return ok;
3200 }
3201
3202 /****************************************************************************
3203  Reply to a rmdir.
3204 ****************************************************************************/
3205
3206 int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3207 {
3208         pstring directory;
3209         int outsize = 0;
3210         BOOL ok = False;
3211         BOOL bad_path = False;
3212         SMB_STRUCT_STAT sbuf;
3213         NTSTATUS status;
3214         START_PROFILE(SMBrmdir);
3215
3216         srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), STR_TERMINATE,&status);
3217         if (!NT_STATUS_IS_OK(status)) {
3218                 END_PROFILE(SMBrmdir);
3219                 return ERROR_NT(status);
3220         }
3221
3222         RESOLVE_DFSPATH(directory, conn, inbuf, outbuf)
3223
3224         unix_convert(directory,conn, NULL,&bad_path,&sbuf);
3225   
3226         if (check_name(directory,conn)) {
3227                 dptr_closepath(directory,SVAL(inbuf,smb_pid));
3228                 ok = rmdir_internals(conn, directory);
3229         }
3230   
3231         if (!ok) {
3232                 END_PROFILE(SMBrmdir);
3233                 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRbadpath);
3234         }
3235  
3236         outsize = set_message(outbuf,0,0,True);
3237   
3238         DEBUG( 3, ( "rmdir %s\n", directory ) );
3239   
3240         END_PROFILE(SMBrmdir);
3241         return(outsize);
3242 }
3243
3244 /*******************************************************************
3245  Resolve wildcards in a filename rename.
3246 ********************************************************************/
3247
3248 static BOOL resolve_wildcards(const char *name1, char *name2)
3249 {
3250         fstring root1,root2;
3251         fstring ext1,ext2;
3252         char *p,*p2, *pname1, *pname2;
3253         int available_space;
3254         
3255
3256         pname1 = strrchr_m(name1,'/');
3257         pname2 = strrchr_m(name2,'/');
3258
3259         if (!pname1 || !pname2)
3260                 return(False);
3261   
3262         fstrcpy(root1,pname1);
3263         fstrcpy(root2,pname2);
3264         p = strrchr_m(root1,'.');
3265         if (p) {
3266                 *p = 0;
3267                 fstrcpy(ext1,p+1);
3268         } else {
3269                 fstrcpy(ext1,"");    
3270         }
3271         p = strrchr_m(root2,'.');
3272         if (p) {
3273                 *p = 0;
3274                 fstrcpy(ext2,p+1);
3275         } else {
3276                 fstrcpy(ext2,"");    
3277         }
3278
3279         p = root1;
3280         p2 = root2;
3281         while (*p2) {
3282                 if (*p2 == '?') {
3283                         *p2 = *p;
3284                         p2++;
3285                 } else {
3286                         p2++;
3287                 }
3288                 if (*p)
3289                         p++;
3290         }
3291
3292         p = ext1;
3293         p2 = ext2;
3294         while (*p2) {
3295                 if (*p2 == '?') {
3296                         *p2 = *p;
3297                         p2++;
3298                 } else {
3299                         p2++;
3300                 }
3301                 if (*p)
3302                         p++;
3303         }
3304
3305         available_space = sizeof(pstring) - PTR_DIFF(pname2, name2);
3306         
3307         if (ext2[0]) {
3308                 snprintf(pname2, available_space - 1, "%s.%s", root2, ext2);
3309         } else {
3310                 pstrcpy_base(pname2, root2, name2);
3311         }
3312
3313         return(True);
3314 }
3315
3316 /****************************************************************************
3317  Ensure open files have their names updates.
3318 ****************************************************************************/
3319
3320 static void rename_open_files(connection_struct *conn, SMB_DEV_T dev, SMB_INO_T inode, char *newname)
3321 {
3322         files_struct *fsp;
3323         BOOL did_rename = False;
3324
3325         for(fsp = file_find_di_first(dev, inode); fsp; fsp = file_find_di_next(fsp)) {
3326                 DEBUG(10,("rename_open_files: renaming file fnum %d (dev = %x, inode = %.0f) from %s -> %s\n",
3327                         fsp->fnum, (unsigned int)fsp->dev, (double)fsp->inode,
3328                         fsp->fsp_name, newname ));
3329                 string_set(&fsp->fsp_name, newname);
3330                 did_rename = True;
3331         }
3332
3333         if (!did_rename)
3334                 DEBUG(10,("rename_open_files: no open files on dev %x, inode %.0f for %s\n",
3335                         (unsigned int)dev, (double)inode, newname ));
3336 }
3337
3338 /****************************************************************************
3339  Rename an open file - given an fsp.
3340 ****************************************************************************/
3341
3342 NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, char *newname, BOOL replace_if_exists)
3343 {
3344         SMB_STRUCT_STAT sbuf;
3345         BOOL bad_path = False;
3346         pstring newname_last_component;
3347         NTSTATUS error = NT_STATUS_OK;
3348         BOOL dest_exists;
3349
3350         ZERO_STRUCT(sbuf);
3351         unix_convert(newname,conn,newname_last_component,&bad_path,&sbuf);
3352
3353         /* Ensure newname contains a '/' */
3354         if(strrchr_m(newname,'/') == 0) {
3355                 pstring tmpstr;
3356                 
3357                 pstrcpy(tmpstr, "./");
3358                 pstrcat(tmpstr, newname);
3359                 pstrcpy(newname, tmpstr);
3360         }
3361
3362         /*
3363          * Check for special case with case preserving and not
3364          * case sensitive. If the old last component differs from the original
3365          * last component only by case, then we should allow
3366          * the rename (user is trying to change the case of the
3367          * filename).
3368          */
3369
3370         if((case_sensitive == False) && (case_preserve == True) &&
3371                         strequal(newname, fsp->fsp_name)) {
3372                 char *p;
3373                 pstring newname_modified_last_component;
3374
3375                 /*
3376                  * Get the last component of the modified name.
3377                  * Note that we guarantee that newname contains a '/'
3378                  * character above.
3379                  */
3380                 p = strrchr_m(newname,'/');
3381                 pstrcpy(newname_modified_last_component,p+1);
3382                         
3383                 if(strcsequal(newname_modified_last_component, 
3384                               newname_last_component) == False) {
3385                         /*
3386                          * Replace the modified last component with
3387                          * the original.
3388                          */
3389                         pstrcpy(p+1, newname_last_component);
3390                 }
3391         }
3392
3393         /*
3394          * If the src and dest names are identical - including case,
3395          * don't do the rename, just return success.
3396          */
3397
3398         if (strcsequal(fsp->fsp_name, newname)) {
3399                 DEBUG(3,("rename_internals_fsp: identical names in rename %s - returning success\n",
3400                         newname));
3401                 return NT_STATUS_OK;
3402         }
3403
3404         dest_exists = vfs_object_exist(conn,newname,NULL);
3405
3406         if(!replace_if_exists && dest_exists) {
3407                 DEBUG(3,("rename_internals_fsp: dest exists doing rename %s -> %s\n",
3408                         fsp->fsp_name,newname));
3409                 return NT_STATUS_OBJECT_NAME_COLLISION;
3410         }
3411
3412         error = can_rename(newname,conn,&sbuf);
3413
3414         if (dest_exists && !NT_STATUS_IS_OK(error)) {
3415                 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3416                         nt_errstr(error), fsp->fsp_name,newname));
3417                 if (NT_STATUS_EQUAL(error,NT_STATUS_SHARING_VIOLATION))
3418                         error = NT_STATUS_ACCESS_DENIED;
3419                 return error;
3420         }
3421
3422         if(SMB_VFS_RENAME(conn,fsp->fsp_name, newname) == 0) {
3423                 DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n",
3424                         fsp->fsp_name,newname));
3425                 rename_open_files(conn, fsp->dev, fsp->inode, newname);
3426                 return NT_STATUS_OK;    
3427         }
3428
3429         if (errno == ENOTDIR || errno == EISDIR)
3430                 error = NT_STATUS_OBJECT_NAME_COLLISION;
3431         else
3432                 error = map_nt_error_from_unix(errno);
3433                 
3434         DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
3435                 nt_errstr(error), fsp->fsp_name,newname));
3436
3437         return error;
3438 }
3439
3440 /****************************************************************************
3441  The guts of the rename command, split out so it may be called by the NT SMB
3442  code. 
3443 ****************************************************************************/
3444
3445 NTSTATUS rename_internals(connection_struct *conn, char *name, char *newname, BOOL replace_if_exists)
3446 {
3447         pstring directory;
3448         pstring mask;
3449         pstring newname_last_component;
3450         char *p;
3451         BOOL has_wild;
3452         BOOL bad_path1 = False;
3453         BOOL bad_path2 = False;
3454         int count=0;
3455         NTSTATUS error = NT_STATUS_OK;
3456         BOOL rc = True;
3457         SMB_STRUCT_STAT sbuf1, sbuf2;
3458
3459         *directory = *mask = 0;
3460
3461         ZERO_STRUCT(sbuf1);
3462         ZERO_STRUCT(sbuf2);
3463         rc = unix_convert(name,conn,0,&bad_path1,&sbuf1);
3464         unix_convert(newname,conn,newname_last_component,&bad_path2,&sbuf2);
3465
3466         /*
3467          * Split the old name into directory and last component
3468          * strings. Note that unix_convert may have stripped off a 
3469          * leading ./ from both name and newname if the rename is 
3470          * at the root of the share. We need to make sure either both
3471          * name and newname contain a / character or neither of them do
3472          * as this is checked in resolve_wildcards().
3473          */
3474         
3475         p = strrchr_m(name,'/');
3476         if (!p) {
3477                 pstrcpy(directory,".");
3478                 pstrcpy(mask,name);
3479         } else {
3480                 *p = 0;
3481                 pstrcpy(directory,name);
3482                 pstrcpy(mask,p+1);
3483                 *p = '/'; /* Replace needed for exceptional test below. */
3484         }
3485
3486         /*
3487          * We should only check the mangled cache
3488          * here if unix_convert failed. This means
3489          * that the path in 'mask' doesn't exist
3490          * on the file system and so we need to look
3491          * for a possible mangle. This patch from
3492          * Tine Smukavec <valentin.smukavec@hermes.si>.
3493          */
3494
3495         if (!rc && mangle_is_mangled(mask))
3496                 mangle_check_cache( mask );
3497
3498         has_wild = ms_has_wild(mask);
3499
3500         if (!has_wild) {
3501                 /*
3502                  * No wildcards - just process the one file.
3503                  */
3504                 BOOL is_short_name = mangle_is_8_3(name, True);
3505
3506                 /* Add a terminating '/' to the directory name. */
3507                 pstrcat(directory,"/");
3508                 pstrcat(directory,mask);
3509                 
3510                 /* Ensure newname contains a '/' also */
3511                 if(strrchr_m(newname,'/') == 0) {
3512                         pstring tmpstr;
3513                         
3514                         pstrcpy(tmpstr, "./");
3515                         pstrcat(tmpstr, newname);
3516                         pstrcpy(newname, tmpstr);
3517                 }
3518                 
3519                 DEBUG(3,("rename_internals: case_sensitive = %d, case_preserve = %d, short case preserve = %d, \
3520 directory = %s, newname = %s, newname_last_component = %s, is_8_3 = %d\n", 
3521                          case_sensitive, case_preserve, short_case_preserve, directory, 
3522                          newname, newname_last_component, is_short_name));
3523
3524                 /*
3525                  * Check for special case with case preserving and not
3526                  * case sensitive, if directory and newname are identical,
3527                  * and the old last component differs from the original
3528                  * last component only by case, then we should allow
3529                  * the rename (user is trying to change the case of the
3530                  * filename).
3531                  */
3532                 if((case_sensitive == False) && 
3533                    (((case_preserve == True) && 
3534                      (is_short_name == False)) || 
3535                     ((short_case_preserve == True) && 
3536                      (is_short_name == True))) &&
3537                    strcsequal(directory, newname)) {
3538                         pstring newname_modified_last_component;
3539
3540                         /*
3541                          * Get the last component of the modified name.
3542                          * Note that we guarantee that newname contains a '/'
3543                          * character above.
3544                          */
3545                         p = strrchr_m(newname,'/');
3546                         pstrcpy(newname_modified_last_component,p+1);
3547                         
3548                         if(strcsequal(newname_modified_last_component, 
3549                                       newname_last_component) == False) {
3550                                 /*
3551                                  * Replace the modified last component with
3552                                  * the original.
3553                                  */
3554                                 pstrcpy(p+1, newname_last_component);
3555                         }
3556                 }
3557         
3558                 resolve_wildcards(directory,newname);
3559         
3560                 /*
3561                  * The source object must exist.
3562                  */
3563
3564                 if (!vfs_object_exist(conn, directory, &sbuf1)) {
3565                         DEBUG(3,("rename_internals: source doesn't exist doing rename %s -> %s\n",
3566                                 directory,newname));
3567
3568                         if (errno == ENOTDIR || errno == EISDIR || errno == ENOENT) {
3569                                 /*
3570                                  * Must return different errors depending on whether the parent
3571                                  * directory existed or not.
3572                                  */
3573
3574                                 p = strrchr_m(directory, '/');
3575                                 if (!p)
3576                                         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3577                                 *p = '\0';
3578                                 if (vfs_object_exist(conn, directory, NULL))
3579                                         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3580                                 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3581                         }
3582                         error = map_nt_error_from_unix(errno);
3583                         DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3584                                 nt_errstr(error), directory,newname));
3585
3586                         return error;
3587                 }
3588
3589                 error = can_rename(directory,conn,&sbuf1);
3590
3591                 if (!NT_STATUS_IS_OK(error)) {
3592                         DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3593                                 nt_errstr(error), directory,newname));
3594                         return error;
3595                 }
3596
3597                 /*
3598                  * If the src and dest names are identical - including case,
3599                  * don't do the rename, just return success.
3600                  */
3601
3602                 if (strcsequal(directory, newname)) {
3603                         rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
3604                         DEBUG(3,("rename_internals: identical names in rename %s - returning success\n", directory));
3605                         return NT_STATUS_OK;
3606                 }
3607
3608                 if(!replace_if_exists && vfs_object_exist(conn,newname,NULL)) {
3609                         DEBUG(3,("rename_internals: dest exists doing rename %s -> %s\n",
3610                                 directory,newname));
3611                         return NT_STATUS_OBJECT_NAME_COLLISION;
3612                 }
3613
3614                 if(SMB_VFS_RENAME(conn,directory, newname) == 0) {
3615                         DEBUG(3,("rename_internals: succeeded doing rename on %s -> %s\n",
3616                                 directory,newname));
3617                         rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
3618                         return NT_STATUS_OK;    
3619                 }
3620
3621                 if (errno == ENOTDIR || errno == EISDIR)
3622                         error = NT_STATUS_OBJECT_NAME_COLLISION;
3623                 else
3624                         error = map_nt_error_from_unix(errno);
3625                 
3626                 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3627                         nt_errstr(error), directory,newname));
3628
3629                 return error;
3630         } else {
3631                 /*
3632                  * Wildcards - process each file that matches.
3633                  */
3634                 void *dirptr = NULL;
3635                 const char *dname;
3636                 pstring destname;
3637                 
3638                 if (check_name(directory,conn))
3639                         dirptr = OpenDir(conn, directory, True);
3640                 
3641                 if (dirptr) {
3642                         error = NT_STATUS_OBJECT_NAME_NOT_FOUND;
3643                         
3644                         if (strequal(mask,"????????.???"))
3645                                 pstrcpy(mask,"*");
3646                         
3647                         while ((dname = ReadDirName(dirptr))) {
3648                                 pstring fname;
3649
3650                                 pstrcpy(fname,dname);
3651                                 
3652                                 if(!mask_match(fname, mask, case_sensitive))
3653                                         continue;
3654                                 
3655                                 error = NT_STATUS_ACCESS_DENIED;
3656                                 slprintf(fname,sizeof(fname)-1,"%s/%s",directory,dname);
3657                                 if (!vfs_object_exist(conn, fname, &sbuf1)) {
3658                                         error = NT_STATUS_OBJECT_NAME_NOT_FOUND;
3659                                         DEBUG(6,("rename %s failed. Error %s\n", fname, nt_errstr(error)));
3660                                         continue;
3661                                 }
3662                                 error = can_rename(fname,conn,&sbuf1);
3663                                 if (!NT_STATUS_IS_OK(error)) {
3664                                         DEBUG(6,("rename %s refused\n", fname));
3665                                         continue;
3666                                 }
3667                                 pstrcpy(destname,newname);
3668                                 
3669                                 if (!resolve_wildcards(fname,destname)) {
3670                                         DEBUG(6,("resolve_wildcards %s %s failed\n", 
3671                                                  fname, destname));
3672                                         continue;
3673                                 }
3674                                 
3675                                 if (!replace_if_exists && 
3676                                     vfs_file_exist(conn,destname, NULL)) {
3677                                         DEBUG(6,("file_exist %s\n", destname));
3678                                         error = NT_STATUS_OBJECT_NAME_COLLISION;
3679                                         continue;
3680                                 }
3681                                 
3682                                 if (!SMB_VFS_RENAME(conn,fname,destname)) {
3683                                         rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
3684                                         count++;
3685                                 }
3686                                 DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname));
3687                         }
3688                         CloseDir(dirptr);
3689                 }
3690         }
3691         
3692         if (count == 0 && NT_STATUS_IS_OK(error)) {
3693                 error = map_nt_error_from_unix(errno);
3694         }
3695         
3696         return error;
3697 }
3698
3699 /****************************************************************************
3700  Reply to a mv.
3701 ****************************************************************************/
3702
3703 int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, 
3704              int dum_buffsize)
3705 {
3706         int outsize = 0;
3707         pstring name;
3708         pstring newname;
3709         char *p;
3710         NTSTATUS status;
3711
3712         START_PROFILE(SMBmv);
3713
3714         p = smb_buf(inbuf) + 1;
3715         p += srvstr_get_path(inbuf, name, p, sizeof(name), STR_TERMINATE,&status);
3716         if (!NT_STATUS_IS_OK(status)) {
3717                 END_PROFILE(SMBmv);
3718                 return ERROR_NT(status);
3719         }
3720         p++;
3721         p += srvstr_get_path(inbuf, newname, p, sizeof(newname), STR_TERMINATE,&status);
3722         if (!NT_STATUS_IS_OK(status)) {
3723                 END_PROFILE(SMBmv);
3724                 return ERROR_NT(status);
3725         }
3726         
3727         RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
3728         RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
3729         
3730         DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
3731         
3732         status = rename_internals(conn, name, newname, False);
3733         if (!NT_STATUS_IS_OK(status)) {
3734                 END_PROFILE(SMBmv);
3735                 return ERROR_NT(status);
3736         }
3737
3738         /*
3739          * Win2k needs a changenotify request response before it will
3740          * update after a rename..
3741          */     
3742         process_pending_change_notify_queue((time_t)0);
3743         outsize = set_message(outbuf,0,0,True);
3744   
3745         END_PROFILE(SMBmv);
3746         return(outsize);
3747 }
3748
3749 /*******************************************************************
3750  Copy a file as part of a reply_copy.
3751 ******************************************************************/
3752
3753 static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
3754                       int count,BOOL target_is_directory, int *err_ret)
3755 {
3756         int Access,action;
3757         SMB_STRUCT_STAT src_sbuf, sbuf2;
3758         SMB_OFF_T ret=-1;
3759         files_struct *fsp1,*fsp2;
3760         pstring dest;
3761   
3762         *err_ret = 0;
3763
3764         pstrcpy(dest,dest1);
3765         if (target_is_directory) {
3766                 char *p = strrchr_m(src,'/');
3767                 if (p) 
3768                         p++;
3769                 else
3770                         p = src;
3771                 pstrcat(dest,"/");
3772                 pstrcat(dest,p);
3773         }
3774
3775         if (!vfs_file_exist(conn,src,&src_sbuf))
3776                 return(False);
3777
3778         fsp1 = open_file_shared(conn,src,&src_sbuf,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
3779                                         (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),0,0,&Access,&action);
3780
3781         if (!fsp1)
3782                 return(False);
3783
3784         if (!target_is_directory && count)
3785                 ofun = FILE_EXISTS_OPEN;
3786
3787         if (SMB_VFS_STAT(conn,dest,&sbuf2) == -1)
3788                 ZERO_STRUCTP(&sbuf2);
3789
3790         fsp2 = open_file_shared(conn,dest,&sbuf2,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_WRONLY),
3791                         ofun,src_sbuf.st_mode,0,&Access,&action);
3792
3793         if (!fsp2) {
3794                 close_file(fsp1,False);
3795                 return(False);
3796         }
3797
3798         if ((ofun&3) == 1) {
3799                 if(SMB_VFS_LSEEK(fsp2,fsp2->fd,0,SEEK_END) == -1) {
3800                         DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
3801                         /*
3802                          * Stop the copy from occurring.
3803                          */
3804                         ret = -1;
3805                         src_sbuf.st_size = 0;
3806                 }
3807         }
3808   
3809         if (src_sbuf.st_size)
3810                 ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_size);
3811
3812         close_file(fsp1,False);
3813
3814         /* Ensure the modtime is set correctly on the destination file. */
3815         fsp2->pending_modtime = src_sbuf.st_mtime;
3816
3817         /*
3818          * As we are opening fsp1 read-only we only expect
3819          * an error on close on fsp2 if we are out of space.
3820          * Thus we don't look at the error return from the
3821          * close of fsp1.
3822          */
3823         *err_ret = close_file(fsp2,False);
3824
3825         return(ret == (SMB_OFF_T)src_sbuf.st_size);
3826 }
3827
3828 /****************************************************************************
3829  Reply to a file copy.
3830 ****************************************************************************/
3831
3832 int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3833 {
3834         int outsize = 0;
3835         pstring name;
3836         pstring directory;
3837         pstring mask,newname;
3838         char *p;
3839         int count=0;
3840         int error = ERRnoaccess;
3841         int err = 0;
3842         BOOL has_wild;
3843         BOOL exists=False;
3844         int tid2 = SVAL(inbuf,smb_vwv0);
3845         int ofun = SVAL(inbuf,smb_vwv1);
3846         int flags = SVAL(inbuf,smb_vwv2);
3847         BOOL target_is_directory=False;
3848         BOOL bad_path1 = False;
3849         BOOL bad_path2 = False;
3850         BOOL rc = True;
3851         SMB_STRUCT_STAT sbuf1, sbuf2;
3852         NTSTATUS status;
3853
3854         START_PROFILE(SMBcopy);
3855
3856         *directory = *mask = 0;
3857
3858         p = smb_buf(inbuf);
3859         p += srvstr_get_path(inbuf, name, p, sizeof(name), STR_TERMINATE,&status);
3860         if (!NT_STATUS_IS_OK(status)) {
3861                 END_PROFILE(SMBcopy);
3862                 return ERROR_NT(status);
3863         }
3864         p += srvstr_get_path(inbuf, newname, p, sizeof(newname), STR_TERMINATE,&status);
3865         if (!NT_STATUS_IS_OK(status)) {
3866                 END_PROFILE(SMBcopy);
3867                 return ERROR_NT(status);
3868         }
3869    
3870         DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
3871    
3872         if (tid2 != conn->cnum) {
3873                 /* can't currently handle inter share copies XXXX */
3874                 DEBUG(3,("Rejecting inter-share copy\n"));
3875                 END_PROFILE(SMBcopy);
3876                 return ERROR_DOS(ERRSRV,ERRinvdevice);
3877         }
3878
3879         RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
3880         RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
3881
3882         rc = unix_convert(name,conn,0,&bad_path1,&sbuf1);
3883         unix_convert(newname,conn,0,&bad_path2,&sbuf2);
3884
3885         target_is_directory = VALID_STAT_OF_DIR(sbuf2);
3886
3887         if ((flags&1) && target_is_directory) {
3888                 END_PROFILE(SMBcopy);
3889                 return ERROR_DOS(ERRDOS,ERRbadfile);
3890         }
3891
3892         if ((flags&2) && !target_is_directory) {
3893                 END_PROFILE(SMBcopy);
3894                 return ERROR_DOS(ERRDOS,ERRbadpath);
3895         }
3896
3897         if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) {
3898                 /* wants a tree copy! XXXX */
3899                 DEBUG(3,("Rejecting tree copy\n"));
3900                 END_PROFILE(SMBcopy);
3901                 return ERROR_DOS(ERRSRV,ERRerror);
3902         }
3903
3904         p = strrchr_m(name,'/');
3905         if (!p) {
3906                 pstrcpy(directory,"./");
3907                 pstrcpy(mask,name);
3908         } else {
3909                 *p = 0;
3910                 pstrcpy(directory,name);
3911                 pstrcpy(mask,p+1);
3912         }
3913
3914         /*
3915          * We should only check the mangled cache
3916          * here if unix_convert failed. This means
3917          * that the path in 'mask' doesn't exist
3918          * on the file system and so we need to look
3919          * for a possible mangle. This patch from
3920          * Tine Smukavec <valentin.smukavec@hermes.si>.
3921          */
3922
3923         if (!rc && mangle_is_mangled(mask))
3924                 mangle_check_cache( mask );
3925
3926         has_wild = ms_has_wild(mask);
3927
3928         if (!has_wild) {
3929                 pstrcat(directory,"/");
3930                 pstrcat(directory,mask);
3931                 if (resolve_wildcards(directory,newname) &&
3932                                 copy_file(directory,newname,conn,ofun, count,target_is_directory,&err))
3933                         count++;
3934                 if(!count && err) {
3935                         errno = err;
3936                         END_PROFILE(SMBcopy);
3937                         return(UNIXERROR(ERRHRD,ERRgeneral));
3938                 }
3939                 if (!count) {
3940                         exists = vfs_file_exist(conn,directory,NULL);
3941                 }
3942         } else {
3943                 void *dirptr = NULL;
3944                 const char *dname;
3945                 pstring destname;
3946
3947                 if (check_name(directory,conn))
3948                         dirptr = OpenDir(conn, directory, True);
3949
3950                 if (dirptr) {
3951                         error = ERRbadfile;
3952
3953                         if (strequal(mask,"????????.???"))
3954                                 pstrcpy(mask,"*");
3955
3956                         while ((dname = ReadDirName(dirptr))) {
3957                                 pstring fname;
3958                                 pstrcpy(fname,dname);
3959     
3960                                 if(!mask_match(fname, mask, case_sensitive))
3961                                         continue;
3962
3963                                 error = ERRnoaccess;
3964                                 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
3965                                 pstrcpy(destname,newname);
3966                                 if (resolve_wildcards(fname,destname) && 
3967                                                 copy_file(fname,destname,conn,ofun,
3968                                                 count,target_is_directory,&err))
3969                                         count++;
3970                                 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
3971                         }
3972                         CloseDir(dirptr);
3973                 }
3974         }
3975   
3976         if (count == 0) {
3977                 if(err) {
3978                         /* Error on close... */
3979                         errno = err;
3980                         END_PROFILE(SMBcopy);
3981                         return(UNIXERROR(ERRHRD,ERRgeneral));
3982                 }
3983
3984                 if (exists) {
3985                         END_PROFILE(SMBcopy);
3986                         return ERROR_DOS(ERRDOS,error);
3987                 } else {
3988                         if((errno == ENOENT) && (bad_path1 || bad_path2)) {
3989                                 unix_ERR_class = ERRDOS;
3990                                 unix_ERR_code = ERRbadpath;
3991                         }
3992                         END_PROFILE(SMBcopy);
3993                         return(UNIXERROR(ERRDOS,error));
3994                 }
3995         }
3996   
3997         outsize = set_message(outbuf,1,0,True);
3998         SSVAL(outbuf,smb_vwv0,count);
3999
4000         END_PROFILE(SMBcopy);
4001         return(outsize);
4002 }
4003
4004 /****************************************************************************
4005  Reply to a setdir.
4006 ****************************************************************************/
4007
4008 int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4009 {
4010         int snum;
4011         int outsize = 0;
4012         BOOL ok = False;
4013         pstring newdir;
4014         NTSTATUS status;
4015
4016         START_PROFILE(pathworks_setdir);
4017   
4018         snum = SNUM(conn);
4019         if (!CAN_SETDIR(snum)) {
4020                 END_PROFILE(pathworks_setdir);
4021                 return ERROR_DOS(ERRDOS,ERRnoaccess);
4022         }
4023
4024         srvstr_get_path(inbuf, newdir, smb_buf(inbuf) + 1, sizeof(newdir), STR_TERMINATE,&status);
4025         if (!NT_STATUS_IS_OK(status)) {
4026                 END_PROFILE(pathworks_setdir);
4027                 return ERROR_NT(status);
4028         }
4029   
4030         if (strlen(newdir) == 0) {
4031                 ok = True;
4032         } else {
4033                 ok = vfs_directory_exist(conn,newdir,NULL);
4034                 if (ok)
4035                         string_set(&conn->connectpath,newdir);
4036         }
4037   
4038         if (!ok) {
4039                 END_PROFILE(pathworks_setdir);
4040                 return ERROR_DOS(ERRDOS,ERRbadpath);
4041         }
4042   
4043         outsize = set_message(outbuf,0,0,True);
4044         SCVAL(outbuf,smb_reh,CVAL(inbuf,smb_reh));
4045   
4046         DEBUG(3,("setdir %s\n", newdir));
4047
4048         END_PROFILE(pathworks_setdir);
4049         return(outsize);
4050 }
4051
4052 /****************************************************************************
4053  Get a lock pid, dealing with large count requests.
4054 ****************************************************************************/
4055
4056 uint16 get_lock_pid( char *data, int data_offset, BOOL large_file_format)
4057 {
4058         if(!large_file_format)
4059                 return SVAL(data,SMB_LPID_OFFSET(data_offset));
4060         else
4061                 return SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
4062 }
4063
4064 /****************************************************************************
4065  Get a lock count, dealing with large count requests.
4066 ****************************************************************************/
4067
4068 SMB_BIG_UINT get_lock_count( char *data, int data_offset, BOOL large_file_format)
4069 {
4070         SMB_BIG_UINT count = 0;
4071
4072         if(!large_file_format) {
4073                 count = (SMB_BIG_UINT)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
4074         } else {
4075
4076 #if defined(HAVE_LONGLONG)
4077                 count = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
4078                         ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
4079 #else /* HAVE_LONGLONG */
4080
4081                 /*
4082                  * NT4.x seems to be broken in that it sends large file (64 bit)
4083                  * lockingX calls even if the CAP_LARGE_FILES was *not*
4084                  * negotiated. For boxes without large unsigned ints truncate the
4085                  * lock count by dropping the top 32 bits.
4086                  */
4087
4088                 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
4089                         DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
4090                                 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
4091                                 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
4092                                 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
4093                 }
4094
4095                 count = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
4096 #endif /* HAVE_LONGLONG */
4097         }
4098
4099         return count;
4100 }
4101
4102 #if !defined(HAVE_LONGLONG)
4103 /****************************************************************************
4104  Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
4105 ****************************************************************************/
4106
4107 static uint32 map_lock_offset(uint32 high, uint32 low)
4108 {
4109         unsigned int i;
4110         uint32 mask = 0;
4111         uint32 highcopy = high;
4112  
4113         /*
4114          * Try and find out how many significant bits there are in high.
4115          */
4116  
4117         for(i = 0; highcopy; i++)
4118                 highcopy >>= 1;
4119  
4120         /*
4121          * We use 31 bits not 32 here as POSIX
4122          * lock offsets may not be negative.
4123          */
4124  
4125         mask = (~0) << (31 - i);
4126  
4127         if(low & mask)
4128                 return 0; /* Fail. */
4129  
4130         high <<= (31 - i);
4131  
4132         return (high|low);
4133 }
4134 #endif /* !defined(HAVE_LONGLONG) */
4135
4136 /****************************************************************************
4137  Get a lock offset, dealing with large offset requests.
4138 ****************************************************************************/
4139
4140 SMB_BIG_UINT get_lock_offset( char *data, int data_offset, BOOL large_file_format, BOOL *err)
4141 {
4142         SMB_BIG_UINT offset = 0;
4143
4144         *err = False;
4145
4146         if(!large_file_format) {
4147                 offset = (SMB_BIG_UINT)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
4148         } else {
4149
4150 #if defined(HAVE_LONGLONG)
4151                 offset = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
4152                                 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
4153 #else /* HAVE_LONGLONG */
4154
4155                 /*
4156                  * NT4.x seems to be broken in that it sends large file (64 bit)
4157                  * lockingX calls even if the CAP_LARGE_FILES was *not*
4158                  * negotiated. For boxes without large unsigned ints mangle the
4159                  * lock offset by mapping the top 32 bits onto the lower 32.
4160                  */
4161       
4162                 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
4163                         uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
4164                         uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
4165                         uint32 new_low = 0;
4166
4167                         if((new_low = map_lock_offset(high, low)) == 0) {
4168                                 *err = True;
4169                                 return (SMB_BIG_UINT)-1;
4170                         }
4171
4172                         DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
4173                                 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
4174                         SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
4175                         SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
4176                 }
4177
4178                 offset = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
4179 #endif /* HAVE_LONGLONG */
4180         }
4181
4182         return offset;
4183 }
4184
4185 /****************************************************************************
4186  Reply to a lockingX request.
4187 ****************************************************************************/
4188
4189 int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
4190 {
4191         files_struct *fsp = file_fsp(inbuf,smb_vwv2);
4192         unsigned char locktype = CVAL(inbuf,smb_vwv3);
4193         unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
4194         uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
4195         uint16 num_locks = SVAL(inbuf,smb_vwv7);
4196         SMB_BIG_UINT count = 0, offset = 0;
4197         uint16 lock_pid;
4198         int32 lock_timeout = IVAL(inbuf,smb_vwv4);
4199         int i;
4200         char *data;
4201         BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
4202         BOOL err;
4203         BOOL my_lock_ctx = False;
4204         NTSTATUS status;
4205
4206         START_PROFILE(SMBlockingX);
4207         
4208         CHECK_FSP(fsp,conn);
4209         
4210         data = smb_buf(inbuf);
4211
4212         if (locktype & (LOCKING_ANDX_CANCEL_LOCK | LOCKING_ANDX_CHANGE_LOCKTYPE)) {
4213                 /* we don't support these - and CANCEL_LOCK makes w2k
4214                    and XP reboot so I don't really want to be
4215                    compatible! (tridge) */
4216                 return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
4217         }
4218         
4219         /* Check if this is an oplock break on a file
4220            we have granted an oplock on.
4221         */
4222         if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
4223                 /* Client can insist on breaking to none. */
4224                 BOOL break_to_none = (oplocklevel == 0);
4225                 
4226                 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client for fnum = %d\n",
4227                          (unsigned int)oplocklevel, fsp->fnum ));
4228
4229                 /*
4230                  * Make sure we have granted an exclusive or batch oplock on this file.
4231                  */
4232                 
4233                 if(!EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
4234                         DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \
4235 no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name));
4236
4237                         /* if this is a pure oplock break request then don't send a reply */
4238                         if (num_locks == 0 && num_ulocks == 0) {
4239                                 END_PROFILE(SMBlockingX);
4240                                 return -1;
4241                         } else {
4242                                 END_PROFILE(SMBlockingX);
4243                                 return ERROR_DOS(ERRDOS,ERRlock);
4244                         }
4245                 }
4246
4247                 if (remove_oplock(fsp, break_to_none) == False) {
4248                         DEBUG(0,("reply_lockingX: error in removing oplock on file %s\n",
4249                                  fsp->fsp_name ));
4250                 }
4251                 
4252                 /* if this is a pure oplock break request then don't send a reply */
4253                 if (num_locks == 0 && num_ulocks == 0) {
4254                         /* Sanity check - ensure a pure oplock break is not a
4255                            chained request. */
4256                         if(CVAL(inbuf,smb_vwv0) != 0xff)
4257                                 DEBUG(0,("reply_lockingX: Error : pure oplock break is a chained %d request !\n",
4258                                          (unsigned int)CVAL(inbuf,smb_vwv0) ));
4259                         END_PROFILE(SMBlockingX);
4260                         return -1;
4261                 }
4262         }
4263
4264         /*
4265          * We do this check *after* we have checked this is not a oplock break
4266          * response message. JRA.
4267          */
4268         
4269         release_level_2_oplocks_on_change(fsp);
4270         
4271         /* Data now points at the beginning of the list
4272            of smb_unlkrng structs */
4273         for(i = 0; i < (int)num_ulocks; i++) {
4274                 lock_pid = get_lock_pid( data, i, large_file_format);
4275                 count = get_lock_count( data, i, large_file_format);
4276                 offset = get_lock_offset( data, i, large_file_format, &err);
4277                 
4278                 /*
4279                  * There is no error code marked "stupid client bug".... :-).
4280                  */
4281                 if(err) {
4282                         END_PROFILE(SMBlockingX);
4283                         return ERROR_DOS(ERRDOS,ERRnoaccess);
4284                 }
4285
4286                 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for pid %u, file %s\n",
4287                           (double)offset, (double)count, (unsigned int)lock_pid, fsp->fsp_name ));
4288                 
4289                 status = do_unlock(fsp,conn,lock_pid,count,offset);
4290                 if (NT_STATUS_V(status)) {
4291                         END_PROFILE(SMBlockingX);
4292                         return ERROR_NT(status);
4293                 }
4294         }
4295
4296         /* Setup the timeout in seconds. */
4297
4298         lock_timeout = ((lock_timeout == -1) ? -1 : (lock_timeout+499)/500);
4299         
4300         /* Now do any requested locks */
4301         data += ((large_file_format ? 20 : 10)*num_ulocks);
4302         
4303         /* Data now points at the beginning of the list
4304            of smb_lkrng structs */
4305         
4306         for(i = 0; i < (int)num_locks; i++) {
4307                 lock_pid = get_lock_pid( data, i, large_file_format);
4308                 count = get_lock_count( data, i, large_file_format);
4309                 offset = get_lock_offset( data, i, large_file_format, &err);
4310                 
4311                 /*
4312                  * There is no error code marked "stupid client bug".... :-).
4313                  */
4314                 if(err) {
4315                         END_PROFILE(SMBlockingX);
4316                         return ERROR_DOS(ERRDOS,ERRnoaccess);
4317                 }
4318                 
4319                 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid %u, file %s timeout = %d\n",
4320                         (double)offset, (double)count, (unsigned int)lock_pid,
4321                         fsp->fsp_name, (int)lock_timeout ));
4322                 
4323                 status = do_lock_spin(fsp,conn,lock_pid, count,offset, 
4324                                  ((locktype & 1) ? READ_LOCK : WRITE_LOCK), &my_lock_ctx);
4325                 if (NT_STATUS_V(status)) {
4326                         if ((lock_timeout != 0) && lp_blocking_locks(SNUM(conn)) && !my_lock_ctx && ERROR_WAS_LOCK_DENIED(status)) {
4327                                 /*
4328                                  * A blocking lock was requested. Package up
4329                                  * this smb into a queued request and push it
4330                                  * onto the blocking lock queue.
4331                                  */
4332                                 if(push_blocking_lock_request(inbuf, length, lock_timeout, i, lock_pid, offset, count)) {
4333                                         END_PROFILE(SMBlockingX);
4334                                         return -1;
4335                                 }
4336                         }
4337                         break;
4338                 }
4339         }
4340         
4341         /* If any of the above locks failed, then we must unlock
4342            all of the previous locks (X/Open spec). */
4343         if (i != num_locks && num_locks != 0) {
4344                 /*
4345                  * Ensure we don't do a remove on the lock that just failed,
4346                  * as under POSIX rules, if we have a lock already there, we
4347                  * will delete it (and we shouldn't) .....
4348                  */
4349                 for(i--; i >= 0; i--) {
4350                         lock_pid = get_lock_pid( data, i, large_file_format);
4351                         count = get_lock_count( data, i, large_file_format);
4352                         offset = get_lock_offset( data, i, large_file_format, &err);
4353                         
4354                         /*
4355                          * There is no error code marked "stupid client bug".... :-).
4356                          */
4357                         if(err) {
4358                                 END_PROFILE(SMBlockingX);
4359                                 return ERROR_DOS(ERRDOS,ERRnoaccess);
4360                         }
4361                         
4362                         do_unlock(fsp,conn,lock_pid,count,offset);
4363                 }
4364                 END_PROFILE(SMBlockingX);
4365                 return ERROR_NT(status);
4366         }
4367
4368         set_message(outbuf,2,0,True);
4369         
4370         DEBUG( 3, ( "lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
4371                     fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks ) );
4372         
4373         END_PROFILE(SMBlockingX);
4374         return chain_reply(inbuf,outbuf,length,bufsize);
4375 }
4376
4377 /****************************************************************************
4378  Reply to a SMBreadbmpx (read block multiplex) request.
4379 ****************************************************************************/
4380
4381 int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
4382 {
4383         ssize_t nread = -1;
4384         ssize_t total_read;
4385         char *data;
4386         SMB_OFF_T startpos;
4387         int outsize;
4388         size_t maxcount;
4389         int max_per_packet;
4390         size_t tcount;
4391         int pad;
4392         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4393         START_PROFILE(SMBreadBmpx);
4394
4395         /* this function doesn't seem to work - disable by default */
4396         if (!lp_readbmpx()) {
4397                 END_PROFILE(SMBreadBmpx);
4398                 return ERROR_DOS(ERRSRV,ERRuseSTD);
4399         }
4400
4401         outsize = set_message(outbuf,8,0,True);
4402
4403         CHECK_FSP(fsp,conn);
4404         CHECK_READ(fsp);
4405
4406         startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
4407         maxcount = SVAL(inbuf,smb_vwv3);
4408
4409         data = smb_buf(outbuf);
4410         pad = ((long)data)%4;
4411         if (pad)
4412                 pad = 4 - pad;
4413         data += pad;
4414
4415         max_per_packet = bufsize-(outsize+pad);
4416         tcount = maxcount;
4417         total_read = 0;
4418
4419         if (is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
4420                 END_PROFILE(SMBreadBmpx);
4421                 return ERROR_DOS(ERRDOS,ERRlock);
4422         }
4423
4424         do {
4425                 size_t N = MIN(max_per_packet,tcount-total_read);
4426   
4427                 nread = read_file(fsp,data,startpos,N);
4428
4429                 if (nread <= 0)
4430                         nread = 0;
4431
4432                 if (nread < (ssize_t)N)
4433                         tcount = total_read + nread;
4434
4435                 set_message(outbuf,8,nread,False);
4436                 SIVAL(outbuf,smb_vwv0,startpos);
4437                 SSVAL(outbuf,smb_vwv2,tcount);
4438                 SSVAL(outbuf,smb_vwv6,nread);
4439                 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
4440
4441                 if (!send_smb(smbd_server_fd(),outbuf))
4442                         exit_server("reply_readbmpx: send_smb failed.");
4443
4444                 total_read += nread;
4445                 startpos += nread;
4446         } while (total_read < (ssize_t)tcount);
4447
4448         END_PROFILE(SMBreadBmpx);
4449         return(-1);
4450 }
4451
4452 /****************************************************************************
4453  Reply to a SMBsetattrE.
4454 ****************************************************************************/
4455
4456 int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4457 {
4458         struct utimbuf unix_times;
4459         int outsize = 0;
4460         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4461         START_PROFILE(SMBsetattrE);
4462
4463         outsize = set_message(outbuf,0,0,True);
4464
4465         if(!fsp || (fsp->conn != conn)) {
4466                 END_PROFILE(SMBgetattrE);
4467                 return ERROR_DOS(ERRDOS,ERRbadfid);
4468         }
4469
4470         /*
4471          * Convert the DOS times into unix times. Ignore create
4472          * time as UNIX can't set this.
4473          */
4474
4475         unix_times.actime = make_unix_date2(inbuf+smb_vwv3);
4476         unix_times.modtime = make_unix_date2(inbuf+smb_vwv5);
4477   
4478         /* 
4479          * Patch from Ray Frush <frush@engr.colostate.edu>
4480          * Sometimes times are sent as zero - ignore them.
4481          */
4482
4483         if ((unix_times.actime == 0) && (unix_times.modtime == 0)) {
4484                 /* Ignore request */
4485                 if( DEBUGLVL( 3 ) ) {
4486                         dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
4487                         dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
4488                 }
4489                 END_PROFILE(SMBsetattrE);
4490                 return(outsize);
4491         } else if ((unix_times.actime != 0) && (unix_times.modtime == 0)) {
4492                 /* set modify time = to access time if modify time was 0 */
4493                 unix_times.modtime = unix_times.actime;
4494         }
4495
4496         /* Set the date on this file */
4497         if(file_utime(conn, fsp->fsp_name, &unix_times)) {
4498                 END_PROFILE(SMBsetattrE);
4499                 return ERROR_DOS(ERRDOS,ERRnoaccess);
4500         }
4501   
4502         DEBUG( 3, ( "reply_setattrE fnum=%d actime=%d modtime=%d\n",
4503                 fsp->fnum, (int)unix_times.actime, (int)unix_times.modtime ) );
4504
4505         END_PROFILE(SMBsetattrE);
4506         return(outsize);
4507 }
4508
4509
4510 /* Back from the dead for OS/2..... JRA. */
4511
4512 /****************************************************************************
4513  Reply to a SMBwritebmpx (write block multiplex primary) request.
4514 ****************************************************************************/
4515
4516 int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4517 {
4518         size_t numtowrite;
4519         ssize_t nwritten = -1;
4520         int outsize = 0;
4521         SMB_OFF_T startpos;
4522         size_t tcount;
4523         BOOL write_through;
4524         int smb_doff;
4525         char *data;
4526         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4527         START_PROFILE(SMBwriteBmpx);
4528
4529         CHECK_FSP(fsp,conn);
4530         CHECK_WRITE(fsp);
4531         CHECK_ERROR(fsp);
4532
4533         tcount = SVAL(inbuf,smb_vwv1);
4534         startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
4535         write_through = BITSETW(inbuf+smb_vwv7,0);
4536         numtowrite = SVAL(inbuf,smb_vwv10);
4537         smb_doff = SVAL(inbuf,smb_vwv11);
4538
4539         data = smb_base(inbuf) + smb_doff;
4540
4541         /* If this fails we need to send an SMBwriteC response,
4542                 not an SMBwritebmpx - set this up now so we don't forget */
4543         SCVAL(outbuf,smb_com,SMBwritec);
4544
4545         if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos,WRITE_LOCK,False)) {
4546                 END_PROFILE(SMBwriteBmpx);
4547                 return(ERROR_DOS(ERRDOS,ERRlock));
4548         }
4549
4550         nwritten = write_file(fsp,data,startpos,numtowrite);
4551
4552         if(lp_syncalways(SNUM(conn)) || write_through)
4553                 sync_file(conn,fsp);
4554   
4555         if(nwritten < (ssize_t)numtowrite) {
4556                 END_PROFILE(SMBwriteBmpx);
4557                 return(UNIXERROR(ERRHRD,ERRdiskfull));
4558         }
4559
4560         /* If the maximum to be written to this file
4561                 is greater than what we just wrote then set
4562                 up a secondary struct to be attached to this
4563                 fd, we will use this to cache error messages etc. */
4564
4565         if((ssize_t)tcount > nwritten) {
4566                 write_bmpx_struct *wbms;
4567                 if(fsp->wbmpx_ptr != NULL)
4568                         wbms = fsp->wbmpx_ptr; /* Use an existing struct */
4569                 else
4570                         wbms = (write_bmpx_struct *)malloc(sizeof(write_bmpx_struct));
4571                 if(!wbms) {
4572                         DEBUG(0,("Out of memory in reply_readmpx\n"));
4573                         END_PROFILE(SMBwriteBmpx);
4574                         return(ERROR_DOS(ERRSRV,ERRnoresource));
4575                 }
4576                 wbms->wr_mode = write_through;
4577                 wbms->wr_discard = False; /* No errors yet */
4578                 wbms->wr_total_written = nwritten;
4579                 wbms->wr_errclass = 0;
4580                 wbms->wr_error = 0;
4581                 fsp->wbmpx_ptr = wbms;
4582         }
4583
4584         /* We are returning successfully, set the message type back to
4585                 SMBwritebmpx */
4586         SCVAL(outbuf,smb_com,SMBwriteBmpx);
4587   
4588         outsize = set_message(outbuf,1,0,True);
4589   
4590         SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
4591   
4592         DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
4593                         fsp->fnum, (int)numtowrite, (int)nwritten ) );
4594
4595         if (write_through && tcount==nwritten) {
4596                 /* We need to send both a primary and a secondary response */
4597                 smb_setlen(outbuf,outsize - 4);
4598                 if (!send_smb(smbd_server_fd(),outbuf))
4599                         exit_server("reply_writebmpx: send_smb failed.");
4600
4601                 /* Now the secondary */
4602                 outsize = set_message(outbuf,1,0,True);
4603                 SCVAL(outbuf,smb_com,SMBwritec);
4604                 SSVAL(outbuf,smb_vwv0,nwritten);
4605         }
4606
4607         END_PROFILE(SMBwriteBmpx);
4608         return(outsize);
4609 }
4610
4611 /****************************************************************************
4612  Reply to a SMBwritebs (write block multiplex secondary) request.
4613 ****************************************************************************/
4614
4615 int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4616 {
4617         size_t numtowrite;
4618         ssize_t nwritten = -1;
4619         int outsize = 0;
4620         SMB_OFF_T startpos;
4621         size_t tcount;
4622         BOOL write_through;
4623         int smb_doff;
4624         char *data;
4625         write_bmpx_struct *wbms;
4626         BOOL send_response = False; 
4627         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4628         START_PROFILE(SMBwriteBs);
4629
4630         CHECK_FSP(fsp,conn);
4631         CHECK_WRITE(fsp);
4632
4633         tcount = SVAL(inbuf,smb_vwv1);
4634         startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
4635         numtowrite = SVAL(inbuf,smb_vwv6);
4636         smb_doff = SVAL(inbuf,smb_vwv7);
4637
4638         data = smb_base(inbuf) + smb_doff;
4639
4640         /* We need to send an SMBwriteC response, not an SMBwritebs */
4641         SCVAL(outbuf,smb_com,SMBwritec);
4642
4643         /* This fd should have an auxiliary struct attached,
4644                 check that it does */
4645         wbms = fsp->wbmpx_ptr;
4646         if(!wbms) {
4647                 END_PROFILE(SMBwriteBs);
4648                 return(-1);
4649         }
4650
4651         /* If write through is set we can return errors, else we must cache them */
4652         write_through = wbms->wr_mode;
4653
4654         /* Check for an earlier error */
4655         if(wbms->wr_discard) {
4656                 END_PROFILE(SMBwriteBs);
4657                 return -1; /* Just discard the packet */
4658         }
4659
4660         nwritten = write_file(fsp,data,startpos,numtowrite);
4661
4662         if(lp_syncalways(SNUM(conn)) || write_through)
4663                 sync_file(conn,fsp);
4664   
4665         if (nwritten < (ssize_t)numtowrite) {
4666                 if(write_through) {
4667                         /* We are returning an error - we can delete the aux struct */
4668                         if (wbms)
4669                                 free((char *)wbms);
4670                         fsp->wbmpx_ptr = NULL;
4671                         END_PROFILE(SMBwriteBs);
4672                         return(ERROR_DOS(ERRHRD,ERRdiskfull));
4673                 }
4674                 END_PROFILE(SMBwriteBs);
4675                 return(CACHE_ERROR(wbms,ERRHRD,ERRdiskfull));
4676         }
4677
4678         /* Increment the total written, if this matches tcount
4679                 we can discard the auxiliary struct (hurrah !) and return a writeC */
4680         wbms->wr_total_written += nwritten;
4681         if(wbms->wr_total_written >= tcount) {
4682                 if (write_through) {
4683                         outsize = set_message(outbuf,1,0,True);
4684                         SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);    
4685                         send_response = True;
4686                 }
4687
4688                 free((char *)wbms);
4689                 fsp->wbmpx_ptr = NULL;
4690         }
4691
4692         if(send_response) {
4693                 END_PROFILE(SMBwriteBs);
4694                 return(outsize);
4695         }
4696
4697         END_PROFILE(SMBwriteBs);
4698         return(-1);
4699 }
4700
4701 /****************************************************************************
4702  Reply to a SMBgetattrE.
4703 ****************************************************************************/
4704
4705 int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4706 {
4707         SMB_STRUCT_STAT sbuf;
4708         int outsize = 0;
4709         int mode;
4710         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4711         START_PROFILE(SMBgetattrE);
4712
4713         outsize = set_message(outbuf,11,0,True);
4714
4715         if(!fsp || (fsp->conn != conn)) {
4716                 END_PROFILE(SMBgetattrE);
4717                 return ERROR_DOS(ERRDOS,ERRbadfid);
4718         }
4719
4720         /* Do an fstat on this file */
4721         if(fsp_stat(fsp, &sbuf)) {
4722                 END_PROFILE(SMBgetattrE);
4723                 return(UNIXERROR(ERRDOS,ERRnoaccess));
4724         }
4725   
4726         mode = dos_mode(conn,fsp->fsp_name,&sbuf);
4727   
4728         /*
4729          * Convert the times into dos times. Set create
4730          * date to be last modify date as UNIX doesn't save
4731          * this.
4732          */
4733
4734         put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
4735         put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
4736         put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
4737
4738         if (mode & aDIR) {
4739                 SIVAL(outbuf,smb_vwv6,0);
4740                 SIVAL(outbuf,smb_vwv8,0);
4741         } else {
4742                 uint32 allocation_size = get_allocation_size(fsp, &sbuf);
4743                 SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
4744                 SIVAL(outbuf,smb_vwv8,allocation_size);
4745         }
4746         SSVAL(outbuf,smb_vwv10, mode);
4747   
4748         DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
4749   
4750         END_PROFILE(SMBgetattrE);
4751         return(outsize);
4752 }