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