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