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