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