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