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