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