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