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