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