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