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