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