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