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