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