* We must return 0x2 as the majorversion for nt4 to upload drivers
[tprouty/samba.git] / source / smbd / reply.c
1 /* 
2    Unix SMB/CIFS implementation.
3    Main SMB reply routines
4    Copyright (C) Andrew Tridgell 1992-1998
5    Copyright (C) Andrew Bartlett      2001
6
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11    
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16    
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21 /*
22    This file handles most of the reply_ calls that the server
23    makes to handle specific protocols
24 */
25
26 #include "includes.h"
27
28 /* look in server.c for some explanation of these variables */
29 extern int Protocol;
30 extern int max_send;
31 extern int max_recv;
32 extern char magic_char;
33 extern BOOL case_sensitive;
34 extern BOOL case_preserve;
35 extern BOOL short_case_preserve;
36 extern int global_oplock_break;
37 unsigned int smb_echo_count = 0;
38
39 extern BOOL global_encrypted_passwords_negotiated;
40
41 /****************************************************************************
42  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 *fsname = 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, fsname, -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) || 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) || 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         conn->vfs_ops.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         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 (conn->vfs_ops.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 (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 (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 ( conn->vfs_ops.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 (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(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 ( conn->vfs_ops.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 = conn->vfs_ops.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 = conn->vfs_ops.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(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 = conn->vfs_ops.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(conn->vfs_ops.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(vfs_rmdir(conn,fullname) != 0) {
2915                                 ret = True;
2916                                 break;
2917                         }
2918                 } else if(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 = (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(conn->vfs_ops.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(vfs_rmdir(conn,fullname) != 0)
2985                                                         break;
2986                                         } else if(vfs_unlink(conn,fullname) != 0)
2987                                                 break;
2988                                 }
2989                                 CloseDir(dirptr);
2990                                 /* Retry the rmdir */
2991                                 ok = (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         StrnCpy(pname2, root2, available_space-1);
3108         available_space -= strlen(root2);
3109         if (ext2[0]) {
3110                 strncat(pname2, ".", available_space-1);
3111                 strncat(pname2, ext2, available_space-2);
3112         }
3113
3114         return(True);
3115 }
3116
3117 /****************************************************************************
3118  The guts of the rename command, split out so it may be called by the NT SMB
3119  code. 
3120 ****************************************************************************/
3121
3122 NTSTATUS rename_internals(connection_struct *conn, char *name, char *newname, BOOL replace_if_exists)
3123 {
3124         pstring directory;
3125         pstring mask;
3126         pstring newname_last_component;
3127         char *p;
3128         BOOL has_wild;
3129         BOOL bad_path1 = False;
3130         BOOL bad_path2 = False;
3131         int count=0;
3132         NTSTATUS error = NT_STATUS_OK;
3133         BOOL rc = True;
3134         SMB_STRUCT_STAT sbuf1, sbuf2;
3135
3136         *directory = *mask = 0;
3137
3138         rc = unix_convert(name,conn,0,&bad_path1,&sbuf1);
3139         unix_convert(newname,conn,newname_last_component,&bad_path2,&sbuf2);
3140
3141         /*
3142          * Split the old name into directory and last component
3143          * strings. Note that unix_convert may have stripped off a 
3144          * leading ./ from both name and newname if the rename is 
3145          * at the root of the share. We need to make sure either both
3146          * name and newname contain a / character or neither of them do
3147          * as this is checked in resolve_wildcards().
3148          */
3149         
3150         p = strrchr_m(name,'/');
3151         if (!p) {
3152                 pstrcpy(directory,".");
3153                 pstrcpy(mask,name);
3154         } else {
3155                 *p = 0;
3156                 pstrcpy(directory,name);
3157                 pstrcpy(mask,p+1);
3158                 *p = '/'; /* Replace needed for exceptional test below. */
3159         }
3160
3161         /*
3162          * We should only check the mangled cache
3163          * here if unix_convert failed. This means
3164          * that the path in 'mask' doesn't exist
3165          * on the file system and so we need to look
3166          * for a possible mangle. This patch from
3167          * Tine Smukavec <valentin.smukavec@hermes.si>.
3168          */
3169
3170         if (!rc && mangle_is_mangled(mask))
3171                 mangle_check_cache( mask );
3172
3173         has_wild = ms_has_wild(mask);
3174
3175         if (!has_wild) {
3176                 /*
3177                  * No wildcards - just process the one file.
3178                  */
3179                 BOOL is_short_name = mangle_is_8_3(name, True);
3180
3181                 /* Add a terminating '/' to the directory name. */
3182                 pstrcat(directory,"/");
3183                 pstrcat(directory,mask);
3184                 
3185                 /* Ensure newname contains a '/' also */
3186                 if(strrchr_m(newname,'/') == 0) {
3187                         pstring tmpstr;
3188                         
3189                         pstrcpy(tmpstr, "./");
3190                         pstrcat(tmpstr, newname);
3191                         pstrcpy(newname, tmpstr);
3192                 }
3193                 
3194                 DEBUG(3,("rename_internals: case_sensitive = %d, case_preserve = %d, short case preserve = %d, \
3195 directory = %s, newname = %s, newname_last_component = %s, is_8_3 = %d\n", 
3196                          case_sensitive, case_preserve, short_case_preserve, directory, 
3197                          newname, newname_last_component, is_short_name));
3198
3199                 /*
3200                  * Check for special case with case preserving and not
3201                  * case sensitive, if directory and newname are identical,
3202                  * and the old last component differs from the original
3203                  * last component only by case, then we should allow
3204                  * the rename (user is trying to change the case of the
3205                  * filename).
3206                  */
3207                 if((case_sensitive == False) && 
3208                    (((case_preserve == True) && 
3209                      (is_short_name == False)) || 
3210                     ((short_case_preserve == True) && 
3211                      (is_short_name == True))) &&
3212                    strcsequal(directory, newname)) {
3213                         pstring newname_modified_last_component;
3214
3215                         /*
3216                          * Get the last component of the modified name.
3217                          * Note that we guarantee that newname contains a '/'
3218                          * character above.
3219                          */
3220                         p = strrchr_m(newname,'/');
3221                         pstrcpy(newname_modified_last_component,p+1);
3222                         
3223                         if(strcsequal(newname_modified_last_component, 
3224                                       newname_last_component) == False) {
3225                                 /*
3226                                  * Replace the modified last component with
3227                                  * the original.
3228                                  */
3229                                 pstrcpy(p+1, newname_last_component);
3230                         }
3231                 }
3232         
3233                 resolve_wildcards(directory,newname);
3234         
3235                 /*
3236                  * The source object must exist.
3237                  */
3238
3239                 if (!vfs_object_exist(conn, directory, &sbuf1)) {
3240                         DEBUG(3,("rename_internals: source doesn't exist doing rename %s -> %s\n",
3241                                 directory,newname));
3242
3243                         if (errno == ENOTDIR || errno == EISDIR || errno == ENOENT) {
3244                                 /*
3245                                  * Must return different errors depending on whether the parent
3246                                  * directory existed or not.
3247                                  */
3248
3249                                 p = strrchr_m(directory, '/');
3250                                 if (!p)
3251                                         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3252                                 *p = '\0';
3253                                 if (vfs_object_exist(conn, directory, NULL))
3254                                         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3255                                 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3256                         }
3257                         error = map_nt_error_from_unix(errno);
3258                         DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3259                                 nt_errstr(error), directory,newname));
3260
3261                         return error;
3262                 }
3263
3264                 error = can_rename(directory,conn,&sbuf1);
3265
3266                 if (!NT_STATUS_IS_OK(error)) {
3267                         DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3268                                 nt_errstr(error), directory,newname));
3269                         return error;
3270                 }
3271
3272                 /*
3273                  * If the src and dest names are identical - including case,
3274                  * don't do the rename, just return success.
3275                  */
3276
3277                 if (strcsequal(directory, newname)) {
3278                         DEBUG(3,("rename_internals: identical names in rename %s - returning success\n", directory));
3279                         return NT_STATUS_OK;
3280                 }
3281
3282                 if(!replace_if_exists && vfs_object_exist(conn,newname,NULL)) {
3283                         DEBUG(3,("rename_internals: dest exists doing rename %s -> %s\n",
3284                                 directory,newname));
3285                         return NT_STATUS_OBJECT_NAME_COLLISION;
3286                 }
3287
3288                 if(conn->vfs_ops.rename(conn,directory, newname) == 0) {
3289                         DEBUG(3,("rename_internals: succeeded doing rename on %s -> %s\n",
3290                                 directory,newname));
3291                         return NT_STATUS_OK;    
3292                 }
3293
3294                 if (errno == ENOTDIR || errno == EISDIR)
3295                         error = NT_STATUS_OBJECT_NAME_COLLISION;
3296                 else
3297                         error = map_nt_error_from_unix(errno);
3298                 
3299                 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3300                         nt_errstr(error), directory,newname));
3301
3302                 return error;
3303         } else {
3304                 /*
3305                  * Wildcards - process each file that matches.
3306                  */
3307                 void *dirptr = NULL;
3308                 const char *dname;
3309                 pstring destname;
3310                 
3311                 if (check_name(directory,conn))
3312                         dirptr = OpenDir(conn, directory, True);
3313                 
3314                 if (dirptr) {
3315                         error = NT_STATUS_OBJECT_NAME_NOT_FOUND;
3316                         
3317                         if (strequal(mask,"????????.???"))
3318                                 pstrcpy(mask,"*");
3319                         
3320                         while ((dname = ReadDirName(dirptr))) {
3321                                 pstring fname;
3322
3323                                 pstrcpy(fname,dname);
3324                                 
3325                                 if(!mask_match(fname, mask, case_sensitive))
3326                                         continue;
3327                                 
3328                                 error = NT_STATUS_ACCESS_DENIED;
3329                                 slprintf(fname,sizeof(fname)-1,"%s/%s",directory,dname);
3330                                 if (!vfs_object_exist(conn, fname, &sbuf1)) {
3331                                         error = NT_STATUS_OBJECT_NAME_NOT_FOUND;
3332                                         DEBUG(6,("rename %s failed. Error %s\n", fname, nt_errstr(error)));
3333                                         continue;
3334                                 }
3335                                 error = can_rename(fname,conn,&sbuf1);
3336                                 if (!NT_STATUS_IS_OK(error)) {
3337                                         DEBUG(6,("rename %s refused\n", fname));
3338                                         continue;
3339                                 }
3340                                 pstrcpy(destname,newname);
3341                                 
3342                                 if (!resolve_wildcards(fname,destname)) {
3343                                         DEBUG(6,("resolve_wildcards %s %s failed\n", 
3344                                                  fname, destname));
3345                                         continue;
3346                                 }
3347                                 
3348                                 if (!replace_if_exists && 
3349                                     vfs_file_exist(conn,destname, NULL)) {
3350                                         DEBUG(6,("file_exist %s\n", destname));
3351                                         error = NT_STATUS_OBJECT_NAME_COLLISION;
3352                                         continue;
3353                                 }
3354                                 
3355                                 if (!conn->vfs_ops.rename(conn,fname,destname))
3356                                         count++;
3357                                 DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname));
3358                         }
3359                         CloseDir(dirptr);
3360                 }
3361         }
3362         
3363         if (count == 0 && NT_STATUS_IS_OK(error)) {
3364                 error = map_nt_error_from_unix(errno);
3365         }
3366         
3367         return error;
3368 }
3369
3370 /****************************************************************************
3371  Reply to a mv.
3372 ****************************************************************************/
3373
3374 int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, 
3375              int dum_buffsize)
3376 {
3377         int outsize = 0;
3378         pstring name;
3379         pstring newname;
3380         char *p;
3381         NTSTATUS status;
3382
3383         START_PROFILE(SMBmv);
3384
3385         p = smb_buf(inbuf) + 1;
3386         p += srvstr_pull_buf(inbuf, name, p, sizeof(name), STR_TERMINATE);
3387         p++;
3388         p += srvstr_pull_buf(inbuf, newname, p, sizeof(newname), STR_TERMINATE);
3389         
3390         RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
3391         RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
3392         
3393         DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
3394         
3395         status = rename_internals(conn, name, newname, False);
3396         if (!NT_STATUS_IS_OK(status)) {
3397                 return ERROR_NT(status);
3398         }
3399
3400         /*
3401          * Win2k needs a changenotify request response before it will
3402          * update after a rename..
3403          */     
3404         process_pending_change_notify_queue((time_t)0);
3405         outsize = set_message(outbuf,0,0,True);
3406   
3407         END_PROFILE(SMBmv);
3408         return(outsize);
3409 }
3410
3411 /*******************************************************************
3412  Copy a file as part of a reply_copy.
3413 ******************************************************************/
3414
3415 static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
3416                       int count,BOOL target_is_directory, int *err_ret)
3417 {
3418         int Access,action;
3419         SMB_STRUCT_STAT src_sbuf, sbuf2;
3420         SMB_OFF_T ret=-1;
3421         files_struct *fsp1,*fsp2;
3422         pstring dest;
3423   
3424         *err_ret = 0;
3425
3426         pstrcpy(dest,dest1);
3427         if (target_is_directory) {
3428                 char *p = strrchr_m(src,'/');
3429                 if (p) 
3430                         p++;
3431                 else
3432                         p = src;
3433                 pstrcat(dest,"/");
3434                 pstrcat(dest,p);
3435         }
3436
3437         if (!vfs_file_exist(conn,src,&src_sbuf))
3438                 return(False);
3439
3440         fsp1 = open_file_shared(conn,src,&src_sbuf,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
3441                                         (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),0,0,&Access,&action);
3442
3443         if (!fsp1)
3444                 return(False);
3445
3446         if (!target_is_directory && count)
3447                 ofun = FILE_EXISTS_OPEN;
3448
3449         if (vfs_stat(conn,dest,&sbuf2) == -1)
3450                 ZERO_STRUCTP(&sbuf2);
3451
3452         fsp2 = open_file_shared(conn,dest,&sbuf2,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_WRONLY),
3453                         ofun,src_sbuf.st_mode,0,&Access,&action);
3454
3455         if (!fsp2) {
3456                 close_file(fsp1,False);
3457                 return(False);
3458         }
3459
3460         if ((ofun&3) == 1) {
3461                 if(conn->vfs_ops.lseek(fsp2,fsp2->fd,0,SEEK_END) == -1) {
3462                         DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
3463                         /*
3464                          * Stop the copy from occurring.
3465                          */
3466                         ret = -1;
3467                         src_sbuf.st_size = 0;
3468                 }
3469         }
3470   
3471         if (src_sbuf.st_size)
3472                 ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_size);
3473
3474         close_file(fsp1,False);
3475
3476         /* Ensure the modtime is set correctly on the destination file. */
3477         fsp2->pending_modtime = src_sbuf.st_mtime;
3478
3479         /*
3480          * As we are opening fsp1 read-only we only expect
3481          * an error on close on fsp2 if we are out of space.
3482          * Thus we don't look at the error return from the
3483          * close of fsp1.
3484          */
3485         *err_ret = close_file(fsp2,False);
3486
3487         return(ret == (SMB_OFF_T)src_sbuf.st_size);
3488 }
3489
3490 /****************************************************************************
3491  Reply to a file copy.
3492 ****************************************************************************/
3493
3494 int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3495 {
3496         int outsize = 0;
3497         pstring name;
3498         pstring directory;
3499         pstring mask,newname;
3500         char *p;
3501         int count=0;
3502         int error = ERRnoaccess;
3503         int err = 0;
3504         BOOL has_wild;
3505         BOOL exists=False;
3506         int tid2 = SVAL(inbuf,smb_vwv0);
3507         int ofun = SVAL(inbuf,smb_vwv1);
3508         int flags = SVAL(inbuf,smb_vwv2);
3509         BOOL target_is_directory=False;
3510         BOOL bad_path1 = False;
3511         BOOL bad_path2 = False;
3512         BOOL rc = True;
3513         SMB_STRUCT_STAT sbuf1, sbuf2;
3514
3515         START_PROFILE(SMBcopy);
3516
3517         *directory = *mask = 0;
3518
3519         p = smb_buf(inbuf);
3520         p += srvstr_pull_buf(inbuf, name, p, sizeof(name), STR_TERMINATE);
3521         p += srvstr_pull_buf(inbuf, newname, p, sizeof(newname), STR_TERMINATE);
3522    
3523         DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
3524    
3525         if (tid2 != conn->cnum) {
3526                 /* can't currently handle inter share copies XXXX */
3527                 DEBUG(3,("Rejecting inter-share copy\n"));
3528                 END_PROFILE(SMBcopy);
3529                 return ERROR_DOS(ERRSRV,ERRinvdevice);
3530         }
3531
3532         RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
3533         RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
3534
3535         rc = unix_convert(name,conn,0,&bad_path1,&sbuf1);
3536         unix_convert(newname,conn,0,&bad_path2,&sbuf2);
3537
3538         target_is_directory = VALID_STAT_OF_DIR(sbuf2);
3539
3540         if ((flags&1) && target_is_directory) {
3541                 END_PROFILE(SMBcopy);
3542                 return ERROR_DOS(ERRDOS,ERRbadfile);
3543         }
3544
3545         if ((flags&2) && !target_is_directory) {
3546                 END_PROFILE(SMBcopy);
3547                 return ERROR_DOS(ERRDOS,ERRbadpath);
3548         }
3549
3550         if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) {
3551                 /* wants a tree copy! XXXX */
3552                 DEBUG(3,("Rejecting tree copy\n"));
3553                 END_PROFILE(SMBcopy);
3554                 return ERROR_DOS(ERRSRV,ERRerror);
3555         }
3556
3557         p = strrchr_m(name,'/');
3558         if (!p) {
3559                 pstrcpy(directory,"./");
3560                 pstrcpy(mask,name);
3561         } else {
3562                 *p = 0;
3563                 pstrcpy(directory,name);
3564                 pstrcpy(mask,p+1);
3565         }
3566
3567         /*
3568          * We should only check the mangled cache
3569          * here if unix_convert failed. This means
3570          * that the path in 'mask' doesn't exist
3571          * on the file system and so we need to look
3572          * for a possible mangle. This patch from
3573          * Tine Smukavec <valentin.smukavec@hermes.si>.
3574          */
3575
3576         if (!rc && mangle_is_mangled(mask))
3577                 mangle_check_cache( mask );
3578
3579         has_wild = ms_has_wild(mask);
3580
3581         if (!has_wild) {
3582                 pstrcat(directory,"/");
3583                 pstrcat(directory,mask);
3584                 if (resolve_wildcards(directory,newname) &&
3585                                 copy_file(directory,newname,conn,ofun, count,target_is_directory,&err))
3586                         count++;
3587                 if(!count && err) {
3588                         errno = err;
3589                         END_PROFILE(SMBcopy);
3590                         return(UNIXERROR(ERRHRD,ERRgeneral));
3591                 }
3592                 if (!count) {
3593                         exists = vfs_file_exist(conn,directory,NULL);
3594                 }
3595         } else {
3596                 void *dirptr = NULL;
3597                 const char *dname;
3598                 pstring destname;
3599
3600                 if (check_name(directory,conn))
3601                         dirptr = OpenDir(conn, directory, True);
3602
3603                 if (dirptr) {
3604                         error = ERRbadfile;
3605
3606                         if (strequal(mask,"????????.???"))
3607                                 pstrcpy(mask,"*");
3608
3609                         while ((dname = ReadDirName(dirptr))) {
3610                                 pstring fname;
3611                                 pstrcpy(fname,dname);
3612     
3613                                 if(!mask_match(fname, mask, case_sensitive))
3614                                         continue;
3615
3616                                 error = ERRnoaccess;
3617                                 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
3618                                 pstrcpy(destname,newname);
3619                                 if (resolve_wildcards(fname,destname) && 
3620                                                 copy_file(fname,destname,conn,ofun,
3621                                                 count,target_is_directory,&err))
3622                                         count++;
3623                                 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
3624                         }
3625                         CloseDir(dirptr);
3626                 }
3627         }
3628   
3629         if (count == 0) {
3630                 if(err) {
3631                         /* Error on close... */
3632                         errno = err;
3633                         END_PROFILE(SMBcopy);
3634                         return(UNIXERROR(ERRHRD,ERRgeneral));
3635                 }
3636
3637                 if (exists) {
3638                         END_PROFILE(SMBcopy);
3639                         return ERROR_DOS(ERRDOS,error);
3640                 } else {
3641                         if((errno == ENOENT) && (bad_path1 || bad_path2)) {
3642                                 unix_ERR_class = ERRDOS;
3643                                 unix_ERR_code = ERRbadpath;
3644                         }
3645                         END_PROFILE(SMBcopy);
3646                         return(UNIXERROR(ERRDOS,error));
3647                 }
3648         }
3649   
3650         outsize = set_message(outbuf,1,0,True);
3651         SSVAL(outbuf,smb_vwv0,count);
3652
3653         END_PROFILE(SMBcopy);
3654         return(outsize);
3655 }
3656
3657 /****************************************************************************
3658  Reply to a setdir.
3659 ****************************************************************************/
3660
3661 int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3662 {
3663         int snum;
3664         int outsize = 0;
3665         BOOL ok = False;
3666         pstring newdir;
3667
3668         START_PROFILE(pathworks_setdir);
3669   
3670         snum = SNUM(conn);
3671         if (!CAN_SETDIR(snum)) {
3672                 END_PROFILE(pathworks_setdir);
3673                 return ERROR_DOS(ERRDOS,ERRnoaccess);
3674         }
3675
3676         srvstr_pull_buf(inbuf, newdir, smb_buf(inbuf) + 1, sizeof(newdir), STR_TERMINATE);
3677   
3678         if (strlen(newdir) == 0) {
3679                 ok = True;
3680         } else {
3681                 ok = vfs_directory_exist(conn,newdir,NULL);
3682                 if (ok)
3683                         string_set(&conn->connectpath,newdir);
3684         }
3685   
3686         if (!ok) {
3687                 END_PROFILE(pathworks_setdir);
3688                 return ERROR_DOS(ERRDOS,ERRbadpath);
3689         }
3690   
3691         outsize = set_message(outbuf,0,0,True);
3692         SCVAL(outbuf,smb_reh,CVAL(inbuf,smb_reh));
3693   
3694         DEBUG(3,("setdir %s\n", newdir));
3695
3696         END_PROFILE(pathworks_setdir);
3697         return(outsize);
3698 }
3699
3700 /****************************************************************************
3701  Get a lock pid, dealing with large count requests.
3702 ****************************************************************************/
3703
3704 uint16 get_lock_pid( char *data, int data_offset, BOOL large_file_format)
3705 {
3706         if(!large_file_format)
3707                 return SVAL(data,SMB_LPID_OFFSET(data_offset));
3708         else
3709                 return SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
3710 }
3711
3712 /****************************************************************************
3713  Get a lock count, dealing with large count requests.
3714 ****************************************************************************/
3715
3716 SMB_BIG_UINT get_lock_count( char *data, int data_offset, BOOL large_file_format)
3717 {
3718         SMB_BIG_UINT count = 0;
3719
3720         if(!large_file_format) {
3721                 count = (SMB_BIG_UINT)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
3722         } else {
3723
3724 #if defined(HAVE_LONGLONG)
3725                 count = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
3726                         ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
3727 #else /* HAVE_LONGLONG */
3728
3729                 /*
3730                  * NT4.x seems to be broken in that it sends large file (64 bit)
3731                  * lockingX calls even if the CAP_LARGE_FILES was *not*
3732                  * negotiated. For boxes without large unsigned ints truncate the
3733                  * lock count by dropping the top 32 bits.
3734                  */
3735
3736                 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
3737                         DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
3738                                 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
3739                                 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
3740                                 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
3741                 }
3742
3743                 count = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
3744 #endif /* HAVE_LONGLONG */
3745         }
3746
3747         return count;
3748 }
3749
3750 #if !defined(HAVE_LONGLONG)
3751 /****************************************************************************
3752  Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
3753 ****************************************************************************/
3754
3755 static uint32 map_lock_offset(uint32 high, uint32 low)
3756 {
3757         unsigned int i;
3758         uint32 mask = 0;
3759         uint32 highcopy = high;
3760  
3761         /*
3762          * Try and find out how many significant bits there are in high.
3763          */
3764  
3765         for(i = 0; highcopy; i++)
3766                 highcopy >>= 1;
3767  
3768         /*
3769          * We use 31 bits not 32 here as POSIX
3770          * lock offsets may not be negative.
3771          */
3772  
3773         mask = (~0) << (31 - i);
3774  
3775         if(low & mask)
3776                 return 0; /* Fail. */
3777  
3778         high <<= (31 - i);
3779  
3780         return (high|low);
3781 }
3782 #endif /* !defined(HAVE_LONGLONG) */
3783
3784 /****************************************************************************
3785  Get a lock offset, dealing with large offset requests.
3786 ****************************************************************************/
3787
3788 SMB_BIG_UINT get_lock_offset( char *data, int data_offset, BOOL large_file_format, BOOL *err)
3789 {
3790         SMB_BIG_UINT offset = 0;
3791
3792         *err = False;
3793
3794         if(!large_file_format) {
3795                 offset = (SMB_BIG_UINT)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
3796         } else {
3797
3798 #if defined(HAVE_LONGLONG)
3799                 offset = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
3800                                 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
3801 #else /* HAVE_LONGLONG */
3802
3803                 /*
3804                  * NT4.x seems to be broken in that it sends large file (64 bit)
3805                  * lockingX calls even if the CAP_LARGE_FILES was *not*
3806                  * negotiated. For boxes without large unsigned ints mangle the
3807                  * lock offset by mapping the top 32 bits onto the lower 32.
3808                  */
3809       
3810                 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
3811                         uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
3812                         uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
3813                         uint32 new_low = 0;
3814
3815                         if((new_low = map_lock_offset(high, low)) == 0) {
3816                                 *err = True;
3817                                 return (SMB_BIG_UINT)-1;
3818                         }
3819
3820                         DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
3821                                 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
3822                         SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
3823                         SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
3824                 }
3825
3826                 offset = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
3827 #endif /* HAVE_LONGLONG */
3828         }
3829
3830         return offset;
3831 }
3832
3833 /****************************************************************************
3834  Reply to a lockingX request.
3835 ****************************************************************************/
3836
3837 int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
3838 {
3839         files_struct *fsp = file_fsp(inbuf,smb_vwv2);
3840         unsigned char locktype = CVAL(inbuf,smb_vwv3);
3841         unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
3842         uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
3843         uint16 num_locks = SVAL(inbuf,smb_vwv7);
3844         SMB_BIG_UINT count = 0, offset = 0;
3845         uint16 lock_pid;
3846         int32 lock_timeout = IVAL(inbuf,smb_vwv4);
3847         int i;
3848         char *data;
3849         BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
3850         BOOL err;
3851         NTSTATUS status;
3852
3853         START_PROFILE(SMBlockingX);
3854         
3855         CHECK_FSP(fsp,conn);
3856         
3857         data = smb_buf(inbuf);
3858
3859         if (locktype & (LOCKING_ANDX_CANCEL_LOCK | LOCKING_ANDX_CHANGE_LOCKTYPE)) {
3860                 /* we don't support these - and CANCEL_LOCK makes w2k
3861                    and XP reboot so I don't really want to be
3862                    compatible! (tridge) */
3863                 return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
3864         }
3865         
3866         /* Check if this is an oplock break on a file
3867            we have granted an oplock on.
3868         */
3869         if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
3870                 /* Client can insist on breaking to none. */
3871                 BOOL break_to_none = (oplocklevel == 0);
3872                 
3873                 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client for fnum = %d\n",
3874                          (unsigned int)oplocklevel, fsp->fnum ));
3875
3876                 /*
3877                  * Make sure we have granted an exclusive or batch oplock on this file.
3878                  */
3879                 
3880                 if(!EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
3881                         DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \
3882 no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name));
3883
3884                         /* if this is a pure oplock break request then don't send a reply */
3885                         if (num_locks == 0 && num_ulocks == 0) {
3886                                 END_PROFILE(SMBlockingX);
3887                                 return -1;
3888                         } else {
3889                                 END_PROFILE(SMBlockingX);
3890                                 return ERROR_DOS(ERRDOS,ERRlock);
3891                         }
3892                 }
3893
3894                 if (remove_oplock(fsp, break_to_none) == False) {
3895                         DEBUG(0,("reply_lockingX: error in removing oplock on file %s\n",
3896                                  fsp->fsp_name ));
3897                 }
3898                 
3899                 /* if this is a pure oplock break request then don't send a reply */
3900                 if (num_locks == 0 && num_ulocks == 0) {
3901                         /* Sanity check - ensure a pure oplock break is not a
3902                            chained request. */
3903                         if(CVAL(inbuf,smb_vwv0) != 0xff)
3904                                 DEBUG(0,("reply_lockingX: Error : pure oplock break is a chained %d request !\n",
3905                                          (unsigned int)CVAL(inbuf,smb_vwv0) ));
3906                         END_PROFILE(SMBlockingX);
3907                         return -1;
3908                 }
3909         }
3910
3911         /*
3912          * We do this check *after* we have checked this is not a oplock break
3913          * response message. JRA.
3914          */
3915         
3916         release_level_2_oplocks_on_change(fsp);
3917         
3918         /* Data now points at the beginning of the list
3919            of smb_unlkrng structs */
3920         for(i = 0; i < (int)num_ulocks; i++) {
3921                 lock_pid = get_lock_pid( data, i, large_file_format);
3922                 count = get_lock_count( data, i, large_file_format);
3923                 offset = get_lock_offset( data, i, large_file_format, &err);
3924                 
3925                 /*
3926                  * There is no error code marked "stupid client bug".... :-).
3927                  */
3928                 if(err) {
3929                         END_PROFILE(SMBlockingX);
3930                         return ERROR_DOS(ERRDOS,ERRnoaccess);
3931                 }
3932
3933                 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for pid %u, file %s\n",
3934                           (double)offset, (double)count, (unsigned int)lock_pid, fsp->fsp_name ));
3935                 
3936                 status = do_unlock(fsp,conn,lock_pid,count,offset);
3937                 if (NT_STATUS_V(status)) {
3938                         END_PROFILE(SMBlockingX);
3939                         return ERROR_NT(status);
3940                 }
3941         }
3942
3943         /* Setup the timeout in seconds. */
3944
3945         lock_timeout = ((lock_timeout == -1) ? -1 : (lock_timeout+999)/1000);
3946         
3947         /* Now do any requested locks */
3948         data += ((large_file_format ? 20 : 10)*num_ulocks);
3949         
3950         /* Data now points at the beginning of the list
3951            of smb_lkrng structs */
3952         
3953         for(i = 0; i < (int)num_locks; i++) {
3954                 lock_pid = get_lock_pid( data, i, large_file_format);
3955                 count = get_lock_count( data, i, large_file_format);
3956                 offset = get_lock_offset( data, i, large_file_format, &err);
3957                 
3958                 /*
3959                  * There is no error code marked "stupid client bug".... :-).
3960                  */
3961                 if(err) {
3962                         END_PROFILE(SMBlockingX);
3963                         return ERROR_DOS(ERRDOS,ERRnoaccess);
3964                 }
3965                 
3966                 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid %u, file %s timeout = %d\n",
3967                         (double)offset, (double)count, (unsigned int)lock_pid,
3968                         fsp->fsp_name, (int)lock_timeout ));
3969                 
3970                 status = do_lock_spin(fsp,conn,lock_pid, count,offset, 
3971                                  ((locktype & 1) ? READ_LOCK : WRITE_LOCK));
3972                 if (NT_STATUS_V(status)) {
3973                         if ((lock_timeout != 0) && lp_blocking_locks(SNUM(conn)) && ERROR_WAS_LOCK_DENIED(status)) {
3974                                 /*
3975                                  * A blocking lock was requested. Package up
3976                                  * this smb into a queued request and push it
3977                                  * onto the blocking lock queue.
3978                                  */
3979                                 if(push_blocking_lock_request(inbuf, length, lock_timeout, i, lock_pid, offset, count)) {
3980                                         END_PROFILE(SMBlockingX);
3981                                         return -1;
3982                                 }
3983                         }
3984                         break;
3985                 }
3986         }
3987         
3988         /* If any of the above locks failed, then we must unlock
3989            all of the previous locks (X/Open spec). */
3990         if (i != num_locks && num_locks != 0) {
3991                 /*
3992                  * Ensure we don't do a remove on the lock that just failed,
3993                  * as under POSIX rules, if we have a lock already there, we
3994                  * will delete it (and we shouldn't) .....
3995                  */
3996                 for(i--; i >= 0; i--) {
3997                         lock_pid = get_lock_pid( data, i, large_file_format);
3998                         count = get_lock_count( data, i, large_file_format);
3999                         offset = get_lock_offset( data, i, large_file_format, &err);
4000                         
4001                         /*
4002                          * There is no error code marked "stupid client bug".... :-).
4003                          */
4004                         if(err) {
4005                                 END_PROFILE(SMBlockingX);
4006                                 return ERROR_DOS(ERRDOS,ERRnoaccess);
4007                         }
4008                         
4009                         do_unlock(fsp,conn,lock_pid,count,offset);
4010                 }
4011                 END_PROFILE(SMBlockingX);
4012                 return ERROR_NT(status);
4013         }
4014
4015         set_message(outbuf,2,0,True);
4016         
4017         DEBUG( 3, ( "lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
4018                     fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks ) );
4019         
4020         END_PROFILE(SMBlockingX);
4021         return chain_reply(inbuf,outbuf,length,bufsize);
4022 }
4023
4024 /****************************************************************************
4025  Reply to a SMBreadbmpx (read block multiplex) request.
4026 ****************************************************************************/
4027
4028 int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
4029 {
4030         ssize_t nread = -1;
4031         ssize_t total_read;
4032         char *data;
4033         SMB_OFF_T startpos;
4034         int outsize;
4035         size_t maxcount;
4036         int max_per_packet;
4037         size_t tcount;
4038         int pad;
4039         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4040         START_PROFILE(SMBreadBmpx);
4041
4042         /* this function doesn't seem to work - disable by default */
4043         if (!lp_readbmpx()) {
4044                 END_PROFILE(SMBreadBmpx);
4045                 return ERROR_DOS(ERRSRV,ERRuseSTD);
4046         }
4047
4048         outsize = set_message(outbuf,8,0,True);
4049
4050         CHECK_FSP(fsp,conn);
4051         CHECK_READ(fsp);
4052
4053         startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
4054         maxcount = SVAL(inbuf,smb_vwv3);
4055
4056         data = smb_buf(outbuf);
4057         pad = ((long)data)%4;
4058         if (pad)
4059                 pad = 4 - pad;
4060         data += pad;
4061
4062         max_per_packet = bufsize-(outsize+pad);
4063         tcount = maxcount;
4064         total_read = 0;
4065
4066         if (is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
4067                 END_PROFILE(SMBreadBmpx);
4068                 return ERROR_DOS(ERRDOS,ERRlock);
4069         }
4070
4071         do {
4072                 size_t N = MIN(max_per_packet,tcount-total_read);
4073   
4074                 nread = read_file(fsp,data,startpos,N);
4075
4076                 if (nread <= 0)
4077                         nread = 0;
4078
4079                 if (nread < (ssize_t)N)
4080                         tcount = total_read + nread;
4081
4082                 set_message(outbuf,8,nread,False);
4083                 SIVAL(outbuf,smb_vwv0,startpos);
4084                 SSVAL(outbuf,smb_vwv2,tcount);
4085                 SSVAL(outbuf,smb_vwv6,nread);
4086                 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
4087
4088                 if (!send_smb(smbd_server_fd(),outbuf))
4089                         exit_server("reply_readbmpx: send_smb failed.");
4090
4091                 total_read += nread;
4092                 startpos += nread;
4093         } while (total_read < (ssize_t)tcount);
4094
4095         END_PROFILE(SMBreadBmpx);
4096         return(-1);
4097 }
4098
4099 /****************************************************************************
4100  Reply to a SMBsetattrE.
4101 ****************************************************************************/
4102
4103 int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4104 {
4105         struct utimbuf unix_times;
4106         int outsize = 0;
4107         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4108         START_PROFILE(SMBsetattrE);
4109
4110         outsize = set_message(outbuf,0,0,True);
4111
4112         if(!fsp || (fsp->conn != conn)) {
4113                 END_PROFILE(SMBgetattrE);
4114                 return ERROR_DOS(ERRDOS,ERRbadfid);
4115         }
4116
4117         /*
4118          * Convert the DOS times into unix times. Ignore create
4119          * time as UNIX can't set this.
4120          */
4121
4122         unix_times.actime = make_unix_date2(inbuf+smb_vwv3);
4123         unix_times.modtime = make_unix_date2(inbuf+smb_vwv5);
4124   
4125         /* 
4126          * Patch from Ray Frush <frush@engr.colostate.edu>
4127          * Sometimes times are sent as zero - ignore them.
4128          */
4129
4130         if ((unix_times.actime == 0) && (unix_times.modtime == 0)) {
4131                 /* Ignore request */
4132                 if( DEBUGLVL( 3 ) ) {
4133                         dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
4134                         dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
4135                 }
4136                 END_PROFILE(SMBsetattrE);
4137                 return(outsize);
4138         } else if ((unix_times.actime != 0) && (unix_times.modtime == 0)) {
4139                 /* set modify time = to access time if modify time was 0 */
4140                 unix_times.modtime = unix_times.actime;
4141         }
4142
4143         /* Set the date on this file */
4144         if(file_utime(conn, fsp->fsp_name, &unix_times)) {
4145                 END_PROFILE(SMBsetattrE);
4146                 return ERROR_DOS(ERRDOS,ERRnoaccess);
4147         }
4148   
4149         DEBUG( 3, ( "reply_setattrE fnum=%d actime=%d modtime=%d\n",
4150                 fsp->fnum, (int)unix_times.actime, (int)unix_times.modtime ) );
4151
4152         END_PROFILE(SMBsetattrE);
4153         return(outsize);
4154 }
4155
4156
4157 /* Back from the dead for OS/2..... JRA. */
4158
4159 /****************************************************************************
4160  Reply to a SMBwritebmpx (write block multiplex primary) request.
4161 ****************************************************************************/
4162
4163 int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4164 {
4165         size_t numtowrite;
4166         ssize_t nwritten = -1;
4167         int outsize = 0;
4168         SMB_OFF_T startpos;
4169         size_t tcount;
4170         BOOL write_through;
4171         int smb_doff;
4172         char *data;
4173         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4174         START_PROFILE(SMBwriteBmpx);
4175
4176         CHECK_FSP(fsp,conn);
4177         CHECK_WRITE(fsp);
4178         CHECK_ERROR(fsp);
4179
4180         tcount = SVAL(inbuf,smb_vwv1);
4181         startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
4182         write_through = BITSETW(inbuf+smb_vwv7,0);
4183         numtowrite = SVAL(inbuf,smb_vwv10);
4184         smb_doff = SVAL(inbuf,smb_vwv11);
4185
4186         data = smb_base(inbuf) + smb_doff;
4187
4188         /* If this fails we need to send an SMBwriteC response,
4189                 not an SMBwritebmpx - set this up now so we don't forget */
4190         SCVAL(outbuf,smb_com,SMBwritec);
4191
4192         if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos,WRITE_LOCK,False)) {
4193                 END_PROFILE(SMBwriteBmpx);
4194                 return(ERROR_DOS(ERRDOS,ERRlock));
4195         }
4196
4197         nwritten = write_file(fsp,data,startpos,numtowrite);
4198
4199         if(lp_syncalways(SNUM(conn)) || write_through)
4200                 sync_file(conn,fsp);
4201   
4202         if(nwritten < (ssize_t)numtowrite) {
4203                 END_PROFILE(SMBwriteBmpx);
4204                 return(UNIXERROR(ERRHRD,ERRdiskfull));
4205         }
4206
4207         /* If the maximum to be written to this file
4208                 is greater than what we just wrote then set
4209                 up a secondary struct to be attached to this
4210                 fd, we will use this to cache error messages etc. */
4211
4212         if((ssize_t)tcount > nwritten) {
4213                 write_bmpx_struct *wbms;
4214                 if(fsp->wbmpx_ptr != NULL)
4215                         wbms = fsp->wbmpx_ptr; /* Use an existing struct */
4216                 else
4217                         wbms = (write_bmpx_struct *)malloc(sizeof(write_bmpx_struct));
4218                 if(!wbms) {
4219                         DEBUG(0,("Out of memory in reply_readmpx\n"));
4220                         END_PROFILE(SMBwriteBmpx);
4221                         return(ERROR_DOS(ERRSRV,ERRnoresource));
4222                 }
4223                 wbms->wr_mode = write_through;
4224                 wbms->wr_discard = False; /* No errors yet */
4225                 wbms->wr_total_written = nwritten;
4226                 wbms->wr_errclass = 0;
4227                 wbms->wr_error = 0;
4228                 fsp->wbmpx_ptr = wbms;
4229         }
4230
4231         /* We are returning successfully, set the message type back to
4232                 SMBwritebmpx */
4233         SCVAL(outbuf,smb_com,SMBwriteBmpx);
4234   
4235         outsize = set_message(outbuf,1,0,True);
4236   
4237         SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
4238   
4239         DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
4240                         fsp->fnum, (int)numtowrite, (int)nwritten ) );
4241
4242         if (write_through && tcount==nwritten) {
4243                 /* We need to send both a primary and a secondary response */
4244                 smb_setlen(outbuf,outsize - 4);
4245                 if (!send_smb(smbd_server_fd(),outbuf))
4246                         exit_server("reply_writebmpx: send_smb failed.");
4247
4248                 /* Now the secondary */
4249                 outsize = set_message(outbuf,1,0,True);
4250                 SCVAL(outbuf,smb_com,SMBwritec);
4251                 SSVAL(outbuf,smb_vwv0,nwritten);
4252         }
4253
4254         END_PROFILE(SMBwriteBmpx);
4255         return(outsize);
4256 }
4257
4258 /****************************************************************************
4259  Reply to a SMBwritebs (write block multiplex secondary) request.
4260 ****************************************************************************/
4261
4262 int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4263 {
4264         size_t numtowrite;
4265         ssize_t nwritten = -1;
4266         int outsize = 0;
4267         SMB_OFF_T startpos;
4268         size_t tcount;
4269         BOOL write_through;
4270         int smb_doff;
4271         char *data;
4272         write_bmpx_struct *wbms;
4273         BOOL send_response = False; 
4274         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4275         START_PROFILE(SMBwriteBs);
4276
4277         CHECK_FSP(fsp,conn);
4278         CHECK_WRITE(fsp);
4279
4280         tcount = SVAL(inbuf,smb_vwv1);
4281         startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
4282         numtowrite = SVAL(inbuf,smb_vwv6);
4283         smb_doff = SVAL(inbuf,smb_vwv7);
4284
4285         data = smb_base(inbuf) + smb_doff;
4286
4287         /* We need to send an SMBwriteC response, not an SMBwritebs */
4288         SCVAL(outbuf,smb_com,SMBwritec);
4289
4290         /* This fd should have an auxiliary struct attached,
4291                 check that it does */
4292         wbms = fsp->wbmpx_ptr;
4293         if(!wbms) {
4294                 END_PROFILE(SMBwriteBs);
4295                 return(-1);
4296         }
4297
4298         /* If write through is set we can return errors, else we must cache them */
4299         write_through = wbms->wr_mode;
4300
4301         /* Check for an earlier error */
4302         if(wbms->wr_discard) {
4303                 END_PROFILE(SMBwriteBs);
4304                 return -1; /* Just discard the packet */
4305         }
4306
4307         nwritten = write_file(fsp,data,startpos,numtowrite);
4308
4309         if(lp_syncalways(SNUM(conn)) || write_through)
4310                 sync_file(conn,fsp);
4311   
4312         if (nwritten < (ssize_t)numtowrite) {
4313                 if(write_through) {
4314                         /* We are returning an error - we can delete the aux struct */
4315                         if (wbms)
4316                                 free((char *)wbms);
4317                         fsp->wbmpx_ptr = NULL;
4318                         END_PROFILE(SMBwriteBs);
4319                         return(ERROR_DOS(ERRHRD,ERRdiskfull));
4320                 }
4321                 END_PROFILE(SMBwriteBs);
4322                 return(CACHE_ERROR(wbms,ERRHRD,ERRdiskfull));
4323         }
4324
4325         /* Increment the total written, if this matches tcount
4326                 we can discard the auxiliary struct (hurrah !) and return a writeC */
4327         wbms->wr_total_written += nwritten;
4328         if(wbms->wr_total_written >= tcount) {
4329                 if (write_through) {
4330                         outsize = set_message(outbuf,1,0,True);
4331                         SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);    
4332                         send_response = True;
4333                 }
4334
4335                 free((char *)wbms);
4336                 fsp->wbmpx_ptr = NULL;
4337         }
4338
4339         if(send_response) {
4340                 END_PROFILE(SMBwriteBs);
4341                 return(outsize);
4342         }
4343
4344         END_PROFILE(SMBwriteBs);
4345         return(-1);
4346 }
4347
4348 /****************************************************************************
4349  Reply to a SMBgetattrE.
4350 ****************************************************************************/
4351
4352 int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4353 {
4354         SMB_STRUCT_STAT sbuf;
4355         int outsize = 0;
4356         int mode;
4357         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4358         START_PROFILE(SMBgetattrE);
4359
4360         outsize = set_message(outbuf,11,0,True);
4361
4362         if(!fsp || (fsp->conn != conn)) {
4363                 END_PROFILE(SMBgetattrE);
4364                 return ERROR_DOS(ERRDOS,ERRbadfid);
4365         }
4366
4367         /* Do an fstat on this file */
4368         if(fsp_stat(fsp, &sbuf)) {
4369                 END_PROFILE(SMBgetattrE);
4370                 return(UNIXERROR(ERRDOS,ERRnoaccess));
4371         }
4372   
4373         mode = dos_mode(conn,fsp->fsp_name,&sbuf);
4374   
4375         /*
4376          * Convert the times into dos times. Set create
4377          * date to be last modify date as UNIX doesn't save
4378          * this.
4379          */
4380
4381         put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
4382         put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
4383         put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
4384
4385         if (mode & aDIR) {
4386                 SIVAL(outbuf,smb_vwv6,0);
4387                 SIVAL(outbuf,smb_vwv8,0);
4388         } else {
4389                 SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
4390                 SIVAL(outbuf,smb_vwv8,SMB_ROUNDUP(sbuf.st_size,1024));
4391         }
4392         SSVAL(outbuf,smb_vwv10, mode);
4393   
4394         DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
4395   
4396         END_PROFILE(SMBgetattrE);
4397         return(outsize);
4398 }