011186ba89caf0b1309650a5da8fe858ae5ed404
[samba.git] / source3 / 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 = NT_STATUS_OK;
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 (numtowrite && 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         if (numtowrite) {
2197                 status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)numtowrite, 
2198                                    (SMB_BIG_UINT)startpos);
2199                 if (NT_STATUS_V(status)) {
2200                         END_PROFILE(SMBwriteunlock);
2201                         return ERROR_NT(status);
2202                 }
2203         }
2204         
2205         outsize = set_message(outbuf,1,0,True);
2206         
2207         SSVAL(outbuf,smb_vwv0,nwritten);
2208         
2209         DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
2210                  fsp->fnum, (int)numtowrite, (int)nwritten));
2211         
2212         END_PROFILE(SMBwriteunlock);
2213         return outsize;
2214 }
2215
2216 /****************************************************************************
2217  Reply to a write.
2218 ****************************************************************************/
2219
2220 int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int dum_buffsize)
2221 {
2222         size_t numtowrite;
2223         ssize_t nwritten = -1;
2224         SMB_OFF_T startpos;
2225         char *data;
2226         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2227         int outsize = 0;
2228         START_PROFILE(SMBwrite);
2229
2230         /* If it's an IPC, pass off the pipe handler. */
2231         if (IS_IPC(conn)) {
2232                 END_PROFILE(SMBwrite);
2233                 return reply_pipe_write(inbuf,outbuf,size,dum_buffsize);
2234         }
2235
2236         CHECK_FSP(fsp,conn);
2237         CHECK_WRITE(fsp);
2238
2239         numtowrite = SVAL(inbuf,smb_vwv1);
2240         startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2241         data = smb_buf(inbuf) + 3;
2242   
2243         if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2244                 END_PROFILE(SMBwrite);
2245                 return ERROR_DOS(ERRDOS,ERRlock);
2246         }
2247
2248         /*
2249          * X/Open SMB protocol says that if smb_vwv1 is
2250          * zero then the file size should be extended or
2251          * truncated to the size given in smb_vwv[2-3].
2252          */
2253
2254         if(numtowrite == 0) {
2255                 /*
2256                  * This is actually an allocate call, and set EOF. JRA.
2257                  */
2258                 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
2259                 if (nwritten < 0) {
2260                         END_PROFILE(SMBwrite);
2261                         return ERROR_NT(NT_STATUS_DISK_FULL);
2262                 }
2263                 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
2264                 if (nwritten < 0) {
2265                         END_PROFILE(SMBwrite);
2266                         return ERROR_NT(NT_STATUS_DISK_FULL);
2267                 }
2268         } else
2269                 nwritten = write_file(fsp,data,startpos,numtowrite);
2270   
2271         if (lp_syncalways(SNUM(conn)))
2272                 sync_file(conn,fsp);
2273
2274         if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2275                 END_PROFILE(SMBwrite);
2276                 return(UNIXERROR(ERRHRD,ERRdiskfull));
2277         }
2278
2279         outsize = set_message(outbuf,1,0,True);
2280   
2281         SSVAL(outbuf,smb_vwv0,nwritten);
2282
2283         if (nwritten < (ssize_t)numtowrite) {
2284                 SCVAL(outbuf,smb_rcls,ERRHRD);
2285                 SSVAL(outbuf,smb_err,ERRdiskfull);      
2286         }
2287   
2288         DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
2289
2290         END_PROFILE(SMBwrite);
2291         return(outsize);
2292 }
2293
2294 /****************************************************************************
2295  Reply to a write and X.
2296 ****************************************************************************/
2297
2298 int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2299 {
2300         files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2301         SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2302         size_t numtowrite = SVAL(inbuf,smb_vwv10);
2303         BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
2304         ssize_t nwritten = -1;
2305         unsigned int smb_doff = SVAL(inbuf,smb_vwv11);
2306         unsigned int smblen = smb_len(inbuf);
2307         char *data;
2308         BOOL large_writeX = ((CVAL(inbuf,smb_wct) == 14) && (smblen > 0xFFFF));
2309         START_PROFILE(SMBwriteX);
2310
2311         /* If it's an IPC, pass off the pipe handler. */
2312         if (IS_IPC(conn)) {
2313                 END_PROFILE(SMBwriteX);
2314                 return reply_pipe_write_and_X(inbuf,outbuf,length,bufsize);
2315         }
2316
2317         CHECK_FSP(fsp,conn);
2318         CHECK_WRITE(fsp);
2319
2320         /* Deal with possible LARGE_WRITEX */
2321         if (large_writeX)
2322                 numtowrite |= ((((size_t)SVAL(inbuf,smb_vwv9)) & 1 )<<16);
2323
2324         if(smb_doff > smblen || (smb_doff + numtowrite > smblen)) {
2325                 END_PROFILE(SMBwriteX);
2326                 return ERROR_DOS(ERRDOS,ERRbadmem);
2327         }
2328
2329         data = smb_base(inbuf) + smb_doff;
2330
2331         if(CVAL(inbuf,smb_wct) == 14) {
2332 #ifdef LARGE_SMB_OFF_T
2333                 /*
2334                  * This is a large offset (64 bit) write.
2335                  */
2336                 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv12)) << 32);
2337
2338 #else /* !LARGE_SMB_OFF_T */
2339
2340                 /*
2341                  * Ensure we haven't been sent a >32 bit offset.
2342                  */
2343
2344                 if(IVAL(inbuf,smb_vwv12) != 0) {
2345                         DEBUG(0,("reply_write_and_X - large offset (%x << 32) used and we don't support \
2346 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv12) ));
2347                         END_PROFILE(SMBwriteX);
2348                         return ERROR_DOS(ERRDOS,ERRbadaccess);
2349                 }
2350
2351 #endif /* LARGE_SMB_OFF_T */
2352         }
2353
2354         if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2355                 END_PROFILE(SMBwriteX);
2356                 return ERROR_DOS(ERRDOS,ERRlock);
2357         }
2358
2359         /* X/Open SMB protocol says that, unlike SMBwrite
2360         if the length is zero then NO truncation is
2361         done, just a write of zero. To truncate a file,
2362         use SMBwrite. */
2363
2364         if(numtowrite == 0)
2365                 nwritten = 0;
2366         else
2367                 nwritten = write_file(fsp,data,startpos,numtowrite);
2368   
2369         if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2370                 END_PROFILE(SMBwriteX);
2371                 return(UNIXERROR(ERRHRD,ERRdiskfull));
2372         }
2373
2374         set_message(outbuf,6,0,True);
2375   
2376         SSVAL(outbuf,smb_vwv2,nwritten);
2377         if (large_writeX)
2378                 SSVAL(outbuf,smb_vwv4,(nwritten>>16)&1);
2379
2380         if (nwritten < (ssize_t)numtowrite) {
2381                 SCVAL(outbuf,smb_rcls,ERRHRD);
2382                 SSVAL(outbuf,smb_err,ERRdiskfull);      
2383         }
2384
2385         DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
2386                 fsp->fnum, (int)numtowrite, (int)nwritten));
2387
2388         if (lp_syncalways(SNUM(conn)) || write_through)
2389                 sync_file(conn,fsp);
2390
2391         END_PROFILE(SMBwriteX);
2392         return chain_reply(inbuf,outbuf,length,bufsize);
2393 }
2394
2395 /****************************************************************************
2396  Reply to a lseek.
2397 ****************************************************************************/
2398
2399 int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2400 {
2401         SMB_OFF_T startpos;
2402         SMB_OFF_T res= -1;
2403         int mode,umode;
2404         int outsize = 0;
2405         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2406         START_PROFILE(SMBlseek);
2407
2408         CHECK_FSP(fsp,conn);
2409
2410         flush_write_cache(fsp, SEEK_FLUSH);
2411
2412         mode = SVAL(inbuf,smb_vwv1) & 3;
2413         /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
2414         startpos = (SMB_OFF_T)IVALS(inbuf,smb_vwv2);
2415
2416         switch (mode) {
2417                 case 0:
2418                         umode = SEEK_SET;
2419                         res = startpos;
2420                         break;
2421                 case 1:
2422                         umode = SEEK_CUR;
2423                         res = fsp->pos + startpos;
2424                         break;
2425                 case 2:
2426                         umode = SEEK_END;
2427                         break;
2428                 default:
2429                         umode = SEEK_SET;
2430                         res = startpos;
2431                         break;
2432         }
2433
2434         if (umode == SEEK_END) {
2435                 if((res = SMB_VFS_LSEEK(fsp,fsp->fd,startpos,umode)) == -1) {
2436                         if(errno == EINVAL) {
2437                                 SMB_OFF_T current_pos = startpos;
2438                                 SMB_STRUCT_STAT sbuf;
2439
2440                                 if(SMB_VFS_FSTAT(fsp,fsp->fd, &sbuf) == -1) {
2441                                         END_PROFILE(SMBlseek);
2442                                         return(UNIXERROR(ERRDOS,ERRnoaccess));
2443                                 }
2444
2445                                 current_pos += sbuf.st_size;
2446                                 if(current_pos < 0)
2447                                         res = SMB_VFS_LSEEK(fsp,fsp->fd,0,SEEK_SET);
2448                         }
2449                 }
2450
2451                 if(res == -1) {
2452                         END_PROFILE(SMBlseek);
2453                         return(UNIXERROR(ERRDOS,ERRnoaccess));
2454                 }
2455         }
2456
2457         fsp->pos = res;
2458   
2459         outsize = set_message(outbuf,2,0,True);
2460         SIVAL(outbuf,smb_vwv0,res);
2461   
2462         DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
2463                 fsp->fnum, (double)startpos, (double)res, mode));
2464
2465         END_PROFILE(SMBlseek);
2466         return(outsize);
2467 }
2468
2469 /****************************************************************************
2470  Reply to a flush.
2471 ****************************************************************************/
2472
2473 int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2474 {
2475         int outsize = set_message(outbuf,0,0,True);
2476         uint16 fnum = SVAL(inbuf,smb_vwv0);
2477         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2478         START_PROFILE(SMBflush);
2479
2480         if (fnum != 0xFFFF)
2481                 CHECK_FSP(fsp,conn);
2482         
2483         if (!fsp) {
2484                 file_sync_all(conn);
2485         } else {
2486                 sync_file(conn,fsp);
2487         }
2488         
2489         DEBUG(3,("flush\n"));
2490         END_PROFILE(SMBflush);
2491         return(outsize);
2492 }
2493
2494 /****************************************************************************
2495  Reply to a exit.
2496 ****************************************************************************/
2497
2498 int reply_exit(connection_struct *conn, 
2499                char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2500 {
2501         int outsize;
2502         START_PROFILE(SMBexit);
2503
2504         file_close_pid(SVAL(inbuf,smb_pid));
2505
2506         outsize = set_message(outbuf,0,0,True);
2507
2508         DEBUG(3,("exit\n"));
2509
2510         END_PROFILE(SMBexit);
2511         return(outsize);
2512 }
2513
2514 /****************************************************************************
2515  Reply to a close - has to deal with closing a directory opened by NT SMB's.
2516 ****************************************************************************/
2517
2518 int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size,
2519                 int dum_buffsize)
2520 {
2521         extern struct current_user current_user;
2522         int outsize = 0;
2523         time_t mtime;
2524         int32 eclass = 0, err = 0;
2525         files_struct *fsp = NULL;
2526         START_PROFILE(SMBclose);
2527
2528         outsize = set_message(outbuf,0,0,True);
2529
2530         /* If it's an IPC, pass off to the pipe handler. */
2531         if (IS_IPC(conn)) {
2532                 END_PROFILE(SMBclose);
2533                 return reply_pipe_close(conn, inbuf,outbuf);
2534         }
2535
2536         fsp = file_fsp(inbuf,smb_vwv0);
2537
2538         /*
2539          * We can only use CHECK_FSP if we know it's not a directory.
2540          */
2541
2542         if(!fsp || (fsp->conn != conn) || (fsp->vuid != current_user.vuid)) {
2543                 END_PROFILE(SMBclose);
2544                 return ERROR_DOS(ERRDOS,ERRbadfid);
2545         }
2546
2547         if(fsp->is_directory) {
2548                 /*
2549                  * Special case - close NT SMB directory handle.
2550                  */
2551                 DEBUG(3,("close %s fnum=%d\n", fsp->is_directory ? "directory" : "stat file open", fsp->fnum));
2552                 close_file(fsp,True);
2553         } else {
2554                 /*
2555                  * Close ordinary file.
2556                  */
2557                 int close_err;
2558                 pstring file_name;
2559
2560                 /* Save the name for time set in close. */
2561                 pstrcpy( file_name, fsp->fsp_name);
2562
2563                 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
2564                          fsp->fd, fsp->fnum,
2565                          conn->num_files_open));
2566  
2567                 /*
2568                  * close_file() returns the unix errno if an error
2569                  * was detected on close - normally this is due to
2570                  * a disk full error. If not then it was probably an I/O error.
2571                  */
2572  
2573                 if((close_err = close_file(fsp,True)) != 0) {
2574                         errno = close_err;
2575                         END_PROFILE(SMBclose);
2576                         return (UNIXERROR(ERRHRD,ERRgeneral));
2577                 }
2578
2579                 /*
2580                  * Now take care of any time sent in the close.
2581                  */
2582
2583                 mtime = make_unix_date3(inbuf+smb_vwv1);
2584                 
2585                 /* try and set the date */
2586                 set_filetime(conn, file_name, mtime);
2587
2588         }  
2589
2590         /* We have a cached error */
2591         if(eclass || err) {
2592                 END_PROFILE(SMBclose);
2593                 return ERROR_DOS(eclass,err);
2594         }
2595
2596         END_PROFILE(SMBclose);
2597         return(outsize);
2598 }
2599
2600 /****************************************************************************
2601  Reply to a writeclose (Core+ protocol).
2602 ****************************************************************************/
2603
2604 int reply_writeclose(connection_struct *conn,
2605                      char *inbuf,char *outbuf, int size, int dum_buffsize)
2606 {
2607         size_t numtowrite;
2608         ssize_t nwritten = -1;
2609         int outsize = 0;
2610         int close_err = 0;
2611         SMB_OFF_T startpos;
2612         char *data;
2613         time_t mtime;
2614         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2615         START_PROFILE(SMBwriteclose);
2616
2617         CHECK_FSP(fsp,conn);
2618         CHECK_WRITE(fsp);
2619
2620         numtowrite = SVAL(inbuf,smb_vwv1);
2621         startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2622         mtime = make_unix_date3(inbuf+smb_vwv4);
2623         data = smb_buf(inbuf) + 1;
2624   
2625         if (numtowrite && is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2626                 END_PROFILE(SMBwriteclose);
2627                 return ERROR_DOS(ERRDOS,ERRlock);
2628         }
2629   
2630         nwritten = write_file(fsp,data,startpos,numtowrite);
2631
2632         set_filetime(conn, fsp->fsp_name,mtime);
2633   
2634         /*
2635          * More insanity. W2K only closes the file if writelen > 0.
2636          * JRA.
2637          */
2638
2639         if (numtowrite) {
2640                 DEBUG(3,("reply_writeclose: zero length write doesn't close file %s\n",
2641                         fsp->fsp_name ));
2642                 close_err = close_file(fsp,True);
2643         }
2644
2645         DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
2646                  fsp->fnum, (int)numtowrite, (int)nwritten,
2647                  conn->num_files_open));
2648   
2649         if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2650                 END_PROFILE(SMBwriteclose);
2651                 return(UNIXERROR(ERRHRD,ERRdiskfull));
2652         }
2653  
2654         if(close_err != 0) {
2655                 errno = close_err;
2656                 END_PROFILE(SMBwriteclose);
2657                 return(UNIXERROR(ERRHRD,ERRgeneral));
2658         }
2659  
2660         outsize = set_message(outbuf,1,0,True);
2661   
2662         SSVAL(outbuf,smb_vwv0,nwritten);
2663         END_PROFILE(SMBwriteclose);
2664         return(outsize);
2665 }
2666
2667 /****************************************************************************
2668  Reply to a lock.
2669 ****************************************************************************/
2670
2671 int reply_lock(connection_struct *conn,
2672                char *inbuf,char *outbuf, int length, int dum_buffsize)
2673 {
2674         int outsize = set_message(outbuf,0,0,True);
2675         SMB_BIG_UINT count,offset;
2676         NTSTATUS status;
2677         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2678         BOOL my_lock_ctx = False;
2679
2680         START_PROFILE(SMBlock);
2681
2682         CHECK_FSP(fsp,conn);
2683
2684         release_level_2_oplocks_on_change(fsp);
2685
2686         count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
2687         offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
2688
2689         DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2690                  fsp->fd, fsp->fnum, (double)offset, (double)count));
2691
2692         status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid), count, offset, WRITE_LOCK, &my_lock_ctx);
2693         if (NT_STATUS_V(status)) {
2694 #if 0
2695                 /* Tests using Samba4 against W2K show this call never creates a blocking lock. */
2696                 if (lp_blocking_locks(SNUM(conn)) && !my_lock_ctx && ERROR_WAS_LOCK_DENIED(status)) {
2697                         /*
2698                          * A blocking lock was requested. Package up
2699                          * this smb into a queued request and push it
2700                          * onto the blocking lock queue.
2701                          */
2702                         if(push_blocking_lock_request(inbuf, length, -1, 0, SVAL(inbuf,smb_pid), offset, count)) {
2703                                 END_PROFILE(SMBlock);
2704                                 return -1;
2705                         }
2706                 }
2707 #endif
2708                 END_PROFILE(SMBlock);
2709                 return ERROR_NT(status);
2710         }
2711
2712         END_PROFILE(SMBlock);
2713         return(outsize);
2714 }
2715
2716 /****************************************************************************
2717  Reply to a unlock.
2718 ****************************************************************************/
2719
2720 int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size, 
2721                  int dum_buffsize)
2722 {
2723         int outsize = set_message(outbuf,0,0,True);
2724         SMB_BIG_UINT count,offset;
2725         NTSTATUS status;
2726         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2727         START_PROFILE(SMBunlock);
2728
2729         CHECK_FSP(fsp,conn);
2730         
2731         count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
2732         offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
2733         
2734         status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), count, offset);
2735         if (NT_STATUS_V(status)) {
2736                 END_PROFILE(SMBunlock);
2737                 return ERROR_NT(status);
2738         }
2739
2740         DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2741                     fsp->fd, fsp->fnum, (double)offset, (double)count ) );
2742         
2743         END_PROFILE(SMBunlock);
2744         return(outsize);
2745 }
2746
2747 /****************************************************************************
2748  Reply to a tdis.
2749 ****************************************************************************/
2750
2751 int reply_tdis(connection_struct *conn, 
2752                char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2753 {
2754         int outsize = set_message(outbuf,0,0,True);
2755         uint16 vuid;
2756         START_PROFILE(SMBtdis);
2757
2758         vuid = SVAL(inbuf,smb_uid);
2759
2760         if (!conn) {
2761                 DEBUG(4,("Invalid connection in tdis\n"));
2762                 END_PROFILE(SMBtdis);
2763                 return ERROR_DOS(ERRSRV,ERRinvnid);
2764         }
2765
2766         conn->used = False;
2767
2768         close_cnum(conn,vuid);
2769   
2770         END_PROFILE(SMBtdis);
2771         return outsize;
2772 }
2773
2774 /****************************************************************************
2775  Reply to a echo.
2776 ****************************************************************************/
2777
2778 int reply_echo(connection_struct *conn,
2779                char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2780 {
2781         int smb_reverb = SVAL(inbuf,smb_vwv0);
2782         int seq_num;
2783         unsigned int data_len = smb_buflen(inbuf);
2784         int outsize = set_message(outbuf,1,data_len,True);
2785         START_PROFILE(SMBecho);
2786
2787         if (data_len > BUFFER_SIZE) {
2788                 DEBUG(0,("reply_echo: data_len too large.\n"));
2789                 END_PROFILE(SMBecho);
2790                 return -1;
2791         }
2792
2793         /* copy any incoming data back out */
2794         if (data_len > 0)
2795                 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
2796
2797         if (smb_reverb > 100) {
2798                 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
2799                 smb_reverb = 100;
2800         }
2801
2802         for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
2803                 SSVAL(outbuf,smb_vwv0,seq_num);
2804
2805                 smb_setlen(outbuf,outsize - 4);
2806
2807                 if (!send_smb(smbd_server_fd(),outbuf))
2808                         exit_server("reply_echo: send_smb failed.");
2809         }
2810
2811         DEBUG(3,("echo %d times\n", smb_reverb));
2812
2813         smb_echo_count++;
2814
2815         END_PROFILE(SMBecho);
2816         return -1;
2817 }
2818
2819 /****************************************************************************
2820  Reply to a printopen.
2821 ****************************************************************************/
2822
2823 int reply_printopen(connection_struct *conn, 
2824                     char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2825 {
2826         int outsize = 0;
2827         files_struct *fsp;
2828         START_PROFILE(SMBsplopen);
2829         
2830         if (!CAN_PRINT(conn)) {
2831                 END_PROFILE(SMBsplopen);
2832                 return ERROR_DOS(ERRDOS,ERRnoaccess);
2833         }
2834
2835         /* Open for exclusive use, write only. */
2836         fsp = print_fsp_open(conn, NULL);
2837
2838         if (!fsp) {
2839                 END_PROFILE(SMBsplopen);
2840                 return(UNIXERROR(ERRDOS,ERRnoaccess));
2841         }
2842
2843         outsize = set_message(outbuf,1,0,True);
2844         SSVAL(outbuf,smb_vwv0,fsp->fnum);
2845   
2846         DEBUG(3,("openprint fd=%d fnum=%d\n",
2847                  fsp->fd, fsp->fnum));
2848
2849         END_PROFILE(SMBsplopen);
2850         return(outsize);
2851 }
2852
2853 /****************************************************************************
2854  Reply to a printclose.
2855 ****************************************************************************/
2856
2857 int reply_printclose(connection_struct *conn,
2858                      char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2859 {
2860         int outsize = set_message(outbuf,0,0,True);
2861         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2862         int close_err = 0;
2863         START_PROFILE(SMBsplclose);
2864
2865         CHECK_FSP(fsp,conn);
2866
2867         if (!CAN_PRINT(conn)) {
2868                 END_PROFILE(SMBsplclose);
2869                 return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
2870         }
2871   
2872         DEBUG(3,("printclose fd=%d fnum=%d\n",
2873                  fsp->fd,fsp->fnum));
2874   
2875         close_err = close_file(fsp,True);
2876
2877         if(close_err != 0) {
2878                 errno = close_err;
2879                 END_PROFILE(SMBsplclose);
2880                 return(UNIXERROR(ERRHRD,ERRgeneral));
2881         }
2882
2883         END_PROFILE(SMBsplclose);
2884         return(outsize);
2885 }
2886
2887 /****************************************************************************
2888  Reply to a printqueue.
2889 ****************************************************************************/
2890
2891 int reply_printqueue(connection_struct *conn,
2892                      char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2893 {
2894         int outsize = set_message(outbuf,2,3,True);
2895         int max_count = SVAL(inbuf,smb_vwv0);
2896         int start_index = SVAL(inbuf,smb_vwv1);
2897         START_PROFILE(SMBsplretq);
2898
2899         /* we used to allow the client to get the cnum wrong, but that
2900            is really quite gross and only worked when there was only
2901            one printer - I think we should now only accept it if they
2902            get it right (tridge) */
2903         if (!CAN_PRINT(conn)) {
2904                 END_PROFILE(SMBsplretq);
2905                 return ERROR_DOS(ERRDOS,ERRnoaccess);
2906         }
2907
2908         SSVAL(outbuf,smb_vwv0,0);
2909         SSVAL(outbuf,smb_vwv1,0);
2910         SCVAL(smb_buf(outbuf),0,1);
2911         SSVAL(smb_buf(outbuf),1,0);
2912   
2913         DEBUG(3,("printqueue start_index=%d max_count=%d\n",
2914                  start_index, max_count));
2915
2916         {
2917                 print_queue_struct *queue = NULL;
2918                 print_status_struct status;
2919                 char *p = smb_buf(outbuf) + 3;
2920                 int count = print_queue_status(SNUM(conn), &queue, &status);
2921                 int num_to_get = ABS(max_count);
2922                 int first = (max_count>0?start_index:start_index+max_count+1);
2923                 int i;
2924
2925                 if (first >= count)
2926                         num_to_get = 0;
2927                 else
2928                         num_to_get = MIN(num_to_get,count-first);
2929     
2930
2931                 for (i=first;i<first+num_to_get;i++) {
2932                         put_dos_date2(p,0,queue[i].time);
2933                         SCVAL(p,4,(queue[i].status==LPQ_PRINTING?2:3));
2934                         SSVAL(p,5, queue[i].job);
2935                         SIVAL(p,7,queue[i].size);
2936                         SCVAL(p,11,0);
2937                         srvstr_push(outbuf, p+12, queue[i].fs_user, 16, STR_ASCII);
2938                         p += 28;
2939                 }
2940
2941                 if (count > 0) {
2942                         outsize = set_message(outbuf,2,28*count+3,False); 
2943                         SSVAL(outbuf,smb_vwv0,count);
2944                         SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
2945                         SCVAL(smb_buf(outbuf),0,1);
2946                         SSVAL(smb_buf(outbuf),1,28*count);
2947                 }
2948
2949                 SAFE_FREE(queue);
2950           
2951                 DEBUG(3,("%d entries returned in queue\n",count));
2952         }
2953   
2954         END_PROFILE(SMBsplretq);
2955         return(outsize);
2956 }
2957
2958 /****************************************************************************
2959  Reply to a printwrite.
2960 ****************************************************************************/
2961
2962 int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2963 {
2964         int numtowrite;
2965         int outsize = set_message(outbuf,0,0,True);
2966         char *data;
2967         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2968
2969         START_PROFILE(SMBsplwr);
2970   
2971         if (!CAN_PRINT(conn)) {
2972                 END_PROFILE(SMBsplwr);
2973                 return ERROR_DOS(ERRDOS,ERRnoaccess);
2974         }
2975
2976         CHECK_FSP(fsp,conn);
2977         CHECK_WRITE(fsp);
2978
2979         numtowrite = SVAL(smb_buf(inbuf),1);
2980         data = smb_buf(inbuf) + 3;
2981   
2982         if (write_file(fsp,data,-1,numtowrite) != numtowrite) {
2983                 END_PROFILE(SMBsplwr);
2984                 return(UNIXERROR(ERRHRD,ERRdiskfull));
2985         }
2986
2987         DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
2988   
2989         END_PROFILE(SMBsplwr);
2990         return(outsize);
2991 }
2992
2993 /****************************************************************************
2994  The guts of the mkdir command, split out so it may be called by the NT SMB
2995  code. 
2996 ****************************************************************************/
2997
2998 NTSTATUS mkdir_internal(connection_struct *conn, pstring directory)
2999 {
3000         BOOL bad_path = False;
3001         SMB_STRUCT_STAT sbuf;
3002         int ret= -1;
3003         
3004         unix_convert(directory,conn,0,&bad_path,&sbuf);
3005
3006         if (ms_has_wild(directory)) {
3007                 return NT_STATUS_OBJECT_NAME_INVALID;
3008         }
3009
3010         if (check_name(directory, conn))
3011                 ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory));
3012         
3013         if (ret == -1) {
3014                 NTSTATUS nterr = NT_STATUS_OK;
3015                 if(errno == ENOENT) {
3016                         unix_ERR_class = ERRDOS;
3017                         if (bad_path) {
3018                                 unix_ERR_code = ERRbadpath;
3019                                 nterr = NT_STATUS_OBJECT_PATH_NOT_FOUND;
3020                         } else {
3021                                 unix_ERR_code = ERRbadfile;
3022                                 nterr = NT_STATUS_OBJECT_NAME_NOT_FOUND;
3023                         }
3024                 }
3025                 if (!NT_STATUS_IS_OK(nterr))
3026                         return nterr;
3027                 return map_nt_error_from_unix(errno);
3028         }
3029         
3030         return NT_STATUS_OK;
3031 }
3032
3033 /****************************************************************************
3034  Reply to a mkdir.
3035 ****************************************************************************/
3036
3037 int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3038 {
3039         pstring directory;
3040         int outsize;
3041         NTSTATUS status;
3042         START_PROFILE(SMBmkdir);
3043  
3044         srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), STR_TERMINATE,&status);
3045         if (!NT_STATUS_IS_OK(status)) {
3046                 END_PROFILE(SMBmkdir);
3047                 return ERROR_NT(status);
3048         }
3049
3050         RESOLVE_DFSPATH(directory, conn, inbuf, outbuf);
3051
3052         status = mkdir_internal(conn, directory);
3053         if (!NT_STATUS_IS_OK(status)) {
3054                 END_PROFILE(SMBmkdir);
3055                 return ERROR_NT(status);
3056         }
3057
3058         outsize = set_message(outbuf,0,0,True);
3059
3060         DEBUG( 3, ( "mkdir %s ret=%d\n", directory, outsize ) );
3061
3062         END_PROFILE(SMBmkdir);
3063         return(outsize);
3064 }
3065
3066 /****************************************************************************
3067  Static function used by reply_rmdir to delete an entire directory
3068  tree recursively. Return False on ok, True on fail.
3069 ****************************************************************************/
3070
3071 static BOOL recursive_rmdir(connection_struct *conn, char *directory)
3072 {
3073         const char *dname = NULL;
3074         BOOL ret = False;
3075         void *dirptr = OpenDir(conn, directory, False);
3076
3077         if(dirptr == NULL)
3078                 return True;
3079
3080         while((dname = ReadDirName(dirptr))) {
3081                 pstring fullname;
3082                 SMB_STRUCT_STAT st;
3083
3084                 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3085                         continue;
3086
3087                 /* Construct the full name. */
3088                 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
3089                         errno = ENOMEM;
3090                         ret = True;
3091                         break;
3092                 }
3093
3094                 pstrcpy(fullname, directory);
3095                 pstrcat(fullname, "/");
3096                 pstrcat(fullname, dname);
3097
3098                 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
3099                         ret = True;
3100                         break;
3101                 }
3102
3103                 if(st.st_mode & S_IFDIR) {
3104                         if(recursive_rmdir(conn, fullname)!=0) {
3105                                 ret = True;
3106                                 break;
3107                         }
3108                         if(SMB_VFS_RMDIR(conn,fullname) != 0) {
3109                                 ret = True;
3110                                 break;
3111                         }
3112                 } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
3113                         ret = True;
3114                         break;
3115                 }
3116         }
3117         CloseDir(dirptr);
3118         return ret;
3119 }
3120
3121 /****************************************************************************
3122  The internals of the rmdir code - called elsewhere.
3123 ****************************************************************************/
3124
3125 BOOL rmdir_internals(connection_struct *conn, char *directory)
3126 {
3127         BOOL ok;
3128
3129         ok = (SMB_VFS_RMDIR(conn,directory) == 0);
3130         if(!ok && ((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
3131                 /* 
3132                  * Check to see if the only thing in this directory are
3133                  * vetoed files/directories. If so then delete them and
3134                  * retry. If we fail to delete any of them (and we *don't*
3135                  * do a recursive delete) then fail the rmdir.
3136                  */
3137                 BOOL all_veto_files = True;
3138                 const char *dname;
3139                 void *dirptr = OpenDir(conn, directory, False);
3140
3141                 if(dirptr != NULL) {
3142                         int dirpos = TellDir(dirptr);
3143                         while ((dname = ReadDirName(dirptr))) {
3144                                 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3145                                         continue;
3146                                 if(!IS_VETO_PATH(conn, dname)) {
3147                                         all_veto_files = False;
3148                                         break;
3149                                 }
3150                         }
3151
3152                         if(all_veto_files) {
3153                                 SeekDir(dirptr,dirpos);
3154                                 while ((dname = ReadDirName(dirptr))) {
3155                                         pstring fullname;
3156                                         SMB_STRUCT_STAT st;
3157
3158                                         if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3159                                                 continue;
3160
3161                                         /* Construct the full name. */
3162                                         if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
3163                                                 errno = ENOMEM;
3164                                                 break;
3165                                         }
3166
3167                                         pstrcpy(fullname, directory);
3168                                         pstrcat(fullname, "/");
3169                                         pstrcat(fullname, dname);
3170                      
3171                                         if(SMB_VFS_LSTAT(conn,fullname, &st) != 0)
3172                                                 break;
3173                                         if(st.st_mode & S_IFDIR) {
3174                                                 if(lp_recursive_veto_delete(SNUM(conn))) {
3175                                                         if(recursive_rmdir(conn, fullname) != 0)
3176                                                                 break;
3177                                                 }
3178                                                 if(SMB_VFS_RMDIR(conn,fullname) != 0)
3179                                                         break;
3180                                         } else if(SMB_VFS_UNLINK(conn,fullname) != 0)
3181                                                 break;
3182                                 }
3183                                 CloseDir(dirptr);
3184                                 /* Retry the rmdir */
3185                                 ok = (SMB_VFS_RMDIR(conn,directory) == 0);
3186                         } else {
3187                                 CloseDir(dirptr);
3188                         }
3189                 } else {
3190                         errno = ENOTEMPTY;
3191                 }
3192         }
3193
3194         if (!ok)
3195                 DEBUG(3,("rmdir_internals: couldn't remove directory %s : %s\n", directory,strerror(errno)));
3196
3197         return ok;
3198 }
3199
3200 /****************************************************************************
3201  Reply to a rmdir.
3202 ****************************************************************************/
3203
3204 int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3205 {
3206         pstring directory;
3207         int outsize = 0;
3208         BOOL ok = False;
3209         BOOL bad_path = False;
3210         SMB_STRUCT_STAT sbuf;
3211         NTSTATUS status;
3212         START_PROFILE(SMBrmdir);
3213
3214         srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), STR_TERMINATE,&status);
3215         if (!NT_STATUS_IS_OK(status)) {
3216                 END_PROFILE(SMBrmdir);
3217                 return ERROR_NT(status);
3218         }
3219
3220         RESOLVE_DFSPATH(directory, conn, inbuf, outbuf)
3221
3222         unix_convert(directory,conn, NULL,&bad_path,&sbuf);
3223   
3224         if (check_name(directory,conn)) {
3225                 dptr_closepath(directory,SVAL(inbuf,smb_pid));
3226                 ok = rmdir_internals(conn, directory);
3227         }
3228   
3229         if (!ok) {
3230                 END_PROFILE(SMBrmdir);
3231                 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRbadpath);
3232         }
3233  
3234         outsize = set_message(outbuf,0,0,True);
3235   
3236         DEBUG( 3, ( "rmdir %s\n", directory ) );
3237   
3238         END_PROFILE(SMBrmdir);
3239         return(outsize);
3240 }
3241
3242 /*******************************************************************
3243  Resolve wildcards in a filename rename.
3244 ********************************************************************/
3245
3246 static BOOL resolve_wildcards(const char *name1, char *name2)
3247 {
3248         fstring root1,root2;
3249         fstring ext1,ext2;
3250         char *p,*p2, *pname1, *pname2;
3251         int available_space;
3252         
3253
3254         pname1 = strrchr_m(name1,'/');
3255         pname2 = strrchr_m(name2,'/');
3256
3257         if (!pname1 || !pname2)
3258                 return(False);
3259   
3260         fstrcpy(root1,pname1);
3261         fstrcpy(root2,pname2);
3262         p = strrchr_m(root1,'.');
3263         if (p) {
3264                 *p = 0;
3265                 fstrcpy(ext1,p+1);
3266         } else {
3267                 fstrcpy(ext1,"");    
3268         }
3269         p = strrchr_m(root2,'.');
3270         if (p) {
3271                 *p = 0;
3272                 fstrcpy(ext2,p+1);
3273         } else {
3274                 fstrcpy(ext2,"");    
3275         }
3276
3277         p = root1;
3278         p2 = root2;
3279         while (*p2) {
3280                 if (*p2 == '?') {
3281                         *p2 = *p;
3282                         p2++;
3283                 } else {
3284                         p2++;
3285                 }
3286                 if (*p)
3287                         p++;
3288         }
3289
3290         p = ext1;
3291         p2 = ext2;
3292         while (*p2) {
3293                 if (*p2 == '?') {
3294                         *p2 = *p;
3295                         p2++;
3296                 } else {
3297                         p2++;
3298                 }
3299                 if (*p)
3300                         p++;
3301         }
3302
3303         available_space = sizeof(pstring) - PTR_DIFF(pname2, name2);
3304         
3305         if (ext2[0]) {
3306                 snprintf(pname2, available_space - 1, "%s.%s", root2, ext2);
3307         } else {
3308                 pstrcpy_base(pname2, root2, name2);
3309         }
3310
3311         return(True);
3312 }
3313
3314 /****************************************************************************
3315  Ensure open files have their names updates.
3316 ****************************************************************************/
3317
3318 static void rename_open_files(connection_struct *conn, SMB_DEV_T dev, SMB_INO_T inode, char *newname)
3319 {
3320         files_struct *fsp;
3321         BOOL did_rename = False;
3322
3323         for(fsp = file_find_di_first(dev, inode); fsp; fsp = file_find_di_next(fsp)) {
3324                 DEBUG(10,("rename_open_files: renaming file fnum %d (dev = %x, inode = %.0f) from %s -> %s\n",
3325                         fsp->fnum, (unsigned int)fsp->dev, (double)fsp->inode,
3326                         fsp->fsp_name, newname ));
3327                 string_set(&fsp->fsp_name, newname);
3328                 did_rename = True;
3329         }
3330
3331         if (!did_rename)
3332                 DEBUG(10,("rename_open_files: no open files on dev %x, inode %.0f for %s\n",
3333                         (unsigned int)dev, (double)inode, newname ));
3334 }
3335
3336 /****************************************************************************
3337  Rename an open file - given an fsp.
3338 ****************************************************************************/
3339
3340 NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, char *newname, BOOL replace_if_exists)
3341 {
3342         SMB_STRUCT_STAT sbuf;
3343         BOOL bad_path = False;
3344         pstring newname_last_component;
3345         NTSTATUS error = NT_STATUS_OK;
3346         BOOL dest_exists;
3347
3348         ZERO_STRUCT(sbuf);
3349         unix_convert(newname,conn,newname_last_component,&bad_path,&sbuf);
3350
3351         /* Ensure newname contains a '/' */
3352         if(strrchr_m(newname,'/') == 0) {
3353                 pstring tmpstr;
3354                 
3355                 pstrcpy(tmpstr, "./");
3356                 pstrcat(tmpstr, newname);
3357                 pstrcpy(newname, tmpstr);
3358         }
3359
3360         /*
3361          * Check for special case with case preserving and not
3362          * case sensitive. If the old last component differs from the original
3363          * last component only by case, then we should allow
3364          * the rename (user is trying to change the case of the
3365          * filename).
3366          */
3367
3368         if((case_sensitive == False) && (case_preserve == True) &&
3369                         strequal(newname, fsp->fsp_name)) {
3370                 char *p;
3371                 pstring newname_modified_last_component;
3372
3373                 /*
3374                  * Get the last component of the modified name.
3375                  * Note that we guarantee that newname contains a '/'
3376                  * character above.
3377                  */
3378                 p = strrchr_m(newname,'/');
3379                 pstrcpy(newname_modified_last_component,p+1);
3380                         
3381                 if(strcsequal(newname_modified_last_component, 
3382                               newname_last_component) == False) {
3383                         /*
3384                          * Replace the modified last component with
3385                          * the original.
3386                          */
3387                         pstrcpy(p+1, newname_last_component);
3388                 }
3389         }
3390
3391         /*
3392          * If the src and dest names are identical - including case,
3393          * don't do the rename, just return success.
3394          */
3395
3396         if (strcsequal(fsp->fsp_name, newname)) {
3397                 DEBUG(3,("rename_internals_fsp: identical names in rename %s - returning success\n",
3398                         newname));
3399                 return NT_STATUS_OK;
3400         }
3401
3402         dest_exists = vfs_object_exist(conn,newname,NULL);
3403
3404         if(!replace_if_exists && dest_exists) {
3405                 DEBUG(3,("rename_internals_fsp: dest exists doing rename %s -> %s\n",
3406                         fsp->fsp_name,newname));
3407                 return NT_STATUS_OBJECT_NAME_COLLISION;
3408         }
3409
3410         error = can_rename(newname,conn,&sbuf);
3411
3412         if (dest_exists && !NT_STATUS_IS_OK(error)) {
3413                 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3414                         nt_errstr(error), fsp->fsp_name,newname));
3415                 if (NT_STATUS_EQUAL(error,NT_STATUS_SHARING_VIOLATION))
3416                         error = NT_STATUS_ACCESS_DENIED;
3417                 return error;
3418         }
3419
3420         if(SMB_VFS_RENAME(conn,fsp->fsp_name, newname) == 0) {
3421                 DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n",
3422                         fsp->fsp_name,newname));
3423                 rename_open_files(conn, fsp->dev, fsp->inode, newname);
3424                 return NT_STATUS_OK;    
3425         }
3426
3427         if (errno == ENOTDIR || errno == EISDIR)
3428                 error = NT_STATUS_OBJECT_NAME_COLLISION;
3429         else
3430                 error = map_nt_error_from_unix(errno);
3431                 
3432         DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
3433                 nt_errstr(error), fsp->fsp_name,newname));
3434
3435         return error;
3436 }
3437
3438 /****************************************************************************
3439  The guts of the rename command, split out so it may be called by the NT SMB
3440  code. 
3441 ****************************************************************************/
3442
3443 NTSTATUS rename_internals(connection_struct *conn, char *name, char *newname, BOOL replace_if_exists)
3444 {
3445         pstring directory;
3446         pstring mask;
3447         pstring newname_last_component;
3448         char *p;
3449         BOOL has_wild;
3450         BOOL bad_path1 = False;
3451         BOOL bad_path2 = False;
3452         int count=0;
3453         NTSTATUS error = NT_STATUS_OK;
3454         BOOL rc = True;
3455         SMB_STRUCT_STAT sbuf1, sbuf2;
3456
3457         *directory = *mask = 0;
3458
3459         ZERO_STRUCT(sbuf1);
3460         ZERO_STRUCT(sbuf2);
3461         rc = unix_convert(name,conn,0,&bad_path1,&sbuf1);
3462         unix_convert(newname,conn,newname_last_component,&bad_path2,&sbuf2);
3463
3464         /*
3465          * Split the old name into directory and last component
3466          * strings. Note that unix_convert may have stripped off a 
3467          * leading ./ from both name and newname if the rename is 
3468          * at the root of the share. We need to make sure either both
3469          * name and newname contain a / character or neither of them do
3470          * as this is checked in resolve_wildcards().
3471          */
3472         
3473         p = strrchr_m(name,'/');
3474         if (!p) {
3475                 pstrcpy(directory,".");
3476                 pstrcpy(mask,name);
3477         } else {
3478                 *p = 0;
3479                 pstrcpy(directory,name);
3480                 pstrcpy(mask,p+1);
3481                 *p = '/'; /* Replace needed for exceptional test below. */
3482         }
3483
3484         /*
3485          * We should only check the mangled cache
3486          * here if unix_convert failed. This means
3487          * that the path in 'mask' doesn't exist
3488          * on the file system and so we need to look
3489          * for a possible mangle. This patch from
3490          * Tine Smukavec <valentin.smukavec@hermes.si>.
3491          */
3492
3493         if (!rc && mangle_is_mangled(mask))
3494                 mangle_check_cache( mask );
3495
3496         has_wild = ms_has_wild(mask);
3497
3498         if (!has_wild) {
3499                 /*
3500                  * No wildcards - just process the one file.
3501                  */
3502                 BOOL is_short_name = mangle_is_8_3(name, True);
3503
3504                 /* Add a terminating '/' to the directory name. */
3505                 pstrcat(directory,"/");
3506                 pstrcat(directory,mask);
3507                 
3508                 /* Ensure newname contains a '/' also */
3509                 if(strrchr_m(newname,'/') == 0) {
3510                         pstring tmpstr;
3511                         
3512                         pstrcpy(tmpstr, "./");
3513                         pstrcat(tmpstr, newname);
3514                         pstrcpy(newname, tmpstr);
3515                 }
3516                 
3517                 DEBUG(3,("rename_internals: case_sensitive = %d, case_preserve = %d, short case preserve = %d, \
3518 directory = %s, newname = %s, newname_last_component = %s, is_8_3 = %d\n", 
3519                          case_sensitive, case_preserve, short_case_preserve, directory, 
3520                          newname, newname_last_component, is_short_name));
3521
3522                 /*
3523                  * Check for special case with case preserving and not
3524                  * case sensitive, if directory and newname are identical,
3525                  * and the old last component differs from the original
3526                  * last component only by case, then we should allow
3527                  * the rename (user is trying to change the case of the
3528                  * filename).
3529                  */
3530                 if((case_sensitive == False) && 
3531                    (((case_preserve == True) && 
3532                      (is_short_name == False)) || 
3533                     ((short_case_preserve == True) && 
3534                      (is_short_name == True))) &&
3535                    strcsequal(directory, newname)) {
3536                         pstring newname_modified_last_component;
3537
3538                         /*
3539                          * Get the last component of the modified name.
3540                          * Note that we guarantee that newname contains a '/'
3541                          * character above.
3542                          */
3543                         p = strrchr_m(newname,'/');
3544                         pstrcpy(newname_modified_last_component,p+1);
3545                         
3546                         if(strcsequal(newname_modified_last_component, 
3547                                       newname_last_component) == False) {
3548                                 /*
3549                                  * Replace the modified last component with
3550                                  * the original.
3551                                  */
3552                                 pstrcpy(p+1, newname_last_component);
3553                         }
3554                 }
3555         
3556                 resolve_wildcards(directory,newname);
3557         
3558                 /*
3559                  * The source object must exist.
3560                  */
3561
3562                 if (!vfs_object_exist(conn, directory, &sbuf1)) {
3563                         DEBUG(3,("rename_internals: source doesn't exist doing rename %s -> %s\n",
3564                                 directory,newname));
3565
3566                         if (errno == ENOTDIR || errno == EISDIR || errno == ENOENT) {
3567                                 /*
3568                                  * Must return different errors depending on whether the parent
3569                                  * directory existed or not.
3570                                  */
3571
3572                                 p = strrchr_m(directory, '/');
3573                                 if (!p)
3574                                         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3575                                 *p = '\0';
3576                                 if (vfs_object_exist(conn, directory, NULL))
3577                                         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3578                                 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3579                         }
3580                         error = map_nt_error_from_unix(errno);
3581                         DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3582                                 nt_errstr(error), directory,newname));
3583
3584                         return error;
3585                 }
3586
3587                 error = can_rename(directory,conn,&sbuf1);
3588
3589                 if (!NT_STATUS_IS_OK(error)) {
3590                         DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3591                                 nt_errstr(error), directory,newname));
3592                         return error;
3593                 }
3594
3595                 /*
3596                  * If the src and dest names are identical - including case,
3597                  * don't do the rename, just return success.
3598                  */
3599
3600                 if (strcsequal(directory, newname)) {
3601                         rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
3602                         DEBUG(3,("rename_internals: identical names in rename %s - returning success\n", directory));
3603                         return NT_STATUS_OK;
3604                 }
3605
3606                 if(!replace_if_exists && vfs_object_exist(conn,newname,NULL)) {
3607                         DEBUG(3,("rename_internals: dest exists doing rename %s -> %s\n",
3608                                 directory,newname));
3609                         return NT_STATUS_OBJECT_NAME_COLLISION;
3610                 }
3611
3612                 if(SMB_VFS_RENAME(conn,directory, newname) == 0) {
3613                         DEBUG(3,("rename_internals: succeeded doing rename on %s -> %s\n",
3614                                 directory,newname));
3615                         rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
3616                         return NT_STATUS_OK;    
3617                 }
3618
3619                 if (errno == ENOTDIR || errno == EISDIR)
3620                         error = NT_STATUS_OBJECT_NAME_COLLISION;
3621                 else
3622                         error = map_nt_error_from_unix(errno);
3623                 
3624                 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3625                         nt_errstr(error), directory,newname));
3626
3627                 return error;
3628         } else {
3629                 /*
3630                  * Wildcards - process each file that matches.
3631                  */
3632                 void *dirptr = NULL;
3633                 const char *dname;
3634                 pstring destname;
3635                 
3636                 if (check_name(directory,conn))
3637                         dirptr = OpenDir(conn, directory, True);
3638                 
3639                 if (dirptr) {
3640                         error = NT_STATUS_OBJECT_NAME_NOT_FOUND;
3641                         
3642                         if (strequal(mask,"????????.???"))
3643                                 pstrcpy(mask,"*");
3644                         
3645                         while ((dname = ReadDirName(dirptr))) {
3646                                 pstring fname;
3647
3648                                 pstrcpy(fname,dname);
3649                                 
3650                                 if(!mask_match(fname, mask, case_sensitive))
3651                                         continue;
3652                                 
3653                                 error = NT_STATUS_ACCESS_DENIED;
3654                                 slprintf(fname,sizeof(fname)-1,"%s/%s",directory,dname);
3655                                 if (!vfs_object_exist(conn, fname, &sbuf1)) {
3656                                         error = NT_STATUS_OBJECT_NAME_NOT_FOUND;
3657                                         DEBUG(6,("rename %s failed. Error %s\n", fname, nt_errstr(error)));
3658                                         continue;
3659                                 }
3660                                 error = can_rename(fname,conn,&sbuf1);
3661                                 if (!NT_STATUS_IS_OK(error)) {
3662                                         DEBUG(6,("rename %s refused\n", fname));
3663                                         continue;
3664                                 }
3665                                 pstrcpy(destname,newname);
3666                                 
3667                                 if (!resolve_wildcards(fname,destname)) {
3668                                         DEBUG(6,("resolve_wildcards %s %s failed\n", 
3669                                                  fname, destname));
3670                                         continue;
3671                                 }
3672                                 
3673                                 if (!replace_if_exists && 
3674                                     vfs_file_exist(conn,destname, NULL)) {
3675                                         DEBUG(6,("file_exist %s\n", destname));
3676                                         error = NT_STATUS_OBJECT_NAME_COLLISION;
3677                                         continue;
3678                                 }
3679                                 
3680                                 if (!SMB_VFS_RENAME(conn,fname,destname)) {
3681                                         rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
3682                                         count++;
3683                                 }
3684                                 DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname));
3685                         }
3686                         CloseDir(dirptr);
3687                 }
3688         }
3689         
3690         if (count == 0 && NT_STATUS_IS_OK(error)) {
3691                 error = map_nt_error_from_unix(errno);
3692         }
3693         
3694         return error;
3695 }
3696
3697 /****************************************************************************
3698  Reply to a mv.
3699 ****************************************************************************/
3700
3701 int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, 
3702              int dum_buffsize)
3703 {
3704         int outsize = 0;
3705         pstring name;
3706         pstring newname;
3707         char *p;
3708         NTSTATUS status;
3709
3710         START_PROFILE(SMBmv);
3711
3712         p = smb_buf(inbuf) + 1;
3713         p += srvstr_get_path(inbuf, name, p, sizeof(name), STR_TERMINATE,&status);
3714         if (!NT_STATUS_IS_OK(status)) {
3715                 END_PROFILE(SMBmv);
3716                 return ERROR_NT(status);
3717         }
3718         p++;
3719         p += srvstr_get_path(inbuf, newname, p, sizeof(newname), STR_TERMINATE,&status);
3720         if (!NT_STATUS_IS_OK(status)) {
3721                 END_PROFILE(SMBmv);
3722                 return ERROR_NT(status);
3723         }
3724         
3725         RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
3726         RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
3727         
3728         DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
3729         
3730         status = rename_internals(conn, name, newname, False);
3731         if (!NT_STATUS_IS_OK(status)) {
3732                 END_PROFILE(SMBmv);
3733                 return ERROR_NT(status);
3734         }
3735
3736         /*
3737          * Win2k needs a changenotify request response before it will
3738          * update after a rename..
3739          */     
3740         process_pending_change_notify_queue((time_t)0);
3741         outsize = set_message(outbuf,0,0,True);
3742   
3743         END_PROFILE(SMBmv);
3744         return(outsize);
3745 }
3746
3747 /*******************************************************************
3748  Copy a file as part of a reply_copy.
3749 ******************************************************************/
3750
3751 static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
3752                       int count,BOOL target_is_directory, int *err_ret)
3753 {
3754         int Access,action;
3755         SMB_STRUCT_STAT src_sbuf, sbuf2;
3756         SMB_OFF_T ret=-1;
3757         files_struct *fsp1,*fsp2;
3758         pstring dest;
3759   
3760         *err_ret = 0;
3761
3762         pstrcpy(dest,dest1);
3763         if (target_is_directory) {
3764                 char *p = strrchr_m(src,'/');
3765                 if (p) 
3766                         p++;
3767                 else
3768                         p = src;
3769                 pstrcat(dest,"/");
3770                 pstrcat(dest,p);
3771         }
3772
3773         if (!vfs_file_exist(conn,src,&src_sbuf))
3774                 return(False);
3775
3776         fsp1 = open_file_shared(conn,src,&src_sbuf,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
3777                                         (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),0,0,&Access,&action);
3778
3779         if (!fsp1)
3780                 return(False);
3781
3782         if (!target_is_directory && count)
3783                 ofun = FILE_EXISTS_OPEN;
3784
3785         if (SMB_VFS_STAT(conn,dest,&sbuf2) == -1)
3786                 ZERO_STRUCTP(&sbuf2);
3787
3788         fsp2 = open_file_shared(conn,dest,&sbuf2,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_WRONLY),
3789                         ofun,src_sbuf.st_mode,0,&Access,&action);
3790
3791         if (!fsp2) {
3792                 close_file(fsp1,False);
3793                 return(False);
3794         }
3795
3796         if ((ofun&3) == 1) {
3797                 if(SMB_VFS_LSEEK(fsp2,fsp2->fd,0,SEEK_END) == -1) {
3798                         DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
3799                         /*
3800                          * Stop the copy from occurring.
3801                          */
3802                         ret = -1;
3803                         src_sbuf.st_size = 0;
3804                 }
3805         }
3806   
3807         if (src_sbuf.st_size)
3808                 ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_size);
3809
3810         close_file(fsp1,False);
3811
3812         /* Ensure the modtime is set correctly on the destination file. */
3813         fsp2->pending_modtime = src_sbuf.st_mtime;
3814
3815         /*
3816          * As we are opening fsp1 read-only we only expect
3817          * an error on close on fsp2 if we are out of space.
3818          * Thus we don't look at the error return from the
3819          * close of fsp1.
3820          */
3821         *err_ret = close_file(fsp2,False);
3822
3823         return(ret == (SMB_OFF_T)src_sbuf.st_size);
3824 }
3825
3826 /****************************************************************************
3827  Reply to a file copy.
3828 ****************************************************************************/
3829
3830 int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3831 {
3832         int outsize = 0;
3833         pstring name;
3834         pstring directory;
3835         pstring mask,newname;
3836         char *p;
3837         int count=0;
3838         int error = ERRnoaccess;
3839         int err = 0;
3840         BOOL has_wild;
3841         BOOL exists=False;
3842         int tid2 = SVAL(inbuf,smb_vwv0);
3843         int ofun = SVAL(inbuf,smb_vwv1);
3844         int flags = SVAL(inbuf,smb_vwv2);
3845         BOOL target_is_directory=False;
3846         BOOL bad_path1 = False;
3847         BOOL bad_path2 = False;
3848         BOOL rc = True;
3849         SMB_STRUCT_STAT sbuf1, sbuf2;
3850         NTSTATUS status;
3851
3852         START_PROFILE(SMBcopy);
3853
3854         *directory = *mask = 0;
3855
3856         p = smb_buf(inbuf);
3857         p += srvstr_get_path(inbuf, name, p, sizeof(name), STR_TERMINATE,&status);
3858         if (!NT_STATUS_IS_OK(status)) {
3859                 END_PROFILE(SMBcopy);
3860                 return ERROR_NT(status);
3861         }
3862         p += srvstr_get_path(inbuf, newname, p, sizeof(newname), STR_TERMINATE,&status);
3863         if (!NT_STATUS_IS_OK(status)) {
3864                 END_PROFILE(SMBcopy);
3865                 return ERROR_NT(status);
3866         }
3867    
3868         DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
3869    
3870         if (tid2 != conn->cnum) {
3871                 /* can't currently handle inter share copies XXXX */
3872                 DEBUG(3,("Rejecting inter-share copy\n"));
3873                 END_PROFILE(SMBcopy);
3874                 return ERROR_DOS(ERRSRV,ERRinvdevice);
3875         }
3876
3877         RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
3878         RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
3879
3880         rc = unix_convert(name,conn,0,&bad_path1,&sbuf1);
3881         unix_convert(newname,conn,0,&bad_path2,&sbuf2);
3882
3883         target_is_directory = VALID_STAT_OF_DIR(sbuf2);
3884
3885         if ((flags&1) && target_is_directory) {
3886                 END_PROFILE(SMBcopy);
3887                 return ERROR_DOS(ERRDOS,ERRbadfile);
3888         }
3889
3890         if ((flags&2) && !target_is_directory) {
3891                 END_PROFILE(SMBcopy);
3892                 return ERROR_DOS(ERRDOS,ERRbadpath);
3893         }
3894
3895         if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) {
3896                 /* wants a tree copy! XXXX */
3897                 DEBUG(3,("Rejecting tree copy\n"));
3898                 END_PROFILE(SMBcopy);
3899                 return ERROR_DOS(ERRSRV,ERRerror);
3900         }
3901
3902         p = strrchr_m(name,'/');
3903         if (!p) {
3904                 pstrcpy(directory,"./");
3905                 pstrcpy(mask,name);
3906         } else {
3907                 *p = 0;
3908                 pstrcpy(directory,name);
3909                 pstrcpy(mask,p+1);
3910         }
3911
3912         /*
3913          * We should only check the mangled cache
3914          * here if unix_convert failed. This means
3915          * that the path in 'mask' doesn't exist
3916          * on the file system and so we need to look
3917          * for a possible mangle. This patch from
3918          * Tine Smukavec <valentin.smukavec@hermes.si>.
3919          */
3920
3921         if (!rc && mangle_is_mangled(mask))
3922                 mangle_check_cache( mask );
3923
3924         has_wild = ms_has_wild(mask);
3925
3926         if (!has_wild) {
3927                 pstrcat(directory,"/");
3928                 pstrcat(directory,mask);
3929                 if (resolve_wildcards(directory,newname) &&
3930                                 copy_file(directory,newname,conn,ofun, count,target_is_directory,&err))
3931                         count++;
3932                 if(!count && err) {
3933                         errno = err;
3934                         END_PROFILE(SMBcopy);
3935                         return(UNIXERROR(ERRHRD,ERRgeneral));
3936                 }
3937                 if (!count) {
3938                         exists = vfs_file_exist(conn,directory,NULL);
3939                 }
3940         } else {
3941                 void *dirptr = NULL;
3942                 const char *dname;
3943                 pstring destname;
3944
3945                 if (check_name(directory,conn))
3946                         dirptr = OpenDir(conn, directory, True);
3947
3948                 if (dirptr) {
3949                         error = ERRbadfile;
3950
3951                         if (strequal(mask,"????????.???"))
3952                                 pstrcpy(mask,"*");
3953
3954                         while ((dname = ReadDirName(dirptr))) {
3955                                 pstring fname;
3956                                 pstrcpy(fname,dname);
3957     
3958                                 if(!mask_match(fname, mask, case_sensitive))
3959                                         continue;
3960
3961                                 error = ERRnoaccess;
3962                                 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
3963                                 pstrcpy(destname,newname);
3964                                 if (resolve_wildcards(fname,destname) && 
3965                                                 copy_file(fname,destname,conn,ofun,
3966                                                 count,target_is_directory,&err))
3967                                         count++;
3968                                 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
3969                         }
3970                         CloseDir(dirptr);
3971                 }
3972         }
3973   
3974         if (count == 0) {
3975                 if(err) {
3976                         /* Error on close... */
3977                         errno = err;
3978                         END_PROFILE(SMBcopy);
3979                         return(UNIXERROR(ERRHRD,ERRgeneral));
3980                 }
3981
3982                 if (exists) {
3983                         END_PROFILE(SMBcopy);
3984                         return ERROR_DOS(ERRDOS,error);
3985                 } else {
3986                         if((errno == ENOENT) && (bad_path1 || bad_path2)) {
3987                                 unix_ERR_class = ERRDOS;
3988                                 unix_ERR_code = ERRbadpath;
3989                         }
3990                         END_PROFILE(SMBcopy);
3991                         return(UNIXERROR(ERRDOS,error));
3992                 }
3993         }
3994   
3995         outsize = set_message(outbuf,1,0,True);
3996         SSVAL(outbuf,smb_vwv0,count);
3997
3998         END_PROFILE(SMBcopy);
3999         return(outsize);
4000 }
4001
4002 /****************************************************************************
4003  Reply to a setdir.
4004 ****************************************************************************/
4005
4006 int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4007 {
4008         int snum;
4009         int outsize = 0;
4010         BOOL ok = False;
4011         pstring newdir;
4012         NTSTATUS status;
4013
4014         START_PROFILE(pathworks_setdir);
4015   
4016         snum = SNUM(conn);
4017         if (!CAN_SETDIR(snum)) {
4018                 END_PROFILE(pathworks_setdir);
4019                 return ERROR_DOS(ERRDOS,ERRnoaccess);
4020         }
4021
4022         srvstr_get_path(inbuf, newdir, smb_buf(inbuf) + 1, sizeof(newdir), STR_TERMINATE,&status);
4023         if (!NT_STATUS_IS_OK(status)) {
4024                 END_PROFILE(pathworks_setdir);
4025                 return ERROR_NT(status);
4026         }
4027   
4028         if (strlen(newdir) == 0) {
4029                 ok = True;
4030         } else {
4031                 ok = vfs_directory_exist(conn,newdir,NULL);
4032                 if (ok)
4033                         string_set(&conn->connectpath,newdir);
4034         }
4035   
4036         if (!ok) {
4037                 END_PROFILE(pathworks_setdir);
4038                 return ERROR_DOS(ERRDOS,ERRbadpath);
4039         }
4040   
4041         outsize = set_message(outbuf,0,0,True);
4042         SCVAL(outbuf,smb_reh,CVAL(inbuf,smb_reh));
4043   
4044         DEBUG(3,("setdir %s\n", newdir));
4045
4046         END_PROFILE(pathworks_setdir);
4047         return(outsize);
4048 }
4049
4050 /****************************************************************************
4051  Get a lock pid, dealing with large count requests.
4052 ****************************************************************************/
4053
4054 uint16 get_lock_pid( char *data, int data_offset, BOOL large_file_format)
4055 {
4056         if(!large_file_format)
4057                 return SVAL(data,SMB_LPID_OFFSET(data_offset));
4058         else
4059                 return SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
4060 }
4061
4062 /****************************************************************************
4063  Get a lock count, dealing with large count requests.
4064 ****************************************************************************/
4065
4066 SMB_BIG_UINT get_lock_count( char *data, int data_offset, BOOL large_file_format)
4067 {
4068         SMB_BIG_UINT count = 0;
4069
4070         if(!large_file_format) {
4071                 count = (SMB_BIG_UINT)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
4072         } else {
4073
4074 #if defined(HAVE_LONGLONG)
4075                 count = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
4076                         ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
4077 #else /* HAVE_LONGLONG */
4078
4079                 /*
4080                  * NT4.x seems to be broken in that it sends large file (64 bit)
4081                  * lockingX calls even if the CAP_LARGE_FILES was *not*
4082                  * negotiated. For boxes without large unsigned ints truncate the
4083                  * lock count by dropping the top 32 bits.
4084                  */
4085
4086                 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
4087                         DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
4088                                 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
4089                                 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
4090                                 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
4091                 }
4092
4093                 count = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
4094 #endif /* HAVE_LONGLONG */
4095         }
4096
4097         return count;
4098 }
4099
4100 #if !defined(HAVE_LONGLONG)
4101 /****************************************************************************
4102  Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
4103 ****************************************************************************/
4104
4105 static uint32 map_lock_offset(uint32 high, uint32 low)
4106 {
4107         unsigned int i;
4108         uint32 mask = 0;
4109         uint32 highcopy = high;
4110  
4111         /*
4112          * Try and find out how many significant bits there are in high.
4113          */
4114  
4115         for(i = 0; highcopy; i++)
4116                 highcopy >>= 1;
4117  
4118         /*
4119          * We use 31 bits not 32 here as POSIX
4120          * lock offsets may not be negative.
4121          */
4122  
4123         mask = (~0) << (31 - i);
4124  
4125         if(low & mask)
4126                 return 0; /* Fail. */
4127  
4128         high <<= (31 - i);
4129  
4130         return (high|low);
4131 }
4132 #endif /* !defined(HAVE_LONGLONG) */
4133
4134 /****************************************************************************
4135  Get a lock offset, dealing with large offset requests.
4136 ****************************************************************************/
4137
4138 SMB_BIG_UINT get_lock_offset( char *data, int data_offset, BOOL large_file_format, BOOL *err)
4139 {
4140         SMB_BIG_UINT offset = 0;
4141
4142         *err = False;
4143
4144         if(!large_file_format) {
4145                 offset = (SMB_BIG_UINT)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
4146         } else {
4147
4148 #if defined(HAVE_LONGLONG)
4149                 offset = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
4150                                 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
4151 #else /* HAVE_LONGLONG */
4152
4153                 /*
4154                  * NT4.x seems to be broken in that it sends large file (64 bit)
4155                  * lockingX calls even if the CAP_LARGE_FILES was *not*
4156                  * negotiated. For boxes without large unsigned ints mangle the
4157                  * lock offset by mapping the top 32 bits onto the lower 32.
4158                  */
4159       
4160                 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
4161                         uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
4162                         uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
4163                         uint32 new_low = 0;
4164
4165                         if((new_low = map_lock_offset(high, low)) == 0) {
4166                                 *err = True;
4167                                 return (SMB_BIG_UINT)-1;
4168                         }
4169
4170                         DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
4171                                 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
4172                         SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
4173                         SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
4174                 }
4175
4176                 offset = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
4177 #endif /* HAVE_LONGLONG */
4178         }
4179
4180         return offset;
4181 }
4182
4183 /****************************************************************************
4184  Reply to a lockingX request.
4185 ****************************************************************************/
4186
4187 int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
4188 {
4189         files_struct *fsp = file_fsp(inbuf,smb_vwv2);
4190         unsigned char locktype = CVAL(inbuf,smb_vwv3);
4191         unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
4192         uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
4193         uint16 num_locks = SVAL(inbuf,smb_vwv7);
4194         SMB_BIG_UINT count = 0, offset = 0;
4195         uint16 lock_pid;
4196         int32 lock_timeout = IVAL(inbuf,smb_vwv4);
4197         int i;
4198         char *data;
4199         BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
4200         BOOL err;
4201         BOOL my_lock_ctx = False;
4202         NTSTATUS status;
4203
4204         START_PROFILE(SMBlockingX);
4205         
4206         CHECK_FSP(fsp,conn);
4207         
4208         data = smb_buf(inbuf);
4209
4210         if (locktype & (LOCKING_ANDX_CANCEL_LOCK | LOCKING_ANDX_CHANGE_LOCKTYPE)) {
4211                 /* we don't support these - and CANCEL_LOCK makes w2k
4212                    and XP reboot so I don't really want to be
4213                    compatible! (tridge) */
4214                 return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
4215         }
4216         
4217         /* Check if this is an oplock break on a file
4218            we have granted an oplock on.
4219         */
4220         if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
4221                 /* Client can insist on breaking to none. */
4222                 BOOL break_to_none = (oplocklevel == 0);
4223                 
4224                 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client for fnum = %d\n",
4225                          (unsigned int)oplocklevel, fsp->fnum ));
4226
4227                 /*
4228                  * Make sure we have granted an exclusive or batch oplock on this file.
4229                  */
4230                 
4231                 if(!EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
4232                         DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \
4233 no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name));
4234
4235                         /* if this is a pure oplock break request then don't send a reply */
4236                         if (num_locks == 0 && num_ulocks == 0) {
4237                                 END_PROFILE(SMBlockingX);
4238                                 return -1;
4239                         } else {
4240                                 END_PROFILE(SMBlockingX);
4241                                 return ERROR_DOS(ERRDOS,ERRlock);
4242                         }
4243                 }
4244
4245                 if (remove_oplock(fsp, break_to_none) == False) {
4246                         DEBUG(0,("reply_lockingX: error in removing oplock on file %s\n",
4247                                  fsp->fsp_name ));
4248                 }
4249                 
4250                 /* if this is a pure oplock break request then don't send a reply */
4251                 if (num_locks == 0 && num_ulocks == 0) {
4252                         /* Sanity check - ensure a pure oplock break is not a
4253                            chained request. */
4254                         if(CVAL(inbuf,smb_vwv0) != 0xff)
4255                                 DEBUG(0,("reply_lockingX: Error : pure oplock break is a chained %d request !\n",
4256                                          (unsigned int)CVAL(inbuf,smb_vwv0) ));
4257                         END_PROFILE(SMBlockingX);
4258                         return -1;
4259                 }
4260         }
4261
4262         /*
4263          * We do this check *after* we have checked this is not a oplock break
4264          * response message. JRA.
4265          */
4266         
4267         release_level_2_oplocks_on_change(fsp);
4268         
4269         /* Data now points at the beginning of the list
4270            of smb_unlkrng structs */
4271         for(i = 0; i < (int)num_ulocks; i++) {
4272                 lock_pid = get_lock_pid( data, i, large_file_format);
4273                 count = get_lock_count( data, i, large_file_format);
4274                 offset = get_lock_offset( data, i, large_file_format, &err);
4275                 
4276                 /*
4277                  * There is no error code marked "stupid client bug".... :-).
4278                  */
4279                 if(err) {
4280                         END_PROFILE(SMBlockingX);
4281                         return ERROR_DOS(ERRDOS,ERRnoaccess);
4282                 }
4283
4284                 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for pid %u, file %s\n",
4285                           (double)offset, (double)count, (unsigned int)lock_pid, fsp->fsp_name ));
4286                 
4287                 status = do_unlock(fsp,conn,lock_pid,count,offset);
4288                 if (NT_STATUS_V(status)) {
4289                         END_PROFILE(SMBlockingX);
4290                         return ERROR_NT(status);
4291                 }
4292         }
4293
4294         /* Setup the timeout in seconds. */
4295
4296         lock_timeout = ((lock_timeout == -1) ? -1 : (lock_timeout+499)/500);
4297         
4298         /* Now do any requested locks */
4299         data += ((large_file_format ? 20 : 10)*num_ulocks);
4300         
4301         /* Data now points at the beginning of the list
4302            of smb_lkrng structs */
4303         
4304         for(i = 0; i < (int)num_locks; i++) {
4305                 lock_pid = get_lock_pid( data, i, large_file_format);
4306                 count = get_lock_count( data, i, large_file_format);
4307                 offset = get_lock_offset( data, i, large_file_format, &err);
4308                 
4309                 /*
4310                  * There is no error code marked "stupid client bug".... :-).
4311                  */
4312                 if(err) {
4313                         END_PROFILE(SMBlockingX);
4314                         return ERROR_DOS(ERRDOS,ERRnoaccess);
4315                 }
4316                 
4317                 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid %u, file %s timeout = %d\n",
4318                         (double)offset, (double)count, (unsigned int)lock_pid,
4319                         fsp->fsp_name, (int)lock_timeout ));
4320                 
4321                 status = do_lock_spin(fsp,conn,lock_pid, count,offset, 
4322                                  ((locktype & 1) ? READ_LOCK : WRITE_LOCK), &my_lock_ctx);
4323                 if (NT_STATUS_V(status)) {
4324                         if ((lock_timeout != 0) && lp_blocking_locks(SNUM(conn)) && !my_lock_ctx && ERROR_WAS_LOCK_DENIED(status)) {
4325                                 /*
4326                                  * A blocking lock was requested. Package up
4327                                  * this smb into a queued request and push it
4328                                  * onto the blocking lock queue.
4329                                  */
4330                                 if(push_blocking_lock_request(inbuf, length, lock_timeout, i, lock_pid, offset, count)) {
4331                                         END_PROFILE(SMBlockingX);
4332                                         return -1;
4333                                 }
4334                         }
4335                         break;
4336                 }
4337         }
4338         
4339         /* If any of the above locks failed, then we must unlock
4340            all of the previous locks (X/Open spec). */
4341         if (i != num_locks && num_locks != 0) {
4342                 /*
4343                  * Ensure we don't do a remove on the lock that just failed,
4344                  * as under POSIX rules, if we have a lock already there, we
4345                  * will delete it (and we shouldn't) .....
4346                  */
4347                 for(i--; i >= 0; i--) {
4348                         lock_pid = get_lock_pid( data, i, large_file_format);
4349                         count = get_lock_count( data, i, large_file_format);
4350                         offset = get_lock_offset( data, i, large_file_format, &err);
4351                         
4352                         /*
4353                          * There is no error code marked "stupid client bug".... :-).
4354                          */
4355                         if(err) {
4356                                 END_PROFILE(SMBlockingX);
4357                                 return ERROR_DOS(ERRDOS,ERRnoaccess);
4358                         }
4359                         
4360                         do_unlock(fsp,conn,lock_pid,count,offset);
4361                 }
4362                 END_PROFILE(SMBlockingX);
4363                 return ERROR_NT(status);
4364         }
4365
4366         set_message(outbuf,2,0,True);
4367         
4368         DEBUG( 3, ( "lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
4369                     fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks ) );
4370         
4371         END_PROFILE(SMBlockingX);
4372         return chain_reply(inbuf,outbuf,length,bufsize);
4373 }
4374
4375 /****************************************************************************
4376  Reply to a SMBreadbmpx (read block multiplex) request.
4377 ****************************************************************************/
4378
4379 int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
4380 {
4381         ssize_t nread = -1;
4382         ssize_t total_read;
4383         char *data;
4384         SMB_OFF_T startpos;
4385         int outsize;
4386         size_t maxcount;
4387         int max_per_packet;
4388         size_t tcount;
4389         int pad;
4390         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4391         START_PROFILE(SMBreadBmpx);
4392
4393         /* this function doesn't seem to work - disable by default */
4394         if (!lp_readbmpx()) {
4395                 END_PROFILE(SMBreadBmpx);
4396                 return ERROR_DOS(ERRSRV,ERRuseSTD);
4397         }
4398
4399         outsize = set_message(outbuf,8,0,True);
4400
4401         CHECK_FSP(fsp,conn);
4402         CHECK_READ(fsp);
4403
4404         startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
4405         maxcount = SVAL(inbuf,smb_vwv3);
4406
4407         data = smb_buf(outbuf);
4408         pad = ((long)data)%4;
4409         if (pad)
4410                 pad = 4 - pad;
4411         data += pad;
4412
4413         max_per_packet = bufsize-(outsize+pad);
4414         tcount = maxcount;
4415         total_read = 0;
4416
4417         if (is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
4418                 END_PROFILE(SMBreadBmpx);
4419                 return ERROR_DOS(ERRDOS,ERRlock);
4420         }
4421
4422         do {
4423                 size_t N = MIN(max_per_packet,tcount-total_read);
4424   
4425                 nread = read_file(fsp,data,startpos,N);
4426
4427                 if (nread <= 0)
4428                         nread = 0;
4429
4430                 if (nread < (ssize_t)N)
4431                         tcount = total_read + nread;
4432
4433                 set_message(outbuf,8,nread,False);
4434                 SIVAL(outbuf,smb_vwv0,startpos);
4435                 SSVAL(outbuf,smb_vwv2,tcount);
4436                 SSVAL(outbuf,smb_vwv6,nread);
4437                 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
4438
4439                 if (!send_smb(smbd_server_fd(),outbuf))
4440                         exit_server("reply_readbmpx: send_smb failed.");
4441
4442                 total_read += nread;
4443                 startpos += nread;
4444         } while (total_read < (ssize_t)tcount);
4445
4446         END_PROFILE(SMBreadBmpx);
4447         return(-1);
4448 }
4449
4450 /****************************************************************************
4451  Reply to a SMBsetattrE.
4452 ****************************************************************************/
4453
4454 int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4455 {
4456         struct utimbuf unix_times;
4457         int outsize = 0;
4458         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4459         START_PROFILE(SMBsetattrE);
4460
4461         outsize = set_message(outbuf,0,0,True);
4462
4463         if(!fsp || (fsp->conn != conn)) {
4464                 END_PROFILE(SMBgetattrE);
4465                 return ERROR_DOS(ERRDOS,ERRbadfid);
4466         }
4467
4468         /*
4469          * Convert the DOS times into unix times. Ignore create
4470          * time as UNIX can't set this.
4471          */
4472
4473         unix_times.actime = make_unix_date2(inbuf+smb_vwv3);
4474         unix_times.modtime = make_unix_date2(inbuf+smb_vwv5);
4475   
4476         /* 
4477          * Patch from Ray Frush <frush@engr.colostate.edu>
4478          * Sometimes times are sent as zero - ignore them.
4479          */
4480
4481         if ((unix_times.actime == 0) && (unix_times.modtime == 0)) {
4482                 /* Ignore request */
4483                 if( DEBUGLVL( 3 ) ) {
4484                         dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
4485                         dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
4486                 }
4487                 END_PROFILE(SMBsetattrE);
4488                 return(outsize);
4489         } else if ((unix_times.actime != 0) && (unix_times.modtime == 0)) {
4490                 /* set modify time = to access time if modify time was 0 */
4491                 unix_times.modtime = unix_times.actime;
4492         }
4493
4494         /* Set the date on this file */
4495         if(file_utime(conn, fsp->fsp_name, &unix_times)) {
4496                 END_PROFILE(SMBsetattrE);
4497                 return ERROR_DOS(ERRDOS,ERRnoaccess);
4498         }
4499   
4500         DEBUG( 3, ( "reply_setattrE fnum=%d actime=%d modtime=%d\n",
4501                 fsp->fnum, (int)unix_times.actime, (int)unix_times.modtime ) );
4502
4503         END_PROFILE(SMBsetattrE);
4504         return(outsize);
4505 }
4506
4507
4508 /* Back from the dead for OS/2..... JRA. */
4509
4510 /****************************************************************************
4511  Reply to a SMBwritebmpx (write block multiplex primary) request.
4512 ****************************************************************************/
4513
4514 int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4515 {
4516         size_t numtowrite;
4517         ssize_t nwritten = -1;
4518         int outsize = 0;
4519         SMB_OFF_T startpos;
4520         size_t tcount;
4521         BOOL write_through;
4522         int smb_doff;
4523         char *data;
4524         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4525         START_PROFILE(SMBwriteBmpx);
4526
4527         CHECK_FSP(fsp,conn);
4528         CHECK_WRITE(fsp);
4529         CHECK_ERROR(fsp);
4530
4531         tcount = SVAL(inbuf,smb_vwv1);
4532         startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
4533         write_through = BITSETW(inbuf+smb_vwv7,0);
4534         numtowrite = SVAL(inbuf,smb_vwv10);
4535         smb_doff = SVAL(inbuf,smb_vwv11);
4536
4537         data = smb_base(inbuf) + smb_doff;
4538
4539         /* If this fails we need to send an SMBwriteC response,
4540                 not an SMBwritebmpx - set this up now so we don't forget */
4541         SCVAL(outbuf,smb_com,SMBwritec);
4542
4543         if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos,WRITE_LOCK,False)) {
4544                 END_PROFILE(SMBwriteBmpx);
4545                 return(ERROR_DOS(ERRDOS,ERRlock));
4546         }
4547
4548         nwritten = write_file(fsp,data,startpos,numtowrite);
4549
4550         if(lp_syncalways(SNUM(conn)) || write_through)
4551                 sync_file(conn,fsp);
4552   
4553         if(nwritten < (ssize_t)numtowrite) {
4554                 END_PROFILE(SMBwriteBmpx);
4555                 return(UNIXERROR(ERRHRD,ERRdiskfull));
4556         }
4557
4558         /* If the maximum to be written to this file
4559                 is greater than what we just wrote then set
4560                 up a secondary struct to be attached to this
4561                 fd, we will use this to cache error messages etc. */
4562
4563         if((ssize_t)tcount > nwritten) {
4564                 write_bmpx_struct *wbms;
4565                 if(fsp->wbmpx_ptr != NULL)
4566                         wbms = fsp->wbmpx_ptr; /* Use an existing struct */
4567                 else
4568                         wbms = (write_bmpx_struct *)malloc(sizeof(write_bmpx_struct));
4569                 if(!wbms) {
4570                         DEBUG(0,("Out of memory in reply_readmpx\n"));
4571                         END_PROFILE(SMBwriteBmpx);
4572                         return(ERROR_DOS(ERRSRV,ERRnoresource));
4573                 }
4574                 wbms->wr_mode = write_through;
4575                 wbms->wr_discard = False; /* No errors yet */
4576                 wbms->wr_total_written = nwritten;
4577                 wbms->wr_errclass = 0;
4578                 wbms->wr_error = 0;
4579                 fsp->wbmpx_ptr = wbms;
4580         }
4581
4582         /* We are returning successfully, set the message type back to
4583                 SMBwritebmpx */
4584         SCVAL(outbuf,smb_com,SMBwriteBmpx);
4585   
4586         outsize = set_message(outbuf,1,0,True);
4587   
4588         SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
4589   
4590         DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
4591                         fsp->fnum, (int)numtowrite, (int)nwritten ) );
4592
4593         if (write_through && tcount==nwritten) {
4594                 /* We need to send both a primary and a secondary response */
4595                 smb_setlen(outbuf,outsize - 4);
4596                 if (!send_smb(smbd_server_fd(),outbuf))
4597                         exit_server("reply_writebmpx: send_smb failed.");
4598
4599                 /* Now the secondary */
4600                 outsize = set_message(outbuf,1,0,True);
4601                 SCVAL(outbuf,smb_com,SMBwritec);
4602                 SSVAL(outbuf,smb_vwv0,nwritten);
4603         }
4604
4605         END_PROFILE(SMBwriteBmpx);
4606         return(outsize);
4607 }
4608
4609 /****************************************************************************
4610  Reply to a SMBwritebs (write block multiplex secondary) request.
4611 ****************************************************************************/
4612
4613 int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4614 {
4615         size_t numtowrite;
4616         ssize_t nwritten = -1;
4617         int outsize = 0;
4618         SMB_OFF_T startpos;
4619         size_t tcount;
4620         BOOL write_through;
4621         int smb_doff;
4622         char *data;
4623         write_bmpx_struct *wbms;
4624         BOOL send_response = False; 
4625         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4626         START_PROFILE(SMBwriteBs);
4627
4628         CHECK_FSP(fsp,conn);
4629         CHECK_WRITE(fsp);
4630
4631         tcount = SVAL(inbuf,smb_vwv1);
4632         startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
4633         numtowrite = SVAL(inbuf,smb_vwv6);
4634         smb_doff = SVAL(inbuf,smb_vwv7);
4635
4636         data = smb_base(inbuf) + smb_doff;
4637
4638         /* We need to send an SMBwriteC response, not an SMBwritebs */
4639         SCVAL(outbuf,smb_com,SMBwritec);
4640
4641         /* This fd should have an auxiliary struct attached,
4642                 check that it does */
4643         wbms = fsp->wbmpx_ptr;
4644         if(!wbms) {
4645                 END_PROFILE(SMBwriteBs);
4646                 return(-1);
4647         }
4648
4649         /* If write through is set we can return errors, else we must cache them */
4650         write_through = wbms->wr_mode;
4651
4652         /* Check for an earlier error */
4653         if(wbms->wr_discard) {
4654                 END_PROFILE(SMBwriteBs);
4655                 return -1; /* Just discard the packet */
4656         }
4657
4658         nwritten = write_file(fsp,data,startpos,numtowrite);
4659
4660         if(lp_syncalways(SNUM(conn)) || write_through)
4661                 sync_file(conn,fsp);
4662   
4663         if (nwritten < (ssize_t)numtowrite) {
4664                 if(write_through) {
4665                         /* We are returning an error - we can delete the aux struct */
4666                         if (wbms)
4667                                 free((char *)wbms);
4668                         fsp->wbmpx_ptr = NULL;
4669                         END_PROFILE(SMBwriteBs);
4670                         return(ERROR_DOS(ERRHRD,ERRdiskfull));
4671                 }
4672                 END_PROFILE(SMBwriteBs);
4673                 return(CACHE_ERROR(wbms,ERRHRD,ERRdiskfull));
4674         }
4675
4676         /* Increment the total written, if this matches tcount
4677                 we can discard the auxiliary struct (hurrah !) and return a writeC */
4678         wbms->wr_total_written += nwritten;
4679         if(wbms->wr_total_written >= tcount) {
4680                 if (write_through) {
4681                         outsize = set_message(outbuf,1,0,True);
4682                         SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);    
4683                         send_response = True;
4684                 }
4685
4686                 free((char *)wbms);
4687                 fsp->wbmpx_ptr = NULL;
4688         }
4689
4690         if(send_response) {
4691                 END_PROFILE(SMBwriteBs);
4692                 return(outsize);
4693         }
4694
4695         END_PROFILE(SMBwriteBs);
4696         return(-1);
4697 }
4698
4699 /****************************************************************************
4700  Reply to a SMBgetattrE.
4701 ****************************************************************************/
4702
4703 int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4704 {
4705         SMB_STRUCT_STAT sbuf;
4706         int outsize = 0;
4707         int mode;
4708         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4709         START_PROFILE(SMBgetattrE);
4710
4711         outsize = set_message(outbuf,11,0,True);
4712
4713         if(!fsp || (fsp->conn != conn)) {
4714                 END_PROFILE(SMBgetattrE);
4715                 return ERROR_DOS(ERRDOS,ERRbadfid);
4716         }
4717
4718         /* Do an fstat on this file */
4719         if(fsp_stat(fsp, &sbuf)) {
4720                 END_PROFILE(SMBgetattrE);
4721                 return(UNIXERROR(ERRDOS,ERRnoaccess));
4722         }
4723   
4724         mode = dos_mode(conn,fsp->fsp_name,&sbuf);
4725   
4726         /*
4727          * Convert the times into dos times. Set create
4728          * date to be last modify date as UNIX doesn't save
4729          * this.
4730          */
4731
4732         put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
4733         put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
4734         put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
4735
4736         if (mode & aDIR) {
4737                 SIVAL(outbuf,smb_vwv6,0);
4738                 SIVAL(outbuf,smb_vwv8,0);
4739         } else {
4740                 uint32 allocation_size = get_allocation_size(fsp, &sbuf);
4741                 SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
4742                 SIVAL(outbuf,smb_vwv8,allocation_size);
4743         }
4744         SSVAL(outbuf,smb_vwv10, mode);
4745   
4746         DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
4747   
4748         END_PROFILE(SMBgetattrE);
4749         return(outsize);
4750 }