8cccd9b56837eec62aa2ba4c390cf34da1af4820
[samba.git] / source3 / smbd / reply.c
1 /* 
2    Unix SMB/CIFS implementation.
3    Main SMB reply routines
4    Copyright (C) Andrew Tridgell 1992-1998
5    Copyright (C) Andrew Bartlett      2001
6    Copyright (C) Jeremy Allison 1992-2004.
7
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 2 of the License, or
11    (at your option) any later version.
12    
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17    
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 */
22 /*
23    This file handles most of the reply_ calls that the server
24    makes to handle specific protocols
25 */
26
27 #include "includes.h"
28
29 /* look in server.c for some explanation of these variables */
30 extern enum protocol_types Protocol;
31 extern int max_send;
32 extern int max_recv;
33 extern int global_oplock_break;
34 unsigned int smb_echo_count = 0;
35 extern uint32 global_client_caps;
36
37 extern struct current_user current_user;
38 extern BOOL global_encrypted_passwords_negotiated;
39
40 /****************************************************************************
41  Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
42  We're assuming here that '/' is not the second byte in any multibyte char
43  set (a safe assumption). '\\' *may* be the second byte in a multibyte char
44  set.
45 ****************************************************************************/
46
47 NTSTATUS check_path_syntax(pstring destname, const pstring srcname)
48 {
49         char *d = destname;
50         const char *s = srcname;
51         NTSTATUS ret = NT_STATUS_OK;
52         BOOL start_of_name_component = True;
53         unsigned int num_bad_components = 0;
54
55         while (*s) {
56                 if (IS_DIRECTORY_SEP(*s)) {
57                         /*
58                          * Safe to assume is not the second part of a mb char as this is handled below.
59                          */
60                         /* Eat multiple '/' or '\\' */
61                         while (IS_DIRECTORY_SEP(*s)) {
62                                 s++;
63                         }
64                         if ((d != destname) && (*s != '\0')) {
65                                 /* We only care about non-leading or trailing '/' or '\\' */
66                                 *d++ = '/';
67                         }
68
69                         start_of_name_component = True;
70                         continue;
71                 }
72
73                 if (start_of_name_component) {
74                         if ((s[0] == '.') && (s[1] == '.') && (IS_DIRECTORY_SEP(s[2]) || s[2] == '\0')) {
75                                 /* Uh oh - "/../" or "\\..\\"  or "/..\0" or "\\..\0" ! */
76
77                                 /*
78                                  * No mb char starts with '.' so we're safe checking the directory separator here.
79                                  */
80
81                                 /* If  we just added a '/' - delete it */
82                                 if ((d > destname) && (*(d-1) == '/')) {
83                                         *(d-1) = '\0';
84                                         d--;
85                                 }
86
87                                 /* Are we at the start ? Can't go back further if so. */
88                                 if (d <= destname) {
89                                         ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
90                                         break;
91                                 }
92                                 /* Go back one level... */
93                                 /* We know this is safe as '/' cannot be part of a mb sequence. */
94                                 /* NOTE - if this assumption is invalid we are not in good shape... */
95                                 /* Decrement d first as d points to the *next* char to write into. */
96                                 for (d--; d > destname; d--) {
97                                         if (*d == '/')
98                                                 break;
99                                 }
100                                 s += 2; /* Else go past the .. */
101                                 /* We're still at the start of a name component, just the previous one. */
102
103                                 if (num_bad_components) {
104                                         /* Hmmm. Should we only decrement the bad_components if
105                                            we're removing a bad component ? Need to check this. JRA. */
106                                         num_bad_components--;
107                                 }
108
109                                 continue;
110
111                         } else if ((s[0] == '.') && ((s[1] == '\0') || IS_DIRECTORY_SEP(s[1]))) {
112                                 /* Component of pathname can't be "." only. */
113                                 ret =  NT_STATUS_OBJECT_NAME_INVALID;
114                                 num_bad_components++;
115                                 *d++ = *s++;
116                                 continue;
117                         }
118                 }
119
120                 if (!(*s & 0x80)) {
121                         switch (*s) {
122                                 case '*':
123                                 case '?':
124                                 case '<':
125                                 case '>':
126                                 case '"':
127                                         return NT_STATUS_OBJECT_NAME_INVALID;
128                                 default:
129                                         *d++ = *s++;
130                                         break;
131                         }
132                 } else {
133                         switch(next_mb_char_size(s)) {
134                                 case 4:
135                                         *d++ = *s++;
136                                 case 3:
137                                         *d++ = *s++;
138                                 case 2:
139                                         *d++ = *s++;
140                                 case 1:
141                                         *d++ = *s++;
142                                         break;
143                                 default:
144                                         DEBUG(0,("check_path_syntax: character length assumptions invalid !\n"));
145                                         *d = '\0';
146                                         return NT_STATUS_INVALID_PARAMETER;
147                         }
148                 }
149                 if (start_of_name_component && num_bad_components) {
150                         num_bad_components++;
151                 }
152                 start_of_name_component = False;
153         }
154
155         if (NT_STATUS_EQUAL(ret, NT_STATUS_OBJECT_NAME_INVALID)) {
156                 if (num_bad_components > 1) {
157                         ret = NT_STATUS_OBJECT_PATH_NOT_FOUND;
158                 }
159         }
160
161         *d = '\0';
162         return ret;
163 }
164
165 /****************************************************************************
166  Ensure we check the path in *exactly* the same way as W2K for a findfirst/findnext
167  path or anything including wildcards.
168  We're assuming here that '/' is not the second byte in any multibyte char
169  set (a safe assumption). '\\' *may* be the second byte in a multibyte char
170  set.
171 ****************************************************************************/
172
173 NTSTATUS check_path_syntax_wcard(pstring destname, const pstring srcname)
174 {
175         char *d = destname;
176         const char *s = srcname;
177         NTSTATUS ret = NT_STATUS_OK;
178         BOOL start_of_name_component = True;
179         unsigned int num_bad_components = 0;
180
181         while (*s) {
182                 if (IS_DIRECTORY_SEP(*s)) {
183                         /*
184                          * Safe to assume is not the second part of a mb char as this is handled below.
185                          */
186                         /* Eat multiple '/' or '\\' */
187                         while (IS_DIRECTORY_SEP(*s)) {
188                                 s++;
189                         }
190                         if ((d != destname) && (*s != '\0')) {
191                                 /* We only care about non-leading or trailing '/' or '\\' */
192                                 *d++ = '/';
193                         }
194
195                         start_of_name_component = True;
196                         continue;
197                 }
198
199                 if (start_of_name_component) {
200                         if ((s[0] == '.') && (s[1] == '.') && (IS_DIRECTORY_SEP(s[2]) || s[2] == '\0')) {
201                                 /* Uh oh - "/../" or "\\..\\"  or "/..\0" or "\\..\0" ! */
202
203                                 /*
204                                  * No mb char starts with '.' so we're safe checking the directory separator here.
205                                  */
206
207                                 /* If  we just added a '/' - delete it */
208                                 if ((d > destname) && (*(d-1) == '/')) {
209                                         *(d-1) = '\0';
210                                         d--;
211                                 }
212
213                                 /* Are we at the start ? Can't go back further if so. */
214                                 if (d <= destname) {
215                                         ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
216                                         break;
217                                 }
218                                 /* Go back one level... */
219                                 /* We know this is safe as '/' cannot be part of a mb sequence. */
220                                 /* NOTE - if this assumption is invalid we are not in good shape... */
221                                 /* Decrement d first as d points to the *next* char to write into. */
222                                 for (d--; d > destname; d--) {
223                                         if (*d == '/')
224                                                 break;
225                                 }
226                                 s += 2; /* Else go past the .. */
227                                 /* We're still at the start of a name component, just the previous one. */
228
229                                 if (num_bad_components) {
230                                         /* Hmmm. Should we only decrement the bad_components if
231                                            we're removing a bad component ? Need to check this. JRA. */
232                                         num_bad_components--;
233                                 }
234
235                                 continue;
236
237                         } else if ((s[0] == '.') && ((s[1] == '\0') || IS_DIRECTORY_SEP(s[1]))) {
238                                 /* Component of pathname can't be "." only. */
239                                 ret =  NT_STATUS_OBJECT_NAME_INVALID;
240                                 num_bad_components++;
241                                 *d++ = *s++;
242                                 continue;
243                         }
244                 }
245
246                 if (!(*s & 0x80)) {
247                         *d++ = *s++;
248                 } else {
249                         switch(next_mb_char_size(s)) {
250                                 case 4:
251                                         *d++ = *s++;
252                                 case 3:
253                                         *d++ = *s++;
254                                 case 2:
255                                         *d++ = *s++;
256                                 case 1:
257                                         *d++ = *s++;
258                                         break;
259                                 default:
260                                         DEBUG(0,("check_path_syntax_wcard: character length assumptions invalid !\n"));
261                                         *d = '\0';
262                                         return NT_STATUS_INVALID_PARAMETER;
263                         }
264                 }
265                 if (start_of_name_component && num_bad_components) {
266                         num_bad_components++;
267                 }
268                 start_of_name_component = False;
269         }
270
271         if (NT_STATUS_EQUAL(ret, NT_STATUS_OBJECT_NAME_INVALID)) {
272                 /* For some strange reason being called from findfirst changes
273                    the num_components number to cause the error return to change. JRA. */
274                 if (num_bad_components > 2) {
275                         ret = NT_STATUS_OBJECT_PATH_NOT_FOUND;
276                 }
277         }
278
279         *d = '\0';
280         return ret;
281 }
282
283 /****************************************************************************
284  Pull a string and check the path - provide for error return.
285 ****************************************************************************/
286
287 size_t srvstr_get_path(char *inbuf, char *dest, const char *src, size_t dest_len, size_t src_len, int flags, NTSTATUS *err, BOOL allow_wcard_names)
288 {
289         pstring tmppath;
290         char *tmppath_ptr = tmppath;
291         size_t ret;
292 #ifdef DEVELOPER
293         SMB_ASSERT(dest_len == sizeof(pstring));
294 #endif
295
296         if (src_len == 0) {
297                 ret = srvstr_pull_buf( inbuf, tmppath_ptr, src, dest_len, flags);
298         } else {
299                 ret = srvstr_pull( inbuf, tmppath_ptr, src, dest_len, src_len, flags);
300         }
301         if (allow_wcard_names) {
302                 *err = check_path_syntax_wcard(dest, tmppath);
303         } else {
304                 *err = check_path_syntax(dest, tmppath);
305         }
306         return ret;
307 }
308
309 /****************************************************************************
310  Reply to a special message.
311 ****************************************************************************/
312
313 int reply_special(char *inbuf,char *outbuf)
314 {
315         int outsize = 4;
316         int msg_type = CVAL(inbuf,0);
317         int msg_flags = CVAL(inbuf,1);
318         fstring name1,name2;
319         char name_type = 0;
320         
321         static BOOL already_got_session = False;
322
323         *name1 = *name2 = 0;
324         
325         memset(outbuf,'\0',smb_size);
326
327         smb_setlen(outbuf,0);
328         
329         switch (msg_type) {
330         case 0x81: /* session request */
331                 
332                 if (already_got_session) {
333                         exit_server("multiple session request not permitted");
334                 }
335                 
336                 SCVAL(outbuf,0,0x82);
337                 SCVAL(outbuf,3,0);
338                 if (name_len(inbuf+4) > 50 || 
339                     name_len(inbuf+4 + name_len(inbuf + 4)) > 50) {
340                         DEBUG(0,("Invalid name length in session request\n"));
341                         return(0);
342                 }
343                 name_extract(inbuf,4,name1);
344                 name_type = name_extract(inbuf,4 + name_len(inbuf + 4),name2);
345                 DEBUG(2,("netbios connect: name1=%s name2=%s\n",
346                          name1,name2));      
347
348                 set_local_machine_name(name1, True);
349                 set_remote_machine_name(name2, True);
350
351                 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
352                          get_local_machine_name(), get_remote_machine_name(),
353                          name_type));
354
355                 if (name_type == 'R') {
356                         /* We are being asked for a pathworks session --- 
357                            no thanks! */
358                         SCVAL(outbuf, 0,0x83);
359                         break;
360                 }
361
362                 /* only add the client's machine name to the list
363                    of possibly valid usernames if we are operating
364                    in share mode security */
365                 if (lp_security() == SEC_SHARE) {
366                         add_session_user(get_remote_machine_name());
367                 }
368
369                 reload_services(True);
370                 reopen_logs();
371
372                 already_got_session = True;
373                 break;
374                 
375         case 0x89: /* session keepalive request 
376                       (some old clients produce this?) */
377                 SCVAL(outbuf,0,SMBkeepalive);
378                 SCVAL(outbuf,3,0);
379                 break;
380                 
381         case 0x82: /* positive session response */
382         case 0x83: /* negative session response */
383         case 0x84: /* retarget session response */
384                 DEBUG(0,("Unexpected session response\n"));
385                 break;
386                 
387         case SMBkeepalive: /* session keepalive */
388         default:
389                 return(0);
390         }
391         
392         DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
393                     msg_type, msg_flags));
394         
395         return(outsize);
396 }
397
398 /****************************************************************************
399  Reply to a tcon.
400 ****************************************************************************/
401
402 int reply_tcon(connection_struct *conn,
403                char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
404 {
405         const char *service;
406         pstring service_buf;
407         pstring password;
408         pstring dev;
409         int outsize = 0;
410         uint16 vuid = SVAL(inbuf,smb_uid);
411         int pwlen=0;
412         NTSTATUS nt_status;
413         char *p;
414         DATA_BLOB password_blob;
415         
416         START_PROFILE(SMBtcon);
417
418         *service_buf = *password = *dev = 0;
419
420         p = smb_buf(inbuf)+1;
421         p += srvstr_pull_buf(inbuf, service_buf, p, sizeof(service_buf), STR_TERMINATE) + 1;
422         pwlen = srvstr_pull_buf(inbuf, password, p, sizeof(password), STR_TERMINATE) + 1;
423         p += pwlen;
424         p += srvstr_pull_buf(inbuf, dev, p, sizeof(dev), STR_TERMINATE) + 1;
425
426         p = strrchr_m(service_buf,'\\');
427         if (p) {
428                 service = p+1;
429         } else {
430                 service = service_buf;
431         }
432
433         password_blob = data_blob(password, pwlen+1);
434
435         conn = make_connection(service,password_blob,dev,vuid,&nt_status);
436
437         data_blob_clear_free(&password_blob);
438   
439         if (!conn) {
440                 END_PROFILE(SMBtcon);
441                 return ERROR_NT(nt_status);
442         }
443   
444         outsize = set_message(outbuf,2,0,True);
445         SSVAL(outbuf,smb_vwv0,max_recv);
446         SSVAL(outbuf,smb_vwv1,conn->cnum);
447         SSVAL(outbuf,smb_tid,conn->cnum);
448   
449         DEBUG(3,("tcon service=%s cnum=%d\n", 
450                  service, conn->cnum));
451   
452         END_PROFILE(SMBtcon);
453         return(outsize);
454 }
455
456 /****************************************************************************
457  Reply to a tcon and X.
458 ****************************************************************************/
459
460 int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
461 {
462         fstring service;
463         DATA_BLOB password;
464
465         /* what the cleint thinks the device is */
466         fstring client_devicetype;
467         /* what the server tells the client the share represents */
468         const char *server_devicetype;
469         NTSTATUS nt_status;
470         uint16 vuid = SVAL(inbuf,smb_uid);
471         int passlen = SVAL(inbuf,smb_vwv3);
472         pstring path;
473         char *p, *q;
474         
475         START_PROFILE(SMBtconX);        
476
477         *service = *client_devicetype = 0;
478
479         /* we might have to close an old one */
480         if ((SVAL(inbuf,smb_vwv2) & 0x1) && conn) {
481                 close_cnum(conn,vuid);
482         }
483
484         if (passlen > MAX_PASS_LEN) {
485                 return ERROR_DOS(ERRDOS,ERRbuftoosmall);
486         }
487  
488         if (global_encrypted_passwords_negotiated) {
489                 password = data_blob(smb_buf(inbuf),passlen);
490         } else {
491                 password = data_blob(smb_buf(inbuf),passlen+1);
492                 /* Ensure correct termination */
493                 password.data[passlen]=0;    
494         }
495
496         p = smb_buf(inbuf) + passlen;
497         p += srvstr_pull_buf(inbuf, path, p, sizeof(path), STR_TERMINATE);
498
499         /*
500          * the service name can be either: \\server\share
501          * or share directly like on the DELL PowerVault 705
502          */
503         if (*path=='\\') {      
504                 q = strchr_m(path+2,'\\');
505                 if (!q) {
506                         END_PROFILE(SMBtconX);
507                         return(ERROR_DOS(ERRDOS,ERRnosuchshare));
508                 }
509                 fstrcpy(service,q+1);
510         }
511         else
512                 fstrcpy(service,path);
513                 
514         p += srvstr_pull(inbuf, client_devicetype, p, sizeof(client_devicetype), 6, STR_ASCII);
515
516         DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
517
518         conn = make_connection(service,password,client_devicetype,vuid,&nt_status);
519         
520         data_blob_clear_free(&password);
521
522         if (!conn) {
523                 END_PROFILE(SMBtconX);
524                 return ERROR_NT(nt_status);
525         }
526
527         if ( IS_IPC(conn) )
528                 server_devicetype = "IPC";
529         else if ( IS_PRINT(conn) )
530                 server_devicetype = "LPT1:";
531         else 
532                 server_devicetype = "A:";
533
534         if (Protocol < PROTOCOL_NT1) {
535                 set_message(outbuf,2,0,True);
536                 p = smb_buf(outbuf);
537                 p += srvstr_push(outbuf, p, server_devicetype, -1, 
538                                  STR_TERMINATE|STR_ASCII);
539                 set_message_end(outbuf,p);
540         } else {
541                 /* NT sets the fstype of IPC$ to the null string */
542                 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
543                 
544                 set_message(outbuf,3,0,True);
545
546                 p = smb_buf(outbuf);
547                 p += srvstr_push(outbuf, p, server_devicetype, -1, 
548                                  STR_TERMINATE|STR_ASCII);
549                 p += srvstr_push(outbuf, p, fstype, -1, 
550                                  STR_TERMINATE);
551                 
552                 set_message_end(outbuf,p);
553                 
554                 /* what does setting this bit do? It is set by NT4 and
555                    may affect the ability to autorun mounted cdroms */
556                 SSVAL(outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS|
557                                 (lp_csc_policy(SNUM(conn)) << 2));
558                 
559                 init_dfsroot(conn, inbuf, outbuf);
560         }
561
562   
563         DEBUG(3,("tconX service=%s \n",
564                  service));
565   
566         /* set the incoming and outgoing tid to the just created one */
567         SSVAL(inbuf,smb_tid,conn->cnum);
568         SSVAL(outbuf,smb_tid,conn->cnum);
569
570         END_PROFILE(SMBtconX);
571         return chain_reply(inbuf,outbuf,length,bufsize);
572 }
573
574 /****************************************************************************
575  Reply to an unknown type.
576 ****************************************************************************/
577
578 int reply_unknown(char *inbuf,char *outbuf)
579 {
580         int type;
581         type = CVAL(inbuf,smb_com);
582   
583         DEBUG(0,("unknown command type (%s): type=%d (0x%X)\n",
584                  smb_fn_name(type), type, type));
585   
586         return(ERROR_DOS(ERRSRV,ERRunknownsmb));
587 }
588
589 /****************************************************************************
590  Reply to an ioctl.
591 ****************************************************************************/
592
593 int reply_ioctl(connection_struct *conn,
594                 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
595 {
596         uint16 device     = SVAL(inbuf,smb_vwv1);
597         uint16 function   = SVAL(inbuf,smb_vwv2);
598         uint32 ioctl_code = (device << 16) + function;
599         int replysize, outsize;
600         char *p;
601         START_PROFILE(SMBioctl);
602
603         DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
604
605         switch (ioctl_code) {
606             case IOCTL_QUERY_JOB_INFO:
607                 replysize = 32;
608                 break;
609             default:
610                 END_PROFILE(SMBioctl);
611                 return(ERROR_DOS(ERRSRV,ERRnosupport));
612         }
613
614         outsize = set_message(outbuf,8,replysize+1,True);
615         SSVAL(outbuf,smb_vwv1,replysize); /* Total data bytes returned */
616         SSVAL(outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
617         SSVAL(outbuf,smb_vwv6,52);        /* Offset to data */
618         p = smb_buf(outbuf) + 1;          /* Allow for alignment */
619
620         switch (ioctl_code) {
621                 case IOCTL_QUERY_JOB_INFO:                  
622                 {
623                         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
624                         if (!fsp) {
625                                 END_PROFILE(SMBioctl);
626                                 return(UNIXERROR(ERRDOS,ERRbadfid));
627                         }
628                         SSVAL(p,0,fsp->rap_print_jobid);             /* Job number */
629                         srvstr_push(outbuf, p+2, global_myname(), 15, STR_TERMINATE|STR_ASCII);
630                         if (conn) {
631                                 srvstr_push(outbuf, p+18, lp_servicename(SNUM(conn)), 13, STR_TERMINATE|STR_ASCII);
632                         }
633                         break;
634                 }
635         }
636
637         END_PROFILE(SMBioctl);
638         return outsize;
639 }
640
641 /****************************************************************************
642  Reply to a chkpth.
643 ****************************************************************************/
644
645 int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
646 {
647         int outsize = 0;
648         pstring name;
649         BOOL ok = False;
650         BOOL bad_path = False;
651         SMB_STRUCT_STAT sbuf;
652         NTSTATUS status;
653
654         START_PROFILE(SMBchkpth);
655
656         srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status, False);
657         if (!NT_STATUS_IS_OK(status)) {
658                 END_PROFILE(SMBchkpth);
659                 return ERROR_NT(status);
660         }
661
662         RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
663
664         unix_convert(name,conn,0,&bad_path,&sbuf);
665         if (bad_path) {
666                 END_PROFILE(SMBchkpth);
667                 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
668         }
669
670         if (check_name(name,conn)) {
671                 if (VALID_STAT(sbuf) || SMB_VFS_STAT(conn,name,&sbuf) == 0)
672                         if (!(ok = S_ISDIR(sbuf.st_mode))) {
673                                 END_PROFILE(SMBchkpth);
674                                 return ERROR_BOTH(NT_STATUS_NOT_A_DIRECTORY,ERRDOS,ERRbadpath);
675                         }
676         }
677
678         if (!ok) {
679                 /* We special case this - as when a Windows machine
680                         is parsing a path is steps through the components
681                         one at a time - if a component fails it expects
682                         ERRbadpath, not ERRbadfile.
683                 */
684                 if(errno == ENOENT) {
685                         /*
686                          * Windows returns different error codes if
687                          * the parent directory is valid but not the
688                          * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
689                          * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
690                          * if the path is invalid. This is different from set_bad_path_error()
691                          * in the non-NT error case.
692                          */
693                         END_PROFILE(SMBchkpth);
694                         return ERROR_BOTH(NT_STATUS_OBJECT_NAME_NOT_FOUND,ERRDOS,ERRbadpath);
695                 }
696
697                 END_PROFILE(SMBchkpth);
698                 return(UNIXERROR(ERRDOS,ERRbadpath));
699         }
700
701         outsize = set_message(outbuf,0,0,True);
702         DEBUG(3,("chkpth %s mode=%d\n", name, (int)SVAL(inbuf,smb_vwv0)));
703
704         END_PROFILE(SMBchkpth);
705         return(outsize);
706 }
707
708 /****************************************************************************
709  Reply to a getatr.
710 ****************************************************************************/
711
712 int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
713 {
714         pstring fname;
715         int outsize = 0;
716         SMB_STRUCT_STAT sbuf;
717         BOOL ok = False;
718         int mode=0;
719         SMB_OFF_T size=0;
720         time_t mtime=0;
721         BOOL bad_path = False;
722         char *p;
723         NTSTATUS status;
724
725         START_PROFILE(SMBgetatr);
726
727         p = smb_buf(inbuf) + 1;
728         p += srvstr_get_path(inbuf, fname, p, sizeof(fname), 0, STR_TERMINATE, &status, False);
729         if (!NT_STATUS_IS_OK(status)) {
730                 END_PROFILE(SMBgetatr);
731                 return ERROR_NT(status);
732         }
733
734         RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
735   
736         /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
737                 under WfWg - weird! */
738         if (! (*fname)) {
739                 mode = aHIDDEN | aDIR;
740                 if (!CAN_WRITE(conn))
741                         mode |= aRONLY;
742                 size = 0;
743                 mtime = 0;
744                 ok = True;
745         } else {
746                 unix_convert(fname,conn,0,&bad_path,&sbuf);
747                 if (bad_path) {
748                         END_PROFILE(SMBgetatr);
749                         return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
750                 }
751                 if (check_name(fname,conn)) {
752                         if (VALID_STAT(sbuf) || SMB_VFS_STAT(conn,fname,&sbuf) == 0) {
753                                 mode = dos_mode(conn,fname,&sbuf);
754                                 size = sbuf.st_size;
755                                 mtime = sbuf.st_mtime;
756                                 if (mode & aDIR)
757                                         size = 0;
758                                 ok = True;
759                         } else {
760                                 DEBUG(3,("stat of %s failed (%s)\n",fname,strerror(errno)));
761                         }
762                 }
763         }
764   
765         if (!ok) {
766                 END_PROFILE(SMBgetatr);
767                 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadfile);
768         }
769  
770         outsize = set_message(outbuf,10,0,True);
771
772         SSVAL(outbuf,smb_vwv0,mode);
773         if(lp_dos_filetime_resolution(SNUM(conn)) )
774                 put_dos_date3(outbuf,smb_vwv1,mtime & ~1);
775         else
776                 put_dos_date3(outbuf,smb_vwv1,mtime);
777         SIVAL(outbuf,smb_vwv3,(uint32)size);
778
779         if (Protocol >= PROTOCOL_NT1)
780                 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
781   
782         DEBUG( 3, ( "getatr name=%s mode=%d size=%d\n", fname, mode, (uint32)size ) );
783   
784         END_PROFILE(SMBgetatr);
785         return(outsize);
786 }
787
788 /****************************************************************************
789  Reply to a setatr.
790 ****************************************************************************/
791
792 int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
793 {
794         pstring fname;
795         int outsize = 0;
796         BOOL ok=False;
797         int mode;
798         time_t mtime;
799         SMB_STRUCT_STAT sbuf;
800         BOOL bad_path = False;
801         char *p;
802         NTSTATUS status;
803
804         START_PROFILE(SMBsetatr);
805
806         p = smb_buf(inbuf) + 1;
807         p += srvstr_get_path(inbuf, fname, p, sizeof(fname), 0, STR_TERMINATE, &status, False);
808         if (!NT_STATUS_IS_OK(status)) {
809                 END_PROFILE(SMBsetatr);
810                 return ERROR_NT(status);
811         }
812
813         RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
814   
815         unix_convert(fname,conn,0,&bad_path,&sbuf);
816         if (bad_path) {
817                 END_PROFILE(SMBsetatr);
818                 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
819         }
820
821         mode = SVAL(inbuf,smb_vwv0);
822         mtime = make_unix_date3(inbuf+smb_vwv1);
823   
824         if (mode != FILE_ATTRIBUTE_NORMAL) {
825                 if (VALID_STAT_OF_DIR(sbuf))
826                         mode |= aDIR;
827                 else
828                         mode &= ~aDIR;
829
830                 if (check_name(fname,conn)) {
831                         ok = (file_set_dosmode(conn,fname,mode,&sbuf,False) == 0);
832                 }
833         } else {
834                 ok = True;
835         }
836
837         if (ok)
838                 ok = set_filetime(conn,fname,mtime);
839   
840         if (!ok) {
841                 END_PROFILE(SMBsetatr);
842                 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
843         }
844  
845         outsize = set_message(outbuf,0,0,True);
846   
847         DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
848   
849         END_PROFILE(SMBsetatr);
850         return(outsize);
851 }
852
853 /****************************************************************************
854  Reply to a dskattr.
855 ****************************************************************************/
856
857 int reply_dskattr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
858 {
859         int outsize = 0;
860         SMB_BIG_UINT dfree,dsize,bsize;
861         START_PROFILE(SMBdskattr);
862
863         if (SMB_VFS_DISK_FREE(conn,".",True,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
864                 END_PROFILE(SMBdskattr);
865                 return(UNIXERROR(ERRHRD,ERRgeneral));
866         }
867   
868         outsize = set_message(outbuf,5,0,True);
869         
870         if (Protocol <= PROTOCOL_LANMAN2) {
871                 double total_space, free_space;
872                 /* we need to scale this to a number that DOS6 can handle. We
873                    use floating point so we can handle large drives on systems
874                    that don't have 64 bit integers 
875
876                    we end up displaying a maximum of 2G to DOS systems
877                 */
878                 total_space = dsize * (double)bsize;
879                 free_space = dfree * (double)bsize;
880
881                 dsize = (total_space+63*512) / (64*512);
882                 dfree = (free_space+63*512) / (64*512);
883                 
884                 if (dsize > 0xFFFF) dsize = 0xFFFF;
885                 if (dfree > 0xFFFF) dfree = 0xFFFF;
886
887                 SSVAL(outbuf,smb_vwv0,dsize);
888                 SSVAL(outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
889                 SSVAL(outbuf,smb_vwv2,512); /* and this must be 512 */
890                 SSVAL(outbuf,smb_vwv3,dfree);
891         } else {
892                 SSVAL(outbuf,smb_vwv0,dsize);
893                 SSVAL(outbuf,smb_vwv1,bsize/512);
894                 SSVAL(outbuf,smb_vwv2,512);
895                 SSVAL(outbuf,smb_vwv3,dfree);
896         }
897
898         DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
899
900         END_PROFILE(SMBdskattr);
901         return(outsize);
902 }
903
904 /****************************************************************************
905  Reply to a search.
906  Can be called from SMBsearch, SMBffirst or SMBfunique.
907 ****************************************************************************/
908
909 int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
910 {
911         pstring mask;
912         pstring directory;
913         pstring fname;
914         SMB_OFF_T size;
915         int mode;
916         time_t date;
917         int dirtype;
918         int outsize = 0;
919         unsigned int numentries = 0;
920         unsigned int maxentries = 0;
921         BOOL finished = False;
922         char *p;
923         BOOL ok = False;
924         int status_len;
925         pstring path;
926         char status[21];
927         int dptr_num= -1;
928         BOOL check_descend = False;
929         BOOL expect_close = False;
930         BOOL can_open = True;
931         BOOL bad_path = False;
932         NTSTATUS nt_status;
933         BOOL allow_long_path_components = (SVAL(inbuf,smb_flg2) & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
934
935         START_PROFILE(SMBsearch);
936
937         *mask = *directory = *fname = 0;
938
939         /* If we were called as SMBffirst then we must expect close. */
940         if(CVAL(inbuf,smb_com) == SMBffirst)
941                 expect_close = True;
942   
943         outsize = set_message(outbuf,1,3,True);
944         maxentries = SVAL(inbuf,smb_vwv0); 
945         dirtype = SVAL(inbuf,smb_vwv1);
946         p = smb_buf(inbuf) + 1;
947         p += srvstr_get_path(inbuf, path, p, sizeof(path), 0, STR_TERMINATE, &nt_status, True);
948         if (!NT_STATUS_IS_OK(nt_status)) {
949                 END_PROFILE(SMBsearch);
950                 return ERROR_NT(nt_status);
951         }
952
953         RESOLVE_DFSPATH_WCARD(path, conn, inbuf, outbuf);
954   
955         p++;
956         status_len = SVAL(p, 0);
957         p += 2;
958   
959         /* dirtype &= ~aDIR; */
960
961         if (status_len == 0) {
962                 SMB_STRUCT_STAT sbuf;
963                 pstring dir2;
964
965                 pstrcpy(directory,path);
966                 pstrcpy(dir2,path);
967                 unix_convert(directory,conn,0,&bad_path,&sbuf);
968                 unix_format(dir2);
969
970                 if (!check_name(directory,conn))
971                         can_open = False;
972
973                 p = strrchr_m(dir2,'/');
974                 if (p == NULL) {
975                         pstrcpy(mask,dir2);
976                         *dir2 = 0;
977                 } else {
978                         *p = 0;
979                         pstrcpy(mask,p+1);
980                 }
981
982                 p = strrchr_m(directory,'/');
983                 if (!p) 
984                         *directory = 0;
985                 else
986                         *p = 0;
987
988                 if (strlen(directory) == 0)
989                         pstrcpy(directory,".");
990                 memset((char *)status,'\0',21);
991                 SCVAL(status,0,(dirtype & 0x1F));
992         } else {
993                 int status_dirtype;
994
995                 memcpy(status,p,21);
996                 status_dirtype = CVAL(status,0) & 0x1F;
997                 if (status_dirtype != (dirtype & 0x1F))
998                         dirtype = status_dirtype;
999
1000                 conn->dirptr = dptr_fetch(status+12,&dptr_num);      
1001                 if (!conn->dirptr)
1002                         goto SearchEmpty;
1003                 string_set(&conn->dirpath,dptr_path(dptr_num));
1004                 pstrcpy(mask, dptr_wcard(dptr_num));
1005         }
1006
1007         if (can_open) {
1008                 p = smb_buf(outbuf) + 3;
1009                 ok = True;
1010      
1011                 if (status_len == 0) {
1012                         dptr_num = dptr_create(conn,directory,True,expect_close,SVAL(inbuf,smb_pid));
1013                         if (dptr_num < 0) {
1014                                 if(dptr_num == -2) {
1015                                         END_PROFILE(SMBsearch);
1016                                         return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnofids);
1017                                 }
1018                                 END_PROFILE(SMBsearch);
1019                                 return ERROR_DOS(ERRDOS,ERRnofids);
1020                         }
1021                         if (!dptr_set_wcard_and_attributes(dptr_num, mask, dirtype)) {
1022                                 END_PROFILE(SMBsearch);
1023                                 return ERROR_DOS(ERRDOS,ERRnomem);
1024                         }
1025                 } else {
1026                         dirtype = dptr_attr(dptr_num);
1027                 }
1028
1029                 DEBUG(4,("dptr_num is %d\n",dptr_num));
1030
1031                 if (ok) {
1032                         if ((dirtype&0x1F) == aVOLID) {   
1033                                 memcpy(p,status,21);
1034                                 make_dir_struct(p,"???????????",volume_label(SNUM(conn)),
1035                                                 0,aVOLID,0,!allow_long_path_components);
1036                                 dptr_fill(p+12,dptr_num);
1037                                 if (dptr_zero(p+12) && (status_len==0))
1038                                         numentries = 1;
1039                                 else
1040                                         numentries = 0;
1041                                 p += DIR_STRUCT_SIZE;
1042                         } else {
1043                                 unsigned int i;
1044                                 maxentries = MIN(maxentries, ((BUFFER_SIZE - (p - outbuf))/DIR_STRUCT_SIZE));
1045
1046                                 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1047                                 conn->dirpath,lp_dontdescend(SNUM(conn))));
1048                                 if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True))
1049                                         check_descend = True;
1050
1051                                 for (i=numentries;(i<maxentries) && !finished;i++) {
1052                                         finished = !get_dir_entry(conn,mask,dirtype,fname,&size,&mode,&date,check_descend);
1053                                         if (!finished) {
1054                                                 memcpy(p,status,21);
1055                                                 make_dir_struct(p,mask,fname,size, mode,date,
1056                                                                 !allow_long_path_components);
1057                                                 dptr_fill(p+12,dptr_num);
1058                                                 numentries++;
1059                                                 p += DIR_STRUCT_SIZE;
1060                                         }
1061                                 }
1062                         }
1063                 } /* if (ok ) */
1064         }
1065
1066
1067   SearchEmpty:
1068
1069         /* If we were called as SMBffirst with smb_search_id == NULL
1070                 and no entries were found then return error and close dirptr 
1071                 (X/Open spec) */
1072
1073         if (numentries == 0 || !ok) {
1074                 dptr_close(&dptr_num);
1075         } else if(ok && expect_close && status_len == 0) {
1076                 /* Close the dptr - we know it's gone */
1077                 dptr_close(&dptr_num);
1078         }
1079
1080         /* If we were called as SMBfunique, then we can close the dirptr now ! */
1081         if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique) {
1082                 dptr_close(&dptr_num);
1083         }
1084
1085         if ((numentries == 0) && !ms_has_wild(mask)) {
1086                 return ERROR_BOTH(STATUS_NO_MORE_FILES,ERRDOS,ERRnofiles);
1087         }
1088
1089         SSVAL(outbuf,smb_vwv0,numentries);
1090         SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1091         SCVAL(smb_buf(outbuf),0,5);
1092         SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
1093
1094         /* The replies here are never long name. */
1095         SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
1096         if (!allow_long_path_components) {
1097                 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) & (~FLAGS2_LONG_PATH_COMPONENTS));
1098         }
1099
1100         /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1101         SSVAL(outbuf,smb_flg2, (SVAL(outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
1102           
1103         outsize += DIR_STRUCT_SIZE*numentries;
1104         smb_setlen(outbuf,outsize - 4);
1105   
1106         if ((! *directory) && dptr_path(dptr_num))
1107                 slprintf(directory, sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1108
1109         DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1110                 smb_fn_name(CVAL(inbuf,smb_com)), 
1111                 mask, directory, dirtype, numentries, maxentries ) );
1112
1113         END_PROFILE(SMBsearch);
1114         return(outsize);
1115 }
1116
1117 /****************************************************************************
1118  Reply to a fclose (stop directory search).
1119 ****************************************************************************/
1120
1121 int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1122 {
1123         int outsize = 0;
1124         int status_len;
1125         pstring path;
1126         char status[21];
1127         int dptr_num= -2;
1128         char *p;
1129         NTSTATUS err;
1130
1131         START_PROFILE(SMBfclose);
1132
1133         outsize = set_message(outbuf,1,0,True);
1134         p = smb_buf(inbuf) + 1;
1135         p += srvstr_get_path(inbuf, path, p, sizeof(path), 0, STR_TERMINATE, &err, True);
1136         if (!NT_STATUS_IS_OK(err)) {
1137                 END_PROFILE(SMBfclose);
1138                 return ERROR_NT(err);
1139         }
1140         p++;
1141         status_len = SVAL(p,0);
1142         p += 2;
1143
1144         if (status_len == 0) {
1145                 END_PROFILE(SMBfclose);
1146                 return ERROR_DOS(ERRSRV,ERRsrverror);
1147         }
1148
1149         memcpy(status,p,21);
1150
1151         if(dptr_fetch(status+12,&dptr_num)) {
1152                 /*  Close the dptr - we know it's gone */
1153                 dptr_close(&dptr_num);
1154         }
1155
1156         SSVAL(outbuf,smb_vwv0,0);
1157
1158         DEBUG(3,("search close\n"));
1159
1160         END_PROFILE(SMBfclose);
1161         return(outsize);
1162 }
1163
1164 /****************************************************************************
1165  Reply to an open.
1166 ****************************************************************************/
1167
1168 int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1169 {
1170         pstring fname;
1171         int outsize = 0;
1172         int fmode=0;
1173         int share_mode;
1174         SMB_OFF_T size = 0;
1175         time_t mtime=0;
1176         int rmode=0;
1177         SMB_STRUCT_STAT sbuf;
1178         BOOL bad_path = False;
1179         files_struct *fsp;
1180         int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1181         uint16 dos_attr = SVAL(inbuf,smb_vwv1);
1182         NTSTATUS status;
1183         START_PROFILE(SMBopen);
1184  
1185         share_mode = SVAL(inbuf,smb_vwv0);
1186
1187         srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), 0, STR_TERMINATE, &status, False);
1188         if (!NT_STATUS_IS_OK(status)) {
1189                 END_PROFILE(SMBopen);
1190                 return ERROR_NT(status);
1191         }
1192
1193         RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1194
1195         unix_convert(fname,conn,0,&bad_path,&sbuf);
1196         if (bad_path) {
1197                 END_PROFILE(SMBopen);
1198                 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1199         }
1200     
1201         fsp = open_file_shared(conn,fname,&sbuf,share_mode,(FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
1202                         (uint32)dos_attr, oplock_request,&rmode,NULL);
1203
1204         if (!fsp) {
1205                 END_PROFILE(SMBopen);
1206                 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1207                         /* We have re-scheduled this call. */
1208                         return -1;
1209                 }
1210                 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1211         }
1212
1213         size = sbuf.st_size;
1214         fmode = dos_mode(conn,fname,&sbuf);
1215         mtime = sbuf.st_mtime;
1216
1217         if (fmode & aDIR) {
1218                 DEBUG(3,("attempt to open a directory %s\n",fname));
1219                 close_file(fsp,False);
1220                 END_PROFILE(SMBopen);
1221                 return ERROR_DOS(ERRDOS,ERRnoaccess);
1222         }
1223   
1224         outsize = set_message(outbuf,7,0,True);
1225         SSVAL(outbuf,smb_vwv0,fsp->fnum);
1226         SSVAL(outbuf,smb_vwv1,fmode);
1227         if(lp_dos_filetime_resolution(SNUM(conn)) )
1228                 put_dos_date3(outbuf,smb_vwv2,mtime & ~1);
1229         else
1230                 put_dos_date3(outbuf,smb_vwv2,mtime);
1231         SIVAL(outbuf,smb_vwv4,(uint32)size);
1232         SSVAL(outbuf,smb_vwv6,rmode);
1233
1234         if (oplock_request && lp_fake_oplocks(SNUM(conn)))
1235                 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1236     
1237         if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1238                 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1239         END_PROFILE(SMBopen);
1240         return(outsize);
1241 }
1242
1243 /****************************************************************************
1244  Reply to an open and X.
1245 ****************************************************************************/
1246
1247 int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1248 {
1249         pstring fname;
1250         int smb_mode = SVAL(inbuf,smb_vwv3);
1251         int smb_attr = SVAL(inbuf,smb_vwv5);
1252         /* Breakout the oplock request bits so we can set the
1253                 reply bits separately. */
1254         BOOL ex_oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf);
1255         BOOL core_oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1256         BOOL oplock_request = ex_oplock_request | core_oplock_request;
1257 #if 0
1258         int open_flags = SVAL(inbuf,smb_vwv2);
1259         int smb_sattr = SVAL(inbuf,smb_vwv4); 
1260         uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
1261 #endif
1262         int smb_ofun = SVAL(inbuf,smb_vwv8);
1263         SMB_OFF_T size=0;
1264         int fmode=0,mtime=0,rmode=0;
1265         SMB_STRUCT_STAT sbuf;
1266         int smb_action = 0;
1267         BOOL bad_path = False;
1268         files_struct *fsp;
1269         NTSTATUS status;
1270         SMB_BIG_UINT allocation_size = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv9);
1271         ssize_t retval = -1;
1272
1273         START_PROFILE(SMBopenX);
1274
1275         /* If it's an IPC, pass off the pipe handler. */
1276         if (IS_IPC(conn)) {
1277                 if (lp_nt_pipe_support()) {
1278                         END_PROFILE(SMBopenX);
1279                         return reply_open_pipe_and_X(conn, inbuf,outbuf,length,bufsize);
1280                 } else {
1281                         END_PROFILE(SMBopenX);
1282                         return ERROR_DOS(ERRSRV,ERRaccess);
1283                 }
1284         }
1285
1286         /* XXXX we need to handle passed times, sattr and flags */
1287         srvstr_get_path(inbuf, fname, smb_buf(inbuf), sizeof(fname), 0, STR_TERMINATE, &status, False);
1288         if (!NT_STATUS_IS_OK(status)) {
1289                 END_PROFILE(SMBopenX);
1290                 return ERROR_NT(status);
1291         }
1292
1293         RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1294
1295         unix_convert(fname,conn,0,&bad_path,&sbuf);
1296         if (bad_path) {
1297                 END_PROFILE(SMBopenX);
1298                 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1299         }
1300
1301         /* Strange open mode mapping. */
1302         if (smb_ofun == 0) {
1303                 if (GET_OPEN_MODE(smb_mode) == DOS_OPEN_EXEC) {
1304                         smb_ofun = FILE_EXISTS_FAIL | FILE_CREATE_IF_NOT_EXIST;
1305                 } else {
1306                         END_PROFILE(SMBopenX);
1307                         return ERROR_FORCE_DOS(ERRDOS, ERRbadaccess);
1308                 }
1309         }
1310
1311         fsp = open_file_shared(conn,fname,&sbuf,smb_mode,smb_ofun,(uint32)smb_attr,
1312                         oplock_request, &rmode,&smb_action);
1313       
1314         if (!fsp) {
1315                 END_PROFILE(SMBopenX);
1316                 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1317                         /* We have re-scheduled this call. */
1318                         return -1;
1319                 }
1320                 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1321         }
1322
1323         size = sbuf.st_size;
1324
1325         /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
1326            if the file is truncated or created. */
1327         if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
1328                 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
1329                 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
1330                         close_file(fsp,False);
1331                         END_PROFILE(SMBntcreateX);
1332                         return ERROR_NT(NT_STATUS_DISK_FULL);
1333                 }
1334                 retval = vfs_set_filelen(fsp, (SMB_OFF_T)allocation_size);
1335                 if (retval < 0) {
1336                         close_file(fsp,False);
1337                         END_PROFILE(SMBwrite);
1338                         return ERROR_NT(NT_STATUS_DISK_FULL);
1339                 }
1340                 size = get_allocation_size(conn,fsp,&sbuf);
1341         }
1342
1343         fmode = dos_mode(conn,fname,&sbuf);
1344         mtime = sbuf.st_mtime;
1345         if (fmode & aDIR) {
1346                 close_file(fsp,False);
1347                 END_PROFILE(SMBopenX);
1348                 return ERROR_DOS(ERRDOS,ERRnoaccess);
1349         }
1350
1351         /* If the caller set the extended oplock request bit
1352                 and we granted one (by whatever means) - set the
1353                 correct bit for extended oplock reply.
1354         */
1355
1356         if (ex_oplock_request && lp_fake_oplocks(SNUM(conn)))
1357                 smb_action |= EXTENDED_OPLOCK_GRANTED;
1358
1359         if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1360                 smb_action |= EXTENDED_OPLOCK_GRANTED;
1361
1362         /* If the caller set the core oplock request bit
1363                 and we granted one (by whatever means) - set the
1364                 correct bit for core oplock reply.
1365         */
1366
1367         if (core_oplock_request && lp_fake_oplocks(SNUM(conn)))
1368                 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1369
1370         if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1371                 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1372
1373         set_message(outbuf,15,0,True);
1374         SSVAL(outbuf,smb_vwv2,fsp->fnum);
1375         SSVAL(outbuf,smb_vwv3,fmode);
1376         if(lp_dos_filetime_resolution(SNUM(conn)) )
1377                 put_dos_date3(outbuf,smb_vwv4,mtime & ~1);
1378         else
1379                 put_dos_date3(outbuf,smb_vwv4,mtime);
1380         SIVAL(outbuf,smb_vwv6,(uint32)size);
1381         SSVAL(outbuf,smb_vwv8,rmode);
1382         SSVAL(outbuf,smb_vwv11,smb_action);
1383
1384         END_PROFILE(SMBopenX);
1385         return chain_reply(inbuf,outbuf,length,bufsize);
1386 }
1387
1388 /****************************************************************************
1389  Reply to a SMBulogoffX.
1390 ****************************************************************************/
1391
1392 int reply_ulogoffX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1393 {
1394         uint16 vuid = SVAL(inbuf,smb_uid);
1395         user_struct *vuser = get_valid_user_struct(vuid);
1396         START_PROFILE(SMBulogoffX);
1397
1398         if(vuser == 0)
1399                 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid));
1400
1401         /* in user level security we are supposed to close any files
1402                 open by this user */
1403         if ((vuser != 0) && (lp_security() != SEC_SHARE))
1404                 file_close_user(vuid);
1405
1406         invalidate_vuid(vuid);
1407
1408         set_message(outbuf,2,0,True);
1409
1410         DEBUG( 3, ( "ulogoffX vuid=%d\n", vuid ) );
1411
1412         END_PROFILE(SMBulogoffX);
1413         return chain_reply(inbuf,outbuf,length,bufsize);
1414 }
1415
1416 /****************************************************************************
1417  Reply to a mknew or a create.
1418 ****************************************************************************/
1419
1420 int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1421 {
1422         pstring fname;
1423         int com;
1424         int outsize = 0;
1425         int createmode;
1426         int ofun = 0;
1427         BOOL bad_path = False;
1428         files_struct *fsp;
1429         int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1430         SMB_STRUCT_STAT sbuf;
1431         NTSTATUS status;
1432         START_PROFILE(SMBcreate);
1433  
1434         com = SVAL(inbuf,smb_com);
1435
1436         createmode = SVAL(inbuf,smb_vwv0);
1437         srvstr_get_path(inbuf, fname, smb_buf(inbuf) + 1, sizeof(fname), 0, STR_TERMINATE, &status, False);
1438         if (!NT_STATUS_IS_OK(status)) {
1439                 END_PROFILE(SMBcreate);
1440                 return ERROR_NT(status);
1441         }
1442
1443         RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1444
1445         unix_convert(fname,conn,0,&bad_path,&sbuf);
1446         if (bad_path) {
1447                 END_PROFILE(SMBcreate);
1448                 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1449         }
1450
1451         if (createmode & aVOLID)
1452                 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
1453   
1454         if(com == SMBmknew) {
1455                 /* We should fail if file exists. */
1456                 ofun = FILE_CREATE_IF_NOT_EXIST;
1457         } else {
1458                 /* SMBcreate - Create if file doesn't exist, truncate if it does. */
1459                 ofun = FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_TRUNCATE;
1460         }
1461
1462         /* Open file in dos compatibility share mode. */
1463         fsp = open_file_shared(conn,fname,&sbuf,SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB), 
1464                         ofun, (uint32)createmode, oplock_request, NULL, NULL);
1465   
1466         if (!fsp) {
1467                 END_PROFILE(SMBcreate);
1468                 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1469                         /* We have re-scheduled this call. */
1470                         return -1;
1471                 }
1472                 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1473         }
1474  
1475         outsize = set_message(outbuf,1,0,True);
1476         SSVAL(outbuf,smb_vwv0,fsp->fnum);
1477
1478         if (oplock_request && lp_fake_oplocks(SNUM(conn)))
1479                 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1480  
1481         if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1482                 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1483  
1484         DEBUG( 2, ( "new file %s\n", fname ) );
1485         DEBUG( 3, ( "mknew %s fd=%d dmode=%d\n", fname, fsp->fd, createmode ) );
1486
1487         END_PROFILE(SMBcreate);
1488         return(outsize);
1489 }
1490
1491 /****************************************************************************
1492  Reply to a create temporary file.
1493 ****************************************************************************/
1494
1495 int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1496 {
1497         pstring fname;
1498         int outsize = 0;
1499         int createattr;
1500         BOOL bad_path = False;
1501         files_struct *fsp;
1502         int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1503         int tmpfd;
1504         SMB_STRUCT_STAT sbuf;
1505         char *p, *s;
1506         NTSTATUS status;
1507         unsigned int namelen;
1508
1509         START_PROFILE(SMBctemp);
1510
1511         createattr = SVAL(inbuf,smb_vwv0);
1512         srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), 0, STR_TERMINATE, &status, False);
1513         if (!NT_STATUS_IS_OK(status)) {
1514                 END_PROFILE(SMBctemp);
1515                 return ERROR_NT(status);
1516         }
1517         if (*fname) {
1518                 pstrcat(fname,"/TMXXXXXX");
1519         } else {
1520                 pstrcat(fname,"TMXXXXXX");
1521         }
1522
1523         RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1524
1525         unix_convert(fname,conn,0,&bad_path,&sbuf);
1526         if (bad_path) {
1527                 END_PROFILE(SMBctemp);
1528                 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1529         }
1530   
1531         tmpfd = smb_mkstemp(fname);
1532         if (tmpfd == -1) {
1533                 END_PROFILE(SMBctemp);
1534                 return(UNIXERROR(ERRDOS,ERRnoaccess));
1535         }
1536
1537         SMB_VFS_STAT(conn,fname,&sbuf);
1538
1539         /* Open file in dos compatibility share mode. */
1540         /* We should fail if file does not exist. */
1541         fsp = open_file_shared(conn,fname,&sbuf,
1542                 SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1543                 FILE_EXISTS_OPEN|FILE_FAIL_IF_NOT_EXIST,
1544                 (uint32)createattr, oplock_request, NULL, NULL);
1545
1546         /* close fd from smb_mkstemp() */
1547         close(tmpfd);
1548
1549         if (!fsp) {
1550                 END_PROFILE(SMBctemp);
1551                 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1552                         /* We have re-scheduled this call. */
1553                         return -1;
1554                 }
1555                 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1556         }
1557
1558         outsize = set_message(outbuf,1,0,True);
1559         SSVAL(outbuf,smb_vwv0,fsp->fnum);
1560
1561         /* the returned filename is relative to the directory */
1562         s = strrchr_m(fname, '/');
1563         if (!s)
1564                 s = fname;
1565         else
1566                 s++;
1567
1568         p = smb_buf(outbuf);
1569 #if 0
1570         /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
1571            thing in the byte section. JRA */
1572         SSVALS(p, 0, -1); /* what is this? not in spec */
1573 #endif
1574         namelen = srvstr_push(outbuf, p, s, -1, STR_ASCII|STR_TERMINATE);
1575         p += namelen;
1576         outsize = set_message_end(outbuf, p);
1577
1578         if (oplock_request && lp_fake_oplocks(SNUM(conn)))
1579                 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1580   
1581         if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1582                 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1583
1584         DEBUG( 2, ( "created temp file %s\n", fname ) );
1585         DEBUG( 3, ( "ctemp %s fd=%d umode=%o\n",
1586                         fname, fsp->fd, sbuf.st_mode ) );
1587
1588         END_PROFILE(SMBctemp);
1589         return(outsize);
1590 }
1591
1592 /*******************************************************************
1593  Check if a user is allowed to rename a file.
1594 ********************************************************************/
1595
1596 static NTSTATUS can_rename(connection_struct *conn, char *fname, uint16 dirtype, SMB_STRUCT_STAT *pst)
1597 {
1598         int smb_action;
1599         int access_mode;
1600         files_struct *fsp;
1601         uint16 fmode;
1602
1603         if (!CAN_WRITE(conn))
1604                 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1605
1606         fmode = dos_mode(conn,fname,pst);
1607         if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
1608                 return NT_STATUS_NO_SUCH_FILE;
1609
1610         if (S_ISDIR(pst->st_mode))
1611                 return NT_STATUS_OK;
1612
1613         /* We need a better way to return NT status codes from open... */
1614         set_saved_error_triple(0, 0, NT_STATUS_OK);
1615
1616         fsp = open_file_shared1(conn, fname, pst, DELETE_ACCESS, SET_DENY_MODE(DENY_ALL),
1617                 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), FILE_ATTRIBUTE_NORMAL, 0, &access_mode, &smb_action);
1618
1619         if (!fsp) {
1620                 NTSTATUS ret;
1621                 if (get_saved_error_triple(NULL, NULL, &ret)) {
1622                         set_saved_error_triple(0, 0, NT_STATUS_OK);
1623                         return ret;
1624                 }
1625                 set_saved_error_triple(0, 0, NT_STATUS_OK);
1626                 return NT_STATUS_ACCESS_DENIED;
1627         }
1628         close_file(fsp,False);
1629         return NT_STATUS_OK;
1630 }
1631
1632 /*******************************************************************
1633  Check if a user is allowed to delete a file.
1634 ********************************************************************/
1635
1636 NTSTATUS can_delete(connection_struct *conn, char *fname, int dirtype, BOOL bad_path, BOOL check_is_at_open)
1637 {
1638         SMB_STRUCT_STAT sbuf;
1639         int fmode;
1640         int smb_action;
1641         int access_mode;
1642         files_struct *fsp;
1643
1644         DEBUG(10,("can_delete: %s, dirtype = %d\n",
1645                 fname, dirtype ));
1646
1647         if (!CAN_WRITE(conn))
1648                 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1649
1650         if (SMB_VFS_LSTAT(conn,fname,&sbuf) != 0) {
1651                 if(errno == ENOENT) {
1652                         if (bad_path)
1653                                 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
1654                         else
1655                                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1656                 }
1657                 return map_nt_error_from_unix(errno);
1658         }
1659
1660         fmode = dos_mode(conn,fname,&sbuf);
1661
1662         /* Can't delete a directory. */
1663         if (fmode & aDIR)
1664                 return NT_STATUS_FILE_IS_A_DIRECTORY;
1665 #if 0 /* JRATEST */
1666         else if (dirtype & aDIR) /* Asked for a directory and it isn't. */
1667                 return NT_STATUS_OBJECT_NAME_INVALID;
1668 #endif /* JRATEST */
1669
1670         if (!lp_delete_readonly(SNUM(conn))) {
1671                 if (fmode & aRONLY)
1672                         return NT_STATUS_CANNOT_DELETE;
1673         }
1674         if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
1675                 return NT_STATUS_NO_SUCH_FILE;
1676
1677         if (check_is_at_open) {
1678                 if (!can_delete_file_in_directory(conn, fname)) {
1679                         return NT_STATUS_ACCESS_DENIED;
1680                 }
1681         } else {
1682                 /* On open checks the open itself will check the share mode, so
1683                    don't do it here as we'll get it wrong. */
1684
1685                 /* We need a better way to return NT status codes from open... */
1686                 set_saved_error_triple(0, 0, NT_STATUS_OK);
1687
1688                 fsp = open_file_shared1(conn, fname, &sbuf, DELETE_ACCESS, SET_DENY_MODE(DENY_ALL),
1689                         (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), FILE_ATTRIBUTE_NORMAL, 0, &access_mode, &smb_action);
1690
1691                 if (!fsp) {
1692                         NTSTATUS ret;
1693                         if (get_saved_error_triple(NULL, NULL, &ret)) {
1694                                 set_saved_error_triple(0, 0, NT_STATUS_OK);
1695                                 return ret;
1696                         }
1697                         set_saved_error_triple(0, 0, NT_STATUS_OK);
1698                         return NT_STATUS_ACCESS_DENIED;
1699                 }
1700                 close_file(fsp,False);
1701         }
1702         return NT_STATUS_OK;
1703 }
1704
1705 /****************************************************************************
1706  The guts of the unlink command, split out so it may be called by the NT SMB
1707  code.
1708 ****************************************************************************/
1709
1710 NTSTATUS unlink_internals(connection_struct *conn, int dirtype, char *name)
1711 {
1712         pstring directory;
1713         pstring mask;
1714         char *p;
1715         int count=0;
1716         NTSTATUS error = NT_STATUS_OK;
1717         BOOL has_wild;
1718         BOOL bad_path = False;
1719         BOOL rc = True;
1720         SMB_STRUCT_STAT sbuf;
1721         
1722         *directory = *mask = 0;
1723         
1724         /* We must check for wildcards in the name given
1725          * directly by the client - before any unmangling.
1726          * This prevents an unmangling of a UNIX name containing
1727          * a DOS wildcard like '*' or '?' from unmangling into
1728          * a wildcard delete which was not intended.
1729          * FIX for #226. JRA.
1730          */
1731
1732         has_wild = ms_has_wild(name);
1733
1734         rc = unix_convert(name,conn,0,&bad_path,&sbuf);
1735         
1736         p = strrchr_m(name,'/');
1737         if (!p) {
1738                 pstrcpy(directory,".");
1739                 pstrcpy(mask,name);
1740         } else {
1741                 *p = 0;
1742                 pstrcpy(directory,name);
1743                 pstrcpy(mask,p+1);
1744         }
1745         
1746         /*
1747          * We should only check the mangled cache
1748          * here if unix_convert failed. This means
1749          * that the path in 'mask' doesn't exist
1750          * on the file system and so we need to look
1751          * for a possible mangle. This patch from
1752          * Tine Smukavec <valentin.smukavec@hermes.si>.
1753          */
1754         
1755         if (!rc && mangle_is_mangled(mask,SNUM(conn)))
1756                 mangle_check_cache( mask, sizeof(pstring)-1, SNUM(conn));
1757         
1758         if (!has_wild) {
1759                 pstrcat(directory,"/");
1760                 pstrcat(directory,mask);
1761                 error = can_delete(conn,directory,dirtype,bad_path,False);
1762                 if (!NT_STATUS_IS_OK(error))
1763                         return error;
1764
1765                 if (SMB_VFS_UNLINK(conn,directory) == 0) {
1766                         count++;
1767                 }
1768         } else {
1769                 struct smb_Dir *dir_hnd = NULL;
1770                 const char *dname;
1771                 
1772                 if (check_name(directory,conn))
1773                         dir_hnd = OpenDir(conn, directory);
1774                 
1775                 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
1776                    the pattern matches against the long name, otherwise the short name 
1777                    We don't implement this yet XXXX
1778                 */
1779                 
1780                 if (dir_hnd) {
1781                         long offset = 0;
1782                         error = NT_STATUS_NO_SUCH_FILE;
1783
1784                         if (strequal(mask,"????????.???"))
1785                                 pstrcpy(mask,"*");
1786
1787                         while ((dname = ReadDirName(dir_hnd, &offset))) {
1788                                 SMB_STRUCT_STAT st;
1789                                 pstring fname;
1790                                 BOOL sys_direntry = False;
1791                                 pstrcpy(fname,dname);
1792
1793                                 if (!is_visible_file(conn, directory, dname, &st, True)) {
1794                                         continue;
1795                                 }
1796
1797                                 /* Quick check for "." and ".." */
1798                                 if (fname[0] == '.') {
1799                                         if (!fname[1] || (fname[1] == '.' && !fname[2])) {
1800                                                 if ((dirtype & FILE_ATTRIBUTE_DIRECTORY) && (dirtype & FILE_ATTRIBUTE_SYSTEM)) {
1801                                                         sys_direntry = True;
1802                                                 } else {
1803                                                         continue;
1804                                                 }
1805                                         }
1806                                 }
1807
1808                                 if(!mask_match(fname, mask, conn->case_sensitive))
1809                                         continue;
1810                                 
1811                                 if (sys_direntry) {
1812                                         error = NT_STATUS_OBJECT_NAME_INVALID;
1813                                         DEBUG(3,("unlink_internals: system directory delete denied [%s] mask [%s]\n",
1814                                                 fname, mask));
1815                                         break;
1816                                 }
1817
1818                                 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
1819                                 error = can_delete(conn,fname,dirtype,bad_path,False);
1820                                 if (!NT_STATUS_IS_OK(error)) {
1821                                         continue;
1822                                 }
1823                                 if (SMB_VFS_UNLINK(conn,fname) == 0)
1824                                         count++;
1825                                 DEBUG(3,("unlink_internals: succesful unlink [%s]\n",fname));
1826                         }
1827                         CloseDir(dir_hnd);
1828                 }
1829         }
1830         
1831         if (count == 0 && NT_STATUS_IS_OK(error)) {
1832                 error = map_nt_error_from_unix(errno);
1833         }
1834
1835         return error;
1836 }
1837
1838 /****************************************************************************
1839  Reply to a unlink
1840 ****************************************************************************/
1841
1842 int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, 
1843                  int dum_buffsize)
1844 {
1845         int outsize = 0;
1846         pstring name;
1847         int dirtype;
1848         NTSTATUS status;
1849         START_PROFILE(SMBunlink);
1850         
1851         dirtype = SVAL(inbuf,smb_vwv0);
1852         
1853         srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status, True);
1854         if (!NT_STATUS_IS_OK(status)) {
1855                 END_PROFILE(SMBunlink);
1856                 return ERROR_NT(status);
1857         }
1858         
1859         RESOLVE_DFSPATH_WCARD(name, conn, inbuf, outbuf);
1860         
1861         DEBUG(3,("reply_unlink : %s\n",name));
1862         
1863         status = unlink_internals(conn, dirtype, name);
1864         if (!NT_STATUS_IS_OK(status)) {
1865                 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1866                         /* We have re-scheduled this call. */
1867                         return -1;
1868                 }
1869                 return ERROR_NT(status);
1870         }
1871
1872         /*
1873          * Win2k needs a changenotify request response before it will
1874          * update after a rename..
1875          */
1876         process_pending_change_notify_queue((time_t)0);
1877         
1878         outsize = set_message(outbuf,0,0,True);
1879   
1880         END_PROFILE(SMBunlink);
1881         return outsize;
1882 }
1883
1884 /****************************************************************************
1885  Fail for readbraw.
1886 ****************************************************************************/
1887
1888 static void fail_readraw(void)
1889 {
1890         pstring errstr;
1891         slprintf(errstr, sizeof(errstr)-1, "FAIL ! reply_readbraw: socket write fail (%s)",
1892                 strerror(errno) );
1893         exit_server(errstr);
1894 }
1895
1896 #if defined(WITH_SENDFILE)
1897 /****************************************************************************
1898  Fake (read/write) sendfile. Returns -1 on read or write fail.
1899 ****************************************************************************/
1900
1901 static ssize_t fake_sendfile(files_struct *fsp, SMB_OFF_T startpos, size_t nread, char *buf, int bufsize)
1902 {
1903         ssize_t ret=0;
1904
1905         /* Paranioa check... */
1906         if (nread > bufsize) {
1907                 fail_readraw();
1908         }
1909
1910         if (nread > 0) {
1911                 ret = read_file(fsp,buf,startpos,nread);
1912                 if (ret == -1) {
1913                         return -1;
1914                 }
1915         }
1916
1917         /* If we had a short read, fill with zeros. */
1918         if (ret < nread) {
1919                 memset(buf, '\0', nread - ret);
1920         }
1921
1922         if (write_data(smbd_server_fd(),buf,nread) != nread) {
1923                 return -1;
1924         }       
1925
1926         return (ssize_t)nread;
1927 }
1928 #endif
1929
1930 /****************************************************************************
1931  Use sendfile in readbraw.
1932 ****************************************************************************/
1933
1934 void send_file_readbraw(connection_struct *conn, files_struct *fsp, SMB_OFF_T startpos, size_t nread,
1935                 ssize_t mincount, char *outbuf, int out_buffsize)
1936 {
1937         ssize_t ret=0;
1938
1939 #if defined(WITH_SENDFILE)
1940         /*
1941          * We can only use sendfile on a non-chained packet 
1942          * but we can use on a non-oplocked file. tridge proved this
1943          * on a train in Germany :-). JRA.
1944          * reply_readbraw has already checked the length.
1945          */
1946
1947         if (chain_size ==0 && (nread > 0) && (lp_write_cache_size(SNUM(conn)) == 0) && lp_use_sendfile(SNUM(conn)) ) {
1948                 DATA_BLOB header;
1949
1950                 _smb_setlen(outbuf,nread);
1951                 header.data = outbuf;
1952                 header.length = 4;
1953                 header.free = NULL;
1954
1955                 if ( SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fd, &header, startpos, nread) == -1) {
1956                         /* Returning ENOSYS means no data at all was sent. Do this as a normal read. */
1957                         if (errno == ENOSYS) {
1958                                 goto normal_readbraw;
1959                         }
1960
1961                         /*
1962                          * Special hack for broken Linux with no working sendfile. If we
1963                          * return EINTR we sent the header but not the rest of the data.
1964                          * Fake this up by doing read/write calls.
1965                          */
1966                         if (errno == EINTR) {
1967                                 /* Ensure we don't do this again. */
1968                                 set_use_sendfile(SNUM(conn), False);
1969                                 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
1970
1971                                 if (fake_sendfile(fsp, startpos, nread, outbuf + 4, out_buffsize - 4) == -1) {
1972                                         DEBUG(0,("send_file_readbraw: fake_sendfile failed for file %s (%s).\n",
1973                                                 fsp->fsp_name, strerror(errno) ));
1974                                         exit_server("send_file_readbraw fake_sendfile failed");
1975                                 }
1976                                 return;
1977                         }
1978
1979                         DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n",
1980                                 fsp->fsp_name, strerror(errno) ));
1981                         exit_server("send_file_readbraw sendfile failed");
1982                 }
1983
1984         }
1985
1986   normal_readbraw:
1987
1988 #endif
1989
1990         if (nread > 0) {
1991                 ret = read_file(fsp,outbuf+4,startpos,nread);
1992 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
1993                 if (ret < mincount)
1994                         ret = 0;
1995 #else
1996                 if (ret < nread)
1997                         ret = 0;
1998 #endif
1999         }
2000
2001         _smb_setlen(outbuf,ret);
2002         if (write_data(smbd_server_fd(),outbuf,4+ret) != 4+ret)
2003                 fail_readraw();
2004 }
2005
2006 /****************************************************************************
2007  Reply to a readbraw (core+ protocol).
2008 ****************************************************************************/
2009
2010 int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_size, int out_buffsize)
2011 {
2012         ssize_t maxcount,mincount;
2013         size_t nread = 0;
2014         SMB_OFF_T startpos;
2015         char *header = outbuf;
2016         files_struct *fsp;
2017         START_PROFILE(SMBreadbraw);
2018
2019         if (srv_is_signing_active()) {
2020                 exit_server("reply_readbraw: SMB signing is active - raw reads/writes are disallowed.");
2021         }
2022
2023         /*
2024          * Special check if an oplock break has been issued
2025          * and the readraw request croses on the wire, we must
2026          * return a zero length response here.
2027          */
2028
2029         if(global_oplock_break) {
2030                 _smb_setlen(header,0);
2031                 if (write_data(smbd_server_fd(),header,4) != 4)
2032                         fail_readraw();
2033                 DEBUG(5,("readbraw - oplock break finished\n"));
2034                 END_PROFILE(SMBreadbraw);
2035                 return -1;
2036         }
2037
2038         fsp = file_fsp(inbuf,smb_vwv0);
2039
2040         if (!FNUM_OK(fsp,conn) || !fsp->can_read) {
2041                 /*
2042                  * fsp could be NULL here so use the value from the packet. JRA.
2043                  */
2044                 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",(int)SVAL(inbuf,smb_vwv0)));
2045                 _smb_setlen(header,0);
2046                 if (write_data(smbd_server_fd(),header,4) != 4)
2047                         fail_readraw();
2048                 END_PROFILE(SMBreadbraw);
2049                 return(-1);
2050         }
2051
2052         CHECK_FSP(fsp,conn);
2053
2054         flush_write_cache(fsp, READRAW_FLUSH);
2055
2056         startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
2057         if(CVAL(inbuf,smb_wct) == 10) {
2058                 /*
2059                  * This is a large offset (64 bit) read.
2060                  */
2061 #ifdef LARGE_SMB_OFF_T
2062
2063                 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv8)) << 32);
2064
2065 #else /* !LARGE_SMB_OFF_T */
2066
2067                 /*
2068                  * Ensure we haven't been sent a >32 bit offset.
2069                  */
2070
2071                 if(IVAL(inbuf,smb_vwv8) != 0) {
2072                         DEBUG(0,("readbraw - large offset (%x << 32) used and we don't support \
2073 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv8) ));
2074                         _smb_setlen(header,0);
2075                         if (write_data(smbd_server_fd(),header,4) != 4)
2076                                 fail_readraw();
2077                         END_PROFILE(SMBreadbraw);
2078                         return(-1);
2079                 }
2080
2081 #endif /* LARGE_SMB_OFF_T */
2082
2083                 if(startpos < 0) {
2084                         DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n", (double)startpos ));
2085                         _smb_setlen(header,0);
2086                         if (write_data(smbd_server_fd(),header,4) != 4)
2087                                 fail_readraw();
2088                         END_PROFILE(SMBreadbraw);
2089                         return(-1);
2090                 }      
2091         }
2092         maxcount = (SVAL(inbuf,smb_vwv3) & 0xFFFF);
2093         mincount = (SVAL(inbuf,smb_vwv4) & 0xFFFF);
2094
2095         /* ensure we don't overrun the packet size */
2096         maxcount = MIN(65535,maxcount);
2097
2098         if (!is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK)) {
2099                 SMB_OFF_T size = fsp->size;
2100                 SMB_OFF_T sizeneeded = startpos + maxcount;
2101   
2102                 if (size < sizeneeded) {
2103                         SMB_STRUCT_STAT st;
2104                         if (SMB_VFS_FSTAT(fsp,fsp->fd,&st) == 0)
2105                                 size = st.st_size;
2106                         if (!fsp->can_write) 
2107                                 fsp->size = size;
2108                 }
2109
2110                 if (startpos >= size)
2111                         nread = 0;
2112                 else
2113                         nread = MIN(maxcount,(size - startpos));          
2114         }
2115
2116 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2117         if (nread < mincount)
2118                 nread = 0;
2119 #endif
2120   
2121         DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%d min=%d nread=%d\n", fsp->fnum, (double)startpos,
2122                                 (int)maxcount, (int)mincount, (int)nread ) );
2123   
2124         send_file_readbraw(conn, fsp, startpos, nread, mincount, outbuf, out_buffsize);
2125
2126         DEBUG(5,("readbraw finished\n"));
2127         END_PROFILE(SMBreadbraw);
2128         return -1;
2129 }
2130
2131 #undef DBGC_CLASS
2132 #define DBGC_CLASS DBGC_LOCKING
2133
2134 /****************************************************************************
2135  Reply to a lockread (core+ protocol).
2136 ****************************************************************************/
2137
2138 int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length, int dum_buffsiz)
2139 {
2140         ssize_t nread = -1;
2141         char *data;
2142         int outsize = 0;
2143         SMB_OFF_T startpos;
2144         size_t numtoread;
2145         NTSTATUS status;
2146         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2147         BOOL my_lock_ctx = False;
2148         START_PROFILE(SMBlockread);
2149
2150         CHECK_FSP(fsp,conn);
2151         CHECK_READ(fsp);
2152
2153         release_level_2_oplocks_on_change(fsp);
2154
2155         numtoread = SVAL(inbuf,smb_vwv1);
2156         startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2157   
2158         outsize = set_message(outbuf,5,3,True);
2159         numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2160         data = smb_buf(outbuf) + 3;
2161         
2162         /*
2163          * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
2164          * protocol request that predates the read/write lock concept. 
2165          * Thus instead of asking for a read lock here we need to ask
2166          * for a write lock. JRA.
2167          * Note that the requested lock size is unaffected by max_recv.
2168          */
2169         
2170         status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid), 
2171                          (SMB_BIG_UINT)numtoread, (SMB_BIG_UINT)startpos, WRITE_LOCK, &my_lock_ctx);
2172
2173         if (NT_STATUS_V(status)) {
2174 #if 0
2175                 /*
2176                  * We used to make lockread a blocking lock. It turns out
2177                  * that this isn't on W2k. Found by the Samba 4 RAW-READ torture
2178                  * tester. JRA.
2179                  */
2180
2181                 if (lp_blocking_locks(SNUM(conn)) && !my_lock_ctx && ERROR_WAS_LOCK_DENIED(status)) {
2182                         /*
2183                          * A blocking lock was requested. Package up
2184                          * this smb into a queued request and push it
2185                          * onto the blocking lock queue.
2186                          */
2187                         if(push_blocking_lock_request(inbuf, length, -1, 0, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)startpos,
2188                                                                 (SMB_BIG_UINT)numtoread)) {
2189                                 END_PROFILE(SMBlockread);
2190                                 return -1;
2191                         }
2192                 }
2193 #endif
2194                 END_PROFILE(SMBlockread);
2195                 return ERROR_NT(status);
2196         }
2197
2198         /*
2199          * However the requested READ size IS affected by max_recv. Insanity.... JRA.
2200          */
2201
2202         if (numtoread > max_recv) {
2203                 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
2204 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
2205                         (unsigned int)numtoread, (unsigned int)max_recv ));
2206                 numtoread = MIN(numtoread,max_recv);
2207         }
2208         nread = read_file(fsp,data,startpos,numtoread);
2209
2210         if (nread < 0) {
2211                 END_PROFILE(SMBlockread);
2212                 return(UNIXERROR(ERRDOS,ERRnoaccess));
2213         }
2214         
2215         outsize += nread;
2216         SSVAL(outbuf,smb_vwv0,nread);
2217         SSVAL(outbuf,smb_vwv5,nread+3);
2218         SSVAL(smb_buf(outbuf),1,nread);
2219         
2220         DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
2221                  fsp->fnum, (int)numtoread, (int)nread));
2222
2223         END_PROFILE(SMBlockread);
2224         return(outsize);
2225 }
2226
2227 #undef DBGC_CLASS
2228 #define DBGC_CLASS DBGC_ALL
2229
2230 /****************************************************************************
2231  Reply to a read.
2232 ****************************************************************************/
2233
2234 int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2235 {
2236         size_t numtoread;
2237         ssize_t nread = 0;
2238         char *data;
2239         SMB_OFF_T startpos;
2240         int outsize = 0;
2241         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2242         START_PROFILE(SMBread);
2243
2244         CHECK_FSP(fsp,conn);
2245         CHECK_READ(fsp);
2246
2247         numtoread = SVAL(inbuf,smb_vwv1);
2248         startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2249
2250         outsize = set_message(outbuf,5,3,True);
2251         numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2252         /*
2253          * The requested read size cannot be greater than max_recv. JRA.
2254          */
2255         if (numtoread > max_recv) {
2256                 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
2257 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
2258                         (unsigned int)numtoread, (unsigned int)max_recv ));
2259                 numtoread = MIN(numtoread,max_recv);
2260         }
2261
2262         data = smb_buf(outbuf) + 3;
2263   
2264         if (is_locked(fsp,conn,(SMB_BIG_UINT)numtoread,(SMB_BIG_UINT)startpos, READ_LOCK)) {
2265                 END_PROFILE(SMBread);
2266                 return ERROR_DOS(ERRDOS,ERRlock);
2267         }
2268
2269         if (numtoread > 0)
2270                 nread = read_file(fsp,data,startpos,numtoread);
2271
2272         if (nread < 0) {
2273                 END_PROFILE(SMBread);
2274                 return(UNIXERROR(ERRDOS,ERRnoaccess));
2275         }
2276   
2277         outsize += nread;
2278         SSVAL(outbuf,smb_vwv0,nread);
2279         SSVAL(outbuf,smb_vwv5,nread+3);
2280         SCVAL(smb_buf(outbuf),0,1);
2281         SSVAL(smb_buf(outbuf),1,nread);
2282   
2283         DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
2284                 fsp->fnum, (int)numtoread, (int)nread ) );
2285
2286         END_PROFILE(SMBread);
2287         return(outsize);
2288 }
2289
2290 /****************************************************************************
2291  Reply to a read and X - possibly using sendfile.
2292 ****************************************************************************/
2293
2294 int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length, int len_outbuf,
2295                 files_struct *fsp, SMB_OFF_T startpos, size_t smb_maxcnt)
2296 {
2297         int outsize = 0;
2298         ssize_t nread = -1;
2299         char *data = smb_buf(outbuf);
2300
2301 #if defined(WITH_SENDFILE)
2302         /*
2303          * We can only use sendfile on a non-chained packet 
2304          * but we can use on a non-oplocked file. tridge proved this
2305          * on a train in Germany :-). JRA.
2306          */
2307
2308         if (chain_size ==0 && (CVAL(inbuf,smb_vwv0) == 0xFF) && lp_use_sendfile(SNUM(conn)) &&
2309                         (lp_write_cache_size(SNUM(conn)) == 0) ) {
2310                 SMB_STRUCT_STAT sbuf;
2311                 DATA_BLOB header;
2312
2313                 if(SMB_VFS_FSTAT(fsp,fsp->fd, &sbuf) == -1)
2314                         return(UNIXERROR(ERRDOS,ERRnoaccess));
2315
2316                 if (startpos > sbuf.st_size)
2317                         goto normal_read;
2318
2319                 if (smb_maxcnt > (sbuf.st_size - startpos))
2320                         smb_maxcnt = (sbuf.st_size - startpos);
2321
2322                 if (smb_maxcnt == 0)
2323                         goto normal_read;
2324
2325                 /* 
2326                  * Set up the packet header before send. We
2327                  * assume here the sendfile will work (get the
2328                  * correct amount of data).
2329                  */
2330
2331                 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
2332                 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
2333                 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2334                 SSVAL(outbuf,smb_vwv7,((smb_maxcnt >> 16) & 1));
2335                 SSVAL(smb_buf(outbuf),-2,smb_maxcnt);
2336                 SCVAL(outbuf,smb_vwv0,0xFF);
2337                 set_message(outbuf,12,smb_maxcnt,False);
2338                 header.data = outbuf;
2339                 header.length = data - outbuf;
2340                 header.free = NULL;
2341
2342                 if ((nread = SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fd, &header, startpos, smb_maxcnt)) == -1) {
2343                         /* Returning ENOSYS means no data at all was sent. Do this as a normal read. */
2344                         if (errno == ENOSYS) {
2345                                 goto normal_read;
2346                         }
2347
2348                         /*
2349                          * Special hack for broken Linux with no working sendfile. If we
2350                          * return EINTR we sent the header but not the rest of the data.
2351                          * Fake this up by doing read/write calls.
2352                          */
2353
2354                         if (errno == EINTR) {
2355                                 /* Ensure we don't do this again. */
2356                                 set_use_sendfile(SNUM(conn), False);
2357                                 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
2358
2359                                 if ((nread = fake_sendfile(fsp, startpos, smb_maxcnt, data,
2360                                                         len_outbuf - (data-outbuf))) == -1) {
2361                                         DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
2362                                                 fsp->fsp_name, strerror(errno) ));
2363                                         exit_server("send_file_readX: fake_sendfile failed");
2364                                 }
2365                                 DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
2366                                         fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2367                                 /* Returning -1 here means successful sendfile. */
2368                                 return -1;
2369                         }
2370
2371                         DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n",
2372                                 fsp->fsp_name, strerror(errno) ));
2373                         exit_server("send_file_readX sendfile failed");
2374                 }
2375
2376                 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
2377                         fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2378                 /* Returning -1 here means successful sendfile. */
2379                 return -1;
2380         }
2381
2382   normal_read:
2383
2384 #endif
2385
2386         nread = read_file(fsp,data,startpos,smb_maxcnt);
2387   
2388         if (nread < 0) {
2389                 END_PROFILE(SMBreadX);
2390                 return(UNIXERROR(ERRDOS,ERRnoaccess));
2391         }
2392
2393         outsize = set_message(outbuf,12,nread,False);
2394         SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
2395         SSVAL(outbuf,smb_vwv5,nread);
2396         SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2397         SSVAL(outbuf,smb_vwv7,((nread >> 16) & 1));
2398         SSVAL(smb_buf(outbuf),-2,nread);
2399   
2400         DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
2401                 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2402
2403         /* Returning the number of bytes we want to send back - including header. */
2404         return outsize;
2405 }
2406
2407 /****************************************************************************
2408  Reply to a read and X.
2409 ****************************************************************************/
2410
2411 int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2412 {
2413         files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2414         SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2415         ssize_t nread = -1;
2416         size_t smb_maxcnt = SVAL(inbuf,smb_vwv5);
2417 #if 0
2418         size_t smb_mincnt = SVAL(inbuf,smb_vwv6);
2419 #endif
2420
2421         START_PROFILE(SMBreadX);
2422
2423         /* If it's an IPC, pass off the pipe handler. */
2424         if (IS_IPC(conn)) {
2425                 END_PROFILE(SMBreadX);
2426                 return reply_pipe_read_and_X(inbuf,outbuf,length,bufsize);
2427         }
2428
2429         CHECK_FSP(fsp,conn);
2430         CHECK_READ(fsp);
2431
2432         set_message(outbuf,12,0,True);
2433
2434         if (global_client_caps & CAP_LARGE_READX) {
2435                 if (SVAL(inbuf,smb_vwv7) == 1) {
2436                         smb_maxcnt |= (1<<16);
2437                 }
2438                 if (smb_maxcnt > BUFFER_SIZE) {
2439                         DEBUG(0,("reply_read_and_X - read too large (%u) for reply buffer %u\n",
2440                                 (unsigned int)smb_maxcnt, (unsigned int)BUFFER_SIZE));
2441                         END_PROFILE(SMBreadX);
2442                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2443                 }
2444         }
2445
2446         if(CVAL(inbuf,smb_wct) == 12) {
2447 #ifdef LARGE_SMB_OFF_T
2448                 /*
2449                  * This is a large offset (64 bit) read.
2450                  */
2451                 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv10)) << 32);
2452
2453 #else /* !LARGE_SMB_OFF_T */
2454
2455                 /*
2456                  * Ensure we haven't been sent a >32 bit offset.
2457                  */
2458
2459                 if(IVAL(inbuf,smb_vwv10) != 0) {
2460                         DEBUG(0,("reply_read_and_X - large offset (%x << 32) used and we don't support \
2461 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv10) ));
2462                         END_PROFILE(SMBreadX);
2463                         return ERROR_DOS(ERRDOS,ERRbadaccess);
2464                 }
2465
2466 #endif /* LARGE_SMB_OFF_T */
2467
2468         }
2469
2470         if (is_locked(fsp,conn,(SMB_BIG_UINT)smb_maxcnt,(SMB_BIG_UINT)startpos, READ_LOCK)) {
2471                 END_PROFILE(SMBreadX);
2472                 return ERROR_DOS(ERRDOS,ERRlock);
2473         }
2474
2475         nread = send_file_readX(conn, inbuf, outbuf, length, bufsize, fsp, startpos, smb_maxcnt);
2476         if (nread != -1)
2477                 nread = chain_reply(inbuf,outbuf,length,bufsize);
2478
2479         END_PROFILE(SMBreadX);
2480         return nread;
2481 }
2482
2483 /****************************************************************************
2484  Reply to a writebraw (core+ or LANMAN1.0 protocol).
2485 ****************************************************************************/
2486
2487 int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2488 {
2489         ssize_t nwritten=0;
2490         ssize_t total_written=0;
2491         size_t numtowrite=0;
2492         size_t tcount;
2493         SMB_OFF_T startpos;
2494         char *data=NULL;
2495         BOOL write_through;
2496         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2497         int outsize = 0;
2498         START_PROFILE(SMBwritebraw);
2499
2500         if (srv_is_signing_active()) {
2501                 exit_server("reply_writebraw: SMB signing is active - raw reads/writes are disallowed.");
2502         }
2503
2504         CHECK_FSP(fsp,conn);
2505         CHECK_WRITE(fsp);
2506   
2507         tcount = IVAL(inbuf,smb_vwv1);
2508         startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2509         write_through = BITSETW(inbuf+smb_vwv7,0);
2510
2511         /* We have to deal with slightly different formats depending
2512                 on whether we are using the core+ or lanman1.0 protocol */
2513
2514         if(Protocol <= PROTOCOL_COREPLUS) {
2515                 numtowrite = SVAL(smb_buf(inbuf),-2);
2516                 data = smb_buf(inbuf);
2517         } else {
2518                 numtowrite = SVAL(inbuf,smb_vwv10);
2519                 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
2520         }
2521
2522         /* force the error type */
2523         SCVAL(inbuf,smb_com,SMBwritec);
2524         SCVAL(outbuf,smb_com,SMBwritec);
2525
2526         if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2527                 END_PROFILE(SMBwritebraw);
2528                 return(ERROR_DOS(ERRDOS,ERRlock));
2529         }
2530
2531         if (numtowrite>0)
2532                 nwritten = write_file(fsp,data,startpos,numtowrite);
2533   
2534         DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
2535                 fsp->fnum, (double)startpos, (int)numtowrite, (int)nwritten, (int)write_through));
2536
2537         if (nwritten < (ssize_t)numtowrite)  {
2538                 END_PROFILE(SMBwritebraw);
2539                 return(UNIXERROR(ERRHRD,ERRdiskfull));
2540         }
2541
2542         total_written = nwritten;
2543
2544         /* Return a message to the redirector to tell it to send more bytes */
2545         SCVAL(outbuf,smb_com,SMBwritebraw);
2546         SSVALS(outbuf,smb_vwv0,-1);
2547         outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
2548         if (!send_smb(smbd_server_fd(),outbuf))
2549                 exit_server("reply_writebraw: send_smb failed.");
2550   
2551         /* Now read the raw data into the buffer and write it */
2552         if (read_smb_length(smbd_server_fd(),inbuf,SMB_SECONDARY_WAIT) == -1) {
2553                 exit_server("secondary writebraw failed");
2554         }
2555   
2556         /* Even though this is not an smb message, smb_len returns the generic length of an smb message */
2557         numtowrite = smb_len(inbuf);
2558
2559         /* Set up outbuf to return the correct return */
2560         outsize = set_message(outbuf,1,0,True);
2561         SCVAL(outbuf,smb_com,SMBwritec);
2562         SSVAL(outbuf,smb_vwv0,total_written);
2563
2564         if (numtowrite != 0) {
2565
2566                 if (numtowrite > BUFFER_SIZE) {
2567                         DEBUG(0,("reply_writebraw: Oversize secondary write raw requested (%u). Terminating\n",
2568                                 (unsigned int)numtowrite ));
2569                         exit_server("secondary writebraw failed");
2570                 }
2571
2572                 if (tcount > nwritten+numtowrite) {
2573                         DEBUG(3,("Client overestimated the write %d %d %d\n",
2574                                 (int)tcount,(int)nwritten,(int)numtowrite));
2575                 }
2576
2577                 if (read_data( smbd_server_fd(), inbuf+4, numtowrite) != numtowrite ) {
2578                         DEBUG(0,("reply_writebraw: Oversize secondary write raw read failed (%s). Terminating\n",
2579                                 strerror(errno) ));
2580                         exit_server("secondary writebraw failed");
2581                 }
2582
2583                 nwritten = write_file(fsp,inbuf+4,startpos+nwritten,numtowrite);
2584
2585                 if (nwritten < (ssize_t)numtowrite) {
2586                         SCVAL(outbuf,smb_rcls,ERRHRD);
2587                         SSVAL(outbuf,smb_err,ERRdiskfull);      
2588                 }
2589
2590                 if (nwritten > 0)
2591                         total_written += nwritten;
2592         }
2593  
2594         if ((lp_syncalways(SNUM(conn)) || write_through) && lp_strict_sync(SNUM(conn)))
2595                 sync_file(conn,fsp);
2596
2597         DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
2598                 fsp->fnum, (double)startpos, (int)numtowrite,(int)total_written));
2599
2600         /* we won't return a status if write through is not selected - this follows what WfWg does */
2601         END_PROFILE(SMBwritebraw);
2602         if (!write_through && total_written==tcount) {
2603
2604 #if RABBIT_PELLET_FIX
2605                 /*
2606                  * Fix for "rabbit pellet" mode, trigger an early TCP ack by
2607                  * sending a SMBkeepalive. Thanks to DaveCB at Sun for this. JRA.
2608                  */
2609                 if (!send_keepalive(smbd_server_fd()))
2610                         exit_server("reply_writebraw: send of keepalive failed");
2611 #endif
2612                 return(-1);
2613         }
2614
2615         return(outsize);
2616 }
2617
2618 #undef DBGC_CLASS
2619 #define DBGC_CLASS DBGC_LOCKING
2620
2621 /****************************************************************************
2622  Reply to a writeunlock (core+).
2623 ****************************************************************************/
2624
2625 int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf, 
2626                       int size, int dum_buffsize)
2627 {
2628         ssize_t nwritten = -1;
2629         size_t numtowrite;
2630         SMB_OFF_T startpos;
2631         char *data;
2632         NTSTATUS status = NT_STATUS_OK;
2633         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2634         int outsize = 0;
2635         START_PROFILE(SMBwriteunlock);
2636         
2637         CHECK_FSP(fsp,conn);
2638         CHECK_WRITE(fsp);
2639
2640         numtowrite = SVAL(inbuf,smb_vwv1);
2641         startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2642         data = smb_buf(inbuf) + 3;
2643   
2644         if (numtowrite && is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2645                 END_PROFILE(SMBwriteunlock);
2646                 return ERROR_DOS(ERRDOS,ERRlock);
2647         }
2648
2649         /* The special X/Open SMB protocol handling of
2650            zero length writes is *NOT* done for
2651            this call */
2652         if(numtowrite == 0)
2653                 nwritten = 0;
2654         else
2655                 nwritten = write_file(fsp,data,startpos,numtowrite);
2656   
2657         if (lp_syncalways(SNUM(conn)))
2658                 sync_file(conn,fsp);
2659
2660         if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2661                 END_PROFILE(SMBwriteunlock);
2662                 return(UNIXERROR(ERRHRD,ERRdiskfull));
2663         }
2664
2665         if (numtowrite) {
2666                 status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)numtowrite, 
2667                                    (SMB_BIG_UINT)startpos);
2668                 if (NT_STATUS_V(status)) {
2669                         END_PROFILE(SMBwriteunlock);
2670                         return ERROR_NT(status);
2671                 }
2672         }
2673         
2674         outsize = set_message(outbuf,1,0,True);
2675         
2676         SSVAL(outbuf,smb_vwv0,nwritten);
2677         
2678         DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
2679                  fsp->fnum, (int)numtowrite, (int)nwritten));
2680         
2681         END_PROFILE(SMBwriteunlock);
2682         return outsize;
2683 }
2684
2685 #undef DBGC_CLASS
2686 #define DBGC_CLASS DBGC_ALL
2687
2688 /****************************************************************************
2689  Reply to a write.
2690 ****************************************************************************/
2691
2692 int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int dum_buffsize)
2693 {
2694         size_t numtowrite;
2695         ssize_t nwritten = -1;
2696         SMB_OFF_T startpos;
2697         char *data;
2698         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2699         int outsize = 0;
2700         START_PROFILE(SMBwrite);
2701
2702         /* If it's an IPC, pass off the pipe handler. */
2703         if (IS_IPC(conn)) {
2704                 END_PROFILE(SMBwrite);
2705                 return reply_pipe_write(inbuf,outbuf,size,dum_buffsize);
2706         }
2707
2708         CHECK_FSP(fsp,conn);
2709         CHECK_WRITE(fsp);
2710
2711         numtowrite = SVAL(inbuf,smb_vwv1);
2712         startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2713         data = smb_buf(inbuf) + 3;
2714   
2715         if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2716                 END_PROFILE(SMBwrite);
2717                 return ERROR_DOS(ERRDOS,ERRlock);
2718         }
2719
2720         /*
2721          * X/Open SMB protocol says that if smb_vwv1 is
2722          * zero then the file size should be extended or
2723          * truncated to the size given in smb_vwv[2-3].
2724          */
2725
2726         if(numtowrite == 0) {
2727                 /*
2728                  * This is actually an allocate call, and set EOF. JRA.
2729                  */
2730                 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
2731                 if (nwritten < 0) {
2732                         END_PROFILE(SMBwrite);
2733                         return ERROR_NT(NT_STATUS_DISK_FULL);
2734                 }
2735                 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
2736                 if (nwritten < 0) {
2737                         END_PROFILE(SMBwrite);
2738                         return ERROR_NT(NT_STATUS_DISK_FULL);
2739                 }
2740         } else
2741                 nwritten = write_file(fsp,data,startpos,numtowrite);
2742   
2743         if (lp_syncalways(SNUM(conn)))
2744                 sync_file(conn,fsp);
2745
2746         if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2747                 END_PROFILE(SMBwrite);
2748                 return(UNIXERROR(ERRHRD,ERRdiskfull));
2749         }
2750
2751         outsize = set_message(outbuf,1,0,True);
2752   
2753         SSVAL(outbuf,smb_vwv0,nwritten);
2754
2755         if (nwritten < (ssize_t)numtowrite) {
2756                 SCVAL(outbuf,smb_rcls,ERRHRD);
2757                 SSVAL(outbuf,smb_err,ERRdiskfull);      
2758         }
2759   
2760         DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
2761
2762         END_PROFILE(SMBwrite);
2763         return(outsize);
2764 }
2765
2766 /****************************************************************************
2767  Reply to a write and X.
2768 ****************************************************************************/
2769
2770 int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2771 {
2772         files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2773         SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2774         size_t numtowrite = SVAL(inbuf,smb_vwv10);
2775         BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
2776         ssize_t nwritten = -1;
2777         unsigned int smb_doff = SVAL(inbuf,smb_vwv11);
2778         unsigned int smblen = smb_len(inbuf);
2779         char *data;
2780         BOOL large_writeX = ((CVAL(inbuf,smb_wct) == 14) && (smblen > 0xFFFF));
2781         START_PROFILE(SMBwriteX);
2782
2783         /* If it's an IPC, pass off the pipe handler. */
2784         if (IS_IPC(conn)) {
2785                 END_PROFILE(SMBwriteX);
2786                 return reply_pipe_write_and_X(inbuf,outbuf,length,bufsize);
2787         }
2788
2789         CHECK_FSP(fsp,conn);
2790         CHECK_WRITE(fsp);
2791
2792         /* Deal with possible LARGE_WRITEX */
2793         if (large_writeX)
2794                 numtowrite |= ((((size_t)SVAL(inbuf,smb_vwv9)) & 1 )<<16);
2795
2796         if(smb_doff > smblen || (smb_doff + numtowrite > smblen)) {
2797                 END_PROFILE(SMBwriteX);
2798                 return ERROR_DOS(ERRDOS,ERRbadmem);
2799         }
2800
2801         data = smb_base(inbuf) + smb_doff;
2802
2803         if(CVAL(inbuf,smb_wct) == 14) {
2804 #ifdef LARGE_SMB_OFF_T
2805                 /*
2806                  * This is a large offset (64 bit) write.
2807                  */
2808                 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv12)) << 32);
2809
2810 #else /* !LARGE_SMB_OFF_T */
2811
2812                 /*
2813                  * Ensure we haven't been sent a >32 bit offset.
2814                  */
2815
2816                 if(IVAL(inbuf,smb_vwv12) != 0) {
2817                         DEBUG(0,("reply_write_and_X - large offset (%x << 32) used and we don't support \
2818 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv12) ));
2819                         END_PROFILE(SMBwriteX);
2820                         return ERROR_DOS(ERRDOS,ERRbadaccess);
2821                 }
2822
2823 #endif /* LARGE_SMB_OFF_T */
2824         }
2825
2826         if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2827                 END_PROFILE(SMBwriteX);
2828                 return ERROR_DOS(ERRDOS,ERRlock);
2829         }
2830
2831         /* X/Open SMB protocol says that, unlike SMBwrite
2832         if the length is zero then NO truncation is
2833         done, just a write of zero. To truncate a file,
2834         use SMBwrite. */
2835
2836         if(numtowrite == 0)
2837                 nwritten = 0;
2838         else
2839                 nwritten = write_file(fsp,data,startpos,numtowrite);
2840   
2841         if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2842                 END_PROFILE(SMBwriteX);
2843                 return(UNIXERROR(ERRHRD,ERRdiskfull));
2844         }
2845
2846         set_message(outbuf,6,0,True);
2847   
2848         SSVAL(outbuf,smb_vwv2,nwritten);
2849         if (large_writeX)
2850                 SSVAL(outbuf,smb_vwv4,(nwritten>>16)&1);
2851
2852         if (nwritten < (ssize_t)numtowrite) {
2853                 SCVAL(outbuf,smb_rcls,ERRHRD);
2854                 SSVAL(outbuf,smb_err,ERRdiskfull);      
2855         }
2856
2857         DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
2858                 fsp->fnum, (int)numtowrite, (int)nwritten));
2859
2860         if (lp_syncalways(SNUM(conn)) || write_through)
2861                 sync_file(conn,fsp);
2862
2863         END_PROFILE(SMBwriteX);
2864         return chain_reply(inbuf,outbuf,length,bufsize);
2865 }
2866
2867 /****************************************************************************
2868  Reply to a lseek.
2869 ****************************************************************************/
2870
2871 int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2872 {
2873         SMB_OFF_T startpos;
2874         SMB_OFF_T res= -1;
2875         int mode,umode;
2876         int outsize = 0;
2877         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2878         START_PROFILE(SMBlseek);
2879
2880         CHECK_FSP(fsp,conn);
2881
2882         flush_write_cache(fsp, SEEK_FLUSH);
2883
2884         mode = SVAL(inbuf,smb_vwv1) & 3;
2885         /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
2886         startpos = (SMB_OFF_T)IVALS(inbuf,smb_vwv2);
2887
2888         switch (mode) {
2889                 case 0:
2890                         umode = SEEK_SET;
2891                         res = startpos;
2892                         break;
2893                 case 1:
2894                         umode = SEEK_CUR;
2895                         res = fsp->pos + startpos;
2896                         break;
2897                 case 2:
2898                         umode = SEEK_END;
2899                         break;
2900                 default:
2901                         umode = SEEK_SET;
2902                         res = startpos;
2903                         break;
2904         }
2905
2906         if (umode == SEEK_END) {
2907                 if((res = SMB_VFS_LSEEK(fsp,fsp->fd,startpos,umode)) == -1) {
2908                         if(errno == EINVAL) {
2909                                 SMB_OFF_T current_pos = startpos;
2910                                 SMB_STRUCT_STAT sbuf;
2911
2912                                 if(SMB_VFS_FSTAT(fsp,fsp->fd, &sbuf) == -1) {
2913                                         END_PROFILE(SMBlseek);
2914                                         return(UNIXERROR(ERRDOS,ERRnoaccess));
2915                                 }
2916
2917                                 current_pos += sbuf.st_size;
2918                                 if(current_pos < 0)
2919                                         res = SMB_VFS_LSEEK(fsp,fsp->fd,0,SEEK_SET);
2920                         }
2921                 }
2922
2923                 if(res == -1) {
2924                         END_PROFILE(SMBlseek);
2925                         return(UNIXERROR(ERRDOS,ERRnoaccess));
2926                 }
2927         }
2928
2929         fsp->pos = res;
2930   
2931         outsize = set_message(outbuf,2,0,True);
2932         SIVAL(outbuf,smb_vwv0,res);
2933   
2934         DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
2935                 fsp->fnum, (double)startpos, (double)res, mode));
2936
2937         END_PROFILE(SMBlseek);
2938         return(outsize);
2939 }
2940
2941 /****************************************************************************
2942  Reply to a flush.
2943 ****************************************************************************/
2944
2945 int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2946 {
2947         int outsize = set_message(outbuf,0,0,True);
2948         uint16 fnum = SVAL(inbuf,smb_vwv0);
2949         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2950         START_PROFILE(SMBflush);
2951
2952         if (fnum != 0xFFFF)
2953                 CHECK_FSP(fsp,conn);
2954         
2955         if (!fsp) {
2956                 file_sync_all(conn);
2957         } else {
2958                 sync_file(conn,fsp);
2959         }
2960         
2961         DEBUG(3,("flush\n"));
2962         END_PROFILE(SMBflush);
2963         return(outsize);
2964 }
2965
2966 /****************************************************************************
2967  Reply to a exit.
2968 ****************************************************************************/
2969
2970 int reply_exit(connection_struct *conn, 
2971                char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2972 {
2973         int outsize;
2974         START_PROFILE(SMBexit);
2975
2976         file_close_pid(SVAL(inbuf,smb_pid));
2977
2978         outsize = set_message(outbuf,0,0,True);
2979
2980         DEBUG(3,("exit\n"));
2981
2982         END_PROFILE(SMBexit);
2983         return(outsize);
2984 }
2985
2986 /****************************************************************************
2987  Reply to a close - has to deal with closing a directory opened by NT SMB's.
2988 ****************************************************************************/
2989
2990 int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size,
2991                 int dum_buffsize)
2992 {
2993         int outsize = 0;
2994         time_t mtime;
2995         int32 eclass = 0, err = 0;
2996         files_struct *fsp = NULL;
2997         START_PROFILE(SMBclose);
2998
2999         outsize = set_message(outbuf,0,0,True);
3000
3001         /* If it's an IPC, pass off to the pipe handler. */
3002         if (IS_IPC(conn)) {
3003                 END_PROFILE(SMBclose);
3004                 return reply_pipe_close(conn, inbuf,outbuf);
3005         }
3006
3007         fsp = file_fsp(inbuf,smb_vwv0);
3008
3009         /*
3010          * We can only use CHECK_FSP if we know it's not a directory.
3011          */
3012
3013         if(!fsp || (fsp->conn != conn) || (fsp->vuid != current_user.vuid)) {
3014                 END_PROFILE(SMBclose);
3015                 return ERROR_DOS(ERRDOS,ERRbadfid);
3016         }
3017
3018         if(fsp->is_directory) {
3019                 /*
3020                  * Special case - close NT SMB directory handle.
3021                  */
3022                 DEBUG(3,("close %s fnum=%d\n", fsp->is_directory ? "directory" : "stat file open", fsp->fnum));
3023                 close_file(fsp,True);
3024         } else {
3025                 /*
3026                  * Close ordinary file.
3027                  */
3028                 int close_err;
3029                 pstring file_name;
3030
3031                 /* Save the name for time set in close. */
3032                 pstrcpy( file_name, fsp->fsp_name);
3033
3034                 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
3035                          fsp->fd, fsp->fnum,
3036                          conn->num_files_open));
3037  
3038                 /*
3039                  * Take care of any time sent in the close.
3040                  */
3041
3042                 mtime = make_unix_date3(inbuf+smb_vwv1);
3043                 fsp_set_pending_modtime(fsp, mtime);
3044
3045                 /*
3046                  * close_file() returns the unix errno if an error
3047                  * was detected on close - normally this is due to
3048                  * a disk full error. If not then it was probably an I/O error.
3049                  */
3050  
3051                 if((close_err = close_file(fsp,True)) != 0) {
3052                         errno = close_err;
3053                         END_PROFILE(SMBclose);
3054                         return (UNIXERROR(ERRHRD,ERRgeneral));
3055                 }
3056         }  
3057
3058         /* We have a cached error */
3059         if(eclass || err) {
3060                 END_PROFILE(SMBclose);
3061                 return ERROR_DOS(eclass,err);
3062         }
3063
3064         END_PROFILE(SMBclose);
3065         return(outsize);
3066 }
3067
3068 /****************************************************************************
3069  Reply to a writeclose (Core+ protocol).
3070 ****************************************************************************/
3071
3072 int reply_writeclose(connection_struct *conn,
3073                      char *inbuf,char *outbuf, int size, int dum_buffsize)
3074 {
3075         size_t numtowrite;
3076         ssize_t nwritten = -1;
3077         int outsize = 0;
3078         int close_err = 0;
3079         SMB_OFF_T startpos;
3080         char *data;
3081         time_t mtime;
3082         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3083         START_PROFILE(SMBwriteclose);
3084
3085         CHECK_FSP(fsp,conn);
3086         CHECK_WRITE(fsp);
3087
3088         numtowrite = SVAL(inbuf,smb_vwv1);
3089         startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
3090         mtime = make_unix_date3(inbuf+smb_vwv4);
3091         data = smb_buf(inbuf) + 1;
3092   
3093         if (numtowrite && is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
3094                 END_PROFILE(SMBwriteclose);
3095                 return ERROR_DOS(ERRDOS,ERRlock);
3096         }
3097   
3098         nwritten = write_file(fsp,data,startpos,numtowrite);
3099
3100         set_filetime(conn, fsp->fsp_name,mtime);
3101   
3102         /*
3103          * More insanity. W2K only closes the file if writelen > 0.
3104          * JRA.
3105          */
3106
3107         if (numtowrite) {
3108                 DEBUG(3,("reply_writeclose: zero length write doesn't close file %s\n",
3109                         fsp->fsp_name ));
3110                 close_err = close_file(fsp,True);
3111         }
3112
3113         DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
3114                  fsp->fnum, (int)numtowrite, (int)nwritten,
3115                  conn->num_files_open));
3116   
3117         if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
3118                 END_PROFILE(SMBwriteclose);
3119                 return(UNIXERROR(ERRHRD,ERRdiskfull));
3120         }
3121  
3122         if(close_err != 0) {
3123                 errno = close_err;
3124                 END_PROFILE(SMBwriteclose);
3125                 return(UNIXERROR(ERRHRD,ERRgeneral));
3126         }
3127  
3128         outsize = set_message(outbuf,1,0,True);
3129   
3130         SSVAL(outbuf,smb_vwv0,nwritten);
3131         END_PROFILE(SMBwriteclose);
3132         return(outsize);
3133 }
3134
3135 #undef DBGC_CLASS
3136 #define DBGC_CLASS DBGC_LOCKING
3137
3138 /****************************************************************************
3139  Reply to a lock.
3140 ****************************************************************************/
3141
3142 int reply_lock(connection_struct *conn,
3143                char *inbuf,char *outbuf, int length, int dum_buffsize)
3144 {
3145         int outsize = set_message(outbuf,0,0,True);
3146         SMB_BIG_UINT count,offset;
3147         NTSTATUS status;
3148         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3149         BOOL my_lock_ctx = False;
3150
3151         START_PROFILE(SMBlock);
3152
3153         CHECK_FSP(fsp,conn);
3154
3155         release_level_2_oplocks_on_change(fsp);
3156
3157         count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
3158         offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
3159
3160         DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
3161                  fsp->fd, fsp->fnum, (double)offset, (double)count));
3162
3163         status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid), count, offset, WRITE_LOCK, &my_lock_ctx);
3164         if (NT_STATUS_V(status)) {
3165 #if 0
3166                 /* Tests using Samba4 against W2K show this call never creates a blocking lock. */
3167                 if (lp_blocking_locks(SNUM(conn)) && !my_lock_ctx && ERROR_WAS_LOCK_DENIED(status)) {
3168                         /*
3169                          * A blocking lock was requested. Package up
3170                          * this smb into a queued request and push it
3171                          * onto the blocking lock queue.
3172                          */
3173                         if(push_blocking_lock_request(inbuf, length, -1, 0, SVAL(inbuf,smb_pid), offset, count)) {
3174                                 END_PROFILE(SMBlock);
3175                                 return -1;
3176                         }
3177                 }
3178 #endif
3179                 END_PROFILE(SMBlock);
3180                 return ERROR_NT(status);
3181         }
3182
3183         END_PROFILE(SMBlock);
3184         return(outsize);
3185 }
3186
3187 /****************************************************************************
3188  Reply to a unlock.
3189 ****************************************************************************/
3190
3191 int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size, 
3192                  int dum_buffsize)
3193 {
3194         int outsize = set_message(outbuf,0,0,True);
3195         SMB_BIG_UINT count,offset;
3196         NTSTATUS status;
3197         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3198         START_PROFILE(SMBunlock);
3199
3200         CHECK_FSP(fsp,conn);
3201         
3202         count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
3203         offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
3204         
3205         status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), count, offset);
3206         if (NT_STATUS_V(status)) {
3207                 END_PROFILE(SMBunlock);
3208                 return ERROR_NT(status);
3209         }
3210
3211         DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
3212                     fsp->fd, fsp->fnum, (double)offset, (double)count ) );
3213         
3214         END_PROFILE(SMBunlock);
3215         return(outsize);
3216 }
3217
3218 #undef DBGC_CLASS
3219 #define DBGC_CLASS DBGC_ALL
3220
3221 /****************************************************************************
3222  Reply to a tdis.
3223 ****************************************************************************/
3224
3225 int reply_tdis(connection_struct *conn, 
3226                char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3227 {
3228         int outsize = set_message(outbuf,0,0,True);
3229         uint16 vuid;
3230         START_PROFILE(SMBtdis);
3231
3232         vuid = SVAL(inbuf,smb_uid);
3233
3234         if (!conn) {
3235                 DEBUG(4,("Invalid connection in tdis\n"));
3236                 END_PROFILE(SMBtdis);
3237                 return ERROR_DOS(ERRSRV,ERRinvnid);
3238         }
3239
3240         conn->used = False;
3241
3242         close_cnum(conn,vuid);
3243   
3244         END_PROFILE(SMBtdis);
3245         return outsize;
3246 }
3247
3248 /****************************************************************************
3249  Reply to a echo.
3250 ****************************************************************************/
3251
3252 int reply_echo(connection_struct *conn,
3253                char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3254 {
3255         int smb_reverb = SVAL(inbuf,smb_vwv0);
3256         int seq_num;
3257         unsigned int data_len = smb_buflen(inbuf);
3258         int outsize = set_message(outbuf,1,data_len,True);
3259         START_PROFILE(SMBecho);
3260
3261         if (data_len > BUFFER_SIZE) {
3262                 DEBUG(0,("reply_echo: data_len too large.\n"));
3263                 END_PROFILE(SMBecho);
3264                 return -1;
3265         }
3266
3267         /* copy any incoming data back out */
3268         if (data_len > 0)
3269                 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
3270
3271         if (smb_reverb > 100) {
3272                 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
3273                 smb_reverb = 100;
3274         }
3275
3276         for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
3277                 SSVAL(outbuf,smb_vwv0,seq_num);
3278
3279                 smb_setlen(outbuf,outsize - 4);
3280
3281                 if (!send_smb(smbd_server_fd(),outbuf))
3282                         exit_server("reply_echo: send_smb failed.");
3283         }
3284
3285         DEBUG(3,("echo %d times\n", smb_reverb));
3286
3287         smb_echo_count++;
3288
3289         END_PROFILE(SMBecho);
3290         return -1;
3291 }
3292
3293 /****************************************************************************
3294  Reply to a printopen.
3295 ****************************************************************************/
3296
3297 int reply_printopen(connection_struct *conn, 
3298                     char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3299 {
3300         int outsize = 0;
3301         files_struct *fsp;
3302         START_PROFILE(SMBsplopen);
3303         
3304         if (!CAN_PRINT(conn)) {
3305                 END_PROFILE(SMBsplopen);
3306                 return ERROR_DOS(ERRDOS,ERRnoaccess);
3307         }
3308
3309         /* Open for exclusive use, write only. */
3310         fsp = print_fsp_open(conn, NULL);
3311
3312         if (!fsp) {
3313                 END_PROFILE(SMBsplopen);
3314                 return(UNIXERROR(ERRDOS,ERRnoaccess));
3315         }
3316
3317         outsize = set_message(outbuf,1,0,True);
3318         SSVAL(outbuf,smb_vwv0,fsp->fnum);
3319   
3320         DEBUG(3,("openprint fd=%d fnum=%d\n",
3321                  fsp->fd, fsp->fnum));
3322
3323         END_PROFILE(SMBsplopen);
3324         return(outsize);
3325 }
3326
3327 /****************************************************************************
3328  Reply to a printclose.
3329 ****************************************************************************/
3330
3331 int reply_printclose(connection_struct *conn,
3332                      char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3333 {
3334         int outsize = set_message(outbuf,0,0,True);
3335         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3336         int close_err = 0;
3337         START_PROFILE(SMBsplclose);
3338
3339         CHECK_FSP(fsp,conn);
3340
3341         if (!CAN_PRINT(conn)) {
3342                 END_PROFILE(SMBsplclose);
3343                 return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
3344         }
3345   
3346         DEBUG(3,("printclose fd=%d fnum=%d\n",
3347                  fsp->fd,fsp->fnum));
3348   
3349         close_err = close_file(fsp,True);
3350
3351         if(close_err != 0) {
3352                 errno = close_err;
3353                 END_PROFILE(SMBsplclose);
3354                 return(UNIXERROR(ERRHRD,ERRgeneral));
3355         }
3356
3357         END_PROFILE(SMBsplclose);
3358         return(outsize);
3359 }
3360
3361 /****************************************************************************
3362  Reply to a printqueue.
3363 ****************************************************************************/
3364
3365 int reply_printqueue(connection_struct *conn,
3366                      char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3367 {
3368         int outsize = set_message(outbuf,2,3,True);
3369         int max_count = SVAL(inbuf,smb_vwv0);
3370         int start_index = SVAL(inbuf,smb_vwv1);
3371         START_PROFILE(SMBsplretq);
3372
3373         /* we used to allow the client to get the cnum wrong, but that
3374            is really quite gross and only worked when there was only
3375            one printer - I think we should now only accept it if they
3376            get it right (tridge) */
3377         if (!CAN_PRINT(conn)) {
3378                 END_PROFILE(SMBsplretq);
3379                 return ERROR_DOS(ERRDOS,ERRnoaccess);
3380         }
3381
3382         SSVAL(outbuf,smb_vwv0,0);
3383         SSVAL(outbuf,smb_vwv1,0);
3384         SCVAL(smb_buf(outbuf),0,1);
3385         SSVAL(smb_buf(outbuf),1,0);
3386   
3387         DEBUG(3,("printqueue start_index=%d max_count=%d\n",
3388                  start_index, max_count));
3389
3390         {
3391                 print_queue_struct *queue = NULL;
3392                 print_status_struct status;
3393                 char *p = smb_buf(outbuf) + 3;
3394                 int count = print_queue_status(SNUM(conn), &queue, &status);
3395                 int num_to_get = ABS(max_count);
3396                 int first = (max_count>0?start_index:start_index+max_count+1);
3397                 int i;
3398
3399                 if (first >= count)
3400                         num_to_get = 0;
3401                 else
3402                         num_to_get = MIN(num_to_get,count-first);
3403     
3404
3405                 for (i=first;i<first+num_to_get;i++) {
3406                         put_dos_date2(p,0,queue[i].time);
3407                         SCVAL(p,4,(queue[i].status==LPQ_PRINTING?2:3));
3408                         SSVAL(p,5, queue[i].job);
3409                         SIVAL(p,7,queue[i].size);
3410                         SCVAL(p,11,0);
3411                         srvstr_push(outbuf, p+12, queue[i].fs_user, 16, STR_ASCII);
3412                         p += 28;
3413                 }
3414
3415                 if (count > 0) {
3416                         outsize = set_message(outbuf,2,28*count+3,False); 
3417                         SSVAL(outbuf,smb_vwv0,count);
3418                         SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
3419                         SCVAL(smb_buf(outbuf),0,1);
3420                         SSVAL(smb_buf(outbuf),1,28*count);
3421                 }
3422
3423                 SAFE_FREE(queue);
3424           
3425                 DEBUG(3,("%d entries returned in queue\n",count));
3426         }
3427   
3428         END_PROFILE(SMBsplretq);
3429         return(outsize);
3430 }
3431
3432 /****************************************************************************
3433  Reply to a printwrite.
3434 ****************************************************************************/
3435
3436 int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3437 {
3438         int numtowrite;
3439         int outsize = set_message(outbuf,0,0,True);
3440         char *data;
3441         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3442
3443         START_PROFILE(SMBsplwr);
3444   
3445         if (!CAN_PRINT(conn)) {
3446                 END_PROFILE(SMBsplwr);
3447                 return ERROR_DOS(ERRDOS,ERRnoaccess);
3448         }
3449
3450         CHECK_FSP(fsp,conn);
3451         CHECK_WRITE(fsp);
3452
3453         numtowrite = SVAL(smb_buf(inbuf),1);
3454         data = smb_buf(inbuf) + 3;
3455   
3456         if (write_file(fsp,data,-1,numtowrite) != numtowrite) {
3457                 END_PROFILE(SMBsplwr);
3458                 return(UNIXERROR(ERRHRD,ERRdiskfull));
3459         }
3460
3461         DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
3462   
3463         END_PROFILE(SMBsplwr);
3464         return(outsize);
3465 }
3466
3467 /****************************************************************************
3468  The guts of the mkdir command, split out so it may be called by the NT SMB
3469  code. 
3470 ****************************************************************************/
3471
3472 NTSTATUS mkdir_internal(connection_struct *conn, const pstring directory, BOOL bad_path)
3473 {
3474         int ret= -1;
3475         
3476         if(!CAN_WRITE(conn)) {
3477                 DEBUG(5,("mkdir_internal: failing create on read-only share %s\n", lp_servicename(SNUM(conn))));
3478                 errno = EACCES;
3479                 return map_nt_error_from_unix(errno);
3480         }
3481
3482         if (bad_path) {
3483                 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3484         }
3485
3486         if (!check_name(directory, conn)) {
3487                 if(errno == ENOENT) {
3488                         if (bad_path) {
3489                                 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3490                         } else {
3491                                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3492                         }
3493                 }
3494                 return map_nt_error_from_unix(errno);
3495         }
3496
3497         ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory,True));
3498         if (ret == -1) {
3499                 if(errno == ENOENT) {
3500                         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3501                 }
3502                 return map_nt_error_from_unix(errno);
3503         }
3504         
3505         return NT_STATUS_OK;
3506 }
3507
3508 /****************************************************************************
3509  Reply to a mkdir.
3510 ****************************************************************************/
3511
3512 int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3513 {
3514         pstring directory;
3515         int outsize;
3516         NTSTATUS status;
3517         BOOL bad_path = False;
3518         SMB_STRUCT_STAT sbuf;
3519
3520         START_PROFILE(SMBmkdir);
3521  
3522         srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status, False);
3523         if (!NT_STATUS_IS_OK(status)) {
3524                 END_PROFILE(SMBmkdir);
3525                 return ERROR_NT(status);
3526         }
3527
3528         RESOLVE_DFSPATH(directory, conn, inbuf, outbuf);
3529
3530         unix_convert(directory,conn,0,&bad_path,&sbuf);
3531
3532         if( strchr_m(directory, ':')) {
3533                 DEBUG(5,("reply_mkdir: failing create on filename %s with colon in name\n", directory));
3534                 END_PROFILE(SMBmkdir);
3535                 return ERROR_FORCE_DOS(ERRDOS, ERRinvalidname);
3536         }
3537
3538         status = mkdir_internal(conn, directory,bad_path);
3539         if (!NT_STATUS_IS_OK(status)) {
3540                 END_PROFILE(SMBmkdir);
3541                 return ERROR_NT(status);
3542         }
3543
3544         if (lp_inherit_owner(SNUM(conn))) {
3545                 /* Ensure we're checking for a symlink here.... */
3546                 /* We don't want to get caught by a symlink racer. */
3547
3548                 if(SMB_VFS_LSTAT(conn,directory, &sbuf) != 0) {
3549                         END_PROFILE(SMBmkdir);
3550                         return(UNIXERROR(ERRDOS,ERRnoaccess));
3551                 }
3552                                                                                                                                                    
3553                 if(!S_ISDIR(sbuf.st_mode)) {
3554                         DEBUG(0,("reply_mkdir: %s is not a directory !\n", directory ));
3555                         END_PROFILE(SMBmkdir);
3556                         return(UNIXERROR(ERRDOS,ERRnoaccess));
3557                 }
3558
3559                 change_owner_to_parent(conn, NULL, directory, &sbuf);
3560         }
3561
3562         outsize = set_message(outbuf,0,0,True);
3563
3564         DEBUG( 3, ( "mkdir %s ret=%d\n", directory, outsize ) );
3565
3566         END_PROFILE(SMBmkdir);
3567         return(outsize);
3568 }
3569
3570 /****************************************************************************
3571  Static function used by reply_rmdir to delete an entire directory
3572  tree recursively. Return False on ok, True on fail.
3573 ****************************************************************************/
3574
3575 static BOOL recursive_rmdir(connection_struct *conn, char *directory)
3576 {
3577         const char *dname = NULL;
3578         BOOL ret = False;
3579         long offset = 0;
3580         struct smb_Dir *dir_hnd = OpenDir(conn, directory);
3581
3582         if(dir_hnd == NULL)
3583                 return True;
3584
3585         while((dname = ReadDirName(dir_hnd, &offset))) {
3586                 pstring fullname;
3587                 SMB_STRUCT_STAT st;
3588
3589                 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3590                         continue;
3591
3592                 if (!is_visible_file(conn, directory, dname, &st, False))
3593                         continue;
3594
3595                 /* Construct the full name. */
3596                 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
3597                         errno = ENOMEM;
3598                         ret = True;
3599                         break;
3600                 }
3601
3602                 pstrcpy(fullname, directory);
3603                 pstrcat(fullname, "/");
3604                 pstrcat(fullname, dname);
3605
3606                 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
3607                         ret = True;
3608                         break;
3609                 }
3610
3611                 if(st.st_mode & S_IFDIR) {
3612                         if(recursive_rmdir(conn, fullname)!=0) {
3613                                 ret = True;
3614                                 break;
3615                         }
3616                         if(SMB_VFS_RMDIR(conn,fullname) != 0) {
3617                                 ret = True;
3618                                 break;
3619                         }
3620                 } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
3621                         ret = True;
3622                         break;
3623                 }
3624         }
3625         CloseDir(dir_hnd);
3626         return ret;
3627 }
3628
3629 /****************************************************************************
3630  The internals of the rmdir code - called elsewhere.
3631 ****************************************************************************/
3632
3633 BOOL rmdir_internals(connection_struct *conn, char *directory)
3634 {
3635         BOOL ok;
3636         SMB_STRUCT_STAT st;
3637
3638         ok = (SMB_VFS_RMDIR(conn,directory) == 0);
3639         if(!ok && ((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
3640                 /* 
3641                  * Check to see if the only thing in this directory are
3642                  * vetoed files/directories. If so then delete them and
3643                  * retry. If we fail to delete any of them (and we *don't*
3644                  * do a recursive delete) then fail the rmdir.
3645                  */
3646                 BOOL all_veto_files = True;
3647                 const char *dname;
3648                 struct smb_Dir *dir_hnd = OpenDir(conn, directory);
3649
3650                 if(dir_hnd != NULL) {
3651                         long dirpos = TellDir(dir_hnd);
3652                         while ((dname = ReadDirName(dir_hnd,&dirpos))) {
3653                                 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3654                                         continue;
3655                                 if (!is_visible_file(conn, directory, dname, &st, False))
3656                                         continue;
3657                                 if(!IS_VETO_PATH(conn, dname)) {
3658                                         all_veto_files = False;
3659                                         break;
3660                                 }
3661                         }
3662
3663                         if(all_veto_files) {
3664                                 SeekDir(dir_hnd,dirpos);
3665                                 while ((dname = ReadDirName(dir_hnd,&dirpos))) {
3666                                         pstring fullname;
3667
3668                                         if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3669                                                 continue;
3670                                         if (!is_visible_file(conn, directory, dname, &st, False))
3671                                                 continue;
3672
3673                                         /* Construct the full name. */
3674                                         if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
3675                                                 errno = ENOMEM;
3676                                                 break;
3677                                         }
3678
3679                                         pstrcpy(fullname, directory);
3680                                         pstrcat(fullname, "/");
3681                                         pstrcat(fullname, dname);
3682                      
3683                                         if(SMB_VFS_LSTAT(conn,fullname, &st) != 0)
3684                                                 break;
3685                                         if(st.st_mode & S_IFDIR) {
3686                                                 if(lp_recursive_veto_delete(SNUM(conn))) {
3687                                                         if(recursive_rmdir(conn, fullname) != 0)
3688                                                                 break;
3689                                                 }
3690                                                 if(SMB_VFS_RMDIR(conn,fullname) != 0)
3691                                                         break;
3692                                         } else if(SMB_VFS_UNLINK(conn,fullname) != 0)
3693                                                 break;
3694                                 }
3695                                 CloseDir(dir_hnd);
3696                                 /* Retry the rmdir */
3697                                 ok = (SMB_VFS_RMDIR(conn,directory) == 0);
3698                         } else {
3699                                 CloseDir(dir_hnd);
3700                         }
3701                 } else {
3702                         errno = ENOTEMPTY;
3703                 }
3704         }
3705
3706         if (!ok)
3707                 DEBUG(3,("rmdir_internals: couldn't remove directory %s : %s\n", directory,strerror(errno)));
3708
3709         return ok;
3710 }
3711
3712 /****************************************************************************
3713  Reply to a rmdir.
3714 ****************************************************************************/
3715
3716 int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3717 {
3718         pstring directory;
3719         int outsize = 0;
3720         BOOL ok = False;
3721         BOOL bad_path = False;
3722         SMB_STRUCT_STAT sbuf;
3723         NTSTATUS status;
3724         START_PROFILE(SMBrmdir);
3725
3726         srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status, False);
3727         if (!NT_STATUS_IS_OK(status)) {
3728                 END_PROFILE(SMBrmdir);
3729                 return ERROR_NT(status);
3730         }
3731
3732         RESOLVE_DFSPATH(directory, conn, inbuf, outbuf)
3733
3734         unix_convert(directory,conn, NULL,&bad_path,&sbuf);
3735         if (bad_path) {
3736                 END_PROFILE(SMBrmdir);
3737                 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
3738         }
3739   
3740         if (check_name(directory,conn)) {
3741                 dptr_closepath(directory,SVAL(inbuf,smb_pid));
3742                 ok = rmdir_internals(conn, directory);
3743         }
3744   
3745         if (!ok) {
3746                 END_PROFILE(SMBrmdir);
3747                 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRbadpath);
3748         }
3749  
3750         outsize = set_message(outbuf,0,0,True);
3751   
3752         DEBUG( 3, ( "rmdir %s\n", directory ) );
3753   
3754         END_PROFILE(SMBrmdir);
3755         return(outsize);
3756 }
3757
3758 /*******************************************************************
3759  Resolve wildcards in a filename rename.
3760  Note that name is in UNIX charset and thus potentially can be more
3761  than fstring buffer (255 bytes) especially in default UTF-8 case.
3762  Therefore, we use pstring inside and all calls should ensure that
3763  name2 is at least pstring-long (they do already)
3764 ********************************************************************/
3765
3766 static BOOL resolve_wildcards(const char *name1, char *name2)
3767 {
3768         pstring root1,root2;
3769         pstring ext1,ext2;
3770         char *p,*p2, *pname1, *pname2;
3771         int available_space, actual_space;
3772         
3773
3774         pname1 = strrchr_m(name1,'/');
3775         pname2 = strrchr_m(name2,'/');
3776
3777         if (!pname1 || !pname2)
3778                 return(False);
3779   
3780         pstrcpy(root1,pname1);
3781         pstrcpy(root2,pname2);
3782         p = strrchr_m(root1,'.');
3783         if (p) {
3784                 *p = 0;
3785                 pstrcpy(ext1,p+1);
3786         } else {
3787                 pstrcpy(ext1,"");    
3788         }
3789         p = strrchr_m(root2,'.');
3790         if (p) {
3791                 *p = 0;
3792                 pstrcpy(ext2,p+1);
3793         } else {
3794                 pstrcpy(ext2,"");    
3795         }
3796
3797         p = root1;
3798         p2 = root2;
3799         while (*p2) {
3800                 if (*p2 == '?') {
3801                         *p2 = *p;
3802                         p2++;
3803                 } else if (*p2 == '*') {
3804                         pstrcpy(p2, p);
3805                         break;
3806                 } else {
3807                         p2++;
3808                 }
3809                 if (*p)
3810                         p++;
3811         }
3812
3813         p = ext1;
3814         p2 = ext2;
3815         while (*p2) {
3816                 if (*p2 == '?') {
3817                         *p2 = *p;
3818                         p2++;
3819                 } else if (*p2 == '*') {
3820                         pstrcpy(p2, p);
3821                         break;
3822                 } else {
3823                         p2++;
3824                 }
3825                 if (*p)
3826                         p++;
3827         }
3828
3829         available_space = sizeof(pstring) - PTR_DIFF(pname2, name2);
3830         
3831         if (ext2[0]) {
3832                 actual_space = snprintf(pname2, available_space - 1, "%s.%s", root2, ext2);
3833                 if (actual_space >= available_space - 1) {
3834                         DEBUG(1,("resolve_wildcards: can't fit resolved name into specified buffer (overrun by %d bytes)\n",
3835                                 actual_space - available_space));
3836                 }
3837         } else {
3838                 pstrcpy_base(pname2, root2, name2);
3839         }
3840
3841         return(True);
3842 }
3843
3844 /****************************************************************************
3845  Ensure open files have their names updates.
3846 ****************************************************************************/
3847
3848 static void rename_open_files(connection_struct *conn, SMB_DEV_T dev, SMB_INO_T inode, char *newname)
3849 {
3850         files_struct *fsp;
3851         BOOL did_rename = False;
3852
3853         for(fsp = file_find_di_first(dev, inode); fsp; fsp = file_find_di_next(fsp)) {
3854                 DEBUG(10,("rename_open_files: renaming file fnum %d (dev = %x, inode = %.0f) from %s -> %s\n",
3855                         fsp->fnum, (unsigned int)fsp->dev, (double)fsp->inode,
3856                         fsp->fsp_name, newname ));
3857                 string_set(&fsp->fsp_name, newname);
3858                 did_rename = True;
3859         }
3860
3861         if (!did_rename)
3862                 DEBUG(10,("rename_open_files: no open files on dev %x, inode %.0f for %s\n",
3863                         (unsigned int)dev, (double)inode, newname ));
3864 }
3865
3866 /****************************************************************************
3867  Rename an open file - given an fsp.
3868 ****************************************************************************/
3869
3870 NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, char *newname, uint16 attrs, BOOL replace_if_exists)
3871 {
3872         SMB_STRUCT_STAT sbuf;
3873         BOOL bad_path = False;
3874         pstring newname_last_component;
3875         NTSTATUS error = NT_STATUS_OK;
3876         BOOL dest_exists;
3877         BOOL rcdest = True;
3878
3879         ZERO_STRUCT(sbuf);
3880         rcdest = unix_convert(newname,conn,newname_last_component,&bad_path,&sbuf);
3881
3882         /* Quick check for "." and ".." */
3883         if (!bad_path && newname_last_component[0] == '.') {
3884                 if (!newname_last_component[1] || (newname_last_component[1] == '.' && !newname_last_component[2])) {
3885                         return NT_STATUS_ACCESS_DENIED;
3886                 }
3887         }
3888         if (!rcdest && bad_path) {
3889                 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3890         }
3891
3892         /* Ensure newname contains a '/' */
3893         if(strrchr_m(newname,'/') == 0) {
3894                 pstring tmpstr;
3895                 
3896                 pstrcpy(tmpstr, "./");
3897                 pstrcat(tmpstr, newname);
3898                 pstrcpy(newname, tmpstr);
3899         }
3900
3901         /*
3902          * Check for special case with case preserving and not
3903          * case sensitive. If the old last component differs from the original
3904          * last component only by case, then we should allow
3905          * the rename (user is trying to change the case of the
3906          * filename).
3907          */
3908
3909         if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
3910                         strequal(newname, fsp->fsp_name)) {
3911                 char *p;
3912                 pstring newname_modified_last_component;
3913
3914                 /*
3915                  * Get the last component of the modified name.
3916                  * Note that we guarantee that newname contains a '/'
3917                  * character above.
3918                  */
3919                 p = strrchr_m(newname,'/');
3920                 pstrcpy(newname_modified_last_component,p+1);
3921                         
3922                 if(strcsequal(newname_modified_last_component, 
3923                               newname_last_component) == False) {
3924                         /*
3925                          * Replace the modified last component with
3926                          * the original.
3927                          */
3928                         pstrcpy(p+1, newname_last_component);
3929                 }
3930         }
3931
3932         /*
3933          * If the src and dest names are identical - including case,
3934          * don't do the rename, just return success.
3935          */
3936
3937         if (strcsequal(fsp->fsp_name, newname)) {
3938                 DEBUG(3,("rename_internals_fsp: identical names in rename %s - returning success\n",
3939                         newname));
3940                 return NT_STATUS_OK;
3941         }
3942
3943         dest_exists = vfs_object_exist(conn,newname,NULL);
3944
3945         if(!replace_if_exists && dest_exists) {
3946                 DEBUG(3,("rename_internals_fsp: dest exists doing rename %s -> %s\n",
3947                         fsp->fsp_name,newname));
3948                 return NT_STATUS_OBJECT_NAME_COLLISION;
3949         }
3950
3951         error = can_rename(conn,newname,attrs,&sbuf);
3952
3953         if (dest_exists && !NT_STATUS_IS_OK(error)) {
3954                 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3955                         nt_errstr(error), fsp->fsp_name,newname));
3956                 if (NT_STATUS_EQUAL(error,NT_STATUS_SHARING_VIOLATION))
3957                         error = NT_STATUS_ACCESS_DENIED;
3958                 return error;
3959         }
3960
3961         if(SMB_VFS_RENAME(conn,fsp->fsp_name, newname) == 0) {
3962                 DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n",
3963                         fsp->fsp_name,newname));
3964                 rename_open_files(conn, fsp->dev, fsp->inode, newname);
3965                 return NT_STATUS_OK;    
3966         }
3967
3968         if (errno == ENOTDIR || errno == EISDIR)
3969                 error = NT_STATUS_OBJECT_NAME_COLLISION;
3970         else
3971                 error = map_nt_error_from_unix(errno);
3972                 
3973         DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
3974                 nt_errstr(error), fsp->fsp_name,newname));
3975
3976         return error;
3977 }
3978
3979 /****************************************************************************
3980  The guts of the rename command, split out so it may be called by the NT SMB
3981  code. 
3982 ****************************************************************************/
3983
3984 NTSTATUS rename_internals(connection_struct *conn, char *name, char *newname, uint16 attrs, BOOL replace_if_exists)
3985 {
3986         pstring directory;
3987         pstring mask;
3988         pstring last_component_src;
3989         pstring last_component_dest;
3990         char *p;
3991         BOOL has_wild;
3992         BOOL bad_path_src = False;
3993         BOOL bad_path_dest = False;
3994         int count=0;
3995         NTSTATUS error = NT_STATUS_OK;
3996         BOOL rc = True;
3997         BOOL rcdest = True;
3998         SMB_STRUCT_STAT sbuf1, sbuf2;
3999
4000         *directory = *mask = 0;
4001
4002         ZERO_STRUCT(sbuf1);
4003         ZERO_STRUCT(sbuf2);
4004
4005         rc = unix_convert(name,conn,last_component_src,&bad_path_src,&sbuf1);
4006         if (!rc && bad_path_src) {
4007                 if (ms_has_wild(last_component_src))
4008                         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4009                 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
4010         }
4011
4012         /* Quick check for "." and ".." */
4013         if (last_component_src[0] == '.') {
4014                 if (!last_component_src[1] || (last_component_src[1] == '.' && !last_component_src[2])) {
4015                         return NT_STATUS_OBJECT_NAME_INVALID;
4016                 }
4017         }
4018
4019         rcdest = unix_convert(newname,conn,last_component_dest,&bad_path_dest,&sbuf2);
4020
4021         /* Quick check for "." and ".." */
4022         if (last_component_dest[0] == '.') {
4023                 if (!last_component_dest[1] || (last_component_dest[1] == '.' && !last_component_dest[2])) {
4024                         return NT_STATUS_OBJECT_NAME_INVALID;
4025                 }
4026         }
4027
4028         /*
4029          * Split the old name into directory and last component
4030          * strings. Note that unix_convert may have stripped off a 
4031          * leading ./ from both name and newname if the rename is 
4032          * at the root of the share. We need to make sure either both
4033          * name and newname contain a / character or neither of them do
4034          * as this is checked in resolve_wildcards().
4035          */
4036
4037         p = strrchr_m(name,'/');
4038         if (!p) {
4039                 pstrcpy(directory,".");
4040                 pstrcpy(mask,name);
4041         } else {
4042                 *p = 0;
4043                 pstrcpy(directory,name);
4044                 pstrcpy(mask,p+1);
4045                 *p = '/'; /* Replace needed for exceptional test below. */
4046         }
4047
4048         /*
4049          * We should only check the mangled cache
4050          * here if unix_convert failed. This means
4051          * that the path in 'mask' doesn't exist
4052          * on the file system and so we need to look
4053          * for a possible mangle. This patch from
4054          * Tine Smukavec <valentin.smukavec@hermes.si>.
4055          */
4056
4057         if (!rc && mangle_is_mangled(mask,SNUM(conn)))
4058                 mangle_check_cache( mask, sizeof(pstring)-1, SNUM(conn));
4059
4060         has_wild = ms_has_wild(mask);
4061
4062         if (!has_wild) {
4063                 /*
4064                  * No wildcards - just process the one file.
4065                  */
4066                 BOOL is_short_name = mangle_is_8_3(name, True, SNUM(conn));
4067
4068                 /* Add a terminating '/' to the directory name. */
4069                 pstrcat(directory,"/");
4070                 pstrcat(directory,mask);
4071                 
4072                 /* Ensure newname contains a '/' also */
4073                 if(strrchr_m(newname,'/') == 0) {
4074                         pstring tmpstr;
4075                         
4076                         pstrcpy(tmpstr, "./");
4077                         pstrcat(tmpstr, newname);
4078                         pstrcpy(newname, tmpstr);
4079                 }
4080                 
4081                 DEBUG(3,("rename_internals: case_sensitive = %d, case_preserve = %d, short case preserve = %d, \
4082 directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n", 
4083                          conn->case_sensitive, conn->case_preserve, conn->short_case_preserve, directory, 
4084                          newname, last_component_dest, is_short_name));
4085
4086                 /*
4087                  * Check for special case with case preserving and not
4088                  * case sensitive, if directory and newname are identical,
4089                  * and the old last component differs from the original
4090                  * last component only by case, then we should allow
4091                  * the rename (user is trying to change the case of the
4092                  * filename).
4093                  */
4094                 if((conn->case_sensitive == False) && 
4095                    (((conn->case_preserve == True) && 
4096                      (is_short_name == False)) || 
4097                     ((conn->short_case_preserve == True) && 
4098                      (is_short_name == True))) &&
4099                    strcsequal(directory, newname)) {
4100                         pstring modified_last_component;
4101
4102                         /*
4103                          * Get the last component of the modified name.
4104                          * Note that we guarantee that newname contains a '/'
4105                          * character above.
4106                          */
4107                         p = strrchr_m(newname,'/');
4108                         pstrcpy(modified_last_component,p+1);
4109                         
4110                         if(strcsequal(modified_last_component, 
4111                                       last_component_dest) == False) {
4112                                 /*
4113                                  * Replace the modified last component with
4114                                  * the original.
4115                                  */
4116                                 pstrcpy(p+1, last_component_dest);
4117                         }
4118                 }
4119         
4120                 resolve_wildcards(directory,newname);
4121         
4122                 /*
4123                  * The source object must exist.
4124                  */
4125
4126                 if (!vfs_object_exist(conn, directory, &sbuf1)) {
4127                         DEBUG(3,("rename_internals: source doesn't exist doing rename %s -> %s\n",
4128                                 directory,newname));
4129
4130                         if (errno == ENOTDIR || errno == EISDIR || errno == ENOENT) {
4131                                 /*
4132                                  * Must return different errors depending on whether the parent
4133                                  * directory existed or not.
4134                                  */
4135
4136                                 p = strrchr_m(directory, '/');
4137                                 if (!p)
4138                                         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4139                                 *p = '\0';
4140                                 if (vfs_object_exist(conn, directory, NULL))
4141                                         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4142                                 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
4143                         }
4144                         error = map_nt_error_from_unix(errno);
4145                         DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
4146                                 nt_errstr(error), directory,newname));
4147
4148                         return error;
4149                 }
4150
4151                 if (!rcdest && bad_path_dest) {
4152                         if (ms_has_wild(last_component_dest))
4153                                 return NT_STATUS_OBJECT_NAME_INVALID;
4154                         return NT_STATUS_OBJECT_PATH_NOT_FOUND;
4155                 }
4156
4157                 error = can_rename(conn,directory,attrs,&sbuf1);
4158
4159                 if (!NT_STATUS_IS_OK(error)) {
4160                         DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
4161                                 nt_errstr(error), directory,newname));
4162                         return error;
4163                 }
4164
4165                 /*
4166                  * If the src and dest names are identical - including case,
4167                  * don't do the rename, just return success.
4168                  */
4169
4170                 if (strcsequal(directory, newname)) {
4171                         rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
4172                         DEBUG(3,("rename_internals: identical names in rename %s - returning success\n", directory));
4173                         return NT_STATUS_OK;
4174                 }
4175
4176                 if(!replace_if_exists && vfs_object_exist(conn,newname,NULL)) {
4177                         DEBUG(3,("rename_internals: dest exists doing rename %s -> %s\n",
4178                                 directory,newname));
4179                         return NT_STATUS_OBJECT_NAME_COLLISION;
4180                 }
4181
4182                 if(SMB_VFS_RENAME(conn,directory, newname) == 0) {
4183                         DEBUG(3,("rename_internals: succeeded doing rename on %s -> %s\n",
4184                                 directory,newname));
4185                         rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
4186                         return NT_STATUS_OK;    
4187                 }
4188
4189                 if (errno == ENOTDIR || errno == EISDIR)
4190                         error = NT_STATUS_OBJECT_NAME_COLLISION;
4191                 else
4192                         error = map_nt_error_from_unix(errno);
4193                 
4194                 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
4195                         nt_errstr(error), directory,newname));
4196
4197                 return error;
4198         } else {
4199                 /*
4200                  * Wildcards - process each file that matches.
4201                  */
4202                 struct smb_Dir *dir_hnd = NULL;
4203                 const char *dname;
4204                 pstring destname;
4205                 
4206                 if (check_name(directory,conn))
4207                         dir_hnd = OpenDir(conn, directory);
4208                 
4209                 if (dir_hnd) {
4210                         long offset = 0;
4211                         error = NT_STATUS_NO_SUCH_FILE;
4212 /*                      Was error = NT_STATUS_OBJECT_NAME_NOT_FOUND; - gentest fix. JRA */
4213                         
4214                         if (strequal(mask,"????????.???"))
4215                                 pstrcpy(mask,"*");
4216                         
4217                         while ((dname = ReadDirName(dir_hnd, &offset))) {
4218                                 pstring fname;
4219                                 BOOL sysdir_entry = False;
4220
4221                                 pstrcpy(fname,dname);
4222                                 
4223                                 /* Quick check for "." and ".." */
4224                                 if (fname[0] == '.') {
4225                                         if (!fname[1] || (fname[1] == '.' && !fname[2])) {
4226                                                 if (attrs & aDIR) {
4227                                                         sysdir_entry = True;
4228                                                 } else {
4229                                                         continue;
4230                                                 }
4231                                         }
4232                                 }
4233
4234                                 if (!is_visible_file(conn, directory, dname, &sbuf1, False))
4235                                         continue;
4236
4237                                 if(!mask_match(fname, mask, conn->case_sensitive))
4238                                         continue;
4239                                 
4240                                 if (sysdir_entry) {
4241                                         error = NT_STATUS_OBJECT_NAME_INVALID;
4242                                         break;
4243                                 }
4244
4245                                 error = NT_STATUS_ACCESS_DENIED;
4246                                 slprintf(fname,sizeof(fname)-1,"%s/%s",directory,dname);
4247                                 if (!vfs_object_exist(conn, fname, &sbuf1)) {
4248                                         error = NT_STATUS_OBJECT_NAME_NOT_FOUND;
4249                                         DEBUG(6,("rename %s failed. Error %s\n", fname, nt_errstr(error)));
4250                                         continue;
4251                                 }
4252                                 error = can_rename(conn,fname,attrs,&sbuf1);
4253                                 if (!NT_STATUS_IS_OK(error)) {
4254                                         DEBUG(6,("rename %s refused\n", fname));
4255                                         continue;
4256                                 }
4257                                 pstrcpy(destname,newname);
4258                                 
4259                                 if (!resolve_wildcards(fname,destname)) {
4260                                         DEBUG(6,("resolve_wildcards %s %s failed\n", 
4261                                                  fname, destname));
4262                                         continue;
4263                                 }
4264                                 
4265                                 if (strcsequal(fname,destname)) {
4266                                         rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
4267                                         DEBUG(3,("rename_internals: identical names in wildcard rename %s - success\n", fname));
4268                                         count++;
4269                                         error = NT_STATUS_OK;
4270                                         continue;
4271                                 }
4272
4273                                 if (!replace_if_exists && 
4274                                     vfs_file_exist(conn,destname, NULL)) {
4275                                         DEBUG(6,("file_exist %s\n", destname));
4276                                         error = NT_STATUS_OBJECT_NAME_COLLISION;
4277                                         continue;
4278                                 }
4279                                 
4280                                 if (!SMB_VFS_RENAME(conn,fname,destname)) {
4281                                         rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
4282                                         count++;
4283                                         error = NT_STATUS_OK;
4284                                 }
4285                                 DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname));
4286                         }
4287                         CloseDir(dir_hnd);
4288                 }
4289
4290                 if (!NT_STATUS_EQUAL(error,NT_STATUS_NO_SUCH_FILE)) {
4291                         if (!rcdest && bad_path_dest) {
4292                                 if (ms_has_wild(last_component_dest))
4293                                         return NT_STATUS_OBJECT_NAME_INVALID;
4294                                 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
4295                         }
4296                 }
4297         }
4298         
4299         if (count == 0 && NT_STATUS_IS_OK(error)) {
4300                 error = map_nt_error_from_unix(errno);
4301         }
4302         
4303         return error;
4304 }
4305
4306 /****************************************************************************
4307  Reply to a mv.
4308 ****************************************************************************/
4309
4310 int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, 
4311              int dum_buffsize)
4312 {
4313         int outsize = 0;
4314         pstring name;
4315         pstring newname;
4316         char *p;
4317         uint16 attrs = SVAL(inbuf,smb_vwv0);
4318         NTSTATUS status;
4319
4320         START_PROFILE(SMBmv);
4321
4322         p = smb_buf(inbuf) + 1;
4323         p += srvstr_get_path(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status, True);
4324         if (!NT_STATUS_IS_OK(status)) {
4325                 END_PROFILE(SMBmv);
4326                 return ERROR_NT(status);
4327         }
4328         p++;
4329         p += srvstr_get_path(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, True);
4330         if (!NT_STATUS_IS_OK(status)) {
4331                 END_PROFILE(SMBmv);
4332                 return ERROR_NT(status);
4333         }
4334         
4335         RESOLVE_DFSPATH_WCARD(name, conn, inbuf, outbuf);
4336         RESOLVE_DFSPATH_WCARD(newname, conn, inbuf, outbuf);
4337         
4338         DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
4339         
4340         status = rename_internals(conn, name, newname, attrs, False);
4341         if (!NT_STATUS_IS_OK(status)) {
4342                 END_PROFILE(SMBmv);
4343                 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
4344                         /* We have re-scheduled this call. */
4345                         return -1;
4346                 }
4347                 return ERROR_NT(status);
4348         }
4349
4350         /*
4351          * Win2k needs a changenotify request response before it will
4352          * update after a rename..
4353          */     
4354         process_pending_change_notify_queue((time_t)0);
4355         outsize = set_message(outbuf,0,0,True);
4356   
4357         END_PROFILE(SMBmv);
4358         return(outsize);
4359 }
4360
4361 /*******************************************************************
4362  Copy a file as part of a reply_copy.
4363 ******************************************************************/
4364
4365 static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
4366                       int count,BOOL target_is_directory, int *err_ret)
4367 {
4368         int Access,action;
4369         SMB_STRUCT_STAT src_sbuf, sbuf2;
4370         SMB_OFF_T ret=-1;
4371         files_struct *fsp1,*fsp2;
4372         pstring dest;
4373         uint32 dosattrs;
4374  
4375         *err_ret = 0;
4376
4377         pstrcpy(dest,dest1);
4378         if (target_is_directory) {
4379                 char *p = strrchr_m(src,'/');
4380                 if (p) 
4381                         p++;
4382                 else
4383                         p = src;
4384                 pstrcat(dest,"/");
4385                 pstrcat(dest,p);
4386         }
4387
4388         if (!vfs_file_exist(conn,src,&src_sbuf))
4389                 return(False);
4390
4391         fsp1 = open_file_shared(conn,src,&src_sbuf,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
4392                                         (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),FILE_ATTRIBUTE_NORMAL,INTERNAL_OPEN_ONLY,
4393                                         &Access,&action);
4394
4395         if (!fsp1)
4396                 return(False);
4397
4398         if (!target_is_directory && count)
4399                 ofun = FILE_EXISTS_OPEN;
4400
4401         dosattrs = dos_mode(conn, src, &src_sbuf);
4402         if (SMB_VFS_STAT(conn,dest,&sbuf2) == -1)
4403                 ZERO_STRUCTP(&sbuf2);
4404
4405         fsp2 = open_file_shared(conn,dest,&sbuf2,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_WRONLY),
4406                         ofun,dosattrs,INTERNAL_OPEN_ONLY,&Access,&action);
4407
4408         if (!fsp2) {
4409                 close_file(fsp1,False);
4410                 return(False);
4411         }
4412
4413         if ((ofun&3) == 1) {
4414                 if(SMB_VFS_LSEEK(fsp2,fsp2->fd,0,SEEK_END) == -1) {
4415                         DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
4416                         /*
4417                          * Stop the copy from occurring.
4418                          */
4419                         ret = -1;
4420                         src_sbuf.st_size = 0;
4421                 }
4422         }
4423   
4424         if (src_sbuf.st_size)
4425                 ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_size);
4426
4427         close_file(fsp1,False);
4428
4429         /* Ensure the modtime is set correctly on the destination file. */
4430         fsp_set_pending_modtime( fsp2, src_sbuf.st_mtime);
4431
4432         /*
4433          * As we are opening fsp1 read-only we only expect
4434          * an error on close on fsp2 if we are out of space.
4435          * Thus we don't look at the error return from the
4436          * close of fsp1.
4437          */
4438         *err_ret = close_file(fsp2,False);
4439
4440         return(ret == (SMB_OFF_T)src_sbuf.st_size);
4441 }
4442
4443 /****************************************************************************
4444  Reply to a file copy.
4445 ****************************************************************************/
4446
4447 int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4448 {
4449         int outsize = 0;
4450         pstring name;
4451         pstring directory;
4452         pstring mask,newname;
4453         char *p;
4454         int count=0;
4455         int error = ERRnoaccess;
4456         int err = 0;
4457         BOOL has_wild;
4458         BOOL exists=False;
4459         int tid2 = SVAL(inbuf,smb_vwv0);
4460         int ofun = SVAL(inbuf,smb_vwv1);
4461         int flags = SVAL(inbuf,smb_vwv2);
4462         BOOL target_is_directory=False;
4463         BOOL bad_path1 = False;
4464         BOOL bad_path2 = False;
4465         BOOL rc = True;
4466         SMB_STRUCT_STAT sbuf1, sbuf2;
4467         NTSTATUS status;
4468
4469         START_PROFILE(SMBcopy);
4470
4471         *directory = *mask = 0;
4472
4473         p = smb_buf(inbuf);
4474         p += srvstr_get_path(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status, True);
4475         if (!NT_STATUS_IS_OK(status)) {
4476                 END_PROFILE(SMBcopy);
4477                 return ERROR_NT(status);
4478         }
4479         p += srvstr_get_path(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, True);
4480         if (!NT_STATUS_IS_OK(status)) {
4481                 END_PROFILE(SMBcopy);
4482                 return ERROR_NT(status);
4483         }
4484    
4485         DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
4486    
4487         if (tid2 != conn->cnum) {
4488                 /* can't currently handle inter share copies XXXX */
4489                 DEBUG(3,("Rejecting inter-share copy\n"));
4490                 END_PROFILE(SMBcopy);
4491                 return ERROR_DOS(ERRSRV,ERRinvdevice);
4492         }
4493
4494         RESOLVE_DFSPATH_WCARD(name, conn, inbuf, outbuf);
4495         RESOLVE_DFSPATH_WCARD(newname, conn, inbuf, outbuf);
4496
4497         rc = unix_convert(name,conn,0,&bad_path1,&sbuf1);
4498         unix_convert(newname,conn,0,&bad_path2,&sbuf2);
4499
4500         target_is_directory = VALID_STAT_OF_DIR(sbuf2);
4501
4502         if ((flags&1) && target_is_directory) {
4503                 END_PROFILE(SMBcopy);
4504                 return ERROR_DOS(ERRDOS,ERRbadfile);
4505         }
4506
4507         if ((flags&2) && !target_is_directory) {
4508                 END_PROFILE(SMBcopy);
4509                 return ERROR_DOS(ERRDOS,ERRbadpath);
4510         }
4511
4512         if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) {
4513                 /* wants a tree copy! XXXX */
4514                 DEBUG(3,("Rejecting tree copy\n"));
4515                 END_PROFILE(SMBcopy);
4516                 return ERROR_DOS(ERRSRV,ERRerror);
4517         }
4518
4519         p = strrchr_m(name,'/');
4520         if (!p) {
4521                 pstrcpy(directory,"./");
4522                 pstrcpy(mask,name);
4523         } else {
4524                 *p = 0;
4525                 pstrcpy(directory,name);
4526                 pstrcpy(mask,p+1);
4527         }
4528
4529         /*
4530          * We should only check the mangled cache
4531          * here if unix_convert failed. This means
4532          * that the path in 'mask' doesn't exist
4533          * on the file system and so we need to look
4534          * for a possible mangle. This patch from
4535          * Tine Smukavec <valentin.smukavec@hermes.si>.
4536          */
4537
4538         if (!rc && mangle_is_mangled(mask, SNUM(conn)))
4539                 mangle_check_cache( mask, sizeof(pstring)-1, SNUM(conn));
4540
4541         has_wild = ms_has_wild(mask);
4542
4543         if (!has_wild) {
4544                 pstrcat(directory,"/");
4545                 pstrcat(directory,mask);
4546                 if (resolve_wildcards(directory,newname) &&
4547                                 copy_file(directory,newname,conn,ofun, count,target_is_directory,&err))
4548                         count++;
4549                 if(!count && err) {
4550                         errno = err;
4551                         END_PROFILE(SMBcopy);
4552                         return(UNIXERROR(ERRHRD,ERRgeneral));
4553                 }
4554                 if (!count) {
4555                         exists = vfs_file_exist(conn,directory,NULL);
4556                 }
4557         } else {
4558                 struct smb_Dir *dir_hnd = NULL;
4559                 const char *dname;
4560                 pstring destname;
4561
4562                 if (check_name(directory,conn))
4563                         dir_hnd = OpenDir(conn, directory);
4564
4565                 if (dir_hnd) {
4566                         long offset = 0;
4567                         error = ERRbadfile;
4568
4569                         if (strequal(mask,"????????.???"))
4570                                 pstrcpy(mask,"*");
4571
4572                         while ((dname = ReadDirName(dir_hnd, &offset))) {
4573                                 pstring fname;
4574                                 pstrcpy(fname,dname);
4575     
4576                                 if (!is_visible_file(conn, directory, dname, &sbuf1, False))
4577                                         continue;
4578
4579                                 if(!mask_match(fname, mask, conn->case_sensitive))
4580                                         continue;
4581
4582                                 error = ERRnoaccess;
4583                                 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
4584                                 pstrcpy(destname,newname);
4585                                 if (resolve_wildcards(fname,destname) && 
4586                                                 copy_file(fname,destname,conn,ofun,
4587                                                 count,target_is_directory,&err))
4588                                         count++;
4589                                 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
4590                         }
4591                         CloseDir(dir_hnd);
4592                 }
4593         }
4594   
4595         if (count == 0) {
4596                 if(err) {
4597                         /* Error on close... */
4598                         errno = err;
4599                         END_PROFILE(SMBcopy);
4600                         return(UNIXERROR(ERRHRD,ERRgeneral));
4601                 }
4602
4603                 if (exists) {
4604                         END_PROFILE(SMBcopy);
4605                         return ERROR_DOS(ERRDOS,error);
4606                 } else {
4607                         if((errno == ENOENT) && (bad_path1 || bad_path2)) {
4608                                 set_saved_error_triple(ERRDOS, ERRbadpath, NT_STATUS_OK);
4609                         }
4610                         END_PROFILE(SMBcopy);
4611                         return(UNIXERROR(ERRDOS,error));
4612                 }
4613         }
4614   
4615         outsize = set_message(outbuf,1,0,True);
4616         SSVAL(outbuf,smb_vwv0,count);
4617
4618         END_PROFILE(SMBcopy);
4619         return(outsize);
4620 }
4621
4622 /****************************************************************************
4623  Reply to a setdir.
4624 ****************************************************************************/
4625
4626 int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4627 {
4628         int snum;
4629         int outsize = 0;
4630         BOOL ok = False;
4631         pstring newdir;
4632         NTSTATUS status;
4633
4634         START_PROFILE(pathworks_setdir);
4635   
4636         snum = SNUM(conn);
4637         if (!CAN_SETDIR(snum)) {
4638                 END_PROFILE(pathworks_setdir);
4639                 return ERROR_DOS(ERRDOS,ERRnoaccess);
4640         }
4641
4642         srvstr_get_path(inbuf, newdir, smb_buf(inbuf) + 1, sizeof(newdir), 0, STR_TERMINATE, &status, False);
4643         if (!NT_STATUS_IS_OK(status)) {
4644                 END_PROFILE(pathworks_setdir);
4645                 return ERROR_NT(status);
4646         }
4647   
4648         RESOLVE_DFSPATH(newdir, conn, inbuf, outbuf);
4649
4650         if (strlen(newdir) == 0) {
4651                 ok = True;
4652         } else {
4653                 ok = vfs_directory_exist(conn,newdir,NULL);
4654                 if (ok)
4655                         string_set(&conn->connectpath,newdir);
4656         }
4657   
4658         if (!ok) {
4659                 END_PROFILE(pathworks_setdir);
4660                 return ERROR_DOS(ERRDOS,ERRbadpath);
4661         }
4662   
4663         outsize = set_message(outbuf,0,0,True);
4664         SCVAL(outbuf,smb_reh,CVAL(inbuf,smb_reh));
4665   
4666         DEBUG(3,("setdir %s\n", newdir));
4667
4668         END_PROFILE(pathworks_setdir);
4669         return(outsize);
4670 }
4671
4672 #undef DBGC_CLASS
4673 #define DBGC_CLASS DBGC_LOCKING
4674
4675 /****************************************************************************
4676  Get a lock pid, dealing with large count requests.
4677 ****************************************************************************/
4678
4679 uint16 get_lock_pid( char *data, int data_offset, BOOL large_file_format)
4680 {
4681         if(!large_file_format)
4682                 return SVAL(data,SMB_LPID_OFFSET(data_offset));
4683         else
4684                 return SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
4685 }
4686
4687 /****************************************************************************
4688  Get a lock count, dealing with large count requests.
4689 ****************************************************************************/
4690
4691 SMB_BIG_UINT get_lock_count( char *data, int data_offset, BOOL large_file_format)
4692 {
4693         SMB_BIG_UINT count = 0;
4694
4695         if(!large_file_format) {
4696                 count = (SMB_BIG_UINT)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
4697         } else {
4698
4699 #if defined(HAVE_LONGLONG)
4700                 count = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
4701                         ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
4702 #else /* HAVE_LONGLONG */
4703
4704                 /*
4705                  * NT4.x seems to be broken in that it sends large file (64 bit)
4706                  * lockingX calls even if the CAP_LARGE_FILES was *not*
4707                  * negotiated. For boxes without large unsigned ints truncate the
4708                  * lock count by dropping the top 32 bits.
4709                  */
4710
4711                 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
4712                         DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
4713                                 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
4714                                 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
4715                                 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
4716                 }
4717
4718                 count = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
4719 #endif /* HAVE_LONGLONG */
4720         }
4721
4722         return count;
4723 }
4724
4725 #if !defined(HAVE_LONGLONG)
4726 /****************************************************************************
4727  Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
4728 ****************************************************************************/
4729
4730 static uint32 map_lock_offset(uint32 high, uint32 low)
4731 {
4732         unsigned int i;
4733         uint32 mask = 0;
4734         uint32 highcopy = high;
4735  
4736         /*
4737          * Try and find out how many significant bits there are in high.
4738          */
4739  
4740         for(i = 0; highcopy; i++)
4741                 highcopy >>= 1;
4742  
4743         /*
4744          * We use 31 bits not 32 here as POSIX
4745          * lock offsets may not be negative.
4746          */
4747  
4748         mask = (~0) << (31 - i);
4749  
4750         if(low & mask)
4751                 return 0; /* Fail. */
4752  
4753         high <<= (31 - i);
4754  
4755         return (high|low);
4756 }
4757 #endif /* !defined(HAVE_LONGLONG) */
4758
4759 /****************************************************************************
4760  Get a lock offset, dealing with large offset requests.
4761 ****************************************************************************/
4762
4763 SMB_BIG_UINT get_lock_offset( char *data, int data_offset, BOOL large_file_format, BOOL *err)
4764 {
4765         SMB_BIG_UINT offset = 0;
4766
4767         *err = False;
4768
4769         if(!large_file_format) {
4770                 offset = (SMB_BIG_UINT)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
4771         } else {
4772
4773 #if defined(HAVE_LONGLONG)
4774                 offset = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
4775                                 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
4776 #else /* HAVE_LONGLONG */
4777
4778                 /*
4779                  * NT4.x seems to be broken in that it sends large file (64 bit)
4780                  * lockingX calls even if the CAP_LARGE_FILES was *not*
4781                  * negotiated. For boxes without large unsigned ints mangle the
4782                  * lock offset by mapping the top 32 bits onto the lower 32.
4783                  */
4784       
4785                 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
4786                         uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
4787                         uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
4788                         uint32 new_low = 0;
4789
4790                         if((new_low = map_lock_offset(high, low)) == 0) {
4791                                 *err = True;
4792                                 return (SMB_BIG_UINT)-1;
4793                         }
4794
4795                         DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
4796                                 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
4797                         SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
4798                         SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
4799                 }
4800
4801                 offset = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
4802 #endif /* HAVE_LONGLONG */
4803         }
4804
4805         return offset;
4806 }
4807
4808 /****************************************************************************
4809  Reply to a lockingX request.
4810 ****************************************************************************/
4811
4812 int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
4813 {
4814         files_struct *fsp = file_fsp(inbuf,smb_vwv2);
4815         unsigned char locktype = CVAL(inbuf,smb_vwv3);
4816         unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
4817         uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
4818         uint16 num_locks = SVAL(inbuf,smb_vwv7);
4819         SMB_BIG_UINT count = 0, offset = 0;
4820         uint16 lock_pid;
4821         int32 lock_timeout = IVAL(inbuf,smb_vwv4);
4822         int i;
4823         char *data;
4824         BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
4825         BOOL err;
4826         BOOL my_lock_ctx = False;
4827         NTSTATUS status;
4828
4829         START_PROFILE(SMBlockingX);
4830         
4831         CHECK_FSP(fsp,conn);
4832         
4833         data = smb_buf(inbuf);
4834
4835         if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
4836                 /* we don't support these - and CANCEL_LOCK makes w2k
4837                    and XP reboot so I don't really want to be
4838                    compatible! (tridge) */
4839                 return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
4840         }
4841         
4842         if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
4843                 /* Need to make this like a cancel.... JRA. */
4844                 return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
4845         }
4846         
4847         /* Check if this is an oplock break on a file
4848            we have granted an oplock on.
4849         */
4850         if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
4851                 /* Client can insist on breaking to none. */
4852                 BOOL break_to_none = (oplocklevel == 0);
4853                 
4854                 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client for fnum = %d\n",
4855                          (unsigned int)oplocklevel, fsp->fnum ));
4856
4857                 /*
4858                  * Make sure we have granted an exclusive or batch oplock on this file.
4859                  */
4860                 
4861                 if(!EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
4862                         DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \
4863 no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name));
4864
4865                         /* if this is a pure oplock break request then don't send a reply */
4866                         if (num_locks == 0 && num_ulocks == 0) {
4867                                 END_PROFILE(SMBlockingX);
4868                                 return -1;
4869                         } else {
4870                                 END_PROFILE(SMBlockingX);
4871                                 return ERROR_DOS(ERRDOS,ERRlock);
4872                         }
4873                 }
4874
4875                 if (remove_oplock(fsp, break_to_none) == False) {
4876                         DEBUG(0,("reply_lockingX: error in removing oplock on file %s\n",
4877                                  fsp->fsp_name ));
4878                 }
4879                 
4880                 /* if this is a pure oplock break request then don't send a reply */
4881                 if (num_locks == 0 && num_ulocks == 0) {
4882                         /* Sanity check - ensure a pure oplock break is not a
4883                            chained request. */
4884                         if(CVAL(inbuf,smb_vwv0) != 0xff)
4885                                 DEBUG(0,("reply_lockingX: Error : pure oplock break is a chained %d request !\n",
4886                                          (unsigned int)CVAL(inbuf,smb_vwv0) ));
4887                         END_PROFILE(SMBlockingX);
4888                         return -1;
4889                 }
4890         }
4891
4892         /*
4893          * We do this check *after* we have checked this is not a oplock break
4894          * response message. JRA.
4895          */
4896         
4897         release_level_2_oplocks_on_change(fsp);
4898         
4899         /* Data now points at the beginning of the list
4900            of smb_unlkrng structs */
4901         for(i = 0; i < (int)num_ulocks; i++) {
4902                 lock_pid = get_lock_pid( data, i, large_file_format);
4903                 count = get_lock_count( data, i, large_file_format);
4904                 offset = get_lock_offset( data, i, large_file_format, &err);
4905                 
4906                 /*
4907                  * There is no error code marked "stupid client bug".... :-).
4908                  */
4909                 if(err) {
4910                         END_PROFILE(SMBlockingX);
4911                         return ERROR_DOS(ERRDOS,ERRnoaccess);
4912                 }
4913
4914                 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for pid %u, file %s\n",
4915                           (double)offset, (double)count, (unsigned int)lock_pid, fsp->fsp_name ));
4916                 
4917                 status = do_unlock(fsp,conn,lock_pid,count,offset);
4918                 if (NT_STATUS_V(status)) {
4919                         END_PROFILE(SMBlockingX);
4920                         return ERROR_NT(status);
4921                 }
4922         }
4923
4924         /* Setup the timeout in seconds. */
4925
4926         lock_timeout = ((lock_timeout == -1) ? -1 : (lock_timeout+999)/1000);
4927         
4928         /* Now do any requested locks */
4929         data += ((large_file_format ? 20 : 10)*num_ulocks);
4930         
4931         /* Data now points at the beginning of the list
4932            of smb_lkrng structs */
4933         
4934         for(i = 0; i < (int)num_locks; i++) {
4935                 lock_pid = get_lock_pid( data, i, large_file_format);
4936                 count = get_lock_count( data, i, large_file_format);
4937                 offset = get_lock_offset( data, i, large_file_format, &err);
4938                 
4939                 /*
4940                  * There is no error code marked "stupid client bug".... :-).
4941                  */
4942                 if(err) {
4943                         END_PROFILE(SMBlockingX);
4944                         return ERROR_DOS(ERRDOS,ERRnoaccess);
4945                 }
4946                 
4947                 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid %u, file %s timeout = %d\n",
4948                         (double)offset, (double)count, (unsigned int)lock_pid,
4949                         fsp->fsp_name, (int)lock_timeout ));
4950                 
4951                 status = do_lock_spin(fsp,conn,lock_pid, count,offset, 
4952                                  ((locktype & 1) ? READ_LOCK : WRITE_LOCK), &my_lock_ctx);
4953                 if (NT_STATUS_V(status)) {
4954                         /*
4955                          * Interesting fact found by IFSTEST /t LockOverlappedTest...
4956                          * Even if it's our own lock context, we need to wait here as
4957                          * there may be an unlock on the way.
4958                          * So I removed a "&& !my_lock_ctx" from the following
4959                          * if statement. JRA.
4960                          */
4961                         if ((lock_timeout != 0) && lp_blocking_locks(SNUM(conn)) && ERROR_WAS_LOCK_DENIED(status)) {
4962                                 /*
4963                                  * A blocking lock was requested. Package up
4964                                  * this smb into a queued request and push it
4965                                  * onto the blocking lock queue.
4966                                  */
4967                                 if(push_blocking_lock_request(inbuf, length, lock_timeout, i, lock_pid, offset, count)) {
4968                                         END_PROFILE(SMBlockingX);
4969                                         return -1;
4970                                 }
4971                         }
4972                         break;
4973                 }
4974         }
4975         
4976         /* If any of the above locks failed, then we must unlock
4977            all of the previous locks (X/Open spec). */
4978         if (i != num_locks && num_locks != 0) {
4979                 /*
4980                  * Ensure we don't do a remove on the lock that just failed,
4981                  * as under POSIX rules, if we have a lock already there, we
4982                  * will delete it (and we shouldn't) .....
4983                  */
4984                 for(i--; i >= 0; i--) {
4985                         lock_pid = get_lock_pid( data, i, large_file_format);
4986                         count = get_lock_count( data, i, large_file_format);
4987                         offset = get_lock_offset( data, i, large_file_format, &err);
4988                         
4989                         /*
4990                          * There is no error code marked "stupid client bug".... :-).
4991                          */
4992                         if(err) {
4993                                 END_PROFILE(SMBlockingX);
4994                                 return ERROR_DOS(ERRDOS,ERRnoaccess);
4995                         }
4996                         
4997                         do_unlock(fsp,conn,lock_pid,count,offset);
4998                 }
4999                 END_PROFILE(SMBlockingX);
5000                 return ERROR_NT(status);
5001         }
5002
5003         set_message(outbuf,2,0,True);
5004         
5005         DEBUG( 3, ( "lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
5006                     fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks ) );
5007         
5008         END_PROFILE(SMBlockingX);
5009         return chain_reply(inbuf,outbuf,length,bufsize);
5010 }
5011
5012 #undef DBGC_CLASS
5013 #define DBGC_CLASS DBGC_ALL
5014
5015 /****************************************************************************
5016  Reply to a SMBreadbmpx (read block multiplex) request.
5017 ****************************************************************************/
5018
5019 int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
5020 {
5021         ssize_t nread = -1;
5022         ssize_t total_read;
5023         char *data;
5024         SMB_OFF_T startpos;
5025         int outsize;
5026         size_t maxcount;
5027         int max_per_packet;
5028         size_t tcount;
5029         int pad;
5030         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5031         START_PROFILE(SMBreadBmpx);
5032
5033         /* this function doesn't seem to work - disable by default */
5034         if (!lp_readbmpx()) {
5035                 END_PROFILE(SMBreadBmpx);
5036                 return ERROR_DOS(ERRSRV,ERRuseSTD);
5037         }
5038
5039         outsize = set_message(outbuf,8,0,True);
5040
5041         CHECK_FSP(fsp,conn);
5042         CHECK_READ(fsp);
5043
5044         startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
5045         maxcount = SVAL(inbuf,smb_vwv3);
5046
5047         data = smb_buf(outbuf);
5048         pad = ((long)data)%4;
5049         if (pad)
5050                 pad = 4 - pad;
5051         data += pad;
5052
5053         max_per_packet = bufsize-(outsize+pad);
5054         tcount = maxcount;
5055         total_read = 0;
5056
5057         if (is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK)) {
5058                 END_PROFILE(SMBreadBmpx);
5059                 return ERROR_DOS(ERRDOS,ERRlock);
5060         }
5061
5062         do {
5063                 size_t N = MIN(max_per_packet,tcount-total_read);
5064   
5065                 nread = read_file(fsp,data,startpos,N);
5066
5067                 if (nread <= 0)
5068                         nread = 0;
5069
5070                 if (nread < (ssize_t)N)
5071                         tcount = total_read + nread;
5072
5073                 set_message(outbuf,8,nread,False);
5074                 SIVAL(outbuf,smb_vwv0,startpos);
5075                 SSVAL(outbuf,smb_vwv2,tcount);
5076                 SSVAL(outbuf,smb_vwv6,nread);
5077                 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
5078
5079                 if (!send_smb(smbd_server_fd(),outbuf))
5080                         exit_server("reply_readbmpx: send_smb failed.");
5081
5082                 total_read += nread;
5083                 startpos += nread;
5084         } while (total_read < (ssize_t)tcount);
5085
5086         END_PROFILE(SMBreadBmpx);
5087         return(-1);
5088 }
5089
5090 /****************************************************************************
5091  Reply to a SMBsetattrE.
5092 ****************************************************************************/
5093
5094 int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
5095 {
5096         struct utimbuf unix_times;
5097         int outsize = 0;
5098         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5099         START_PROFILE(SMBsetattrE);
5100
5101         outsize = set_message(outbuf,0,0,True);
5102
5103         if(!fsp || (fsp->conn != conn)) {
5104                 END_PROFILE(SMBgetattrE);
5105                 return ERROR_DOS(ERRDOS,ERRbadfid);
5106         }
5107
5108         /*
5109          * Convert the DOS times into unix times. Ignore create
5110          * time as UNIX can't set this.
5111          */
5112
5113         unix_times.actime = make_unix_date2(inbuf+smb_vwv3);
5114         unix_times.modtime = make_unix_date2(inbuf+smb_vwv5);
5115   
5116         /* 
5117          * Patch from Ray Frush <frush@engr.colostate.edu>
5118          * Sometimes times are sent as zero - ignore them.
5119          */
5120
5121         if (null_mtime(unix_times.actime) && null_mtime(unix_times.modtime)) {
5122                 /* Ignore request */
5123                 if( DEBUGLVL( 3 ) ) {
5124                         dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
5125                         dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
5126                 }
5127                 END_PROFILE(SMBsetattrE);
5128                 return(outsize);
5129         } else if (!null_mtime(unix_times.actime) && null_mtime(unix_times.modtime)) {
5130                 /* set modify time = to access time if modify time was unset */
5131                 unix_times.modtime = unix_times.actime;
5132         }
5133
5134         /* Set the date on this file */
5135         /* Should we set pending modtime here ? JRA */
5136         if(file_utime(conn, fsp->fsp_name, &unix_times)) {
5137                 END_PROFILE(SMBsetattrE);
5138                 return ERROR_DOS(ERRDOS,ERRnoaccess);
5139         }
5140   
5141         DEBUG( 3, ( "reply_setattrE fnum=%d actime=%d modtime=%d\n",
5142                 fsp->fnum, (int)unix_times.actime, (int)unix_times.modtime ) );
5143
5144         END_PROFILE(SMBsetattrE);
5145         return(outsize);
5146 }
5147
5148
5149 /* Back from the dead for OS/2..... JRA. */
5150
5151 /****************************************************************************
5152  Reply to a SMBwritebmpx (write block multiplex primary) request.
5153 ****************************************************************************/
5154
5155 int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
5156 {
5157         size_t numtowrite;
5158         ssize_t nwritten = -1;
5159         int outsize = 0;
5160         SMB_OFF_T startpos;
5161         size_t tcount;
5162         BOOL write_through;
5163         int smb_doff;
5164         char *data;
5165         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5166         START_PROFILE(SMBwriteBmpx);
5167
5168         CHECK_FSP(fsp,conn);
5169         CHECK_WRITE(fsp);
5170         if (HAS_CACHED_ERROR(fsp)) {
5171                 return(CACHED_ERROR(fsp));
5172         }
5173
5174         tcount = SVAL(inbuf,smb_vwv1);
5175         startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
5176         write_through = BITSETW(inbuf+smb_vwv7,0);
5177         numtowrite = SVAL(inbuf,smb_vwv10);
5178         smb_doff = SVAL(inbuf,smb_vwv11);
5179
5180         data = smb_base(inbuf) + smb_doff;
5181
5182         /* If this fails we need to send an SMBwriteC response,
5183                 not an SMBwritebmpx - set this up now so we don't forget */
5184         SCVAL(outbuf,smb_com,SMBwritec);
5185
5186         if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos,WRITE_LOCK)) {
5187                 END_PROFILE(SMBwriteBmpx);
5188                 return(ERROR_DOS(ERRDOS,ERRlock));
5189         }
5190
5191         nwritten = write_file(fsp,data,startpos,numtowrite);
5192
5193         if(lp_syncalways(SNUM(conn)) || write_through)
5194                 sync_file(conn,fsp);
5195   
5196         if(nwritten < (ssize_t)numtowrite) {
5197                 END_PROFILE(SMBwriteBmpx);
5198                 return(UNIXERROR(ERRHRD,ERRdiskfull));
5199         }
5200
5201         /* If the maximum to be written to this file
5202                 is greater than what we just wrote then set
5203                 up a secondary struct to be attached to this
5204                 fd, we will use this to cache error messages etc. */
5205
5206         if((ssize_t)tcount > nwritten) {
5207                 write_bmpx_struct *wbms;
5208                 if(fsp->wbmpx_ptr != NULL)
5209                         wbms = fsp->wbmpx_ptr; /* Use an existing struct */
5210                 else
5211                         wbms = SMB_MALLOC_P(write_bmpx_struct);
5212                 if(!wbms) {
5213                         DEBUG(0,("Out of memory in reply_readmpx\n"));
5214                         END_PROFILE(SMBwriteBmpx);
5215                         return(ERROR_DOS(ERRSRV,ERRnoresource));
5216                 }
5217                 wbms->wr_mode = write_through;
5218                 wbms->wr_discard = False; /* No errors yet */
5219                 wbms->wr_total_written = nwritten;
5220                 wbms->wr_errclass = 0;
5221                 wbms->wr_error = 0;
5222                 fsp->wbmpx_ptr = wbms;
5223         }
5224
5225         /* We are returning successfully, set the message type back to
5226                 SMBwritebmpx */
5227         SCVAL(outbuf,smb_com,SMBwriteBmpx);
5228   
5229         outsize = set_message(outbuf,1,0,True);
5230   
5231         SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
5232   
5233         DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
5234                         fsp->fnum, (int)numtowrite, (int)nwritten ) );
5235
5236         if (write_through && tcount==nwritten) {
5237                 /* We need to send both a primary and a secondary response */
5238                 smb_setlen(outbuf,outsize - 4);
5239                 if (!send_smb(smbd_server_fd(),outbuf))
5240                         exit_server("reply_writebmpx: send_smb failed.");
5241
5242                 /* Now the secondary */
5243                 outsize = set_message(outbuf,1,0,True);
5244                 SCVAL(outbuf,smb_com,SMBwritec);
5245                 SSVAL(outbuf,smb_vwv0,nwritten);
5246         }
5247
5248         END_PROFILE(SMBwriteBmpx);
5249         return(outsize);
5250 }
5251
5252 /****************************************************************************
5253  Reply to a SMBwritebs (write block multiplex secondary) request.
5254 ****************************************************************************/
5255
5256 int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
5257 {
5258         size_t numtowrite;
5259         ssize_t nwritten = -1;
5260         int outsize = 0;
5261         SMB_OFF_T startpos;
5262         size_t tcount;
5263         BOOL write_through;
5264         int smb_doff;
5265         char *data;
5266         write_bmpx_struct *wbms;
5267         BOOL send_response = False; 
5268         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5269         START_PROFILE(SMBwriteBs);
5270
5271         CHECK_FSP(fsp,conn);
5272         CHECK_WRITE(fsp);
5273
5274         tcount = SVAL(inbuf,smb_vwv1);
5275         startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
5276         numtowrite = SVAL(inbuf,smb_vwv6);
5277         smb_doff = SVAL(inbuf,smb_vwv7);
5278
5279         data = smb_base(inbuf) + smb_doff;
5280
5281         /* We need to send an SMBwriteC response, not an SMBwritebs */
5282         SCVAL(outbuf,smb_com,SMBwritec);
5283
5284         /* This fd should have an auxiliary struct attached,
5285                 check that it does */
5286         wbms = fsp->wbmpx_ptr;
5287         if(!wbms) {
5288                 END_PROFILE(SMBwriteBs);
5289                 return(-1);
5290         }
5291
5292         /* If write through is set we can return errors, else we must cache them */
5293         write_through = wbms->wr_mode;
5294
5295         /* Check for an earlier error */
5296         if(wbms->wr_discard) {
5297                 END_PROFILE(SMBwriteBs);
5298                 return -1; /* Just discard the packet */
5299         }
5300
5301         nwritten = write_file(fsp,data,startpos,numtowrite);
5302
5303         if(lp_syncalways(SNUM(conn)) || write_through)
5304                 sync_file(conn,fsp);
5305   
5306         if (nwritten < (ssize_t)numtowrite) {
5307                 if(write_through) {
5308                         /* We are returning an error - we can delete the aux struct */
5309                         if (wbms)
5310                                 free((char *)wbms);
5311                         fsp->wbmpx_ptr = NULL;
5312                         END_PROFILE(SMBwriteBs);
5313                         return(ERROR_DOS(ERRHRD,ERRdiskfull));
5314                 }
5315                 wbms->wr_errclass = ERRHRD;
5316                 wbms->wr_error = ERRdiskfull;
5317                 wbms->wr_status = NT_STATUS_DISK_FULL;
5318                 wbms->wr_discard = True;
5319                 END_PROFILE(SMBwriteBs);
5320                 return -1;
5321         }
5322
5323         /* Increment the total written, if this matches tcount
5324                 we can discard the auxiliary struct (hurrah !) and return a writeC */
5325         wbms->wr_total_written += nwritten;
5326         if(wbms->wr_total_written >= tcount) {
5327                 if (write_through) {
5328                         outsize = set_message(outbuf,1,0,True);
5329                         SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);    
5330                         send_response = True;
5331                 }
5332
5333                 free((char *)wbms);
5334                 fsp->wbmpx_ptr = NULL;
5335         }
5336
5337         if(send_response) {
5338                 END_PROFILE(SMBwriteBs);
5339                 return(outsize);
5340         }
5341
5342         END_PROFILE(SMBwriteBs);
5343         return(-1);
5344 }
5345
5346 /****************************************************************************
5347  Reply to a SMBgetattrE.
5348 ****************************************************************************/
5349
5350 int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
5351 {
5352         SMB_STRUCT_STAT sbuf;
5353         int outsize = 0;
5354         int mode;
5355         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5356         START_PROFILE(SMBgetattrE);
5357
5358         outsize = set_message(outbuf,11,0,True);
5359
5360         if(!fsp || (fsp->conn != conn)) {
5361                 END_PROFILE(SMBgetattrE);
5362                 return ERROR_DOS(ERRDOS,ERRbadfid);
5363         }
5364
5365         /* Do an fstat on this file */
5366         if(fsp_stat(fsp, &sbuf)) {
5367                 END_PROFILE(SMBgetattrE);
5368                 return(UNIXERROR(ERRDOS,ERRnoaccess));
5369         }
5370   
5371         mode = dos_mode(conn,fsp->fsp_name,&sbuf);
5372   
5373         /*
5374          * Convert the times into dos times. Set create
5375          * date to be last modify date as UNIX doesn't save
5376          * this.
5377          */
5378
5379         put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
5380         put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
5381         /* Should we check pending modtime here ? JRA */
5382         put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
5383
5384         if (mode & aDIR) {
5385                 SIVAL(outbuf,smb_vwv6,0);
5386                 SIVAL(outbuf,smb_vwv8,0);
5387         } else {
5388                 uint32 allocation_size = get_allocation_size(conn,fsp, &sbuf);
5389                 SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
5390                 SIVAL(outbuf,smb_vwv8,allocation_size);
5391         }
5392         SSVAL(outbuf,smb_vwv10, mode);
5393   
5394         DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
5395   
5396         END_PROFILE(SMBgetattrE);
5397         return(outsize);
5398 }