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