r15018: Merge Volker's ipc/trans2/nttrans changes over
[sfrench/samba-autobuild/.git] / source / 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 unsigned int smb_echo_count = 0;
34 extern uint32 global_client_caps;
35
36 extern struct current_user current_user;
37 extern BOOL global_encrypted_passwords_negotiated;
38
39 /****************************************************************************
40  Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
41  We're assuming here that '/' is not the second byte in any multibyte char
42  set (a safe assumption). '\\' *may* be the second byte in a multibyte char
43  set.
44 ****************************************************************************/
45
46 NTSTATUS check_path_syntax(pstring destname, const pstring srcname)
47 {
48         char *d = destname;
49         const char *s = srcname;
50         NTSTATUS ret = NT_STATUS_OK;
51         BOOL start_of_name_component = True;
52         unsigned int num_bad_components = 0;
53
54         while (*s) {
55                 if (IS_DIRECTORY_SEP(*s)) {
56                         /*
57                          * Safe to assume is not the second part of a mb char as this is handled below.
58                          */
59                         /* Eat multiple '/' or '\\' */
60                         while (IS_DIRECTORY_SEP(*s)) {
61                                 s++;
62                         }
63                         if ((d != destname) && (*s != '\0')) {
64                                 /* We only care about non-leading or trailing '/' or '\\' */
65                                 *d++ = '/';
66                         }
67
68                         start_of_name_component = True;
69                         continue;
70                 }
71
72                 if (start_of_name_component) {
73                         if ((s[0] == '.') && (s[1] == '.') && (IS_DIRECTORY_SEP(s[2]) || s[2] == '\0')) {
74                                 /* Uh oh - "/../" or "\\..\\"  or "/..\0" or "\\..\0" ! */
75
76                                 /*
77                                  * No mb char starts with '.' so we're safe checking the directory separator here.
78                                  */
79
80                                 /* If  we just added a '/' - delete it */
81                                 if ((d > destname) && (*(d-1) == '/')) {
82                                         *(d-1) = '\0';
83                                         d--;
84                                 }
85
86                                 /* Are we at the start ? Can't go back further if so. */
87                                 if (d <= destname) {
88                                         ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
89                                         break;
90                                 }
91                                 /* Go back one level... */
92                                 /* We know this is safe as '/' cannot be part of a mb sequence. */
93                                 /* NOTE - if this assumption is invalid we are not in good shape... */
94                                 /* Decrement d first as d points to the *next* char to write into. */
95                                 for (d--; d > destname; d--) {
96                                         if (*d == '/')
97                                                 break;
98                                 }
99                                 s += 2; /* Else go past the .. */
100                                 /* We're still at the start of a name component, just the previous one. */
101
102                                 if (num_bad_components) {
103                                         /* Hmmm. Should we only decrement the bad_components if
104                                            we're removing a bad component ? Need to check this. JRA. */
105                                         num_bad_components--;
106                                 }
107
108                                 continue;
109
110                         } else if ((s[0] == '.') && ((s[1] == '\0') || IS_DIRECTORY_SEP(s[1]))) {
111                                 /* Component of pathname can't be "." only. */
112                                 ret =  NT_STATUS_OBJECT_NAME_INVALID;
113                                 num_bad_components++;
114                                 *d++ = *s++;
115                                 continue;
116                         }
117                 }
118
119                 if (!(*s & 0x80)) {
120                         if (*s <= 0x1f) {
121                                 return NT_STATUS_OBJECT_NAME_INVALID;
122                         }
123                         switch (*s) {
124                                 case '*':
125                                 case '?':
126                                 case '<':
127                                 case '>':
128                                 case '"':
129                                         return NT_STATUS_OBJECT_NAME_INVALID;
130                                 default:
131                                         *d++ = *s++;
132                                         break;
133                         }
134                 } else {
135                         switch(next_mb_char_size(s)) {
136                                 case 4:
137                                         *d++ = *s++;
138                                 case 3:
139                                         *d++ = *s++;
140                                 case 2:
141                                         *d++ = *s++;
142                                 case 1:
143                                         *d++ = *s++;
144                                         break;
145                                 default:
146                                         DEBUG(0,("check_path_syntax: character length assumptions invalid !\n"));
147                                         *d = '\0';
148                                         return NT_STATUS_INVALID_PARAMETER;
149                         }
150                 }
151                 if (start_of_name_component && num_bad_components) {
152                         num_bad_components++;
153                 }
154                 start_of_name_component = False;
155         }
156
157         if (NT_STATUS_EQUAL(ret, NT_STATUS_OBJECT_NAME_INVALID)) {
158                 if (num_bad_components > 1) {
159                         ret = NT_STATUS_OBJECT_PATH_NOT_FOUND;
160                 }
161         }
162
163         *d = '\0';
164         return ret;
165 }
166
167 /****************************************************************************
168  Ensure we check the path in *exactly* the same way as W2K for a findfirst/findnext
169  path or anything including wildcards.
170  We're assuming here that '/' is not the second byte in any multibyte char
171  set (a safe assumption). '\\' *may* be the second byte in a multibyte char
172  set.
173 ****************************************************************************/
174
175 NTSTATUS check_path_syntax_wcard(pstring destname, const pstring srcname, BOOL *p_contains_wcard)
176 {
177         char *d = destname;
178         const char *s = srcname;
179         NTSTATUS ret = NT_STATUS_OK;
180         BOOL start_of_name_component = True;
181         unsigned int num_bad_components = 0;
182
183         *p_contains_wcard = False;
184
185         while (*s) {
186                 if (IS_DIRECTORY_SEP(*s)) {
187                         /*
188                          * Safe to assume is not the second part of a mb char as this is handled below.
189                          */
190                         /* Eat multiple '/' or '\\' */
191                         while (IS_DIRECTORY_SEP(*s)) {
192                                 s++;
193                         }
194                         if ((d != destname) && (*s != '\0')) {
195                                 /* We only care about non-leading or trailing '/' or '\\' */
196                                 *d++ = '/';
197                         }
198
199                         start_of_name_component = True;
200                         continue;
201                 }
202
203                 if (start_of_name_component) {
204                         if ((s[0] == '.') && (s[1] == '.') && (IS_DIRECTORY_SEP(s[2]) || s[2] == '\0')) {
205                                 /* Uh oh - "/../" or "\\..\\"  or "/..\0" or "\\..\0" ! */
206
207                                 /*
208                                  * No mb char starts with '.' so we're safe checking the directory separator here.
209                                  */
210
211                                 /* If  we just added a '/' - delete it */
212                                 if ((d > destname) && (*(d-1) == '/')) {
213                                         *(d-1) = '\0';
214                                         d--;
215                                 }
216
217                                 /* Are we at the start ? Can't go back further if so. */
218                                 if (d <= destname) {
219                                         ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
220                                         break;
221                                 }
222                                 /* Go back one level... */
223                                 /* We know this is safe as '/' cannot be part of a mb sequence. */
224                                 /* NOTE - if this assumption is invalid we are not in good shape... */
225                                 /* Decrement d first as d points to the *next* char to write into. */
226                                 for (d--; d > destname; d--) {
227                                         if (*d == '/')
228                                                 break;
229                                 }
230                                 s += 2; /* Else go past the .. */
231                                 /* We're still at the start of a name component, just the previous one. */
232
233                                 if (num_bad_components) {
234                                         /* Hmmm. Should we only decrement the bad_components if
235                                            we're removing a bad component ? Need to check this. JRA. */
236                                         num_bad_components--;
237                                 }
238
239                                 continue;
240
241                         } else if ((s[0] == '.') && ((s[1] == '\0') || IS_DIRECTORY_SEP(s[1]))) {
242                                 /* Component of pathname can't be "." only. */
243                                 ret =  NT_STATUS_OBJECT_NAME_INVALID;
244                                 num_bad_components++;
245                                 *d++ = *s++;
246                                 continue;
247                         }
248                 }
249
250                 if (!(*s & 0x80)) {
251                         if (*s <= 0x1f) {
252                                 return NT_STATUS_OBJECT_NAME_INVALID;
253                         }
254                         if (!*p_contains_wcard) {
255                                 switch (*s) {
256                                         case '*':
257                                         case '?':
258                                         case '<':
259                                         case '>':
260                                         case '"':
261                                                 *p_contains_wcard = True;
262                                                 break;
263                                         default:
264                                                 break;
265                                 }
266                         }
267                         *d++ = *s++;
268                 } else {
269                         switch(next_mb_char_size(s)) {
270                                 case 4:
271                                         *d++ = *s++;
272                                         /*fall through*/
273                                 case 3:
274                                         *d++ = *s++;
275                                         /*fall through*/
276                                 case 2:
277                                         *d++ = *s++;
278                                         /*fall through*/
279                                 case 1:
280                                         *d++ = *s++;
281                                         break;
282                                 default:
283                                         DEBUG(0,("check_path_syntax_wcard: character length assumptions invalid !\n"));
284                                         *d = '\0';
285                                         return NT_STATUS_INVALID_PARAMETER;
286                         }
287                 }
288                 if (start_of_name_component && num_bad_components) {
289                         num_bad_components++;
290                 }
291                 start_of_name_component = False;
292         }
293
294         if (NT_STATUS_EQUAL(ret, NT_STATUS_OBJECT_NAME_INVALID)) {
295                 /* For some strange reason being called from findfirst changes
296                    the num_components number to cause the error return to change. JRA. */
297                 if (num_bad_components > 2) {
298                         ret = NT_STATUS_OBJECT_PATH_NOT_FOUND;
299                 }
300         }
301
302         *d = '\0';
303         return ret;
304 }
305
306 /****************************************************************************
307  Check the path for a POSIX client.
308  We're assuming here that '/' is not the second byte in any multibyte char
309  set (a safe assumption).
310 ****************************************************************************/
311
312 NTSTATUS check_path_syntax_posix(pstring destname, const pstring srcname)
313 {
314         char *d = destname;
315         const char *s = srcname;
316         NTSTATUS ret = NT_STATUS_OK;
317         BOOL start_of_name_component = True;
318
319         while (*s) {
320                 if (*s == '/') {
321                         /*
322                          * Safe to assume is not the second part of a mb char as this is handled below.
323                          */
324                         /* Eat multiple '/' or '\\' */
325                         while (*s == '/') {
326                                 s++;
327                         }
328                         if ((d != destname) && (*s != '\0')) {
329                                 /* We only care about non-leading or trailing '/' */
330                                 *d++ = '/';
331                         }
332
333                         start_of_name_component = True;
334                         continue;
335                 }
336
337                 if (start_of_name_component) {
338                         if ((s[0] == '.') && (s[1] == '.') && (s[2] == '/' || s[2] == '\0')) {
339                                 /* Uh oh - "/../" or "/..\0" ! */
340
341                                 /*
342                                  * No mb char starts with '.' so we're safe checking the directory separator here.
343                                  */
344
345                                 /* If  we just added a '/' - delete it */
346                                 if ((d > destname) && (*(d-1) == '/')) {
347                                         *(d-1) = '\0';
348                                         d--;
349                                 }
350
351                                 /* Are we at the start ? Can't go back further if so. */
352                                 if (d <= destname) {
353                                         ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
354                                         break;
355                                 }
356                                 /* Go back one level... */
357                                 /* We know this is safe as '/' cannot be part of a mb sequence. */
358                                 /* NOTE - if this assumption is invalid we are not in good shape... */
359                                 /* Decrement d first as d points to the *next* char to write into. */
360                                 for (d--; d > destname; d--) {
361                                         if (*d == '/')
362                                                 break;
363                                 }
364                                 s += 2; /* Else go past the .. */
365                                 continue;
366
367                         } else if ((s[0] == '.') && ((s[1] == '\0') || (s[1] == '/'))) {
368                                 /* Eat the '.' */
369                                 s++;
370                                 continue;
371                         }
372                 }
373
374                 if (!(*s & 0x80)) {
375                         *d++ = *s++;
376                 } else {
377                         switch(next_mb_char_size(s)) {
378                                 case 4:
379                                         *d++ = *s++;
380                                         /*fall through*/
381                                 case 3:
382                                         *d++ = *s++;
383                                         /*fall through*/
384                                 case 2:
385                                         *d++ = *s++;
386                                         /*fall through*/
387                                 case 1:
388                                         *d++ = *s++;
389                                         break;
390                                 default:
391                                         DEBUG(0,("check_path_syntax_posix: character length assumptions invalid !\n"));
392                                         *d = '\0';
393                                         return NT_STATUS_INVALID_PARAMETER;
394                         }
395                 }
396                 start_of_name_component = False;
397         }
398
399         *d = '\0';
400         return ret;
401 }
402
403 /****************************************************************************
404  Pull a string and check the path allowing a wilcard - provide for error return.
405 ****************************************************************************/
406
407 size_t srvstr_get_path_wcard(char *inbuf, char *dest, const char *src, size_t dest_len, size_t src_len, int flags,
408                                 NTSTATUS *err, BOOL *contains_wcard)
409 {
410         pstring tmppath;
411         char *tmppath_ptr = tmppath;
412         size_t ret;
413 #ifdef DEVELOPER
414         SMB_ASSERT(dest_len == sizeof(pstring));
415 #endif
416
417         if (src_len == 0) {
418                 ret = srvstr_pull_buf( inbuf, tmppath_ptr, src, dest_len, flags);
419         } else {
420                 ret = srvstr_pull( inbuf, tmppath_ptr, src, dest_len, src_len, flags);
421         }
422
423         *contains_wcard = False;
424
425         if (lp_posix_pathnames()) {
426                 *err = check_path_syntax_posix(dest, tmppath);
427         } else {
428                 *err = check_path_syntax_wcard(dest, tmppath, contains_wcard);
429         }
430         return ret;
431 }
432
433 /****************************************************************************
434  Pull a string and check the path - provide for error return.
435 ****************************************************************************/
436
437 size_t srvstr_get_path(char *inbuf, char *dest, const char *src, size_t dest_len, size_t src_len, int flags, NTSTATUS *err)
438 {
439         pstring tmppath;
440         char *tmppath_ptr = tmppath;
441         size_t ret;
442 #ifdef DEVELOPER
443         SMB_ASSERT(dest_len == sizeof(pstring));
444 #endif
445
446         if (src_len == 0) {
447                 ret = srvstr_pull_buf( inbuf, tmppath_ptr, src, dest_len, flags);
448         } else {
449                 ret = srvstr_pull( inbuf, tmppath_ptr, src, dest_len, src_len, flags);
450         }
451         if (lp_posix_pathnames()) {
452                 *err = check_path_syntax_posix(dest, tmppath);
453         } else {
454                 *err = check_path_syntax(dest, tmppath);
455         }
456         return ret;
457 }
458
459 /****************************************************************************
460  Reply to a special message.
461 ****************************************************************************/
462
463 int reply_special(char *inbuf,char *outbuf)
464 {
465         int outsize = 4;
466         int msg_type = CVAL(inbuf,0);
467         int msg_flags = CVAL(inbuf,1);
468         fstring name1,name2;
469         char name_type = 0;
470         
471         static BOOL already_got_session = False;
472
473         *name1 = *name2 = 0;
474         
475         memset(outbuf,'\0',smb_size);
476
477         smb_setlen(outbuf,0);
478         
479         switch (msg_type) {
480         case 0x81: /* session request */
481                 
482                 if (already_got_session) {
483                         exit_server("multiple session request not permitted");
484                 }
485                 
486                 SCVAL(outbuf,0,0x82);
487                 SCVAL(outbuf,3,0);
488                 if (name_len(inbuf+4) > 50 || 
489                     name_len(inbuf+4 + name_len(inbuf + 4)) > 50) {
490                         DEBUG(0,("Invalid name length in session request\n"));
491                         return(0);
492                 }
493                 name_extract(inbuf,4,name1);
494                 name_type = name_extract(inbuf,4 + name_len(inbuf + 4),name2);
495                 DEBUG(2,("netbios connect: name1=%s name2=%s\n",
496                          name1,name2));      
497
498                 set_local_machine_name(name1, True);
499                 set_remote_machine_name(name2, True);
500
501                 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
502                          get_local_machine_name(), get_remote_machine_name(),
503                          name_type));
504
505                 if (name_type == 'R') {
506                         /* We are being asked for a pathworks session --- 
507                            no thanks! */
508                         SCVAL(outbuf, 0,0x83);
509                         break;
510                 }
511
512                 /* only add the client's machine name to the list
513                    of possibly valid usernames if we are operating
514                    in share mode security */
515                 if (lp_security() == SEC_SHARE) {
516                         add_session_user(get_remote_machine_name());
517                 }
518
519                 reload_services(True);
520                 reopen_logs();
521
522                 already_got_session = True;
523                 break;
524                 
525         case 0x89: /* session keepalive request 
526                       (some old clients produce this?) */
527                 SCVAL(outbuf,0,SMBkeepalive);
528                 SCVAL(outbuf,3,0);
529                 break;
530                 
531         case 0x82: /* positive session response */
532         case 0x83: /* negative session response */
533         case 0x84: /* retarget session response */
534                 DEBUG(0,("Unexpected session response\n"));
535                 break;
536                 
537         case SMBkeepalive: /* session keepalive */
538         default:
539                 return(0);
540         }
541         
542         DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
543                     msg_type, msg_flags));
544         
545         return(outsize);
546 }
547
548 /****************************************************************************
549  Reply to a tcon.
550 ****************************************************************************/
551
552 int reply_tcon(connection_struct *conn,
553                char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
554 {
555         const char *service;
556         pstring service_buf;
557         pstring password;
558         pstring dev;
559         int outsize = 0;
560         uint16 vuid = SVAL(inbuf,smb_uid);
561         int pwlen=0;
562         NTSTATUS nt_status;
563         char *p;
564         DATA_BLOB password_blob;
565         
566         START_PROFILE(SMBtcon);
567
568         *service_buf = *password = *dev = 0;
569
570         p = smb_buf(inbuf)+1;
571         p += srvstr_pull_buf(inbuf, service_buf, p, sizeof(service_buf), STR_TERMINATE) + 1;
572         pwlen = srvstr_pull_buf(inbuf, password, p, sizeof(password), STR_TERMINATE) + 1;
573         p += pwlen;
574         p += srvstr_pull_buf(inbuf, dev, p, sizeof(dev), STR_TERMINATE) + 1;
575
576         p = strrchr_m(service_buf,'\\');
577         if (p) {
578                 service = p+1;
579         } else {
580                 service = service_buf;
581         }
582
583         password_blob = data_blob(password, pwlen+1);
584
585         conn = make_connection(service,password_blob,dev,vuid,&nt_status);
586
587         data_blob_clear_free(&password_blob);
588   
589         if (!conn) {
590                 END_PROFILE(SMBtcon);
591                 return ERROR_NT(nt_status);
592         }
593   
594         outsize = set_message(outbuf,2,0,True);
595         SSVAL(outbuf,smb_vwv0,max_recv);
596         SSVAL(outbuf,smb_vwv1,conn->cnum);
597         SSVAL(outbuf,smb_tid,conn->cnum);
598   
599         DEBUG(3,("tcon service=%s cnum=%d\n", 
600                  service, conn->cnum));
601   
602         END_PROFILE(SMBtcon);
603         return(outsize);
604 }
605
606 /****************************************************************************
607  Reply to a tcon and X.
608 ****************************************************************************/
609
610 int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
611 {
612         fstring service;
613         DATA_BLOB password;
614
615         /* what the cleint thinks the device is */
616         fstring client_devicetype;
617         /* what the server tells the client the share represents */
618         const char *server_devicetype;
619         NTSTATUS nt_status;
620         uint16 vuid = SVAL(inbuf,smb_uid);
621         int passlen = SVAL(inbuf,smb_vwv3);
622         pstring path;
623         char *p, *q;
624         
625         START_PROFILE(SMBtconX);        
626
627         *service = *client_devicetype = 0;
628
629         /* we might have to close an old one */
630         if ((SVAL(inbuf,smb_vwv2) & 0x1) && conn) {
631                 close_cnum(conn,vuid);
632         }
633
634         if (passlen > MAX_PASS_LEN) {
635                 return ERROR_DOS(ERRDOS,ERRbuftoosmall);
636         }
637  
638         if (global_encrypted_passwords_negotiated) {
639                 password = data_blob(smb_buf(inbuf),passlen);
640         } else {
641                 password = data_blob(smb_buf(inbuf),passlen+1);
642                 /* Ensure correct termination */
643                 password.data[passlen]=0;    
644         }
645
646         p = smb_buf(inbuf) + passlen;
647         p += srvstr_pull_buf(inbuf, path, p, sizeof(path), STR_TERMINATE);
648
649         /*
650          * the service name can be either: \\server\share
651          * or share directly like on the DELL PowerVault 705
652          */
653         if (*path=='\\') {      
654                 q = strchr_m(path+2,'\\');
655                 if (!q) {
656                         END_PROFILE(SMBtconX);
657                         return(ERROR_DOS(ERRDOS,ERRnosuchshare));
658                 }
659                 fstrcpy(service,q+1);
660         }
661         else
662                 fstrcpy(service,path);
663                 
664         p += srvstr_pull(inbuf, client_devicetype, p, sizeof(client_devicetype), 6, STR_ASCII);
665
666         DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
667
668         conn = make_connection(service,password,client_devicetype,vuid,&nt_status);
669         
670         data_blob_clear_free(&password);
671
672         if (!conn) {
673                 END_PROFILE(SMBtconX);
674                 return ERROR_NT(nt_status);
675         }
676
677         if ( IS_IPC(conn) )
678                 server_devicetype = "IPC";
679         else if ( IS_PRINT(conn) )
680                 server_devicetype = "LPT1:";
681         else 
682                 server_devicetype = "A:";
683
684         if (Protocol < PROTOCOL_NT1) {
685                 set_message(outbuf,2,0,True);
686                 p = smb_buf(outbuf);
687                 p += srvstr_push(outbuf, p, server_devicetype, -1, 
688                                  STR_TERMINATE|STR_ASCII);
689                 set_message_end(outbuf,p);
690         } else {
691                 /* NT sets the fstype of IPC$ to the null string */
692                 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
693                 
694                 set_message(outbuf,3,0,True);
695
696                 p = smb_buf(outbuf);
697                 p += srvstr_push(outbuf, p, server_devicetype, -1, 
698                                  STR_TERMINATE|STR_ASCII);
699                 p += srvstr_push(outbuf, p, fstype, -1, 
700                                  STR_TERMINATE);
701                 
702                 set_message_end(outbuf,p);
703                 
704                 /* what does setting this bit do? It is set by NT4 and
705                    may affect the ability to autorun mounted cdroms */
706                 SSVAL(outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS|
707                                 (lp_csc_policy(SNUM(conn)) << 2));
708                 
709                 init_dfsroot(conn, inbuf, outbuf);
710         }
711
712   
713         DEBUG(3,("tconX service=%s \n",
714                  service));
715   
716         /* set the incoming and outgoing tid to the just created one */
717         SSVAL(inbuf,smb_tid,conn->cnum);
718         SSVAL(outbuf,smb_tid,conn->cnum);
719
720         END_PROFILE(SMBtconX);
721         return chain_reply(inbuf,outbuf,length,bufsize);
722 }
723
724 /****************************************************************************
725  Reply to an unknown type.
726 ****************************************************************************/
727
728 int reply_unknown(char *inbuf,char *outbuf)
729 {
730         int type;
731         type = CVAL(inbuf,smb_com);
732   
733         DEBUG(0,("unknown command type (%s): type=%d (0x%X)\n",
734                  smb_fn_name(type), type, type));
735   
736         return(ERROR_DOS(ERRSRV,ERRunknownsmb));
737 }
738
739 /****************************************************************************
740  Reply to an ioctl.
741 ****************************************************************************/
742
743 int reply_ioctl(connection_struct *conn,
744                 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
745 {
746         uint16 device     = SVAL(inbuf,smb_vwv1);
747         uint16 function   = SVAL(inbuf,smb_vwv2);
748         uint32 ioctl_code = (device << 16) + function;
749         int replysize, outsize;
750         char *p;
751         START_PROFILE(SMBioctl);
752
753         DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
754
755         switch (ioctl_code) {
756             case IOCTL_QUERY_JOB_INFO:
757                 replysize = 32;
758                 break;
759             default:
760                 END_PROFILE(SMBioctl);
761                 return(ERROR_DOS(ERRSRV,ERRnosupport));
762         }
763
764         outsize = set_message(outbuf,8,replysize+1,True);
765         SSVAL(outbuf,smb_vwv1,replysize); /* Total data bytes returned */
766         SSVAL(outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
767         SSVAL(outbuf,smb_vwv6,52);        /* Offset to data */
768         p = smb_buf(outbuf) + 1;          /* Allow for alignment */
769
770         switch (ioctl_code) {
771                 case IOCTL_QUERY_JOB_INFO:                  
772                 {
773                         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
774                         if (!fsp) {
775                                 END_PROFILE(SMBioctl);
776                                 return(UNIXERROR(ERRDOS,ERRbadfid));
777                         }
778                         SSVAL(p,0,fsp->rap_print_jobid);             /* Job number */
779                         srvstr_push(outbuf, p+2, global_myname(), 15, STR_TERMINATE|STR_ASCII);
780                         if (conn) {
781                                 srvstr_push(outbuf, p+18, lp_servicename(SNUM(conn)), 13, STR_TERMINATE|STR_ASCII);
782                         }
783                         break;
784                 }
785         }
786
787         END_PROFILE(SMBioctl);
788         return outsize;
789 }
790
791 /****************************************************************************
792  Reply to a chkpth.
793 ****************************************************************************/
794
795 int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
796 {
797         int outsize = 0;
798         pstring name;
799         BOOL ok = False;
800         BOOL bad_path = False;
801         SMB_STRUCT_STAT sbuf;
802         NTSTATUS status;
803
804         START_PROFILE(SMBchkpth);
805
806         srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
807         if (!NT_STATUS_IS_OK(status)) {
808                 END_PROFILE(SMBchkpth);
809                 return ERROR_NT(status);
810         }
811
812         RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
813
814         unix_convert(name,conn,0,&bad_path,&sbuf);
815         if (bad_path) {
816                 END_PROFILE(SMBchkpth);
817                 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
818         }
819
820         if (check_name(name,conn)) {
821                 if (VALID_STAT(sbuf) || SMB_VFS_STAT(conn,name,&sbuf) == 0)
822                         if (!(ok = S_ISDIR(sbuf.st_mode))) {
823                                 END_PROFILE(SMBchkpth);
824                                 return ERROR_BOTH(NT_STATUS_NOT_A_DIRECTORY,ERRDOS,ERRbadpath);
825                         }
826         }
827
828         if (!ok) {
829                 /* We special case this - as when a Windows machine
830                         is parsing a path is steps through the components
831                         one at a time - if a component fails it expects
832                         ERRbadpath, not ERRbadfile.
833                 */
834                 if(errno == ENOENT) {
835                         /*
836                          * Windows returns different error codes if
837                          * the parent directory is valid but not the
838                          * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
839                          * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
840                          * if the path is invalid. This is different from set_bad_path_error()
841                          * in the non-NT error case.
842                          */
843                         END_PROFILE(SMBchkpth);
844                         return ERROR_BOTH(NT_STATUS_OBJECT_NAME_NOT_FOUND,ERRDOS,ERRbadpath);
845                 }
846
847                 END_PROFILE(SMBchkpth);
848                 return(UNIXERROR(ERRDOS,ERRbadpath));
849         }
850
851         outsize = set_message(outbuf,0,0,True);
852         DEBUG(3,("chkpth %s mode=%d\n", name, (int)SVAL(inbuf,smb_vwv0)));
853
854         END_PROFILE(SMBchkpth);
855         return(outsize);
856 }
857
858 /****************************************************************************
859  Reply to a getatr.
860 ****************************************************************************/
861
862 int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
863 {
864         pstring fname;
865         int outsize = 0;
866         SMB_STRUCT_STAT sbuf;
867         BOOL ok = False;
868         int mode=0;
869         SMB_OFF_T size=0;
870         time_t mtime=0;
871         BOOL bad_path = False;
872         char *p;
873         NTSTATUS status;
874
875         START_PROFILE(SMBgetatr);
876
877         p = smb_buf(inbuf) + 1;
878         p += srvstr_get_path(inbuf, fname, p, sizeof(fname), 0, STR_TERMINATE, &status);
879         if (!NT_STATUS_IS_OK(status)) {
880                 END_PROFILE(SMBgetatr);
881                 return ERROR_NT(status);
882         }
883
884         RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
885   
886         /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
887                 under WfWg - weird! */
888         if (! (*fname)) {
889                 mode = aHIDDEN | aDIR;
890                 if (!CAN_WRITE(conn))
891                         mode |= aRONLY;
892                 size = 0;
893                 mtime = 0;
894                 ok = True;
895         } else {
896                 unix_convert(fname,conn,0,&bad_path,&sbuf);
897                 if (bad_path) {
898                         END_PROFILE(SMBgetatr);
899                         return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
900                 }
901                 if (check_name(fname,conn)) {
902                         if (VALID_STAT(sbuf) || SMB_VFS_STAT(conn,fname,&sbuf) == 0) {
903                                 mode = dos_mode(conn,fname,&sbuf);
904                                 size = sbuf.st_size;
905                                 mtime = sbuf.st_mtime;
906                                 if (mode & aDIR)
907                                         size = 0;
908                                 ok = True;
909                         } else {
910                                 DEBUG(3,("stat of %s failed (%s)\n",fname,strerror(errno)));
911                         }
912                 }
913         }
914   
915         if (!ok) {
916                 END_PROFILE(SMBgetatr);
917                 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadfile);
918         }
919  
920         outsize = set_message(outbuf,10,0,True);
921
922         SSVAL(outbuf,smb_vwv0,mode);
923         if(lp_dos_filetime_resolution(SNUM(conn)) ) {
924                 srv_put_dos_date3(outbuf,smb_vwv1,mtime & ~1);
925         } else {
926                 srv_put_dos_date3(outbuf,smb_vwv1,mtime);
927         }
928         SIVAL(outbuf,smb_vwv3,(uint32)size);
929
930         if (Protocol >= PROTOCOL_NT1) {
931                 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
932         }
933   
934         DEBUG( 3, ( "getatr name=%s mode=%d size=%d\n", fname, mode, (uint32)size ) );
935   
936         END_PROFILE(SMBgetatr);
937         return(outsize);
938 }
939
940 /****************************************************************************
941  Reply to a setatr.
942 ****************************************************************************/
943
944 int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
945 {
946         pstring fname;
947         int outsize = 0;
948         BOOL ok=False;
949         int mode;
950         time_t mtime;
951         SMB_STRUCT_STAT sbuf;
952         BOOL bad_path = False;
953         char *p;
954         NTSTATUS status;
955
956         START_PROFILE(SMBsetatr);
957
958         p = smb_buf(inbuf) + 1;
959         p += srvstr_get_path(inbuf, fname, p, sizeof(fname), 0, STR_TERMINATE, &status);
960         if (!NT_STATUS_IS_OK(status)) {
961                 END_PROFILE(SMBsetatr);
962                 return ERROR_NT(status);
963         }
964
965         RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
966   
967         unix_convert(fname,conn,0,&bad_path,&sbuf);
968         if (bad_path) {
969                 END_PROFILE(SMBsetatr);
970                 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
971         }
972
973         mode = SVAL(inbuf,smb_vwv0);
974         mtime = srv_make_unix_date3(inbuf+smb_vwv1);
975   
976         if (mode != FILE_ATTRIBUTE_NORMAL) {
977                 if (VALID_STAT_OF_DIR(sbuf))
978                         mode |= aDIR;
979                 else
980                         mode &= ~aDIR;
981
982                 if (check_name(fname,conn)) {
983                         ok = (file_set_dosmode(conn,fname,mode,&sbuf,False) == 0);
984                 }
985         } else {
986                 ok = True;
987         }
988
989         if (ok)
990                 ok = set_filetime(conn,fname,mtime);
991   
992         if (!ok) {
993                 END_PROFILE(SMBsetatr);
994                 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
995         }
996  
997         outsize = set_message(outbuf,0,0,True);
998   
999         DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
1000   
1001         END_PROFILE(SMBsetatr);
1002         return(outsize);
1003 }
1004
1005 /****************************************************************************
1006  Reply to a dskattr.
1007 ****************************************************************************/
1008
1009 int reply_dskattr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1010 {
1011         int outsize = 0;
1012         SMB_BIG_UINT dfree,dsize,bsize;
1013         START_PROFILE(SMBdskattr);
1014
1015         if (get_dfree_info(conn,".",True,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
1016                 END_PROFILE(SMBdskattr);
1017                 return(UNIXERROR(ERRHRD,ERRgeneral));
1018         }
1019   
1020         outsize = set_message(outbuf,5,0,True);
1021         
1022         if (Protocol <= PROTOCOL_LANMAN2) {
1023                 double total_space, free_space;
1024                 /* we need to scale this to a number that DOS6 can handle. We
1025                    use floating point so we can handle large drives on systems
1026                    that don't have 64 bit integers 
1027
1028                    we end up displaying a maximum of 2G to DOS systems
1029                 */
1030                 total_space = dsize * (double)bsize;
1031                 free_space = dfree * (double)bsize;
1032
1033                 dsize = (total_space+63*512) / (64*512);
1034                 dfree = (free_space+63*512) / (64*512);
1035                 
1036                 if (dsize > 0xFFFF) dsize = 0xFFFF;
1037                 if (dfree > 0xFFFF) dfree = 0xFFFF;
1038
1039                 SSVAL(outbuf,smb_vwv0,dsize);
1040                 SSVAL(outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
1041                 SSVAL(outbuf,smb_vwv2,512); /* and this must be 512 */
1042                 SSVAL(outbuf,smb_vwv3,dfree);
1043         } else {
1044                 SSVAL(outbuf,smb_vwv0,dsize);
1045                 SSVAL(outbuf,smb_vwv1,bsize/512);
1046                 SSVAL(outbuf,smb_vwv2,512);
1047                 SSVAL(outbuf,smb_vwv3,dfree);
1048         }
1049
1050         DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1051
1052         END_PROFILE(SMBdskattr);
1053         return(outsize);
1054 }
1055
1056 /****************************************************************************
1057  Reply to a search.
1058  Can be called from SMBsearch, SMBffirst or SMBfunique.
1059 ****************************************************************************/
1060
1061 int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1062 {
1063         pstring mask;
1064         pstring directory;
1065         pstring fname;
1066         SMB_OFF_T size;
1067         uint32 mode;
1068         time_t date;
1069         uint32 dirtype;
1070         int outsize = 0;
1071         unsigned int numentries = 0;
1072         unsigned int maxentries = 0;
1073         BOOL finished = False;
1074         char *p;
1075         BOOL ok = False;
1076         int status_len;
1077         pstring path;
1078         char status[21];
1079         int dptr_num= -1;
1080         BOOL check_descend = False;
1081         BOOL expect_close = False;
1082         BOOL can_open = True;
1083         BOOL bad_path = False;
1084         NTSTATUS nt_status;
1085         BOOL mask_contains_wcard = False;
1086         BOOL allow_long_path_components = (SVAL(inbuf,smb_flg2) & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
1087
1088         if (lp_posix_pathnames()) {
1089                 return reply_unknown(inbuf, outbuf);
1090         }
1091
1092         START_PROFILE(SMBsearch);
1093
1094         *mask = *directory = *fname = 0;
1095
1096         /* If we were called as SMBffirst then we must expect close. */
1097         if(CVAL(inbuf,smb_com) == SMBffirst)
1098                 expect_close = True;
1099   
1100         outsize = set_message(outbuf,1,3,True);
1101         maxentries = SVAL(inbuf,smb_vwv0); 
1102         dirtype = SVAL(inbuf,smb_vwv1);
1103         p = smb_buf(inbuf) + 1;
1104         p += srvstr_get_path_wcard(inbuf, path, p, sizeof(path), 0, STR_TERMINATE, &nt_status, &mask_contains_wcard);
1105         if (!NT_STATUS_IS_OK(nt_status)) {
1106                 END_PROFILE(SMBsearch);
1107                 return ERROR_NT(nt_status);
1108         }
1109
1110         RESOLVE_DFSPATH_WCARD(path, conn, inbuf, outbuf);
1111   
1112         p++;
1113         status_len = SVAL(p, 0);
1114         p += 2;
1115   
1116         /* dirtype &= ~aDIR; */
1117
1118         if (status_len == 0) {
1119                 SMB_STRUCT_STAT sbuf;
1120                 pstring dir2;
1121
1122                 pstrcpy(directory,path);
1123                 pstrcpy(dir2,path);
1124                 unix_convert(directory,conn,0,&bad_path,&sbuf);
1125                 unix_format(dir2);
1126
1127                 if (!check_name(directory,conn))
1128                         can_open = False;
1129
1130                 p = strrchr_m(dir2,'/');
1131                 if (p == NULL) {
1132                         pstrcpy(mask,dir2);
1133                         *dir2 = 0;
1134                 } else {
1135                         *p = 0;
1136                         pstrcpy(mask,p+1);
1137                 }
1138
1139                 p = strrchr_m(directory,'/');
1140                 if (!p) 
1141                         *directory = 0;
1142                 else
1143                         *p = 0;
1144
1145                 if (strlen(directory) == 0)
1146                         pstrcpy(directory,".");
1147                 memset((char *)status,'\0',21);
1148                 SCVAL(status,0,(dirtype & 0x1F));
1149         } else {
1150                 int status_dirtype;
1151
1152                 memcpy(status,p,21);
1153                 status_dirtype = CVAL(status,0) & 0x1F;
1154                 if (status_dirtype != (dirtype & 0x1F))
1155                         dirtype = status_dirtype;
1156
1157                 conn->dirptr = dptr_fetch(status+12,&dptr_num);      
1158                 if (!conn->dirptr)
1159                         goto SearchEmpty;
1160                 string_set(&conn->dirpath,dptr_path(dptr_num));
1161                 pstrcpy(mask, dptr_wcard(dptr_num));
1162         }
1163
1164         if (can_open) {
1165                 p = smb_buf(outbuf) + 3;
1166                 ok = True;
1167      
1168                 if (status_len == 0) {
1169                         dptr_num = dptr_create(conn,directory,True,expect_close,SVAL(inbuf,smb_pid), mask, mask_contains_wcard, dirtype);
1170                         if (dptr_num < 0) {
1171                                 if(dptr_num == -2) {
1172                                         END_PROFILE(SMBsearch);
1173                                         return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnofids);
1174                                 }
1175                                 END_PROFILE(SMBsearch);
1176                                 return ERROR_DOS(ERRDOS,ERRnofids);
1177                         }
1178                 } else {
1179                         dirtype = dptr_attr(dptr_num);
1180                 }
1181
1182                 DEBUG(4,("dptr_num is %d\n",dptr_num));
1183
1184                 if (ok) {
1185                         if ((dirtype&0x1F) == aVOLID) {   
1186                                 memcpy(p,status,21);
1187                                 make_dir_struct(p,"???????????",volume_label(SNUM(conn)),
1188                                                 0,aVOLID,0,!allow_long_path_components);
1189                                 dptr_fill(p+12,dptr_num);
1190                                 if (dptr_zero(p+12) && (status_len==0))
1191                                         numentries = 1;
1192                                 else
1193                                         numentries = 0;
1194                                 p += DIR_STRUCT_SIZE;
1195                         } else {
1196                                 unsigned int i;
1197                                 maxentries = MIN(maxentries, ((BUFFER_SIZE - (p - outbuf))/DIR_STRUCT_SIZE));
1198
1199                                 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1200                                 conn->dirpath,lp_dontdescend(SNUM(conn))));
1201                                 if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True))
1202                                         check_descend = True;
1203
1204                                 for (i=numentries;(i<maxentries) && !finished;i++) {
1205                                         finished = !get_dir_entry(conn,mask,dirtype,fname,&size,&mode,&date,check_descend);
1206                                         if (!finished) {
1207                                                 memcpy(p,status,21);
1208                                                 make_dir_struct(p,mask,fname,size, mode,date,
1209                                                                 !allow_long_path_components);
1210                                                 if (!dptr_fill(p+12,dptr_num)) {
1211                                                         break;
1212                                                 }
1213                                                 numentries++;
1214                                                 p += DIR_STRUCT_SIZE;
1215                                         }
1216                                 }
1217                         }
1218                 } /* if (ok ) */
1219         }
1220
1221
1222   SearchEmpty:
1223
1224         /* If we were called as SMBffirst with smb_search_id == NULL
1225                 and no entries were found then return error and close dirptr 
1226                 (X/Open spec) */
1227
1228         if (numentries == 0 || !ok) {
1229                 dptr_close(&dptr_num);
1230         } else if(ok && expect_close && status_len == 0) {
1231                 /* Close the dptr - we know it's gone */
1232                 dptr_close(&dptr_num);
1233         }
1234
1235         /* If we were called as SMBfunique, then we can close the dirptr now ! */
1236         if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique) {
1237                 dptr_close(&dptr_num);
1238         }
1239
1240         if ((numentries == 0) && !mask_contains_wcard) {
1241                 return ERROR_BOTH(STATUS_NO_MORE_FILES,ERRDOS,ERRnofiles);
1242         }
1243
1244         SSVAL(outbuf,smb_vwv0,numentries);
1245         SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1246         SCVAL(smb_buf(outbuf),0,5);
1247         SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
1248
1249         /* The replies here are never long name. */
1250         SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
1251         if (!allow_long_path_components) {
1252                 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) & (~FLAGS2_LONG_PATH_COMPONENTS));
1253         }
1254
1255         /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1256         SSVAL(outbuf,smb_flg2, (SVAL(outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
1257           
1258         outsize += DIR_STRUCT_SIZE*numentries;
1259         smb_setlen(outbuf,outsize - 4);
1260   
1261         if ((! *directory) && dptr_path(dptr_num))
1262                 slprintf(directory, sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1263
1264         DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1265                 smb_fn_name(CVAL(inbuf,smb_com)), 
1266                 mask, directory, dirtype, numentries, maxentries ) );
1267
1268         END_PROFILE(SMBsearch);
1269         return(outsize);
1270 }
1271
1272 /****************************************************************************
1273  Reply to a fclose (stop directory search).
1274 ****************************************************************************/
1275
1276 int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1277 {
1278         int outsize = 0;
1279         int status_len;
1280         pstring path;
1281         char status[21];
1282         int dptr_num= -2;
1283         char *p;
1284         NTSTATUS err;
1285         BOOL path_contains_wcard = False;
1286
1287         if (lp_posix_pathnames()) {
1288                 return reply_unknown(inbuf, outbuf);
1289         }
1290
1291         START_PROFILE(SMBfclose);
1292
1293         outsize = set_message(outbuf,1,0,True);
1294         p = smb_buf(inbuf) + 1;
1295         p += srvstr_get_path_wcard(inbuf, path, p, sizeof(path), 0, STR_TERMINATE, &err, &path_contains_wcard);
1296         if (!NT_STATUS_IS_OK(err)) {
1297                 END_PROFILE(SMBfclose);
1298                 return ERROR_NT(err);
1299         }
1300         p++;
1301         status_len = SVAL(p,0);
1302         p += 2;
1303
1304         if (status_len == 0) {
1305                 END_PROFILE(SMBfclose);
1306                 return ERROR_DOS(ERRSRV,ERRsrverror);
1307         }
1308
1309         memcpy(status,p,21);
1310
1311         if(dptr_fetch(status+12,&dptr_num)) {
1312                 /*  Close the dptr - we know it's gone */
1313                 dptr_close(&dptr_num);
1314         }
1315
1316         SSVAL(outbuf,smb_vwv0,0);
1317
1318         DEBUG(3,("search close\n"));
1319
1320         END_PROFILE(SMBfclose);
1321         return(outsize);
1322 }
1323
1324 /****************************************************************************
1325  Reply to an open.
1326 ****************************************************************************/
1327
1328 int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1329 {
1330         pstring fname;
1331         int outsize = 0;
1332         uint32 fattr=0;
1333         SMB_OFF_T size = 0;
1334         time_t mtime=0;
1335         int info;
1336         SMB_STRUCT_STAT sbuf;
1337         BOOL bad_path = False;
1338         files_struct *fsp;
1339         int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1340         int deny_mode;
1341         uint32 dos_attr = SVAL(inbuf,smb_vwv1);
1342         uint32 access_mask;
1343         uint32 share_mode;
1344         uint32 create_disposition;
1345         uint32 create_options = 0;
1346         NTSTATUS status;
1347         START_PROFILE(SMBopen);
1348  
1349         deny_mode = SVAL(inbuf,smb_vwv0);
1350
1351         srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), 0, STR_TERMINATE, &status);
1352         if (!NT_STATUS_IS_OK(status)) {
1353                 END_PROFILE(SMBopen);
1354                 return ERROR_NT(status);
1355         }
1356
1357         RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1358
1359         unix_convert(fname,conn,0,&bad_path,&sbuf);
1360         if (bad_path) {
1361                 END_PROFILE(SMBopen);
1362                 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1363         }
1364     
1365         if (!map_open_params_to_ntcreate(fname, deny_mode, OPENX_FILE_EXISTS_OPEN,
1366                         &access_mask, &share_mode, &create_disposition, &create_options)) {
1367                 END_PROFILE(SMBopen);
1368                 return ERROR_FORCE_DOS(ERRDOS, ERRbadaccess);
1369         }
1370
1371         fsp = open_file_ntcreate(conn,fname,&sbuf,
1372                         access_mask,
1373                         share_mode,
1374                         create_disposition,
1375                         create_options,
1376                         dos_attr,
1377                         oplock_request,
1378                         &info);
1379
1380         if (!fsp) {
1381                 END_PROFILE(SMBopen);
1382                 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1383                         /* We have re-scheduled this call. */
1384                         return -1;
1385                 }
1386                 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1387         }
1388
1389         size = sbuf.st_size;
1390         fattr = dos_mode(conn,fname,&sbuf);
1391         mtime = sbuf.st_mtime;
1392
1393         if (fattr & aDIR) {
1394                 DEBUG(3,("attempt to open a directory %s\n",fname));
1395                 close_file(fsp,ERROR_CLOSE);
1396                 END_PROFILE(SMBopen);
1397                 return ERROR_DOS(ERRDOS,ERRnoaccess);
1398         }
1399   
1400         outsize = set_message(outbuf,7,0,True);
1401         SSVAL(outbuf,smb_vwv0,fsp->fnum);
1402         SSVAL(outbuf,smb_vwv1,fattr);
1403         if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1404                 srv_put_dos_date3(outbuf,smb_vwv2,mtime & ~1);
1405         } else {
1406                 srv_put_dos_date3(outbuf,smb_vwv2,mtime);
1407         }
1408         SIVAL(outbuf,smb_vwv4,(uint32)size);
1409         SSVAL(outbuf,smb_vwv6,deny_mode);
1410
1411         if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1412                 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1413         }
1414     
1415         if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1416                 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1417         }
1418         END_PROFILE(SMBopen);
1419         return(outsize);
1420 }
1421
1422 /****************************************************************************
1423  Reply to an open and X.
1424 ****************************************************************************/
1425
1426 int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1427 {
1428         pstring fname;
1429         uint16 open_flags = SVAL(inbuf,smb_vwv2);
1430         int deny_mode = SVAL(inbuf,smb_vwv3);
1431         uint32 smb_attr = SVAL(inbuf,smb_vwv5);
1432         /* Breakout the oplock request bits so we can set the
1433                 reply bits separately. */
1434         BOOL ex_oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf);
1435         BOOL core_oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1436         BOOL oplock_request = ex_oplock_request | core_oplock_request;
1437 #if 0
1438         int smb_sattr = SVAL(inbuf,smb_vwv4); 
1439         uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
1440 #endif
1441         int smb_ofun = SVAL(inbuf,smb_vwv8);
1442         SMB_OFF_T size=0;
1443         uint32 fattr=0;
1444         int mtime=0;
1445         SMB_STRUCT_STAT sbuf;
1446         int smb_action = 0;
1447         BOOL bad_path = False;
1448         files_struct *fsp;
1449         NTSTATUS status;
1450         SMB_BIG_UINT allocation_size = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv9);
1451         ssize_t retval = -1;
1452         uint32 access_mask;
1453         uint32 share_mode;
1454         uint32 create_disposition;
1455         uint32 create_options = 0;
1456
1457         START_PROFILE(SMBopenX);
1458
1459         /* If it's an IPC, pass off the pipe handler. */
1460         if (IS_IPC(conn)) {
1461                 if (lp_nt_pipe_support()) {
1462                         END_PROFILE(SMBopenX);
1463                         return reply_open_pipe_and_X(conn, inbuf,outbuf,length,bufsize);
1464                 } else {
1465                         END_PROFILE(SMBopenX);
1466                         return ERROR_DOS(ERRSRV,ERRaccess);
1467                 }
1468         }
1469
1470         /* XXXX we need to handle passed times, sattr and flags */
1471         srvstr_get_path(inbuf, fname, smb_buf(inbuf), sizeof(fname), 0, STR_TERMINATE, &status);
1472         if (!NT_STATUS_IS_OK(status)) {
1473                 END_PROFILE(SMBopenX);
1474                 return ERROR_NT(status);
1475         }
1476
1477         RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1478
1479         unix_convert(fname,conn,0,&bad_path,&sbuf);
1480         if (bad_path) {
1481                 END_PROFILE(SMBopenX);
1482                 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1483         }
1484
1485         if (!map_open_params_to_ntcreate(fname, deny_mode, smb_ofun,
1486                                 &access_mask,
1487                                 &share_mode,
1488                                 &create_disposition,
1489                                 &create_options)) {
1490                 END_PROFILE(SMBopenX);
1491                 return ERROR_FORCE_DOS(ERRDOS, ERRbadaccess);
1492         }
1493
1494         fsp = open_file_ntcreate(conn,fname,&sbuf,
1495                         access_mask,
1496                         share_mode,
1497                         create_disposition,
1498                         create_options,
1499                         smb_attr,
1500                         oplock_request,
1501                         &smb_action);
1502       
1503         if (!fsp) {
1504                 END_PROFILE(SMBopenX);
1505                 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1506                         /* We have re-scheduled this call. */
1507                         return -1;
1508                 }
1509                 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1510         }
1511
1512         size = sbuf.st_size;
1513
1514         /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
1515            if the file is truncated or created. */
1516         if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
1517                 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
1518                 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
1519                         close_file(fsp,ERROR_CLOSE);
1520                         END_PROFILE(SMBntcreateX);
1521                         return ERROR_NT(NT_STATUS_DISK_FULL);
1522                 }
1523                 retval = vfs_set_filelen(fsp, (SMB_OFF_T)allocation_size);
1524                 if (retval < 0) {
1525                         close_file(fsp,ERROR_CLOSE);
1526                         END_PROFILE(SMBwrite);
1527                         return ERROR_NT(NT_STATUS_DISK_FULL);
1528                 }
1529                 size = get_allocation_size(conn,fsp,&sbuf);
1530         }
1531
1532         fattr = dos_mode(conn,fname,&sbuf);
1533         mtime = sbuf.st_mtime;
1534         if (fattr & aDIR) {
1535                 close_file(fsp,ERROR_CLOSE);
1536                 END_PROFILE(SMBopenX);
1537                 return ERROR_DOS(ERRDOS,ERRnoaccess);
1538         }
1539
1540         /* If the caller set the extended oplock request bit
1541                 and we granted one (by whatever means) - set the
1542                 correct bit for extended oplock reply.
1543         */
1544
1545         if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1546                 smb_action |= EXTENDED_OPLOCK_GRANTED;
1547         }
1548
1549         if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1550                 smb_action |= EXTENDED_OPLOCK_GRANTED;
1551         }
1552
1553         /* If the caller set the core oplock request bit
1554                 and we granted one (by whatever means) - set the
1555                 correct bit for core oplock reply.
1556         */
1557
1558         if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1559                 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1560         }
1561
1562         if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1563                 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1564         }
1565
1566         if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
1567                 set_message(outbuf,19,0,True);
1568         } else {
1569                 set_message(outbuf,15,0,True);
1570         }
1571         SSVAL(outbuf,smb_vwv2,fsp->fnum);
1572         SSVAL(outbuf,smb_vwv3,fattr);
1573         if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1574                 srv_put_dos_date3(outbuf,smb_vwv4,mtime & ~1);
1575         } else {
1576                 srv_put_dos_date3(outbuf,smb_vwv4,mtime);
1577         }
1578         SIVAL(outbuf,smb_vwv6,(uint32)size);
1579         SSVAL(outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
1580         SSVAL(outbuf,smb_vwv11,smb_action);
1581
1582         if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
1583                 SIVAL(outbuf, smb_vwv15, STD_RIGHT_ALL_ACCESS);
1584         }
1585
1586         END_PROFILE(SMBopenX);
1587         return chain_reply(inbuf,outbuf,length,bufsize);
1588 }
1589
1590 /****************************************************************************
1591  Reply to a SMBulogoffX.
1592 ****************************************************************************/
1593
1594 int reply_ulogoffX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1595 {
1596         uint16 vuid = SVAL(inbuf,smb_uid);
1597         user_struct *vuser = get_valid_user_struct(vuid);
1598         START_PROFILE(SMBulogoffX);
1599
1600         if(vuser == 0)
1601                 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid));
1602
1603         /* in user level security we are supposed to close any files
1604                 open by this user */
1605         if ((vuser != 0) && (lp_security() != SEC_SHARE))
1606                 file_close_user(vuid);
1607
1608         invalidate_vuid(vuid);
1609
1610         set_message(outbuf,2,0,True);
1611
1612         DEBUG( 3, ( "ulogoffX vuid=%d\n", vuid ) );
1613
1614         END_PROFILE(SMBulogoffX);
1615         return chain_reply(inbuf,outbuf,length,bufsize);
1616 }
1617
1618 /****************************************************************************
1619  Reply to a mknew or a create.
1620 ****************************************************************************/
1621
1622 int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1623 {
1624         pstring fname;
1625         int com;
1626         int outsize = 0;
1627         uint32 fattr = SVAL(inbuf,smb_vwv0);
1628         BOOL bad_path = False;
1629         files_struct *fsp;
1630         int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1631         SMB_STRUCT_STAT sbuf;
1632         NTSTATUS status;
1633         uint32 access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
1634         uint32 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
1635         uint32 create_disposition;
1636         uint32 create_options = 0;
1637
1638         START_PROFILE(SMBcreate);
1639  
1640         com = SVAL(inbuf,smb_com);
1641
1642         srvstr_get_path(inbuf, fname, smb_buf(inbuf) + 1, sizeof(fname), 0, STR_TERMINATE, &status);
1643         if (!NT_STATUS_IS_OK(status)) {
1644                 END_PROFILE(SMBcreate);
1645                 return ERROR_NT(status);
1646         }
1647
1648         RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1649
1650         unix_convert(fname,conn,0,&bad_path,&sbuf);
1651         if (bad_path) {
1652                 END_PROFILE(SMBcreate);
1653                 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1654         }
1655
1656         if (fattr & aVOLID) {
1657                 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
1658         }
1659
1660         if(com == SMBmknew) {
1661                 /* We should fail if file exists. */
1662                 create_disposition = FILE_CREATE;
1663         } else {
1664                 /* Create if file doesn't exist, truncate if it does. */
1665                 create_disposition = FILE_OVERWRITE_IF;
1666         }
1667
1668         /* Open file using ntcreate. */
1669         fsp = open_file_ntcreate(conn,fname,&sbuf,
1670                                 access_mask,
1671                                 share_mode,
1672                                 create_disposition,
1673                                 create_options,
1674                                 fattr,
1675                                 oplock_request,
1676                                 NULL);
1677   
1678         if (!fsp) {
1679                 END_PROFILE(SMBcreate);
1680                 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1681                         /* We have re-scheduled this call. */
1682                         return -1;
1683                 }
1684                 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1685         }
1686  
1687         outsize = set_message(outbuf,1,0,True);
1688         SSVAL(outbuf,smb_vwv0,fsp->fnum);
1689
1690         if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1691                 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1692         }
1693  
1694         if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1695                 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1696         }
1697  
1698         DEBUG( 2, ( "reply_mknew: file %s\n", fname ) );
1699         DEBUG( 3, ( "reply_mknew %s fd=%d dmode=0x%x\n", fname, fsp->fh->fd, (unsigned int)fattr ) );
1700
1701         END_PROFILE(SMBcreate);
1702         return(outsize);
1703 }
1704
1705 /****************************************************************************
1706  Reply to a create temporary file.
1707 ****************************************************************************/
1708
1709 int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1710 {
1711         pstring fname;
1712         int outsize = 0;
1713         uint32 fattr = SVAL(inbuf,smb_vwv0);
1714         BOOL bad_path = False;
1715         files_struct *fsp;
1716         int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1717         int tmpfd;
1718         SMB_STRUCT_STAT sbuf;
1719         char *p, *s;
1720         NTSTATUS status;
1721         unsigned int namelen;
1722
1723         START_PROFILE(SMBctemp);
1724
1725         srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), 0, STR_TERMINATE, &status);
1726         if (!NT_STATUS_IS_OK(status)) {
1727                 END_PROFILE(SMBctemp);
1728                 return ERROR_NT(status);
1729         }
1730         if (*fname) {
1731                 pstrcat(fname,"/TMXXXXXX");
1732         } else {
1733                 pstrcat(fname,"TMXXXXXX");
1734         }
1735
1736         RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1737
1738         unix_convert(fname,conn,0,&bad_path,&sbuf);
1739         if (bad_path) {
1740                 END_PROFILE(SMBctemp);
1741                 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1742         }
1743   
1744         tmpfd = smb_mkstemp(fname);
1745         if (tmpfd == -1) {
1746                 END_PROFILE(SMBctemp);
1747                 return(UNIXERROR(ERRDOS,ERRnoaccess));
1748         }
1749
1750         SMB_VFS_STAT(conn,fname,&sbuf);
1751
1752         /* We should fail if file does not exist. */
1753         fsp = open_file_ntcreate(conn,fname,&sbuf,
1754                                 FILE_GENERIC_READ | FILE_GENERIC_WRITE,
1755                                 FILE_SHARE_READ|FILE_SHARE_WRITE,
1756                                 FILE_OPEN,
1757                                 0,
1758                                 fattr,
1759                                 oplock_request,
1760                                 NULL);
1761
1762         /* close fd from smb_mkstemp() */
1763         close(tmpfd);
1764
1765         if (!fsp) {
1766                 END_PROFILE(SMBctemp);
1767                 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1768                         /* We have re-scheduled this call. */
1769                         return -1;
1770                 }
1771                 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1772         }
1773
1774         outsize = set_message(outbuf,1,0,True);
1775         SSVAL(outbuf,smb_vwv0,fsp->fnum);
1776
1777         /* the returned filename is relative to the directory */
1778         s = strrchr_m(fname, '/');
1779         if (!s) {
1780                 s = fname;
1781         } else {
1782                 s++;
1783         }
1784
1785         p = smb_buf(outbuf);
1786 #if 0
1787         /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
1788            thing in the byte section. JRA */
1789         SSVALS(p, 0, -1); /* what is this? not in spec */
1790 #endif
1791         namelen = srvstr_push(outbuf, p, s, -1, STR_ASCII|STR_TERMINATE);
1792         p += namelen;
1793         outsize = set_message_end(outbuf, p);
1794
1795         if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1796                 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1797         }
1798   
1799         if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1800                 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1801         }
1802
1803         DEBUG( 2, ( "reply_ctemp: created temp file %s\n", fname ) );
1804         DEBUG( 3, ( "reply_ctemp %s fd=%d umode=0%o\n", fname, fsp->fh->fd,
1805                         (unsigned int)sbuf.st_mode ) );
1806
1807         END_PROFILE(SMBctemp);
1808         return(outsize);
1809 }
1810
1811 /*******************************************************************
1812  Check if a user is allowed to rename a file.
1813 ********************************************************************/
1814
1815 static NTSTATUS can_rename(connection_struct *conn, char *fname, uint16 dirtype, SMB_STRUCT_STAT *pst)
1816 {
1817         files_struct *fsp;
1818         uint32 fmode;
1819
1820         if (!CAN_WRITE(conn)) {
1821                 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1822         }
1823
1824         fmode = dos_mode(conn,fname,pst);
1825         if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM)) {
1826                 return NT_STATUS_NO_SUCH_FILE;
1827         }
1828
1829         if (S_ISDIR(pst->st_mode)) {
1830                 return NT_STATUS_OK;
1831         }
1832
1833         /* We need a better way to return NT status codes from open... */
1834         set_saved_ntstatus(NT_STATUS_OK);
1835
1836         fsp = open_file_ntcreate(conn, fname, pst,
1837                                 DELETE_ACCESS,
1838                                 FILE_SHARE_READ|FILE_SHARE_WRITE,
1839                                 FILE_OPEN,
1840                                 0,
1841                                 FILE_ATTRIBUTE_NORMAL,
1842                                 0,
1843                                 NULL);
1844
1845         if (!fsp) {
1846                 NTSTATUS ret = get_saved_ntstatus();
1847                 if (!NT_STATUS_IS_OK(ret)) {
1848                         set_saved_ntstatus(NT_STATUS_OK);
1849                         return ret;
1850                 }
1851                 set_saved_ntstatus(NT_STATUS_OK);
1852                 return NT_STATUS_ACCESS_DENIED;
1853         }
1854         close_file(fsp,NORMAL_CLOSE);
1855         return NT_STATUS_OK;
1856 }
1857
1858 /*******************************************************************
1859  Check if a user is allowed to delete a file.
1860 ********************************************************************/
1861
1862 NTSTATUS can_delete(connection_struct *conn, char *fname, uint32 dirtype, BOOL bad_path, BOOL check_is_at_open)
1863 {
1864         SMB_STRUCT_STAT sbuf;
1865         uint32 fattr;
1866         files_struct *fsp;
1867
1868         DEBUG(10,("can_delete: %s, dirtype = %d\n", fname, dirtype ));
1869
1870         if (!CAN_WRITE(conn)) {
1871                 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1872         }
1873
1874         if (SMB_VFS_LSTAT(conn,fname,&sbuf) != 0) {
1875                 if(errno == ENOENT) {
1876                         if (bad_path) {
1877                                 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
1878                         } else {
1879                                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1880                         }
1881                 }
1882                 return map_nt_error_from_unix(errno);
1883         }
1884
1885         fattr = dos_mode(conn,fname,&sbuf);
1886
1887         /* Can't delete a directory. */
1888         if (fattr & aDIR) {
1889                 return NT_STATUS_FILE_IS_A_DIRECTORY;
1890         }
1891
1892 #if 0 /* JRATEST */
1893         else if (dirtype & aDIR) /* Asked for a directory and it isn't. */
1894                 return NT_STATUS_OBJECT_NAME_INVALID;
1895 #endif /* JRATEST */
1896
1897         /* Fix for bug #3035 from SATOH Fumiyasu <fumiyas@miraclelinux.com>
1898
1899           On a Windows share, a file with read-only dosmode can be opened with
1900           DELETE_ACCESS. But on a Samba share (delete readonly = no), it
1901           fails with NT_STATUS_CANNOT_DELETE error.
1902
1903           This semantic causes a problem that a user can not
1904           rename a file with read-only dosmode on a Samba share
1905           from a Windows command prompt (i.e. cmd.exe, but can rename
1906           from Windows Explorer).
1907         */
1908
1909         if (!check_is_at_open && !lp_delete_readonly(SNUM(conn))) {
1910                 if (fattr & aRONLY) {
1911                         return NT_STATUS_CANNOT_DELETE;
1912                 }
1913         }
1914         if ((fattr & ~dirtype) & (aHIDDEN | aSYSTEM)) {
1915                 return NT_STATUS_NO_SUCH_FILE;
1916         }
1917
1918         if (check_is_at_open) {
1919                 if (!can_delete_file_in_directory(conn, fname)) {
1920                         return NT_STATUS_ACCESS_DENIED;
1921                 }
1922         } else {
1923                 /* On open checks the open itself will check the share mode, so
1924                    don't do it here as we'll get it wrong. */
1925
1926                 /* We need a better way to return NT status codes from open... */
1927                 set_saved_ntstatus(NT_STATUS_OK);
1928
1929                 fsp = open_file_ntcreate(conn, fname, &sbuf,
1930                                         DELETE_ACCESS,
1931                                         FILE_SHARE_NONE,
1932                                         FILE_OPEN,
1933                                         0,
1934                                         FILE_ATTRIBUTE_NORMAL,
1935                                         0,
1936                                         NULL);
1937
1938                 if (!fsp) {
1939                         NTSTATUS ret = get_saved_ntstatus();
1940                         if (!NT_STATUS_IS_OK(ret)) {
1941                                 set_saved_ntstatus(NT_STATUS_OK);
1942                                 return ret;
1943                         }
1944                         set_saved_ntstatus(NT_STATUS_OK);
1945                         return NT_STATUS_ACCESS_DENIED;
1946                 }
1947                 close_file(fsp,NORMAL_CLOSE);
1948         }
1949         return NT_STATUS_OK;
1950 }
1951
1952 /****************************************************************************
1953  The guts of the unlink command, split out so it may be called by the NT SMB
1954  code.
1955 ****************************************************************************/
1956
1957 NTSTATUS unlink_internals(connection_struct *conn, uint32 dirtype, char *name, BOOL has_wild)
1958 {
1959         pstring directory;
1960         pstring mask;
1961         char *p;
1962         int count=0;
1963         NTSTATUS error = NT_STATUS_OK;
1964         BOOL bad_path = False;
1965         BOOL rc = True;
1966         SMB_STRUCT_STAT sbuf;
1967         
1968         *directory = *mask = 0;
1969         
1970         rc = unix_convert(name,conn,0,&bad_path,&sbuf);
1971         
1972         p = strrchr_m(name,'/');
1973         if (!p) {
1974                 pstrcpy(directory,".");
1975                 pstrcpy(mask,name);
1976         } else {
1977                 *p = 0;
1978                 pstrcpy(directory,name);
1979                 pstrcpy(mask,p+1);
1980         }
1981         
1982         /*
1983          * We should only check the mangled cache
1984          * here if unix_convert failed. This means
1985          * that the path in 'mask' doesn't exist
1986          * on the file system and so we need to look
1987          * for a possible mangle. This patch from
1988          * Tine Smukavec <valentin.smukavec@hermes.si>.
1989          */
1990         
1991         if (!rc && mangle_is_mangled(mask,SNUM(conn)))
1992                 mangle_check_cache( mask, sizeof(pstring)-1, SNUM(conn));
1993         
1994         if (!has_wild) {
1995                 pstrcat(directory,"/");
1996                 pstrcat(directory,mask);
1997                 error = can_delete(conn,directory,dirtype,bad_path,False);
1998                 if (!NT_STATUS_IS_OK(error))
1999                         return error;
2000
2001                 if (SMB_VFS_UNLINK(conn,directory) == 0) {
2002                         count++;
2003                 }
2004         } else {
2005                 struct smb_Dir *dir_hnd = NULL;
2006                 const char *dname;
2007                 
2008                 if (strequal(mask,"????????.???"))
2009                         pstrcpy(mask,"*");
2010
2011                 if (check_name(directory,conn))
2012                         dir_hnd = OpenDir(conn, directory, mask, dirtype);
2013                 
2014                 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2015                    the pattern matches against the long name, otherwise the short name 
2016                    We don't implement this yet XXXX
2017                 */
2018                 
2019                 if (dir_hnd) {
2020                         long offset = 0;
2021                         error = NT_STATUS_NO_SUCH_FILE;
2022
2023                         while ((dname = ReadDirName(dir_hnd, &offset))) {
2024                                 SMB_STRUCT_STAT st;
2025                                 pstring fname;
2026                                 BOOL sys_direntry = False;
2027                                 pstrcpy(fname,dname);
2028
2029                                 if (!is_visible_file(conn, directory, dname, &st, True)) {
2030                                         continue;
2031                                 }
2032
2033                                 /* Quick check for "." and ".." */
2034                                 if (fname[0] == '.') {
2035                                         if (!fname[1] || (fname[1] == '.' && !fname[2])) {
2036                                                 if ((dirtype & FILE_ATTRIBUTE_DIRECTORY) && (dirtype & FILE_ATTRIBUTE_SYSTEM)) {
2037                                                         sys_direntry = True;
2038                                                 } else {
2039                                                         continue;
2040                                                 }
2041                                         }
2042                                 }
2043
2044                                 if(!mask_match(fname, mask, conn->case_sensitive))
2045                                         continue;
2046                                 
2047                                 if (sys_direntry) {
2048                                         error = NT_STATUS_OBJECT_NAME_INVALID;
2049                                         DEBUG(3,("unlink_internals: system directory delete denied [%s] mask [%s]\n",
2050                                                 fname, mask));
2051                                         break;
2052                                 }
2053
2054                                 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
2055                                 error = can_delete(conn,fname,dirtype,bad_path,False);
2056                                 if (!NT_STATUS_IS_OK(error)) {
2057                                         continue;
2058                                 }
2059                                 if (SMB_VFS_UNLINK(conn,fname) == 0)
2060                                         count++;
2061                                 DEBUG(3,("unlink_internals: succesful unlink [%s]\n",fname));
2062                         }
2063                         CloseDir(dir_hnd);
2064                 }
2065         }
2066         
2067         if (count == 0 && NT_STATUS_IS_OK(error)) {
2068                 error = map_nt_error_from_unix(errno);
2069         }
2070
2071         return error;
2072 }
2073
2074 /****************************************************************************
2075  Reply to a unlink
2076 ****************************************************************************/
2077
2078 int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, 
2079                  int dum_buffsize)
2080 {
2081         int outsize = 0;
2082         pstring name;
2083         uint32 dirtype;
2084         NTSTATUS status;
2085         BOOL path_contains_wcard = False;
2086
2087         START_PROFILE(SMBunlink);
2088
2089         dirtype = SVAL(inbuf,smb_vwv0);
2090         
2091         srvstr_get_path_wcard(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status, &path_contains_wcard);
2092         if (!NT_STATUS_IS_OK(status)) {
2093                 END_PROFILE(SMBunlink);
2094                 return ERROR_NT(status);
2095         }
2096         
2097         RESOLVE_DFSPATH_WCARD(name, conn, inbuf, outbuf);
2098         
2099         DEBUG(3,("reply_unlink : %s\n",name));
2100         
2101         status = unlink_internals(conn, dirtype, name, path_contains_wcard);
2102         if (!NT_STATUS_IS_OK(status)) {
2103                 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
2104                         /* We have re-scheduled this call. */
2105                         return -1;
2106                 }
2107                 return ERROR_NT(status);
2108         }
2109
2110         /*
2111          * Win2k needs a changenotify request response before it will
2112          * update after a rename..
2113          */
2114         process_pending_change_notify_queue((time_t)0);
2115         
2116         outsize = set_message(outbuf,0,0,True);
2117   
2118         END_PROFILE(SMBunlink);
2119         return outsize;
2120 }
2121
2122 /****************************************************************************
2123  Fail for readbraw.
2124 ****************************************************************************/
2125
2126 static void fail_readraw(void)
2127 {
2128         pstring errstr;
2129         slprintf(errstr, sizeof(errstr)-1, "FAIL ! reply_readbraw: socket write fail (%s)",
2130                 strerror(errno) );
2131         exit_server(errstr);
2132 }
2133
2134 #if defined(WITH_SENDFILE)
2135 /****************************************************************************
2136  Fake (read/write) sendfile. Returns -1 on read or write fail.
2137 ****************************************************************************/
2138
2139 static ssize_t fake_sendfile(files_struct *fsp, SMB_OFF_T startpos, size_t nread, char *buf, int bufsize)
2140 {
2141         ssize_t ret=0;
2142
2143         /* Paranioa check... */
2144         if (nread > bufsize) {
2145                 fail_readraw();
2146         }
2147
2148         if (nread > 0) {
2149                 ret = read_file(fsp,buf,startpos,nread);
2150                 if (ret == -1) {
2151                         return -1;
2152                 }
2153         }
2154
2155         /* If we had a short read, fill with zeros. */
2156         if (ret < nread) {
2157                 memset(buf, '\0', nread - ret);
2158         }
2159
2160         if (write_data(smbd_server_fd(),buf,nread) != nread) {
2161                 return -1;
2162         }       
2163
2164         return (ssize_t)nread;
2165 }
2166 #endif
2167
2168 /****************************************************************************
2169  Use sendfile in readbraw.
2170 ****************************************************************************/
2171
2172 void send_file_readbraw(connection_struct *conn, files_struct *fsp, SMB_OFF_T startpos, size_t nread,
2173                 ssize_t mincount, char *outbuf, int out_buffsize)
2174 {
2175         ssize_t ret=0;
2176
2177 #if defined(WITH_SENDFILE)
2178         /*
2179          * We can only use sendfile on a non-chained packet 
2180          * but we can use on a non-oplocked file. tridge proved this
2181          * on a train in Germany :-). JRA.
2182          * reply_readbraw has already checked the length.
2183          */
2184
2185         if ( (chain_size == 0) && (nread > 0) &&
2186             (fsp->wcp == NULL) && lp_use_sendfile(SNUM(conn)) ) {
2187                 DATA_BLOB header;
2188
2189                 _smb_setlen(outbuf,nread);
2190                 header.data = (uint8 *)outbuf;
2191                 header.length = 4;
2192                 header.free = NULL;
2193
2194                 if ( SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fh->fd, &header, startpos, nread) == -1) {
2195                         /* Returning ENOSYS means no data at all was sent. Do this as a normal read. */
2196                         if (errno == ENOSYS) {
2197                                 goto normal_readbraw;
2198                         }
2199
2200                         /*
2201                          * Special hack for broken Linux with no working sendfile. If we
2202                          * return EINTR we sent the header but not the rest of the data.
2203                          * Fake this up by doing read/write calls.
2204                          */
2205                         if (errno == EINTR) {
2206                                 /* Ensure we don't do this again. */
2207                                 set_use_sendfile(SNUM(conn), False);
2208                                 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
2209
2210                                 if (fake_sendfile(fsp, startpos, nread, outbuf + 4, out_buffsize - 4) == -1) {
2211                                         DEBUG(0,("send_file_readbraw: fake_sendfile failed for file %s (%s).\n",
2212                                                 fsp->fsp_name, strerror(errno) ));
2213                                         exit_server("send_file_readbraw fake_sendfile failed");
2214                                 }
2215                                 return;
2216                         }
2217
2218                         DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n",
2219                                 fsp->fsp_name, strerror(errno) ));
2220                         exit_server("send_file_readbraw sendfile failed");
2221                 }
2222
2223         }
2224
2225   normal_readbraw:
2226
2227 #endif
2228
2229         if (nread > 0) {
2230                 ret = read_file(fsp,outbuf+4,startpos,nread);
2231 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2232                 if (ret < mincount)
2233                         ret = 0;
2234 #else
2235                 if (ret < nread)
2236                         ret = 0;
2237 #endif
2238         }
2239
2240         _smb_setlen(outbuf,ret);
2241         if (write_data(smbd_server_fd(),outbuf,4+ret) != 4+ret)
2242                 fail_readraw();
2243 }
2244
2245 /****************************************************************************
2246  Reply to a readbraw (core+ protocol).
2247 ****************************************************************************/
2248
2249 int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_size, int out_buffsize)
2250 {
2251         ssize_t maxcount,mincount;
2252         size_t nread = 0;
2253         SMB_OFF_T startpos;
2254         char *header = outbuf;
2255         files_struct *fsp;
2256         START_PROFILE(SMBreadbraw);
2257
2258         if (srv_is_signing_active()) {
2259                 exit_server("reply_readbraw: SMB signing is active - raw reads/writes are disallowed.");
2260         }
2261
2262         /*
2263          * Special check if an oplock break has been issued
2264          * and the readraw request croses on the wire, we must
2265          * return a zero length response here.
2266          */
2267
2268         fsp = file_fsp(inbuf,smb_vwv0);
2269
2270         if (!FNUM_OK(fsp,conn) || !fsp->can_read) {
2271                 /*
2272                  * fsp could be NULL here so use the value from the packet. JRA.
2273                  */
2274                 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",(int)SVAL(inbuf,smb_vwv0)));
2275                 _smb_setlen(header,0);
2276                 if (write_data(smbd_server_fd(),header,4) != 4)
2277                         fail_readraw();
2278                 END_PROFILE(SMBreadbraw);
2279                 return(-1);
2280         }
2281
2282         CHECK_FSP(fsp,conn);
2283
2284         flush_write_cache(fsp, READRAW_FLUSH);
2285
2286         startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
2287         if(CVAL(inbuf,smb_wct) == 10) {
2288                 /*
2289                  * This is a large offset (64 bit) read.
2290                  */
2291 #ifdef LARGE_SMB_OFF_T
2292
2293                 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv8)) << 32);
2294
2295 #else /* !LARGE_SMB_OFF_T */
2296
2297                 /*
2298                  * Ensure we haven't been sent a >32 bit offset.
2299                  */
2300
2301                 if(IVAL(inbuf,smb_vwv8) != 0) {
2302                         DEBUG(0,("readbraw - large offset (%x << 32) used and we don't support \
2303 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv8) ));
2304                         _smb_setlen(header,0);
2305                         if (write_data(smbd_server_fd(),header,4) != 4)
2306                                 fail_readraw();
2307                         END_PROFILE(SMBreadbraw);
2308                         return(-1);
2309                 }
2310
2311 #endif /* LARGE_SMB_OFF_T */
2312
2313                 if(startpos < 0) {
2314                         DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n", (double)startpos ));
2315                         _smb_setlen(header,0);
2316                         if (write_data(smbd_server_fd(),header,4) != 4)
2317                                 fail_readraw();
2318                         END_PROFILE(SMBreadbraw);
2319                         return(-1);
2320                 }      
2321         }
2322         maxcount = (SVAL(inbuf,smb_vwv3) & 0xFFFF);
2323         mincount = (SVAL(inbuf,smb_vwv4) & 0xFFFF);
2324
2325         /* ensure we don't overrun the packet size */
2326         maxcount = MIN(65535,maxcount);
2327
2328         if (!is_locked(fsp,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK)) {
2329                 SMB_STRUCT_STAT st;
2330                 SMB_OFF_T size = 0;
2331   
2332                 if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&st) == 0) {
2333                         size = st.st_size;
2334                 }
2335
2336                 if (startpos >= size) {
2337                         nread = 0;
2338                 } else {
2339                         nread = MIN(maxcount,(size - startpos));          
2340                 }
2341         }
2342
2343 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2344         if (nread < mincount)
2345                 nread = 0;
2346 #endif
2347   
2348         DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%lu min=%lu nread=%lu\n", fsp->fnum, (double)startpos,
2349                                 (unsigned long)maxcount, (unsigned long)mincount, (unsigned long)nread ) );
2350   
2351         send_file_readbraw(conn, fsp, startpos, nread, mincount, outbuf, out_buffsize);
2352
2353         DEBUG(5,("readbraw finished\n"));
2354         END_PROFILE(SMBreadbraw);
2355         return -1;
2356 }
2357
2358 #undef DBGC_CLASS
2359 #define DBGC_CLASS DBGC_LOCKING
2360
2361 /****************************************************************************
2362  Reply to a lockread (core+ protocol).
2363 ****************************************************************************/
2364
2365 int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length, int dum_buffsiz)
2366 {
2367         ssize_t nread = -1;
2368         char *data;
2369         int outsize = 0;
2370         SMB_OFF_T startpos;
2371         size_t numtoread;
2372         NTSTATUS status;
2373         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2374         BOOL my_lock_ctx = False;
2375         START_PROFILE(SMBlockread);
2376
2377         CHECK_FSP(fsp,conn);
2378         if (!CHECK_READ(fsp,inbuf)) {
2379                 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2380         }
2381
2382         release_level_2_oplocks_on_change(fsp);
2383
2384         numtoread = SVAL(inbuf,smb_vwv1);
2385         startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2386   
2387         outsize = set_message(outbuf,5,3,True);
2388         numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2389         data = smb_buf(outbuf) + 3;
2390         
2391         /*
2392          * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
2393          * protocol request that predates the read/write lock concept. 
2394          * Thus instead of asking for a read lock here we need to ask
2395          * for a write lock. JRA.
2396          * Note that the requested lock size is unaffected by max_recv.
2397          */
2398         
2399         status = do_lock_spin(fsp,
2400                                 SVAL(inbuf,smb_pid), 
2401                                 (SMB_BIG_UINT)numtoread,
2402                                 (SMB_BIG_UINT)startpos,
2403                                 WRITE_LOCK,
2404                                 WINDOWS_LOCK,
2405                                 &my_lock_ctx);
2406
2407         if (NT_STATUS_V(status)) {
2408 #if 0
2409                 /*
2410                  * We used to make lockread a blocking lock. It turns out
2411                  * that this isn't on W2k. Found by the Samba 4 RAW-READ torture
2412                  * tester. JRA.
2413                  */
2414
2415                 if (lp_blocking_locks(SNUM(conn)) && !my_lock_ctx && ERROR_WAS_LOCK_DENIED(status)) {
2416                         /*
2417                          * A blocking lock was requested. Package up
2418                          * this smb into a queued request and push it
2419                          * onto the blocking lock queue.
2420                          */
2421                         if(push_blocking_lock_request(inbuf, length,
2422                                         fsp,
2423                                         -1,
2424                                         0,
2425                                         SVAL(inbuf,smb_pid),
2426                                         WRITE_LOCK,
2427                                         WINDOWS_LOCK,
2428                                         (SMB_BIG_UINT)startpos,
2429                                         (SMB_BIG_UINT)numtoread)) {
2430                                 END_PROFILE(SMBlockread);
2431                                 return -1;
2432                         }
2433                 }
2434 #endif
2435                 END_PROFILE(SMBlockread);
2436                 return ERROR_NT(status);
2437         }
2438
2439         /*
2440          * However the requested READ size IS affected by max_recv. Insanity.... JRA.
2441          */
2442
2443         if (numtoread > max_recv) {
2444                 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
2445 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
2446                         (unsigned int)numtoread, (unsigned int)max_recv ));
2447                 numtoread = MIN(numtoread,max_recv);
2448         }
2449         nread = read_file(fsp,data,startpos,numtoread);
2450
2451         if (nread < 0) {
2452                 END_PROFILE(SMBlockread);
2453                 return(UNIXERROR(ERRDOS,ERRnoaccess));
2454         }
2455         
2456         outsize += nread;
2457         SSVAL(outbuf,smb_vwv0,nread);
2458         SSVAL(outbuf,smb_vwv5,nread+3);
2459         SSVAL(smb_buf(outbuf),1,nread);
2460         
2461         DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
2462                  fsp->fnum, (int)numtoread, (int)nread));
2463
2464         END_PROFILE(SMBlockread);
2465         return(outsize);
2466 }
2467
2468 #undef DBGC_CLASS
2469 #define DBGC_CLASS DBGC_ALL
2470
2471 /****************************************************************************
2472  Reply to a read.
2473 ****************************************************************************/
2474
2475 int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2476 {
2477         size_t numtoread;
2478         ssize_t nread = 0;
2479         char *data;
2480         SMB_OFF_T startpos;
2481         int outsize = 0;
2482         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2483         START_PROFILE(SMBread);
2484
2485         CHECK_FSP(fsp,conn);
2486         if (!CHECK_READ(fsp,inbuf)) {
2487                 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2488         }
2489
2490         numtoread = SVAL(inbuf,smb_vwv1);
2491         startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2492
2493         outsize = set_message(outbuf,5,3,True);
2494         numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2495         /*
2496          * The requested read size cannot be greater than max_recv. JRA.
2497          */
2498         if (numtoread > max_recv) {
2499                 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
2500 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
2501                         (unsigned int)numtoread, (unsigned int)max_recv ));
2502                 numtoread = MIN(numtoread,max_recv);
2503         }
2504
2505         data = smb_buf(outbuf) + 3;
2506   
2507         if (is_locked(fsp,(SMB_BIG_UINT)numtoread,(SMB_BIG_UINT)startpos, READ_LOCK)) {
2508                 END_PROFILE(SMBread);
2509                 return ERROR_DOS(ERRDOS,ERRlock);
2510         }
2511
2512         if (numtoread > 0)
2513                 nread = read_file(fsp,data,startpos,numtoread);
2514
2515         if (nread < 0) {
2516                 END_PROFILE(SMBread);
2517                 return(UNIXERROR(ERRDOS,ERRnoaccess));
2518         }
2519   
2520         outsize += nread;
2521         SSVAL(outbuf,smb_vwv0,nread);
2522         SSVAL(outbuf,smb_vwv5,nread+3);
2523         SCVAL(smb_buf(outbuf),0,1);
2524         SSVAL(smb_buf(outbuf),1,nread);
2525   
2526         DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
2527                 fsp->fnum, (int)numtoread, (int)nread ) );
2528
2529         END_PROFILE(SMBread);
2530         return(outsize);
2531 }
2532
2533 /****************************************************************************
2534  Reply to a read and X - possibly using sendfile.
2535 ****************************************************************************/
2536
2537 int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length, int len_outbuf,
2538                 files_struct *fsp, SMB_OFF_T startpos, size_t smb_maxcnt)
2539 {
2540         int outsize = 0;
2541         ssize_t nread = -1;
2542         char *data = smb_buf(outbuf);
2543
2544 #if defined(WITH_SENDFILE)
2545         /*
2546          * We can only use sendfile on a non-chained packet 
2547          * but we can use on a non-oplocked file. tridge proved this
2548          * on a train in Germany :-). JRA.
2549          */
2550
2551         if ((chain_size == 0) && (CVAL(inbuf,smb_vwv0) == 0xFF) &&
2552             lp_use_sendfile(SNUM(conn)) && (fsp->wcp == NULL) ) {
2553                 SMB_STRUCT_STAT sbuf;
2554                 DATA_BLOB header;
2555
2556                 if(SMB_VFS_FSTAT(fsp,fsp->fh->fd, &sbuf) == -1)
2557                         return(UNIXERROR(ERRDOS,ERRnoaccess));
2558
2559                 if (startpos > sbuf.st_size)
2560                         goto normal_read;
2561
2562                 if (smb_maxcnt > (sbuf.st_size - startpos))
2563                         smb_maxcnt = (sbuf.st_size - startpos);
2564
2565                 if (smb_maxcnt == 0)
2566                         goto normal_read;
2567
2568                 /* 
2569                  * Set up the packet header before send. We
2570                  * assume here the sendfile will work (get the
2571                  * correct amount of data).
2572                  */
2573
2574                 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
2575                 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
2576                 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2577                 SSVAL(outbuf,smb_vwv7,((smb_maxcnt >> 16) & 1));
2578                 SSVAL(smb_buf(outbuf),-2,smb_maxcnt);
2579                 SCVAL(outbuf,smb_vwv0,0xFF);
2580                 set_message(outbuf,12,smb_maxcnt,False);
2581                 header.data = (uint8 *)outbuf;
2582                 header.length = data - outbuf;
2583                 header.free = NULL;
2584
2585                 if ((nread = SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fh->fd, &header, startpos, smb_maxcnt)) == -1) {
2586                         /* Returning ENOSYS means no data at all was sent. Do this as a normal read. */
2587                         if (errno == ENOSYS) {
2588                                 goto normal_read;
2589                         }
2590
2591                         /*
2592                          * Special hack for broken Linux with no working sendfile. If we
2593                          * return EINTR we sent the header but not the rest of the data.
2594                          * Fake this up by doing read/write calls.
2595                          */
2596
2597                         if (errno == EINTR) {
2598                                 /* Ensure we don't do this again. */
2599                                 set_use_sendfile(SNUM(conn), False);
2600                                 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
2601
2602                                 if ((nread = fake_sendfile(fsp, startpos, smb_maxcnt, data,
2603                                                         len_outbuf - (data-outbuf))) == -1) {
2604                                         DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
2605                                                 fsp->fsp_name, strerror(errno) ));
2606                                         exit_server("send_file_readX: fake_sendfile failed");
2607                                 }
2608                                 DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
2609                                         fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2610                                 /* Returning -1 here means successful sendfile. */
2611                                 return -1;
2612                         }
2613
2614                         DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n",
2615                                 fsp->fsp_name, strerror(errno) ));
2616                         exit_server("send_file_readX sendfile failed");
2617                 }
2618
2619                 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
2620                         fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2621                 /* Returning -1 here means successful sendfile. */
2622                 return -1;
2623         }
2624
2625   normal_read:
2626
2627 #endif
2628
2629         nread = read_file(fsp,data,startpos,smb_maxcnt);
2630   
2631         if (nread < 0) {
2632                 END_PROFILE(SMBreadX);
2633                 return(UNIXERROR(ERRDOS,ERRnoaccess));
2634         }
2635
2636         outsize = set_message(outbuf,12,nread,False);
2637         SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
2638         SSVAL(outbuf,smb_vwv5,nread);
2639         SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2640         SSVAL(outbuf,smb_vwv7,((nread >> 16) & 1));
2641         SSVAL(smb_buf(outbuf),-2,nread);
2642   
2643         DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
2644                 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2645
2646         /* Returning the number of bytes we want to send back - including header. */
2647         return outsize;
2648 }
2649
2650 /****************************************************************************
2651  Reply to a read and X.
2652 ****************************************************************************/
2653
2654 int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2655 {
2656         files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2657         SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2658         ssize_t nread = -1;
2659         size_t smb_maxcnt = SVAL(inbuf,smb_vwv5);
2660 #if 0
2661         size_t smb_mincnt = SVAL(inbuf,smb_vwv6);
2662 #endif
2663
2664         START_PROFILE(SMBreadX);
2665
2666         /* If it's an IPC, pass off the pipe handler. */
2667         if (IS_IPC(conn)) {
2668                 END_PROFILE(SMBreadX);
2669                 return reply_pipe_read_and_X(inbuf,outbuf,length,bufsize);
2670         }
2671
2672         CHECK_FSP(fsp,conn);
2673         if (!CHECK_READ(fsp,inbuf)) {
2674                 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2675         }
2676
2677         set_message(outbuf,12,0,True);
2678
2679         if (global_client_caps & CAP_LARGE_READX) {
2680                 if (SVAL(inbuf,smb_vwv7) == 1) {
2681                         smb_maxcnt |= (1<<16);
2682                 }
2683                 if (smb_maxcnt > BUFFER_SIZE) {
2684                         DEBUG(0,("reply_read_and_X - read too large (%u) for reply buffer %u\n",
2685                                 (unsigned int)smb_maxcnt, (unsigned int)BUFFER_SIZE));
2686                         END_PROFILE(SMBreadX);
2687                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2688                 }
2689         }
2690
2691         if(CVAL(inbuf,smb_wct) == 12) {
2692 #ifdef LARGE_SMB_OFF_T
2693                 /*
2694                  * This is a large offset (64 bit) read.
2695                  */
2696                 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv10)) << 32);
2697
2698 #else /* !LARGE_SMB_OFF_T */
2699
2700                 /*
2701                  * Ensure we haven't been sent a >32 bit offset.
2702                  */
2703
2704                 if(IVAL(inbuf,smb_vwv10) != 0) {
2705                         DEBUG(0,("reply_read_and_X - large offset (%x << 32) used and we don't support \
2706 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv10) ));
2707                         END_PROFILE(SMBreadX);
2708                         return ERROR_DOS(ERRDOS,ERRbadaccess);
2709                 }
2710
2711 #endif /* LARGE_SMB_OFF_T */
2712
2713         }
2714
2715         if (is_locked(fsp,(SMB_BIG_UINT)smb_maxcnt,(SMB_BIG_UINT)startpos, READ_LOCK)) {
2716                 END_PROFILE(SMBreadX);
2717                 return ERROR_DOS(ERRDOS,ERRlock);
2718         }
2719
2720         if (schedule_aio_read_and_X(conn, inbuf, outbuf, length, bufsize, fsp, startpos, smb_maxcnt)) {
2721                 END_PROFILE(SMBreadX);
2722                 return -1;
2723         }
2724
2725         nread = send_file_readX(conn, inbuf, outbuf, length, bufsize, fsp, startpos, smb_maxcnt);
2726         if (nread != -1)
2727                 nread = chain_reply(inbuf,outbuf,length,bufsize);
2728
2729         END_PROFILE(SMBreadX);
2730         return nread;
2731 }
2732
2733 /****************************************************************************
2734  Reply to a writebraw (core+ or LANMAN1.0 protocol).
2735 ****************************************************************************/
2736
2737 int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2738 {
2739         ssize_t nwritten=0;
2740         ssize_t total_written=0;
2741         size_t numtowrite=0;
2742         size_t tcount;
2743         SMB_OFF_T startpos;
2744         char *data=NULL;
2745         BOOL write_through;
2746         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2747         int outsize = 0;
2748         START_PROFILE(SMBwritebraw);
2749
2750         if (srv_is_signing_active()) {
2751                 exit_server("reply_writebraw: SMB signing is active - raw reads/writes are disallowed.");
2752         }
2753
2754         CHECK_FSP(fsp,conn);
2755         if (!CHECK_WRITE(fsp)) {
2756                 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2757         }
2758   
2759         tcount = IVAL(inbuf,smb_vwv1);
2760         startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2761         write_through = BITSETW(inbuf+smb_vwv7,0);
2762
2763         /* We have to deal with slightly different formats depending
2764                 on whether we are using the core+ or lanman1.0 protocol */
2765
2766         if(Protocol <= PROTOCOL_COREPLUS) {
2767                 numtowrite = SVAL(smb_buf(inbuf),-2);
2768                 data = smb_buf(inbuf);
2769         } else {
2770                 numtowrite = SVAL(inbuf,smb_vwv10);
2771                 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
2772         }
2773
2774         /* force the error type */
2775         SCVAL(inbuf,smb_com,SMBwritec);
2776         SCVAL(outbuf,smb_com,SMBwritec);
2777
2778         if (is_locked(fsp,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2779                 END_PROFILE(SMBwritebraw);
2780                 return(ERROR_DOS(ERRDOS,ERRlock));
2781         }
2782
2783         if (numtowrite>0)
2784                 nwritten = write_file(fsp,data,startpos,numtowrite);
2785   
2786         DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
2787                 fsp->fnum, (double)startpos, (int)numtowrite, (int)nwritten, (int)write_through));
2788
2789         if (nwritten < (ssize_t)numtowrite)  {
2790                 END_PROFILE(SMBwritebraw);
2791                 return(UNIXERROR(ERRHRD,ERRdiskfull));
2792         }
2793
2794         total_written = nwritten;
2795
2796         /* Return a message to the redirector to tell it to send more bytes */
2797         SCVAL(outbuf,smb_com,SMBwritebraw);
2798         SSVALS(outbuf,smb_vwv0,-1);
2799         outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
2800         show_msg(outbuf);
2801         if (!send_smb(smbd_server_fd(),outbuf))
2802                 exit_server("reply_writebraw: send_smb failed.");
2803   
2804         /* Now read the raw data into the buffer and write it */
2805         if (read_smb_length(smbd_server_fd(),inbuf,SMB_SECONDARY_WAIT) == -1) {
2806                 exit_server("secondary writebraw failed");
2807         }
2808   
2809         /* Even though this is not an smb message, smb_len returns the generic length of an smb message */
2810         numtowrite = smb_len(inbuf);
2811
2812         /* Set up outbuf to return the correct return */
2813         outsize = set_message(outbuf,1,0,True);
2814         SCVAL(outbuf,smb_com,SMBwritec);
2815
2816         if (numtowrite != 0) {
2817
2818                 if (numtowrite > BUFFER_SIZE) {
2819                         DEBUG(0,("reply_writebraw: Oversize secondary write raw requested (%u). Terminating\n",
2820                                 (unsigned int)numtowrite ));
2821                         exit_server("secondary writebraw failed");
2822                 }
2823
2824                 if (tcount > nwritten+numtowrite) {
2825                         DEBUG(3,("Client overestimated the write %d %d %d\n",
2826                                 (int)tcount,(int)nwritten,(int)numtowrite));
2827                 }
2828
2829                 if (read_data( smbd_server_fd(), inbuf+4, numtowrite) != numtowrite ) {
2830                         DEBUG(0,("reply_writebraw: Oversize secondary write raw read failed (%s). Terminating\n",
2831                                 strerror(errno) ));
2832                         exit_server("secondary writebraw failed");
2833                 }
2834
2835                 nwritten = write_file(fsp,inbuf+4,startpos+nwritten,numtowrite);
2836
2837                 if (nwritten < (ssize_t)numtowrite) {
2838                         SCVAL(outbuf,smb_rcls,ERRHRD);
2839                         SSVAL(outbuf,smb_err,ERRdiskfull);      
2840                 }
2841
2842                 if (nwritten > 0)
2843                         total_written += nwritten;
2844         }
2845  
2846         SSVAL(outbuf,smb_vwv0,total_written);
2847
2848         sync_file(conn, fsp, write_through);
2849
2850         DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
2851                 fsp->fnum, (double)startpos, (int)numtowrite,(int)total_written));
2852
2853         /* we won't return a status if write through is not selected - this follows what WfWg does */
2854         END_PROFILE(SMBwritebraw);
2855         if (!write_through && total_written==tcount) {
2856
2857 #if RABBIT_PELLET_FIX
2858                 /*
2859                  * Fix for "rabbit pellet" mode, trigger an early TCP ack by
2860                  * sending a SMBkeepalive. Thanks to DaveCB at Sun for this. JRA.
2861                  */
2862                 if (!send_keepalive(smbd_server_fd()))
2863                         exit_server("reply_writebraw: send of keepalive failed");
2864 #endif
2865                 return(-1);
2866         }
2867
2868         return(outsize);
2869 }
2870
2871 #undef DBGC_CLASS
2872 #define DBGC_CLASS DBGC_LOCKING
2873
2874 /****************************************************************************
2875  Reply to a writeunlock (core+).
2876 ****************************************************************************/
2877
2878 int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf, 
2879                       int size, int dum_buffsize)
2880 {
2881         ssize_t nwritten = -1;
2882         size_t numtowrite;
2883         SMB_OFF_T startpos;
2884         char *data;
2885         NTSTATUS status = NT_STATUS_OK;
2886         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2887         int outsize = 0;
2888         START_PROFILE(SMBwriteunlock);
2889         
2890         CHECK_FSP(fsp,conn);
2891         if (!CHECK_WRITE(fsp)) {
2892                 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2893         }
2894
2895         numtowrite = SVAL(inbuf,smb_vwv1);
2896         startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2897         data = smb_buf(inbuf) + 3;
2898   
2899         if (numtowrite && is_locked(fsp,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2900                 END_PROFILE(SMBwriteunlock);
2901                 return ERROR_DOS(ERRDOS,ERRlock);
2902         }
2903
2904         /* The special X/Open SMB protocol handling of
2905            zero length writes is *NOT* done for
2906            this call */
2907         if(numtowrite == 0) {
2908                 nwritten = 0;
2909         } else {
2910                 nwritten = write_file(fsp,data,startpos,numtowrite);
2911         }
2912   
2913         sync_file(conn, fsp, False /* write through */);
2914
2915         if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2916                 END_PROFILE(SMBwriteunlock);
2917                 return(UNIXERROR(ERRHRD,ERRdiskfull));
2918         }
2919
2920         if (numtowrite) {
2921                 status = do_unlock(fsp,
2922                                 SVAL(inbuf,smb_pid),
2923                                 (SMB_BIG_UINT)numtowrite, 
2924                                 (SMB_BIG_UINT)startpos,
2925                                 WINDOWS_LOCK);
2926
2927                 if (NT_STATUS_V(status)) {
2928                         END_PROFILE(SMBwriteunlock);
2929                         return ERROR_NT(status);
2930                 }
2931         }
2932         
2933         outsize = set_message(outbuf,1,0,True);
2934         
2935         SSVAL(outbuf,smb_vwv0,nwritten);
2936         
2937         DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
2938                  fsp->fnum, (int)numtowrite, (int)nwritten));
2939         
2940         END_PROFILE(SMBwriteunlock);
2941         return outsize;
2942 }
2943
2944 #undef DBGC_CLASS
2945 #define DBGC_CLASS DBGC_ALL
2946
2947 /****************************************************************************
2948  Reply to a write.
2949 ****************************************************************************/
2950
2951 int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int dum_buffsize)
2952 {
2953         size_t numtowrite;
2954         ssize_t nwritten = -1;
2955         SMB_OFF_T startpos;
2956         char *data;
2957         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2958         int outsize = 0;
2959         START_PROFILE(SMBwrite);
2960
2961         /* If it's an IPC, pass off the pipe handler. */
2962         if (IS_IPC(conn)) {
2963                 END_PROFILE(SMBwrite);
2964                 return reply_pipe_write(inbuf,outbuf,size,dum_buffsize);
2965         }
2966
2967         CHECK_FSP(fsp,conn);
2968         if (!CHECK_WRITE(fsp)) {
2969                 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2970         }
2971
2972         numtowrite = SVAL(inbuf,smb_vwv1);
2973         startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2974         data = smb_buf(inbuf) + 3;
2975   
2976         if (is_locked(fsp,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2977                 END_PROFILE(SMBwrite);
2978                 return ERROR_DOS(ERRDOS,ERRlock);
2979         }
2980
2981         /*
2982          * X/Open SMB protocol says that if smb_vwv1 is
2983          * zero then the file size should be extended or
2984          * truncated to the size given in smb_vwv[2-3].
2985          */
2986
2987         if(numtowrite == 0) {
2988                 /*
2989                  * This is actually an allocate call, and set EOF. JRA.
2990                  */
2991                 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
2992                 if (nwritten < 0) {
2993                         END_PROFILE(SMBwrite);
2994                         return ERROR_NT(NT_STATUS_DISK_FULL);
2995                 }
2996                 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
2997                 if (nwritten < 0) {
2998                         END_PROFILE(SMBwrite);
2999                         return ERROR_NT(NT_STATUS_DISK_FULL);
3000                 }
3001         } else
3002                 nwritten = write_file(fsp,data,startpos,numtowrite);
3003   
3004         sync_file(conn, fsp, False);
3005
3006         if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
3007                 END_PROFILE(SMBwrite);
3008                 return(UNIXERROR(ERRHRD,ERRdiskfull));
3009         }
3010
3011         outsize = set_message(outbuf,1,0,True);
3012   
3013         SSVAL(outbuf,smb_vwv0,nwritten);
3014
3015         if (nwritten < (ssize_t)numtowrite) {
3016                 SCVAL(outbuf,smb_rcls,ERRHRD);
3017                 SSVAL(outbuf,smb_err,ERRdiskfull);      
3018         }
3019   
3020         DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
3021
3022         END_PROFILE(SMBwrite);
3023         return(outsize);
3024 }
3025
3026 /****************************************************************************
3027  Reply to a write and X.
3028 ****************************************************************************/
3029
3030 int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
3031 {
3032         files_struct *fsp = file_fsp(inbuf,smb_vwv2);
3033         SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
3034         size_t numtowrite = SVAL(inbuf,smb_vwv10);
3035         BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
3036         ssize_t nwritten = -1;
3037         unsigned int smb_doff = SVAL(inbuf,smb_vwv11);
3038         unsigned int smblen = smb_len(inbuf);
3039         char *data;
3040         BOOL large_writeX = ((CVAL(inbuf,smb_wct) == 14) && (smblen > 0xFFFF));
3041         START_PROFILE(SMBwriteX);
3042
3043         /* If it's an IPC, pass off the pipe handler. */
3044         if (IS_IPC(conn)) {
3045                 END_PROFILE(SMBwriteX);
3046                 return reply_pipe_write_and_X(inbuf,outbuf,length,bufsize);
3047         }
3048
3049         CHECK_FSP(fsp,conn);
3050         if (!CHECK_WRITE(fsp)) {
3051                 return(ERROR_DOS(ERRDOS,ERRbadaccess));
3052         }
3053
3054         set_message(outbuf,6,0,True);
3055   
3056      &n