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