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