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