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