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