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