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