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