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