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