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