SAM database "set user info".
[samba.git] / source / smbd / reply.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 1.9.
4    Main SMB reply routines
5    Copyright (C) Andrew Tridgell 1992-1998
6    
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11    
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16    
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21 /*
22    This file handles most of the reply_ calls that the server
23    makes to handle specific protocols
24 */
25
26
27 #include "includes.h"
28 #include "trans2.h"
29 #include "nterr.h"
30
31 /* look in server.c for some explanation of these variables */
32 extern int Protocol;
33 extern int DEBUGLEVEL;
34 extern int max_send;
35 extern int max_recv;
36 extern char magic_char;
37 extern BOOL case_sensitive;
38 extern BOOL case_preserve;
39 extern BOOL short_case_preserve;
40 extern pstring sesssetup_user;
41 extern 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
629   DEBUG(3,("sesssetupX:name=[%s]\n",user));
630
631   /* If name ends in $ then I think it's asking about whether a */
632   /* computer with that name (minus the $) has access. For now */
633   /* say yes to everything ending in $. */
634   if ((user[strlen(user) - 1] == '$') && (smb_apasslen == 24) && (smb_ntpasslen == 24))
635   {
636     return session_trust_account(conn, inbuf, outbuf, user, 
637                                  smb_apasswd, smb_apasslen,
638                                  smb_ntpasswd, smb_ntpasslen);
639   }
640
641   /* If no username is sent use the guest account */
642   if (!*user)
643   {
644     pstrcpy(user,lp_guestaccount(-1));
645     /* If no user and no password then set guest flag. */
646     if( *smb_apasswd == 0)
647       guest = True;
648   }
649
650   strlower(user);
651
652   /*
653    * In share level security, only overwrite sesssetup_use if
654    * it's a non null-session share. Helps keep %U and %G
655    * working.
656    */
657
658   if((lp_security() != SEC_SHARE) || (*user && !guest))
659     pstrcpy(sesssetup_user,user);
660
661   reload_services(True);
662
663   /*
664    * Save the username before mapping. We will use
665    * the original username sent to us for security=server
666    * and security=domain checking.
667    */
668
669   pstrcpy( orig_user, user);
670
671         map_nt_and_unix_username(domain, user);
672
673   add_session_user(user);
674
675   /*
676    * Check if the given username was the guest user with no password.
677    */
678
679   if(!guest && strequal(user,lp_guestaccount(-1)) && (*smb_apasswd == 0))
680     guest = True;
681
682   /* 
683    * Check with orig_user for security=server and
684    * security=domain.
685    */
686
687   if (!guest && 
688       !check_server_security(orig_user, domain,
689                              smb_apasswd, smb_apasslen,
690                              smb_ntpasswd, smb_ntpasslen) &&
691       !check_domain_security(orig_user, domain,
692                              smb_apasswd, smb_apasslen,
693                              smb_ntpasswd, smb_ntpasslen) &&
694       !check_hosts_equiv(user)
695      )
696   {
697
698     /* 
699      * If we get here then the user wasn't guest and the remote
700      * authentication methods failed. Check the authentication
701      * methods on this local server.
702      *
703      * If an NT password was supplied try and validate with that
704      * first. This is superior as the passwords are mixed case 
705      * 128 length unicode.
706       */
707
708     if(smb_ntpasslen)
709     {
710       if(!password_ok(user, smb_ntpasswd,smb_ntpasslen,NULL,user_sess_key))
711         DEBUG(0,("NT Password did not match ! Defaulting to Lanman\n"));
712       else
713         valid_nt_password = True;
714     } 
715
716     if (!valid_nt_password && !password_ok(user, smb_apasswd,smb_apasslen,NULL,user_sess_key))
717     {
718       if (lp_security() >= SEC_USER) 
719       {
720         if (lp_map_to_guest() == NEVER_MAP_TO_GUEST)
721           return(ERROR(ERRSRV,ERRbadpw));
722
723         if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_USER)
724         {
725          if (Get_Pwnam(user,True))
726             return(ERROR(ERRSRV,ERRbadpw));
727         }
728
729         /*
730          * ..else if lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD
731          * Then always map to guest account - as done below.
732          */
733       }
734
735       if (*smb_apasswd || !Get_Pwnam(user,True))
736          pstrcpy(user,lp_guestaccount(-1));
737       DEBUG(3,("Registered username %s for guest access\n",user));
738       guest = True;
739     }
740   }
741
742   if (!Get_Pwnam(user,True)) {
743     DEBUG(3,("No such user %s - using guest account\n",user));
744     pstrcpy(user,lp_guestaccount(-1));
745     guest = True;
746   }
747
748   if (!strequal(user,lp_guestaccount(-1)) &&
749       lp_servicenumber(user) < 0)      
750   {
751     int homes = lp_servicenumber(HOMES_NAME);
752     char *home = get_home_dir(user);
753     if (homes >= 0 && home)
754         {
755                 pstring home_dir;
756                 fstrcpy(home_dir, home);
757                 lp_add_home(user,homes,home_dir);
758         }
759   }
760
761
762   /* it's ok - setup a reply */
763   if (Protocol < PROTOCOL_NT1) {
764     set_message(outbuf,3,0,True);
765   } else {
766     char *p;
767     set_message(outbuf,3,3,True);
768     p = smb_buf(outbuf);
769     pstrcpy(p,"Unix"); p = skip_string(p,1);
770     pstrcpy(p,"Samba "); pstrcat(p,VERSION); p = skip_string(p,1);
771     pstrcpy(p,global_myworkgroup); p = skip_string(p,1);
772     set_message(outbuf,3,PTR_DIFF(p,smb_buf(outbuf)),False);
773     /* perhaps grab OS version here?? */
774   }
775
776   /* Set the correct uid in the outgoing and incoming packets
777      We will use this on future requests to determine which
778      user we should become.
779      */
780   {
781     struct passwd *pw = Get_Pwnam(user,False);
782     if (!pw) {
783       DEBUG(1,("Username %s is invalid on this system\n",user));
784       return(ERROR(ERRSRV,ERRbadpw));
785     }
786     gid = pw->pw_gid;
787     uid = pw->pw_uid;
788   }
789
790   if (guest)
791     SSVAL(outbuf,smb_vwv2,1);
792
793   /* register the name and uid as being validated, so further connections
794      to a uid can get through without a password, on the same VC */
795   sess_vuid = register_vuid(uid,gid,user,sesssetup_user,guest,user_sess_key);
796  
797   SSVAL(outbuf,smb_uid,sess_vuid);
798   SSVAL(inbuf,smb_uid,sess_vuid);
799
800   if (!done_sesssetup)
801     max_send = MIN(max_send,smb_bufsize);
802
803   DEBUG(6,("Client requested max send size of %d\n", max_send));
804
805   done_sesssetup = True;
806
807   return chain_reply(inbuf,outbuf,length,bufsize);
808 }
809
810
811 /****************************************************************************
812   reply to a chkpth
813 ****************************************************************************/
814 int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
815 {
816   int outsize = 0;
817   int mode;
818   pstring name;
819   BOOL ok = False;
820   BOOL bad_path = False;
821   SMB_STRUCT_STAT st;
822  
823   pstrcpy(name,smb_buf(inbuf) + 1);
824   unix_convert(name,conn,0,&bad_path,&st);
825
826   mode = SVAL(inbuf,smb_vwv0);
827
828   if (check_name(name,conn)) {
829     if(VALID_STAT(st))
830       ok = S_ISDIR(st.st_mode);
831     else
832       ok = dos_directory_exist(name,NULL);
833   }
834
835   if (!ok)
836   {
837     /* We special case this - as when a Windows machine
838        is parsing a path is steps through the components
839        one at a time - if a component fails it expects
840        ERRbadpath, not ERRbadfile.
841      */
842     if(errno == ENOENT)
843     {
844       unix_ERR_class = ERRDOS;
845       unix_ERR_code = ERRbadpath;
846     }
847
848 #if 0
849     /* Ugly - NT specific hack - maybe not needed ? (JRA) */
850     if((errno == ENOTDIR) && (Protocol >= PROTOCOL_NT1) &&
851        (get_remote_arch() == RA_WINNT))
852     {
853       unix_ERR_class = ERRDOS;
854       unix_ERR_code = ERRbaddirectory;
855     }
856 #endif
857
858     return(UNIXERROR(ERRDOS,ERRbadpath));
859   }
860
861   outsize = set_message(outbuf,0,0,True);
862
863   DEBUG(3,("chkpth %s mode=%d\n", name, mode));
864
865   return(outsize);
866 }
867
868
869 /****************************************************************************
870   reply to a getatr
871 ****************************************************************************/
872 int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
873 {
874   pstring fname;
875   int outsize = 0;
876   SMB_STRUCT_STAT sbuf;
877   BOOL ok = False;
878   int mode=0;
879   SMB_OFF_T size=0;
880   time_t mtime=0;
881   BOOL bad_path = False;
882  
883   pstrcpy(fname,smb_buf(inbuf) + 1);
884
885   /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
886      under WfWg - weird! */
887   if (! (*fname))
888   {
889     mode = aHIDDEN | aDIR;
890     if (!CAN_WRITE(conn)) mode |= aRONLY;
891     size = 0;
892     mtime = 0;
893     ok = True;
894   }
895   else
896   {
897     unix_convert(fname,conn,0,&bad_path,&sbuf);
898     if (check_name(fname,conn))
899     {
900       if (VALID_STAT(sbuf) || dos_stat(fname,&sbuf) == 0)
901       {
902         mode = dos_mode(conn,fname,&sbuf);
903         size = sbuf.st_size;
904         mtime = sbuf.st_mtime;
905         if (mode & aDIR)
906           size = 0;
907         ok = True;
908       }
909       else
910         DEBUG(3,("stat of %s failed (%s)\n",fname,strerror(errno)));
911     }
912   }
913   
914   if (!ok)
915   {
916     if((errno == ENOENT) && bad_path)
917     {
918       unix_ERR_class = ERRDOS;
919       unix_ERR_code = ERRbadpath;
920     }
921
922     return(UNIXERROR(ERRDOS,ERRbadfile));
923   }
924  
925   outsize = set_message(outbuf,10,0,True);
926
927   SSVAL(outbuf,smb_vwv0,mode);
928   if(lp_dos_filetime_resolution(SNUM(conn)) )
929     put_dos_date3(outbuf,smb_vwv1,mtime & ~1);
930   else
931     put_dos_date3(outbuf,smb_vwv1,mtime);
932   SIVAL(outbuf,smb_vwv3,(uint32)size);
933
934   if (Protocol >= PROTOCOL_NT1) {
935     char *p = strrchr(fname,'/');
936     uint16 flg2 = SVAL(outbuf,smb_flg2);
937     if (!p) p = fname;
938     if (!is_8_3(fname, True))
939       SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */
940   }
941   
942   DEBUG( 3, ( "getatr name=%s mode=%d size=%d\n", fname, mode, (uint32)size ) );
943   
944   return(outsize);
945 }
946
947
948 /****************************************************************************
949   reply to a setatr
950 ****************************************************************************/
951 int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
952 {
953   pstring fname;
954   int outsize = 0;
955   BOOL ok=False;
956   int mode;
957   time_t mtime;
958   SMB_STRUCT_STAT st;
959   BOOL bad_path = False;
960  
961   pstrcpy(fname,smb_buf(inbuf) + 1);
962   unix_convert(fname,conn,0,&bad_path,&st);
963
964   mode = SVAL(inbuf,smb_vwv0);
965   mtime = make_unix_date3(inbuf+smb_vwv1);
966   
967   if (VALID_STAT_OF_DIR(st) || dos_directory_exist(fname,NULL))
968     mode |= aDIR;
969   if (check_name(fname,conn))
970     ok =  (file_chmod(conn,fname,mode,NULL) == 0);
971   if (ok)
972     ok = set_filetime(conn,fname,mtime);
973   
974   if (!ok)
975   {
976     if((errno == ENOENT) && bad_path)
977     {
978       unix_ERR_class = ERRDOS;
979       unix_ERR_code = ERRbadpath;
980     }
981
982     return(UNIXERROR(ERRDOS,ERRnoaccess));
983   }
984  
985   outsize = set_message(outbuf,0,0,True);
986   
987   DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
988   
989   return(outsize);
990 }
991
992
993 /****************************************************************************
994   reply to a dskattr
995 ****************************************************************************/
996 int reply_dskattr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
997 {
998   int outsize = 0;
999   SMB_BIG_UINT dfree,dsize,bsize;
1000   
1001   sys_disk_free(".",&bsize,&dfree,&dsize);
1002   
1003   outsize = set_message(outbuf,5,0,True);
1004   
1005   SSVAL(outbuf,smb_vwv0,dsize);
1006   SSVAL(outbuf,smb_vwv1,bsize/512);
1007   SSVAL(outbuf,smb_vwv2,512);
1008   SSVAL(outbuf,smb_vwv3,dfree);
1009
1010   DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1011
1012   return(outsize);
1013 }
1014
1015
1016 /****************************************************************************
1017   reply to a search
1018   Can be called from SMBsearch, SMBffirst or SMBfunique.
1019 ****************************************************************************/
1020 int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1021 {
1022   pstring mask;
1023   pstring directory;
1024   pstring fname;
1025   SMB_OFF_T size;
1026   int mode;
1027   time_t date;
1028   int dirtype;
1029   int outsize = 0;
1030   int numentries = 0;
1031   BOOL finished = False;
1032   int maxentries;
1033   int i;
1034   char *p;
1035   BOOL ok = False;
1036   int status_len;
1037   char *path;
1038   char status[21];
1039   int dptr_num= -1;
1040   BOOL check_descend = False;
1041   BOOL expect_close = False;
1042   BOOL can_open = True;
1043   BOOL bad_path = False;
1044
1045   *mask = *directory = *fname = 0;
1046
1047   /* If we were called as SMBffirst then we must expect close. */
1048   if(CVAL(inbuf,smb_com) == SMBffirst)
1049     expect_close = True;
1050   
1051   outsize = set_message(outbuf,1,3,True);
1052   maxentries = SVAL(inbuf,smb_vwv0); 
1053   dirtype = SVAL(inbuf,smb_vwv1);
1054   path = smb_buf(inbuf) + 1;
1055   status_len = SVAL(smb_buf(inbuf),3 + strlen(path));
1056
1057   
1058   /* dirtype &= ~aDIR; */
1059   
1060   DEBUG(5,("path=%s status_len=%d\n",path,status_len));
1061
1062   
1063   if (status_len == 0)
1064     {
1065       pstring dir2;
1066
1067       pstrcpy(directory,smb_buf(inbuf)+1);
1068       pstrcpy(dir2,smb_buf(inbuf)+1);
1069       unix_convert(directory,conn,0,&bad_path,NULL);
1070       unix_format(dir2);
1071
1072       if (!check_name(directory,conn))
1073         can_open = False;
1074
1075       p = strrchr(dir2,'/');
1076       if (p == NULL) 
1077       {
1078         pstrcpy(mask,dir2);
1079         *dir2 = 0;
1080       }
1081       else
1082       {
1083         *p = 0;
1084         pstrcpy(mask,p+1);
1085       }
1086
1087       p = strrchr(directory,'/');
1088       if (!p) 
1089         *directory = 0;
1090       else
1091         *p = 0;
1092
1093       if (strlen(directory) == 0)
1094         pstrcpy(directory,"./");
1095       bzero(status,21);
1096       CVAL(status,0) = dirtype;
1097     }
1098   else
1099     {
1100       memcpy(status,smb_buf(inbuf) + 1 + strlen(path) + 4,21);
1101       memcpy(mask,status+1,11);
1102       mask[11] = 0;
1103       dirtype = CVAL(status,0) & 0x1F;
1104       conn->dirptr = dptr_fetch(status+12,&dptr_num);      
1105       if (!conn->dirptr)
1106         goto SearchEmpty;
1107       string_set(&conn->dirpath,dptr_path(dptr_num));
1108       if (!case_sensitive)
1109         strnorm(mask);
1110     }
1111
1112   /* turn strings of spaces into a . */  
1113   {
1114     trim_string(mask,NULL," ");
1115     if ((p = strrchr(mask,' ')))
1116       {
1117         fstring ext;
1118         fstrcpy(ext,p+1);
1119         *p = 0;
1120         trim_string(mask,NULL," ");
1121         pstrcat(mask,".");
1122         pstrcat(mask,ext);
1123       }
1124   }
1125
1126   /* Convert the formatted mask. (This code lives in trans2.c) */
1127   mask_convert(mask);
1128
1129   {
1130     int skip;
1131     p = mask;
1132     while(*p)
1133     {
1134       if((skip = skip_multibyte_char( *p )) != 0 )
1135       {
1136         p += skip;
1137       }
1138       else
1139       {
1140         if (*p != '?' && *p != '*' && !isdoschar(*p))
1141         {
1142           DEBUG(5,("Invalid char [%c] in search mask?\n",*p));
1143           *p = '?';
1144         }
1145         p++;
1146       }
1147     }
1148   }
1149
1150   if (!strchr(mask,'.') && strlen(mask)>8)
1151     {
1152       fstring tmp;
1153       fstrcpy(tmp,&mask[8]);
1154       mask[8] = '.';
1155       mask[9] = 0;
1156       pstrcat(mask,tmp);
1157     }
1158
1159   DEBUG(5,("mask=%s directory=%s\n",mask,directory));
1160   
1161   if (can_open)
1162     {
1163       p = smb_buf(outbuf) + 3;
1164       
1165       ok = True;
1166       
1167       if (status_len == 0)
1168         {
1169           dptr_num = dptr_create(conn,directory,expect_close,SVAL(inbuf,smb_pid));
1170           if (dptr_num < 0)
1171         {
1172           if(dptr_num == -2)
1173           {
1174             if((errno == ENOENT) && bad_path)
1175             {
1176               unix_ERR_class = ERRDOS;
1177               unix_ERR_code = ERRbadpath;
1178             }
1179             return (UNIXERROR(ERRDOS,ERRnofids));
1180           }
1181           return(ERROR(ERRDOS,ERRnofids));
1182         }
1183         }
1184
1185       DEBUG(4,("dptr_num is %d\n",dptr_num));
1186
1187       if (ok)
1188         {
1189           if ((dirtype&0x1F) == aVOLID)
1190             {     
1191               memcpy(p,status,21);
1192               make_dir_struct(p,"???????????",volume_label(SNUM(conn)),0,aVOLID,0);
1193               dptr_fill(p+12,dptr_num);
1194               if (dptr_zero(p+12) && (status_len==0))
1195                 numentries = 1;
1196               else
1197                 numentries = 0;
1198               p += DIR_STRUCT_SIZE;
1199             }
1200           else 
1201             {
1202               DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1203                        conn->dirpath,lp_dontdescend(SNUM(conn))));
1204               if (in_list(conn->dirpath,
1205                           lp_dontdescend(SNUM(conn)),True))
1206                 check_descend = True;
1207
1208               for (i=numentries;(i<maxentries) && !finished;i++)
1209                 {
1210                   finished = 
1211                     !get_dir_entry(conn,mask,dirtype,fname,&size,&mode,&date,check_descend);
1212                   if (!finished)
1213                     {
1214                       memcpy(p,status,21);
1215                       make_dir_struct(p,mask,fname,size,mode,date);
1216                       dptr_fill(p+12,dptr_num);
1217                       numentries++;
1218                     }
1219                   p += DIR_STRUCT_SIZE;
1220                 }
1221             }
1222         }
1223     }
1224
1225
1226  SearchEmpty:
1227
1228   if (numentries == 0 || !ok)
1229     {
1230       CVAL(outbuf,smb_rcls) = ERRDOS;
1231       SSVAL(outbuf,smb_err,ERRnofiles);
1232     }
1233
1234   /* If we were called as SMBffirst with smb_search_id == NULL
1235      and no entries were found then return error and close dirptr 
1236      (X/Open spec) */
1237
1238   if(ok && expect_close && numentries == 0 && status_len == 0)
1239     {
1240       CVAL(outbuf,smb_rcls) = ERRDOS;
1241       SSVAL(outbuf,smb_err,ERRnofiles);
1242       /* Also close the dptr - we know it's gone */
1243       dptr_close(dptr_num);
1244     }
1245
1246   /* If we were called as SMBfunique, then we can close the dirptr now ! */
1247   if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique)
1248     dptr_close(dptr_num);
1249
1250   SSVAL(outbuf,smb_vwv0,numentries);
1251   SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1252   CVAL(smb_buf(outbuf),0) = 5;
1253   SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
1254
1255   if (Protocol >= PROTOCOL_NT1) {
1256     uint16 flg2 = SVAL(outbuf,smb_flg2);
1257     SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */
1258   }
1259   
1260   outsize += DIR_STRUCT_SIZE*numentries;
1261   smb_setlen(outbuf,outsize - 4);
1262   
1263   if ((! *directory) && dptr_path(dptr_num))
1264     slprintf(directory, sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1265
1266   DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%d of %d\n",
1267         smb_fn_name(CVAL(inbuf,smb_com)), 
1268         mask, directory, dirtype, numentries, maxentries ) );
1269
1270   return(outsize);
1271 }
1272
1273
1274 /****************************************************************************
1275   reply to a fclose (stop directory search)
1276 ****************************************************************************/
1277 int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1278 {
1279   int outsize = 0;
1280   int status_len;
1281   char *path;
1282   char status[21];
1283   int dptr_num= -1;
1284
1285   outsize = set_message(outbuf,1,0,True);
1286   path = smb_buf(inbuf) + 1;
1287   status_len = SVAL(smb_buf(inbuf),3 + strlen(path));
1288
1289   
1290   if (status_len == 0)
1291     return(ERROR(ERRSRV,ERRsrverror));
1292
1293   memcpy(status,smb_buf(inbuf) + 1 + strlen(path) + 4,21);
1294
1295   if(dptr_fetch(status+12,&dptr_num)) {
1296     /*  Close the dptr - we know it's gone */
1297     dptr_close(dptr_num);
1298   }
1299
1300   SSVAL(outbuf,smb_vwv0,0);
1301
1302   DEBUG(3,("search close\n"));
1303
1304   return(outsize);
1305 }
1306
1307
1308 /****************************************************************************
1309   reply to an open
1310 ****************************************************************************/
1311
1312 int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1313 {
1314   pstring fname;
1315   int outsize = 0;
1316   int fmode=0;
1317   int share_mode;
1318   SMB_OFF_T size = 0;
1319   time_t mtime=0;
1320   mode_t unixmode;
1321   int rmode=0;
1322   SMB_STRUCT_STAT sbuf;
1323   BOOL bad_path = False;
1324   files_struct *fsp;
1325   int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1326  
1327   share_mode = SVAL(inbuf,smb_vwv0);
1328
1329   pstrcpy(fname,smb_buf(inbuf)+1);
1330   unix_convert(fname,conn,0,&bad_path,NULL);
1331     
1332   fsp = file_new();
1333   if (!fsp)
1334     return(ERROR(ERRSRV,ERRnofids));
1335
1336   if (!check_name(fname,conn))
1337   {
1338     if((errno == ENOENT) && bad_path)
1339     {
1340       unix_ERR_class = ERRDOS;
1341       unix_ERR_code = ERRbadpath;
1342     }
1343     file_free(fsp);
1344     return(UNIXERROR(ERRDOS,ERRnoaccess));
1345   }
1346  
1347   unixmode = unix_mode(conn,aARCH);
1348       
1349   open_file_shared(fsp,conn,fname,share_mode,(FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
1350                    unixmode, oplock_request,&rmode,NULL);
1351
1352   if (!fsp->open)
1353   {
1354     if((errno == ENOENT) && bad_path)
1355     {
1356       unix_ERR_class = ERRDOS;
1357       unix_ERR_code = ERRbadpath;
1358     }
1359     file_free(fsp);
1360     return(UNIXERROR(ERRDOS,ERRnoaccess));
1361   }
1362
1363   if (sys_fstat(fsp->fd_ptr->fd,&sbuf) != 0) {
1364     close_file(fsp,False);
1365     return(ERROR(ERRDOS,ERRnoaccess));
1366   }
1367     
1368   size = sbuf.st_size;
1369   fmode = dos_mode(conn,fname,&sbuf);
1370   mtime = sbuf.st_mtime;
1371
1372   if (fmode & aDIR) {
1373     DEBUG(3,("attempt to open a directory %s\n",fname));
1374     close_file(fsp,False);
1375     return(ERROR(ERRDOS,ERRnoaccess));
1376   }
1377   
1378   outsize = set_message(outbuf,7,0,True);
1379   SSVAL(outbuf,smb_vwv0,fsp->fnum);
1380   SSVAL(outbuf,smb_vwv1,fmode);
1381   if(lp_dos_filetime_resolution(SNUM(conn)) )
1382     put_dos_date3(outbuf,smb_vwv2,mtime & ~1);
1383   else
1384     put_dos_date3(outbuf,smb_vwv2,mtime);
1385   SIVAL(outbuf,smb_vwv4,(uint32)size);
1386   SSVAL(outbuf,smb_vwv6,rmode);
1387
1388   if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1389     CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1390   }
1391     
1392   if(fsp->granted_oplock)
1393     CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1394   return(outsize);
1395 }
1396
1397
1398 /****************************************************************************
1399   reply to an open and X
1400 ****************************************************************************/
1401 int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1402 {
1403   pstring fname;
1404   int smb_mode = SVAL(inbuf,smb_vwv3);
1405   int smb_attr = SVAL(inbuf,smb_vwv5);
1406   /* Breakout the oplock request bits so we can set the
1407      reply bits separately. */
1408   BOOL ex_oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf);
1409   BOOL core_oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1410   BOOL oplock_request = ex_oplock_request | core_oplock_request;
1411 #if 0
1412   int open_flags = SVAL(inbuf,smb_vwv2);
1413   int smb_sattr = SVAL(inbuf,smb_vwv4); 
1414   uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
1415 #endif
1416   int smb_ofun = SVAL(inbuf,smb_vwv8);
1417   mode_t unixmode;
1418   SMB_OFF_T size=0;
1419   int fmode=0,mtime=0,rmode=0;
1420   SMB_STRUCT_STAT sbuf;
1421   int smb_action = 0;
1422   BOOL bad_path = False;
1423   files_struct *fsp;
1424
1425   /* If it's an IPC, pass off the pipe handler. */
1426   if (IS_IPC(conn) && lp_nt_pipe_support() && lp_security() != SEC_SHARE)
1427   {
1428     return reply_open_pipe_and_X(conn, inbuf,outbuf,length,bufsize);
1429   }
1430
1431   /* XXXX we need to handle passed times, sattr and flags */
1432
1433   pstrcpy(fname,smb_buf(inbuf));
1434   unix_convert(fname,conn,0,&bad_path,NULL);
1435     
1436   fsp = file_new();
1437   if (!fsp)
1438     return(ERROR(ERRSRV,ERRnofids));
1439
1440   if (!check_name(fname,conn))
1441   {
1442     if((errno == ENOENT) && bad_path)
1443     {
1444       unix_ERR_class = ERRDOS;
1445       unix_ERR_code = ERRbadpath;
1446     }
1447     file_free(fsp);
1448     return(UNIXERROR(ERRDOS,ERRnoaccess));
1449   }
1450
1451   unixmode = unix_mode(conn,smb_attr | aARCH);
1452       
1453   open_file_shared(fsp,conn,fname,smb_mode,smb_ofun,unixmode,
1454                        oplock_request, &rmode,&smb_action);
1455       
1456   if (!fsp->open)
1457   {
1458     if((errno == ENOENT) && bad_path)
1459     {
1460       unix_ERR_class = ERRDOS;
1461       unix_ERR_code = ERRbadpath;
1462     }
1463     file_free(fsp);
1464     return(UNIXERROR(ERRDOS,ERRnoaccess));
1465   }
1466
1467   if (sys_fstat(fsp->fd_ptr->fd,&sbuf) != 0) {
1468     close_file(fsp,False);
1469     return(ERROR(ERRDOS,ERRnoaccess));
1470   }
1471
1472   size = sbuf.st_size;
1473   fmode = dos_mode(conn,fname,&sbuf);
1474   mtime = sbuf.st_mtime;
1475   if (fmode & aDIR) {
1476     close_file(fsp,False);
1477     return(ERROR(ERRDOS,ERRnoaccess));
1478   }
1479
1480   /* If the caller set the extended oplock request bit
1481      and we granted one (by whatever means) - set the
1482      correct bit for extended oplock reply.
1483    */
1484
1485   if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1486     smb_action |= EXTENDED_OPLOCK_GRANTED;
1487   }
1488
1489   if(ex_oplock_request && fsp->granted_oplock) {
1490     smb_action |= EXTENDED_OPLOCK_GRANTED;
1491   }
1492
1493   /* If the caller set the core oplock request bit
1494      and we granted one (by whatever means) - set the
1495      correct bit for core oplock reply.
1496    */
1497
1498   if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1499     CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1500   }
1501
1502   if(core_oplock_request && fsp->granted_oplock) {
1503     CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1504   }
1505
1506   set_message(outbuf,15,0,True);
1507   SSVAL(outbuf,smb_vwv2,fsp->fnum);
1508   SSVAL(outbuf,smb_vwv3,fmode);
1509   if(lp_dos_filetime_resolution(SNUM(conn)) )
1510     put_dos_date3(outbuf,smb_vwv4,mtime & ~1);
1511   else
1512     put_dos_date3(outbuf,smb_vwv4,mtime);
1513   SIVAL(outbuf,smb_vwv6,(uint32)size);
1514   SSVAL(outbuf,smb_vwv8,rmode);
1515   SSVAL(outbuf,smb_vwv11,smb_action);
1516
1517   return chain_reply(inbuf,outbuf,length,bufsize);
1518 }
1519
1520
1521 /****************************************************************************
1522   reply to a SMBulogoffX
1523 ****************************************************************************/
1524 int reply_ulogoffX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1525 {
1526   uint16 vuid = SVAL(inbuf,smb_uid);
1527   user_struct *vuser = get_valid_user_struct(vuid);
1528
1529   if(vuser == 0) {
1530     DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid));
1531   }
1532
1533   /* in user level security we are supposed to close any files
1534      open by this user */
1535   if ((vuser != 0) && (lp_security() != SEC_SHARE)) {
1536           file_close_user(vuid);
1537   }
1538
1539   invalidate_vuid(vuid);
1540
1541   set_message(outbuf,2,0,True);
1542
1543   DEBUG( 3, ( "ulogoffX vuid=%d\n", vuid ) );
1544
1545   return chain_reply(inbuf,outbuf,length,bufsize);
1546 }
1547
1548
1549 /****************************************************************************
1550   reply to a mknew or a create
1551 ****************************************************************************/
1552 int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1553 {
1554   pstring fname;
1555   int com;
1556   int outsize = 0;
1557   int createmode;
1558   mode_t unixmode;
1559   int ofun = 0;
1560   BOOL bad_path = False;
1561   files_struct *fsp;
1562   int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1563  
1564   com = SVAL(inbuf,smb_com);
1565
1566   createmode = SVAL(inbuf,smb_vwv0);
1567   pstrcpy(fname,smb_buf(inbuf)+1);
1568   unix_convert(fname,conn,0,&bad_path,NULL);
1569
1570   if (createmode & aVOLID)
1571     {
1572       DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
1573     }
1574   
1575   unixmode = unix_mode(conn,createmode);
1576   
1577   fsp = file_new();
1578   if (!fsp)
1579     return(ERROR(ERRSRV,ERRnofids));
1580
1581   if (!check_name(fname,conn))
1582   {
1583     if((errno == ENOENT) && bad_path)
1584     {
1585       unix_ERR_class = ERRDOS;
1586       unix_ERR_code = ERRbadpath;
1587     }
1588     file_free(fsp);
1589     return(UNIXERROR(ERRDOS,ERRnoaccess));
1590   }
1591
1592   if(com == SMBmknew)
1593   {
1594     /* We should fail if file exists. */
1595     ofun = 0x10;
1596   }
1597   else
1598   {
1599     /* SMBcreate - Create if file doesn't exist, truncate if it does. */
1600     ofun = 0x12;
1601   }
1602
1603   /* Open file in dos compatibility share mode. */
1604   open_file_shared(fsp,conn,fname,SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB), 
1605                    ofun, unixmode, oplock_request, NULL, NULL);
1606   
1607   if (!fsp->open)
1608   {
1609     if((errno == ENOENT) && bad_path) 
1610     {
1611       unix_ERR_class = ERRDOS;
1612       unix_ERR_code = ERRbadpath;
1613     }
1614     file_free(fsp);
1615     return(UNIXERROR(ERRDOS,ERRnoaccess));
1616   }
1617  
1618   outsize = set_message(outbuf,1,0,True);
1619   SSVAL(outbuf,smb_vwv0,fsp->fnum);
1620
1621   if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1622     CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1623   }
1624  
1625   if(fsp->granted_oplock)
1626     CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1627  
1628   DEBUG( 2, ( "new file %s\n", fname ) );
1629   DEBUG( 3, ( "mknew %s fd=%d dmode=%d umode=%o\n",
1630         fname, fsp->fd_ptr->fd, createmode, (int)unixmode ) );
1631
1632   return(outsize);
1633 }
1634
1635
1636 /****************************************************************************
1637   reply to a create temporary file
1638 ****************************************************************************/
1639 int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1640 {
1641   pstring fname;
1642   pstring fname2;
1643   int outsize = 0;
1644   int createmode;
1645   mode_t unixmode;
1646   BOOL bad_path = False;
1647   files_struct *fsp;
1648   int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1649  
1650   createmode = SVAL(inbuf,smb_vwv0);
1651   pstrcpy(fname,smb_buf(inbuf)+1);
1652   pstrcat(fname,"/TMXXXXXX");
1653   unix_convert(fname,conn,0,&bad_path,NULL);
1654   
1655   unixmode = unix_mode(conn,createmode);
1656   
1657   fsp = file_new();
1658   if (fsp)
1659     return(ERROR(ERRSRV,ERRnofids));
1660
1661   if (!check_name(fname,conn))
1662   {
1663     if((errno == ENOENT) && bad_path)
1664     {
1665       unix_ERR_class = ERRDOS;
1666       unix_ERR_code = ERRbadpath;
1667     }
1668     file_free(fsp);
1669     return(UNIXERROR(ERRDOS,ERRnoaccess));
1670   }
1671
1672   pstrcpy(fname2,(char *)mktemp(fname));
1673
1674   /* Open file in dos compatibility share mode. */
1675   /* We should fail if file exists. */
1676   open_file_shared(fsp,conn,fname2,SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB), 
1677                    (FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_FAIL), 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 (dos_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) && !dos_unlink(directory))
1778       count++;
1779     if (!count)
1780       exists = dos_file_exist(directory,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 (!dos_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 (sys_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->fd_ptr->fd,startpos,header+4,NULL,nread);
1928 #endif /* USE_READ_PREDICTION */
1929
1930     if ((nread-predict) > 0) {
1931       if(seek_file(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)transfer_file(fsp->fd_ptr->fd,Client,
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   if (nread < 0)
2046     return(UNIXERROR(ERRDOS,ERRnoaccess));
2047   
2048   outsize += nread;
2049   SSVAL(outbuf,smb_vwv0,nread);
2050   SSVAL(outbuf,smb_vwv5,nread+3);
2051   CVAL(smb_buf(outbuf),0) = 1;
2052   SSVAL(smb_buf(outbuf),1,nread);
2053   
2054   DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
2055             fsp->fnum, numtoread, nread ) );
2056
2057   return(outsize);
2058 }
2059
2060
2061 /****************************************************************************
2062   reply to a read and X
2063 ****************************************************************************/
2064 int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2065 {
2066   files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2067   SMB_OFF_T startpos = IVAL(inbuf,smb_vwv3);
2068   size_t smb_maxcnt = SVAL(inbuf,smb_vwv5);
2069   size_t smb_mincnt = SVAL(inbuf,smb_vwv6);
2070   ssize_t nread = -1;
2071   char *data;
2072
2073   /* If it's an IPC, pass off the pipe handler. */
2074   if (IS_IPC(conn))
2075     return reply_pipe_read_and_X(inbuf,outbuf,length,bufsize);
2076
2077   CHECK_FSP(fsp,conn);
2078   CHECK_READ(fsp);
2079   CHECK_ERROR(fsp);
2080
2081   set_message(outbuf,12,0,True);
2082   data = smb_buf(outbuf);
2083
2084 #ifdef LARGE_SMB_OFF_T
2085   if(CVAL(inbuf,smb_wct) == 12) {
2086     /*
2087      * This is a large offset (64 bit) read.
2088      */
2089     startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv10)) << 32);
2090   }
2091 #endif /* LARGE_SMB_OFF_T */
2092
2093   if (is_locked(fsp,conn,smb_maxcnt,startpos, F_RDLCK))
2094     return(ERROR(ERRDOS,ERRlock));
2095   nread = read_file(fsp,data,startpos,smb_maxcnt);
2096   
2097   if (nread < 0)
2098     return(UNIXERROR(ERRDOS,ERRnoaccess));
2099   
2100   SSVAL(outbuf,smb_vwv5,nread);
2101   SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2102   SSVAL(smb_buf(outbuf),-2,nread);
2103   
2104   DEBUG( 3, ( "readX fnum=%d min=%d max=%d nread=%d\n",
2105               fsp->fnum, smb_mincnt, smb_maxcnt, nread ) );
2106
2107   return chain_reply(inbuf,outbuf,length,bufsize);
2108 }
2109
2110 /****************************************************************************
2111   reply to a writebraw (core+ or LANMAN1.0 protocol)
2112 ****************************************************************************/
2113 int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2114 {
2115   ssize_t nwritten=0;
2116   ssize_t total_written=0;
2117   size_t numtowrite=0;
2118   size_t tcount;
2119   SMB_OFF_T startpos;
2120   char *data=NULL;
2121   BOOL write_through;
2122   files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2123   int outsize = 0;
2124
2125   CHECK_FSP(fsp,conn);
2126   CHECK_WRITE(fsp);
2127   CHECK_ERROR(fsp);
2128   
2129   tcount = IVAL(inbuf,smb_vwv1);
2130   startpos = IVAL(inbuf,smb_vwv3);
2131   write_through = BITSETW(inbuf+smb_vwv7,0);
2132
2133   /* We have to deal with slightly different formats depending
2134      on whether we are using the core+ or lanman1.0 protocol */
2135   if(Protocol <= PROTOCOL_COREPLUS) {
2136     numtowrite = SVAL(smb_buf(inbuf),-2);
2137     data = smb_buf(inbuf);
2138   } else {
2139     numtowrite = SVAL(inbuf,smb_vwv10);
2140     data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
2141   }
2142
2143   /* force the error type */
2144   CVAL(inbuf,smb_com) = SMBwritec;
2145   CVAL(outbuf,smb_com) = SMBwritec;
2146
2147   if (is_locked(fsp,conn,tcount,startpos, F_WRLCK))
2148     return(ERROR(ERRDOS,ERRlock));
2149
2150   if (seek_file(fsp,startpos) == -1) {
2151     DEBUG(0,("couldn't seek to %.0f in writebraw\n",(double)startpos));
2152     return(UNIXERROR(ERRDOS,ERRnoaccess));
2153   }
2154
2155   if (numtowrite>0)
2156     nwritten = write_file(fsp,data,numtowrite);
2157   
2158   DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
2159            fsp->fnum, (double)startpos, numtowrite, nwritten, write_through));
2160
2161   if (nwritten < numtowrite) 
2162     return(UNIXERROR(ERRHRD,ERRdiskfull));
2163
2164   total_written = nwritten;
2165
2166   /* Return a message to the redirector to tell it
2167      to send more bytes */
2168   CVAL(outbuf,smb_com) = SMBwritebraw;
2169   SSVALS(outbuf,smb_vwv0,-1);
2170   outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
2171   send_smb(Client,outbuf);
2172   
2173   /* Now read the raw data into the buffer and write it */
2174   if (read_smb_length(Client,inbuf,SMB_SECONDARY_WAIT) == -1) {
2175     exit_server("secondary writebraw failed");
2176   }
2177   
2178   /* Even though this is not an smb message, smb_len
2179      returns the generic length of an smb message */
2180   numtowrite = smb_len(inbuf);
2181
2182   if (tcount > nwritten+numtowrite) {
2183     DEBUG(3,("Client overestimated the write %d %d %d\n",
2184              tcount,nwritten,numtowrite));
2185   }
2186
2187   nwritten = transfer_file(Client,fsp->fd_ptr->fd,(SMB_OFF_T)numtowrite,NULL,0,
2188                            startpos+nwritten);
2189   total_written += nwritten;
2190   
2191   /* Set up outbuf to return the correct return */
2192   outsize = set_message(outbuf,1,0,True);
2193   CVAL(outbuf,smb_com) = SMBwritec;
2194   SSVAL(outbuf,smb_vwv0,total_written);
2195
2196   if (nwritten < (ssize_t)numtowrite) {
2197     CVAL(outbuf,smb_rcls) = ERRHRD;
2198     SSVAL(outbuf,smb_err,ERRdiskfull);      
2199   }
2200
2201   if (lp_syncalways(SNUM(conn)) || write_through)
2202     sync_file(conn,fsp);
2203
2204   DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
2205            fsp->fnum, (double)startpos, numtowrite, total_written));
2206
2207   /* we won't return a status if write through is not selected - this 
2208      follows what WfWg does */
2209   if (!write_through && total_written==tcount)
2210     return(-1);
2211
2212   return(outsize);
2213 }
2214
2215 /****************************************************************************
2216   reply to a writeunlock (core+)
2217 ****************************************************************************/
2218 int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2219 {
2220   ssize_t nwritten = -1;
2221   size_t numtowrite;
2222   SMB_OFF_T startpos;
2223   char *data;
2224   int eclass;
2225   uint32 ecode;
2226   files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2227   int outsize = 0;
2228
2229   CHECK_FSP(fsp,conn);
2230   CHECK_WRITE(fsp);
2231   CHECK_ERROR(fsp);
2232
2233   numtowrite = SVAL(inbuf,smb_vwv1);
2234   startpos = IVAL(inbuf,smb_vwv2);
2235   data = smb_buf(inbuf) + 3;
2236   
2237   if (is_locked(fsp,conn,numtowrite,startpos, F_WRLCK))
2238     return(ERROR(ERRDOS,ERRlock));
2239
2240   if(seek_file(fsp,startpos) == -1)
2241     return(UNIXERROR(ERRDOS,ERRnoaccess));
2242
2243   /* The special X/Open SMB protocol handling of
2244      zero length writes is *NOT* done for
2245      this call */
2246   if(numtowrite == 0)
2247     nwritten = 0;
2248   else
2249     nwritten = write_file(fsp,data,numtowrite);
2250   
2251   if (lp_syncalways(SNUM(conn)))
2252     sync_file(conn,fsp);
2253
2254   if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0))
2255     return(UNIXERROR(ERRDOS,ERRnoaccess));
2256
2257   if(!do_unlock(fsp, conn, numtowrite, startpos, &eclass, &ecode))
2258     return(ERROR(eclass,ecode));
2259
2260   outsize = set_message(outbuf,1,0,True);
2261   
2262   SSVAL(outbuf,smb_vwv0,nwritten);
2263   
2264   DEBUG( 3, ( "writeunlock fnum=%d num=%d wrote=%d\n",
2265               fsp->fnum, numtowrite, nwritten ) );
2266
2267   return(outsize);
2268 }
2269
2270 /****************************************************************************
2271   reply to a write
2272 ****************************************************************************/
2273 int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int dum_size,int dum_buffsize)
2274 {
2275   size_t numtowrite;
2276   ssize_t nwritten = -1;
2277   SMB_OFF_T startpos;
2278   char *data;
2279   files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2280   int outsize = 0;
2281
2282   CHECK_FSP(fsp,conn);
2283   CHECK_WRITE(fsp);
2284   CHECK_ERROR(fsp);
2285
2286   numtowrite = SVAL(inbuf,smb_vwv1);
2287   startpos = IVAL(inbuf,smb_vwv2);
2288   data = smb_buf(inbuf) + 3;
2289   
2290   if (is_locked(fsp,conn,numtowrite,startpos, F_WRLCK))
2291     return(ERROR(ERRDOS,ERRlock));
2292
2293   if(seek_file(fsp,startpos) == -1)
2294     return(UNIXERROR(ERRDOS,ERRnoaccess));
2295
2296   /* X/Open SMB protocol says that if smb_vwv1 is
2297      zero then the file size should be extended or
2298      truncated to the size given in smb_vwv[2-3] */
2299   if(numtowrite == 0)
2300     nwritten = set_filelen(fsp->fd_ptr->fd, (SMB_OFF_T)startpos);
2301   else
2302     nwritten = write_file(fsp,data,numtowrite);
2303   
2304   if (lp_syncalways(SNUM(conn)))
2305     sync_file(conn,fsp);
2306
2307   if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0))
2308     return(UNIXERROR(ERRDOS,ERRnoaccess));
2309
2310   outsize = set_message(outbuf,1,0,True);
2311   
2312   SSVAL(outbuf,smb_vwv0,nwritten);
2313
2314   if (nwritten < (ssize_t)numtowrite) {
2315     CVAL(outbuf,smb_rcls) = ERRHRD;
2316     SSVAL(outbuf,smb_err,ERRdiskfull);      
2317   }
2318   
2319   DEBUG(3,("write fnum=%d num=%d wrote=%d\n",
2320            fsp->fnum, numtowrite, nwritten));
2321
2322   return(outsize);
2323 }
2324
2325
2326 /****************************************************************************
2327   reply to a write and X
2328 ****************************************************************************/
2329 int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2330 {
2331   files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2332   SMB_OFF_T startpos = IVAL(inbuf,smb_vwv3);
2333   size_t numtowrite = SVAL(inbuf,smb_vwv10);
2334   BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
2335   ssize_t nwritten = -1;
2336   int smb_doff = SVAL(inbuf,smb_vwv11);
2337   char *data;
2338
2339   /* If it's an IPC, pass off the pipe handler. */
2340   if (IS_IPC(conn))
2341     return reply_pipe_write_and_X(inbuf,outbuf,length,bufsize);
2342
2343   CHECK_FSP(fsp,conn);
2344   CHECK_WRITE(fsp);
2345   CHECK_ERROR(fsp);
2346
2347   data = smb_base(inbuf) + smb_doff;
2348
2349 #ifdef LARGE_SMB_OFF_T
2350   if(CVAL(inbuf,smb_wct) == 14) {
2351     /*
2352      * This is a large offset (64 bit) write.
2353      */
2354     startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv12)) << 32);
2355   }
2356 #endif /* LARGE_SMB_OFF_T */
2357
2358   if (is_locked(fsp,conn,numtowrite,startpos, F_WRLCK))
2359     return(ERROR(ERRDOS,ERRlock));
2360
2361   if(seek_file(fsp,startpos) == -1)
2362     return(UNIXERROR(ERRDOS,ERRnoaccess));
2363   
2364   /* X/Open SMB protocol says that, unlike SMBwrite
2365      if the length is zero then NO truncation is
2366      done, just a write of zero. To truncate a file,
2367      use SMBwrite. */
2368   if(numtowrite == 0)
2369     nwritten = 0;
2370   else
2371     nwritten = write_file(fsp,data,numtowrite);
2372   
2373   if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0))
2374     return(UNIXERROR(ERRDOS,ERRnoaccess));
2375
2376   set_message(outbuf,6,0,True);
2377   
2378   SSVAL(outbuf,smb_vwv2,nwritten);
2379   
2380   if (nwritten < (ssize_t)numtowrite) {
2381     CVAL(outbuf,smb_rcls) = ERRHRD;
2382     SSVAL(outbuf,smb_err,ERRdiskfull);      
2383   }
2384
2385   DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
2386            fsp->fnum, numtowrite, nwritten));
2387
2388   if (lp_syncalways(SNUM(conn)) || write_through)
2389     sync_file(conn,fsp);
2390
2391   return chain_reply(inbuf,outbuf,length,bufsize);
2392 }
2393
2394
2395 /****************************************************************************
2396   reply to a lseek
2397 ****************************************************************************/
2398 int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2399 {
2400   SMB_OFF_T startpos;
2401   SMB_OFF_T res= -1;
2402   int mode,umode;
2403   int outsize = 0;
2404   files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2405
2406   CHECK_FSP(fsp,conn);
2407   CHECK_ERROR(fsp);
2408
2409   mode = SVAL(inbuf,smb_vwv1) & 3;
2410   startpos = IVAL(inbuf,smb_vwv2);
2411
2412   switch (mode & 3) 
2413   {
2414     case 0: umode = SEEK_SET; break;
2415     case 1: umode = SEEK_CUR; break;
2416     case 2: umode = SEEK_END; break;
2417     default:
2418       umode = SEEK_SET; break;
2419   }
2420
2421   if((res = sys_lseek(fsp->fd_ptr->fd,startpos,umode)) == -1)
2422     return(UNIXERROR(ERRDOS,ERRnoaccess));
2423
2424   fsp->pos = res;
2425   
2426   outsize = set_message(outbuf,2,0,True);
2427   SIVALS(outbuf,smb_vwv0,res);
2428   
2429   DEBUG(3,("lseek fnum=%d ofs=%.0f mode=%d\n",
2430            fsp->fnum, (double)startpos, mode));
2431
2432   return(outsize);
2433 }
2434
2435 /****************************************************************************
2436   reply to a flush
2437 ****************************************************************************/
2438 int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2439 {
2440   int outsize = set_message(outbuf,0,0,True);
2441   files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2442
2443   if (fsp) {
2444           CHECK_FSP(fsp,conn);
2445           CHECK_ERROR(fsp);
2446   }
2447
2448   if (!fsp) {
2449           file_sync_all(conn);
2450   } else {
2451           sync_file(conn,fsp);
2452   }
2453
2454   DEBUG(3,("flush\n"));
2455   return(outsize);
2456 }
2457
2458
2459 /****************************************************************************
2460   reply to a exit
2461 ****************************************************************************/
2462 int reply_exit(connection_struct *conn, 
2463                char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2464 {
2465         int outsize = set_message(outbuf,0,0,True);
2466         DEBUG(3,("exit\n"));
2467
2468         return(outsize);
2469 }
2470
2471
2472 /****************************************************************************
2473  Reply to a close - has to deal with closing a directory opened by NT SMB's.
2474 ****************************************************************************/
2475 int reply_close(connection_struct *conn,
2476                 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2477 {
2478         int outsize = 0;
2479         time_t mtime;
2480         int32 eclass = 0, err = 0;
2481         files_struct *fsp = NULL;
2482
2483         outsize = set_message(outbuf,0,0,True);
2484
2485         /* If it's an IPC, pass off to the pipe handler. */
2486         if (IS_IPC(conn)) {
2487                 return reply_pipe_close(conn, inbuf,outbuf);
2488         }
2489
2490         fsp = file_fsp(inbuf,smb_vwv0);
2491
2492         /*
2493          * We can only use CHECK_FSP if we know it's not a directory.
2494          */
2495
2496     if(!fsp || !fsp->open || (fsp->conn != conn))
2497       return(ERROR(ERRDOS,ERRbadfid));
2498
2499         if(HAS_CACHED_ERROR(fsp)) {
2500                 eclass = fsp->wbmpx_ptr->wr_errclass;
2501                 err = fsp->wbmpx_ptr->wr_error;
2502         }
2503
2504         if(fsp->is_directory) {
2505                 /*
2506                  * Special case - close NT SMB directory
2507                  * handle.
2508                  */
2509                 DEBUG(3,("close directory fnum=%d\n", fsp->fnum));
2510                 close_directory(fsp);
2511         } else {
2512                 /*
2513                  * Close ordinary file.
2514                  */
2515
2516                 /*
2517                  * If there was a modify time outstanding,
2518                  * try and set it here.
2519                  */
2520                 if(fsp->pending_modtime)
2521                         set_filetime(conn, fsp->fsp_name, fsp->pending_modtime);
2522
2523                 /*
2524                  * Now take care of any time sent in the close.
2525                  */
2526                 mtime = make_unix_date3(inbuf+smb_vwv1);
2527                 
2528                 /* try and set the date */
2529                 set_filetime(conn, fsp->fsp_name,mtime);
2530
2531                 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
2532                          fsp->fd_ptr->fd, fsp->fnum,
2533                          conn->num_files_open));
2534   
2535                 close_file(fsp,True);
2536         }  
2537
2538         /* We have a cached error */
2539         if(eclass || err)
2540                 return(ERROR(eclass,err));
2541
2542         return(outsize);
2543 }
2544
2545
2546 /****************************************************************************
2547   reply to a writeclose (Core+ protocol)
2548 ****************************************************************************/
2549 int reply_writeclose(connection_struct *conn,
2550                      char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2551 {
2552         size_t numtowrite;
2553         ssize_t nwritten = -1;
2554         int outsize = 0;
2555         SMB_OFF_T startpos;
2556         char *data;
2557         time_t mtime;
2558         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2559
2560         CHECK_FSP(fsp,conn);
2561         CHECK_WRITE(fsp);
2562         CHECK_ERROR(fsp);
2563
2564         numtowrite = SVAL(inbuf,smb_vwv1);
2565         startpos = IVAL(inbuf,smb_vwv2);
2566         mtime = make_unix_date3(inbuf+smb_vwv4);
2567         data = smb_buf(inbuf) + 1;
2568   
2569         if (is_locked(fsp,conn,numtowrite,startpos, F_WRLCK))
2570                 return(ERROR(ERRDOS,ERRlock));
2571       
2572         if(seek_file(fsp,startpos) == -1)
2573                 return(UNIXERROR(ERRDOS,ERRnoaccess));
2574       
2575         nwritten = write_file(fsp,data,numtowrite);
2576
2577         set_filetime(conn, fsp->fsp_name,mtime);
2578   
2579         close_file(fsp,True);
2580
2581         DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
2582                  fsp->fnum, numtowrite, nwritten,
2583                  conn->num_files_open));
2584   
2585         if (nwritten <= 0)
2586                 return(UNIXERROR(ERRDOS,ERRnoaccess));
2587   
2588         outsize = set_message(outbuf,1,0,True);
2589   
2590         SSVAL(outbuf,smb_vwv0,nwritten);
2591         return(outsize);
2592 }
2593
2594
2595 /****************************************************************************
2596   reply to a lock
2597 ****************************************************************************/
2598 int reply_lock(connection_struct *conn,
2599                char *inbuf,char *outbuf, int length, int dum_buffsize)
2600 {
2601         int outsize = set_message(outbuf,0,0,True);
2602         SMB_OFF_T count,offset;
2603         int eclass;
2604         uint32 ecode;
2605         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2606
2607         CHECK_FSP(fsp,conn);
2608         CHECK_ERROR(fsp);
2609
2610         count = IVAL(inbuf,smb_vwv1);
2611         offset = IVAL(inbuf,smb_vwv3);
2612
2613         DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2614                  fsp->fd_ptr->fd, fsp->fnum, (double)offset, (double)count));
2615
2616         if (!do_lock(fsp, conn, count, offset, F_WRLCK, &eclass, &ecode)) {
2617       if((ecode == ERRlock) && lp_blocking_locks(SNUM(conn))) {
2618         /*
2619          * A blocking lock was requested. Package up
2620          * this smb into a queued request and push it
2621          * onto the blocking lock queue.
2622          */
2623         if(push_blocking_lock_request(inbuf, length, -1, 0))
2624           return -1;
2625       }
2626       return (ERROR(eclass,ecode));
2627     }
2628
2629         return(outsize);
2630 }
2631
2632
2633 /****************************************************************************
2634   reply to a unlock
2635 ****************************************************************************/
2636 int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2637 {
2638   int outsize = set_message(outbuf,0,0,True);
2639   SMB_OFF_T count,offset;
2640   int eclass;
2641   uint32 ecode;
2642   files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2643
2644   CHECK_FSP(fsp,conn);
2645   CHECK_ERROR(fsp);
2646
2647   count = IVAL(inbuf,smb_vwv1);
2648   offset = IVAL(inbuf,smb_vwv3);
2649
2650   if(!do_unlock(fsp, conn, count, offset, &eclass, &ecode))
2651     return (ERROR(eclass,ecode));
2652
2653   DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2654         fsp->fd_ptr->fd, fsp->fnum, (double)offset, (double)count ) );
2655   
2656   return(outsize);
2657 }
2658
2659
2660 /****************************************************************************
2661   reply to a tdis
2662 ****************************************************************************/
2663 int reply_tdis(connection_struct *conn, 
2664                char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2665 {
2666         int outsize = set_message(outbuf,0,0,True);
2667         uint16 vuid;
2668
2669         vuid = SVAL(inbuf,smb_uid);
2670
2671         if (!conn) {
2672                 DEBUG(4,("Invalid connection in tdis\n"));
2673                 return(ERROR(ERRSRV,ERRinvnid));
2674         }
2675
2676         conn->used = False;
2677
2678         close_cnum(conn,vuid);
2679   
2680         return outsize;
2681 }
2682
2683
2684
2685 /****************************************************************************
2686   reply to a echo
2687 ****************************************************************************/
2688 int reply_echo(connection_struct *conn,
2689                char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2690 {
2691         int smb_reverb = SVAL(inbuf,smb_vwv0);
2692         int seq_num;
2693         int data_len = smb_buflen(inbuf);
2694         int outsize = set_message(outbuf,1,data_len,True);
2695         
2696         /* copy any incoming data back out */
2697         if (data_len > 0)
2698                 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
2699
2700         if (smb_reverb > 100) {
2701                 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
2702                 smb_reverb = 100;
2703         }
2704
2705         for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
2706                 SSVAL(outbuf,smb_vwv0,seq_num);
2707
2708                 smb_setlen(outbuf,outsize - 4);
2709
2710                 send_smb(Client,outbuf);
2711         }
2712
2713         DEBUG(3,("echo %d times\n", smb_reverb));
2714
2715         return -1;
2716 }
2717
2718
2719 /****************************************************************************
2720   reply to a printopen
2721 ****************************************************************************/
2722 int reply_printopen(connection_struct *conn, 
2723                     char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2724 {
2725         pstring fname;
2726         pstring fname2;
2727         int outsize = 0;
2728         files_struct *fsp;
2729         
2730         *fname = *fname2 = 0;
2731         
2732         if (!CAN_PRINT(conn))
2733                 return(ERROR(ERRDOS,ERRnoaccess));
2734
2735         {
2736                 pstring s;
2737                 char *p;
2738                 pstrcpy(s,smb_buf(inbuf)+1);
2739                 p = s;
2740                 while (*p) {
2741                         if (!(isalnum((int)*p) || strchr("._-",*p)))
2742                                 *p = 'X';
2743                         p++;
2744                 }
2745
2746                 if (strlen(s) > 10) s[10] = 0;
2747
2748                 slprintf(fname,sizeof(fname)-1, "%s.XXXXXX",s);  
2749         }
2750
2751         fsp = file_new();
2752         if (!fsp)
2753                 return(ERROR(ERRSRV,ERRnofids));
2754         
2755         pstrcpy(fname2,(char *)mktemp(fname));
2756
2757         if (!check_name(fname2,conn)) {
2758                 file_free(fsp);
2759                 return(ERROR(ERRDOS,ERRnoaccess));
2760         }
2761
2762         /* Open for exclusive use, write only. */
2763         open_file_shared(fsp,conn,fname2, SET_DENY_MODE(DENY_ALL)|SET_OPEN_MODE(DOS_OPEN_WRONLY),
2764                      (FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_FAIL), unix_mode(conn,0), 0, NULL, NULL);
2765
2766         if (!fsp->open) {
2767                 file_free(fsp);
2768                 return(UNIXERROR(ERRDOS,ERRnoaccess));
2769         }
2770
2771         /* force it to be a print file */
2772         fsp->print_file = True;
2773   
2774         outsize = set_message(outbuf,1,0,True);
2775         SSVAL(outbuf,smb_vwv0,fsp->fnum);
2776   
2777         DEBUG(3,("openprint %s fd=%d fnum=%d\n",
2778                    fname2, fsp->fd_ptr->fd, fsp->fnum));
2779
2780         return(outsize);
2781 }
2782
2783
2784 /****************************************************************************
2785   reply to a printclose
2786 ****************************************************************************/
2787 int reply_printclose(connection_struct *conn,
2788                      char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2789 {
2790         int outsize = set_message(outbuf,0,0,True);
2791         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2792
2793         CHECK_FSP(fsp,conn);
2794         CHECK_ERROR(fsp);
2795
2796         if (!CAN_PRINT(conn))
2797                 return(ERROR(ERRDOS,ERRnoaccess));
2798   
2799         DEBUG(3,("printclose fd=%d fnum=%d\n",
2800                  fsp->fd_ptr->fd,fsp->fnum));
2801   
2802         close_file(fsp,True);
2803
2804         return(outsize);
2805 }
2806
2807
2808 /****************************************************************************
2809   reply to a printqueue
2810 ****************************************************************************/
2811 int reply_printqueue(connection_struct *conn,
2812                      char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2813 {
2814         int outsize = set_message(outbuf,2,3,True);
2815         int max_count = SVAL(inbuf,smb_vwv0);
2816         int start_index = SVAL(inbuf,smb_vwv1);
2817
2818         /* we used to allow the client to get the cnum wrong, but that
2819            is really quite gross and only worked when there was only
2820            one printer - I think we should now only accept it if they
2821            get it right (tridge) */
2822         if (!CAN_PRINT(conn))
2823                 return(ERROR(ERRDOS,ERRnoaccess));
2824
2825         SSVAL(outbuf,smb_vwv0,0);
2826         SSVAL(outbuf,smb_vwv1,0);
2827         CVAL(smb_buf(outbuf),0) = 1;
2828         SSVAL(smb_buf(outbuf),1,0);
2829   
2830         DEBUG(3,("printqueue start_index=%d max_count=%d\n",
2831                  start_index, max_count));
2832
2833         {
2834                 print_queue_struct *queue = NULL;
2835                 char *p = smb_buf(outbuf) + 3;
2836                 int count = get_printqueue(SNUM(conn), conn,&queue,NULL);
2837                 int num_to_get = ABS(max_count);
2838                 int first = (max_count>0?start_index:start_index+max_count+1);
2839                 int i;
2840
2841                 if (first >= count)
2842                         num_to_get = 0;
2843                 else
2844                         num_to_get = MIN(num_to_get,count-first);
2845     
2846
2847                 for (i=first;i<first+num_to_get;i++) {
2848                         put_dos_date2(p,0,queue[i].time);
2849                         CVAL(p,4) = (queue[i].status==LPQ_PRINTING?2:3);
2850                         SSVAL(p,5,printjob_encode(SNUM(conn), 
2851                                                   queue[i].job));
2852                         SIVAL(p,7,queue[i].size);
2853                         CVAL(p,11) = 0;
2854                         StrnCpy(p+12,queue[i].user,16);
2855                         p += 28;
2856                 }
2857
2858                 if (count > 0) {
2859                         outsize = set_message(outbuf,2,28*count+3,False); 
2860                         SSVAL(outbuf,smb_vwv0,count);
2861                         SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
2862                         CVAL(smb_buf(outbuf),0) = 1;
2863                         SSVAL(smb_buf(outbuf),1,28*count);
2864                 }
2865
2866                 if (queue) free(queue);
2867           
2868                 DEBUG(3,("%d entries returned in queue\n",count));
2869         }
2870   
2871         return(outsize);
2872 }
2873
2874
2875 /****************************************************************************
2876   reply to a printwrite
2877 ****************************************************************************/
2878 int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2879 {
2880   int numtowrite;
2881   int outsize = set_message(outbuf,0,0,True);
2882   char *data;
2883   files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2884   
2885   if (!CAN_PRINT(conn))
2886     return(ERROR(ERRDOS,ERRnoaccess));
2887
2888   CHECK_FSP(fsp,conn);
2889   CHECK_WRITE(fsp);
2890   CHECK_ERROR(fsp);
2891
2892   numtowrite = SVAL(smb_buf(inbuf),1);
2893   data = smb_buf(inbuf) + 3;
2894   
2895   if (write_file(fsp,data,numtowrite) != numtowrite)
2896     return(UNIXERROR(ERRDOS,ERRnoaccess));
2897   
2898   DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
2899   
2900   return(outsize);
2901 }
2902
2903
2904 /****************************************************************************
2905   reply to a mkdir
2906 ****************************************************************************/
2907 int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2908 {
2909   pstring directory;
2910   int outsize,ret= -1;
2911   BOOL bad_path = False;
2912  
2913   pstrcpy(directory,smb_buf(inbuf) + 1);
2914   unix_convert(directory,conn,0,&bad_path,NULL);
2915   
2916   if (check_name(directory, conn))
2917     ret = dos_mkdir(directory,unix_mode(conn,aDIR));
2918   
2919   if (ret < 0)
2920   {
2921     if((errno == ENOENT) && bad_path)
2922     {
2923       unix_ERR_class = ERRDOS;
2924       unix_ERR_code = ERRbadpath;
2925     }
2926     return(UNIXERROR(ERRDOS,ERRnoaccess));
2927   }
2928
2929   outsize = set_message(outbuf,0,0,True);
2930
2931   DEBUG( 3, ( "mkdir %s ret=%d\n", directory, ret ) );
2932
2933   return(outsize);
2934 }
2935
2936 /****************************************************************************
2937 Static function used by reply_rmdir to delete an entire directory
2938 tree recursively.
2939 ****************************************************************************/
2940 static BOOL recursive_rmdir(char *directory)
2941 {
2942   char *dname = NULL;
2943   BOOL ret = False;
2944   void *dirptr = OpenDir(NULL, directory, False);
2945
2946   if(dirptr == NULL)
2947     return True;
2948
2949   while((dname = ReadDirName(dirptr)))
2950   {
2951     pstring fullname;
2952     SMB_STRUCT_STAT st;
2953
2954     if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
2955       continue;
2956
2957     /* Construct the full name. */
2958     if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname))
2959     {
2960       errno = ENOMEM;
2961       ret = True;
2962       break;
2963     }
2964     pstrcpy(fullname, directory);
2965     pstrcat(fullname, "/");
2966     pstrcat(fullname, dname);
2967
2968     if(dos_lstat(fullname, &st) != 0)
2969     {
2970       ret = True;
2971       break;
2972     }
2973
2974     if(st.st_mode & S_IFDIR)
2975     {
2976       if(recursive_rmdir(fullname)!=0)
2977       {
2978         ret = True;
2979         break;
2980       }
2981       if(dos_rmdir(fullname) != 0)
2982       {
2983         ret = True;
2984         break;
2985       }
2986     }
2987     else if(dos_unlink(fullname) != 0)
2988     {
2989       ret = True;
2990       break;
2991     }
2992   }
2993   CloseDir(dirptr);
2994   return ret;
2995 }
2996
2997 /****************************************************************************
2998   reply to a rmdir
2999 ****************************************************************************/
3000 int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3001 {
3002   pstring directory;
3003   int outsize = 0;
3004   BOOL ok = False;
3005   BOOL bad_path = False;
3006
3007   pstrcpy(directory,smb_buf(inbuf) + 1);
3008   unix_convert(directory,conn, NULL,&bad_path,NULL);
3009   
3010   if (check_name(directory,conn))
3011     {
3012
3013       dptr_closepath(directory,SVAL(inbuf,smb_pid));
3014       ok = (dos_rmdir(directory) == 0);
3015       if(!ok && (errno == ENOTEMPTY) && lp_veto_files(SNUM(conn)))
3016         {
3017           /* Check to see if the only thing in this directory are
3018              vetoed files/directories. If so then delete them and
3019              retry. If we fail to delete any of them (and we *don't*
3020              do a recursive delete) then fail the rmdir. */
3021           BOOL all_veto_files = True;
3022           char *dname;
3023           void *dirptr = OpenDir(conn, directory, False);
3024
3025           if(dirptr != NULL)
3026             {
3027               int dirpos = TellDir(dirptr);
3028                   while ((dname = ReadDirName(dirptr)))
3029                     {
3030                   if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3031                     continue;
3032                   if(!IS_VETO_PATH(conn, dname))
3033                     {
3034                       all_veto_files = False;
3035                       break;
3036                     }
3037                 }
3038               if(all_veto_files)
3039                 {
3040                   SeekDir(dirptr,dirpos);
3041                   while ((dname = ReadDirName(dirptr)))
3042                     {
3043                       pstring fullname;
3044                       SMB_STRUCT_STAT st;
3045
3046                       if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3047                         continue;
3048
3049                       /* Construct the full name. */
3050                       if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname))
3051                         {
3052                           errno = ENOMEM;
3053                           break;
3054                         }
3055                       pstrcpy(fullname, directory);
3056                       pstrcat(fullname, "/");
3057                       pstrcat(fullname, dname);
3058                       
3059                       if(dos_lstat(fullname, &st) != 0)
3060                         break;
3061                       if(st.st_mode & S_IFDIR)
3062                       {
3063                         if(lp_recursive_veto_delete(SNUM(conn)))
3064                         {
3065                           if(recursive_rmdir(fullname) != 0)
3066                             break;
3067                         }
3068                         if(dos_rmdir(fullname) != 0)
3069                           break;
3070                       }
3071                       else if(dos_unlink(fullname) != 0)
3072                         break;
3073                     }
3074                   CloseDir(dirptr);
3075                   /* Retry the rmdir */
3076                   ok = (dos_rmdir(directory) == 0);
3077                 }
3078               else
3079                 CloseDir(dirptr);
3080             }
3081           else
3082             errno = ENOTEMPTY;
3083          }
3084           
3085       if (!ok)
3086         DEBUG(3,("couldn't remove directory %s : %s\n",
3087                  directory,strerror(errno)));
3088     }
3089   
3090   if (!ok)
3091   {
3092     if((errno == ENOENT) && bad_path)
3093     {
3094       unix_ERR_class = ERRDOS;
3095       unix_ERR_code = ERRbadpath;
3096     }
3097     return(UNIXERROR(ERRDOS,ERRbadpath));
3098   }
3099  
3100   outsize = set_message(outbuf,0,0,True);
3101   
3102   DEBUG( 3, ( "rmdir %s\n", directory ) );
3103   
3104   return(outsize);
3105 }
3106
3107
3108 /*******************************************************************
3109 resolve wildcards in a filename rename
3110 ********************************************************************/
3111 static BOOL resolve_wildcards(char *name1,char *name2)
3112 {
3113   fstring root1,root2;
3114   fstring ext1,ext2;
3115   char *p,*p2;
3116
3117   name1 = strrchr(name1,'/');
3118   name2 = strrchr(name2,'/');
3119
3120   if (!name1 || !name2) return(False);
3121   
3122   fstrcpy(root1,name1);
3123   fstrcpy(root2,name2);
3124   p = strrchr(root1,'.');
3125   if (p) {
3126     *p = 0;
3127     fstrcpy(ext1,p+1);
3128   } else {
3129     fstrcpy(ext1,"");    
3130   }
3131   p = strrchr(root2,'.');
3132   if (p) {
3133     *p = 0;
3134     fstrcpy(ext2,p+1);
3135   } else {
3136     fstrcpy(ext2,"");    
3137   }
3138
3139   p = root1;
3140   p2 = root2;
3141   while (*p2) {
3142     if (*p2 == '?') {
3143       *p2 = *p;
3144       p2++;
3145     } else {
3146       p2++;
3147     }
3148     if (*p) p++;
3149   }
3150
3151   p = ext1;
3152   p2 = ext2;
3153   while (*p2) {
3154     if (*p2 == '?') {
3155       *p2 = *p;
3156       p2++;
3157     } else {
3158       p2++;
3159     }
3160     if (*p) p++;
3161   }
3162
3163   pstrcpy(name2,root2);
3164   if (ext2[0]) {
3165     pstrcat(name2,".");
3166     pstrcat(name2,ext2);
3167   }
3168
3169   return(True);
3170 }
3171
3172 /*******************************************************************
3173 check if a user is allowed to rename a file
3174 ********************************************************************/
3175 static BOOL can_rename(char *fname,connection_struct *conn)
3176 {
3177   SMB_STRUCT_STAT sbuf;
3178
3179   if (!CAN_WRITE(conn)) return(False);
3180
3181   if (dos_lstat(fname,&sbuf) != 0) return(False);
3182   if (!check_file_sharing(conn,fname,True)) return(False);
3183
3184   return(True);
3185 }
3186
3187 /****************************************************************************
3188  The guts of the rename command, split out so it may be called by the NT SMB
3189  code. 
3190 ****************************************************************************/
3191 int rename_internals(connection_struct *conn, 
3192                      char *inbuf, char *outbuf, char *name, 
3193                      char *newname, BOOL replace_if_exists)
3194 {
3195         pstring directory;
3196         pstring mask;
3197         pstring newname_last_component;
3198         char *p;
3199         BOOL has_wild;
3200         BOOL bad_path1 = False;
3201         BOOL bad_path2 = False;
3202         int count=0;
3203         int error = ERRnoaccess;
3204         BOOL exists=False;
3205
3206         *directory = *mask = 0;
3207
3208         unix_convert(name,conn,0,&bad_path1,NULL);
3209         unix_convert(newname,conn,newname_last_component,&bad_path2,NULL);
3210
3211         /*
3212          * Split the old name into directory and last component
3213          * strings. Note that unix_convert may have stripped off a 
3214          * leading ./ from both name and newname if the rename is 
3215          * at the root of the share. We need to make sure either both
3216          * name and newname contain a / character or neither of them do
3217          * as this is checked in resolve_wildcards().
3218          */
3219         
3220         p = strrchr(name,'/');
3221         if (!p) {
3222                 pstrcpy(directory,".");
3223                 pstrcpy(mask,name);
3224         } else {
3225                 *p = 0;
3226                 pstrcpy(directory,name);
3227                 pstrcpy(mask,p+1);
3228                 *p = '/'; /* Replace needed for exceptional test below. */
3229         }
3230
3231         if (is_mangled(mask))
3232                 check_mangled_cache( mask );
3233
3234         has_wild = strchr(mask,'*') || strchr(mask,'?');
3235
3236         if (!has_wild) {
3237                 /*
3238                  * No wildcards - just process the one file.
3239                  */
3240                 BOOL is_short_name = is_8_3(name, True);
3241
3242                 /* Add a terminating '/' to the directory name. */
3243                 pstrcat(directory,"/");
3244                 pstrcat(directory,mask);
3245                 
3246                 /* Ensure newname contains a '/' also */
3247                 if(strrchr(newname,'/') == 0) {
3248                         pstring tmpstr;
3249                         
3250                         pstrcpy(tmpstr, "./");
3251                         pstrcat(tmpstr, newname);
3252                         pstrcpy(newname, tmpstr);
3253                 }
3254                 
3255                 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", 
3256                          case_sensitive, case_preserve, short_case_preserve, directory, 
3257                          newname, newname_last_component, is_short_name));
3258
3259                 /*
3260                  * Check for special case with case preserving and not
3261                  * case sensitive, if directory and newname are identical,
3262                  * and the old last component differs from the original
3263                  * last component only by case, then we should allow
3264                  * the rename (user is trying to change the case of the
3265                  * filename).
3266                  */
3267                 if((case_sensitive == False) && 
3268                    (((case_preserve == True) && 
3269                      (is_short_name == False)) || 
3270                     ((short_case_preserve == True) && 
3271                      (is_short_name == True))) &&
3272                    strcsequal(directory, newname)) {
3273                         pstring newname_modified_last_component;
3274
3275                         /*
3276                          * Get the last component of the modified name.
3277                          * Note that we guarantee that newname contains a '/'
3278                          * character above.
3279                          */
3280                         p = strrchr(newname,'/');
3281                         pstrcpy(newname_modified_last_component,p+1);
3282                         
3283                         if(strcsequal(newname_modified_last_component, 
3284                                       newname_last_component) == False) {
3285                                 /*
3286                                  * Replace the modified last component with
3287                                  * the original.
3288                                  */
3289                                 pstrcpy(p+1, newname_last_component);
3290                         }
3291                 }
3292                 
3293                 if(replace_if_exists) {
3294                         /*
3295                          * NT SMB specific flag - rename can overwrite
3296                          * file with the same name so don't check for
3297                          * dos_file_exist().
3298                          */
3299                         if(resolve_wildcards(directory,newname) &&
3300                            can_rename(directory,conn) &&
3301                            !dos_rename(directory,newname))
3302                                 count++;
3303                 } else {
3304                         if (resolve_wildcards(directory,newname) && 
3305                             can_rename(directory,conn) && 
3306                             !dos_file_exist(newname,NULL) &&
3307                             !dos_rename(directory,newname))
3308                                 count++;
3309                 }
3310
3311                 DEBUG(3,("rename_internals: %s doing rename on %s -> %s\n",(count != 0) ? "succeeded" : "failed",
3312                          directory,newname));
3313                 
3314                 if (!count) exists = dos_file_exist(directory,NULL);
3315                 if (!count && exists && dos_file_exist(newname,NULL)) {
3316                         exists = True;
3317                         error = ERRrename;
3318                 }
3319         } else {
3320                 /*
3321                  * Wildcards - process each file that matches.
3322                  */
3323                 void *dirptr = NULL;
3324                 char *dname;
3325                 pstring destname;
3326                 
3327                 if (check_name(directory,conn))
3328                         dirptr = OpenDir(conn, directory, True);
3329                 
3330                 if (dirptr) {
3331                         error = ERRbadfile;
3332                         
3333                         if (strequal(mask,"????????.???"))
3334                                 pstrcpy(mask,"*");
3335                         
3336                         while ((dname = ReadDirName(dirptr))) {
3337                                 pstring fname;
3338                                 pstrcpy(fname,dname);
3339                                 
3340                                 if(!mask_match(fname, mask, case_sensitive, False))
3341                                         continue;
3342                                 
3343                                 error = ERRnoaccess;
3344                                 slprintf(fname,sizeof(fname)-1,"%s/%s",directory,dname);
3345                                 if (!can_rename(fname,conn)) {
3346                                         DEBUG(6,("rename %s refused\n", fname));
3347                                         continue;
3348                                 }
3349                                 pstrcpy(destname,newname);
3350                                 
3351                                 if (!resolve_wildcards(fname,destname)) {
3352                                         DEBUG(6,("resolve_wildcards %s %s failed\n", fname, destname));
3353                                         continue;
3354                                 }
3355                                 
3356                                 if (!replace_if_exists && dos_file_exist(destname,NULL)) {
3357                                         DEBUG(6,("dos_file_exist %s\n", destname));
3358                                         error = 183;
3359                                         continue;
3360                                 }
3361                                 
3362                                 if (!dos_rename(fname,destname))
3363                                         count++;
3364                                 DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname));
3365                         }
3366                         CloseDir(dirptr);
3367                 }
3368         }
3369         
3370         if (count == 0) {
3371                 if (exists)
3372                         return(ERROR(ERRDOS,error));
3373                 else {
3374                         if((errno == ENOENT) && (bad_path1 || bad_path2)) {
3375                                 unix_ERR_class = ERRDOS;
3376                                 unix_ERR_code = ERRbadpath;
3377                         }
3378                         return(UNIXERROR(ERRDOS,error));
3379                 }
3380         }
3381         
3382         return 0;
3383 }
3384
3385 /****************************************************************************
3386  Reply to a mv.
3387 ****************************************************************************/
3388
3389 int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3390 {
3391   int outsize = 0;
3392   pstring name;
3393   pstring newname;
3394
3395   pstrcpy(name,smb_buf(inbuf) + 1);
3396   pstrcpy(newname,smb_buf(inbuf) + 3 + strlen(name));
3397    
3398   DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
3399
3400   outsize = rename_internals(conn, inbuf, outbuf, name, newname, False);
3401   if(outsize == 0) 
3402     outsize = set_message(outbuf,0,0,True);
3403   
3404   return(outsize);
3405 }
3406
3407 /*******************************************************************
3408   copy a file as part of a reply_copy
3409   ******************************************************************/
3410
3411 static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
3412                       int count,BOOL target_is_directory)
3413 {
3414   int Access,action;
3415   SMB_STRUCT_STAT st;
3416   int ret=-1;
3417   files_struct *fsp1,*fsp2;
3418   pstring dest;
3419   
3420   pstrcpy(dest,dest1);
3421   if (target_is_directory) {
3422     char *p = strrchr(src,'/');
3423     if (p) 
3424       p++;
3425     else
3426       p = src;
3427     pstrcat(dest,"/");
3428     pstrcat(dest,p);
3429   }
3430
3431   if (!dos_file_exist(src,&st))
3432     return(False);
3433
3434   fsp1 = file_new();
3435   if (!fsp1)
3436     return(False);
3437
3438   open_file_shared(fsp1,conn,src,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
3439                    (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),0,0,&Access,&action);
3440
3441   if (!fsp1->open) {
3442           file_free(fsp1);
3443           return(False);
3444   }
3445
3446   if (!target_is_directory && count)
3447     ofun = 1;
3448
3449   fsp2 = file_new();
3450   if (!fsp2) {
3451           close_file(fsp1,False);
3452           return(False);
3453   }
3454   open_file_shared(fsp2,conn,dest,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_WRONLY),
3455                    ofun,st.st_mode,0,&Access,&action);
3456
3457   if (!fsp2->open) {
3458     close_file(fsp1,False);
3459     file_free(fsp2);
3460     return(False);
3461   }
3462
3463   if ((ofun&3) == 1) {
3464     if(sys_lseek(fsp2->fd_ptr->fd,0,SEEK_END) == -1) {
3465       DEBUG(0,("copy_file: error - sys_lseek returned error %s\n",
3466                strerror(errno) ));
3467       /*
3468        * Stop the copy from occurring.
3469        */
3470       ret = -1;
3471       st.st_size = 0;
3472     }
3473   }
3474   
3475   if (st.st_size)
3476     ret = transfer_file(fsp1->fd_ptr->fd,
3477                         fsp2->fd_ptr->fd,st.st_size,NULL,0,0);
3478
3479   close_file(fsp1,False);
3480   close_file(fsp2,False);
3481
3482   return(ret == st.st_size);
3483 }
3484
3485
3486
3487 /****************************************************************************
3488   reply to a file copy.
3489   ****************************************************************************/
3490 int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3491 {
3492   int outsize = 0;
3493   pstring name;
3494   pstring directory;
3495   pstring mask,newname;
3496   char *p;
3497   int count=0;
3498   int error = ERRnoaccess;
3499   BOOL has_wild;
3500   BOOL exists=False;
3501   int tid2 = SVAL(inbuf,smb_vwv0);
3502   int ofun = SVAL(inbuf,smb_vwv1);
3503   int flags = SVAL(inbuf,smb_vwv2);
3504   BOOL target_is_directory=False;
3505   BOOL bad_path1 = False;
3506   BOOL bad_path2 = False;
3507
3508   *directory = *mask = 0;
3509
3510   pstrcpy(name,smb_buf(inbuf));
3511   pstrcpy(newname,smb_buf(inbuf) + 1 + strlen(name));
3512    
3513   DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
3514    
3515   if (tid2 != conn->cnum) {
3516     /* can't currently handle inter share copies XXXX */
3517     DEBUG(3,("Rejecting inter-share copy\n"));
3518     return(ERROR(ERRSRV,ERRinvdevice));
3519   }
3520
3521   unix_convert(name,conn,0,&bad_path1,NULL);
3522   unix_convert(newname,conn,0,&bad_path2,NULL);
3523
3524   target_is_directory = dos_directory_exist(newname,NULL);
3525
3526   if ((flags&1) && target_is_directory) {
3527     return(ERROR(ERRDOS,ERRbadfile));
3528   }
3529
3530   if ((flags&2) && !target_is_directory) {
3531     return(ERROR(ERRDOS,ERRbadpath));
3532   }
3533
3534   if ((flags&(1<<5)) && dos_directory_exist(name,NULL)) {
3535     /* wants a tree copy! XXXX */
3536     DEBUG(3,("Rejecting tree copy\n"));
3537     return(ERROR(ERRSRV,ERRerror));    
3538   }
3539
3540   p = strrchr(name,'/');
3541   if (!p) {
3542     pstrcpy(directory,"./");
3543     pstrcpy(mask,name);
3544   } else {
3545     *p = 0;
3546     pstrcpy(directory,name);
3547     pstrcpy(mask,p+1);
3548   }
3549
3550   if (is_mangled(mask))
3551     check_mangled_cache( mask );
3552
3553   has_wild = strchr(mask,'*') || strchr(mask,'?');
3554
3555   if (!has_wild) {
3556     pstrcat(directory,"/");
3557     pstrcat(directory,mask);
3558     if (resolve_wildcards(directory,newname) && 
3559         copy_file(directory,newname,conn,ofun,
3560                   count,target_is_directory)) count++;
3561     if (!count) exists = dos_file_exist(directory,NULL);
3562   } else {
3563     void *dirptr = NULL;
3564     char *dname;
3565     pstring destname;
3566
3567     if (check_name(directory,conn))
3568       dirptr = OpenDir(conn, directory, True);
3569
3570     if (dirptr)
3571       {
3572         error = ERRbadfile;
3573
3574         if (strequal(mask,"????????.???"))
3575           pstrcpy(mask,"*");
3576
3577         while ((dname = ReadDirName(dirptr)))
3578           {
3579             pstring fname;
3580             pstrcpy(fname,dname);
3581             
3582             if(!mask_match(fname, mask, case_sensitive, False)) continue;
3583
3584             error = ERRnoaccess;
3585             slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
3586             pstrcpy(destname,newname);
3587             if (resolve_wildcards(fname,destname) && 
3588                 copy_file(directory,newname,conn,ofun,
3589                           count,target_is_directory)) count++;
3590             DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
3591           }
3592         CloseDir(dirptr);
3593       }
3594   }
3595   
3596   if (count == 0) {
3597     if (exists)
3598       return(ERROR(ERRDOS,error));
3599     else
3600     {
3601       if((errno == ENOENT) && (bad_path1 || bad_path2))
3602       {
3603         unix_ERR_class = ERRDOS;
3604         unix_ERR_code = ERRbadpath;
3605       }
3606       return(UNIXERROR(ERRDOS,error));
3607     }
3608   }
3609   
3610   outsize = set_message(outbuf,1,0,True);
3611   SSVAL(outbuf,smb_vwv0,count);
3612
3613   return(outsize);
3614 }
3615
3616 /****************************************************************************
3617   reply to a setdir
3618 ****************************************************************************/
3619 int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3620 {
3621   int snum;
3622   int outsize = 0;
3623   BOOL ok = False;
3624   pstring newdir;
3625   
3626   snum = SNUM(conn);
3627   if (!CAN_SETDIR(snum))
3628     return(ERROR(ERRDOS,ERRnoaccess));
3629   
3630   pstrcpy(newdir,smb_buf(inbuf) + 1);
3631   strlower(newdir);
3632   
3633   if (strlen(newdir) == 0) {
3634           ok = True;
3635   } else {
3636           ok = dos_directory_exist(newdir,NULL);
3637           if (ok) {
3638                   string_set(&conn->connectpath,newdir);
3639           }
3640   }
3641   
3642   if (!ok)
3643           return(ERROR(ERRDOS,ERRbadpath));
3644   
3645   outsize = set_message(outbuf,0,0,True);
3646   CVAL(outbuf,smb_reh) = CVAL(inbuf,smb_reh);
3647   
3648   DEBUG(3,("setdir %s\n", newdir));
3649
3650   return(outsize);
3651 }
3652
3653 /****************************************************************************
3654   reply to a lockingX request
3655 ****************************************************************************/
3656 int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
3657 {
3658   files_struct *fsp = file_fsp(inbuf,smb_vwv2);
3659   unsigned char locktype = CVAL(inbuf,smb_vwv3);
3660 #if 0
3661   unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
3662 #endif
3663   uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
3664   uint16 num_locks = SVAL(inbuf,smb_vwv7);
3665   SMB_OFF_T count = 0, offset = 0;
3666   int32 lock_timeout = IVAL(inbuf,smb_vwv4);
3667   int i;
3668   char *data;
3669   uint32 ecode=0, dummy2;
3670   int eclass=0, dummy1;
3671   BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES);
3672   CHECK_FSP(fsp,conn);
3673   CHECK_ERROR(fsp);
3674
3675   data = smb_buf(inbuf);
3676
3677   /* Check if this is an oplock break on a file
3678      we have granted an oplock on.
3679    */
3680   if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE))
3681   {
3682     int token;
3683     SMB_DEV_T dev = fsp->fd_ptr->dev;
3684     SMB_INO_T inode = fsp->fd_ptr->inode;
3685
3686     DEBUG(5,("reply_lockingX: oplock break reply from client for fnum = %d\n",
3687               fsp->fnum));
3688     /*
3689      * Make sure we have granted an oplock on this file.
3690      */
3691     if(!fsp->granted_oplock)
3692     {
3693       DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \
3694 no oplock granted on this file.\n", fsp->fnum));
3695       return ERROR(ERRDOS,ERRlock);
3696     }
3697
3698     /* Remove the oplock flag from the sharemode. */
3699     lock_share_entry(fsp->conn, dev, inode, &token);
3700     if(remove_share_oplock(token, fsp)==False) {
3701
3702             DEBUG(0,("reply_lockingX: failed to remove share oplock for fnum %d, \
3703 dev = %x, inode = %.0f\n", fsp->fnum, (unsigned int)dev, (double)inode));
3704
3705             unlock_share_entry(fsp->conn, dev, inode, token);
3706     } else {
3707             unlock_share_entry(fsp->conn, dev, inode, token);
3708
3709             /* Clear the granted flag and return. */
3710             fsp->granted_oplock = False;
3711     }
3712
3713     /* if this is a pure oplock break request then don't send a reply */
3714     if (num_locks == 0 && num_ulocks == 0)
3715     {
3716       /* Sanity check - ensure a pure oplock break is not a
3717          chained request. */
3718       if(CVAL(inbuf,smb_vwv0) != 0xff)
3719         DEBUG(0,("reply_lockingX: Error : pure oplock break is a chained %d request !\n",
3720                  (unsigned int)CVAL(inbuf,smb_vwv0) ));
3721       return -1;
3722     }
3723   }
3724
3725   /* Data now points at the beginning of the list
3726      of smb_unlkrng structs */
3727   for(i = 0; i < (int)num_ulocks; i++) {
3728     if(!large_file_format) {
3729       count = IVAL(data,SMB_LKLEN_OFFSET(i));
3730       offset = IVAL(data,SMB_LKOFF_OFFSET(i));
3731     }
3732 #ifdef LARGE_SMB_OFF_T
3733     else {
3734       count = (((SMB_OFF_T) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(i))) << 32) |
3735               ((SMB_OFF_T) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(i)));
3736       offset = (((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(i))) << 32) |
3737                ((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(i)));
3738     }
3739 #endif /* LARGE_SMB_OFF_T */
3740
3741     DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for file %s\n",
3742           (double)offset, (double)count, fsp->fsp_name ));
3743
3744     if(!do_unlock(fsp,conn,count,offset,&eclass, &ecode))
3745       return ERROR(eclass,ecode);
3746   }
3747
3748   /* Setup the timeout in seconds. */
3749   lock_timeout = ((lock_timeout == -1) ? -1 : lock_timeout/1000);
3750
3751   /* Now do any requested locks */
3752   data += ((large_file_format ? 20 : 10)*num_ulocks);
3753
3754   /* Data now points at the beginning of the list
3755      of smb_lkrng structs */
3756
3757   for(i = 0; i < (int)num_locks; i++) {
3758     if(!large_file_format) {
3759       count = IVAL(data,SMB_LKLEN_OFFSET(i)); 
3760       offset = IVAL(data,SMB_LKOFF_OFFSET(i)); 
3761     }
3762 #ifdef LARGE_SMB_OFF_T
3763     else {
3764       count = (((SMB_OFF_T) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(i))) << 32) |
3765               ((SMB_OFF_T) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(i)));
3766       offset = (((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(i))) << 32) |
3767                ((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(i)));
3768     }
3769 #endif /* LARGE_SMB_OFF_T */
3770  
3771     DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for file %s\n",
3772           (double)offset, (double)count, fsp->fsp_name ));
3773
3774     if(!do_lock(fsp,conn,count,offset, ((locktype & 1) ? F_RDLCK : F_WRLCK),
3775                 &eclass, &ecode)) {
3776       if((ecode == ERRlock) && (lock_timeout != 0) && lp_blocking_locks(SNUM(conn))) {
3777         /*
3778          * A blocking lock was requested. Package up
3779          * this smb into a queued request and push it
3780          * onto the blocking lock queue.
3781          */
3782         if(push_blocking_lock_request(inbuf, length, lock_timeout, i))
3783           return -1;
3784       }
3785       break;
3786     }
3787   }
3788
3789   /* If any of the above locks failed, then we must unlock
3790      all of the previous locks (X/Open spec). */
3791   if(i != num_locks && num_locks != 0) {
3792     for(; i >= 0; i--) {
3793       if(!large_file_format) {
3794         count = IVAL(data,SMB_LKLEN_OFFSET(i));  
3795         offset = IVAL(data,SMB_LKOFF_OFFSET(i)); 
3796       }
3797 #ifdef LARGE_SMB_OFF_T
3798       else {
3799         count = (((SMB_OFF_T) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(i))) << 32) |
3800                 ((SMB_OFF_T) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(i)));
3801         offset = (((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(i))) << 32) |
3802                  ((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(i)));
3803       }
3804 #endif /* LARGE_SMB_OFF_T */
3805
3806       do_unlock(fsp,conn,count,offset,&dummy1,&dummy2);
3807     }
3808     return ERROR(eclass,ecode);
3809   }
3810
3811   set_message(outbuf,2,0,True);
3812   
3813   DEBUG( 3, ( "lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
3814         fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks ) );
3815
3816   return chain_reply(inbuf,outbuf,length,bufsize);
3817 }
3818
3819
3820 /****************************************************************************
3821   reply to a SMBreadbmpx (read block multiplex) request
3822 ****************************************************************************/
3823 int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
3824 {
3825   ssize_t nread = -1;
3826   ssize_t total_read;
3827   char *data;
3828   SMB_OFF_T startpos;
3829   int outsize;
3830   size_t maxcount;
3831   int max_per_packet;
3832   size_t tcount;
3833   int pad;
3834   files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3835
3836   /* this function doesn't seem to work - disable by default */
3837   if (!lp_readbmpx())
3838     return(ERROR(ERRSRV,ERRuseSTD));
3839
3840   outsize = set_message(outbuf,8,0,True);
3841
3842   CHECK_FSP(fsp,conn);
3843   CHECK_READ(fsp);
3844   CHECK_ERROR(fsp);
3845
3846   startpos = IVAL(inbuf,smb_vwv1);
3847   maxcount = SVAL(inbuf,smb_vwv3);
3848
3849   data = smb_buf(outbuf);
3850   pad = ((long)data)%4;
3851   if (pad) pad = 4 - pad;
3852   data += pad;
3853
3854   max_per_packet = bufsize-(outsize+pad);
3855   tcount = maxcount;
3856   total_read = 0;
3857
3858   if (is_locked(fsp,conn,maxcount,startpos, F_RDLCK))
3859     return(ERROR(ERRDOS,ERRlock));
3860         
3861   do
3862     {
3863       size_t N = MIN(max_per_packet,tcount-total_read);
3864   
3865       nread = read_file(fsp,data,startpos,N);
3866
3867       if (nread <= 0) nread = 0;
3868
3869       if (nread < (ssize_t)N)
3870         tcount = total_read + nread;
3871
3872       set_message(outbuf,8,nread,False);
3873       SIVAL(outbuf,smb_vwv0,startpos);
3874       SSVAL(outbuf,smb_vwv2,tcount);
3875       SSVAL(outbuf,smb_vwv6,nread);
3876       SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
3877
3878       send_smb(Client,outbuf);
3879
3880       total_read += nread;
3881       startpos += nread;
3882     }
3883   while (total_read < (ssize_t)tcount);
3884
3885   return(-1);
3886 }
3887
3888 /****************************************************************************
3889   reply to a SMBwritebmpx (write block multiplex primary) request
3890 ****************************************************************************/
3891 int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3892 {
3893   size_t numtowrite;
3894   ssize_t nwritten = -1;
3895   int outsize = 0;
3896   SMB_OFF_T startpos;
3897   size_t tcount;
3898   BOOL write_through;
3899   int smb_doff;
3900   char *data;
3901   files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3902
3903   CHECK_FSP(fsp,conn);
3904   CHECK_WRITE(fsp);
3905   CHECK_ERROR(fsp);
3906
3907   tcount = SVAL(inbuf,smb_vwv1);
3908   startpos = IVAL(inbuf,smb_vwv3);
3909   write_through = BITSETW(inbuf+smb_vwv7,0);
3910   numtowrite = SVAL(inbuf,smb_vwv10);
3911   smb_doff = SVAL(inbuf,smb_vwv11);
3912
3913   data = smb_base(inbuf) + smb_doff;
3914
3915   /* If this fails we need to send an SMBwriteC response,
3916      not an SMBwritebmpx - set this up now so we don't forget */
3917   CVAL(outbuf,smb_com) = SMBwritec;
3918
3919   if (is_locked(fsp,conn,tcount,startpos,F_WRLCK))
3920     return(ERROR(ERRDOS,ERRlock));
3921
3922   if(seek_file(fsp,startpos) == -1)
3923     return(UNIXERROR(ERRDOS,ERRnoaccess));
3924
3925   nwritten = write_file(fsp,data,numtowrite);
3926
3927   if(lp_syncalways(SNUM(conn)) || write_through)
3928     sync_file(conn,fsp);
3929   
3930   if(nwritten < (ssize_t)numtowrite)
3931     return(UNIXERROR(ERRHRD,ERRdiskfull));
3932
3933   /* If the maximum to be written to this file
3934      is greater than what we just wrote then set
3935      up a secondary struct to be attached to this
3936      fd, we will use this to cache error messages etc. */
3937   if((ssize_t)tcount > nwritten) 
3938   {
3939     write_bmpx_struct *wbms;
3940     if(fsp->wbmpx_ptr != NULL)
3941       wbms = fsp->wbmpx_ptr; /* Use an existing struct */
3942     else
3943       wbms = (write_bmpx_struct *)malloc(sizeof(write_bmpx_struct));
3944     if(!wbms)
3945     {
3946       DEBUG(0,("Out of memory in reply_readmpx\n"));
3947       return(ERROR(ERRSRV,ERRnoresource));
3948     }
3949     wbms->wr_mode = write_through;
3950     wbms->wr_discard = False; /* No errors yet */
3951     wbms->wr_total_written = nwritten;
3952     wbms->wr_errclass = 0;
3953     wbms->wr_error = 0;
3954     fsp->wbmpx_ptr = wbms;
3955   }
3956
3957   /* We are returning successfully, set the message type back to
3958      SMBwritebmpx */
3959   CVAL(outbuf,smb_com) = SMBwriteBmpx;
3960   
3961   outsize = set_message(outbuf,1,0,True);
3962   
3963   SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
3964   
3965   DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
3966             fsp->fnum, numtowrite, nwritten ) );
3967
3968   if (write_through && tcount==nwritten) {
3969     /* we need to send both a primary and a secondary response */
3970     smb_setlen(outbuf,outsize - 4);
3971     send_smb(Client,outbuf);
3972
3973     /* now the secondary */
3974     outsize = set_message(outbuf,1,0,True);
3975     CVAL(outbuf,smb_com) = SMBwritec;
3976     SSVAL(outbuf,smb_vwv0,nwritten);
3977   }
3978
3979   return(outsize);
3980 }
3981
3982
3983 /****************************************************************************
3984   reply to a SMBwritebs (write block multiplex secondary) request
3985 ****************************************************************************/
3986 int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3987 {
3988   size_t numtowrite;
3989   ssize_t nwritten = -1;
3990   int outsize = 0;
3991   SMB_OFF_T startpos;
3992   size_t tcount;
3993   BOOL write_through;
3994   int smb_doff;
3995   char *data;
3996   write_bmpx_struct *wbms;
3997   BOOL send_response = False; 
3998   files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3999
4000   CHECK_FSP(fsp,conn);
4001   CHECK_WRITE(fsp);
4002
4003   tcount = SVAL(inbuf,smb_vwv1);
4004   startpos = IVAL(inbuf,smb_vwv2);
4005   numtowrite = SVAL(inbuf,smb_vwv6);
4006   smb_doff = SVAL(inbuf,smb_vwv7);
4007
4008   data = smb_base(inbuf) + smb_doff;
4009
4010   /* We need to send an SMBwriteC response, not an SMBwritebs */
4011   CVAL(outbuf,smb_com) = SMBwritec;
4012
4013   /* This fd should have an auxiliary struct attached,
4014      check that it does */
4015   wbms = fsp->wbmpx_ptr;
4016   if(!wbms) return(-1);
4017
4018   /* If write through is set we can return errors, else we must
4019      cache them */
4020   write_through = wbms->wr_mode;
4021
4022   /* Check for an earlier error */
4023   if(wbms->wr_discard)
4024     return -1; /* Just discard the packet */
4025
4026   if(seek_file(fsp,startpos) == -1)
4027   {
4028     if(write_through)
4029     {
4030       /* We are returning an error - we can delete the aux struct */
4031       if (wbms) free((char *)wbms);
4032       fsp->wbmpx_ptr = NULL;
4033       return(UNIXERROR(ERRDOS,ERRnoaccess));
4034     }
4035     return(CACHE_ERROR(wbms,ERRDOS,ERRnoaccess));
4036   } 
4037
4038   nwritten = write_file(fsp,data,numtowrite);
4039
4040   if(lp_syncalways(SNUM(conn)) || write_through)
4041     sync_file(conn,fsp);
4042   
4043   if (nwritten < (ssize_t)numtowrite)
4044   {
4045     if(write_through)
4046     {
4047       /* We are returning an error - we can delete the aux struct */
4048       if (wbms) free((char *)wbms);
4049       fsp->wbmpx_ptr = NULL;
4050       return(ERROR(ERRHRD,ERRdiskfull));
4051     }
4052     return(CACHE_ERROR(wbms,ERRHRD,ERRdiskfull));
4053   }
4054
4055   /* Increment the total written, if this matches tcount
4056      we can discard the auxiliary struct (hurrah !) and return a writeC */
4057   wbms->wr_total_written += nwritten;
4058   if(wbms->wr_total_written >= tcount)
4059   {
4060     if (write_through)
4061     {
4062       outsize = set_message(outbuf,1,0,True);
4063       SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);    
4064       send_response = True;
4065     }
4066
4067     free((char *)wbms);
4068     fsp->wbmpx_ptr = NULL;
4069   }
4070
4071   if(send_response)
4072     return(outsize);
4073
4074   return(-1);
4075 }
4076
4077
4078 /****************************************************************************
4079   reply to a SMBsetattrE
4080 ****************************************************************************/
4081 int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4082 {
4083   struct utimbuf unix_times;
4084   int outsize = 0;
4085   files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4086
4087   outsize = set_message(outbuf,0,0,True);
4088
4089   CHECK_FSP(fsp,conn);
4090   CHECK_ERROR(fsp);
4091
4092   /* Convert the DOS times into unix times. Ignore create
4093      time as UNIX can't set this.
4094      */
4095   unix_times.actime = make_unix_date2(inbuf+smb_vwv3);
4096   unix_times.modtime = make_unix_date2(inbuf+smb_vwv5);
4097   
4098   /* 
4099    * Patch from Ray Frush <frush@engr.colostate.edu>
4100    * Sometimes times are sent as zero - ignore them.
4101    */
4102
4103   if ((unix_times.actime == 0) && (unix_times.modtime == 0)) 
4104   {
4105     /* Ignore request */
4106     if( DEBUGLVL( 3 ) )
4107       {
4108       dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
4109       dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
4110       }
4111     return(outsize);
4112   }
4113   else if ((unix_times.actime != 0) && (unix_times.modtime == 0)) 
4114   {
4115     /* set modify time = to access time if modify time was 0 */
4116     unix_times.modtime = unix_times.actime;
4117   }
4118
4119   /* Set the date on this file */
4120   if(file_utime(conn, fsp->fsp_name, &unix_times))
4121     return(ERROR(ERRDOS,ERRnoaccess));
4122   
4123   DEBUG( 3, ( "reply_setattrE fnum=%d actime=%d modtime=%d\n",
4124             fsp->fnum, (int)unix_times.actime, (int)unix_times.modtime ) );
4125
4126   return(outsize);
4127 }
4128
4129
4130 /****************************************************************************
4131   reply to a SMBgetattrE
4132 ****************************************************************************/
4133 int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4134 {
4135   SMB_STRUCT_STAT sbuf;
4136   int outsize = 0;
4137   int mode;
4138   files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4139
4140   outsize = set_message(outbuf,11,0,True);
4141
4142   CHECK_FSP(fsp,conn);
4143   CHECK_ERROR(fsp);
4144
4145   /* Do an fstat on this file */
4146   if(sys_fstat(fsp->fd_ptr->fd, &sbuf))
4147     return(UNIXERROR(ERRDOS,ERRnoaccess));
4148   
4149   mode = dos_mode(conn,fsp->fsp_name,&sbuf);
4150   
4151   /* Convert the times into dos times. Set create
4152      date to be last modify date as UNIX doesn't save
4153      this */
4154   put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
4155   put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
4156   put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
4157   if (mode & aDIR)
4158     {
4159       SIVAL(outbuf,smb_vwv6,0);
4160       SIVAL(outbuf,smb_vwv8,0);
4161     }
4162   else
4163     {
4164       SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
4165       SIVAL(outbuf,smb_vwv8,SMB_ROUNDUP(sbuf.st_size,1024));
4166     }
4167   SSVAL(outbuf,smb_vwv10, mode);
4168   
4169   DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
4170   
4171   return(outsize);
4172 }