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