Ok - this is the 64 bit widening check in. It changes the configure
[ira/wip.git] / source3 / smbd / reply.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 1.9.
4    Main SMB reply routines
5    Copyright (C) Andrew Tridgell 1992-1998
6    
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11    
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16    
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21 /*
22    This file handles most of the reply_ calls that the server
23    makes to handle specific protocols
24 */
25
26
27 #include "includes.h"
28 #include "trans2.h"
29 #include "nterr.h"
30
31 /* look in server.c for some explanation of these variables */
32 extern int Protocol;
33 extern int DEBUGLEVEL;
34 extern int max_send;
35 extern int max_recv;
36 extern char magic_char;
37 extern BOOL case_sensitive;
38 extern BOOL case_preserve;
39 extern BOOL short_case_preserve;
40 extern pstring sesssetup_user;
41 extern fstring global_myworkgroup;
42 extern int Client;
43 extern int global_oplock_break;
44
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   int maxcount,mincount;
1769   int nread = 0;
1770   uint32 startpos;
1771   char *header = outbuf;
1772   SMB_OFF_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   maxcount = SVAL(inbuf,smb_vwv3);
1795   mincount = SVAL(inbuf,smb_vwv4);
1796
1797   /* ensure we don't overrun the packet size */
1798   maxcount = MIN(65535,maxcount);
1799   maxcount = MAX(mincount,maxcount);
1800
1801   if (!FNUM_OK(fsp,conn) || !fsp->can_read) {
1802           DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",fsp->fnum));
1803           _smb_setlen(header,0);
1804           transfer_file(0,Client,(SMB_OFF_T)0,header,4,0);
1805           return(-1);
1806   } else {
1807           fd = fsp->fd_ptr->fd;
1808           fname = fsp->fsp_name;
1809   }
1810
1811
1812   if (!is_locked(fsp,conn,maxcount,startpos, F_RDLCK))
1813   {
1814     SMB_OFF_T size = fsp->size;
1815     int sizeneeded = startpos + maxcount;
1816             
1817     if (size < sizeneeded) {
1818       SMB_STRUCT_STAT st;
1819       if (sys_fstat(fsp->fd_ptr->fd,&st) == 0)
1820         size = st.st_size;
1821       if (!fsp->can_write) 
1822         fsp->size = size;
1823     }
1824
1825     nread = MIN(maxcount,(int)(size - startpos));         
1826   }
1827
1828   if (nread < mincount)
1829     nread = 0;
1830   
1831   DEBUG( 3, ( "readbraw fnum=%d start=%d max=%d min=%d nread=%d\n",
1832               fsp->fnum, startpos,
1833               maxcount, mincount, nread ) );
1834   
1835 #if UNSAFE_READRAW
1836   {
1837     int predict=0;
1838     _smb_setlen(header,nread);
1839
1840 #if USE_READ_PREDICTION
1841     if (!fsp->can_write)
1842       predict = read_predict(fd,startpos,header+4,NULL,nread);
1843 #endif
1844
1845     if ((nread-predict) > 0)
1846       seek_file(fsp,startpos + predict);
1847     
1848     ret = transfer_file(fd,Client,(SMB_OFF_T)(nread-predict),header,4+predict,
1849                         startpos+predict);
1850   }
1851
1852   if (ret != nread+4)
1853     DEBUG(0,("ERROR: file read failure on %s at %d for %d bytes (%d)\n",
1854              fname,startpos,nread,ret));
1855
1856 #else
1857   ret = read_file(fsp,header+4,startpos,nread);
1858   if (ret < mincount) ret = 0;
1859
1860   _smb_setlen(header,ret);
1861   transfer_file(0,Client,0,header,4+ret,0);
1862 #endif
1863
1864   DEBUG(5,("readbraw finished\n"));
1865   return -1;
1866 }
1867
1868
1869 /****************************************************************************
1870   reply to a lockread (core+ protocol)
1871 ****************************************************************************/
1872 int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length, int dum_buffsiz)
1873 {
1874   int nread = -1;
1875   char *data;
1876   int outsize = 0;
1877   uint32 startpos, numtoread;
1878   int eclass;
1879   uint32 ecode;
1880   files_struct *fsp = file_fsp(inbuf,smb_vwv0);
1881
1882   CHECK_FSP(fsp,conn);
1883   CHECK_READ(fsp);
1884   CHECK_ERROR(fsp);
1885
1886   numtoread = SVAL(inbuf,smb_vwv1);
1887   startpos = IVAL(inbuf,smb_vwv2);
1888   
1889   outsize = set_message(outbuf,5,3,True);
1890   numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1891   data = smb_buf(outbuf) + 3;
1892   
1893   if(!do_lock( fsp, conn, numtoread, startpos, F_RDLCK, &eclass, &ecode)) {
1894     if(ecode == ERRlock) {
1895       /*
1896        * A blocking lock was requested. Package up
1897        * this smb into a queued request and push it
1898        * onto the blocking lock queue.
1899        */
1900       if(push_blocking_lock_request(inbuf, length, -1, 0))
1901         return -1;
1902     }
1903     return (ERROR(eclass,ecode));
1904   }
1905
1906   nread = read_file(fsp,data,startpos,numtoread);
1907
1908   if (nread < 0)
1909     return(UNIXERROR(ERRDOS,ERRnoaccess));
1910
1911   outsize += nread;
1912   SSVAL(outbuf,smb_vwv0,nread);
1913   SSVAL(outbuf,smb_vwv5,nread+3);
1914   SSVAL(smb_buf(outbuf),1,nread);
1915
1916   DEBUG( 3, ( "lockread fnum=%d num=%d nread=%d\n",
1917             fsp->fnum, numtoread, nread ) );
1918
1919   return(outsize);
1920 }
1921
1922
1923 /****************************************************************************
1924   reply to a read
1925 ****************************************************************************/
1926 int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1927 {
1928   int numtoread;
1929   int nread = 0;
1930   char *data;
1931   uint32 startpos;
1932   int outsize = 0;
1933   files_struct *fsp = file_fsp(inbuf,smb_vwv0);
1934
1935   CHECK_FSP(fsp,conn);
1936   CHECK_READ(fsp);
1937   CHECK_ERROR(fsp);
1938
1939   numtoread = SVAL(inbuf,smb_vwv1);
1940   startpos = IVAL(inbuf,smb_vwv2);
1941   
1942   outsize = set_message(outbuf,5,3,True);
1943   numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1944   data = smb_buf(outbuf) + 3;
1945   
1946   if (is_locked(fsp,conn,numtoread,startpos, F_RDLCK))
1947     return(ERROR(ERRDOS,ERRlock));      
1948
1949   if (numtoread > 0)
1950     nread = read_file(fsp,data,startpos,numtoread);
1951   
1952   if (nread < 0)
1953     return(UNIXERROR(ERRDOS,ERRnoaccess));
1954   
1955   outsize += nread;
1956   SSVAL(outbuf,smb_vwv0,nread);
1957   SSVAL(outbuf,smb_vwv5,nread+3);
1958   CVAL(smb_buf(outbuf),0) = 1;
1959   SSVAL(smb_buf(outbuf),1,nread);
1960   
1961   DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
1962             fsp->fnum, numtoread, nread ) );
1963
1964   return(outsize);
1965 }
1966
1967
1968 /****************************************************************************
1969   reply to a read and X
1970 ****************************************************************************/
1971 int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1972 {
1973   files_struct *fsp = file_fsp(inbuf,smb_vwv2);
1974   uint32 smb_offs = IVAL(inbuf,smb_vwv3);
1975   int smb_maxcnt = SVAL(inbuf,smb_vwv5);
1976   int smb_mincnt = SVAL(inbuf,smb_vwv6);
1977   int nread = -1;
1978   char *data;
1979   BOOL ok = False;
1980
1981   /* If it's an IPC, pass off the pipe handler. */
1982   if (IS_IPC(conn))
1983     return reply_pipe_read_and_X(inbuf,outbuf,length,bufsize);
1984
1985   CHECK_FSP(fsp,conn);
1986   CHECK_READ(fsp);
1987   CHECK_ERROR(fsp);
1988
1989   set_message(outbuf,12,0,True);
1990   data = smb_buf(outbuf);
1991
1992   if (is_locked(fsp,conn,smb_maxcnt,smb_offs, F_RDLCK))
1993     return(ERROR(ERRDOS,ERRlock));
1994   nread = read_file(fsp,data,smb_offs,smb_maxcnt);
1995   ok = True;
1996   
1997   if (nread < 0)
1998     return(UNIXERROR(ERRDOS,ERRnoaccess));
1999   
2000   SSVAL(outbuf,smb_vwv5,nread);
2001   SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2002   SSVAL(smb_buf(outbuf),-2,nread);
2003   
2004   DEBUG( 3, ( "readX fnum=%d min=%d max=%d nread=%d\n",
2005               fsp->fnum, smb_mincnt, smb_maxcnt, nread ) );
2006
2007   return chain_reply(inbuf,outbuf,length,bufsize);
2008 }
2009
2010
2011 /****************************************************************************
2012   reply to a writebraw (core+ or LANMAN1.0 protocol)
2013 ****************************************************************************/
2014 int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2015 {
2016   int nwritten=0;
2017   int total_written=0;
2018   int numtowrite=0;
2019   int outsize = 0;
2020   long startpos;
2021   char *data=NULL;
2022   BOOL write_through;
2023   int tcount;
2024   files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2025
2026   CHECK_FSP(fsp,conn);
2027   CHECK_WRITE(fsp);
2028   CHECK_ERROR(fsp);
2029   
2030   tcount = IVAL(inbuf,smb_vwv1);
2031   startpos = IVAL(inbuf,smb_vwv3);
2032   write_through = BITSETW(inbuf+smb_vwv7,0);
2033
2034   /* We have to deal with slightly different formats depending
2035      on whether we are using the core+ or lanman1.0 protocol */
2036   if(Protocol <= PROTOCOL_COREPLUS) {
2037     numtowrite = SVAL(smb_buf(inbuf),-2);
2038     data = smb_buf(inbuf);
2039   } else {
2040     numtowrite = SVAL(inbuf,smb_vwv10);
2041     data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
2042   }
2043
2044   /* force the error type */
2045   CVAL(inbuf,smb_com) = SMBwritec;
2046   CVAL(outbuf,smb_com) = SMBwritec;
2047
2048   if (is_locked(fsp,conn,tcount,startpos, F_WRLCK))
2049     return(ERROR(ERRDOS,ERRlock));
2050
2051   if (seek_file(fsp,startpos) != startpos)
2052     DEBUG(0,("couldn't seek to %ld in writebraw\n",startpos));
2053
2054   if (numtowrite>0)
2055     nwritten = write_file(fsp,data,numtowrite);
2056   
2057   DEBUG(3,("writebraw1 fnum=%d start=%ld num=%d wrote=%d sync=%d\n",
2058            fsp->fnum, startpos, numtowrite, nwritten, write_through));
2059
2060   if (nwritten < numtowrite) 
2061     return(UNIXERROR(ERRHRD,ERRdiskfull));
2062
2063   total_written = nwritten;
2064
2065   /* Return a message to the redirector to tell it
2066      to send more bytes */
2067   CVAL(outbuf,smb_com) = SMBwritebraw;
2068   SSVALS(outbuf,smb_vwv0,-1);
2069   outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
2070   send_smb(Client,outbuf);
2071   
2072   /* Now read the raw data into the buffer and write it */
2073   if (read_smb_length(Client,inbuf,SMB_SECONDARY_WAIT) == -1) {
2074     exit_server("secondary writebraw failed");
2075   }
2076   
2077   /* Even though this is not an smb message, smb_len
2078      returns the generic length of an smb message */
2079   numtowrite = smb_len(inbuf);
2080
2081   if (tcount > nwritten+numtowrite) {
2082     DEBUG(3,("Client overestimated the write %d %d %d\n",
2083              tcount,nwritten,numtowrite));
2084   }
2085
2086   nwritten = transfer_file(Client,fsp->fd_ptr->fd,(SMB_OFF_T)numtowrite,NULL,0,
2087                            startpos+nwritten);
2088   total_written += nwritten;
2089   
2090   /* Set up outbuf to return the correct return */
2091   outsize = set_message(outbuf,1,0,True);
2092   CVAL(outbuf,smb_com) = SMBwritec;
2093   SSVAL(outbuf,smb_vwv0,total_written);
2094
2095   if (nwritten < numtowrite) {
2096     CVAL(outbuf,smb_rcls) = ERRHRD;
2097     SSVAL(outbuf,smb_err,ERRdiskfull);      
2098   }
2099
2100   if (lp_syncalways(SNUM(conn)) || write_through)
2101     sync_file(conn,fsp);
2102
2103   DEBUG(3,("writebraw2 fnum=%d start=%ld num=%d wrote=%d\n",
2104            fsp->fnum, startpos, numtowrite, total_written));
2105
2106   /* we won't return a status if write through is not selected - this 
2107      follows what WfWg does */
2108   if (!write_through && total_written==tcount)
2109     return(-1);
2110
2111   return(outsize);
2112 }
2113
2114
2115 /****************************************************************************
2116   reply to a writeunlock (core+)
2117 ****************************************************************************/
2118 int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2119 {
2120   int nwritten = -1;
2121   int outsize = 0;
2122   char *data;
2123   uint32 numtowrite,startpos;
2124   int eclass;
2125   uint32 ecode;
2126   files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2127
2128   CHECK_FSP(fsp,conn);
2129   CHECK_WRITE(fsp);
2130   CHECK_ERROR(fsp);
2131
2132   numtowrite = SVAL(inbuf,smb_vwv1);
2133   startpos = IVAL(inbuf,smb_vwv2);
2134   data = smb_buf(inbuf) + 3;
2135   
2136   if (is_locked(fsp,conn,numtowrite,startpos, F_WRLCK))
2137     return(ERROR(ERRDOS,ERRlock));
2138
2139   seek_file(fsp,startpos);
2140
2141   /* The special X/Open SMB protocol handling of
2142      zero length writes is *NOT* done for
2143      this call */
2144   if(numtowrite == 0)
2145     nwritten = 0;
2146   else
2147     nwritten = write_file(fsp,data,numtowrite);
2148   
2149   if (lp_syncalways(SNUM(conn)))
2150     sync_file(conn,fsp);
2151
2152   if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0))
2153     return(UNIXERROR(ERRDOS,ERRnoaccess));
2154
2155   if(!do_unlock(fsp, conn, numtowrite, startpos, &eclass, &ecode))
2156     return(ERROR(eclass,ecode));
2157
2158   outsize = set_message(outbuf,1,0,True);
2159   
2160   SSVAL(outbuf,smb_vwv0,nwritten);
2161   
2162   DEBUG( 3, ( "writeunlock fnum=%d num=%d wrote=%d\n",
2163               fsp->fnum, numtowrite, nwritten ) );
2164
2165   return(outsize);
2166 }
2167
2168
2169 /****************************************************************************
2170   reply to a write
2171 ****************************************************************************/
2172 int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int dum_size,int dum_buffsize)
2173 {
2174   int numtowrite;
2175   int nwritten = -1;
2176   int outsize = 0;
2177   int startpos;
2178   char *data;
2179   files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2180
2181   CHECK_FSP(fsp,conn);
2182   CHECK_WRITE(fsp);
2183   CHECK_ERROR(fsp);
2184
2185   numtowrite = SVAL(inbuf,smb_vwv1);
2186   startpos = IVAL(inbuf,smb_vwv2);
2187   data = smb_buf(inbuf) + 3;
2188   
2189   if (is_locked(fsp,conn,numtowrite,startpos, F_WRLCK))
2190     return(ERROR(ERRDOS,ERRlock));
2191
2192   seek_file(fsp,startpos);
2193
2194   /* X/Open SMB protocol says that if smb_vwv1 is
2195      zero then the file size should be extended or
2196      truncated to the size given in smb_vwv[2-3] */
2197   if(numtowrite == 0)
2198     nwritten = set_filelen(fsp->fd_ptr->fd, (SMB_OFF_T)startpos);
2199   else
2200     nwritten = write_file(fsp,data,numtowrite);
2201   
2202   if (lp_syncalways(SNUM(conn)))
2203     sync_file(conn,fsp);
2204
2205   if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0))
2206     return(UNIXERROR(ERRDOS,ERRnoaccess));
2207
2208   outsize = set_message(outbuf,1,0,True);
2209   
2210   SSVAL(outbuf,smb_vwv0,nwritten);
2211
2212   if (nwritten < numtowrite) {
2213     CVAL(outbuf,smb_rcls) = ERRHRD;
2214     SSVAL(outbuf,smb_err,ERRdiskfull);      
2215   }
2216   
2217   DEBUG(3,("write fnum=%d num=%d wrote=%d\n",
2218            fsp->fnum, numtowrite, nwritten));
2219
2220   return(outsize);
2221 }
2222
2223
2224 /****************************************************************************
2225   reply to a write and X
2226 ****************************************************************************/
2227 int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2228 {
2229   files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2230   uint32 smb_offs = IVAL(inbuf,smb_vwv3);
2231   int smb_dsize = SVAL(inbuf,smb_vwv10);
2232   int smb_doff = SVAL(inbuf,smb_vwv11);
2233   BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
2234   int nwritten = -1;
2235   char *data;
2236
2237   CHECK_FSP(fsp,conn);
2238   CHECK_WRITE(fsp);
2239   CHECK_ERROR(fsp);
2240
2241   data = smb_base(inbuf) + smb_doff;
2242
2243   if (is_locked(fsp,conn,smb_dsize,smb_offs, F_WRLCK))
2244     return(ERROR(ERRDOS,ERRlock));
2245
2246   seek_file(fsp,smb_offs);
2247   
2248   /* X/Open SMB protocol says that, unlike SMBwrite
2249      if the length is zero then NO truncation is
2250      done, just a write of zero. To truncate a file,
2251      use SMBwrite. */
2252   if(smb_dsize == 0)
2253     nwritten = 0;
2254   else
2255     nwritten = write_file(fsp,data,smb_dsize);
2256   
2257   if(((nwritten == 0) && (smb_dsize != 0))||(nwritten < 0))
2258     return(UNIXERROR(ERRDOS,ERRnoaccess));
2259
2260   set_message(outbuf,6,0,True);
2261   
2262   SSVAL(outbuf,smb_vwv2,nwritten);
2263   
2264   if (nwritten < smb_dsize) {
2265     CVAL(outbuf,smb_rcls) = ERRHRD;
2266     SSVAL(outbuf,smb_err,ERRdiskfull);      
2267   }
2268
2269   DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
2270            fsp->fnum, smb_dsize, nwritten));
2271
2272   if (lp_syncalways(SNUM(conn)) || write_through)
2273     sync_file(conn,fsp);
2274
2275   return chain_reply(inbuf,outbuf,length,bufsize);
2276 }
2277
2278
2279 /****************************************************************************
2280   reply to a lseek
2281 ****************************************************************************/
2282 int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2283 {
2284   uint32 startpos;
2285   SMB_OFF_T res= -1;
2286   int mode,umode;
2287   int outsize = 0;
2288   files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2289
2290   CHECK_FSP(fsp,conn);
2291   CHECK_ERROR(fsp);
2292
2293   mode = SVAL(inbuf,smb_vwv1) & 3;
2294   startpos = IVAL(inbuf,smb_vwv2);
2295
2296   switch (mode & 3) 
2297   {
2298     case 0: umode = SEEK_SET; break;
2299     case 1: umode = SEEK_CUR; break;
2300     case 2: umode = SEEK_END; break;
2301     default:
2302       umode = SEEK_SET; break;
2303   }
2304
2305   res = sys_lseek(fsp->fd_ptr->fd,(SMB_OFF_T)startpos,umode);
2306   fsp->pos = res;
2307   
2308   outsize = set_message(outbuf,2,0,True);
2309   SIVALS(outbuf,smb_vwv0,(uint32)res);
2310   
2311   DEBUG(3,("lseek fnum=%d ofs=%d mode=%d\n",
2312            fsp->fnum, startpos, mode));
2313
2314   return(outsize);
2315 }
2316
2317
2318 /****************************************************************************
2319   reply to a flush
2320 ****************************************************************************/
2321 int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2322 {
2323   int outsize = set_message(outbuf,0,0,True);
2324   files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2325
2326   if (fsp) {
2327           CHECK_FSP(fsp,conn);
2328           CHECK_ERROR(fsp);
2329   }
2330
2331   if (!fsp) {
2332           file_sync_all(conn);
2333   } else {
2334           sync_file(conn,fsp);
2335   }
2336
2337   DEBUG(3,("flush\n"));
2338   return(outsize);
2339 }
2340
2341
2342 /****************************************************************************
2343   reply to a exit
2344 ****************************************************************************/
2345 int reply_exit(connection_struct *conn, 
2346                char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2347 {
2348         int outsize = set_message(outbuf,0,0,True);
2349         DEBUG(3,("exit\n"));
2350
2351         return(outsize);
2352 }
2353
2354
2355 /****************************************************************************
2356  Reply to a close - has to deal with closing a directory opened by NT SMB's.
2357 ****************************************************************************/
2358 int reply_close(connection_struct *conn,
2359                 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2360 {
2361         int outsize = 0;
2362         time_t mtime;
2363         int32 eclass = 0, err = 0;
2364         files_struct *fsp = NULL;
2365
2366         outsize = set_message(outbuf,0,0,True);
2367
2368         /* If it's an IPC, pass off to the pipe handler. */
2369         if (IS_IPC(conn)) {
2370                 return reply_pipe_close(conn, inbuf,outbuf);
2371         }
2372
2373         fsp = file_fsp(inbuf,smb_vwv0);
2374
2375         /*
2376          * We can only use CHECK_FSP if we know it's not a directory.
2377          */
2378
2379         if(!(fsp && fsp->open && fsp->is_directory))
2380                 CHECK_FSP(fsp,conn);
2381
2382         if(HAS_CACHED_ERROR(fsp)) {
2383                 eclass = fsp->wbmpx_ptr->wr_errclass;
2384                 err = fsp->wbmpx_ptr->wr_error;
2385         }
2386
2387         if(fsp->is_directory) {
2388                 /*
2389                  * Special case - close NT SMB directory
2390                  * handle.
2391                  */
2392                 DEBUG(3,("close directory fnum=%d\n", fsp->fnum));
2393                 close_directory(fsp);
2394         } else {
2395                 /*
2396                  * Close ordinary file.
2397                  */
2398                 mtime = make_unix_date3(inbuf+smb_vwv1);
2399                 
2400                 /* try and set the date */
2401                 set_filetime(conn, fsp->fsp_name,mtime);
2402
2403                 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
2404                          fsp->fd_ptr->fd, fsp->fnum,
2405                          conn->num_files_open));
2406   
2407                 close_file(fsp,True);
2408         }  
2409
2410         /* We have a cached error */
2411         if(eclass || err)
2412                 return(ERROR(eclass,err));
2413
2414         return(outsize);
2415 }
2416
2417
2418 /****************************************************************************
2419   reply to a writeclose (Core+ protocol)
2420 ****************************************************************************/
2421 int reply_writeclose(connection_struct *conn,
2422                      char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2423 {
2424         int numtowrite;
2425         int nwritten = -1;
2426         int outsize = 0;
2427         int startpos;
2428         char *data;
2429         time_t mtime;
2430         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2431
2432         CHECK_FSP(fsp,conn);
2433         CHECK_WRITE(fsp);
2434         CHECK_ERROR(fsp);
2435
2436         numtowrite = SVAL(inbuf,smb_vwv1);
2437         startpos = IVAL(inbuf,smb_vwv2);
2438         mtime = make_unix_date3(inbuf+smb_vwv4);
2439         data = smb_buf(inbuf) + 1;
2440   
2441         if (is_locked(fsp,conn,numtowrite,startpos, F_WRLCK))
2442                 return(ERROR(ERRDOS,ERRlock));
2443       
2444         seek_file(fsp,startpos);
2445       
2446         nwritten = write_file(fsp,data,numtowrite);
2447
2448         set_filetime(conn, fsp->fsp_name,mtime);
2449   
2450         close_file(fsp,True);
2451
2452         DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
2453                  fsp->fnum, numtowrite, nwritten,
2454                  conn->num_files_open));
2455   
2456         if (nwritten <= 0)
2457                 return(UNIXERROR(ERRDOS,ERRnoaccess));
2458   
2459         outsize = set_message(outbuf,1,0,True);
2460   
2461         SSVAL(outbuf,smb_vwv0,nwritten);
2462         return(outsize);
2463 }
2464
2465
2466 /****************************************************************************
2467   reply to a lock
2468 ****************************************************************************/
2469 int reply_lock(connection_struct *conn,
2470                char *inbuf,char *outbuf, int length, int dum_buffsize)
2471 {
2472         int outsize = set_message(outbuf,0,0,True);
2473         uint32 count,offset;
2474         int eclass;
2475         uint32 ecode;
2476         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2477
2478         CHECK_FSP(fsp,conn);
2479         CHECK_ERROR(fsp);
2480
2481         count = IVAL(inbuf,smb_vwv1);
2482         offset = IVAL(inbuf,smb_vwv3);
2483
2484         DEBUG(3,("lock fd=%d fnum=%d ofs=%d cnt=%d\n",
2485                  fsp->fd_ptr->fd, fsp->fnum, offset, count));
2486
2487         if (!do_lock(fsp, conn, count, offset, F_WRLCK, &eclass, &ecode)) {
2488       if(ecode == ERRlock) {
2489         /*
2490          * A blocking lock was requested. Package up
2491          * this smb into a queued request and push it
2492          * onto the blocking lock queue.
2493          */
2494         if(push_blocking_lock_request(inbuf, length, -1, 0))
2495           return -1;
2496       }
2497       return (ERROR(eclass,ecode));
2498     }
2499
2500         return(outsize);
2501 }
2502
2503
2504 /****************************************************************************
2505   reply to a unlock
2506 ****************************************************************************/
2507 int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2508 {
2509   int outsize = set_message(outbuf,0,0,True);
2510   uint32 count,offset;
2511   int eclass;
2512   uint32 ecode;
2513   files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2514
2515   CHECK_FSP(fsp,conn);
2516   CHECK_ERROR(fsp);
2517
2518   count = IVAL(inbuf,smb_vwv1);
2519   offset = IVAL(inbuf,smb_vwv3);
2520
2521   if(!do_unlock(fsp, conn, count, offset, &eclass, &ecode))
2522     return (ERROR(eclass,ecode));
2523
2524   DEBUG( 3, ( "unlock fd=%d fnum=%d ofs=%d cnt=%d\n",
2525         fsp->fd_ptr->fd, fsp->fnum, offset, count ) );
2526   
2527   return(outsize);
2528 }
2529
2530
2531 /****************************************************************************
2532   reply to a tdis
2533 ****************************************************************************/
2534 int reply_tdis(connection_struct *conn, 
2535                char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2536 {
2537         int outsize = set_message(outbuf,0,0,True);
2538         uint16 vuid;
2539
2540         vuid = SVAL(inbuf,smb_uid);
2541
2542         if (!conn) {
2543                 DEBUG(4,("Invalid connection in tdis\n"));
2544                 return(ERROR(ERRSRV,ERRinvnid));
2545         }
2546
2547         conn->used = False;
2548
2549         close_cnum(conn,vuid);
2550   
2551         return outsize;
2552 }
2553
2554
2555
2556 /****************************************************************************
2557   reply to a echo
2558 ****************************************************************************/
2559 int reply_echo(connection_struct *conn,
2560                char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2561 {
2562         int smb_reverb = SVAL(inbuf,smb_vwv0);
2563         int seq_num;
2564         int data_len = smb_buflen(inbuf);
2565         int outsize = set_message(outbuf,1,data_len,True);
2566         
2567         /* copy any incoming data back out */
2568         if (data_len > 0)
2569                 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
2570
2571         if (smb_reverb > 100) {
2572                 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
2573                 smb_reverb = 100;
2574         }
2575
2576         for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
2577                 SSVAL(outbuf,smb_vwv0,seq_num);
2578
2579                 smb_setlen(outbuf,outsize - 4);
2580
2581                 send_smb(Client,outbuf);
2582         }
2583
2584         DEBUG(3,("echo %d times\n", smb_reverb));
2585
2586         return -1;
2587 }
2588
2589
2590 /****************************************************************************
2591   reply to a printopen
2592 ****************************************************************************/
2593 int reply_printopen(connection_struct *conn, 
2594                     char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2595 {
2596         pstring fname;
2597         pstring fname2;
2598         int outsize = 0;
2599         files_struct *fsp;
2600         
2601         *fname = *fname2 = 0;
2602         
2603         if (!CAN_PRINT(conn))
2604                 return(ERROR(ERRDOS,ERRnoaccess));
2605
2606         {
2607                 pstring s;
2608                 char *p;
2609                 pstrcpy(s,smb_buf(inbuf)+1);
2610                 p = s;
2611                 while (*p) {
2612                         if (!(isalnum((int)*p) || strchr("._-",*p)))
2613                                 *p = 'X';
2614                         p++;
2615                 }
2616
2617                 if (strlen(s) > 10) s[10] = 0;
2618
2619                 slprintf(fname,sizeof(fname)-1, "%s.XXXXXX",s);  
2620         }
2621
2622         fsp = file_new();
2623         if (!fsp)
2624                 return(ERROR(ERRSRV,ERRnofids));
2625         
2626         pstrcpy(fname2,(char *)mktemp(fname));
2627
2628         if (!check_name(fname2,conn)) {
2629                 file_free(fsp);
2630                 return(ERROR(ERRDOS,ERRnoaccess));
2631         }
2632
2633         /* Open for exclusive use, write only. */
2634         open_file_shared(fsp,conn,fname2,
2635                          (DENY_ALL<<4)|1, 0x12, unix_mode(conn,0), 
2636                          0, NULL, NULL);
2637
2638         if (!fsp->open) {
2639                 file_free(fsp);
2640                 return(UNIXERROR(ERRDOS,ERRnoaccess));
2641         }
2642
2643         /* force it to be a print file */
2644         fsp->print_file = True;
2645   
2646         outsize = set_message(outbuf,1,0,True);
2647         SSVAL(outbuf,smb_vwv0,fsp->fnum);
2648   
2649         DEBUG(3,("openprint %s fd=%d fnum=%d\n",
2650                    fname2, fsp->fd_ptr->fd, fsp->fnum));
2651
2652         return(outsize);
2653 }
2654
2655
2656 /****************************************************************************
2657   reply to a printclose
2658 ****************************************************************************/
2659 int reply_printclose(connection_struct *conn,
2660                      char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2661 {
2662         int outsize = set_message(outbuf,0,0,True);
2663         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2664
2665         CHECK_FSP(fsp,conn);
2666         CHECK_ERROR(fsp);
2667
2668         if (!CAN_PRINT(conn))
2669                 return(ERROR(ERRDOS,ERRnoaccess));
2670   
2671         DEBUG(3,("printclose fd=%d fnum=%d\n",
2672                  fsp->fd_ptr->fd,fsp->fnum));
2673   
2674         close_file(fsp,True);
2675
2676         return(outsize);
2677 }
2678
2679
2680 /****************************************************************************
2681   reply to a printqueue
2682 ****************************************************************************/
2683 int reply_printqueue(connection_struct *conn,
2684                      char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2685 {
2686         int outsize = set_message(outbuf,2,3,True);
2687         int max_count = SVAL(inbuf,smb_vwv0);
2688         int start_index = SVAL(inbuf,smb_vwv1);
2689         uint16 vuid;
2690
2691         vuid = SVAL(inbuf,smb_uid);
2692
2693         /* we used to allow the client to get the cnum wrong, but that
2694            is really quite gross and only worked when there was only
2695            one printer - I think we should now only accept it if they
2696            get it right (tridge) */
2697         if (!CAN_PRINT(conn))
2698                 return(ERROR(ERRDOS,ERRnoaccess));
2699
2700         SSVAL(outbuf,smb_vwv0,0);
2701         SSVAL(outbuf,smb_vwv1,0);
2702         CVAL(smb_buf(outbuf),0) = 1;
2703         SSVAL(smb_buf(outbuf),1,0);
2704   
2705         DEBUG(3,("printqueue start_index=%d max_count=%d\n",
2706                  start_index, max_count));
2707
2708         {
2709                 print_queue_struct *queue = NULL;
2710                 char *p = smb_buf(outbuf) + 3;
2711                 int count = get_printqueue(SNUM(conn), conn,&queue,NULL);
2712                 int num_to_get = ABS(max_count);
2713                 int first = (max_count>0?start_index:start_index+max_count+1);
2714                 int i;
2715
2716                 if (first >= count)
2717                         num_to_get = 0;
2718                 else
2719                         num_to_get = MIN(num_to_get,count-first);
2720     
2721
2722                 for (i=first;i<first+num_to_get;i++) {
2723                         put_dos_date2(p,0,queue[i].time);
2724                         CVAL(p,4) = (queue[i].status==LPQ_PRINTING?2:3);
2725                         SSVAL(p,5,printjob_encode(SNUM(conn), 
2726                                                   queue[i].job));
2727                         SIVAL(p,7,queue[i].size);
2728                         CVAL(p,11) = 0;
2729                         StrnCpy(p+12,queue[i].user,16);
2730                         p += 28;
2731                 }
2732
2733                 if (count > 0) {
2734                         outsize = set_message(outbuf,2,28*count+3,False); 
2735                         SSVAL(outbuf,smb_vwv0,count);
2736                         SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
2737                         CVAL(smb_buf(outbuf),0) = 1;
2738                         SSVAL(smb_buf(outbuf),1,28*count);
2739                 }
2740
2741                 if (queue) free(queue);
2742           
2743                 DEBUG(3,("%d entries returned in queue\n",count));
2744         }
2745   
2746         return(outsize);
2747 }
2748
2749
2750 /****************************************************************************
2751   reply to a printwrite
2752 ****************************************************************************/
2753 int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2754 {
2755   int numtowrite;
2756   int outsize = set_message(outbuf,0,0,True);
2757   char *data;
2758   files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2759   
2760   if (!CAN_PRINT(conn))
2761     return(ERROR(ERRDOS,ERRnoaccess));
2762
2763   CHECK_FSP(fsp,conn);
2764   CHECK_WRITE(fsp);
2765   CHECK_ERROR(fsp);
2766
2767   numtowrite = SVAL(smb_buf(inbuf),1);
2768   data = smb_buf(inbuf) + 3;
2769   
2770   if (write_file(fsp,data,numtowrite) != numtowrite)
2771     return(UNIXERROR(ERRDOS,ERRnoaccess));
2772   
2773   DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
2774   
2775   return(outsize);
2776 }
2777
2778
2779 /****************************************************************************
2780   reply to a mkdir
2781 ****************************************************************************/
2782 int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2783 {
2784   pstring directory;
2785   int outsize,ret= -1;
2786   BOOL bad_path = False;
2787  
2788   pstrcpy(directory,smb_buf(inbuf) + 1);
2789   unix_convert(directory,conn,0,&bad_path,NULL);
2790   
2791   if (check_name(directory, conn))
2792     ret = dos_mkdir(directory,unix_mode(conn,aDIR));
2793   
2794   if (ret < 0)
2795   {
2796     if((errno == ENOENT) && bad_path)
2797     {
2798       unix_ERR_class = ERRDOS;
2799       unix_ERR_code = ERRbadpath;
2800     }
2801     return(UNIXERROR(ERRDOS,ERRnoaccess));
2802   }
2803
2804   outsize = set_message(outbuf,0,0,True);
2805
2806   DEBUG( 3, ( "mkdir %s ret=%d\n", directory, ret ) );
2807
2808   return(outsize);
2809 }
2810
2811 /****************************************************************************
2812 Static function used by reply_rmdir to delete an entire directory
2813 tree recursively.
2814 ****************************************************************************/
2815 static BOOL recursive_rmdir(char *directory)
2816 {
2817   char *dname = NULL;
2818   BOOL ret = False;
2819   void *dirptr = OpenDir(NULL, directory, False);
2820
2821   if(dirptr == NULL)
2822     return True;
2823
2824   while((dname = ReadDirName(dirptr)))
2825   {
2826     pstring fullname;
2827     SMB_STRUCT_STAT st;
2828
2829     if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
2830       continue;
2831
2832     /* Construct the full name. */
2833     if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname))
2834     {
2835       errno = ENOMEM;
2836       ret = True;
2837       break;
2838     }
2839     pstrcpy(fullname, directory);
2840     pstrcat(fullname, "/");
2841     pstrcat(fullname, dname);
2842
2843     if(dos_lstat(fullname, &st) != 0)
2844     {
2845       ret = True;
2846       break;
2847     }
2848
2849     if(st.st_mode & S_IFDIR)
2850     {
2851       if(recursive_rmdir(fullname)!=0)
2852       {
2853         ret = True;
2854         break;
2855       }
2856       if(dos_rmdir(fullname) != 0)
2857       {
2858         ret = True;
2859         break;
2860       }
2861     }
2862     else if(dos_unlink(fullname) != 0)
2863     {
2864       ret = True;
2865       break;
2866     }
2867   }
2868   CloseDir(dirptr);
2869   return ret;
2870 }
2871
2872 /****************************************************************************
2873   reply to a rmdir
2874 ****************************************************************************/
2875 int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2876 {
2877   pstring directory;
2878   int outsize = 0;
2879   BOOL ok = False;
2880   BOOL bad_path = False;
2881
2882   pstrcpy(directory,smb_buf(inbuf) + 1);
2883   unix_convert(directory,conn, NULL,&bad_path,NULL);
2884   
2885   if (check_name(directory,conn))
2886     {
2887
2888       dptr_closepath(directory,SVAL(inbuf,smb_pid));
2889       ok = (dos_rmdir(directory) == 0);
2890       if(!ok && (errno == ENOTEMPTY) && lp_veto_files(SNUM(conn)))
2891         {
2892           /* Check to see if the only thing in this directory are
2893              vetoed files/directories. If so then delete them and
2894              retry. If we fail to delete any of them (and we *don't*
2895              do a recursive delete) then fail the rmdir. */
2896           BOOL all_veto_files = True;
2897           char *dname;
2898           void *dirptr = OpenDir(conn, directory, False);
2899
2900           if(dirptr != NULL)
2901             {
2902               int dirpos = TellDir(dirptr);
2903                   while ((dname = ReadDirName(dirptr)))
2904                     {
2905                   if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
2906                     continue;
2907                   if(!IS_VETO_PATH(conn, dname))
2908                     {
2909                       all_veto_files = False;
2910                       break;
2911                     }
2912                 }
2913               if(all_veto_files)
2914                 {
2915                   SeekDir(dirptr,dirpos);
2916                   while ((dname = ReadDirName(dirptr)))
2917                     {
2918                       pstring fullname;
2919                       SMB_STRUCT_STAT st;
2920
2921                       if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
2922                         continue;
2923
2924                       /* Construct the full name. */
2925                       if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname))
2926                         {
2927                           errno = ENOMEM;
2928                           break;
2929                         }
2930                       pstrcpy(fullname, directory);
2931                       pstrcat(fullname, "/");
2932                       pstrcat(fullname, dname);
2933                       
2934                       if(dos_lstat(fullname, &st) != 0)
2935                         break;
2936                       if(st.st_mode & S_IFDIR)
2937                       {
2938                         if(lp_recursive_veto_delete(SNUM(conn)))
2939                         {
2940                           if(recursive_rmdir(fullname) != 0)
2941                             break;
2942                         }
2943                         if(dos_rmdir(fullname) != 0)
2944                           break;
2945                       }
2946                       else if(dos_unlink(fullname) != 0)
2947                         break;
2948                     }
2949                   CloseDir(dirptr);
2950                   /* Retry the rmdir */
2951                   ok = (dos_rmdir(directory) == 0);
2952                 }
2953               else
2954                 CloseDir(dirptr);
2955             }
2956           else
2957             errno = ENOTEMPTY;
2958          }
2959           
2960       if (!ok)
2961         DEBUG(3,("couldn't remove directory %s : %s\n",
2962                  directory,strerror(errno)));
2963     }
2964   
2965   if (!ok)
2966   {
2967     if((errno == ENOENT) && bad_path)
2968     {
2969       unix_ERR_class = ERRDOS;
2970       unix_ERR_code = ERRbadpath;
2971     }
2972     return(UNIXERROR(ERRDOS,ERRbadpath));
2973   }
2974  
2975   outsize = set_message(outbuf,0,0,True);
2976   
2977   DEBUG( 3, ( "rmdir %s\n", directory ) );
2978   
2979   return(outsize);
2980 }
2981
2982
2983 /*******************************************************************
2984 resolve wildcards in a filename rename
2985 ********************************************************************/
2986 static BOOL resolve_wildcards(char *name1,char *name2)
2987 {
2988   fstring root1,root2;
2989   fstring ext1,ext2;
2990   char *p,*p2;
2991
2992   name1 = strrchr(name1,'/');
2993   name2 = strrchr(name2,'/');
2994
2995   if (!name1 || !name2) return(False);
2996   
2997   fstrcpy(root1,name1);
2998   fstrcpy(root2,name2);
2999   p = strrchr(root1,'.');
3000   if (p) {
3001     *p = 0;
3002     fstrcpy(ext1,p+1);
3003   } else {
3004     fstrcpy(ext1,"");    
3005   }
3006   p = strrchr(root2,'.');
3007   if (p) {
3008     *p = 0;
3009     fstrcpy(ext2,p+1);
3010   } else {
3011     fstrcpy(ext2,"");    
3012   }
3013
3014   p = root1;
3015   p2 = root2;
3016   while (*p2) {
3017     if (*p2 == '?') {
3018       *p2 = *p;
3019       p2++;
3020     } else {
3021       p2++;
3022     }
3023     if (*p) p++;
3024   }
3025
3026   p = ext1;
3027   p2 = ext2;
3028   while (*p2) {
3029     if (*p2 == '?') {
3030       *p2 = *p;
3031       p2++;
3032     } else {
3033       p2++;
3034     }
3035     if (*p) p++;
3036   }
3037
3038   pstrcpy(name2,root2);
3039   if (ext2[0]) {
3040     pstrcat(name2,".");
3041     pstrcat(name2,ext2);
3042   }
3043
3044   return(True);
3045 }
3046
3047 /*******************************************************************
3048 check if a user is allowed to rename a file
3049 ********************************************************************/
3050 static BOOL can_rename(char *fname,connection_struct *conn)
3051 {
3052   SMB_STRUCT_STAT sbuf;
3053
3054   if (!CAN_WRITE(conn)) return(False);
3055
3056   if (dos_lstat(fname,&sbuf) != 0) return(False);
3057   if (!check_file_sharing(conn,fname,True)) return(False);
3058
3059   return(True);
3060 }
3061
3062 /****************************************************************************
3063  The guts of the rename command, split out so it may be called by the NT SMB
3064  code. 
3065 ****************************************************************************/
3066 int rename_internals(connection_struct *conn, 
3067                      char *inbuf, char *outbuf, char *name, 
3068                      char *newname, BOOL replace_if_exists)
3069 {
3070         pstring directory;
3071         pstring mask;
3072         pstring newname_last_component;
3073         char *p;
3074         BOOL has_wild;
3075         BOOL bad_path1 = False;
3076         BOOL bad_path2 = False;
3077         int count=0;
3078         int error = ERRnoaccess;
3079         BOOL exists=False;
3080
3081         *directory = *mask = 0;
3082
3083         unix_convert(name,conn,0,&bad_path1,NULL);
3084         unix_convert(newname,conn,newname_last_component,&bad_path2,NULL);
3085
3086         /*
3087          * Split the old name into directory and last component
3088          * strings. Note that unix_convert may have stripped off a 
3089          * leading ./ from both name and newname if the rename is 
3090          * at the root of the share. We need to make sure either both
3091          * name and newname contain a / character or neither of them do
3092          * as this is checked in resolve_wildcards().
3093          */
3094         
3095         p = strrchr(name,'/');
3096         if (!p) {
3097                 pstrcpy(directory,".");
3098                 pstrcpy(mask,name);
3099         } else {
3100                 *p = 0;
3101                 pstrcpy(directory,name);
3102                 pstrcpy(mask,p+1);
3103                 *p = '/'; /* Replace needed for exceptional test below. */
3104         }
3105
3106         if (is_mangled(mask))
3107                 check_mangled_cache( mask );
3108
3109         has_wild = strchr(mask,'*') || strchr(mask,'?');
3110
3111         if (!has_wild) {
3112                 /*
3113                  * No wildcards - just process the one file.
3114                  */
3115                 BOOL is_short_name = is_8_3(name, True);
3116
3117                 /* Add a terminating '/' to the directory name. */
3118                 pstrcat(directory,"/");
3119                 pstrcat(directory,mask);
3120                 
3121                 /* Ensure newname contains a '/' also */
3122                 if(strrchr(newname,'/') == 0) {
3123                         pstring tmpstr;
3124                         
3125                         pstrcpy(tmpstr, "./");
3126                         pstrcat(tmpstr, newname);
3127                         pstrcpy(newname, tmpstr);
3128                 }
3129                 
3130                 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", 
3131                          case_sensitive, case_preserve, short_case_preserve, directory, 
3132                          newname, newname_last_component, is_short_name));
3133
3134                 /*
3135                  * Check for special case with case preserving and not
3136                  * case sensitive, if directory and newname are identical,
3137                  * and the old last component differs from the original
3138                  * last component only by case, then we should allow
3139                  * the rename (user is trying to change the case of the
3140                  * filename).
3141                  */
3142                 if((case_sensitive == False) && 
3143                    (((case_preserve == True) && 
3144                      (is_short_name == False)) || 
3145                     ((short_case_preserve == True) && 
3146                      (is_short_name == True))) &&
3147                    strcsequal(directory, newname)) {
3148                         pstring newname_modified_last_component;
3149
3150                         /*
3151                          * Get the last component of the modified name.
3152                          * Note that we guarantee that newname contains a '/'
3153                          * character above.
3154                          */
3155                         p = strrchr(newname,'/');
3156                         pstrcpy(newname_modified_last_component,p+1);
3157                         
3158                         if(strcsequal(newname_modified_last_component, 
3159                                       newname_last_component) == False) {
3160                                 /*
3161                                  * Replace the modified last component with
3162                                  * the original.
3163                                  */
3164                                 pstrcpy(p+1, newname_last_component);
3165                         }
3166                 }
3167                 
3168                 if(replace_if_exists) {
3169                         /*
3170                          * NT SMB specific flag - rename can overwrite
3171                          * file with the same name so don't check for
3172                          * file_exist().
3173                          */
3174                         if(resolve_wildcards(directory,newname) &&
3175                            can_rename(directory,conn) &&
3176                            !dos_rename(directory,newname))
3177                                 count++;
3178                 } else {
3179                         if (resolve_wildcards(directory,newname) && 
3180                             can_rename(directory,conn) && 
3181                             !file_exist(newname,NULL) &&
3182                             !dos_rename(directory,newname))
3183                                 count++;
3184                 }
3185
3186                 DEBUG(3,("rename_internals: %s doing rename on %s -> %s\n",(count != 0) ? "succeeded" : "failed",
3187                          directory,newname));
3188                 
3189                 if (!count) exists = file_exist(directory,NULL);
3190                 if (!count && exists && file_exist(newname,NULL)) {
3191                         exists = True;
3192                         error = 183;
3193                 }
3194         } else {
3195                 /*
3196                  * Wildcards - process each file that matches.
3197                  */
3198                 void *dirptr = NULL;
3199                 char *dname;
3200                 pstring destname;
3201                 
3202                 if (check_name(directory,conn))
3203                         dirptr = OpenDir(conn, directory, True);
3204                 
3205                 if (dirptr) {
3206                         error = ERRbadfile;
3207                         
3208                         if (strequal(mask,"????????.???"))
3209                                 pstrcpy(mask,"*");
3210                         
3211                         while ((dname = ReadDirName(dirptr))) {
3212                                 pstring fname;
3213                                 pstrcpy(fname,dname);
3214                                 
3215                                 if(!mask_match(fname, mask, case_sensitive, False))
3216                                         continue;
3217                                 
3218                                 error = ERRnoaccess;
3219                                 slprintf(fname,sizeof(fname)-1,"%s/%s",directory,dname);
3220                                 if (!can_rename(fname,conn)) {
3221                                         DEBUG(6,("rename %s refused\n", fname));
3222                                         continue;
3223                                 }
3224                                 pstrcpy(destname,newname);
3225                                 
3226                                 if (!resolve_wildcards(fname,destname)) {
3227                                         DEBUG(6,("resolve_wildcards %s %s failed\n", fname, destname));
3228                                         continue;
3229                                 }
3230                                 
3231                                 if (!replace_if_exists && file_exist(destname,NULL)) {
3232                                         DEBUG(6,("file_exist %s\n", destname));
3233                                         error = 183;
3234                                         continue;
3235                                 }
3236                                 
3237                                 if (!dos_rename(fname,destname))
3238                                         count++;
3239                                 DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname));
3240                         }
3241                         CloseDir(dirptr);
3242                 }
3243         }
3244         
3245         if (count == 0) {
3246                 if (exists)
3247                         return(ERROR(ERRDOS,error));
3248                 else {
3249                         if((errno == ENOENT) && (bad_path1 || bad_path2)) {
3250                                 unix_ERR_class = ERRDOS;
3251                                 unix_ERR_code = ERRbadpath;
3252                         }
3253                         return(UNIXERROR(ERRDOS,error));
3254                 }
3255         }
3256         
3257         return 0;
3258 }
3259
3260 /****************************************************************************
3261  Reply to a mv.
3262 ****************************************************************************/
3263
3264 int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3265 {
3266   int outsize = 0;
3267   pstring name;
3268   pstring newname;
3269
3270   pstrcpy(name,smb_buf(inbuf) + 1);
3271   pstrcpy(newname,smb_buf(inbuf) + 3 + strlen(name));
3272    
3273   DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
3274
3275   outsize = rename_internals(conn, inbuf, outbuf, name, newname, False);
3276   if(outsize == 0) 
3277     outsize = set_message(outbuf,0,0,True);
3278   
3279   return(outsize);
3280 }
3281
3282 /*******************************************************************
3283   copy a file as part of a reply_copy
3284   ******************************************************************/
3285 static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
3286                       int count,BOOL target_is_directory)
3287 {
3288   int Access,action;
3289   SMB_STRUCT_STAT st;
3290   int ret=0;
3291   files_struct *fsp1,*fsp2;
3292   pstring dest;
3293   
3294   pstrcpy(dest,dest1);
3295   if (target_is_directory) {
3296     char *p = strrchr(src,'/');
3297     if (p) 
3298       p++;
3299     else
3300       p = src;
3301     pstrcat(dest,"/");
3302     pstrcat(dest,p);
3303   }
3304
3305   if (!file_exist(src,&st)) return(False);
3306
3307   fsp1 = file_new();
3308   if (!fsp1) return(False);
3309   open_file_shared(fsp1,conn,src,(DENY_NONE<<4),
3310                    1,0,0,&Access,&action);
3311
3312   if (!fsp1->open) {
3313           file_free(fsp1);
3314           return(False);
3315   }
3316
3317   if (!target_is_directory && count)
3318     ofun = 1;
3319
3320   fsp2 = file_new();
3321   if (!fsp2) {
3322           close_file(fsp1,False);
3323           return(False);
3324   }
3325   open_file_shared(fsp2,conn,dest,(DENY_NONE<<4)|1,
3326                    ofun,st.st_mode,0,&Access,&action);
3327
3328   if (!fsp2->open) {
3329     close_file(fsp1,False);
3330     file_free(fsp2);
3331     return(False);
3332   }
3333
3334   if ((ofun&3) == 1) {
3335     sys_lseek(fsp2->fd_ptr->fd,0,SEEK_END);
3336   }
3337   
3338   if (st.st_size)
3339     ret = transfer_file(fsp1->fd_ptr->fd,
3340                         fsp2->fd_ptr->fd,st.st_size,NULL,0,0);
3341
3342   close_file(fsp1,False);
3343   close_file(fsp2,False);
3344
3345   return(ret == st.st_size);
3346 }
3347
3348
3349
3350 /****************************************************************************
3351   reply to a file copy.
3352   ****************************************************************************/
3353 int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3354 {
3355   int outsize = 0;
3356   pstring name;
3357   pstring directory;
3358   pstring mask,newname;
3359   char *p;
3360   int count=0;
3361   int error = ERRnoaccess;
3362   BOOL has_wild;
3363   BOOL exists=False;
3364   int tid2 = SVAL(inbuf,smb_vwv0);
3365   int ofun = SVAL(inbuf,smb_vwv1);
3366   int flags = SVAL(inbuf,smb_vwv2);
3367   BOOL target_is_directory=False;
3368   BOOL bad_path1 = False;
3369   BOOL bad_path2 = False;
3370
3371   *directory = *mask = 0;
3372
3373   pstrcpy(name,smb_buf(inbuf));
3374   pstrcpy(newname,smb_buf(inbuf) + 1 + strlen(name));
3375    
3376   DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
3377    
3378   if (tid2 != conn->cnum) {
3379     /* can't currently handle inter share copies XXXX */
3380     DEBUG(3,("Rejecting inter-share copy\n"));
3381     return(ERROR(ERRSRV,ERRinvdevice));
3382   }
3383
3384   unix_convert(name,conn,0,&bad_path1,NULL);
3385   unix_convert(newname,conn,0,&bad_path2,NULL);
3386
3387   target_is_directory = directory_exist(newname,NULL);
3388
3389   if ((flags&1) && target_is_directory) {
3390     return(ERROR(ERRDOS,ERRbadfile));
3391   }
3392
3393   if ((flags&2) && !target_is_directory) {
3394     return(ERROR(ERRDOS,ERRbadpath));
3395   }
3396
3397   if ((flags&(1<<5)) && directory_exist(name,NULL)) {
3398     /* wants a tree copy! XXXX */
3399     DEBUG(3,("Rejecting tree copy\n"));
3400     return(ERROR(ERRSRV,ERRerror));    
3401   }
3402
3403   p = strrchr(name,'/');
3404   if (!p) {
3405     pstrcpy(directory,"./");
3406     pstrcpy(mask,name);
3407   } else {
3408     *p = 0;
3409     pstrcpy(directory,name);
3410     pstrcpy(mask,p+1);
3411   }
3412
3413   if (is_mangled(mask))
3414     check_mangled_cache( mask );
3415
3416   has_wild = strchr(mask,'*') || strchr(mask,'?');
3417
3418   if (!has_wild) {
3419     pstrcat(directory,"/");
3420     pstrcat(directory,mask);
3421     if (resolve_wildcards(directory,newname) && 
3422         copy_file(directory,newname,conn,ofun,
3423                   count,target_is_directory)) count++;
3424     if (!count) exists = file_exist(directory,NULL);
3425   } else {
3426     void *dirptr = NULL;
3427     char *dname;
3428     pstring destname;
3429
3430     if (check_name(directory,conn))
3431       dirptr = OpenDir(conn, directory, True);
3432
3433     if (dirptr)
3434       {
3435         error = ERRbadfile;
3436
3437         if (strequal(mask,"????????.???"))
3438           pstrcpy(mask,"*");
3439
3440         while ((dname = ReadDirName(dirptr)))
3441           {
3442             pstring fname;
3443             pstrcpy(fname,dname);
3444             
3445             if(!mask_match(fname, mask, case_sensitive, False)) continue;
3446
3447             error = ERRnoaccess;
3448             slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
3449             pstrcpy(destname,newname);
3450             if (resolve_wildcards(fname,destname) && 
3451                 copy_file(directory,newname,conn,ofun,
3452                           count,target_is_directory)) count++;
3453             DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
3454           }
3455         CloseDir(dirptr);
3456       }
3457   }
3458   
3459   if (count == 0) {
3460     if (exists)
3461       return(ERROR(ERRDOS,error));
3462     else
3463     {
3464       if((errno == ENOENT) && (bad_path1 || bad_path2))
3465       {
3466         unix_ERR_class = ERRDOS;
3467         unix_ERR_code = ERRbadpath;
3468       }
3469       return(UNIXERROR(ERRDOS,error));
3470     }
3471   }
3472   
3473   outsize = set_message(outbuf,1,0,True);
3474   SSVAL(outbuf,smb_vwv0,count);
3475
3476   return(outsize);
3477 }
3478
3479
3480
3481 /****************************************************************************
3482   reply to a setdir
3483 ****************************************************************************/
3484 int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3485 {
3486   int snum;
3487   int outsize = 0;
3488   BOOL ok = False;
3489   pstring newdir;
3490   
3491   snum = SNUM(conn);
3492   if (!CAN_SETDIR(snum))
3493     return(ERROR(ERRDOS,ERRnoaccess));
3494   
3495   pstrcpy(newdir,smb_buf(inbuf) + 1);
3496   strlower(newdir);
3497   
3498   if (strlen(newdir) == 0) {
3499           ok = True;
3500   } else {
3501           ok = directory_exist(newdir,NULL);
3502           if (ok) {
3503                   string_set(&conn->connectpath,newdir);
3504           }
3505   }
3506   
3507   if (!ok)
3508           return(ERROR(ERRDOS,ERRbadpath));
3509   
3510   outsize = set_message(outbuf,0,0,True);
3511   CVAL(outbuf,smb_reh) = CVAL(inbuf,smb_reh);
3512   
3513   DEBUG(3,("setdir %s\n", newdir));
3514
3515   return(outsize);
3516 }
3517
3518
3519 /****************************************************************************
3520   reply to a lockingX request
3521 ****************************************************************************/
3522 int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
3523 {
3524   files_struct *fsp = file_fsp(inbuf,smb_vwv2);
3525   unsigned char locktype = CVAL(inbuf,smb_vwv3);
3526 #if 0
3527   unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
3528 #endif
3529   uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
3530   uint16 num_locks = SVAL(inbuf,smb_vwv7);
3531   uint32 count, offset;
3532   int32 lock_timeout = IVAL(inbuf,smb_vwv4);
3533   int i;
3534   char *data;
3535   uint32 ecode=0, dummy2;
3536   int eclass=0, dummy1;
3537
3538   CHECK_FSP(fsp,conn);
3539   CHECK_ERROR(fsp);
3540
3541   data = smb_buf(inbuf);
3542
3543   /* Check if this is an oplock break on a file
3544      we have granted an oplock on.
3545    */
3546   if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE))
3547   {
3548     int token;
3549     SMB_DEV_T dev = fsp->fd_ptr->dev;
3550     SMB_INO_T inode = fsp->fd_ptr->inode;
3551
3552     DEBUG(5,("reply_lockingX: oplock break reply from client for fnum = %d\n",
3553               fsp->fnum));
3554     /*
3555      * Make sure we have granted an oplock on this file.
3556      */
3557     if(!fsp->granted_oplock)
3558     {
3559       DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \
3560 no oplock granted on this file.\n", fsp->fnum));
3561       return ERROR(ERRDOS,ERRlock);
3562     }
3563
3564     /* Remove the oplock flag from the sharemode. */
3565     lock_share_entry(fsp->conn, dev, inode, &token);
3566     if(remove_share_oplock(fsp, token)==False) {
3567             DEBUG(0,("reply_lockingX: failed to remove share oplock for fnum %d, \
3568 dev = %x, inode = %x\n", 
3569                      fsp->fnum, dev, inode));
3570             unlock_share_entry(fsp->conn, dev, inode, token);
3571     } else {
3572             unlock_share_entry(fsp->conn, dev, inode, token);
3573
3574             /* Clear the granted flag and return. */
3575             fsp->granted_oplock = False;
3576     }
3577
3578     /* if this is a pure oplock break request then don't send a reply */
3579     if (num_locks == 0 && num_ulocks == 0)
3580     {
3581       /* Sanity check - ensure a pure oplock break is not a
3582          chained request. */
3583       if(CVAL(inbuf,smb_vwv0) != 0xff)
3584         DEBUG(0,("reply_lockingX: Error : pure oplock break is a chained %d request !\n",
3585                  (unsigned int)CVAL(inbuf,smb_vwv0) ));
3586       return -1;
3587     }
3588   }
3589
3590   /* Data now points at the beginning of the list
3591      of smb_unlkrng structs */
3592   for(i = 0; i < (int)num_ulocks; i++) {
3593     count = IVAL(data,SMB_LKLEN_OFFSET(i));
3594     offset = IVAL(data,SMB_LKOFF_OFFSET(i));
3595     DEBUG(10,("reply_lockingX: unlock start=%d, len=%d for file %s\n",
3596           (int)offset, (int)count, fsp->fsp_name ));
3597     if(!do_unlock(fsp,conn,count,offset,&eclass, &ecode))
3598       return ERROR(eclass,ecode);
3599   }
3600
3601   /* Setup the timeout in seconds. */
3602   lock_timeout = ((lock_timeout == -1) ? -1 : lock_timeout/1000);
3603
3604   /* Now do any requested locks */
3605   data += 10*num_ulocks;
3606   /* Data now points at the beginning of the list
3607      of smb_lkrng structs */
3608   for(i = 0; i < (int)num_locks; i++) {
3609     count = IVAL(data,SMB_LKLEN_OFFSET(i)); 
3610     offset = IVAL(data,SMB_LKOFF_OFFSET(i)); 
3611     DEBUG(10,("reply_lockingX: lock start=%d, len=%d for file %s\n",
3612           (int)offset, (int)count, fsp->fsp_name ));
3613     if(!do_lock(fsp,conn,count,offset, ((locktype & 1) ? F_RDLCK : F_WRLCK),
3614                 &eclass, &ecode)) {
3615       if((ecode == ERRlock) && (lock_timeout != 0)) {
3616         /*
3617          * A blocking lock was requested. Package up
3618          * this smb into a queued request and push it
3619          * onto the blocking lock queue.
3620          */
3621         if(push_blocking_lock_request(inbuf, length, lock_timeout, i))
3622           return -1;
3623       }
3624       break;
3625     }
3626   }
3627
3628   /* If any of the above locks failed, then we must unlock
3629      all of the previous locks (X/Open spec). */
3630   if(i != num_locks && num_locks != 0) {
3631     for(; i >= 0; i--) {
3632       count = IVAL(data,SMB_LKLEN_OFFSET(i));  
3633       offset = IVAL(data,SMB_LKOFF_OFFSET(i)); 
3634       do_unlock(fsp,conn,count,offset,&dummy1,&dummy2);
3635     }
3636     return ERROR(eclass,ecode);
3637   }
3638
3639   set_message(outbuf,2,0,True);
3640   
3641   DEBUG( 3, ( "lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
3642         fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks ) );
3643
3644   return chain_reply(inbuf,outbuf,length,bufsize);
3645 }
3646
3647
3648 /****************************************************************************
3649   reply to a SMBreadbmpx (read block multiplex) request
3650 ****************************************************************************/
3651 int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
3652 {
3653   int nread = -1;
3654   int total_read;
3655   char *data;
3656   uint32 startpos;
3657   int outsize, mincount, maxcount;
3658   int max_per_packet;
3659   int tcount;
3660   int pad;
3661   files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3662
3663   /* this function doesn't seem to work - disable by default */
3664   if (!lp_readbmpx())
3665     return(ERROR(ERRSRV,ERRuseSTD));
3666
3667   outsize = set_message(outbuf,8,0,True);
3668
3669   CHECK_FSP(fsp,conn);
3670   CHECK_READ(fsp);
3671   CHECK_ERROR(fsp);
3672
3673   startpos = IVAL(inbuf,smb_vwv1);
3674   maxcount = SVAL(inbuf,smb_vwv3);
3675   mincount = SVAL(inbuf,smb_vwv4);
3676
3677   data = smb_buf(outbuf);
3678   pad = ((long)data)%4;
3679   if (pad) pad = 4 - pad;
3680   data += pad;
3681
3682   max_per_packet = bufsize-(outsize+pad);
3683   tcount = maxcount;
3684   total_read = 0;
3685
3686   if (is_locked(fsp,conn,maxcount,startpos, F_RDLCK))
3687     return(ERROR(ERRDOS,ERRlock));
3688         
3689   do
3690     {
3691       int N = MIN(max_per_packet,tcount-total_read);
3692   
3693       nread = read_file(fsp,data,startpos,N);
3694
3695       if (nread <= 0) nread = 0;
3696
3697       if (nread < N)
3698         tcount = total_read + nread;
3699
3700       set_message(outbuf,8,nread,False);
3701       SIVAL(outbuf,smb_vwv0,startpos);
3702       SSVAL(outbuf,smb_vwv2,tcount);
3703       SSVAL(outbuf,smb_vwv6,nread);
3704       SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
3705
3706       send_smb(Client,outbuf);
3707
3708       total_read += nread;
3709       startpos += nread;
3710     }
3711   while (total_read < tcount);
3712
3713   return(-1);
3714 }
3715
3716
3717 /****************************************************************************
3718   reply to a SMBwritebmpx (write block multiplex primary) request
3719 ****************************************************************************/
3720 int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3721 {
3722 &